phy_procedures_lte_common.c 31.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*! \file phy_procedures_lte_eNB.c
* \brief Implementation of common utilities for eNB/UE procedures from 36.213 LTE specifications
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"

void get_Msg3_alloc(LTE_DL_FRAME_PARMS *frame_parms,
38
39
40
41
42
                    unsigned char current_subframe,
                    unsigned int current_frame,
                    unsigned int *frame,
                    unsigned char *subframe)
{
43
44
45
46
47

  // Fill in other TDD Configuration!!!!

  if (frame_parms->frame_type == FDD) {
    *subframe = current_subframe+6;
48

49
50
    if (*subframe>9) {
      *subframe = *subframe-10;
51
      *frame = (current_frame+1) & 1023;
52
    } else {
53
54
      *frame=current_frame;
    }
55
  } else { // TDD
56
57
    if (frame_parms->tdd_config == 1) {
      switch (current_subframe) {
58

59
      case 0:
60
61
62
63
        *subframe = 7;
        *frame = current_frame;
        break;

64
      case 4:
65
        *subframe = 2;
66
        *frame = (current_frame+1) & 1023;
67
68
        break;

69
      case 5:
70
        *subframe = 2;
71
        *frame = (current_frame+1) & 1023;
72
73
        break;

74
      case 9:
75
        *subframe = 7;
76
        *frame = (current_frame+1) & 1023;
77
        break;
78
      }
79
    } else if (frame_parms->tdd_config == 3) {
80
      switch (current_subframe) {
81

82
83
84
      case 0:
      case 5:
      case 6:
85
        *subframe = 2;
86
        *frame = (current_frame+1) & 1023;
87
88
        break;

89
      case 7:
90
        *subframe = 3;
91
        *frame = (current_frame+1) & 1023;
92
93
        break;

94
      case 8:
95
        *subframe = 4;
96
        *frame = (current_frame+1) & 1023;
97
98
        break;

99
      case 9:
100
        *subframe = 2;
101
        *frame = (current_frame+2) & 1023;
102
        break;
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
134
135
136
137
138
139
140
141
142
143
144
    } else if (frame_parms->tdd_config == 4) {
        switch (current_subframe) {

        case 0:
        case 4:
        case 5:
        case 6:
          *subframe = 2;
          *frame = (current_frame+1) & 1023;
          break;

        case 7:
          *subframe = 3;
          *frame = (current_frame+1) & 1023;
          break;

        case 8:
        case 9:
          *subframe = 2;
          *frame = (current_frame+2) & 1023;
          break;
        }
      } else if (frame_parms->tdd_config == 5) {
          switch (current_subframe) {

          case 0:
          case 4:
          case 5:
          case 6:
            *subframe = 2;
            *frame = (current_frame+1) & 1023;
            break;

          case 7:
          case 8:
          case 9:
            *subframe = 2;
            *frame = (current_frame+2) & 1023;
            break;
          }
        }
145
146
147
148
  }
}

void get_Msg3_alloc_ret(LTE_DL_FRAME_PARMS *frame_parms,
149
150
151
152
153
                        unsigned char current_subframe,
                        unsigned int current_frame,
                        unsigned int *frame,
                        unsigned char *subframe)
{
knopp's avatar
   
knopp committed
154
  if (frame_parms->frame_type == FDD) {
roux's avatar
roux committed
155
156
    /* always retransmit in n+8 */
    *subframe = current_subframe + 8;
157

roux's avatar
roux committed
158
159
160
    if (*subframe > 9) {
      *subframe = *subframe - 10;
      *frame = (current_frame + 1) & 1023;
161
    } else {
roux's avatar
roux committed
162
      *frame = current_frame;
163
    }
164
  } else {
165
166
167
168
169
    if (frame_parms->tdd_config == 1) {
      // original PUSCH in 2, PHICH in 6 (S), ret in 2
      // original PUSCH in 3, PHICH in 9, ret in 3
      // original PUSCH in 7, PHICH in 1 (S), ret in 7
      // original PUSCH in 8, PHICH in 4, ret in 8
170
      *frame = (current_frame+1) & 1023;
171
    } else if (frame_parms->tdd_config == 3) {
172
173
174
      // original PUSCH in 2, PHICH in 8, ret in 2 next frame
      // original PUSCH in 3, PHICH in 9, ret in 3 next frame
      // original PUSCH in 4, PHICH in 0, ret in 4 next frame
175
      *frame=(current_frame+1) & 1023;
176
177
178
179
180
181
182
    } else if (frame_parms->tdd_config == 4) {
        // original PUSCH in 2, PHICH in 8, ret in 2 next frame
        // original PUSCH in 3, PHICH in 9, ret in 3 next frame
        *frame=(current_frame+1) & 1023;
    } else if (frame_parms->tdd_config == 5) {
        // original PUSCH in 2, PHICH in 8, ret in 2 next frame
        *frame=(current_frame+1) & 1023;
183
184
185
186
    }
  }
}

gauthier's avatar
gauthier committed
187
uint8_t get_Msg3_harq_pid(LTE_DL_FRAME_PARMS *frame_parms,
188
189
190
                          uint32_t frame,
                          unsigned char current_subframe)
{
191

gauthier's avatar
gauthier committed
192
  uint8_t ul_subframe=0;
193
  uint32_t ul_frame=0;
194

knopp's avatar
   
knopp committed
195
  if (frame_parms->frame_type ==FDD) {
196
    ul_subframe = (current_subframe>3) ? (current_subframe-4) : (current_subframe+6);
197
    ul_frame    = (current_subframe>3) ? ((frame+1)&1023) : frame;
198
  } else {
199
200
201
202
203
204
    switch (frame_parms->tdd_config) {
    case 1:
      switch (current_subframe) {

      case 9:
      case 0:
205
206
207
        ul_subframe = 7;
        break;

208
209
      case 5:
      case 7:
210
211
        ul_subframe = 2;
        break;
212
213

      }
214

215
      break;
216

217
218
219
220
221
222
    case 3:
      switch (current_subframe) {

      case 0:
      case 5:
      case 6:
223
224
225
        ul_subframe = 2;
        break;

226
      case 7:
227
228
229
        ul_subframe = 3;
        break;

230
      case 8:
231
232
233
        ul_subframe = 4;
        break;

234
      case 9:
235
236
        ul_subframe = 2;
        break;
237
      }
238

239
      break;
240

241
242
243
244
245
246
247
248
    case 4:
      switch (current_subframe) {

      case 0:
      case 5:
      case 6:
      case 8:
      case 9:
249
250
251
        ul_subframe = 2;
        break;

252
      case 7:
253
254
        ul_subframe = 3;
        break;
255
      }
256

257
      break;
258

259
260
261
    case 5:
      ul_subframe =2;
      break;
262

263
264
    default:
      LOG_E(PHY,"get_Msg3_harq_pid: Unsupported TDD configuration %d\n",frame_parms->tdd_config);
265
      AssertFatal(1==0,"get_Msg3_harq_pid: Unsupported TDD configuration");
266
267
268
      break;
    }
  }
269

270
271
272
273
  return(subframe2harq_pid(frame_parms,ul_frame,ul_subframe));

}

274
275
unsigned char ul_ACK_subframe2_dl_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe,unsigned char ACK_index)
{
276

knopp's avatar
   
knopp committed
277
  if (frame_parms->frame_type == FDD) {
278
    return((subframe<4) ? subframe+6 : subframe-4);
279
  } else {
280
281
282
    switch (frame_parms->tdd_config) {
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
283
284
285
286
287
288
289
290
291
292
293
294
        if (ACK_index==2)
          return(1);

        return(5+ACK_index);
      } else if (subframe == 3) { // ACK subframes 7 and 8
        return(7+ACK_index);  // To be updated
      } else if (subframe == 4) { // ACK subframes 9 and 0
        return((9+ACK_index)%10);
      } else {
        LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
295
      }
296

297
      break;
298

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
    case 4:
          if (subframe == 2) {  // ACK subframes 0, 4 and 5
            //if (ACK_index==2)
            //  return(1); TBC
            if (ACK_index==2)
            return(0);

            return(4+ACK_index);
          } else if (subframe == 3) { // ACK subframes 6, 7 8 and 9
            return(6+ACK_index);  // To be updated
          } else {
            LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
                  subframe,frame_parms->tdd_config);
            return(0);
          }

          break;

317
318
    case 1:
      if (subframe == 2) {  // ACK subframes 5 and 6
319
320
321
322
323
324
325
326
327
328
329
        return(5+ACK_index);
      } else if (subframe == 3) { // ACK subframe 9
        return(9);  // To be updated
      } else if (subframe == 7) { // ACK subframes 0 and 1
        return(ACK_index);  // To be updated
      } else if (subframe == 8) { // ACK subframe 4
        return(4);  // To be updated
      } else {
        LOG_E(PHY,"phy_procedures_lte_common.c/ul_ACK_subframe2_dl_subframe: illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
330
      }
331

332
333
334
      break;
    }
  }
