dlsch_coding.c 14.4 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 103 104 105 106

          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;
          }
        }

        free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t));
        dlsch->harq_processes[i] = NULL;
107 108
      }
    }
109

110
    free16(dlsch,sizeof(LTE_eNB_DLSCH_t));
111
    dlsch = NULL;
112
  }
113

114 115
}

116 117
LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigned char N_RB_DL, uint8_t abstraction_flag)
{
118 119 120 121

  LTE_eNB_DLSCH_t *dlsch;
  unsigned char exit_flag = 0,i,j,r;
  unsigned char bw_scaling =1;
122 123 124

  switch (N_RB_DL) {
  case 6:
125 126
    bw_scaling =16;
    break;
127

128 129 130
  case 25:
    bw_scaling =4;
    break;
131 132

  case 50:
133 134
    bw_scaling =2;
    break;
135

136 137 138 139
  default:
    bw_scaling =1;
    break;
  }
140

141
  dlsch = (LTE_eNB_DLSCH_t *)malloc16(sizeof(LTE_eNB_DLSCH_t));
142

143 144 145 146
  if (dlsch) {
    bzero(dlsch,sizeof(LTE_eNB_DLSCH_t));
    dlsch->Kmimo = Kmimo;
    dlsch->Mdlharq = Mdlharq;
147 148

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

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

156
      if (dlsch->harq_processes[i]) {
157 158 159 160 161 162 163 164 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
            dlsch->harq_processes[i]->c[r] = (unsigned char*)malloc16(((r==0)?8:0) + 3+ 768);

            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;
            }
179
          }
180 181 182 183
        }
      } else {
        msg("Can't get harq_p %d\n",i);
        exit_flag=3;
184 185 186
      }
    }

187
    if (exit_flag==0) {
188 189 190 191 192 193 194 195
      for (i=0; i<Mdlharq; i++) {
        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++)
              dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
        }
196
      }
197

198 199 200
      return(dlsch);
    }
  }
201

202 203
  LOG_D(PHY, "new_eNB_dlsch exit flag %d, size of  %ld\n",
        exit_flag, sizeof(LTE_eNB_DLSCH_t));
204 205
  free_eNB_dlsch(dlsch);
  return(NULL);
206 207


208 209
}

210 211
void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch, uint8_t abstraction_flag)
{
212 213 214

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

216 217 218 219
  if (dlsch) {
    Mdlharq = dlsch->Mdlharq;
    dlsch->rnti = 0;
    dlsch->active = 0;
220 221

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

224
    for (i=0; i<Mdlharq; i++) {
225
      if (dlsch->harq_processes[i]) {
226 227 228 229 230 231 232 233 234
        //  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++)
              dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
        }
235 236 237 238 239
      }
    }
  }
}

240

241
int dlsch_encoding(unsigned char *a,
242 243 244 245 246 247 248 249 250 251
                   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)
{

252 253 254
  unsigned int G;
  unsigned int crc=1;
  unsigned short iind;
255

256
  unsigned char harq_pid = dlsch->current_harq_pid;
257
  unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
258
  unsigned int A;
259 260 261
  unsigned char mod_order;
  unsigned int Kr=0,Kr_bytes,r,r_offset=0;
  unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
Xiwen JIANG's avatar
Xiwen JIANG committed
262
  uint8_t beamforming_mode=0;
263

gauthier's avatar
gauthier committed
264
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
265

266 267 268 269
  A = dlsch->harq_processes[harq_pid]->TBS; //6228
  // printf("Encoder: A: %d\n",A);
  mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs);

270
  if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7)
Xiwen JIANG's avatar
Xiwen JIANG committed
271
    beamforming_mode = 7;
272
  else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8)
Xiwen JIANG's avatar
Xiwen JIANG committed
273
    beamforming_mode = 8;
274
  else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10)
Xiwen JIANG's avatar
Xiwen JIANG committed
275 276
    beamforming_mode = 9;
  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,beamforming_mode);
277

278

279 280
  //  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
281 282 283 284 285 286 287 288 289 290

    /*
    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,
291
                 A)>>8;
gauthier's avatar
gauthier committed
292 293 294
    a[A>>3] = ((uint8_t*)&crc)[2];
    a[1+(A>>3)] = ((uint8_t*)&crc)[1];
    a[2+(A>>3)] = ((uint8_t*)&crc)[0];
295 296 297 298 299
    //    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);
300

301
    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
302 303 304 305 306 307 308 309
                         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)
310
      return(-1);
311 312

    for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
313
      if (r<dlsch->harq_processes[harq_pid]->Cminus)
314
        Kr = dlsch->harq_processes[harq_pid]->Kminus;
315
      else
316 317
        Kr = dlsch->harq_processes[harq_pid]->Kplus;

318
      Kr_bytes = Kr>>3;
319

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


335 336 337
#ifdef DEBUG_DLSCH_CODING
      printf("Generating Code Segment %d (%d bits)\n",r,Kr);
      // generate codewords
338

339 340 341 342 343
      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
344 345 346


#ifdef DEBUG_DLSCH_CODING
347 348 349 350
      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],
351 352 353 354 355 356
                                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)
                               );
357 358
      stop_meas(te_stats);
#ifdef DEBUG_DLSCH_CODING
359

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

363 364
#endif
      start_meas(i_stats);
365 366 367 368
      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]);
369 370
      stop_meas(i_stats);
    }
371

372 373 374 375 376
  }

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

377
  for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
378 379
#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",
380 381 382 383
        r,
        G,
        Kr*3,
        mod_order,nb_rb);
384 385 386 387
#endif

    start_meas(rm_stats);
    r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
388 389 390 391 392 393 394 395 396 397 398 399 400
                                        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
401 402
    stop_meas(rm_stats);
#ifdef DEBUG_DLSCH_CODING
403

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

407 408
#endif
  }
409

gauthier's avatar
gauthier committed
410
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
411

412 413 414 415 416
  return(0);
}

#ifdef PHY_ABSTRACTION
void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB,
417 418 419
                         uint8_t *DLSCH_pdu,
                         LTE_eNB_DLSCH_t *dlsch)
{
420 421 422 423 424

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

425 426
  //  if (dlsch->harq_processes[harq_pid]->Ndi == 1) {
  if (dlsch->harq_processes[harq_pid]->round == 0) {
427
    memcpy(dlsch->harq_processes[harq_pid]->b,
428 429 430 431 432 433 434 435
           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++)
436
      LOG_T(PHY,"%x.",DLSCH_pdu[i]);
437

438 439
    LOG_T(PHY,"\n");

knopp's avatar
 
knopp committed
440
    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]],
441 442 443 444 445
           //     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
446
  eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]+=dlsch->harq_processes[harq_pid]->TBS>>3;
447
  //payload_offset +=dlsch->harq_processes[harq_pid]->TBS>>3;
448

449 450
}
#endif