dlsch_coding.c 15.1 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"
47
#include "PHY/LTE_TRANSPORT/proto.h"
Cedric Roux's avatar
Cedric Roux committed
48
#include "SCHED/defs.h"
49
#include "defs.h"
50
#include "UTIL/LOG/vcd_signal_dumper.h"
51

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

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


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

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

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

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

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

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

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

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

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

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

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

120
121
}

122
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)
123
{
124
125
126
127

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

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

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

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

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

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

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

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

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

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

201
    if (exit_flag==0) {
202
203
204
      for (i=0; i<Mdlharq; i++) {
        dlsch->harq_processes[i]->round=0;

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

212
      }
213

214
215
216
      return(dlsch);
    }
  }
217

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


224
225
}

226
void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch)
227
{
228
229
230

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

232
233
234
235
  if (dlsch) {
    Mdlharq = dlsch->Mdlharq;
    dlsch->rnti = 0;
    dlsch->active = 0;
236
237

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

240
    for (i=0; i<Mdlharq; i++) {
241
      if (dlsch->harq_processes[i]) {
242
243
244
245
        //  dlsch->harq_processes[i]->Ndi    = 0;
        dlsch->harq_processes[i]->status = 0;
        dlsch->harq_processes[i]->round  = 0;

246
247
248
249
	for (j=0; j<96; j++)
	  for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++)
	    if (dlsch->harq_processes[i]->d[r])
	      dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
250

251
252
253
254
255
      }
    }
  }
}

256

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

268
269
270
  unsigned int G;
  unsigned int crc=1;
  unsigned short iind;
271

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

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

285
  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);
286

287

288
289
  //  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
290
291
292
293
294
295
296
297
298

    /*
    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
299
    crc = crc24a(a, //input bits for computation, A is a size of a
300
                 A)>>8;
gauthier's avatar
gauthier committed
301
302
303
    a[A>>3] = ((uint8_t*)&crc)[2];
    a[1+(A>>3)] = ((uint8_t*)&crc)[1];
    a[2+(A>>3)] = ((uint8_t*)&crc)[0];
304
305
306
307
308
    //    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);
309

310
311
312
313
314
315
316
317
318
    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b, // bits after CRC attachement
                         dlsch->harq_processes[harq_pid]->c, // output from segmentation
                         dlsch->harq_processes[harq_pid]->B, //size of B=L+A
                         &dlsch->harq_processes[harq_pid]->C, //number of codeblocks
                         &dlsch->harq_processes[harq_pid]->Cplus, //Number of segments of size K+
                         &dlsch->harq_processes[harq_pid]->Cminus,//Number of segments of size K_
                         &dlsch->harq_processes[harq_pid]->Kplus, //First segmentation size
                         &dlsch->harq_processes[harq_pid]->Kminus, //Second segmentation size
                         &dlsch->harq_processes[harq_pid]->F)<0) //Number of filler bits
319
      return(-1);
320
321

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

327
      Kr_bytes = Kr>>3;
328

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


344
345
346
#ifdef DEBUG_DLSCH_CODING
      printf("Generating Code Segment %d (%d bits)\n",r,Kr);
      // generate codewords
347

348
349
350
351
352
      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
353
354
355


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

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

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

381
382
383
384
385
  }

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

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

    start_meas(rm_stats);
    r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
397
398
                                        G,  //G
                                        dlsch->harq_processes[harq_pid]->w[r],
399
                                        dlsch->harq_processes[harq_pid]->e+r_offset, // sequence of bits for transmission
400
                                        dlsch->harq_processes[harq_pid]->C, // C
401
                                        dlsch->Nsoft,                    // Nsoft,
402
403
404
405
406
407
408
409
                                        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
410
    stop_meas(rm_stats);
411
    //printf("dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx);
412
#ifdef DEBUG_DLSCH_CODING
413

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

417
418
#endif
  }
419

gauthier's avatar
gauthier committed
420
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
421

422
423
424
425
426
  return(0);
}

#ifdef PHY_ABSTRACTION
void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB,
427
428
429
                         uint8_t *DLSCH_pdu,
                         LTE_eNB_DLSCH_t *dlsch)
{
430
431
432
433
434

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

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

448
449
    LOG_T(PHY,"\n");

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

459
460
}
#endif