335

336
337
338
  return(0);
}

339
340
unsigned char ul_ACK_subframe2_M(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
{
341

knopp's avatar
   
knopp committed
342
  if (frame_parms->frame_type == FDD) {
343
    return(1);
344
  } else {
345
346
347
    switch (frame_parms->tdd_config) {
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
348
349
350
351
352
353
354
355
356
        return(2); // should be 3
      } else if (subframe == 3) { // ACK subframes 7 and 8
        return(2);  // To be updated
      } else if (subframe == 4) { // ACK subframes 9 and 0
        return(2);
      } else {
        LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
357
      }
358

359
      break;
360

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
    case 4:
          if (subframe == 2) {  // ACK subframes 0,4 and 5
            return(3); // should be 4
          } else if (subframe == 3) { // ACK subframes 6,7,8 and 9
            return(4);
          } else {
            LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
                  subframe,frame_parms->tdd_config);
            return(0);
          }

          break;

    case 5:
              if (subframe == 2) {  // ACK subframes 0,3,4,5,6,7,8 and 9
                return(8); // should be 3
              } else {
                LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
                      subframe,frame_parms->tdd_config);
                return(0);
              }

              break;

385
386
    case 1:
      if (subframe == 2) {  // ACK subframes 5 and 6
387
388
389
390
391
392
393
394
395
396
397
        return(2);
      } else if (subframe == 3) { // ACK subframe 9
        return(1);  // To be updated
      } else if (subframe == 7) { // ACK subframes 0 and 1
        return(2);  // To be updated
      } else if (subframe == 8) { // ACK subframe 4
        return(1);  // To be updated
      } else {
        LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
398
      }
399

400
401
402
      break;
    }
  }
