dlsch_coding.c 14.9 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
ghaddab's avatar
ghaddab committed
3
    Copyright(c) 1999 - 2014 Eurecom
4

ghaddab's avatar
ghaddab committed
5
6
7
8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9
10


ghaddab's avatar
ghaddab committed
11
12
13
14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

ghaddab's avatar
ghaddab committed
16
    You should have received a copy of the GNU General Public License
17
18
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
ghaddab's avatar
ghaddab committed
19
   see <http://www.gnu.org/licenses/>.
20
21

  Contact Information
ghaddab's avatar
ghaddab committed
22
23
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

ghaddab's avatar
ghaddab committed
28
 *******************************************************************************/
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

/*! \file PHY/LTE_TRANSPORT/dlsch_coding.c
* \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/

#include "PHY/defs.h"
#include "PHY/extern.h"
#include "PHY/CODING/defs.h"
#include "PHY/CODING/extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/LTE_TRANSPORT/defs.h"
Cedric Roux's avatar
Cedric Roux committed
47
#include "SCHED/defs.h"
48
#include "defs.h"
49
#include "UTIL/LOG/vcd_signal_dumper.h"
50

51
//#define DEBUG_DLSCH_CODING
52
53
54
//#define DEBUG_DLSCH_FREE 1

/*
55
56
57
#define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \
  ((pilots==1)&&(first_pilot==1)&&(((re>2)&&(re<6))||((re>8)&&(re<12)))) || \
  ((pilots==1)&&(first_pilot==0)&&(((re<3))||((re>5)&&(re<9)))) \
58
59
60
61
*/
#define is_not_pilot(pilots,first_pilot,re) (1)


62
63
void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch)
{
64
65
66
67
68
69
70
  int i;
  int r;

  if (dlsch) {
#ifdef DEBUG_DLSCH_FREE
    msg("Freeing dlsch %p\n",dlsch);
#endif
71
72

    for (i=0; i<dlsch->Mdlharq; i++) {
73
74
75
#ifdef DEBUG_DLSCH_FREE
      msg("Freeing dlsch process %d\n",i);
#endif
76

77
78
      if (dlsch->harq_processes[i]) {
#ifdef DEBUG_DLSCH_FREE
79
        msg("Freeing dlsch process %d (%p)\n",i,dlsch->harq_processes[i]);
80
#endif
81
82
83
84

        if (dlsch->harq_processes[i]->b) {
          free16(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES);
          dlsch->harq_processes[i]->b = NULL;
85
#ifdef DEBUG_DLSCH_FREE
86
          msg("Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b);
87
#endif
88
89
        }

90
#ifdef DEBUG_DLSCH_FREE
91
        msg("Freeing dlsch process %d c (%p)\n",i,dlsch->harq_processes[i]->c);
92
#endif
93
94

        for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++) {
95
96

#ifdef DEBUG_DLSCH_FREE
97
          msg("Freeing dlsch process %d c[%d] (%p)\n",i,r,dlsch->harq_processes[i]->c[r]);
98
#endif
99
100
101
102
103

          if (dlsch->harq_processes[i]->c[r]) {
            free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768);
            dlsch->harq_processes[i]->c[r] = NULL;
          }
104
          if (dlsch->harq_processes[i]->d[r]) {
105
            free16(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144)));
106
107
            dlsch->harq_processes[i]->d[r] = NULL;
          }
108
109
110
111
        }

        free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t));
        dlsch->harq_processes[i] = NULL;
112
113
      }
    }
114

115
    free16(dlsch,sizeof(LTE_eNB_DLSCH_t));
116
    dlsch = NULL;
117
  }
118

119
120
}

