eNB_scheduler_dlsch.c 56.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * 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
 */
21 22 23

/*! \file eNB_scheduler_dlsch.c
 * \brief procedures related to eNB for the DLSCH transport channel
24
 * \author  Navid Nikaein and Raymond Knopp
25
 * \date 2010 - 2014
26
 * \email: navid.nikaein@eurecom.fr
27
 * \version 1.0
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
 * @ingroup _mac

 */

#include "assertions.h"
#include "PHY/defs.h"
#include "PHY/extern.h"

#include "SCHED/defs.h"
#include "SCHED/extern.h"

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/proto.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"

#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"

//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"

54 55
#include "SIMULATION/TOOLS/defs.h" // for taus

56 57 58 59
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

Cedric Roux's avatar
Cedric Roux committed
60 61
#include "T.h"

62
#define ENABLE_MAC_PAYLOAD_DEBUG
Raymond Knopp's avatar
 
Raymond Knopp committed
63
//#define DEBUG_eNB_SCHEDULER 1
64

65
extern RAN_CONTEXT_t RC;
66

67 68 69 70 71 72 73 74 75 76
//------------------------------------------------------------------------------
void
add_ue_dlsch_info(
  module_id_t module_idP,
  int CC_id,
  int UE_id,
  sub_frame_t subframeP,
  UE_DLSCH_STATUS status
)
//------------------------------------------------------------------------------
77
{
78

79 80 81 82
  eNB_dlsch_info[module_idP][CC_id][UE_id].rnti             = UE_RNTI(module_idP,UE_id);
  //  eNB_dlsch_info[module_idP][CC_id][ue_mod_idP].weight           = weight;
  eNB_dlsch_info[module_idP][CC_id][UE_id].subframe         = subframeP;
  eNB_dlsch_info[module_idP][CC_id][UE_id].status           = status;
83

84
  eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num++;
85 86 87

}

88 89 90 91 92 93 94 95
//------------------------------------------------------------------------------
int
schedule_next_dlue(
  module_id_t module_idP,
  int CC_id,
  sub_frame_t subframeP
)
//------------------------------------------------------------------------------
96
{
97

Raymond Knopp's avatar
 
Raymond Knopp committed
98
  int next_ue;
99
  UE_list_t *UE_list=&RC.mac[module_idP]->UE_list;
100

101
  for (next_ue=UE_list->head; next_ue>=0; next_ue=UE_list->next[next_ue] ) {
102
    if  (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_WAITING) {
Raymond Knopp's avatar
 
Raymond Knopp committed
103
      return next_ue;
104
    }
105
  }
106 107

  for (next_ue=UE_list->head; next_ue>=0; next_ue=UE_list->next[next_ue] ) {
108 109
    if  (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_BUFFERED) {
      eNB_dlsch_info[module_idP][CC_id][next_ue].status = S_DL_WAITING;
110
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
111 112 113
  }

  return(-1);//next_ue;
114 115 116

}

117 118 119
//------------------------------------------------------------------------------
unsigned char
generate_dlsch_header(
120 121 122 123 124
  unsigned char* mac_header,
  unsigned char num_sdus,
  unsigned short *sdu_lengths,
  unsigned char *sdu_lcids,
  unsigned char drx_cmd,
125
  unsigned short timing_advance_cmd,
126 127 128
  unsigned char *ue_cont_res_id,
  unsigned char short_padding,
  unsigned short post_padding
129 130
)
//------------------------------------------------------------------------------
131
{
132 133 134 135 136 137 138 139 140 141

  SCH_SUBHEADER_FIXED *mac_header_ptr = (SCH_SUBHEADER_FIXED *)mac_header;
  uint8_t first_element=0,last_size=0,i;
  uint8_t mac_header_control_elements[16],*ce_ptr;

  ce_ptr = &mac_header_control_elements[0];

  // compute header components

  if ((short_padding == 1) || (short_padding == 2)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
142 143 144 145 146
    mac_header_ptr->R    = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    first_element=1;
    last_size=1;
147
  }
148

149
  if (short_padding == 2) {
Raymond Knopp's avatar
 
Raymond Knopp committed
150 151 152 153 154 155
    mac_header_ptr->E = 1;
    mac_header_ptr++;
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    last_size=1;
156 157 158
  }

  if (drx_cmd != 255) {
Raymond Knopp's avatar
 
Raymond Knopp committed
159 160 161
    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
162
    } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
163 164
      first_element=1;
    }
165

Raymond Knopp's avatar
 
Raymond Knopp committed
166 167 168 169
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = DRX_CMD;
    last_size=1;
170 171 172
  }

  if (timing_advance_cmd != 0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
173 174 175
    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
176
    } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
177 178
      first_element=1;
    }
179

Raymond Knopp's avatar
 
Raymond Knopp committed
180 181 182 183 184 185
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = TIMING_ADV_CMD;
    last_size=1;
    //    msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
    ((TIMING_ADVANCE_CMD *)ce_ptr)->R=0;
186 187
    AssertFatal(timing_advance_cmd < 64,"timing_advance_cmd %d > 63\n",timing_advance_cmd);
    ((TIMING_ADVANCE_CMD *)ce_ptr)->TA=timing_advance_cmd;//(timing_advance_cmd+31)&0x3f;
Raymond Knopp's avatar
 
Raymond Knopp committed
188
    LOG_D(MAC,"timing advance =%d (%d)\n",timing_advance_cmd,((TIMING_ADVANCE_CMD *)ce_ptr)->TA);
Raymond Knopp's avatar
 
Raymond Knopp committed
189 190
    ce_ptr+=sizeof(TIMING_ADVANCE_CMD);
    //msg("offset %d\n",ce_ptr-mac_header_control_elements);
191 192 193
  }

  if (ue_cont_res_id) {
Raymond Knopp's avatar
 
Raymond Knopp committed
194 195 196
    if (first_element>0) {
      mac_header_ptr->E = 1;
      /*
197 198 199 200
      printf("[eNB][MAC] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
Raymond Knopp's avatar
 
Raymond Knopp committed
201 202
      */
      mac_header_ptr++;
203
    } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
204 205
      first_element=1;
    }
206

Raymond Knopp's avatar
 
Raymond Knopp committed
207 208 209 210
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = UE_CONT_RES;
    last_size=1;
211

Raymond Knopp's avatar
 
Raymond Knopp committed
212
    LOG_T(MAC,"[eNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n",
213 214 215 216 217 218 219
          ue_cont_res_id[0],
          ue_cont_res_id[1],
          ue_cont_res_id[2],
          ue_cont_res_id[3],
          ue_cont_res_id[4],
          ue_cont_res_id[5]);

Raymond Knopp's avatar
 
Raymond Knopp committed
220 221 222
    memcpy(ce_ptr,ue_cont_res_id,6);
    ce_ptr+=6;
    // msg("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
223 224 225 226
  }

  //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

227
  for (i=0; i<num_sdus; i++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
228
    LOG_T(MAC,"[eNB] Generate DLSCH header num sdu %d len sdu %d\n",num_sdus, sdu_lengths[i]);
229

Raymond Knopp's avatar
 
Raymond Knopp committed
230 231 232
    if (first_element>0) {
      mac_header_ptr->E = 1;
      /*msg("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
233 234 235
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
Raymond Knopp's avatar
 
Raymond Knopp committed
236 237 238
      */
      mac_header_ptr+=last_size;
      //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
239
    } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
240 241
      first_element=1;
    }