403

404
405
406
407
  return(0);
}

// This function implements table 10.1-1 of 36-213, p. 69
408
409
// return the number 'Nbundled'
uint8_t get_reset_ack(LTE_DL_FRAME_PARMS *frame_parms,
410
                harq_status_t *harq_ack,
Bilel's avatar
Bilel committed
411
412
                unsigned char subframe_tx,
                unsigned char subframe_rx,
413
                unsigned char *o_ACK,
Bilel's avatar
Bilel committed
414
                uint8_t *pN_bundled,
415
                uint8_t cw_idx,
416
                uint8_t do_reset) // 1 to reset ACK/NACK status : 0 otherwise
417
{
gauthier's avatar
gauthier committed
418
  uint8_t status=0;
419
  uint8_t subframe_ul=0xff, subframe_dl0=0xff, subframe_dl1=0xff,subframe_dl2=0xff, subframe_dl3=0xff;
420

knopp's avatar
   
knopp committed
421
  //  printf("get_ack: SF %d\n",subframe);
422
  if (frame_parms->frame_type == FDD) {
Bilel's avatar
Bilel committed
423
424
    if (subframe_tx < 4)
      subframe_dl0 = subframe_tx + 6;
425
    else
Bilel's avatar
Bilel committed
426
      subframe_dl0 = subframe_tx - 4;
427

428
    o_ACK[cw_idx] = harq_ack[subframe_dl0].ack;
429
    status = harq_ack[subframe_dl0].send_harq_status;
430

431
    //LOG_I(PHY,"dl subframe %d send_harq_status %d cw_idx %d, reset %d\n",subframe_dl0, status, cw_idx, do_reset);
432
433
    if(do_reset)
    	harq_ack[subframe_dl0].send_harq_status = 0;
434
    //printf("get_ack: Getting ACK/NAK for PDSCH (subframe %d) => %d\n",subframe_dl,o_ACK[0]);
435
  } else {
436
437
    switch (frame_parms->tdd_config) {
    case 1:
Bilel's avatar
Bilel committed
438
      if (subframe_tx == 2) {  // ACK subframes 5,6
439
440
441
        subframe_ul  = 6;
        subframe_dl0 = 5;
        subframe_dl1 = 6;
Bilel's avatar
Bilel committed
442
      } else if (subframe_tx == 3) { // ACK subframe 9
443
444
445
        subframe_ul  = 9;
        subframe_dl0 = 9;
        subframe_dl1 = 0xff;
Bilel's avatar
Bilel committed
446
      } else if (subframe_tx == 4) { // nothing
447
448
449
        subframe_ul  = 0xff;
        subframe_dl0 = 0xff; // invalid subframe number indicates ACK/NACK is not needed
        subframe_dl1 = 0xff;
Bilel's avatar
Bilel committed
450
      } else if (subframe_tx == 7) { // ACK subframes 0,1
451
452
453
        subframe_ul  = 1;
        subframe_dl0 = 0;
        subframe_dl1 = 1;
Bilel's avatar
Bilel committed
454
      } else if (subframe_tx == 8) { // ACK subframes 4
455
456
457
        subframe_ul  = 4;
        subframe_dl0 = 4;
        subframe_dl1 = 0xff;
458
      } else {
Bilel's avatar
Bilel committed
459
460
        LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n",
              subframe_tx,frame_parms->tdd_config);
461
        return(0);
462
      }
463

464
      // report ACK/NACK status
Gabriel's avatar
Gabriel committed
465
      o_ACK[cw_idx] = 1;
466
467
      status = 0;
      if ((subframe_dl0 < 10) && (harq_ack[subframe_dl0].send_harq_status)) {
Gabriel's avatar
Gabriel committed
468
        o_ACK[cw_idx] &= harq_ack[subframe_dl0].ack;
469
470
471
        status = harq_ack[subframe_dl0].send_harq_status;
      }
      if ((subframe_dl1 < 10) && (harq_ack[subframe_dl1].send_harq_status)) {
Gabriel's avatar
Gabriel committed
472
        o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack;
473
474
475
476
        status = harq_ack[subframe_dl1].send_harq_status;
      }
      // report status = Nbundled
      if (!status) {
Gabriel's avatar
Gabriel committed
477
        o_ACK[cw_idx] = 0;
478
479
480
481
482
483
484
485
486
      } else {
        if (harq_ack[subframe_ul].vDAI_UL < 0xff) {
          status = harq_ack[subframe_ul].vDAI_UL;
        }
      }

      if (!do_reset && (subframe_ul < 10)) {
        if ((subframe_dl0 < 10) && (subframe_dl1 < 10)) {
          LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d harq_status=%d vDAI_DL=%d, dlsf#%d ACK=%d harq_status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n",
Bilel's avatar
Bilel committed
487
              subframe_tx, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status,
488
489
              subframe_dl0, harq_ack[subframe_dl0].ack, harq_ack[subframe_dl0].send_harq_status, harq_ack[subframe_dl0].vDAI_DL,
              subframe_dl1, harq_ack[subframe_dl1].ack, harq_ack[subframe_dl1].send_harq_status, harq_ack[subframe_dl1].vDAI_DL,
Gabriel's avatar
Gabriel committed
490
              o_ACK[cw_idx], status);
491
492
        } else if (subframe_dl0 < 10) {
          LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n",
Bilel's avatar
Bilel committed
493
              subframe_tx, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status,
494
              subframe_dl0, harq_ack[subframe_dl0].ack, harq_ack[subframe_dl0].send_harq_status, harq_ack[subframe_dl0].vDAI_DL,
Gabriel's avatar
Gabriel committed
495
              o_ACK[cw_idx], status);
496
497
        }else if (subframe_dl1 < 10) {
          LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n",
Bilel's avatar
Bilel committed
498
              subframe_tx, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status,
499
              subframe_dl1, harq_ack[subframe_dl1].ack, harq_ack[subframe_dl1].send_harq_status, harq_ack[subframe_dl1].vDAI_DL,
Gabriel's avatar
Gabriel committed
500
              o_ACK[cw_idx], status);
501
502
503
504
505
        }
      }

      // reset ACK/NACK status
      if (do_reset) {
Bilel's avatar
Bilel committed
506
        LOG_D(PHY,"ul-sf#%d ACK/NACK status resetting @ dci0-sf#%d, dci1x/2x-sf#%d, dci1x/2x-sf#%d\n", subframe_tx, subframe_ul, subframe_dl0, subframe_dl1);
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
        if (subframe_ul < 10) {
          harq_ack[subframe_ul].vDAI_UL = 0xff;
        }
        if (subframe_dl0 < 10) {
          harq_ack[subframe_dl0].vDAI_DL = 0xff;
          harq_ack[subframe_dl0].ack = 2;
          harq_ack[subframe_dl0].send_harq_status = 0;
        }
        if (subframe_dl1 < 10) {
          harq_ack[subframe_dl1].vDAI_DL = 0xff;
          harq_ack[subframe_dl1].ack = 2;
          harq_ack[subframe_dl1].send_harq_status = 0;
        }
      }