121
LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag)
122
{
123
124
125
126

  LTE_eNB_DLSCH_t *dlsch;
  unsigned char exit_flag = 0,i,j,r;
  unsigned char bw_scaling =1;
127
128
129

  switch (N_RB_DL) {
  case 6:
130
131
    bw_scaling =16;
    break;
132

133
134
135
  case 25:
    bw_scaling =4;
    break;
136
137

  case 50:
138
139
    bw_scaling =2;
    break;
140

141
142
143
144
  default:
    bw_scaling =1;
    break;
  }
145

146
  dlsch = (LTE_eNB_DLSCH_t *)malloc16(sizeof(LTE_eNB_DLSCH_t));
147

148
149
150
151
  if (dlsch) {
    bzero(dlsch,sizeof(LTE_eNB_DLSCH_t));
    dlsch->Kmimo = Kmimo;
    dlsch->Mdlharq = Mdlharq;
152
    dlsch->Nsoft = Nsoft;
153
154

    for (i=0; i<10; i++)
155
156
      dlsch->harq_ids[i] = Mdlharq;

157
158
159
    dlsch->head_freelist = 0;
    dlsch->tail_freelist = 0;

160
    for (i=0; i<Mdlharq; i++) {
161
      dlsch->harq_processes[i] = (LTE_DL_eNB_HARQ_t *)malloc16(sizeof(LTE_DL_eNB_HARQ_t));
162
      LOG_T(PHY, "Required mem size %d (bw scaling %d), dlsch->harq_processes[%d] %p\n",
163
164
            MAX_DLSCH_PAYLOAD_BYTES/bw_scaling,bw_scaling, i,dlsch->harq_processes[i]);

165
      if (dlsch->harq_processes[i]) {
166
167
168
169
170
171
172
173
174
175
176
177
178
179
        bzero(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t));
        //    dlsch->harq_processes[i]->first_tx=1;
        dlsch->harq_processes[i]->b = (unsigned char*)malloc16(MAX_DLSCH_PAYLOAD_BYTES/bw_scaling);

        if (dlsch->harq_processes[i]->b) {
          bzero(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES/bw_scaling);
        } else {
          msg("Can't get b\n");
          exit_flag=1;
        }

        if (abstraction_flag==0) {
          for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) {
            // account for filler in first segment and CRCs for multiple segment case
180
            dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+ 768);
181
            dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16((96+12+3+(3*6144)));
182
183
184
185
186
187
            if (dlsch->harq_processes[i]->c[r]) {
              bzero(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+ 768);
            } else {
              msg("Can't get c\n");
              exit_flag=2;
            }
188
            if (dlsch->harq_processes[i]->d[r]) {
189
              bzero(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144)));
190
191
192
193
            } else {
              msg("Can't get d\n");
              exit_flag=2;
            }
194
          }
195
196
197
198
        }
      } else {
        msg("Can't get harq_p %d\n",i);
        exit_flag=3;
199
      }
200
201

      put_harq_pid_in_freelist(dlsch, i);
202
203
    }

204
    if (exit_flag==0) {
205
206
207
208
209
      for (i=0; i<Mdlharq; i++) {
        dlsch->harq_processes[i]->round=0;

        if (abstraction_flag==0) {
          for (j=0; j<96; j++)
210
211
            for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) {
        //      printf("dlsch->harq_processes[%d]->d[%d] %p\n",i,r,dlsch->harq_processes[i]->d[r]);
212
              dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
213
            }
214
        }
215
      }
216

217
218
219
      return(dlsch);
    }
  }
220

221
222
  LOG_D(PHY, "new_eNB_dlsch exit flag %d, size of  %ld\n",
        exit_flag, sizeof(LTE_eNB_DLSCH_t));
223
224
  free_eNB_dlsch(dlsch);
  return(NULL);
225
226


227
228
}

229
230
void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch, uint8_t abstraction_flag)
{
231
232
233

  unsigned char Mdlharq;
  unsigned char i,j,r;
234

235
236
237
238
  if (dlsch) {
    Mdlharq = dlsch->Mdlharq;
    dlsch->rnti = 0;
    dlsch->active = 0;
239
240

    for (i=0; i<10; i++)
241
242
      dlsch->harq_ids[i] = Mdlharq;

243
    for (i=0; i<Mdlharq; i++) {
244
      if (dlsch->harq_processes[i]) {
245
246
247
248
249
250
251
        //  dlsch->harq_processes[i]->Ndi    = 0;
        dlsch->harq_processes[i]->status = 0;
        dlsch->harq_processes[i]->round  = 0;

        if (abstraction_flag==0) {
          for (j=0; j<96; j++)
            for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++)
knopp's avatar
   
knopp committed
252
253
	      if (dlsch->harq_processes[i]->d[r])
		dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
254
        }
255
256
257
258
259
      }
    }
  }
}

260