242

Raymond Knopp's avatar
 
Raymond Knopp committed
243 244 245 246 247 248 249
    if (sdu_lengths[i] < 128) {
      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R    = 0;
      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E    = 0;
      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F    = 0;
      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = sdu_lcids[i];
      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L    = (unsigned char)sdu_lengths[i];
      last_size=2;
250
    } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
251 252 253 254 255 256 257 258
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R    = 0;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E    = 0;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F    = 1;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i];
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB    = ((unsigned short) sdu_lengths[i]>>8)&0x7f;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB    = (unsigned short) sdu_lengths[i]&0xff;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->padding   = 0x00;
      last_size=3;
259
#ifdef DEBUG_HEADER_PARSING
Raymond Knopp's avatar
 
Raymond Knopp committed
260
      LOG_D(MAC,"[eNB] generate long sdu, size %x (MSB %x, LSB %x)\n",
261 262 263
            sdu_lengths[i],
            ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB,
            ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB);
264
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
265
    }
266
  }
267

268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
  /*

    printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

    printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
    ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
    ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
    ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);


    if (((SCH_SUBHEADER_FIXED*)mac_header_ptr)->LCID < UE_CONT_RES) {
    if (((SCH_SUBHEADER_SHORT*)mac_header_ptr)->F == 0)
    printf("F = 0, sdu len (L field) %d\n",(((SCH_SUBHEADER_SHORT*)mac_header_ptr)->L));
    else
    printf("F = 1, sdu len (L field) %d\n",(((SCH_SUBHEADER_LONG*)mac_header_ptr)->L));
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
284
  */
285
  if (post_padding>0) {// we have lots of padding at the end of the packet
Raymond Knopp's avatar
 
Raymond Knopp committed
286 287 288 289 290 291 292
    mac_header_ptr->E = 1;
    mac_header_ptr+=last_size;
    // add a padding element
    mac_header_ptr->R    = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    mac_header_ptr++;
293
  } else { // no end of packet padding
Raymond Knopp's avatar
 
Raymond Knopp committed
294 295
    // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE)
    mac_header_ptr++;
296 297 298 299 300
  }

  //msg("After subheaders %d\n",(uint8_t*)mac_header_ptr - mac_header);

  if ((ce_ptr-mac_header_control_elements) > 0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
301 302 303
    // printf("Copying %d bytes for control elements\n",ce_ptr-mac_header_control_elements);
    memcpy((void*)mac_header_ptr,mac_header_control_elements,ce_ptr-mac_header_control_elements);
    mac_header_ptr+=(unsigned char)(ce_ptr-mac_header_control_elements);
304
  }
305

306 307 308 309 310 311
  //msg("After CEs %d\n",(uint8_t*)mac_header_ptr - mac_header);

  return((unsigned char*)mac_header_ptr - mac_header);

}

312 313 314 315 316 317 318
//------------------------------------------------------------------------------
void
set_ul_DAI(
  int module_idP,
  int UE_idP,
  int CC_idP,
  int frameP,
319 320
  int subframeP
) 
321
//------------------------------------------------------------------------------
322 323
{

324
  eNB_MAC_INST         *eNB      = RC.mac[module_idP];
Raymond Knopp's avatar
 
Raymond Knopp committed
325 326
  UE_list_t            *UE_list  = &eNB->UE_list;
  unsigned char         DAI;
327 328
  COMMON_channels_t    *cc       = &eNB->common_channels[CC_idP];
  if (cc->tdd_Config != NULL) {  //TDD
Raymond Knopp's avatar
 
Raymond Knopp committed
329
    DAI = (UE_list->UE_template[CC_idP][UE_idP].DAI-1)&3;
330
    LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframe %d: DAI %d for UE %d\n",module_idP,CC_idP,frameP,subframeP,DAI,UE_idP);
Raymond Knopp's avatar
 
Raymond Knopp committed
331
    // Save DAI for Format 0 DCI
332

333
    switch (cc->tdd_Config->subframeAssignment) {
Raymond Knopp's avatar
 
Raymond Knopp committed
334 335 336
    case 0:
      //      if ((subframeP==0)||(subframeP==1)||(subframeP==5)||(subframeP==6))
      break;
337

Raymond Knopp's avatar
 
Raymond Knopp committed
338 339 340
    case 1:
      switch (subframeP) {
      case 1:
341 342 343
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI;
        break;

Raymond Knopp's avatar
 
Raymond Knopp committed
344
      case 4:
345 346 347
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI;
        break;

Raymond Knopp's avatar
 
Raymond Knopp committed
348
      case 6:
349 350 351
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
        break;

Raymond Knopp's avatar
 
Raymond Knopp committed
352
      case 9:
353 354
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
355
      }
356

Raymond Knopp's avatar
 
Raymond Knopp committed
357 358
    case 2:
      //      if ((subframeP==3)||(subframeP==8))
359
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
Raymond Knopp's avatar
 
Raymond Knopp committed
360
      break;
361

Raymond Knopp's avatar
 
Raymond Knopp committed
362
    case 3:
363

Raymond Knopp's avatar
 
Raymond Knopp committed
364 365 366 367
      //if ((subframeP==6)||(subframeP==8)||(subframeP==0)) {
      //  LOG_D(MAC,"schedule_ue_spec: setting UL DAI to %d for subframeP %d => %d\n",DAI,subframeP, ((subframeP+8)%10)>>1);
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul[((subframeP+8)%10)>>1] = DAI;
      //}
368
      switch (subframeP) {
Raymond Knopp's avatar
 
Raymond Knopp committed
369 370 371
      case 5:
      case 6:
      case 1:
372 373 374
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
        break;

Raymond Knopp's avatar
 
Raymond Knopp committed
375 376
      case 7:
      case 8:
377 378 379
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
        break;

Raymond Knopp's avatar
 
Raymond Knopp committed
380 381
      case 9:
      case 0:
382 383 384
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI;
        break;

Raymond Knopp's avatar
 
Raymond Knopp committed
385
      default:
386
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
387
      }
388

Raymond Knopp's avatar
 
Raymond Knopp committed
389
      break;
390

Raymond Knopp's avatar
 
Raymond Knopp committed
391 392
    case 4:
      //      if ((subframeP==8)||(subframeP==9))
393
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
Raymond Knopp's avatar
 
Raymond Knopp committed
394
      break;
395

Raymond Knopp's avatar
 
Raymond Knopp committed
396 397
    case 5:
      //      if (subframeP==8)
398
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
Raymond Knopp's avatar
 
Raymond Knopp committed
399
      break;
400

Raymond Knopp's avatar
 
Raymond Knopp committed
401 402
    case 6:
      //      if ((subframeP==1)||(subframeP==4)||(subframeP==6)||(subframeP==9))
403
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
Raymond Knopp's avatar
 
Raymond Knopp committed
404
      break;
405

Raymond Knopp's avatar
 
Raymond Knopp committed
406 407 408 409 410 411
    default:
      break;
    }
  }
}

412

413 414
// changes to pre-processor for eMTC