522
      break;
523

524
    case 3:
Bilel's avatar
Bilel committed
525
      if (subframe_tx == 2) {  // ACK subframes 5 and 6
526
527
        subframe_dl0 = 5;
        subframe_dl1 = 6;
Bilel's avatar
Bilel committed
528
529
530
        subframe_ul  = 2;
        //printf("subframe_tx 2, TDD config 3: harq_ack[5] = %d (%d),harq_ack[6] = %d (%d)\n",harq_ack[5].ack,harq_ack[5].send_harq_status,harq_ack[6].ack,harq_ack[6].send_harq_status);
      } else if (subframe_tx == 3) { // ACK subframes 7 and 8
531
532
        subframe_dl0 = 7;
        subframe_dl1 = 8;
Bilel's avatar
Bilel committed
533
        subframe_ul  = 3;
534
535
        //printf("Subframe 3, TDD config 3: harq_ack[7] = %d,harq_ack[8] = %d\n",harq_ack[7].ack,harq_ack[8].ack);
        //printf("status %d : o_ACK (%d,%d)\n", status,o_ACK[0],o_ACK[1]);
Bilel's avatar
Bilel committed
536
      } else if (subframe_tx == 4) { // ACK subframes 9 and 0
537
538
        subframe_dl0 = 9;
        subframe_dl1 = 0;
Bilel's avatar
Bilel committed
539
        subframe_ul  = 4;
540
541
        //printf("Subframe 4, TDD config 3: harq_ack[9] = %d,harq_ack[0] = %d\n",harq_ack[9].ack,harq_ack[0].ack);
      } else {
Bilel's avatar
Bilel committed
542
543
        LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n",
              subframe_tx,frame_parms->tdd_config);
544
        return(0);
545
      }
546

547
      // report ACK/NACK status
Bilel's avatar
Bilel committed
548
      o_ACK[cw_idx] = 0;
549
      if (harq_ack[subframe_dl0].send_harq_status == 1) {
Gabriel's avatar
Gabriel committed
550
        o_ACK[cw_idx] = harq_ack[subframe_dl0].ack;
551
552

        if (harq_ack[subframe_dl1].send_harq_status == 1)
Gabriel's avatar
Gabriel committed
553
          o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack;
554
      } else if (harq_ack[subframe_dl1].send_harq_status == 1)
Gabriel's avatar
Gabriel committed
555
        o_ACK[cw_idx] = harq_ack[subframe_dl1].ack;