261
int dlsch_encoding(unsigned char *a,
262
263
264
265
266
267
268
269
270
271
                   LTE_DL_FRAME_PARMS *frame_parms,
                   uint8_t num_pdcch_symbols,
                   LTE_eNB_DLSCH_t *dlsch,
                   int frame,
                   uint8_t subframe,
                   time_stats_t *rm_stats,
                   time_stats_t *te_stats,
                   time_stats_t *i_stats)
{

272
273
274
  unsigned int G;
  unsigned int crc=1;
  unsigned short iind;
275

276
  unsigned char harq_pid = dlsch->current_harq_pid;
277
  unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
278
  unsigned int A;
279
280
281
282
  unsigned char mod_order;
  unsigned int Kr=0,Kr_bytes,r,r_offset=0;
  unsigned short m=dlsch->harq_processes[harq_pid]->mcs;

gauthier's avatar
gauthier committed
283
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
284

285
286
287
288
  A = dlsch->harq_processes[harq_pid]->TBS; //6228
  // printf("Encoder: A: %d\n",A);
  mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs);

289
  G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe);
290

291

292
293
  //  if (dlsch->harq_processes[harq_pid]->Ndi == 1) {  // this is a new packet
  if (dlsch->harq_processes[harq_pid]->round == 0) {  // this is a new packet
294
295
296
297
298
299
300
301
302
303

    /*
    int i;
    printf("dlsch (tx): \n");
    for (i=0;i<(A>>3);i++)
      printf("%02x.",a[i]);
    printf("\n");
    */
    // Add 24-bit crc (polynomial A) to payload
    crc = crc24a(a,
304
                 A)>>8;
gauthier's avatar
gauthier committed
305
306
307
    a[A>>3] = ((uint8_t*)&crc)[2];
    a[1+(A>>3)] = ((uint8_t*)&crc)[1];
    a[2+(A>>3)] = ((uint8_t*)&crc)[0];
308
309
310
311
312
    //    printf("CRC %x (A %d)\n",crc,A);

    dlsch->harq_processes[harq_pid]->B = A+24;
    //    dlsch->harq_processes[harq_pid]->b = a;
    memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4);
313

314
    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
315
316
317
318
319
320
321
322
                         dlsch->harq_processes[harq_pid]->c,
                         dlsch->harq_processes[harq_pid]->B,
                         &dlsch->harq_processes[harq_pid]->C,
                         &dlsch->harq_processes[harq_pid]->Cplus,
                         &dlsch->harq_processes[harq_pid]->Cminus,
                         &dlsch->harq_processes[harq_pid]->Kplus,
                         &dlsch->harq_processes[harq_pid]->Kminus,
                         &dlsch->harq_processes[harq_pid]->F)<0)
323
      return(-1);
324
325

    for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
326
      if (r<dlsch->harq_processes[harq_pid]->Cminus)
327
        Kr = dlsch->harq_processes[harq_pid]->Kminus;
328
      else
329
330
        Kr = dlsch->harq_processes[harq_pid]->Kplus;

331
      Kr_bytes = Kr>>3;
332

333
334
      // get interleaver index for Turbo code (lookup in Table 5.1.3-3 36-212, V8.6 2009-03, p. 13-14)
      if (Kr_bytes<=64)
335
        iind = (Kr_bytes-5);
336
      else if (Kr_bytes <=128)
337
        iind = 59 + ((Kr_bytes-64)>>1);
338
      else if (Kr_bytes <= 256)
339
        iind = 91 + ((Kr_bytes-128)>>2);
340
      else if (Kr_bytes <= 768)
341
        iind = 123 + ((Kr_bytes-256)>>3);
342
      else {
343
344
        msg("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes);
        return(-1);
345
      }
346
347


348
349
350
#ifdef DEBUG_DLSCH_CODING
      printf("Generating Code Segment %d (%d bits)\n",r,Kr);
      // generate codewords
351

352
353
354
355
356
      msg("bits_per_codeword (Kr)= %d, A %d\n",Kr,A);
      msg("N_RB = %d\n",nb_rb);
      msg("Ncp %d\n",frame_parms->Ncp);
      msg("mod_order %d\n",mod_order);
#endif
357
358
359


#ifdef DEBUG_DLSCH_CODING
360
361
362
363
      msg("Encoding ... iind %d f1 %d, f2 %d\n",iind,f1f2mat_old[iind*2],f1f2mat_old[(iind*2)+1]);
#endif
      start_meas(te_stats);
      threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r],