415 416 417
//------------------------------------------------------------------------------
void
schedule_ue_spec(
418 419 420
  module_id_t   module_idP,
  frame_t       frameP,
  sub_frame_t   subframeP,
421
  int*          mbsfn_flag
422 423
)
//------------------------------------------------------------------------------
424
{
Raymond Knopp's avatar
 
Raymond Knopp committed
425

426

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
  uint8_t                        CC_id;
  int                            UE_id;
  unsigned char                  aggregation;
  mac_rlc_status_resp_t          rlc_status;
  unsigned char                  header_len_dcch=0, header_len_dcch_tmp=0; 
  unsigned char                  header_len_dtch=0, header_len_dtch_tmp=0, header_len_dtch_last=0; 
  unsigned char                  ta_len=0;
  unsigned char                  sdu_lcids[NB_RB_MAX],lcid,offset,num_sdus=0;
  uint16_t                       nb_rb,nb_rb_temp,nb_available_rb;
  uint16_t                       TBS,j,sdu_lengths[NB_RB_MAX],rnti,padding=0,post_padding=0;
  unsigned char                  dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
  unsigned char                  round             = 0;
  unsigned char                  harq_pid          = 0;
  eNB_UE_STATS                   *eNB_UE_stats     = NULL;
  uint16_t                       sdu_length_total = 0;

  eNB_MAC_INST                   *eNB      = RC.mac[module_idP];
  COMMON_channels_t              *cc       = eNB->common_channels;
  UE_list_t                      *UE_list  = &eNB->UE_list;
  int                            continue_flag=0;
  int32_t                        normalized_rx_power, target_rx_power;
  int32_t                        tpc=1;
  static int32_t                 tpc_accumulated=0;
  UE_sched_ctrl                  *ue_sched_ctl;
  int                            mcs;
  int                            i;
  int                            min_rb_unit[MAX_NUM_CCs];
  int                            N_RB_DL[MAX_NUM_CCs];
  int                            total_nb_available_rb[MAX_NUM_CCs];
  int                            N_RBG[MAX_NUM_CCs];
457
  nfapi_dl_config_request_body_t *dl_req;
458
  nfapi_dl_config_request_pdu_t  *dl_config_pdu;
459
  int                            tdd_sfa;
460

461
#if 0
462
  if (UE_list->head==-1) {
463
    return;
464
  }
465
#endif
466

467
  start_meas(&eNB->schedule_dlsch);
468
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN);
469

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504

  // for TDD: check that we have to act here, otherwise return
  if (cc[0].tdd_Config) {
    tdd_sfa = cc[0].tdd_Config->subframeAssignment;
    switch (subframeP) {
    case 0:
      // always continue
       break;
    case 1:
      return;
	break;
    case 2:
      return;
      break;
    case 3:
      if ((tdd_sfa!=2) && (tdd_sfa!=5)) return;
      break;
    case 4:
      if ((tdd_sfa!=1)&&(tdd_sfa!=2)&&(tdd_sfa!=4)&&(tdd_sfa!=5)) return;
      break;
    case 5:
      break;
    case 6:
    case 7:
      if ((tdd_sfa!=1)&&(tdd_sfa!=2)&&(tdd_sfa!=4)&&(tdd_sfa!=5)) return;
      break;
    case 8:
      if ((tdd_sfa!=2)&&(tdd_sfa!=3)&&(tdd_sfa!=4)&&(tdd_sfa!=5)) return;
      break;
    case 9:
      if ((tdd_sfa!=1)&&(tdd_sfa!=3)&&(tdd_sfa!=4)&&(tdd_sfa!=6)) return;
      break;
   
    }
  }
Cedric Roux's avatar
Cedric Roux committed
505

506
  //weight = get_ue_weight(module_idP,UE_id);
507
  aggregation = 2; 
508
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
509
    N_RB_DL[CC_id] = to_prb(cc[CC_id].mib->message.dl_Bandwidth);
510
    min_rb_unit[CC_id]=get_min_rb_unit(module_idP,CC_id);
511
    // get number of PRBs less those used by common channels
512 513 514
    total_nb_available_rb[CC_id] = N_RB_DL[CC_id];
    for (i=0;i<N_RB_DL[CC_id];i++)
      if (cc[CC_id].vrb_map[i]!=0)
515 516
	total_nb_available_rb[CC_id]--;

517
    N_RBG[CC_id] = to_rbg(cc[CC_id].mib->message.dl_Bandwidth);
518

519
    // store the global enb stats:
520 521
    eNB->eNB_stats[CC_id].num_dlactive_UEs      =  UE_list->num_UEs;
    eNB->eNB_stats[CC_id].available_prbs        =  total_nb_available_rb[CC_id];
522
    eNB->eNB_stats[CC_id].total_available_prbs +=  total_nb_available_rb[CC_id];
523 524
    eNB->eNB_stats[CC_id].dlsch_bytes_tx        = 0;
    eNB->eNB_stats[CC_id].dlsch_pdus_tx         = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
525
  }
526

527
  /// CALLING Pre_Processor for downlink scheduling (Returns estimation of RBs required by each UE and the allocation on sub-band)
528

529
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_IN);
Raymond Knopp's avatar
 
Raymond Knopp committed
530
  start_meas(&eNB->schedule_dlsch_preprocessor);
531
  dlsch_scheduler_pre_processor(module_idP,
532 533 534 535
                                frameP,
                                subframeP,
                                N_RBG,
                                mbsfn_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
536
  stop_meas(&eNB->schedule_dlsch_preprocessor);
537
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT);
Raymond Knopp's avatar
 
Raymond Knopp committed
538

539
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
540
    LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n",CC_id);
541

542 543
    dl_req        = &eNB->DL_req[CC_id].dl_config_request_body;

Raymond Knopp's avatar
 
Raymond Knopp committed
544 545
    if (mbsfn_flag[CC_id]>0)
      continue;
546 547

    for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
548
      continue_flag=0; // reset the flag to allow allocation for the remaining UEs
Raymond Knopp's avatar
 
Raymond Knopp committed
549
      rnti = UE_RNTI(module_idP,UE_id);
550
      eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
551
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
552

553

554
      if (rnti==NOT_A_RNTI) {
555 556
        LOG_D(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n",UE_id,UE_list->num_UEs);
        continue_flag=1;
557
      }
558

559
      if (eNB_UE_stats==NULL) {
560 561
        LOG_D(MAC,"[eNB] Cannot find eNB_UE_stats\n");
        continue_flag=1;
562
      }
563 564

      if (continue_flag != 1){
565
        switch(get_tmode(module_idP,CC_id,UE_id)){
566 567 568 569
        case 1:
        case 2:
        case 7:
	  aggregation = get_aggregation(get_bw_index(module_idP,CC_id), 
Cedric Roux's avatar
Cedric Roux committed
570
					ue_sched_ctl->dl_cqi[CC_id],
571
					format1);
572 573 574
	  break;
        case 3:
	  aggregation = get_aggregation(get_bw_index(module_idP,CC_id), 
Cedric Roux's avatar
Cedric Roux committed
575
					ue_sched_ctl->dl_cqi[CC_id],
576
					format2A);
577 578
	  break;
        default:
579
	  LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id));
580 581 582 583
	  aggregation = 2;
        }
      } /* if (continue_flag != 1 */

584
      if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) ||  // no RBs allocated 
585
	  CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,aggregation,rnti)
586
	  ) {
587
        LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n",
588
              module_idP, frameP, UE_id, CC_id);
589
        continue_flag=1; //to next user (there might be rbs availiable for other UEs in TM5
590
      }
591

592
      if (cc[CC_id].tdd_Config != NULL) { //TDD
593 594 595
        set_ue_dai (subframeP,
                    UE_id,
                    CC_id,
596
		    cc[CC_id].tdd_Config->subframeAssignment,
597 598
                    UE_list);
        // update UL DAI after DLSCH scheduling
599
        set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP);
