dlsch_coding.c 14.8 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"
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
      for (i=0; i<Mdlharq; i++) {
        dlsch->harq_processes[i]->round=0;

208 209 210 211 212 213 214
	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;
	  }
        
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
void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch)
230
{
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
        //  dlsch->harq_processes[i]->Ndi    = 0;
        dlsch->harq_processes[i]->status = 0;
        dlsch->harq_processes[i]->round  = 0;

249 250 251 252 253
	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;
        
254 255 256 257 258
      }
    }
  }
}

259

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

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

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

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

288
  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);
289

290

291 292
  //  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
293 294 295 296 297 298 299 300 301 302

    /*
    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,
303
                 A)>>8;
304 305 306
    a[A>>3] = ((uint8_t*)&crc)[2];
    a[1+(A>>3)] = ((uint8_t*)&crc)[1];
    a[2+(A>>3)] = ((uint8_t*)&crc)[0];
307 308 309 310 311
    //    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);
312

313
    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
314 315 316 317 318 319 320 321
                         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)
322
      return(-1);
323 324

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

330
      Kr_bytes = Kr>>3;
331

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


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

351 352 353 354 355
      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
356 357 358


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

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

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

384 385 386 387 388
  }

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

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

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

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

419 420
#endif
  }
421

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

424 425 426 427 428
  return(0);
}

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

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

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

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

452
    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]],
453 454 455 456 457
           //     memcpy(&eNB_transport_info[phy_vars_eNB->Mod_id].transport_blocks[payload_offset],
           DLSCH_pdu,
           dlsch->harq_processes[harq_pid]->TBS>>3);
  }

458
  eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]+=dlsch->harq_processes[harq_pid]->TBS>>3;
459
  //payload_offset +=dlsch->harq_processes[harq_pid]->TBS>>3;
460

461 462
}
#endif