364
365
366
367
368
369
                                Kr>>3,
                                &dlsch->harq_processes[harq_pid]->d[r][96],
                                (r==0) ? dlsch->harq_processes[harq_pid]->F : 0,
                                f1f2mat_old[iind*2],   // f1 (see 36121-820, page 14)
                                f1f2mat_old[(iind*2)+1]  // f2 (see 36121-820, page 14)
                               );
370
371
      stop_meas(te_stats);
#ifdef DEBUG_DLSCH_CODING
372

373
      if (r==0)
374
375
        write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4);

376
377
#endif
      start_meas(i_stats);
378
379
380
381
      dlsch->harq_processes[harq_pid]->RTC[r] =
        sub_block_interleaving_turbo(4+(Kr_bytes*8),
                                     &dlsch->harq_processes[harq_pid]->d[r][96],
                                     dlsch->harq_processes[harq_pid]->w[r]);
382
383
      stop_meas(i_stats);
    }
384

385
386
387
388
389
  }

  // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the
  // outputs for each code segment, see Section 5.1.5 p.20

390
  for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
391
392
#ifdef DEBUG_DLSCH_CODING
    msg("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n",
393
394
395
396
        r,
        G,
        Kr*3,
        mod_order,nb_rb);
397
398
399
400
#endif

    start_meas(rm_stats);
    r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
401
402
403
404
                                        G,  //G
                                        dlsch->harq_processes[harq_pid]->w[r],
                                        dlsch->harq_processes[harq_pid]->e+r_offset,
                                        dlsch->harq_processes[harq_pid]->C, // C
405
                                        dlsch->Nsoft,                    // Nsoft,
406
407
408
409
410
411
412
413
                                        dlsch->Mdlharq,
                                        dlsch->Kmimo,
                                        dlsch->harq_processes[harq_pid]->rvidx,
                                        get_Qm(dlsch->harq_processes[harq_pid]->mcs),
                                        dlsch->harq_processes[harq_pid]->Nl,
                                        r,
                                        nb_rb,
                                        m);                       // r
414
415
    stop_meas(rm_stats);
#ifdef DEBUG_DLSCH_CODING
416

417
    if (r==dlsch->harq_processes[harq_pid]->C-1)
418
      write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->e,r_offset,1,4);
419

420
421
#endif
  }
422

gauthier's avatar
gauthier committed
423
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
424

425
426
427
428
429
  return(0);
}

#ifdef PHY_ABSTRACTION
void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB,
430
431
432
                         uint8_t *DLSCH_pdu,
                         LTE_eNB_DLSCH_t *dlsch)
{
433
434
435
436
437

  //int payload_offset = 0;
  unsigned char harq_pid = dlsch->current_harq_pid;
  unsigned short i;

438
439
  //  if (dlsch->harq_processes[harq_pid]->Ndi == 1) {
  if (dlsch->harq_processes[harq_pid]->round == 0) {
440
    memcpy(dlsch->harq_processes[harq_pid]->b,
441
442
443
444
445
446
447
448
           DLSCH_pdu,
           dlsch->harq_processes[harq_pid]->TBS>>3);
    LOG_D(PHY, "eNB %d dlsch_encoding_emul, tbs is %d harq pid %d \n",
          phy_vars_eNB->Mod_id,
          dlsch->harq_processes[harq_pid]->TBS>>3,
          harq_pid);

    for (i=0; i<dlsch->harq_processes[harq_pid]->TBS>>3; i++)
449
      LOG_T(PHY,"%x.",DLSCH_pdu[i]);
450

451
452
    LOG_T(PHY,"\n");

knopp's avatar
   
knopp committed
453
    memcpy(&eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].transport_blocks[eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]],
454
455
456
457
458
           //     memcpy(&eNB_transport_info[phy_vars_eNB->Mod_id].transport_blocks[payload_offset],
           DLSCH_pdu,
           dlsch->harq_processes[harq_pid]->TBS>>3);
  }

knopp's avatar
   
knopp committed
459
  eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]+=dlsch->harq_processes[harq_pid]->TBS>>3;
460
  //payload_offset +=dlsch->harq_processes[harq_pid]->TBS>>3;
461

462
463
}
#endif