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
  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 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
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)
121
{
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
    dlsch->Nsoft = Nsoft;
152 153

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

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

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

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

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

211 212 213
      return(dlsch);
    }
  }
214

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


221 222
}

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

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

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

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

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

254

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

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

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

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

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

285

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

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

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

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

325
      Kr_bytes = Kr>>3;
326

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


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

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


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

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

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

379 380 381 382 383
  }

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

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

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

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

414 415
#endif
  }
416

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

419 420 421 422 423
  return(0);
}

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

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

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

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

447
    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]],
448 449 450 451 452
           //     memcpy(&eNB_transport_info[phy_vars_eNB->Mod_id].transport_blocks[payload_offset],
           DLSCH_pdu,
           dlsch->harq_processes[harq_pid]->TBS>>3);
  }

453
  eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]+=dlsch->harq_processes[harq_pid]->TBS>>3;
454
  //payload_offset +=dlsch->harq_processes[harq_pid]->TBS>>3;
455

456 457
}
#endif