dlsch_coding.c 11.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*******************************************************************************

  Eurecom OpenAirInterface
  Copyright(c) 1999 - 2011 Eurecom

  This program is free software; you can redistribute it and/or modify it
  under the terms and conditions of the GNU General Public License,
  version 2, as published by the Free Software Foundation.

  This program is distributed in the hope 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.

  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

  The full GNU General Public License is included in this distribution in
  the file called "COPYING".

  Contact Information
  Openair Admin: openair_admin@eurecom.fr
  Openair Tech : openair_tech@eurecom.fr
  Forums       : http://forums.eurecom.fsr/openairinterface
  Address      : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France

*******************************************************************************/

/*! \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"

//#define DEBUG_DLSCH_CODING 
//#define DEBUG_DLSCH_FREE 1

/*
#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)))) \
*/
#define is_not_pilot(pilots,first_pilot,re) (1)


void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) {
  int i;
  int r;

  if (dlsch) {
#ifdef DEBUG_DLSCH_FREE
    msg("Freeing dlsch %p\n",dlsch);
#endif
    for (i=0;i<dlsch->Mdlharq;i++) {
#ifdef DEBUG_DLSCH_FREE
      msg("Freeing dlsch process %d\n",i);
#endif
      if (dlsch->harq_processes[i]) {
#ifdef DEBUG_DLSCH_FREE
	msg("Freeing dlsch process %d (%p)\n",i,dlsch->harq_processes[i]);
#endif
	if (dlsch->harq_processes[i]->b) {
knopp's avatar
knopp committed
77
        free16(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES);
78
79
80
#ifdef DEBUG_DLSCH_FREE
	  msg("Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b);
#endif
knopp's avatar
knopp committed
81
    }
82
83
84
85
86
87
88
89
90
	if (dlsch->harq_processes[i]->c) {
#ifdef DEBUG_DLSCH_FREE
	  msg("Freeing dlsch process %d c (%p)\n",i,dlsch->harq_processes[i]->c);
#endif
	  for (r=0;r<MAX_NUM_DLSCH_SEGMENTS;r++) {

#ifdef DEBUG_DLSCH_FREE
	    msg("Freeing dlsch process %d c[%d] (%p)\n",i,r,dlsch->harq_processes[i]->c[r]);
#endif
knopp's avatar
knopp committed
91
	    if (dlsch->harq_processes[i]->c[r]) 
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
	      free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768);
	  }
	}
	free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t));
      }
    }
    free16(dlsch,sizeof(LTE_eNB_DLSCH_t));
  }
  
}

LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigned char N_RB_DL, u8 abstraction_flag) {

  LTE_eNB_DLSCH_t *dlsch;
  unsigned char exit_flag = 0,i,j,r;
  unsigned char bw_scaling =1;
  
  switch (N_RB_DL){
  case 6: 
    bw_scaling =16;
    break;
  case 25:
    bw_scaling =4;
    break;
  case 50: 
    bw_scaling =2;
    break;
  default:
    bw_scaling =1;
    break;
  }
  
  dlsch = (LTE_eNB_DLSCH_t *)malloc16(sizeof(LTE_eNB_DLSCH_t));
  if (dlsch) {
    bzero(dlsch,sizeof(LTE_eNB_DLSCH_t));
    dlsch->Kmimo = Kmimo;
    dlsch->Mdlharq = Mdlharq;
    for (i=0;i<10;i++)
      dlsch->harq_ids[i] = Mdlharq;

    for (i=0;i<Mdlharq;i++) {
      dlsch->harq_processes[i] = (LTE_DL_eNB_HARQ_t *)malloc16(sizeof(LTE_DL_eNB_HARQ_t));
134
      LOG_T(PHY, "Required mem size %d (bw scaling %d), dlsch->harq_processes[%d] %p\n",
135
136
137
	     MAX_DLSCH_PAYLOAD_BYTES/bw_scaling,bw_scaling, i,dlsch->harq_processes[i]);
      if (dlsch->harq_processes[i]) {
          bzero(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t));
138
	  //	  dlsch->harq_processes[i]->first_tx=1;
139
          dlsch->harq_processes[i]->b = (unsigned char*)malloc16(MAX_DLSCH_PAYLOAD_BYTES/bw_scaling);
knopp's avatar
knopp committed
140
          if (!dlsch->harq_processes[i]->b) {
141
142
143
144
145
146
147
              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);  
knopp's avatar
knopp committed
148
	    if (!dlsch->harq_processes[i]->c[r]) {
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
	      msg("Can't get c\n");
	      exit_flag=2;
	    }
	  }
	}
      }	else {
	msg("Can't get harq_p %d\n",i);
	exit_flag=3;
      }
    }

    if ((exit_flag==0)) {
      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;
	}
      }
      return(dlsch);
    }
  }
knopp's avatar
knopp committed
172
  msg("new_eNB_dlsch exit flag %d, size of  %d\n",exit_flag, sizeof(LTE_eNB_DLSCH_t));
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  free_eNB_dlsch(dlsch);
  return(NULL);
  
  
}