Raymond Knopp's avatar
 
Raymond Knopp committed
600 601
      }

602 603 604 605 606 607 608
      if (continue_flag == 1 ) {
        add_ue_dlsch_info(module_idP,
                          CC_id,
                          UE_id,
                          subframeP,
                          S_DL_NONE);
        continue;
609
      }
610

611 612
#warning RK->CR This old API call has to be revisited for FAPI, or logic must be changed
#if 0
Cedric Roux's avatar
Cedric Roux committed
613 614 615 616 617 618 619 620 621 622 623
      /* add "fake" DCI to have CCE_allocation_infeasible work properly for next allocations */
      /* if we don't add it, next allocations may succeed but overall allocations may fail */
      /* will be removed at the end of this function */
      add_ue_spec_dci(&eNB->common_channels[CC_id].DCI_pdu,
                      &(char[]){0},
                      rnti,
                      1,
                      aggregation,
                      1,
                      format1,
                      0);
624
#endif
Cedric Roux's avatar
Cedric Roux committed
625

626
      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
627 628 629 630 631 632

      if (cc->tdd_Config) harq_pid = ((frameP*10)+subframeP)%10;
      else harq_pid = ((frameP*10)+subframeP)&7;

      round = ue_sched_ctl->round[CC_id][harq_pid];

633
      UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti;
634
      UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(module_idP,rnti);
635
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; 
636
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
637

638 639 640

      if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_CONNECTED) continue;

641 642
      sdu_length_total=0;
      num_sdus=0;
643 644

      /*
645 646
      DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) || (eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)),
      eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE);
647
      */
Cedric Roux's avatar
Cedric Roux committed
648
      eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctl->dl_cqi[CC_id]];
649
      eNB_UE_stats->dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1;//cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
650

651

652
      // store stats
Cedric Roux's avatar
Cedric Roux committed
653
      //UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi;
654

655
      // initializing the rb allocation indicator for each UE
656
      for(j=0; j<N_RBG[CC_id]; j++) {
657
        UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
658 659
      }

660
      LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n",
661
            module_idP, frameP, UE_id,CC_id,rnti,harq_pid, round,nb_available_rb,
Cedric Roux's avatar
Cedric Roux committed
662
            ue_sched_ctl->dl_cqi[CC_id], eNB_UE_stats->dlsch_mcs1,
663
	    UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status);
664 665 666



667 668
      /* process retransmission  */

669
      if (round != 8) {
670

671 672
        // get freq_allocation
        nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
673
	TBS = get_TBS_DL(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid],nb_rb);
674 675

        if (nb_rb <= nb_available_rb) {
676
          if (cc[CC_id].tdd_Config != NULL) {
677 678 679 680
            UE_list->UE_template[CC_id][UE_id].DAI++;
            update_ul_dci(module_idP,CC_id,rnti,UE_list->UE_template[CC_id][UE_id].DAI);
            LOG_D(MAC,"DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", CC_id,subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI);
          }
681

682
          if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
683
            for(j=0; j<N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band
684
              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
685
            }
686 687 688 689
          } else {
            nb_rb_temp = nb_rb;
            j = 0;

690
            while((nb_rb_temp > 0) && (j<N_RBG[CC_id])) {
691
              if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
Cedric Roux's avatar
Cedric Roux committed
692
                if (UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]) printf("WARN: rballoc_subband not free for retrans?\n");
693
                UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
694

695 696 697
                if((j == N_RBG[CC_id]-1) &&
                    ((N_RB_DL[CC_id] == 25)||
                     (N_RB_DL[CC_id] == 50))) {
698
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
699
                } else {
700
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
701
                }
702 703 704 705 706 707 708
              }

              j = j+1;
            }
          }

          nb_available_rb -= nb_rb;
709 710 711
	  /*
          eNB->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
          eNB->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
712

713 714
          for(j=0; j<N_RBG[CC_id]; j++) {
            eNB->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
715
          }
716
	  */
717

718
          switch (get_tmode(module_idP,CC_id,UE_id)) {
719 720
          case 1:
          case 2:
Xiwen JIANG's avatar
Xiwen JIANG committed
721
          case 7:
722
          default:
723
	    dl_config_pdu                                                         = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
724 725
	    memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
	    dl_config_pdu->pdu_type                                               = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; 
726
	    dl_config_pdu->pdu_size                                               = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
727
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                  = NFAPI_DL_DCI_FORMAT_1;
Cedric Roux's avatar
Cedric Roux committed
728
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level           = get_aggregation(get_bw_index(module_idP,CC_id),ue_sched_ctl->dl_cqi[CC_id],format1);
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                        = rnti;
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type                   = 1;    // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power          = 6000; // equal to RS power

	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process                = harq_pid;
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc                         = 1; // dont adjust power when retransmitting
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1        = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                       = UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid];
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1        = round&3;

	    if (cc[CC_id].tdd_Config != NULL) { //TDD
	      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
	      LOG_D(MAC,"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n",
		    module_idP,CC_id,harq_pid,round,
		    (UE_list->UE_template[CC_id][UE_id].DAI-1),
		    UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]);
	    } else {
	      LOG_D(MAC,"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n",
		    module_idP,CC_id,harq_pid,round,
		    UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]);
	      
	    }
	    if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,
					   dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
					   rnti)) {
754 755
	      dl_req->number_dci++;
	      dl_req->number_pdu++;
756

757 758
	      fill_nfapi_dlsch_config(eNB,dl_req,
				      TBS,
759
				      -1            /* retransmission, no pdu_index */,
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
				      rnti,
				      0, // type 0 allocation from 7.1.6 in 36.213
				      0, // virtual_resource_block_assignment_flag, unused here
				      0,          // resource_block_coding, to be filled in later
				      getQm(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]),
				      round&3   , // redundancy version
				      1, // transport blocks
				      0, // transport block to codeword swap flag
				      cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme
				      1, // number of layers
				      1, // number of subbands
			     //			     uint8_t codebook_index,
				      4, // UE category capacity
				      UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 
				      0, // delta_power_offset for TM5
				      0, // ngap
				      0, // nprb
				      cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode
				      0, //number of PRBs treated as one subband, not used here
				      0 // number of beamforming vectors, not used here
				      );

Raymond Knopp's avatar
Raymond Knopp committed
782
	      LOG_D(MAC,"Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n",eNB->pdu_index[CC_id],round);
783

784 785
	      program_dlsch_acknak(module_idP,CC_id,UE_id,frameP,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx);
	      // No TX request for retransmission (check if null request for FAPI)
786 787
	    }
	    else {
788 789
	      LOG_W(MAC,"Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n",
		    frameP,subframeP,UE_id,rnti);
790 791
	    }
	  }
792 793


794 795 796 797 798 799 800 801 802 803 804 805 806
	  add_ue_dlsch_info(module_idP,
			    CC_id,
			    UE_id,
			    subframeP,
			    S_DL_SCHEDULED);
	  
	  //eNB_UE_stats->dlsch_trials[round]++;
	  UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1;
	  UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb;
	  UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb;
	  UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1;
	  UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=eNB_UE_stats->dlsch_mcs1;
	} else {
807 808
          LOG_D(MAC,"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n",
                module_idP, frameP, CC_id, UE_id);
809 810
        }
      } else { /* This is a potentially new SDU opportunity */
811
	
812 813 814
        rlc_status.bytes_in_buffer = 0;
        // Now check RLC information to compute number of required RBs
        // get maximum TBS size for RLC request
815
        TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb);