556

Bilel's avatar
Bilel committed
557
      pN_bundled[0] = harq_ack[subframe_rx].vDAI_UL;
Bilel's avatar
Bilel committed
558
      status = harq_ack[subframe_dl0].send_harq_status + harq_ack[subframe_dl1].send_harq_status;
559

560
561
562
      //LOG_D(PHY,"TDD Config3 UL Sfn %d, dl Sfn0 %d status %d o_Ack %d, dl Sfn1 %d status %d o_Ack %d subframe_rx %d N_bundled %d \n",
      //	  subframe_tx, subframe_dl0, harq_ack[subframe_dl0].send_harq_status,harq_ack[subframe_dl0].ack,
      //    subframe_dl1, harq_ack[subframe_dl1].send_harq_status,harq_ack[subframe_dl1].ack, subframe_rx, pN_bundled[0]);
563
564
565
566
567
568
569
570
      if (do_reset) {
        // reset ACK/NACK status
        harq_ack[subframe_dl0].ack = 2;
        harq_ack[subframe_dl1].ack = 2;
        harq_ack[subframe_dl0].send_harq_status = 0;
        harq_ack[subframe_dl1].send_harq_status = 0;
      }

571
      break;
572

573
574
    case 4:
          if (subframe_tx == 2) {  // ACK subframes 4, 5 and 0
Bilel's avatar
Bilel committed
575
576
577
            subframe_dl0 = 0;
            subframe_dl1 = 4;
            subframe_dl2 = 5;
578
579
580
            subframe_ul  = 2;
            //printf("subframe_tx 2, TDD config 3: harq_ack[5] = %d (%d),harq_ack[6] = %d (%d)\n",harq_ack[5].ack,harq_ack[5].send_harq_status,harq_ack[6].ack,harq_ack[6].send_harq_status);
          } else if (subframe_tx == 3) { // ACK subframes 6, 7 8 and 9
Bilel's avatar
Bilel committed
581
582
583
584
            subframe_dl0 = 7;
            subframe_dl1 = 8;
            subframe_dl2 = 9;
            subframe_dl3 = 6;
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
            subframe_ul  = 3;
            //printf("Subframe 3, TDD config 3: harq_ack[7] = %d,harq_ack[8] = %d\n",harq_ack[7].ack,harq_ack[8].ack);
            //printf("status %d : o_ACK (%d,%d)\n", status,o_ACK[0],o_ACK[1]);
          } else {
            LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n",
                  subframe_tx,frame_parms->tdd_config);
            return(0);
          }

          // report ACK/NACK status
          o_ACK[cw_idx] = 0;
          if (harq_ack[subframe_dl0].send_harq_status == 1)
            o_ACK[cw_idx] = harq_ack[subframe_dl0].ack;

          if (harq_ack[subframe_dl1].send_harq_status == 1)
            o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack;

          if (harq_ack[subframe_dl2].send_harq_status == 1)
            o_ACK[cw_idx] &= harq_ack[subframe_dl2].ack;

          if (harq_ack[subframe_dl3].send_harq_status == 1)
            o_ACK[cw_idx] &= harq_ack[subframe_dl3].ack;

          pN_bundled[0] = harq_ack[subframe_rx].vDAI_UL;
          status = harq_ack[subframe_dl0].send_harq_status + harq_ack[subframe_dl1].send_harq_status + harq_ack[subframe_dl2].send_harq_status + harq_ack[subframe_dl3].send_harq_status;

          LOG_I(PHY,"TDD Config3 UL Sfn %d, dl Sfn0 %d status %d o_Ack %d, dl Sfn1 %d status %d o_Ack %d dl Sfn2 %d status %d o_Ack %d dl Sfn3 %d status %d o_Ack %d subframe_rx %d N_bundled %d status %d\n",
                subframe_tx, subframe_dl0, harq_ack[subframe_dl0].send_harq_status,harq_ack[subframe_dl0].ack,
              subframe_dl1, harq_ack[subframe_dl1].send_harq_status,harq_ack[subframe_dl1].ack,
              subframe_dl2, harq_ack[subframe_dl2].send_harq_status,harq_ack[subframe_dl2].ack,
              subframe_dl3, harq_ack[subframe_dl3].send_harq_status,harq_ack[subframe_dl3].ack,subframe_rx, pN_bundled[0], status);
          if (do_reset) {
            // reset ACK/NACK status
            harq_ack[subframe_dl0].ack = 2;
            harq_ack[subframe_dl1].ack = 2;
            harq_ack[subframe_dl2].ack = 2;
            harq_ack[subframe_dl3].ack = 2;
            harq_ack[subframe_dl0].send_harq_status = 0;
            harq_ack[subframe_dl1].send_harq_status = 0;
            harq_ack[subframe_dl2].send_harq_status = 0;
            harq_ack[subframe_dl3].send_harq_status = 0;
          }

          break;

630
631
    }
  }
632

633
634
635
636
637
  //printf("status %d\n",status);

  return(status);
}

638
639
uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,
                harq_status_t *harq_ack,