void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch, u8 abstraction_flag) {

  unsigned char Mdlharq;
  unsigned char i,j,r;
  
  if (dlsch) {
    Mdlharq = dlsch->Mdlharq;
    dlsch->rnti = 0;
    dlsch->active = 0;
    for (i=0;i<10;i++)
      dlsch->harq_ids[i] = Mdlharq;

    for (i=0;i<Mdlharq;i++) {
      if (dlsch->harq_processes[i]) {
193
	//	dlsch->harq_processes[i]->Ndi    = 0;
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
	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;
	}
      }
    }
  }
}

 
int dlsch_encoding(unsigned char *a,
		   LTE_DL_FRAME_PARMS *frame_parms,
		   u8 num_pdcch_symbols,
		   LTE_eNB_DLSCH_t *dlsch,
		   int frame,
		   u8 subframe,
		   time_stats_t *rm_stats,
		   time_stats_t *te_stats,
		   time_stats_t *i_stats) {
  
  unsigned int G;
  unsigned int crc=1;
  unsigned short iind;
  unsigned short nb_rb = dlsch->nb_rb;
  unsigned char harq_pid = dlsch->current_harq_pid;
  unsigned int A; 
  unsigned char mod_order;
  unsigned int Kr=0,Kr_bytes,r,r_offset=0;
  unsigned short m=dlsch->harq_processes[harq_pid]->mcs;

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

  G = get_G(frame_parms,nb_rb,dlsch->rb_alloc,mod_order,num_pdcch_symbols,frame,subframe);

   
234
235
  //  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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

    /*
    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,
		 A)>>8;
    a[A>>3] = ((u8*)&crc)[2];
    a[1+(A>>3)] = ((u8*)&crc)[1];
    a[2+(A>>3)] = ((u8*)&crc)[0];
    //    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);
    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
			 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)
      return(-1);
    
    for (r=0;r<dlsch->harq_processes[harq_pid]->C;r++) {
      if (r<dlsch->harq_processes[harq_pid]->Cminus)
	Kr = dlsch->harq_processes[harq_pid]->Kminus;
      else
	Kr = dlsch->harq_processes[harq_pid]->Kplus;
      Kr_bytes = Kr>>3;
      
      // 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)
	iind = (Kr_bytes-5);
      else if (Kr_bytes <=128)
	iind = 59 + ((Kr_bytes-64)>>1);
      else if (Kr_bytes <= 256)
	iind = 91 + ((Kr_bytes-128)>>2);
      else if (Kr_bytes <= 768)
	iind = 123 + ((Kr_bytes-256)>>3);
      else {
	msg("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes);
	return(-1);
      }
      
      
#ifdef DEBUG_DLSCH_CODING
      printf("Generating Code Segment %d (%d bits)\n",r,Kr);
      // generate codewords
      
      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
      
      
#ifdef DEBUG_DLSCH_CODING    
      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],
				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)
				);
      stop_meas(te_stats);
#ifdef DEBUG_DLSCH_CODING
      if (r==0)
	write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4);
#endif
      start_meas(i_stats);
      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]);
      stop_meas(i_stats);
    }
    
  }

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

  for (r=0;r<dlsch->harq_processes[harq_pid]->C;r++) {
#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",
	   r,
	   G,
	   Kr*3,
	   mod_order,nb_rb);
#endif

    start_meas(rm_stats);
    r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
					G,  //G
					dlsch->harq_processes[harq_pid]->w[r],
					&dlsch->e[0],
					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
    stop_meas(rm_stats);
#ifdef DEBUG_DLSCH_CODING
    if (r==dlsch->harq_processes[harq_pid]->C-1)
      write_output("enc_output.m","enc",dlsch->e,r_offset,1,4);
#endif
  }
  return(0);
}

#ifdef PHY_ABSTRACTION
void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB,
			 u8 *DLSCH_pdu,
			 LTE_eNB_DLSCH_t *dlsch) {

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

370
371
  //  if (dlsch->harq_processes[harq_pid]->Ndi == 1) {
  if (dlsch->harq_processes[harq_pid]->round == 0) {
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
    memcpy(dlsch->harq_processes[harq_pid]->b,
	   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++)
      LOG_T(PHY,"%x.",DLSCH_pdu[i]);
    LOG_T(PHY,"\n");

    memcpy(&eNB_transport_info[phy_vars_eNB->Mod_id].transport_blocks[eNB_transport_info_TB_index[phy_vars_eNB->Mod_id]],
	   //	    memcpy(&eNB_transport_info[phy_vars_eNB->Mod_id].transport_blocks[payload_offset],
    	   DLSCH_pdu,
	   dlsch->harq_processes[harq_pid]->TBS>>3);
  }  
  eNB_transport_info_TB_index[phy_vars_eNB->Mod_id]+=dlsch->harq_processes[harq_pid]->TBS>>3;
  //payload_offset +=dlsch->harq_processes[harq_pid]->TBS>>3;
  
}
#endif