816 817 818
        // check first for RLC data on DCCH
        // add the length for  all the control elements (timing adv, drx, etc) : header + payload

819
        ta_len = (ue_sched_ctl->ta_update!=0) ? 2 : 0;
820 821 822 823 824 825

        header_len_dcch = 2; // 2 bytes DCCH SDU subheader

        if ( TBS-ta_len-header_len_dcch > 0 ) {
          rlc_status = mac_rlc_status_ind(
                         module_idP,
826
                         rnti,
827
			 module_idP,
828
                         frameP,
829
			 subframeP,
830 831 832 833 834 835 836 837
                         ENB_FLAG_YES,
                         MBMS_FLAG_NO,
                         DCCH,
                         (TBS-ta_len-header_len_dcch)); // transport block set size

          sdu_lengths[0]=0;

          if (rlc_status.bytes_in_buffer > 0) {  // There is DCCH to transmit
838 839
            LOG_D(MAC,"[eNB %d] Frame %d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
                  module_idP,frameP,CC_id,TBS-header_len_dcch);
Raymond.Knopp's avatar
Raymond.Knopp committed
840 841 842 843 844 845 846 847
            sdu_lengths[0] = mac_rlc_data_req(
					      module_idP,
					      rnti,
					      module_idP,
					      frameP,
					      ENB_FLAG_YES,
					      MBMS_FLAG_NO,
					      DCCH,
848
					      TBS, //not used
Raymond.Knopp's avatar
Raymond.Knopp committed
849
					      (char *)&dlsch_buffer[0]);
850

Cedric Roux's avatar
Cedric Roux committed
851 852 853
            T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
              T_INT(harq_pid), T_INT(DCCH), T_INT(sdu_lengths[0]));

854
            LOG_D(MAC,"[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n",module_idP,CC_id,sdu_lengths[0]);
855 856 857 858 859
            sdu_length_total = sdu_lengths[0];
            sdu_lcids[0] = DCCH;
            UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH]+=1;
            UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH]+=sdu_lengths[0];
            num_sdus = 1;
860
#ifdef DEBUG_eNB_SCHEDULER
861
            LOG_T(MAC,"[eNB %d][DCCH] CC_id %d Got %d bytes :",module_idP,CC_id,sdu_lengths[0]);
862

863
            for (j=0; j<sdu_lengths[0]; j++) {
864
              LOG_T(MAC,"%x ",dlsch_buffer[j]);
865
            }
866 867 868 869 870 871 872 873

            LOG_T(MAC,"\n");
#endif
          } else {
            header_len_dcch = 0;
            sdu_length_total = 0;
          }
        }
Raymond.Knopp's avatar
Raymond.Knopp committed
874
	
875 876 877 878
        // check for DCCH1 and update header information (assume 2 byte sub-header)
        if (TBS-ta_len-header_len_dcch-sdu_length_total > 0 ) {
          rlc_status = mac_rlc_status_ind(
                         module_idP,
879
                         rnti,
880
			 module_idP,
881
                         frameP,
882
						 subframeP,
883 884 885 886 887
                         ENB_FLAG_YES,
                         MBMS_FLAG_NO,
                         DCCH+1,
                         (TBS-ta_len-header_len_dcch-sdu_length_total)); // transport block set size less allocations for timing advance and
          // DCCH SDU
Raymond.Knopp's avatar
Raymond.Knopp committed
888
	  sdu_lengths[num_sdus] = 0;
889 890

          if (rlc_status.bytes_in_buffer > 0) {
Raymond Knopp's avatar
Raymond Knopp committed
891
            LOG_D(MAC,"[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
892
                  module_idP,frameP,CC_id,TBS-header_len_dcch-sdu_length_total);
893 894
            sdu_lengths[num_sdus] += mac_rlc_data_req(
                                       module_idP,
895
                                       rnti,
896
				       module_idP,
897 898 899 900
                                       frameP,
                                       ENB_FLAG_YES,
                                       MBMS_FLAG_NO,
                                       DCCH+1,
901
									   TBS, //not used
Raymond.Knopp's avatar
Raymond.Knopp committed
902
                                       (char *)&dlsch_buffer[sdu_length_total]);
903

Cedric Roux's avatar
Cedric Roux committed
904 905 906
            T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
              T_INT(harq_pid), T_INT(DCCH+1), T_INT(sdu_lengths[num_sdus]));

907 908 909 910 911
            sdu_lcids[num_sdus] = DCCH1;
            sdu_length_total += sdu_lengths[num_sdus];
            header_len_dcch += 2;
            UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1]+=1;
            UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1]+=sdu_lengths[num_sdus];
912
	    num_sdus++;
nikaeinn's avatar
nikaeinn committed
913 914
#ifdef DEBUG_eNB_SCHEDULER
            LOG_T(MAC,"[eNB %d][DCCH1] CC_id %d Got %d bytes :",module_idP,CC_id,sdu_lengths[num_sdus]);
915

nikaeinn's avatar
nikaeinn committed
916 917
            for (j=0; j<sdu_lengths[num_sdus]; j++) {
              LOG_T(MAC,"%x ",dlsch_buffer[j]);
918 919
            }

nikaeinn's avatar
nikaeinn committed
920 921
            LOG_T(MAC,"\n");
#endif
922

923
	  }
924 925
        }

926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943
	// assume the max dtch header size, and adjust it later
	header_len_dtch=0;
	header_len_dtch_last=0; // the header length of the last mac sdu
	// lcid has to be sorted before the actual allocation (similar struct as ue_list).
	for (lcid=NB_RB_MAX-1; lcid>=DTCH ; lcid--){
	  // TBD: check if the lcid is active
	  
	  header_len_dtch+=3; 
	  header_len_dtch_last=3;
	  LOG_D(MAC,"[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n",
		module_idP,frameP,lcid,TBS,
		TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch);
	  
	  if (TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch > 0 ) { // NN: > 2 ? 
	    rlc_status = mac_rlc_status_ind(module_idP,
					    rnti,
					    module_idP,
					    frameP,
944
						subframeP,
945 946 947 948 949 950 951 952
					    ENB_FLAG_YES,
					    MBMS_FLAG_NO,
					    lcid,
					    TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch);
	   

	    if (rlc_status.bytes_in_buffer > 0) {
	      
953
	      LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n",
954
		    module_idP,frameP,TBS-header_len_dcch-sdu_length_total-header_len_dtch,lcid, header_len_dtch);
955 956 957 958 959 960 961
	      sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
						       rnti,
						       module_idP,
						       frameP,
						       ENB_FLAG_YES,
						       MBMS_FLAG_NO,
						       lcid,
962
							   TBS,	//not used
963
						       (char*)&dlsch_buffer[sdu_length_total]);
Aikaterini Trilyraki's avatar
Aikaterini Trilyraki committed
964 965 966
	      T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
              T_INT(harq_pid), T_INT(lcid), T_INT(sdu_lengths[num_sdus]));