Bilel's avatar
Bilel committed
640
641
                unsigned char subframe_tx,
                unsigned char subframe_rx,
642
643
                unsigned char *o_ACK,
                uint8_t cw_idx)
644
{
Bilel's avatar
Bilel committed
645
646
    uint8_t N_bundled = 0;
  return get_reset_ack(frame_parms, harq_ack, subframe_tx, subframe_rx, o_ACK, &N_bundled, cw_idx, 0);
647
648
649
650
}

uint8_t reset_ack(LTE_DL_FRAME_PARMS *frame_parms,
                harq_status_t *harq_ack,
Bilel's avatar
Bilel committed
651
652
                unsigned char subframe_tx,
                unsigned char subframe_rx,
653
                unsigned char *o_ACK,
Bilel's avatar
Bilel committed
654
                uint8_t *pN_bundled,
655
                uint8_t cw_idx)
656
{
Bilel's avatar
Bilel committed
657
  return get_reset_ack(frame_parms, harq_ack, subframe_tx, subframe_rx, o_ACK, pN_bundled, cw_idx, 1);
658
659
660
661
}



662
663
664
665
666
667
uint8_t Np6[4]= {0,1,3,5};
uint8_t Np15[4]= {0,3,8,13};
uint8_t Np25[4]= {0,5,13,22};
uint8_t Np50[4]= {0,11,27,44};
uint8_t Np75[4]= {0,16,41,66};
uint8_t Np100[4]= {0,22,55,88};
668
// This is part of the PUCCH allocation procedure (see Section 10.1 36.213)
669
670
uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1)
{
gauthier's avatar
gauthier committed
671
  uint8_t *Np;
672

673
  switch (N_RB_DL) {
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
  case 6:
    Np=Np6;
    break;

  case 15:
    Np=Np15;
    break;

  case 25:
    Np=Np25;
    break;

  case 50:
    Np=Np50;
    break;

  case 75:
    Np=Np75;
    break;

  case 100:
    Np=Np100;
    break;

  default:
    LOG_E(PHY,"get_Np() FATAL: unsupported N_RB_DL %d\n",N_RB_DL);
    return(0);
    break;
  }
703
704
705
706
707
708
709
710
711

  if (nCCE>=Np[2])
    return(Np[2+plus1]);
  else if (nCCE>=Np[1])
    return(Np[1+plus1]);
  else
    return(Np[0+plus1]);
}

712
713
lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
{
714
715

  // if FDD return dummy value
knopp's avatar
   
knopp committed
716
  if (frame_parms->frame_type == FDD)
717
718
719
720
721
722
723
724
725
726
727
728
    return(SF_DL);

  switch (frame_parms->tdd_config) {

  case 1:
    switch (subframe) {
    case 0:
    case 4:
    case 5:
    case 9:
      return(SF_DL);
      break;
729

730
731
732
733
734
735
    case 2:
    case 3:
    case 7:
    case 8:
      return(SF_UL);
      break;
736

737
738
739
740
    default:
      return(SF_S);
      break;
    }
741

742
  case 3:
743
    if  ((subframe<1) || (subframe>=5))
744
      return(SF_DL);
745
    else if ((subframe>1) && (subframe < 5))
746
747
748
749
750
751
752
      return(SF_UL);
    else if (subframe==1)
      return (SF_S);
    else  {
      LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
      return(255);
    }
753

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
  case 4:
      if  ((subframe<1) || (subframe>=4))
        return(SF_DL);
      else if ((subframe>1) && (subframe < 4))
        return(SF_UL);
      else if (subframe==1)
        return (SF_S);
      else  {
        LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
        return(255);
      }

  case 5:
        if  ((subframe<1) || (subframe>=3))
          return(SF_DL);
        else if ((subframe>1) && (subframe < 3))
          return(SF_UL);
        else if (subframe==1)
          return (SF_S);
        else  {
          LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
          return(255);
        }
777
    break;
778

779
  default:
780
    AssertFatal(1==0,"subframe %d Unsupported TDD configuration %d\n",subframe,frame_parms->tdd_config);
781
    return(255);
782

783
784
785
  }
}

