dlsch_coding.c 14.7 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
24
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@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
47

/*! \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"
#include "defs.h"
48
#include "UTIL/LOG/vcd_signal_dumper.h"
49

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

/*
54
55
56
#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)))) \
57
58
59
60
*/
#define is_not_pilot(pilots,first_pilot,re) (1)


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

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

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

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

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

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

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

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

          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;
          }
103
          if (dlsch->harq_processes[i]->d[r]) {
104
            free16(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144)));
105
106
            dlsch->harq_processes[i]->d[r] = NULL;
          }
107
108
109
110
        }

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

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

118
119
}

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

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

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

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

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

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

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

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

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

155
    for (i=0; i<Mdlharq; i++) {
156
      dlsch->harq_processes[i] = (LTE_DL_eNB_HARQ_t *)malloc16(sizeof(LTE_DL_eNB_HARQ_t));
157
      LOG_T(PHY, "Required mem size %d (bw scaling %d), dlsch->harq_processes[%d] %p\n",
158
159
            MAX_DLSCH_PAYLOAD_BYTES/bw_scaling,bw_scaling, i,dlsch->harq_processes[i]);

160
      if (dlsch->harq_processes[i]) {
161
162
163
164
165
166
167
168
169
170
171
172
173
174
        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
175
            dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+ 768);
176
            dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16((96+12+3+(3*6144)));
177
178
179
180
181
182
            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;
            }
183
            if (dlsch->harq_processes[i]->d[r]) {
184
              bzero(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144)));
185
186
187
188
            } else {
              msg("Can't get d\n");
              exit_flag=2;
            }
189
          }
190
191
192
193
        }
      } else {
        msg("Can't get harq_p %d\n",i);
        exit_flag=3;
194
195
196
      }
    }

197
    if (exit_flag==0) {
198
199
200
201
202
      for (i=0; i<Mdlharq; i++) {
        dlsch->harq_processes[i]->round=0;

        if (abstraction_flag==0) {
          for (j=0; j<96; j++)
203
204
            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]);
205
              dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
206
            }
207
        }
208
      }
209

210
211
212
      return(dlsch);
    }
  }
213

214
215
  LOG_D(PHY, "new_eNB_dlsch exit flag %d, size of  %ld\n",
        exit_flag, sizeof(LTE_eNB_DLSCH_t));
216
217
  free_eNB_dlsch(dlsch);
  return(NULL);
218
219


220
221
}

222
223
void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch, uint8_t abstraction_flag)
{
224
225
226

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

228
229
230
231
  if (dlsch) {
    Mdlharq = dlsch->Mdlharq;
    dlsch->rnti = 0;
    dlsch->active = 0;
232
233

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

236
    for (i=0; i<Mdlharq; i++) {
237
      if (dlsch->harq_processes[i]) {
238
239
240
241
242
243
244
        //  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
245
246
	      if (dlsch->harq_processes[i]->d[r])
		dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
247
        }
248
249
250
251
252
      }
    }
  }
}

253

254
int dlsch_encoding(unsigned char *a,
255
256
257
258
259
260
261
262
263
264
                   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)
{

265
266
267
  unsigned int G;
  unsigned int crc=1;
  unsigned short iind;
268

269
  unsigned char harq_pid = dlsch->current_harq_pid;
270
  unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
271
  unsigned int A;
272
273
274
275
  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
276
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
277

278
279
280
281
  A = dlsch->harq_processes[harq_pid]->TBS; //6228
  // printf("Encoder: A: %d\n",A);
  mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs);

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

284

285
286
  //  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
287
288
289
290
291
292
293
294
295
296

    /*
    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,
297
                 A)>>8;
gauthier's avatar
gauthier committed
298
299
300
    a[A>>3] = ((uint8_t*)&crc)[2];
    a[1+(A>>3)] = ((uint8_t*)&crc)[1];
    a[2+(A>>3)] = ((uint8_t*)&crc)[0];
301
302
303
304
305
    //    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);
306

307
    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
308
309
310
311
312
313
314
315
                         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)
316
      return(-1);
317
318

    for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
319
      if (r<dlsch->harq_processes[harq_pid]->Cminus)
320
        Kr = dlsch->harq_processes[harq_pid]->Kminus;
321
      else
322
323
        Kr = dlsch->harq_processes[harq_pid]->Kplus;

324
      Kr_bytes = Kr>>3;
325

326
327
      // 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)
328
        iind = (Kr_bytes-5);
329
      else if (Kr_bytes <=128)
330
        iind = 59 + ((Kr_bytes-64)>>1);
331
      else if (Kr_bytes <= 256)
332
        iind = 91 + ((Kr_bytes-128)>>2);
333
      else if (Kr_bytes <= 768)
334
        iind = 123 + ((Kr_bytes-256)>>3);
335
      else {
336
337
        msg("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes);
        return(-1);
338
      }
339
340


341
342
343
#ifdef DEBUG_DLSCH_CODING
      printf("Generating Code Segment %d (%d bits)\n",r,Kr);
      // generate codewords
344

345
346
347
348
349
      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
350
351
352


#ifdef DEBUG_DLSCH_CODING
353
354
355
356
      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],
357
358
359
360
361
362
                                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)
                               );
363
364
      stop_meas(te_stats);
#ifdef DEBUG_DLSCH_CODING
365

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

369
370
#endif
      start_meas(i_stats);
371
372
373
374
      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]);
375
376
      stop_meas(i_stats);
    }
377

378
379
380
381
382
  }

  // 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

383
  for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
384
385
#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",
386
387
388
389
        r,
        G,
        Kr*3,
        mod_order,nb_rb);
390
391
392
393
#endif

    start_meas(rm_stats);
    r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
394
395
396
397
398
399
400
401
402
403
404
405
406
                                        G,  //G
                                        dlsch->harq_processes[harq_pid]->w[r],
                                        dlsch->harq_processes[harq_pid]->e+r_offset,
                                        dlsch->harq_processes[harq_pid]->C, // C
                                        NSOFT,                    // Nsoft,
                                        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
407
408
    stop_meas(rm_stats);
#ifdef DEBUG_DLSCH_CODING
409

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

413
414
#endif
  }
415

gauthier's avatar
gauthier committed
416
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
417

418
419
420
421
422
  return(0);
}

#ifdef PHY_ABSTRACTION
void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB,
423
424
425
                         uint8_t *DLSCH_pdu,
                         LTE_eNB_DLSCH_t *dlsch)
{
426
427
428
429
430

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

431
432
  //  if (dlsch->harq_processes[harq_pid]->Ndi == 1) {
  if (dlsch->harq_processes[harq_pid]->round == 0) {
433
    memcpy(dlsch->harq_processes[harq_pid]->b,
434
435
436
437
438
439
440
441
           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++)
442
      LOG_T(PHY,"%x.",DLSCH_pdu[i]);
443

444
445
    LOG_T(PHY,"\n");

knopp's avatar
   
knopp committed
446
    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]],
447
448
449
450
451
           //     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
452
  eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]+=dlsch->harq_processes[harq_pid]->TBS>>3;
453
  //payload_offset +=dlsch->harq_processes[harq_pid]->TBS>>3;
454

455
456
}
#endif