967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
	      LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n",module_idP,sdu_lengths[num_sdus],lcid);
	      sdu_lcids[num_sdus] = lcid;
	      sdu_length_total += sdu_lengths[num_sdus];
	      UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid]+=1;
	      UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid]+=sdu_lengths[num_sdus];
	      if (sdu_lengths[num_sdus] < 128) {
		header_len_dtch--;
		header_len_dtch_last--;
	      }
	      num_sdus++;
	    } // no data for this LCID
	    else {
	      header_len_dtch-=3;
	    }
	  } // no TBS left
	  else {
	    header_len_dtch-=3;
	    break; 
	  }
	}
	if (header_len_dtch == 0 )
	  header_len_dtch_last= 0;
	// there is at least one SDU 
	// if (num_sdus > 0 ){
	if ((sdu_length_total + header_len_dcch + header_len_dtch )> 0) {
	  
	  // Now compute number of required RBs for total sdu length
	  // Assume RAH format 2
	  // adjust  header lengths
	  header_len_dcch_tmp = header_len_dcch;
	  header_len_dtch_tmp = header_len_dtch;
	  if (header_len_dtch==0) {
	    header_len_dcch = (header_len_dcch >0) ? 1 : 0;//header_len_dcch;  // remove length field
	  } else {
	    header_len_dtch_last-=1; // now use it to find how many bytes has to be removed for the last MAC SDU 
	    header_len_dtch = (header_len_dtch > 0) ? header_len_dtch - header_len_dtch_last  :header_len_dtch;     // remove length field for the last SDU
	  }
1004 1005 1006

          mcs = eNB_UE_stats->dlsch_mcs1;

1007 1008 1009 1010 1011
          if (mcs==0) {
            nb_rb = 4;  // don't let the TBS get too small
          } else {
            nb_rb=min_rb_unit[CC_id];
          }
1012

1013
          TBS = get_TBS_DL(mcs,nb_rb);
1014 1015 1016 1017 1018 1019

          while (TBS < (sdu_length_total + header_len_dcch + header_len_dtch + ta_len))  {
            nb_rb += min_rb_unit[CC_id];  //

            if (nb_rb>nb_available_rb) { // if we've gone beyond the maximum number of RBs
              // (can happen if N_RB_DL is odd)
1020
              TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb);
1021 1022 1023 1024
              nb_rb = nb_available_rb;
              break;
            }

1025
            TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rb);
1026 1027
          }

1028
          if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
1029
            for(j=0; j<N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band
1030
              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
1031 1032 1033 1034 1035
            }
          } else {
            nb_rb_temp = nb_rb;
            j = 0;

1036
            while((nb_rb_temp > 0) && (j<N_RBG[CC_id])) {
1037 1038
              if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
                UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
1039

1040 1041 1042
                if ((j == N_RBG[CC_id]-1) &&
                    ((N_RB_DL[CC_id] == 25)||
                     (N_RB_DL[CC_id] == 50))) {
1043
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
1044
                } else {
1045
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
1046
                }
1047 1048 1049 1050 1051 1052 1053 1054 1055
              }

              j = j+1;
            }
          }

          // decrease mcs until TBS falls below required length
          while ((TBS > (sdu_length_total + header_len_dcch + header_len_dtch + ta_len)) && (mcs>0)) {
            mcs--;
1056
            TBS = get_TBS_DL(mcs,nb_rb);
1057 1058 1059
          }

          // if we have decreased too much or we don't have enough RBs, increase MCS
1060 1061
          while ((TBS < (sdu_length_total + header_len_dcch + header_len_dtch + ta_len)) && ((( ue_sched_ctl->dl_pow_off[CC_id]>0) && (mcs<28))
                 || ( (ue_sched_ctl->dl_pow_off[CC_id]==0) && (mcs<=15)))) {
1062
            mcs++;
1063
            TBS = get_TBS_DL(mcs,nb_rb);
1064 1065 1066 1067 1068
          }

          LOG_D(MAC,"dlsch_mcs before and after the rate matching = (%d, %d)\n",eNB_UE_stats->dlsch_mcs1, mcs);

#ifdef DEBUG_eNB_SCHEDULER
1069 1070
          LOG_D(MAC,"[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n",
                module_idP,CC_id,mcs,TBS,nb_rb);
1071 1072
          // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n",
          //  TBS, sdu_length_total, offset, TBS-sdu_length_total-offset);
1073
#endif
1074 1075 1076 1077 1078 1079 1080 1081

          if ((TBS - header_len_dcch - header_len_dtch - sdu_length_total - ta_len) <= 2) {
            padding = (TBS - header_len_dcch - header_len_dtch - sdu_length_total - ta_len);
            post_padding = 0;
          } else {
            padding = 0;

            // adjust the header len
1082
            if (header_len_dtch==0) {
1083
              header_len_dcch = header_len_dcch_tmp;
1084
            } else { //if (( header_len_dcch==0)&&((header_len_dtch==1)||(header_len_dtch==2)))
1085
              header_len_dtch = header_len_dtch_tmp;
1086
            }
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096

            post_padding = TBS - sdu_length_total - header_len_dcch - header_len_dtch - ta_len ; // 1 is for the postpadding header
          }


          offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
                                         num_sdus,              //num_sdus
                                         sdu_lengths,  //
                                         sdu_lcids,
                                         255,                                   // no drx
1097
                                         ue_sched_ctl->ta_update, // timing advance
1098 1099 1100
                                         NULL,                                  // contention res id
                                         padding,
                                         post_padding);
1101

1102
          //#ifdef DEBUG_eNB_SCHEDULER
1103
          if (ue_sched_ctl->ta_update) {
Raymond Knopp's avatar
Raymond Knopp committed
1104
            LOG_D(MAC,
1105 1106
                  "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_dcch %d, header_dtch %d\n",
                  module_idP,frameP, UE_id, CC_id, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],offset,
1107
                  ue_sched_ctl->ta_update,padding,post_padding,mcs,TBS,nb_rb,header_len_dcch,header_len_dtch);
Aikaterini Trilyraki's avatar
Aikaterini Trilyraki committed
1108
	  }
1109
          //#endif
1110
#ifdef DEBUG_eNB_SCHEDULER
1111 1112
          LOG_T(MAC,"[eNB %d] First 16 bytes of DLSCH : \n");

1113
          for (i=0; i<16; i++) {
1114
            LOG_T(MAC,"%x.",dlsch_buffer[i]);
1115
          }
1116 1117

          LOG_T(MAC,"\n");
1118
#endif
1119 1120
          // cycle through SDUs and place in dlsch_buffer
          memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total);
1121
          // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]);
1122 1123

          // fill remainder of DLSCH with random data
1124
          for (j=0; j<(TBS-sdu_length_total-offset); j++) {
1125
            UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff);
1126
          }
1127

1128

1129 1130 1131
          if (opt_enabled == 1) {
            trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
                      TBS, module_idP, 3, UE_RNTI(module_idP,UE_id),
1132
                      eNB->frame, eNB->subframe,0,0);
1133 1134
            LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d  rnti %x  with size %d\n",
                  module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), TBS);
1135 1136
          }

1137 1138 1139
          T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
            T_INT(harq_pid), T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS));

1140
	  UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb;
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161

          add_ue_dlsch_info(module_idP,
                            CC_id,
                            UE_id,
                            subframeP,
                            S_DL_SCHEDULED);
          // store stats
          eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total;
          eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1;

          UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb;
          UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb;
          UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1;
          UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=mcs;
          UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS;

          UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS- sdu_length_total;
          UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total;
          UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS;
          UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1;