786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
dci_detect_mode_t dci_detect_mode_select(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe)
{
  dci_detect_mode_t ret = 0;

  static dci_detect_mode_t Table_8_2_3gpp_36_213[][10] = {
     //subf0    , subf1     , subf2 , subf3         , subf4     , subf5     , subf6     , subf7 , subf8     , subf9
      {UL_DL_DCI, UL_DL_DCI , NO_DCI    , NO_DCI    , NO_DCI    , UL_DL_DCI , UL_DL_DCI , NO_DCI, NO_DCI    , NO_DCI    },  // tdd0
      {DL_DCI   , UL_DL_DCI , NO_DCI    , NO_DCI    , UL_DL_DCI , DL_DCI    , UL_DL_DCI , NO_DCI, NO_DCI    , UL_DL_DCI },  // tdd1
      {DL_DCI   , DL_DCI    , NO_DCI    , UL_DL_DCI , DL_DCI    , DL_DCI    , DL_DCI    , NO_DCI, UL_DL_DCI , DL_DCI    },  // tdd2
      {UL_DL_DCI, DL_DCI    , NO_DCI    , NO_DCI    , NO_DCI    , DL_DCI    , DL_DCI    , DL_DCI, UL_DL_DCI , UL_DL_DCI },  // tdd3
      {DL_DCI   , DL_DCI    , NO_DCI    , NO_DCI    , DL_DCI    , DL_DCI    , DL_DCI    , DL_DCI, UL_DL_DCI , UL_DL_DCI },  // tdd4
      {DL_DCI   , DL_DCI    , NO_DCI    , DL_DCI    , DL_DCI    , DL_DCI    , DL_DCI    , DL_DCI, UL_DL_DCI , DL_DCI    },  // tdd5
      {UL_DL_DCI, UL_DL_DCI , NO_DCI    , NO_DCI    , NO_DCI    , UL_DL_DCI , UL_DL_DCI , NO_DCI, NO_DCI    , UL_DL_DCI }}; // tdd6


  DevAssert(subframe>=0 && subframe<=9);
  DevAssert((frame_parms->tdd_config)>=0 && (frame_parms->tdd_config)<=6);

  if (frame_parms->frame_type == FDD) {
    ret = UL_DL_DCI;
  } else {
    ret = Table_8_2_3gpp_36_213[frame_parms->tdd_config][subframe];
  }

  LOG_D(PHY, "subframe %d: detect UL_DCI=%d, detect DL_DCI=%d\n", subframe, (ret & UL_DCI)>0, (ret & DL_DCI)>0);
  return ret;
}

814
815
lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subframe)
{
816

817
  return(subframe_select(&RC.eNB[Mod_id][CC_id]->frame_parms,subframe));
818
819
820

}

821
822
uint8_t phich_subframe_to_harq_pid(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t subframe)
{
823
824
825

  //LOG_D(PHY,"phich_subframe_to_harq_pid.c: frame %d, subframe %d\n",frame,subframe);
  return(subframe2harq_pid(frame_parms,
826
827
                           phich_frame2_pusch_frame(frame_parms,frame,subframe),
                           phich_subframe2_pusch_subframe(frame_parms,subframe)));
828
829
}

830
831
unsigned int is_phich_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
{
832

knopp's avatar
   
knopp committed
833
  if (frame_parms->frame_type == FDD) {
834
    return(1);
835
  } else {
836
837
838
    switch (frame_parms->tdd_config) {
    case 1:
      if ((subframe == 1) || (subframe == 4) || (subframe == 6) || (subframe == 9))
839
840
        return(1);

841
      break;
842

843
844
    case 3:
      if ((subframe == 0) || (subframe == 8) || (subframe == 9))
845
846
        return(1);

847
      break;
848

849
    case 4:
850
      if ((subframe == 8) || (subframe == 9) )
851
852
        return(1);

853
      break;
854

855
    case 5:
856
      if (subframe == 8)
857
858
        return(1);

859
      break;
860

861
862
863
864
865
    default:
      return(0);
      break;
    }
  }
866

867
868
869
870
  return(0);
}


871

872
/*
873
LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t  CC_id,uint16_t rnti)
874
{
gauthier's avatar
gauthier committed
875
  int8_t UE_id;
876

877
  if ((RC.eNB == NULL) || (Mod_id > RC.nb_inst) || (CC_id > RC.nb_CC[Mod_id])) {
878
    LOG_E(PHY,"get_UE_stats: No eNB found (or not allocated) for Mod_id %d,CC_id %d\n",Mod_id,CC_id);
879
880
    return NULL;
  }
881

882
  UE_id = find_ue(rnti, RC.eNB[Mod_id][CC_id]);
883

884
  if (UE_id == -1) {
885
    //    LOG_E(PHY,"get_UE_stats: UE with rnti %x not found\n",rnti);
886
887
    return NULL;
  }
888

889
  return(&RC.eNB[Mod_id][CC_id]->UE_stats[(uint32_t)UE_id]);
890
}
891
*/
892

893
/*
894
895
LTE_DL_FRAME_PARMS* get_lte_frame_parms(module_id_t Mod_id, uint8_t  CC_id)
{
896

897
  return(&RC.eNB[Mod_id][CC_id]->frame_parms);
898
899
900

}

901
902
MU_MIMO_mode *get_mu_mimo_mode (module_id_t Mod_id, uint8_t  CC_id, rnti_t rnti)
{
903
  int8_t UE_id = find_ue( rnti, RC.eNB[Mod_id][CC_id] );
904

905
  if (UE_id == -1)
906
907
    return 0;

908
  return &RC.eNB[Mod_id][CC_id]->mu_mimo_mode[UE_id];
909
}
910
*/
911
912
913
914
915
916
917
918
919
920