1162
          if (cc[CC_id].tdd_Config != NULL) { // TDD
1163 1164 1165 1166
            UE_list->UE_template[CC_id][UE_id].DAI++;
            update_ul_dci(module_idP,CC_id,rnti,UE_list->UE_template[CC_id][UE_id].DAI);
          }

1167 1168
	  // do PUCCH power control
          // this is the normalized RX power
1169
	  eNB_UE_stats =  &UE_list->eNB_UE_stats[CC_id][UE_id];
1170 1171 1172

	  normalized_rx_power = ue_sched_ctl->pucch1_snr[CC_id];
	  target_rx_power = 20;
1173 1174 1175
	    
          // this assumes accumulated tpc
	  // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
1176 1177 1178
	  int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe;
          if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case
	      ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around
1179 1180
	    if (ue_sched_ctl->pucch1_cqi_update[CC_id] == 1) { 
	      ue_sched_ctl->pucch1_cqi_update[CC_id] = 0;
1181

1182 1183
	      UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP;
	      UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP;
1184
	      
1185 1186 1187 1188 1189 1190 1191 1192 1193
	      if (normalized_rx_power>(target_rx_power+1)) {
		tpc = 0; //-1
		tpc_accumulated--;
	      } else if (normalized_rx_power<(target_rx_power-1)) {
		tpc = 2; //+1
		tpc_accumulated++;
	      } else {
		tpc = 1; //0
	      }
1194 1195
	      	      
	      LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
1196
		    module_idP,frameP, subframeP,harq_pid,tpc,
1197
		    tpc_accumulated,normalized_rx_power,target_rx_power);
1198

1199
	    } // Po_PUCCH has been updated 
1200 1201
	    else {
	      tpc = 1; //0
1202
	    } // time to do TPC update 
1203 1204 1205 1206
	  else {
	    tpc = 1; //0
	  }

1207
	  dl_config_pdu                                                         = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
1208 1209
	  memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
	  dl_config_pdu->pdu_type                                               = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; 
1210
	  dl_config_pdu->pdu_size                                               = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
1211
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                  = NFAPI_DL_DCI_FORMAT_1;
Cedric Roux's avatar
Cedric Roux committed
1212
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level           = get_aggregation(get_bw_index(module_idP,CC_id),ue_sched_ctl->dl_cqi[CC_id],format1);
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                        = rnti;
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type                   = 1;    // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power          = 6000; // equal to RS power
	  
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process                = harq_pid;
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc                         = tpc; // dont adjust power when retransmitting
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1        = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                       = mcs;
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1        = 0;
	  //deactivate second codeword
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2                       = 0;
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2        = 1;
	  if (cc[CC_id].tdd_Config != NULL) { //TDD
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
1227 1228
	    LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n",
		  module_idP,CC_id,harq_pid,
1229 1230 1231
		  (UE_list->UE_template[CC_id][UE_id].DAI-1),
		  mcs);
	  } else {
1232 1233
	    LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n",
		  module_idP,CC_id,harq_pid,mcs);
1234 1235
	    
	  }
1236
	  LOG_D(MAC,"Checking feasibility pdu %d (new sdu)\n",dl_req->number_pdu);
1237
	  if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,rnti)) {
1238 1239 1240


	    ue_sched_ctl->round[CC_id][harq_pid] = 0;
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
	    dl_req->number_dci++;
	    dl_req->number_pdu++;
	    
	    // Toggle NDI for next time
	    LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n",
		  CC_id, frameP,subframeP,UE_id,
		  rnti,harq_pid,UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]);
	    
	    UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
	    UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs;
	    UE_list->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0;
	    AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n");
	    AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n");
	    
	    fill_nfapi_dlsch_config(eNB,dl_req,
				    TBS,
				    eNB->pdu_index[CC_id],
				    rnti,
				    0, // type 0 allocation from 7.1.6 in 36.213
				    0, // virtual_resource_block_assignment_flag, unused here
				    0, // resource_block_coding, to be filled in later
				    getQm(mcs),
				    0, // redundancy version
				    1, // transport blocks
				    0, // transport block to codeword swap flag
				    cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme
				    1, // number of layers
				    1, // number of subbands
				    //			     uint8_t codebook_index,
				    4, // UE category capacity
				    UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 
				    0, // delta_power_offset for TM5
				    0, // ngap
				    0, // nprb
				    cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode
				    0, //number of PRBs treated as one subband, not used here
				    0 // number of beamforming vectors, not used here
				    );  
	    eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body,
							  (frameP*10)+subframeP,
							  TBS,
1282
							  eNB->pdu_index[CC_id],
1283
							  eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]);
1284
	    
Raymond Knopp's avatar
Raymond Knopp committed
1285
	    LOG_D(MAC,"Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n",eNB->pdu_index[CC_id]);
1286

1287 1288
	    eNB->pdu_index[CC_id]++;
	    program_dlsch_acknak(module_idP,CC_id,UE_id,frameP,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx);
1289

1290 1291 1292 1293 1294
	  }
	  else {
	    LOG_W(MAC,"Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n",
		  frameP,subframeP,UE_id,rnti);
	  }
1295
        } else {  // There is no data from RLC or MAC header, so don't schedule
1296 1297

        }
1298
      }
1299

1300 1301
      if (cc[CC_id].tdd_Config != NULL){ // TDD
        set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP);
1302
      }
1303

1304 1305
    } // UE_id loop
  }  // CC_id loop
Raymond Knopp's avatar
 
Raymond Knopp committed
1306

Cedric Roux's avatar
Cedric Roux committed
1307

1308 1309
     
  fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
1310

1311
  stop_meas(&eNB->schedule_dlsch);
1312
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_OUT);
1313

1314 1315
}

1316 1317 1318
//------------------------------------------------------------------------------
void
fill_DLSCH_dci(
1319 1320 1321 1322 1323
	       module_id_t module_idP,
	       frame_t frameP,
	       sub_frame_t subframeP,
	       int* mbsfn_flagP
	       )
1324
//------------------------------------------------------------------------------
1325
{
1326 1327

  // loop over all allocated UEs and compute frequency allocations for PDSCH
Raymond Knopp's avatar
 
Raymond Knopp committed
1328
  int   UE_id = -1;
1329
  uint8_t            /* first_rb, */ nb_rb=3;
1330
  rnti_t        rnti;
1331
  //unsigned char *vrb_map;
1332
  uint8_t            rballoc_sub[25];
1333 1334
  //uint8_t number_of_subbands=13;

1335
  //unsigned char round;
1336 1337 1338 1339 1340 1341 1342 1343 1344
  unsigned char     harq_pid;
  int               i;
  int               CC_id;
  eNB_MAC_INST      *eNB  =RC.mac[module_idP];
  UE_list_t         *UE_list = &eNB->UE_list;
  int               N_RBG;
  int               N_RB_DL;
  COMMON_channels_t *cc;

Raymond Knopp's avatar
 
Raymond Knopp committed
1345
  start_meas(&eNB->fill_DLSCH_dci);
1346
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI,VCD_FUNCTION_IN);
1347 1348

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1349
    LOG_D(MAC,"Doing fill DCI for CC_id %d\n",CC_id);
Raymond Knopp's avatar
 
Raymond Knopp committed
1350 1351 1352

    if (mbsfn_flagP[CC_id]>0)
      continue;
1353

1354 1355 1356
    cc              = &eNB->common_channels[CC_id];
    N_RBG           = to_rbg(cc->mib->message.dl_Bandwidth);
    N_RB_DL         = to_prb(cc->mib->message.dl_Bandwidth);
Raymond Knopp's avatar
 
Raymond Knopp committed
1357

Raymond Knopp's avatar
 
Raymond Knopp committed
1358
    // UE specific DCIs
1359
    for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
1360
      LOG_T(MAC,"CC_id %d, UE_id: %d => status %d\n",CC_id,UE_id,eNB_dlsch_info[module_idP][CC_id][UE_id].status);
1361

1362
      if (eNB_dlsch_info[module_idP][CC_id][UE_id].status == S_DL_SCHEDULED) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1363

1364 1365 1366
        // clear scheduling flag
        eNB_dlsch_info[module_idP][CC_id][UE_id].status = S_DL_WAITING;
        rnti = UE_RNTI(module_idP,UE_id);
1367 1368
	if (cc->tdd_Config) harq_pid = ((frameP*10)+subframeP)%10;
	else harq_pid = ((frameP*10)+subframeP)&7;
1369 1370 1371
        nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];


1372
	
1373
        /// Synchronizing rballoc with rballoc_sub
1374
        for(i=0; i<N_RBG; i++) {
1375
          rballoc_sub[i] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i];
1376
        }
1377

1378
	nfapi_dl_config_request_t      *DL_req         = &RC.mac[module_idP]->DL_req[0];
1379
	nfapi_dl_config_request_pdu_t* dl_config_pdu;
1380

1381 1382
	for (i=0;i<DL_req[CC_id].dl_config_request_body.number_pdu;i++) {
	  dl_config_pdu                    = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[i];
1383
	  if ((dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)&&
1384 1385
	      (dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti == rnti) &&
          (dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format != 1)) {
1386 1387
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding    = allocate_prbs_sub(nb_rb,N_RB_DL,N_RBG,rballoc_sub);
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0;
1388 1389
	  }
	  else if ((dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE)&&
1390 1391
		       (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == rnti) &&
               (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type==0)) {
1392
	    dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding    = allocate_prbs_sub(nb_rb,N_RB_DL,N_RBG,rballoc_sub);
1393 1394
	  }
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
1395 1396
      }
    }
1397 1398

  }
1399

Raymond Knopp's avatar
 
Raymond Knopp committed
1400
  stop_meas(&eNB->fill_DLSCH_dci);
1401
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI,VCD_FUNCTION_OUT);
1402 1403
}

1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
//------------------------------------------------------------------------------
unsigned char*
get_dlsch_sdu(
  module_id_t module_idP,
  int CC_id,
  frame_t frameP,
  rnti_t rntiP,
  uint8_t TBindex
)
//------------------------------------------------------------------------------
1414
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1415

1416
  int UE_id;
1417
  eNB_MAC_INST *eNB=RC.mac[module_idP];
Raymond Knopp's avatar
 
Raymond Knopp committed
1418 1419

  if (rntiP==SI_RNTI) {
1420
    LOG_D(MAC,"[eNB %d] CC_id %d Frame %d Get DLSCH sdu for BCCH \n", module_idP, CC_id, frameP);
Raymond Knopp's avatar
 
Raymond Knopp committed
1421 1422

    return((unsigned char *)&eNB->common_channels[CC_id].BCCH_pdu.payload[0]);
1423 1424
  }

1425
  UE_id = find_UE_id(module_idP,rntiP);
1426

1427
  if (UE_id != -1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1428 1429 1430 1431 1432 1433 1434 1435
    LOG_D(MAC,"[eNB %d] Frame %d:  CC_id %d Get DLSCH sdu for rnti %x => UE_id %d\n",module_idP,frameP,CC_id,rntiP,UE_id);
    return((unsigned char *)&eNB->UE_list.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]);
  } else {
    LOG_E(MAC,"[eNB %d] Frame %d: CC_id %d UE with RNTI %x does not exist\n", module_idP,frameP,CC_id,rntiP);
    return NULL;
  }

}
1436 1437


1438
//------------------------------------------------------------------------------
1439 1440 1441 1442
void update_ul_dci(module_id_t module_idP,
		   uint8_t CC_idP,
		   rnti_t rntiP,
		   uint8_t daiP)
1443
//------------------------------------------------------------------------------
1444
{
1445

1446 1447
  nfapi_hi_dci0_request_t *HI_DCI0_req    = &RC.mac[module_idP]->HI_DCI0_req[CC_idP];
  nfapi_hi_dci0_request_pdu_t  *hi_dci0_pdu    = &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[0];
1448 1449
  COMMON_channels_t    *cc                     = &RC.mac[module_idP]->common_channels[CC_idP];
  int i;
1450

1451

1452
  if (cc->tdd_Config != NULL) { // TDD 
1453
    for (i=0; i<HI_DCI0_req->hi_dci0_request_body.number_of_dci + HI_DCI0_req->hi_dci0_request_body.number_of_dci; i++) {
1454

1455 1456 1457 1458
      if ((hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE)  && 
	  (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti == rntiP))
        hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.dl_assignment_index = (daiP-1)&3;
      
1459 1460 1461 1462 1463
    }
  }
}


1464 1465 1466
//------------------------------------------------------------------------------
void set_ue_dai(
  sub_frame_t   subframeP,
1467 1468
  int           UE_id,
  uint8_t       CC_id,
1469 1470
  uint8_t       tdd_config,
  UE_list_t*    UE_list
1471 1472
)
//------------------------------------------------------------------------------
1473
{
1474 1475
  switch (tdd_config) {
  case 0:
1476
    if ((subframeP==0)||(subframeP==1)||(subframeP==3)||(subframeP==5)||(subframeP==6)||(subframeP==8)) {
1477
      UE_list->UE_template[CC_id][UE_id].DAI = 0;
1478
    }
1479

1480
    break;
1481

1482
  case 1:
1483
    if ((subframeP==0)||(subframeP==4)||(subframeP==5)||(subframeP==9)) {
1484
      UE_list->UE_template[CC_id][UE_id].DAI = 0;
1485
    }
1486

1487
    break;
1488

1489
  case 2:
1490
    if ((subframeP==4)||(subframeP==5)) {
1491
      UE_list->UE_template[CC_id][UE_id].DAI = 0;
1492
    }
1493

1494
    break;
1495

1496
  case 3:
1497
    if ((subframeP==5)||(subframeP==7)||(subframeP==9)) {
1498
      UE_list->UE_template[CC_id][UE_id].DAI = 0;
1499
    }
1500

1501
    break;
1502

1503
  case 4:
1504
    if ((subframeP==0)||(subframeP==6)) {
1505
      UE_list->UE_template[CC_id][UE_id].DAI = 0;
1506
    }
1507

1508
    break;
1509

1510
  case 5:
1511
    if (subframeP==9) {
1512
      UE_list->UE_template[CC_id][UE_id].DAI = 0;
1513
    }
1514

1515
    break;
1516

1517
  case 6:
1518
    if ((subframeP==0)||(subframeP==1)||(subframeP==5)||(subframeP==6)||(subframeP==9)) {
1519
      UE_list->UE_template[CC_id][UE_id].DAI = 0;
1520
    }
1521

1522
    break;
1523

1524 1525 1526 1527 1528
  default:
    UE_list->UE_template[CC_id][UE_id].DAI = 0;
    LOG_N(MAC,"unknow TDD config %d\n",tdd_config);
    break;
  }
1529
}