int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subframe_tx)
{
  uint8_t isSubframeSRS   = 0; // SRS Cell Occasion

  //ue->ulsch[eNB_id]->srs_active   = 0;
  //ue->ulsch[eNB_id]->Nsymb_pusch  = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active;
  if(frame_parms->soundingrs_ul_config_common.enabled_flag)
  {

921
    //LOG_D(PHY," SRS SUBFRAMECONFIG: %d\n", frame_parms->soundingrs_ul_config_common.srs_SubframeConfig);
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953

      uint8_t  TSFC;
      uint16_t deltaTSFC; // bitmap
      uint8_t  srs_SubframeConfig;

      // table resuming TSFC (Period) and deltaSFC (offset)
      const uint16_t deltaTSFCTabType1[15][2] = { {1,1},{1,2},{2,2},{1,5},{2,5},{4,5},{8,5},{3,5},{12,5},{1,10},{2,10},{4,10},{8,10},{351,10},{383,10} };      // Table 5.5.3.3-2 3GPP 36.211 FDD
      const uint16_t deltaTSFCTabType2[14][2] = { {2,5},{6,5},{10,5},{18,5},{14,5},{22,5},{26,5},{30,5},{70,10},{74,10},{194,10},{326,10},{586,10},{210,10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD

      srs_SubframeConfig = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
      if (FDD == frame_parms->frame_type)
      {
          // srs_SubframeConfig =< 14
          deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
          TSFC      = deltaTSFCTabType1[srs_SubframeConfig][1];
      }
      else
      {
          // srs_SubframeConfig =< 13
          deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
          TSFC      = deltaTSFCTabType2[srs_SubframeConfig][1];
      }

      // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
      uint16_t tmp = (subframe_tx %  TSFC);
      if((1<<tmp) & deltaTSFC)
      {
          // This is a Sounding reference signal subframes
          isSubframeSRS = 1;
      }
      LOG_D(PHY," ISTDD: %d, TSFC: %d, deltaTSFC: %d, AbsSubframeTX: %d.%d\n", frame_parms->frame_type, TSFC, deltaTSFC, frame_tx, subframe_tx);
  }
954
  LOG_D(PHY," isSubframeSRS %d\n", isSubframeSRS);
955
956
957
958
959
960
961
  return(isSubframeSRS);
}

void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset)
{
    if(TDD == frameType)
    {
962
      AssertFatal(isrs>=10,"2 ms SRS periodicity not supported");
963

964
      if((isrs>9)&&(isrs<15))
965
        {
966
967
	  *psrsPeriodicity=5;
	  *psrsOffset=isrs-10;
968
        }
969
      if((isrs>14)&&(isrs<25))
970
        {
971
972
	  *psrsPeriodicity=10;
	  *psrsOffset=isrs-15;
973
        }
974
      if((isrs>24)&&(isrs<45))
975
        {
976
977
	  *psrsPeriodicity=20;
	  *psrsOffset=isrs-25;
978
        }
979
      if((isrs>44)&&(isrs<85))
980
        {
981
982
	  *psrsPeriodicity=40;
	  *psrsOffset=isrs-45;
983
        }
984
      if((isrs>84)&&(isrs<165))
985
        {
986
987
	  *psrsPeriodicity=80;
	  *psrsOffset=isrs-85;
988
        }
989
      if((isrs>164)&&(isrs<325))
990
        {
991
992
	  *psrsPeriodicity=160;
	  *psrsOffset=isrs-165;
993
        }
994
      if((isrs>324)&&(isrs<645))
995
        {
996
997
	  *psrsPeriodicity=320;
	  *psrsOffset=isrs-325;
998
        }
999
1000
1001
      
      AssertFatal(isrs<=644,"Isrs out of range %d>644\n",isrs);
      
1002
1003
    }
    else
1004
      {
1005
        if(isrs<2)
1006
	  {
1007
1008
            *psrsPeriodicity=2;
            *psrsOffset=isrs;
1009
	  }
1010
        if((isrs>1)&&(isrs<7))
1011
	  {
1012
1013
1014
1015
            *psrsPeriodicity=5;
            *psrsOffset=isrs-2;
        }
        if((isrs>6)&&(isrs<17))
1016
	  {
1017
1018
            *psrsPeriodicity=10;
            *psrsOffset=isrs-7;
1019
	  }
1020
        if((isrs>16)&&(isrs<37))
1021
	  {
1022
1023
            *psrsPeriodicity=20;
            *psrsOffset=isrs-17;
1024
	  }
1025
        if((isrs>36)&&(isrs<77))
1026
	  {
1027
1028
            *psrsPeriodicity=40;
            *psrsOffset=isrs-37;
1029
	  }
1030
        if((isrs>76)&&(isrs<157))
1031
	  {
1032
1033
            *psrsPeriodicity=80;
            *psrsOffset=isrs-77;
1034
	  }
1035
        if((isrs>156)&&(isrs<317))
1036
	  {
1037
1038
1039
1040
            *psrsPeriodicity=160;
            *psrsOffset=isrs-157;
        }
        if((isrs>316)&&(isrs<637))
1041
	  {
1042
1043
            *psrsPeriodicity=320;
            *psrsOffset=isrs-317;
1044
1045
1046
1047
	  }
	AssertFatal(isrs<=636,"Isrs out of range %d>636\n",isrs);
	
      }
1048
}