eNB_scheduler_ulsch.c 91.3 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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_ulsch.c
 * \brief eNB procedures for the ULSCH transport channel
24 25 26
 * \author Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \email: navid.nikaein@eurecom.fr
27
 * \version 1.0
28 29 30 31
 * @ingroup _mac

 */

32 33
/* indented with: indent -kr eNB_scheduler_RA.c */

34 35


36 37 38
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
#include "LAYER2/MAC/mac_extern.h"
39 40
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
41 42 43
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
44
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
45

46
#include "RRC/LTE/rrc_extern.h"
47 48
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"

49
#include "assertions.h"
50 51 52 53
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"

#if defined(ENABLE_ITTI)
54
#include "intertask_interface.h"
55 56
#endif

57 58 59 60 61
#include "ENB_APP/flexran_agent_defs.h"
#include "flexran_agent_ran_api.h"
#include "header.pb-c.h"
#include "flexran.pb-c.h"
#include "flexran_agent_mac.h"
62
#include <dlfcn.h>
63

Cedric Roux's avatar
Cedric Roux committed
64 65
#include "T.h"

66 67 68
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;

69
#define ENABLE_MAC_PAYLOAD_DEBUG
70 71
#define DEBUG_eNB_SCHEDULER 1

72 73 74 75 76 77
extern int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req);
extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
extern uint16_t sfnsf_add_subframe(uint16_t frameP, uint16_t subframeP, int offset);
extern int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req);
extern uint8_t nfapi_mode;

78
// This table holds the allowable PRB sizes for ULSCH transmissions
79
uint8_t rb_table[34] =
80
  { 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32,
81
    36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80, 81, 90, 96, 100
82
  };
83

Xu Bo's avatar
Xu Bo committed
84
extern mui_t    rrc_eNB_mui;
85

86 87 88 89 90 91 92 93 94
void
rx_sdu(const module_id_t enb_mod_idP,
       const int CC_idP,
       const frame_t frameP,
       const sub_frame_t subframeP,
       const rnti_t rntiP,
       uint8_t * sduP,
       const uint16_t sdu_lenP,
       const uint16_t timing_advance, const uint8_t ul_cqi)
Cedric Roux's avatar
Cedric Roux committed
95
{
96
  int current_rnti = rntiP;
97 98
  unsigned char rx_ces[MAX_NUM_CE], num_ce, num_sdu, i, *payload_ptr;
  unsigned char rx_lcids[NB_RB_MAX];
99
  unsigned short rx_lengths[NB_RB_MAX];
100
  int UE_id = find_UE_id(enb_mod_idP, current_rnti);
101
  int RA_id;
102 103 104 105
  int ii, j;
  eNB_MAC_INST *mac = RC.mac[enb_mod_idP];
  int harq_pid =
    subframe2harqpid(&mac->common_channels[CC_idP], frameP, subframeP);
106
  int lcgid_updated[4] = {0, 0, 0, 0};
107 108 109 110 111

  UE_list_t *UE_list = &mac->UE_list;
  int crnti_rx = 0;
  RA_t *ra =
    (RA_t *) & RC.mac[enb_mod_idP]->common_channels[CC_idP].ra[0];
Raymond Knopp's avatar
Raymond Knopp committed
112 113
  int first_rb = 0;

114
  start_meas(&mac->rx_ulsch_sdu);
115

116
  if ((UE_id > MAX_MOBILES_PER_ENB) || (UE_id == -1))
117
    for (ii = 0; ii < NB_RB_MAX; ii++) {
118 119
      rx_lengths[ii] = 0;
    }
120

121 122
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
    (VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU, 1);
123
  if (opt_enabled == 1) {
laurent's avatar
laurent committed
124
    trace_pdu(DIRECTION_UPLINK, sduP, sdu_lenP, 0, WS_C_RNTI, current_rnti, frameP, subframeP,
125 126 127
	      0, 0);
    LOG_D(OPT, "[eNB %d][ULSCH] Frame %d  rnti %x  with size %d\n",
	  enb_mod_idP, frameP, current_rnti, sdu_lenP);
128
  }
129

130
  if (UE_id != -1) {
131
    LOG_D(MAC,
132 133
	  "[eNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu round %d from PHY (rnti %x, UE_id %d) ul_cqi %d\n",
	  enb_mod_idP, harq_pid, CC_idP,frameP,subframeP,
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
	  UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid],
	  current_rnti, UE_id, ul_cqi);

    AssertFatal(UE_list->UE_sched_ctrl[UE_id].
		round_UL[CC_idP][harq_pid] < 8, "round >= 8\n");
    if (sduP != NULL) {
      UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
      UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
      UE_list->UE_sched_ctrl[UE_id].ul_scheduled &= (~(1 << harq_pid));
      /* Update with smoothing: 3/4 of old value and 1/4 of new.
       * This is the logic that was done in the function
       * lte_est_timing_advance_pusch, maybe it's not necessary?
       * maybe it's even not correct at all?
       */
      UE_list->UE_sched_ctrl[UE_id].ta_update =	(UE_list->UE_sched_ctrl[UE_id].ta_update * 3 + timing_advance) / 4;
      UE_list->UE_sched_ctrl[UE_id].pusch_snr[CC_idP] = ul_cqi;
      UE_list->UE_sched_ctrl[UE_id].ul_consecutive_errors = 0;
      first_rb = UE_list->UE_template[CC_idP][UE_id].first_rb_ul[harq_pid];

      if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
	UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
	mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
			       subframeP, UE_RNTI(enb_mod_idP,
						  UE_id));
      }
159 160 161 162 163

      /* update scheduled bytes */
      UE_list->UE_template[CC_idP][UE_id].scheduled_ul_bytes -= UE_list->UE_template[CC_idP][UE_id].TBS_UL[harq_pid];
      if (UE_list->UE_template[CC_idP][UE_id].scheduled_ul_bytes < 0)
        UE_list->UE_template[CC_idP][UE_id].scheduled_ul_bytes = 0;
164
    } else {		// we've got an error
165 166 167
      LOG_I(MAC,
	    "[eNB %d][PUSCH %d] CC_id %d %d.%d ULSCH in error in round %d, ul_cqi %d\n",
	    enb_mod_idP, harq_pid, CC_idP,frameP,subframeP,
168 169 170
	    UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid],
	    ul_cqi);

171 172 173 174
      if(ul_cqi>200){ // too high energy pattern
        UE_list->UE_sched_ctrl[UE_id].pusch_snr[CC_idP] = ul_cqi;
      }

175

Raymond Knopp's avatar
Raymond Knopp committed
176
      //      AssertFatal(1==0,"ulsch in error\n");
177
      if (UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid] == 3) {
178 179 180 181
	UE_list->UE_sched_ctrl[UE_id].ul_scheduled &= (~(1 << harq_pid));
	UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid] = 0;
	if (UE_list->UE_sched_ctrl[UE_id].ul_consecutive_errors++ == 10)
	  UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 1;
182 183 184 185 186

        /* update scheduled bytes */
        UE_list->UE_template[CC_idP][UE_id].scheduled_ul_bytes -= UE_list->UE_template[CC_idP][UE_id].TBS_UL[harq_pid];
        if (UE_list->UE_template[CC_idP][UE_id].scheduled_ul_bytes < 0)
          UE_list->UE_template[CC_idP][UE_id].scheduled_ul_bytes = 0;
187 188

        if (find_RA_id(enb_mod_idP, CC_idP, current_rnti) != -1)
189
          cancel_ra_proc(enb_mod_idP, CC_idP, frameP, current_rnti);
190 191
      } else
	UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid]++;
192 193 194 195 196 197 198

      first_rb = UE_list->UE_template[CC_idP][UE_id].first_rb_ul[harq_pid];

      // Program NACK for PHICH
      LOG_D(MAC,
	"Programming PHICH NACK for rnti %x harq_pid %d (first_rb %d)\n",
	current_rnti, harq_pid, first_rb);
wujing's avatar
wujing committed
199 200 201
      nfapi_hi_dci0_request_t *hi_dci0_req;
      uint8_t sf_ahead_dl = ul_subframe2_k_phich(&mac->common_channels[CC_idP] , subframeP);
      hi_dci0_req = &mac->HI_DCI0_req[CC_idP][(subframeP+sf_ahead_dl)%10];
202 203 204 205 206 207 208 209 210 211 212 213 214
      nfapi_hi_dci0_request_body_t *hi_dci0_req_body = &hi_dci0_req->hi_dci0_request_body;
      nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu =
        &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi];
      memset((void *) hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t));
      hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE;
      hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_hi_pdu);
      hi_dci0_pdu->hi_pdu.hi_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG;
      hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = first_rb;
      hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = 0;
      hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 0;
      hi_dci0_req_body->number_of_hi++;
      hi_dci0_req_body->sfnsf = sfnsf_add_subframe(frameP,subframeP, 0);
      hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG;
215
      hi_dci0_req->sfn_sf = sfnsf_add_subframe(frameP,subframeP, sf_ahead_dl);
216 217
      hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST;

218
      return;
219

220
    }
221
  } else if ((RA_id = find_RA_id(enb_mod_idP, CC_idP, current_rnti)) != -1) {	// Check if this is an RA process for the rnti
222
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
223 224
    if (UE_list->UE_template[CC_idP][UE_id].rach_resource_type > 0) harq_pid=0;
#endif
225 226 227 228 229 230 231
    AssertFatal(mac->common_channels[CC_idP].
		radioResourceConfigCommon->rach_ConfigCommon.
		maxHARQ_Msg3Tx > 1,
		"maxHARQ %d should be greater than 1\n",
		(int) mac->common_channels[CC_idP].
		radioResourceConfigCommon->rach_ConfigCommon.
		maxHARQ_Msg3Tx);
232

233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
    LOG_D(MAC,
	  "[eNB %d][PUSCH %d] CC_id %d [RAPROC Msg3] Received ULSCH sdu round %d from PHY (rnti %x, RA_id %d) ul_cqi %d\n",
	  enb_mod_idP, harq_pid, CC_idP, ra[RA_id].msg3_round,
	  current_rnti, RA_id, ul_cqi);

    first_rb = ra->msg3_first_rb;

    if (sduP == NULL) {	// we've got an error on Msg3
      LOG_D(MAC,
	    "[eNB %d] CC_id %d, RA %d ULSCH in error in round %d/%d\n",
	    enb_mod_idP, CC_idP, RA_id,
	    ra[RA_id].msg3_round,
	    (int) mac->common_channels[CC_idP].
	    radioResourceConfigCommon->rach_ConfigCommon.
	    maxHARQ_Msg3Tx);
248
      if (ra[RA_id].msg3_round >= mac->common_channels[CC_idP].radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx - 1) {
249
	cancel_ra_proc(enb_mod_idP, CC_idP, frameP, current_rnti);
250

251
      }
gauthier's avatar
gauthier committed
252

253
      else {
254 255 256
	first_rb = UE_list->UE_template[CC_idP][UE_id].first_rb_ul[harq_pid];
	ra[RA_id].msg3_round++;
	// prepare handling of retransmission
257 258 259
        get_Msg3allocret(&mac->common_channels[CC_idP],
                 ra[RA_id].Msg3_subframe, ra[RA_id].Msg3_frame,
                 &ra[RA_id].Msg3_frame, &ra[RA_id].Msg3_subframe);
260
	add_msg3(enb_mod_idP, CC_idP, &ra[RA_id], frameP, subframeP);
261
      }
262 263 264

      /* TODO: program NACK for PHICH? */

265 266
      return;
    }
267 268 269 270
  } else {
    LOG_W(MAC,
	  "Cannot find UE or RA corresponding to ULSCH rnti %x, dropping it\n",
	  current_rnti);
271 272
    return;
  }
273 274
  payload_ptr = parse_ulsch_header(sduP, &num_ce, &num_sdu, rx_ces, rx_lcids, rx_lengths, sdu_lenP);

275 276 277 278 279
  if(payload_ptr == NULL){
   LOG_E(MAC,"[eNB %d][PUSCH %d] CC_id %d ulsch header unknown lcid(rnti %x, UE_id %d)\n",
         enb_mod_idP, harq_pid, CC_idP,current_rnti, UE_id);
   return;
  }
gauthier's avatar
gauthier committed
280

281 282
  T(T_ENB_MAC_UE_UL_PDU, T_INT(enb_mod_idP), T_INT(CC_idP),
    T_INT(current_rnti), T_INT(frameP), T_INT(subframeP),
283
    T_INT(harq_pid), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu));
284 285 286 287
  T(T_ENB_MAC_UE_UL_PDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP),
    T_INT(current_rnti), T_INT(frameP), T_INT(subframeP),
    T_INT(harq_pid), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu),
    T_BUFFER(sduP, sdu_lenP));
gauthier's avatar
gauthier committed
288

289 290 291
  mac->eNB_stats[CC_idP].ulsch_bytes_rx = sdu_lenP;
  mac->eNB_stats[CC_idP].total_ulsch_bytes_rx += sdu_lenP;
  mac->eNB_stats[CC_idP].total_ulsch_pdus_rx += 1;
Raymond Knopp's avatar
Raymond Knopp committed
292

293
  UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid] = 0;
Raymond Knopp's avatar
Raymond Knopp committed
294

295
  // control element
296
  for (i = 0; i < num_ce; i++) {
297

298 299
    T(T_ENB_MAC_UE_UL_CE, T_INT(enb_mod_idP), T_INT(CC_idP),
      T_INT(current_rnti), T_INT(frameP), T_INT(subframeP),
Cedric Roux's avatar
Cedric Roux committed
300
      T_INT(rx_ces[i]));
Cedric Roux's avatar
Cedric Roux committed
301

302
    switch (rx_ces[i]) {	// implement and process BSR + CRNTI +
303 304
    case POWER_HEADROOM:
      if (UE_id != -1) {
305 306
	UE_list->UE_template[CC_idP][UE_id].phr_info =
	  (payload_ptr[0] & 0x3f) - PHR_MAPPING_OFFSET;
307
	LOG_D(MAC,
308 309 310 311 312 313
	      "[eNB %d] CC_id %d MAC CE_LCID %d : Received PHR PH = %d (db)\n",
	      enb_mod_idP, CC_idP, rx_ces[i],
	      UE_list->UE_template[CC_idP][UE_id].phr_info);
	UE_list->UE_template[CC_idP][UE_id].phr_info_configured =
	  1;
	UE_list->UE_sched_ctrl[UE_id].phr_received = 1;
314
      }
315
      payload_ptr += sizeof(POWER_HEADROOM_CMD);
316 317
      break;

318 319 320 321 322 323 324 325 326 327
    case CRNTI:
      {
	int old_rnti =
	  (((uint16_t) payload_ptr[0]) << 8) + payload_ptr[1];
	int old_UE_id = find_UE_id(enb_mod_idP, old_rnti);
	LOG_D(MAC,
	      "[eNB %d] Frame %d, Subframe %d CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n",
	      enb_mod_idP, frameP, subframeP, CC_idP, rx_ces[i], i,
	      num_ce, old_rnti, old_UE_id);
	/* receiving CRNTI means that the current rnti has to go away */
328 329
	//cancel_ra_proc(enb_mod_idP, CC_idP, frameP,
	//	       current_rnti);
330 331 332 333 334 335 336 337 338 339 340 341
	if (old_UE_id != -1) {
	  /* TODO: if the UE did random access (followed by a MAC uplink with
	   * CRNTI) because none of its scheduling request was granted, then
	   * according to 36.321 5.4.4 the UE's MAC will notify RRC to release
	   * PUCCH/SRS. According to 36.331 5.3.13 the UE will then apply
	   * default configuration for CQI reporting and scheduling requests,
	   * which basically means that the CQI requests won't work anymore and
	   * that the UE won't do any scheduling request anymore as long as the
	   * eNB doesn't reconfigure the UE.
	   * We have to take care of this. As the code is, nothing is done and
	   * the UE state in the eNB is wrong.
	   */
Xu Bo's avatar
Xu Bo committed
342 343 344
          for (ii = 0; ii < NB_RA_PROC_MAX; ii++) {
            ra = &mac->common_channels[CC_idP].ra[ii];
            if ((ra->rnti == current_rnti) && (ra->state != IDLE)) {
345 346 347 348 349 350 351
              mac_rrc_data_ind(enb_mod_idP,
                               CC_idP,
                               frameP, subframeP,
                               old_rnti,
                               DCCH,
                               (uint8_t *) payload_ptr,
                               rx_lengths[i],
352 353 354 355 356
                               0
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
			       ,ra->rach_resource_type>0
#endif
			       );
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
              // prepare transmission of Msg4(RRCConnectionReconfiguration)
              ra->state = MSGCRNTI;
              LOG_I(MAC,
                    "[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) RRCConnectionReconfiguration(Msg4)\n",
                    enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id);

              UE_id = old_UE_id;
              current_rnti = old_rnti;
              ra->rnti = old_rnti;
              ra->crnti_rrc_mui = rrc_eNB_mui-1;
              ra->crnti_harq_pid = -1;
              //clear timer
              UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
              UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
              UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
              if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
                UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
                mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
                                       subframeP, old_rnti);
Xu Bo's avatar
Xu Bo committed
376
              }
377 378 379 380
              UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
              UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
              break;
            }
Xu Bo's avatar
Xu Bo committed
381
          }
382
        } else {
Xu Bo's avatar
Xu Bo committed
383
          cancel_ra_proc(enb_mod_idP, CC_idP, frameP,current_rnti);
384
        }
385 386 387
	crnti_rx = 1;
	payload_ptr += 2;
	break;
kaltenbe's avatar
kaltenbe committed
388
      }
389 390

    case TRUNCATED_BSR:
391 392 393 394
    case SHORT_BSR:
      {
	uint8_t lcgid;
	lcgid = (payload_ptr[0] >> 6);
395 396

	LOG_D(MAC,
397 398 399 400 401 402 403 404 405 406
	      "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n",
	      enb_mod_idP, CC_idP, rx_ces[i], lcgid,
	      payload_ptr[0] & 0x3f);

	if (crnti_rx == 1)
	  LOG_D(MAC,
		"[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n",
		enb_mod_idP, CC_idP, rx_ces[i], lcgid,
		payload_ptr[0] & 0x3f);
	if (UE_id != -1) {
407
          int bsr = payload_ptr[0] & 0x3f;
408

409
          lcgid_updated[lcgid] = 1;
410

411 412
          // update buffer info
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid] = BSR_TABLE[bsr];
413

414
          UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer =
Niccolò Iardella's avatar
Niccolò Iardella committed
415 416 417 418
              UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] +
              UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1] +
              UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2] +
              UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3];
419
          //UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer += UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer / 4;
420

421 422 423 424 425 426 427 428 429
	  RC.eNB[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = (payload_ptr[0] & 0x3f);
	  if (UE_id == UE_list->head)
	    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,
						    RC.eNB[enb_mod_idP][CC_idP]->pusch_stats_bsr
						    [UE_id][(frameP * 10) + subframeP]);
	  if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid] == 0) {
	    UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid] = frameP;
	  }
	  if (mac_eNB_get_rrc_status(enb_mod_idP,UE_RNTI(enb_mod_idP, UE_id)) < RRC_CONNECTED)
430
	    LOG_D(MAC,
431
		  "[eNB %d] CC_id %d MAC CE_LCID %d : estimated_ul_buffer = %d (lcg increment %d)\n",
432
		  enb_mod_idP, CC_idP, rx_ces[i],
433 434
		  UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer,
		  UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid]);
435
	} else {
436 437

	}
438
	payload_ptr += 1;	//sizeof(SHORT_BSR); // fixme
439
      }
440
      break;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
441

442
    case LONG_BSR:
443
      if (UE_id != -1) {
444 445 446 447 448
        int bsr0 = (payload_ptr[0] & 0xFC) >> 2;
        int bsr1 = ((payload_ptr[0] & 0x03) << 4) | ((payload_ptr[1] & 0xF0) >> 4);
        int bsr2 = ((payload_ptr[1] & 0x0F) << 2) | ((payload_ptr[2] & 0xC0) >> 6);
        int bsr3 = payload_ptr[2] & 0x3F;

Niccolò Iardella's avatar
Niccolò Iardella committed
449 450 451 452
        lcgid_updated[LCGID0] = 1;
        lcgid_updated[LCGID1] = 1;
        lcgid_updated[LCGID2] = 1;
        lcgid_updated[LCGID3] = 1;
453

Cedric Roux's avatar
Cedric Roux committed
454
        // update buffer info
455 456 457 458 459 460
        UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] = BSR_TABLE[bsr0];
        UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1] = BSR_TABLE[bsr1];
        UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2] = BSR_TABLE[bsr2];
        UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3] = BSR_TABLE[bsr3];

        UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer =
Niccolò Iardella's avatar
Niccolò Iardella committed
461 462 463 464
            UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] +
            UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1] +
            UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2] +
            UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3];
465 466 467 468 469
        //UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer += UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer / 4;

        LOG_D(MAC,
              "[eNB %d] CC_id %d MAC CE_LCID %d: Received long BSR. Size is LCGID0 = %u LCGID1 = "
              "%u LCGID2 = %u LCGID3 = %u\n", enb_mod_idP, CC_idP,
470
              rx_ces[i],
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
              UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0],
              UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1],
              UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2],
              UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3]);
        if (crnti_rx == 1)
          LOG_D(MAC,
                "[eNB %d] CC_id %d MAC CE_LCID %d: Received long BSR. Size is LCGID0 = %u LCGID1 = "
                "%u LCGID2 = %u LCGID3 = %u\n", enb_mod_idP,
                CC_idP, rx_ces[i],
                UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0],
                UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1],
                UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2],
                UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3]);

	if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] == 0) {
486 487 488 489
	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0] = 0;
	} else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0] == 0) {
	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0] = frameP;
	}
490

491
	if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1] == 0) {
492 493 494
	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID1] = 0;
	} else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID1] == 0) {
	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID1] = frameP;
495 496
	}

497
	if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2] == 0) {
498 499 500 501
	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID2] = 0;
	} else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID2] == 0) {
	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID2] = frameP;
	}
502

503
	if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3] == 0) {
504 505 506
	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID3] = 0;
	} else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID3] == 0) {
	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID3] = frameP;
507 508

	}
509 510
      }

511
      payload_ptr += 3;	////sizeof(LONG_BSR);
512 513 514
      break;

    default:
515 516 517
      LOG_E(MAC,
	    "[eNB %d] CC_id %d Received unknown MAC header (0x%02x)\n",
	    enb_mod_idP, CC_idP, rx_ces[i]);
518 519 520 521
      break;
    }
  }

522 523 524
  for (i = 0; i < num_sdu; i++) {
    LOG_D(MAC, "SDU Number %d MAC Subheader SDU_LCID %d, length %d\n",
	  i, rx_lcids[i], rx_lengths[i]);
525

526
    T(T_ENB_MAC_UE_UL_SDU, T_INT(enb_mod_idP), T_INT(CC_idP),
527
      T_INT(current_rnti), T_INT(frameP), T_INT(subframeP),
Cedric Roux's avatar
Cedric Roux committed
528
      T_INT(rx_lcids[i]), T_INT(rx_lengths[i]));
529
    T(T_ENB_MAC_UE_UL_SDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP),
530
      T_INT(current_rnti), T_INT(frameP), T_INT(subframeP),
531 532 533
      T_INT(rx_lcids[i]), T_INT(rx_lengths[i]), T_BUFFER(payload_ptr,
							 rx_lengths
							 [i]));
Cedric Roux's avatar
Cedric Roux committed
534

535
    switch (rx_lcids[i]) {
536
    case CCCH:
Cedric Roux's avatar
Cedric Roux committed
537
      if (rx_lengths[i] > CCCH_PAYLOAD_SIZE_MAX) {
538 539 540 541 542
	LOG_E(MAC,
	      "[eNB %d/%d] frame %d received CCCH of size %d (too big, maximum allowed is %d, sdu_len %d), dropping packet\n",
	      enb_mod_idP, CC_idP, frameP, rx_lengths[i],
	      CCCH_PAYLOAD_SIZE_MAX, sdu_lenP);
	break;
Cedric Roux's avatar
Cedric Roux committed
543
      }
544 545 546 547 548 549 550 551 552
      LOG_D(MAC,
	    "[eNB %d][RAPROC] CC_id %d Frame %d, Received CCCH:  %x.%x.%x.%x.%x.%x, Terminating RA procedure for UE rnti %x\n",
	    enb_mod_idP, CC_idP, frameP, payload_ptr[0],
	    payload_ptr[1], payload_ptr[2], payload_ptr[3],
	    payload_ptr[4], payload_ptr[5], current_rnti);
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC, 1);
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC, 0);
      for (ii = 0; ii < NB_RA_PROC_MAX; ii++) {
	RA_t *ra = &mac->common_channels[CC_idP].ra[ii];
553

554 555 556 557
	LOG_D(MAC,
	      "[mac %d][RAPROC] CC_id %d Checking proc %d : rnti (%x, %x), state %d\n",
	      enb_mod_idP, CC_idP, ii, ra->rnti,
	      current_rnti, ra->state);
558

559
	if ((ra->rnti == current_rnti) && (ra->state != IDLE)) {
560

561
	  //payload_ptr = parse_ulsch_header(msg3,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,msg3_len);
562

563 564
	  if (UE_id < 0) {
	    memcpy(&ra->cont_res_id[0], payload_ptr, 6);
565
	    LOG_D(MAC,
566 567 568 569 570 571
		  "[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3: length %d, offset %ld\n",
		  enb_mod_idP, CC_idP, frameP, rx_lengths[i],
		  payload_ptr - sduP);

	    if ((UE_id = add_new_ue(enb_mod_idP, CC_idP,
				    mac->common_channels[CC_idP].
572
				    ra->rnti, harq_pid
573
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
574 575
				    ,
				    mac->common_channels[CC_idP].
576
				    ra->rach_resource_type
577
#endif
578
				    )) == -1) {
579 580 581
              LOG_E(MAC,"[MAC][eNB] Max user count reached\n");
              cancel_ra_proc(enb_mod_idP, CC_idP, frameP,current_rnti);
              break;
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
	      // kill RA procedure
	    } else
	      LOG_D(MAC,
		    "[eNB %d][RAPROC] CC_id %d Frame %d Added user with rnti %x => UE %d\n",
		    enb_mod_idP, CC_idP, frameP, ra->rnti,
		    UE_id);
	  } else {
	    LOG_D(MAC,
		  "[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %ld\n",
		  enb_mod_idP, CC_idP, frameP, UE_id,
		  rx_lengths[i], payload_ptr - sduP);
	    // kill RA procedure
	  }

	  mac_rrc_data_ind(enb_mod_idP,
597
			   CC_idP,
598 599
			   frameP, subframeP,
			   current_rnti,
600
			   CCCH,
601
			   (uint8_t *) payload_ptr,
602
			   rx_lengths[i],
603
			   0
604
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
605
			   ,ra->rach_resource_type>0
606 607 608
#endif
			   );

Lionel Gauthier's avatar
 
Lionel Gauthier committed
609

610 611 612 613 614
	  if (num_ce > 0) {	// handle msg3 which is not RRCConnectionRequest
	    //  process_ra_message(msg3,num_ce,rx_lcids,rx_ces);
	  }
	  // prepare transmission of Msg4
	  ra->state = MSG4;
Raymond Knopp's avatar
Raymond Knopp committed
615 616 617



618 619 620 621 622 623 624 625 626 627 628 629 630 631
          if(mac->common_channels[CC_idP].tdd_Config!=NULL){
            switch(mac->common_channels[CC_idP].tdd_Config->subframeAssignment){
            case 1:
              ra->Msg4_frame = frameP + ((subframeP > 2) ? 1 : 0);
              ra->Msg4_subframe = (subframeP + 7) % 10;
              break;
            default: printf("%s:%d: TODO\n", __FILE__, __LINE__); abort();
             // TODO need to be complete for other tdd configs.
            }
          }else{
            // Program Msg4 PDCCH+DLSCH/MPDCCH transmission 4 subframes from now, // Check if this is ok for BL/CE, or if the rule is different
            ra->Msg4_frame = frameP + ((subframeP > 5) ? 1 : 0);
            ra->Msg4_subframe = (subframeP + 4) % 10;
          }
Cedric Roux's avatar
Cedric Roux committed
632

633
          UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0;
634 635
	}		// if process is active
      }			// loop on RA processes
Cedric Roux's avatar
Cedric Roux committed
636

637
      break;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
638

639 640
    case DCCH:
    case DCCH1:
641
      //      if(eNB_mac_inst[module_idP][CC_idP].Dcch_lchan[UE_id].Active==1){
Cedric Roux's avatar
Cedric Roux committed
642

Lionel Gauthier's avatar
 
Lionel Gauthier committed
643

Raymond Knopp's avatar
 
Raymond Knopp committed
644
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
645 646 647 648
      LOG_T(MAC, "offset: %d\n",
	    (unsigned char) ((unsigned char *) payload_ptr - sduP));
      for (j = 0; j < 32; j++) {
	LOG_T(MAC, "%x ", payload_ptr[j]);
649
      }
650
      LOG_T(MAC, "\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
651
#endif
Lionel Gauthier's avatar
 
Lionel Gauthier committed
652

653
      if (UE_id != -1) {
654 655 656 657 658 659 660 661 662 663 664 665 666 667
        if (lcgid_updated[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] == 0) {
	  // adjust buffer occupancy of the correponding logical channel group
	  if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] >= rx_lengths[i])
	    UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] -= rx_lengths[i];
	  else
	    UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] = 0;

          UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer =
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[0] +
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[1] +
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[2] +
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[3];
          //UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer += UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer / 4;
        }
668

669 670 671 672
	LOG_D(MAC,
	      "[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DCCH, received %d bytes form UE %d on LCID %d \n",
	      enb_mod_idP, CC_idP, frameP, rx_lengths[i], UE_id,
	      rx_lcids[i]);
673

674 675 676
	mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL);	//(unsigned int*)crc_status);
	UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1;
	UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i];
677

Raymond Knopp's avatar
Raymond Knopp committed
678

679
      }
Cedric Roux's avatar
Cedric Roux committed
680

681
      /* UE_id != -1 */
Cedric Roux's avatar
Cedric Roux committed
682
      // }
683 684
      break;

Navid Nikaein's avatar
Navid Nikaein committed
685 686
      // all the DRBS
    case DTCH:
687
    default:
Lionel Gauthier's avatar
 
Lionel Gauthier committed
688

Raymond Knopp's avatar
 
Raymond Knopp committed
689
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
690 691 692 693
      LOG_T(MAC, "offset: %d\n",
	    (unsigned char) ((unsigned char *) payload_ptr - sduP));
      for (j = 0; j < 32; j++) {
	LOG_T(MAC, "%x ", payload_ptr[j]);
694
      }
695
      LOG_T(MAC, "\n");
696
#endif
697 698 699 700 701
      if (rx_lcids[i] < NB_RB_MAX) {
	LOG_D(MAC,
	      "[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n",
	      enb_mod_idP, CC_idP, frameP, rx_lengths[i], UE_id,
	      rx_lcids[i]);
702

703 704 705 706 707 708 709 710 711 712 713 714
	if (UE_id != -1) {
	  // adjust buffer occupancy of the correponding logical channel group
	  LOG_D(MAC,
		"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d, removing from LCGID %ld, %d\n",
		enb_mod_idP, CC_idP, frameP, rx_lengths[i],
		UE_id, rx_lcids[i],
		UE_list->UE_template[CC_idP][UE_id].
		lcgidmap[rx_lcids[i]],
		UE_list->UE_template[CC_idP][UE_id].
		ul_buffer_info[UE_list->UE_template[CC_idP]
			       [UE_id].lcgidmap[rx_lcids[i]]]);

715 716 717 718 719 720 721 722 723 724 725 726
          if (lcgid_updated[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] == 0) {
	    if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] >= rx_lengths[i])
	      UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] -= rx_lengths[i];
	    else
	      UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] = 0;

            UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer =
               UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[0] +
               UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[1] +
               UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[2] +
               UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[3];
            //UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer += UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer / 4;
Cedric Roux's avatar
Cedric Roux committed
727
          }
728

729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
	  if ((rx_lengths[i] < SCH_PAYLOAD_SIZE_MAX) && (rx_lengths[i] > 0)) {	// MAX SIZE OF transport block
	    mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL);	//(unsigned int*)crc_status);

	    UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1;
	    UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i];
	    //clear uplane_inactivity_timer
	    UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
	  } else {	/* rx_length[i] */
	    UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx += 1;
	    LOG_E(MAC,
		  "[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d ",
		  enb_mod_idP, CC_idP, frameP, rx_lcids[i],
		  UE_id);
	  }
	} else {	/*(UE_id != -1 */
	  LOG_E(MAC,
		"[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ",
		enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id);
747
	}
Navid Nikaein's avatar
Navid Nikaein committed
748
      }
749 750

      break;
Raymond Knopp's avatar
 
Raymond Knopp committed
751
    }
Cedric Roux's avatar
Cedric Roux committed
752

753
    payload_ptr += rx_lengths[i];
754 755
  }

Raymond Knopp's avatar
Raymond Knopp committed
756
  // Program ACK for PHICH
757 758 759
  LOG_D(MAC,
	"Programming PHICH ACK for rnti %x harq_pid %d (first_rb %d)\n",
	current_rnti, harq_pid, first_rb);
760 761 762 763
  nfapi_hi_dci0_request_t *hi_dci0_req;
  uint8_t sf_ahead_dl = ul_subframe2_k_phich(&mac->common_channels[CC_idP] , subframeP);
  hi_dci0_req = &mac->HI_DCI0_req[CC_idP][(subframeP+sf_ahead_dl)%10];

764 765 766 767 768 769 770 771 772 773 774 775 776
  nfapi_hi_dci0_request_body_t *hi_dci0_req_body = &hi_dci0_req->hi_dci0_request_body;
  nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu =
    &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi];
  memset((void *) hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t));
  hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE;
  hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_hi_pdu);
  hi_dci0_pdu->hi_pdu.hi_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG;
  hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = first_rb;
  hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = 0;
  hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 1;
  hi_dci0_req_body->number_of_hi++;
  hi_dci0_req_body->sfnsf = sfnsf_add_subframe(frameP,subframeP, 0);
  hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG;
777
  hi_dci0_req->sfn_sf = sfnsf_add_subframe(frameP,subframeP, sf_ahead_dl);
778
  hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST;
Cedric Roux's avatar
Cedric Roux committed
779

780
  /* NN--> FK: we could either check the payload, or use a phy helper to detect a false msg3 */
781
  if ((num_sdu == 0) && (num_ce == 0)) {
782
    if (UE_id != -1)
783
      UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx += 1;
784
    /*
785
      if (msg3_flagP != NULL) {
786
      if( *msg3_flagP == 1 ) {
787
      LOG_I(MAC,"[eNB %d] CC_id %d frame %d : false msg3 detection: signal phy to canceling RA and remove the UE\n", enb_mod_idP, CC_idP, frameP);
788
      *msg3_flagP=0;
789
      }
790
      } */
791
  } else {
792
    if (UE_id != -1) {
793 794 795
      UE_list->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx        = sdu_lenP;
      UE_list->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx += sdu_lenP;
      UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx  += 1;
796
    }
797 798
  }

799 800
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU, 0);
  stop_meas(&mac->rx_ulsch_sdu);
Raymond Knopp's avatar
 
Raymond Knopp committed
801 802
}

803 804
uint32_t bytes_to_bsr_index(int32_t nbytes)
{
805
  uint32_t i = 0;
806

807 808
  if (nbytes < 0) {
    return (0);
809
  }
810

811
  while ((i < BSR_TABLE_SIZE) && (BSR_TABLE[i] <= nbytes)) {
812 813 814
    i++;
  }

815
  return (i - 1);
816 817
}

818 819 820
void
add_ue_ulsch_info(module_id_t module_idP, int CC_id, int UE_id,
		  sub_frame_t subframeP, UE_ULSCH_STATUS status)
821
{
822 823 824
  eNB_ulsch_info[module_idP][CC_id][UE_id].rnti     = UE_RNTI(module_idP, UE_id);
  eNB_ulsch_info[module_idP][CC_id][UE_id].subframe = subframeP;
  eNB_ulsch_info[module_idP][CC_id][UE_id].status   = status;
825

826
  eNB_ulsch_info[module_idP][CC_id][UE_id].serving_num++;
827 828 829
}

unsigned char *parse_ulsch_header(unsigned char *mac_header,
830 831 832 833 834 835
				  unsigned char *num_ce,
				  unsigned char *num_sdu,
				  unsigned char *rx_ces,
				  unsigned char *rx_lcids,
				  unsigned short *rx_lengths,
				  unsigned short tb_length)
836
{
837 838
  unsigned char not_done = 1, num_ces = 0, num_sdus =
    0, lcid, num_sdu_cnt;
839
  unsigned char *mac_header_ptr = mac_header;
840
  unsigned short length, ce_len = 0;
841

842
  while (not_done == 1) {
843

844
    if (((SCH_SUBHEADER_FIXED *) mac_header_ptr)->E == 0) {
845
      not_done = 0;
846
    }
847

848
    lcid = ((SCH_SUBHEADER_FIXED *) mac_header_ptr)->LCID;
849 850

    if (lcid < EXTENDED_POWER_HEADROOM) {
851 852 853
      if (not_done == 0) {	// last MAC SDU, length is implicit
	mac_header_ptr++;
	length = tb_length - (mac_header_ptr - mac_header) - ce_len;
854

855 856 857
	for (num_sdu_cnt = 0; num_sdu_cnt < num_sdus;
	     num_sdu_cnt++) {
	  length -= rx_lengths[num_sdu_cnt];
858
	}
859
      } else {
860 861 862 863 864 865 866 867 868
	if (((SCH_SUBHEADER_SHORT *) mac_header_ptr)->F == 0) {
	  length = ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->L;
	  mac_header_ptr += 2;	//sizeof(SCH_SUBHEADER_SHORT);
	} else {	// F = 1
	  length =
	    ((((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_MSB &
	      0x7f) << 8) | (((SCH_SUBHEADER_LONG *)
			      mac_header_ptr)->L_LSB & 0xff);
	  mac_header_ptr += 3;	//sizeof(SCH_SUBHEADER_LONG);
869
	}
870 871
      }

872 873 874 875
      LOG_D(MAC,
	    "[eNB] sdu %d lcid %d tb_length %d length %d (offset now %ld)\n",
	    num_sdus, lcid, tb_length, length,
	    mac_header_ptr - mac_header);
876 877 878
      rx_lcids[num_sdus] = lcid;
      rx_lengths[num_sdus] = length;
      num_sdus++;
879
    } else {		// This is a control element subheader POWER_HEADROOM, BSR and CRNTI
880
      if (lcid == SHORT_PADDING) {
881
	mac_header_ptr++;
882
      } else {
883 884 885 886 887 888 889 890 891 892 893 894 895 896
	rx_ces[num_ces] = lcid;
	num_ces++;
	mac_header_ptr++;

	if (lcid == LONG_BSR) {
	  ce_len += 3;
	} else if (lcid == CRNTI) {
	  ce_len += 2;
	} else if ((lcid == POWER_HEADROOM)
		   || (lcid == TRUNCATED_BSR)
		   || (lcid == SHORT_BSR)) {
	  ce_len++;
	} else {
	  LOG_E(MAC, "unknown CE %d \n", lcid);
897 898
	  //AssertFatal(1 == 0, "unknown CE");
          return NULL;
899
	}
900
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
901
    }
902
  }
903

904 905 906
  *num_ce = num_ces;
  *num_sdu = num_sdus;

907
  return (mac_header_ptr);
908 909
}

910 911 912 913 914
/* This function is called by PHY layer when it schedules some
 * uplink for a random access message 3.
 * The MAC scheduler has to skip the RBs used by this message 3
 * (done below in schedule_ulsch).
 */
915
void
916
set_msg3_subframe(module_id_t mod_id,
917 918 919 920
		  int CC_id,
		  int frame,
		  int subframe, int rnti, int Msg3_frame,
		  int Msg3_subframe)
921
{
922
  eNB_MAC_INST *mac = RC.mac[mod_id];
923
  int i;
924 925 926 927 928
  for (i = 0; i < NB_RA_PROC_MAX; i++) {
    if (mac->common_channels[CC_id].ra[i].state != IDLE &&
	mac->common_channels[CC_id].ra[i].rnti == rnti) {
      mac->common_channels[CC_id].ra[i].Msg3_subframe =
	Msg3_subframe;
929 930 931 932
      break;
    }
  }
}
933

934 935 936
void
schedule_ulsch(module_id_t module_idP, frame_t frameP,
	       sub_frame_t subframeP)
Cedric Roux's avatar
Cedric Roux committed
937
{
Niccolò Iardella's avatar
Niccolò Iardella committed
938
  uint16_t first_rb[NFAPI_CC_MAX], i;
939
  int CC_id;
940
  eNB_MAC_INST *mac = RC.mac[module_idP];
941
  slice_info_t *sli = &RC.mac[module_idP]->slice_info;
942
  COMMON_channels_t *cc;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
943

944
  start_meas(&mac->schedule_ulsch);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
945

946
  int sched_frame=frameP;
947
  int sched_subframe = (subframeP + 4) % 10;
948

949
  cc = &mac->common_channels[0];
950 951 952 953 954 955
  int tdd_sfa;
  // for TDD: check subframes where we have to act and return if nothing should be done now
  if (cc->tdd_Config) {
    tdd_sfa = cc->tdd_Config->subframeAssignment;
    switch (subframeP) {
    case 0:
956
      if ((tdd_sfa == 0) || (tdd_sfa == 3))
957
	sched_subframe = 4;
958 959
      else if (tdd_sfa == 6)
	sched_subframe = 7;
960 961
      else
	return;
962 963
      break;
    case 1:
964 965 966 967
      if ((tdd_sfa == 0) || (tdd_sfa == 1))
	sched_subframe = 7;
      else if (tdd_sfa == 6)
	sched_subframe = 8;
968 969
      else
        return;
970 971 972 973
      break;
    default:
      return;

974
    case 2:		// Don't schedule UL in subframe 2 for TDD
975 976
      return;
    case 3:
977 978 979 980
      if (tdd_sfa == 2)
	sched_subframe = 7;
      else
	return;
981 982
      break;
    case 4:
983 984 985 986
      if (tdd_sfa == 1)
	sched_subframe = 8;
      else
	return;
987 988
      break;
    case 5:
989 990 991
      if (tdd_sfa == 0)
	sched_subframe = 9;
      else if (tdd_sfa == 6)
992
	sched_subframe = 2;
993 994
      else
	return;
995 996
      break;
    case 6:
997
      if (tdd_sfa == 0 || tdd_sfa == 1)
998 999 1000 1001 1002
	sched_subframe = 2;
      else if (tdd_sfa == 6)
	sched_subframe = 3;
      else
	return;
1003 1004 1005 1006
      break;
    case 7:
      return;
    case 8:
1007 1008
      if ((tdd_sfa >= 2) && (tdd_sfa <= 5))
        sched_subframe = 2;
1009
      else
1010
        return;
1011 1012
      break;
    case 9:
1013
      if ((tdd_sfa == 1) || (tdd_sfa == 3) || (tdd_sfa == 4))
1014
        sched_subframe = 3;
1015
      else if (tdd_sfa == 6)
1016
        sched_subframe = 4;
1017
      else
1018
        return;
1019 1020 1021
      break;
    }
  }
sharma's avatar
sharma committed
1022

1023 1024

#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
sharma's avatar
sharma committed
1025 1026 1027 1028 1029
  int  emtc_active[5];
  memset(emtc_active,0,5*sizeof(int));
  schedule_ulsch_rnti_emtc(module_idP, frameP, subframeP, sched_subframe, emtc_active);
#endif

1030
  if (sched_subframe < subframeP) sched_frame++;
1031 1032


sharma's avatar
sharma committed
1033
    //leave out first RB for PUCCH and first narrowband if emtc
1034
  for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) {
1035 1036
    //leave out first RB for PUCCH
    first_rb[CC_id] = 1;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1037

1038
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
sharma's avatar
sharma committed
1039 1040 1041 1042
    first_rb[CC_id] = (emtc_active[CC_id] == 1) ? 7 : 1;
#else
    first_rb[CC_id] = 1;
#endif
1043 1044 1045 1046
    // UE data info;
    // check which UE has data to transmit
    // function to decide the scheduling
    // e.g. scheduling_rslt = Greedy(granted_UEs, nb_RB)
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1047

1048 1049
    // default function for default scheduling
    //
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1050

1051 1052 1053 1054
    // output of scheduling, the UE numbers in RBs, where it is in the code???
    // check if RA (Msg3) is active in this subframeP, if so skip the PRBs used for Msg3
    // Msg3 is using 1 PRB so we need to increase first_rb accordingly
    // not sure about the break (can there be more than 1 active RA procedure?)
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1055

1056 1057 1058 1059 1060 1061
    for (i = 0; i < NB_RA_PROC_MAX; i++) {
      if ((cc->ra[i].state == WAITMSG3) &&
	  (cc->ra[i].Msg3_subframe == sched_subframe)) {
	first_rb[CC_id]++;
	//    cc->ray[i].Msg3_subframe = -1;
	break;
1062
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1063
    }
1064
  }
1065

1066
  for (i = 0; i < sli->n_ul; i++) {
1067
    // Run each enabled slice-specific schedulers one by one
1068
    sli->ul[i].sched_cb(module_idP, i, frameP, subframeP, sched_subframe, first_rb);
1069
  }
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1070

1071
  stop_meas(&mac->schedule_ulsch);
1072 1073
}

1074 1075 1076 1077 1078
void schedule_ulsch_rnti(module_id_t module_idP,
			 int slice_idx,
			 frame_t frameP,
			 sub_frame_t subframeP,
			 unsigned char sched_subframeP, uint16_t * first_rb)
1079
{
1080 1081 1082 1083 1084 1085 1086 1087
  int UE_id;
  uint8_t aggregation = 2;
  rnti_t rnti = -1;
  uint8_t round = 0;
  uint8_t harq_pid = 0;
  uint8_t status = 0;
  uint8_t rb_table_index = -1;
  uint32_t cqi_req, cshift, ndi, tpc;
1088
  int32_t normalized_rx_power, target_rx_power;
1089 1090 1091 1092 1093 1094 1095
  int n;
  int CC_id = 0;
  int drop_ue = 0;
  int N_RB_UL;
  eNB_MAC_INST *mac = RC.mac[module_idP];
  COMMON_channels_t *cc = mac->common_channels;
  UE_list_t *UE_list = &mac->UE_list;
1096
  slice_info_t *sli = &RC.mac[module_idP]->slice_info;
1097 1098 1099 1100
  UE_TEMPLATE *UE_template;
  UE_sched_ctrl *UE_sched_ctrl;
  int sched_frame = frameP;
  int rvidx_tab[4] = { 0, 2, 3, 1 };
1101 1102
  uint16_t          ul_req_index;
  uint8_t           dlsch_flag;
Niccolò Iardella's avatar
Niccolò Iardella committed
1103
  int first_rb_slice[NFAPI_CC_MAX];
1104 1105

  if (sched_subframeP < subframeP)
1106
      sched_frame++;
1107

1108
  nfapi_hi_dci0_request_t        *hi_dci0_req = &mac->HI_DCI0_req[CC_id][subframeP];
1109
  nfapi_hi_dci0_request_body_t   *hi_dci0_req_body = &hi_dci0_req->hi_dci0_request_body;
1110 1111
  nfapi_hi_dci0_request_pdu_t    *hi_dci0_pdu;

1112 1113
  nfapi_ul_config_request_t *ul_req_tmp            = &mac->UL_req_tmp[CC_id][sched_subframeP];
  nfapi_ul_config_request_body_t *ul_req_tmp_body  = &ul_req_tmp->ul_config_request_body;
1114
  nfapi_ul_config_ulsch_harq_information *ulsch_harq_information;
Niccolò Iardella's avatar
Niccolò Iardella committed
1115

1116
  for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; ++CC_id) {
Niccolò Iardella's avatar
Niccolò Iardella committed
1117
    N_RB_UL = to_prb(cc[CC_id].ul_Bandwidth);
1118 1119
    UE_list->first_rb_offset[CC_id][slice_idx] = cmin(N_RB_UL, sli->ul[slice_idx].first_rb);
  }
1120

1121
  //LOG_D(MAC, "entering ulsch preprocesor\n");
1122
  ulsch_scheduler_pre_processor(module_idP, slice_idx, frameP, subframeP, sched_subframeP, first_rb);
1123

1124
	for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; ++CC_id) {
1125
    first_rb_slice[CC_id] = first_rb[CC_id] + UE_list->first_rb_offset[CC_id][slice_idx];
Niccolò Iardella's avatar
Niccolò Iardella committed
1126
  }
1127
  //LOG_D(MAC, "exiting ulsch preprocesor\n");
1128

1129
  hi_dci0_req->sfn_sf = (frameP << 4) + subframeP;
1130

1131
  // loop over all active UEs
1132 1133 1134
  for (UE_id = UE_list->head_ul; UE_id >= 0;
       UE_id = UE_list->next_ul[UE_id]) {

1135
    if (!ue_ul_slice_membership(module_idP, UE_id, slice_idx))
1136
        continue;
1137

sharma's avatar
sharma committed
1138 1139
    if (UE_list->UE_template[UE_PCCID(module_idP,UE_id)][UE_id].rach_resource_type > 0) continue;

1140
    // don't schedule if Msg4 is not received yet
1141
    if (UE_list->UE_template[UE_PCCID(module_idP, UE_id)][UE_id].
1142 1143 1144 1145 1146
        configured == FALSE) {
        LOG_D(MAC,
              "[eNB %d] frame %d subfarme %d, UE %d: not configured, skipping UE scheduling \n",
              module_idP, frameP, subframeP, UE_id);
        continue;
1147
    }
1148

1149
    rnti = UE_RNTI(module_idP, UE_id);
1150

1151 1152 1153
    if (rnti == NOT_A_RNTI) {
      LOG_W(MAC, "[eNB %d] frame %d subfarme %d, UE %d: no RNTI \n",
	    module_idP, frameP, subframeP, UE_id);
1154 1155
      continue;
    }
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1156

1157
    drop_ue = 0;
1158
    /* let's drop the UE if get_eNB_UE_stats returns NULL when calling it with any of the UE's active UL CCs */
Cedric Roux's avatar
Cedric Roux committed
1159
    /* TODO: refine?
1160

1161 1162
       for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
       CC_id = UE_list->ordered_ULCCids[n][UE_id];
Cedric Roux's avatar
Cedric Roux committed
1163

1164 1165 1166 1167 1168 1169
       if (mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti) == NULL) {
       LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: no PHY context\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id);
       drop_ue = 1;
       break;
       }
       } */
1170
    if (drop_ue == 1) {
1171 1172
      /* we can't come here, ulsch_scheduler_pre_processor won't put in the list a UE with no PHY context */
      abort();
1173 1174 1175 1176 1177 1178 1179 1180
      /* TODO: this is a hack. Sometimes the UE has no PHY context but
       * is still present in the MAC with 'ul_failure_timer' = 0 and
       * 'ul_out_of_sync' = 0. It seems wrong and the UE stays there forever. Let's
       * start an UL out of sync procedure in this case.
       * The root cause of this problem has to be found and corrected.
       * In the meantime, this hack...
       */
      if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0 &&
1181 1182 1183 1184 1185 1186 1187 1188 1189
	  UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0) {
	LOG_W(MAC,
	      "[eNB %d] frame %d subframe %d, UE %d/%x CC %d: UE in weird state, let's put it 'out of sync'\n",
	      module_idP, frameP, subframeP, UE_id, rnti, CC_id);
	// inform RRC of failure and clear timer
	mac_eNB_rrc_ul_failure(module_idP, CC_id, frameP,
			       subframeP, rnti);
	UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
	UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 1;
1190
      }
1191
      continue;
1192
    }
1193
    // loop over all active UL CC_ids for this UE
1194
    for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) {
1195
      // This is the actual CC_id in the list
1196 1197
      CC_id = UE_list->ordered_ULCCids[n][UE_id];
      N_RB_UL = to_prb(cc[CC_id].ul_Bandwidth);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1198

1199
      /*
1200 1201 1202
	aggregation=get_aggregation(get_bw_index(module_idP,CC_id),
	eNB_UE_stats->dl_cqi,
	format0);
1203
      */
1204

1205 1206 1207 1208 1209 1210
      if (CCE_allocation_infeasible
	  (module_idP, CC_id, 1, subframeP, aggregation, rnti)) {
	LOG_W(MAC,
	      "[eNB %d] frame %d subframe %d, UE %d/%x CC %d: not enough nCCE\n",
	      module_idP, frameP, subframeP, UE_id, rnti, CC_id);
	continue;	// break;
Cedric Roux's avatar
Cedric Roux committed
1211
      }
Raymond Knopp's avatar
Raymond Knopp committed
1212

Cedric Roux's avatar
Cedric Roux committed
1213
      /* be sure that there are some free RBs */
Niccolò Iardella's avatar
Niccolò Iardella committed
1214
      if (first_rb_slice[CC_id] >= N_RB_UL - 1) {
1215 1216 1217 1218
	LOG_W(MAC,
	      "[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n",
	      module_idP, frameP, subframeP, UE_id, rnti, CC_id);
	continue;
1219
      }
1220 1221
      //      if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel

1222
      UE_template = &UE_list->UE_template[CC_id][UE_id];
1223
      UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
1224 1225 1226 1227 1228 1229 1230 1231 1232
      harq_pid = subframe2harqpid(&cc[CC_id], sched_frame, sched_subframeP);
      round = UE_sched_ctrl->round_UL[CC_id][harq_pid];
      AssertFatal(round < 8, "round %d > 7 for UE %d/%x\n", round,
		  UE_id, rnti);
      LOG_D(MAC,
	    "[eNB %d] frame %d subframe %d (sched_frame %d, sched_subframe %d), Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n",
	    module_idP, frameP, subframeP, sched_frame, sched_subframeP, harq_pid, UE_id, rnti,
	    CC_id, aggregation, N_RB_UL);

1233
      RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP * 10) + subframeP] = UE_template->estimated_ul_buffer;
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO,RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP *
							   10) +
							  subframeP]);
      if (UE_is_to_be_scheduled(module_idP, CC_id, UE_id) > 0 || round > 0)	// || ((frameP%10)==0))
	// if there is information on bsr of DCCH, DTCH or if there is UL_SR, or if there is a packet to retransmit, or we want to schedule a periodic feedback every 10 frames
	{
	  LOG_D(MAC,
		"[eNB %d][PUSCH %d] Frame %d subframe %d Scheduling UE %d/%x in round %d(SR %d,UL_inactivity timer %d,UL_failure timer %d,cqi_req_timer %d)\n",
		module_idP, harq_pid, frameP, subframeP, UE_id, rnti,
		round, UE_template->ul_SR,
		UE_sched_ctrl->ul_inactivity_timer,
		UE_sched_ctrl->ul_failure_timer,
		UE_sched_ctrl->cqi_req_timer);
	  // reset the scheduling request
	  UE_template->ul_SR = 0;
	  status = mac_eNB_get_rrc_status(module_idP, rnti);
1250 1251 1252 1253 1254
	  cqi_req = 0;

	  if (status >= RRC_CONNECTED && UE_sched_ctrl->cqi_req_timer > 30) { 
	    if (UE_sched_ctrl->cqi_received == 0) {
	      if (nfapi_mode) {
1255
	    	  cqi_req = 0;
1256
	      } else {
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
	    	  cqi_req = 1;
		   // To be safe , do not ask CQI in special Subframes:36.213/7.2.3 CQI definition
			if (cc[CC_id].tdd_Config) {
			  switch (cc[CC_id].tdd_Config->subframeAssignment) {
				  case 1:
					if( subframeP == 1 || subframeP == 6 ) cqi_req=0;
					break;
				  case 3:
					if( subframeP == 1 ) cqi_req=0;
					break;
				  default:
					LOG_E(MAC," TDD config not supported\n");
					break;
			  }
			}
			if(cqi_req == 1) UE_sched_ctrl->cqi_req_flag |= 1 << sched_subframeP;
1273
	      }
1274
	    }
1275 1276 1277 1278
	    else if (UE_sched_ctrl->cqi_received == 1) {
	      UE_sched_ctrl->cqi_req_flag = 0;
	      UE_sched_ctrl->cqi_received = 0;
	      UE_sched_ctrl->cqi_req_timer = 0;
1279
	    }
1280
	  }
1281 1282 1283 1284 1285

	  //power control
	  //compute the expected ULSCH RX power (for the stats)

	  // this is the normalized RX power and this should be constant (regardless of mcs
1286
	  //is not in dBm, unit from nfapi, converting to dBm: ToDo: Noise power hard coded to 30
1287 1288
	  normalized_rx_power = (5*UE_sched_ctrl->pusch_snr[CC_id]-640)/10+30;
	  target_rx_power= mac->puSch10xSnr/10 + 30;
1289
	  //printf("\n mac->puSch10xSnr = %d,  normalized_rx_power = %d, target_rx_power = %d \n",mac->puSch10xSnr,normalized_rx_power,target_rx_power);
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299
	  // this assumes accumulated tpc
	  // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
	  int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame * 10 + UE_template->pusch_tpc_tx_subframe;
	  if (((framex10psubframe + 10) <= (frameP * 10 + subframeP)) ||	//normal case
	      ((framex10psubframe > (frameP * 10 + subframeP)) && (((10240 - framex10psubframe + frameP * 10 + subframeP) >= 10))))	//frame wrap-around
	    {
	      UE_template->pusch_tpc_tx_frame = frameP;
	      UE_template->pusch_tpc_tx_subframe = subframeP;
	      if (normalized_rx_power > (target_rx_power + 4)) {
		tpc = 0;	//-1
1300
		UE_sched_ctrl->tpc_accumulated[CC_id]--;
1301 1302
	      } else if (normalized_rx_power < (target_rx_power - 4)) {
		tpc = 2;	//+1
1303
		UE_sched_ctrl->tpc_accumulated[CC_id]++;
1304 1305 1306 1307 1308 1309 1310 1311
	      } else {
		tpc = 1;	//0
	      }
	    } else {
	    tpc = 1;	//0
	  }
	  //tpc = 1;
	  if (tpc != 1) {
1312
	    LOG_D(MAC,
1313 1314
		  "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
		  module_idP, frameP, subframeP, harq_pid, tpc,
1315
		  UE_sched_ctrl->tpc_accumulated[CC_id], normalized_rx_power,
1316 1317 1318 1319 1320 1321 1322
		  target_rx_power);
	  }
	  // new transmission
	  if (round == 0) {

	    ndi = 1 - UE_template->oldNDI_UL[harq_pid];
	    UE_template->oldNDI_UL[harq_pid] = ndi;
1323
	    UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power = normalized_rx_power;
1324
	    UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power = target_rx_power;
1325
		UE_template->mcs_UL[harq_pid] = cmin(UE_template->pre_assigned_mcs_ul, sli->ul[slice_idx].maxmcs);
1326 1327
		UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1= UE_template->mcs_UL[harq_pid];
		//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
1328
	    if (UE_template->pre_allocated_rb_table_index_ul >= 0) {
1329
	      rb_table_index = UE_template->pre_allocated_rb_table_index_ul;
1330 1331 1332
	    } else {
	      UE_template->mcs_UL[harq_pid] = 10;	//cmin (10, openair_daq_vars.target_ue_ul_mcs);
	      rb_table_index = 5;	// for PHR
1333 1334
	    }

1335 1336 1337 1338
	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template->mcs_UL[harq_pid];
	    //            buffer_occupancy = UE_template->ul_total_buffer;


Robert Schmidt's avatar
Robert Schmidt committed
1339
	    while (((rb_table[rb_table_index] > (N_RB_UL - first_rb_slice[CC_id]))
1340 1341
                    || (rb_table[rb_table_index] > 45))
                    && (rb_table_index > 0)) {
1342
	      rb_table_index--;
1343
	    }
1344 1345 1346 1347 1348

	    UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],
						       rb_table[rb_table_index]);
	    UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index];
	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template->TBS_UL[harq_pid];
1349
            UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_TBS += UE_template->TBS_UL[harq_pid];
1350 1351 1352 1353 1354 1355
	    //            buffer_occupancy -= TBS;

	    T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP),
	      T_INT(CC_id), T_INT(rnti), T_INT(frameP),
	      T_INT(subframeP), T_INT(harq_pid),
	      T_INT(UE_template->mcs_UL[harq_pid]),
Niccolò Iardella's avatar
Niccolò Iardella committed
1356
	      T_INT(first_rb_slice[CC_id]),
1357 1358 1359 1360 1361 1362 1363 1364 1365
	      T_INT(rb_table[rb_table_index]),
	      T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi));

	    if (mac_eNB_get_rrc_status(module_idP, rnti) < RRC_CONNECTED)
	      LOG_D(MAC,
		    "[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n",
		    module_idP, harq_pid, rnti, CC_id, frameP,
		    subframeP, UE_id,
		    UE_template->mcs_UL[harq_pid],
Niccolò Iardella's avatar
Niccolò Iardella committed
1366
                first_rb_slice[CC_id], rb_table[rb_table_index],
1367 1368 1369 1370 1371 1372
		    rb_table_index,
		    UE_template->TBS_UL[harq_pid], harq_pid);

	    // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
	    //store for possible retransmission
	    UE_template->nb_rb_ul[harq_pid] = rb_table[rb_table_index];
Niccolò Iardella's avatar
Niccolò Iardella committed
1373
	    UE_template->first_rb_ul[harq_pid] = first_rb_slice[CC_id];
1374 1375 1376 1377 1378 1379

	    UE_sched_ctrl->ul_scheduled |= (1 << harq_pid);
	    if (UE_id == UE_list->head)
	      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,
						      UE_sched_ctrl->ul_scheduled);

1380
	    // adjust scheduled UL bytes by TBS, wait for UL sdus to do final update
1381
	    LOG_D(MAC,
1382
		  "[eNB %d] CC_id %d UE %d/%x : adjusting scheduled_ul_bytes, old %d, TBS %d\n",
1383
		  module_idP, CC_id, UE_id, rnti,
1384
		  UE_template->scheduled_ul_bytes,
1385
		  UE_template->TBS_UL[harq_pid]);
1386 1387 1388 1389 1390

            UE_template->scheduled_ul_bytes += UE_template->TBS_UL[harq_pid];

            LOG_D(MAC, "scheduled_ul_bytes, new %d\n", UE_template->scheduled_ul_bytes);

1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404
	    // Cyclic shift for DM RS
	    cshift = 0;	// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1)
	    // save it for a potential retransmission
	    UE_template->cshift[harq_pid] = cshift;

	    hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi];
	    memset((void *) hi_dci0_pdu, 0,sizeof(nfapi_hi_dci0_request_pdu_t));
	    hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE;
	    hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu);
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG;
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0;
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti;
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000;
Niccolò Iardella's avatar
Niccolò Iardella committed
1405
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb_slice[CC_id];
1406 1407 1408 1409 1410 1411 1412 1413
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index];
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template->mcs_UL[harq_pid];
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift;
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0;
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = ndi;
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc;
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req;
	    hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template->DAI_ul[sched_subframeP];
1414
            hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid;
1415 1416

	    hi_dci0_req_body->number_of_dci++;
1417
	    hi_dci0_req_body->sfnsf = sfnsf_add_subframe(sched_frame, sched_subframeP, 0); //(frameP, subframeP, 4);
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
	    hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG;

	    hi_dci0_req->sfn_sf = frameP<<4|subframeP; // sfnsf_add_subframe(sched_frame, sched_subframeP, 0); // sunday!
	    hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST;


	    LOG_D(MAC,
		  "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n",
		  harq_pid, frameP, subframeP, UE_id, rnti,
		  sched_frame, sched_subframeP);

1429 1430 1431
            ul_req_index = 0;
            dlsch_flag = 0;
            for(ul_req_index = 0;ul_req_index < ul_req_tmp_body->number_of_pdus;ul_req_index++){
1432 1433
              if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE &&
                 ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti){
1434 1435 1436
                dlsch_flag = 1;
                LOG_D(MAC,"Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n",frameP,subframeP,rnti,ul_req_index);
                break;
Cedric Roux's avatar
Cedric Roux committed
1437 1438 1439
              }
            }

1440
	    // Add UL_config PDUs
1441
	    fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], cqi_req, cc, UE_template->physicalConfigDedicated, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, first_rb_slice[CC_id], // resource_block_start
1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
						 rb_table[rb_table_index],	// number_of_resource_blocks
						 UE_template->mcs_UL[harq_pid], cshift,	// cyclic_shift_2_for_drms
						 0,	// frequency_hopping_enabled_flag
						 0,	// frequency_hopping_bits
						 ndi,	// new_data_indication
						 0,	// redundancy_version
						 harq_pid,	// harq_process_number
						 0,	// ul_tx_mode
						 0,	// current_tx_nb
						 0,	// n_srs
						 get_TBS_UL
						 (UE_template->
						  mcs_UL[harq_pid],
						  rb_table
						  [rb_table_index]));
1457
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1458
	    if (UE_template->rach_resource_type > 0) {	// This is a BL/CE UE allocation
1459
	      fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], UE_template->rach_resource_type > 2 ? 2 : 1, 1,	//total_number_of_repetitions
1460 1461 1462 1463 1464
						   1,	//repetition_number
						   (frameP *
						    10) +
						   subframeP);
	    }
1465
#endif
1466
            if(dlsch_flag == 1){
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
              if(cqi_req == 1){
                 ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE;
                 ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information;
                 ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag=NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG;
                 ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0;    // last symbol not punctured
                 ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = rb_table[rb_table_index];

              }else{
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE;
                ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information;
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG;
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0;  // last symbol not punctured
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = rb_table[rb_table_index];
              }
              fill_nfapi_ulsch_harq_information(module_idP, CC_id,rnti, ulsch_harq_information,subframeP);
1482
            }else{
1483
              ul_req_tmp_body->number_of_pdus++;
1484
            }
1485
            //********************************* [khalid] here will make the modification for emtc
Cedric Roux's avatar
Cedric Roux committed
1486

1487

1488 1489 1490 1491 1492 1493 1494
	    ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST;
	    ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
	    mac->ul_handle++;

	    uint16_t ul_sched_frame = sched_frame;
	    uint16_t ul_sched_subframeP = sched_subframeP;

1495
	    //add_subframe(&ul_sched_frame, &ul_sched_subframeP, 2);
1496 1497 1498 1499 1500 1501
	    ul_req_tmp->sfn_sf = ul_sched_frame<<4|ul_sched_subframeP;

	    add_ue_ulsch_info(module_idP,
			      CC_id, UE_id, subframeP,
			      S_UL_SCHEDULED);

1502
	    LOG_D(MAC, "[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP, CC_id, frameP, subframeP, UE_id);
1503 1504 1505
	    LOG_D(MAC,"[PUSCH %d] SFN/SF:%04d%d UL_CFG:SFN/SF:%04d%d CQI:%d for UE %d/%x\n", harq_pid,frameP,subframeP,ul_sched_frame,ul_sched_subframeP,cqi_req,UE_id,rnti);

	    // increment first rb for next UE allocation
Niccolò Iardella's avatar
Niccolò Iardella committed
1506
        first_rb_slice[CC_id] += rb_table[rb_table_index];
1507 1508 1509 1510 1511
	  } else {	// round > 0 => retransmission
	    T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION,
	      T_INT(module_idP), T_INT(CC_id), T_INT(rnti),
	      T_INT(frameP), T_INT(subframeP), T_INT(harq_pid),
	      T_INT(UE_template->mcs_UL[harq_pid]),
Niccolò Iardella's avatar
Niccolò Iardella committed
1512
	      T_INT(first_rb_slice[CC_id]),
1513 1514 1515 1516 1517 1518 1519
	      T_INT(rb_table[rb_table_index]), T_INT(round));

	    // Add UL_config PDUs
	    LOG_D(MAC,
		  "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n",
		  harq_pid, frameP, subframeP, UE_id, rnti,
		  sched_frame, sched_subframeP);
1520 1521 1522
            ul_req_index = 0;
            dlsch_flag = 0;
            for(ul_req_index = 0;ul_req_index < ul_req_tmp_body->number_of_pdus;ul_req_index++){
1523 1524
              if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE &&
                 ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti){
1525 1526 1527 1528
                dlsch_flag = 1;
                LOG_D(MAC,"Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n",frameP,subframeP,rnti,ul_req_index);
                break;
              }
1529
            }
1530
	    fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], cqi_req, cc, UE_template->physicalConfigDedicated, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, UE_template->first_rb_ul[harq_pid],	// resource_block_start
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
						 UE_template->nb_rb_ul[harq_pid],	// number_of_resource_blocks
						 UE_template->mcs_UL[harq_pid], cshift,	// cyclic_shift_2_for_drms
						 0,	// frequency_hopping_enabled_flag
						 0,	// frequency_hopping_bits
						 UE_template->oldNDI_UL[harq_pid],	// new_data_indication
						 rvidx_tab[round & 3],	// redundancy_version
						 harq_pid,	// harq_process_number
						 0,	// ul_tx_mode
						 0,	// current_tx_nb
						 0,	// n_srs
						 UE_template->
						 TBS_UL[harq_pid]);
1543
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1544
	    if (UE_template->rach_resource_type > 0) {	// This is a BL/CE UE allocation
1545
	      fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], UE_template->rach_resource_type > 2 ? 2 : 1, 1,	//total_number_of_repetitions
1546 1547 1548 1549 1550
						   1,	//repetition_number
						   (frameP *
						    10) +
						   subframeP);
	    }
1551
#endif
1552
            if(dlsch_flag == 1){
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567
              if(cqi_req == 1){
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE;
                ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information;
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag=NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG;
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0;    // last symbol not punctured
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = UE_template->nb_rb_ul[harq_pid];

              }else{
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE;
                ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information;
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG;
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0;  // last symbol not punctured
                ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = UE_template->nb_rb_ul[harq_pid];
              }
              fill_nfapi_ulsch_harq_information(module_idP, CC_id,rnti, ulsch_harq_information,subframeP);
1568
            }else{
1569
              ul_req_tmp_body->number_of_pdus++;
1570
            }
khalidhamdy's avatar
khalidhamdy committed
1571 1572


1573
	    mac->ul_handle++;
1574

1575
	    ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
1576

1577 1578
	    ul_req_tmp->sfn_sf = sched_frame<<4|sched_subframeP;
	    ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST;
1579

1580 1581 1582 1583
	    LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d cqi_req %d\n",
		  harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP,cqi_req);
	  }		/*
			  else if (round > 0) { //we schedule a retransmission
1584

1585
			  ndi = UE_template->oldNDI_UL[harq_pid];
1586

1587 1588 1589 1590
			  if ((round&3)==0) {
			  mcs = openair_daq_vars.target_ue_ul_mcs;
			  } else {
			  mcs = rvidx_tab[round&3] + 28; //not correct for round==4!
1591

1592
			  }
1593

1594 1595 1596 1597
			  LOG_I(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE retransmission (mcs %d, first rb %d, nb_rb %d, harq_pid %d, round %d)\n",
			  module_idP,UE_id,rnti,CC_id,frameP,subframeP,mcs,
			  first_rb[CC_id],UE_template->nb_rb_ul[harq_pid],
			  harq_pid, round);
1598

1599 1600 1601 1602
			  rballoc = mac_xface->computeRIV(frame_parms->N_RB_UL,
			  first_rb[CC_id],
			  UE_template->nb_rb_ul[harq_pid]);
			  first_rb[CC_id]+=UE_template->nb_rb_ul[harq_pid];  // increment for next UE allocation
1603

1604 1605 1606 1607 1608 1609 1610
			  UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission_rx+=1;
			  UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx=UE_template->nb_rb_ul[harq_pid];
			  UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=UE_template->nb_rb_ul[harq_pid];
			  UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=mcs;
			  UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs;
			  }
			*/
Cedric Roux's avatar
Cedric Roux committed
1611

1612 1613 1614
	}			// UE_is_to_be_scheduled
    }			// loop over UE_id
  }				// loop of CC_id
1615
}
sharma's avatar
sharma committed
1616

1617
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
sharma's avatar
sharma committed
1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
void schedule_ulsch_rnti_emtc(module_id_t   module_idP,
			     frame_t       frameP,
			     sub_frame_t   subframeP,
			     unsigned char sched_subframeP,
			     uint16_t     *emtc_active)
{
  int               UE_id;
  rnti_t            rnti           = -1;
  uint8_t           round          = 0;
  uint8_t           harq_pid       = 0;
  uint8_t           status         = 0;
1629
  uint32_t          cshift,ndi;
sharma's avatar
sharma committed
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641
  int32_t           normalized_rx_power;
  int32_t           target_rx_power=-90;
  int               n;
  int               CC_id = 0;
  int               N_RB_UL;
  eNB_MAC_INST      *eNB = RC.mac[module_idP];
  COMMON_channels_t *cc  = eNB->common_channels;
  UE_list_t         *UE_list=&eNB->UE_list;
  UE_TEMPLATE       *UE_template;
  UE_sched_ctrl     *UE_sched_ctrl;
  int               sched_frame=frameP;
  int               rvidx_tab[4] = {0,2,3,1};
1642 1643
  int               tpc=0;
  int               cqi_req=0;
sharma's avatar
sharma committed
1644 1645 1646

  if (sched_subframeP<subframeP) sched_frame++;

1647
  nfapi_hi_dci0_request_body_t   *hi_dci0_req = &eNB->HI_DCI0_req[CC_id][subframeP].hi_dci0_request_body;
sharma's avatar
sharma committed
1648 1649 1650 1651 1652
  nfapi_hi_dci0_request_pdu_t    *hi_dci0_pdu;

  nfapi_ul_config_request_body_t *ul_req_tmp       = &eNB->UL_req_tmp[CC_id][sched_subframeP].ul_config_request_body;

  // loop over all active UEs
1653 1654
  if ((frameP&1) == 1) return;

sharma's avatar
sharma committed
1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687
  for (UE_id=UE_list->head_ul; UE_id>=0; UE_id=UE_list->next_ul[UE_id]) {

    if (UE_list->UE_template[UE_PCCID(module_idP,UE_id)][UE_id].rach_resource_type == 0) continue;

    // don't schedule if Msg4 is not received yet
    if (UE_list->UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured==FALSE) {
      LOG_D(MAC,"[eNB %d] frame %d subfarme %d, UE %d: not configured, skipping UE scheduling \n",
            module_idP,frameP,subframeP,UE_id);
      continue;
    }

    rnti = UE_RNTI(module_idP,UE_id);

    if (rnti==NOT_A_RNTI) {
      LOG_W(MAC,"[eNB %d] frame %d subfarme %d, UE %d: no RNTI \n", module_idP,frameP,subframeP,UE_id);
      continue;
    }

    // loop over all active UL CC_ids for this UE
    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
      // This is the actual CC_id in the list
      CC_id        = UE_list->ordered_ULCCids[n][UE_id];
      N_RB_UL      = to_prb(cc[CC_id].ul_Bandwidth);


      UE_template   = &UE_list->UE_template[CC_id][UE_id];
      UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
      harq_pid      = 0;
      round         = UE_sched_ctrl->round_UL[CC_id][harq_pid];
      AssertFatal(round<8,"round %d > 7 for UE %d/%x\n",round,UE_id,rnti);
      LOG_D(MAC,"[eNB %d] frame %d subframe %d,Checking PUSCH %d for BL/CE UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n",
            module_idP,frameP,subframeP,harq_pid,UE_id,rnti,CC_id, 24,N_RB_UL);

1688
      RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP] = UE_template->estimated_ul_buffer;
sharma's avatar
sharma committed
1689
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO,RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP]);
1690
      if ((UE_template->ul_SR >0  || round > 0 || status < RRC_CONNECTED)&&(subframeP==5)) 
sharma's avatar
sharma committed
1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703
        // if there is information on bsr of DCCH, DTCH or if there is UL_SR, or if there is a packet to retransmit, or we want to schedule a periodic feedback every 10 frames
        {
          LOG_I(MAC,"[eNB %d][PUSCH %d] Frame %d subframe %d Scheduling UE %d/%x in round %d(SR %d,UL_inactivity timer %d,UL_failure timer %d,cqi_req_timer %d)\n",
                module_idP,harq_pid,frameP,subframeP,UE_id,rnti,round,UE_template->ul_SR,
                UE_sched_ctrl->ul_inactivity_timer,

                UE_sched_ctrl->ul_failure_timer,

                UE_sched_ctrl->cqi_req_timer);
          // reset the scheduling request
	  emtc_active[CC_id]=1;
          UE_template->ul_SR = 0;
          status = mac_eNB_get_rrc_status(module_idP,rnti);
1704 1705

	  /*
sharma's avatar
sharma committed
1706 1707
          if (status < RRC_CONNECTED)
            cqi_req = 0;
1708
          else if (UE_sched_ctrl->cqi_req_timer>300) {
sharma's avatar
sharma committed
1709 1710
            cqi_req = 1;
            UE_sched_ctrl->cqi_req_timer=0;
1711

sharma's avatar
sharma committed
1712 1713 1714
          }
          else
            cqi_req = 0;
1715 1716
	  */
	  cqi_req = 0;
sharma's avatar
sharma committed
1717

1718
 
sharma's avatar
sharma committed
1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735
          //power control
          //compute the expected ULSCH RX power (for the stats)

          // this is the normalized RX power and this should be constant (regardless of mcs
          normalized_rx_power = UE_sched_ctrl->pusch_snr[CC_id];
          target_rx_power = 178;

          // this assumes accumulated tpc
          // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
          int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame*10+UE_template->pusch_tpc_tx_subframe;
          if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case
              ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around
            {
              UE_template->pusch_tpc_tx_frame=frameP;
              UE_template->pusch_tpc_tx_subframe=subframeP;
              if (normalized_rx_power>(target_rx_power+4)) {
                tpc = 0; //-1
1736
                UE_sched_ctrl->tpc_accumulated[CC_id]--;
sharma's avatar
sharma committed
1737 1738
              } else if (normalized_rx_power<(target_rx_power-4)) {
                tpc = 2; //+1
1739
                UE_sched_ctrl->tpc_accumulated[CC_id]++;
sharma's avatar
sharma committed
1740 1741 1742 1743 1744 1745 1746
              } else {
                tpc = 1; //0
              }
            } else {
            tpc = 1; //0
          }
          //tpc = 1;
1747 1748


sharma's avatar
sharma committed
1749 1750 1751
          if (tpc!=1) {
            LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
                  module_idP,frameP,subframeP,harq_pid,tpc,
1752
                  UE_sched_ctrl->tpc_accumulated[CC_id],normalized_rx_power,target_rx_power);
sharma's avatar
sharma committed
1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782
          }

          // new transmission
          if (round==0) {

            ndi = 1-UE_template->oldNDI_UL[harq_pid];
            UE_template->oldNDI_UL[harq_pid]=ndi;
            UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
            UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
            UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=4;
            UE_template->mcs_UL[harq_pid] = 4;


            UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=UE_template->mcs_UL[harq_pid];
            //            buffer_occupancy = UE_template->ul_total_buffer;



            UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],6);
            UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=6;
            UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid];
            //            buffer_occupancy -= TBS;

            T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
              T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(0), T_INT(6),
              T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi));

            // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
            //store for possible retransmission
            UE_template->nb_rb_ul[harq_pid]    = 6;
1783

sharma's avatar
sharma committed
1784 1785 1786 1787 1788 1789

            UE_sched_ctrl->ul_scheduled |= (1<<harq_pid);
            if (UE_id == UE_list->head)
              VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,UE_sched_ctrl->ul_scheduled);

            // adjust total UL buffer status by TBS, wait for UL sdus to do final update
1790 1791 1792 1793 1794
            UE_template->scheduled_ul_bytes += UE_template->TBS_UL[harq_pid];

            LOG_D(MAC, "scheduled_ul_bytes, new %d\n", UE_template->scheduled_ul_bytes);


sharma's avatar
sharma committed
1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
            // Cyclic shift for DM RS
            cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1)
            // save it for a potential retransmission
            UE_template->cshift[harq_pid] = cshift;

	    AssertFatal (UE_template->physicalConfigDedicated != NULL, 
			 "UE_template->physicalConfigDedicated is null\n");
	    AssertFatal (UE_template->physicalConfigDedicated->ext4 != NULL, 
			 "UE_template->physicalConfigDedicated->ext4 is null\n");
	    AssertFatal (UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11 != NULL, 
			 "UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11 is null\n");
	    AssertFatal (UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.present == EPDCCH_Config_r11__config_r11_PR_setup, 
	      "UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.present != setup\n");
	    AssertFatal (UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11 != NULL,
	      "UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11 = NULL\n");
	    EPDCCH_SetConfig_r11_t *epdcch_setconfig_r11 = UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0];
	    AssertFatal(epdcch_setconfig_r11 != NULL, "epdcch_setconfig_r11 is null\n");
	    AssertFatal(epdcch_setconfig_r11->ext2!=NULL, "epdcch_setconfig_r11->ext2 is null\n");
	    AssertFatal(epdcch_setconfig_r11->ext2->mpdcch_config_r13!=NULL,
			"epdcch_setconfig_r11->ext2->mpdcch_config_r13 is null");
	    AssertFatal(epdcch_setconfig_r11->ext2->mpdcch_config_r13!=NULL,
			"epdcch_setconfig_r11->ext2->mpdcch_config_r13 is null");
	    AssertFatal(epdcch_setconfig_r11->ext2->mpdcch_config_r13->present==EPDCCH_SetConfig_r11__ext2__mpdcch_config_r13_PR_setup, 
			"epdcch_setconfig_r11->ext2->mpdcch_config_r13->present is not setup\n");
	    AssertFatal(epdcch_setconfig_r11->ext2->numberPRB_Pairs_v1310!=NULL,
			"epdcch_setconfig_r11->ext2->numberPRB_Pairs_v1310 is null");
	    AssertFatal(epdcch_setconfig_r11->ext2->numberPRB_Pairs_v1310->present==EPDCCH_SetConfig_r11__ext2__numberPRB_Pairs_v1310_PR_setup, 
			"epdcch_setconfig_r11->ext2->numberPRB_Pairs_v1310->present is not setup\n");
1823 1824 1825 1826 1827 1828

	    LOG_I(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL 6-0A MPDCCH for BL/CE UE %d/%x, ulsch_frame %d, ulsch_subframe %d,UESS MPDCCH Narrowband %d\n",
                  harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP,(int)epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_Narrowband_r13-1);

            UE_template->first_rb_ul[harq_pid] = narrowband_to_first_rb (cc,
									 epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_Narrowband_r13-1);	     
1829
            hi_dci0_pdu                                                         = &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci+hi_dci0_req->number_of_hi];
sharma's avatar
sharma committed
1830 1831 1832 1833 1834 1835
            memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t));

	    hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE;
	    hi_dci0_pdu->pdu_size = (uint8_t) (2 + sizeof (nfapi_dl_config_mpdcch_pdu));
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.dci_format = (UE_template->rach_resource_type > 1) ? 5 : 4;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.ce_mode = (UE_template->rach_resource_type > 1) ? 2 : 1;
1836
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.mpdcch_narrowband = epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_Narrowband_r13-1; 
sharma's avatar
sharma committed
1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853

	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.number_of_prb_pairs = 6;       // checked above that it has to be this
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.resource_block_assignment = 0; // Note: this can be dynamic
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.mpdcch_transmission_type = epdcch_setconfig_r11->transmissionType_r11;  // distibuted

	    AssertFatal(UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.startSymbol_r11!=NULL,
	      "UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.startSymbol_r11 is null\n");

	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.start_symbol = *UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.startSymbol_r11;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.ecce_index = 0;        // Note: this should be dynamic
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.aggreagation_level = 24;        // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.rnti_type = 4; // other
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.rnti = rnti;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.ce_mode = (UE_template->rach_resource_type < 3) ? 1 : 2;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.drms_scrambling_init = epdcch_setconfig_r11->dmrs_ScramblingSequenceInt_r11;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.initial_transmission_sf_io = (frameP * 10) + subframeP;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.transmission_power = 6000;     // 0dB
1854
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.resource_block_start = UE_template->first_rb_ul[harq_pid];
sharma's avatar
sharma committed
1855 1856 1857
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.number_of_resource_blocks = 6;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.mcs = 4;       // adjust according to size of RAR, 208 bits with N1A_PRB=3
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.pusch_repetition_levels = 0;
1858 1859 1860 1861
	    AssertFatal(epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_pdsch_HoppingConfig_r13==
			EPDCCH_SetConfig_r11__ext2__mpdcch_config_r13__setup__mpdcch_pdsch_HoppingConfig_r13_off,
			"epdcch_setconfig_r11->ext2->mpdcch_config_r13->mpdcch_pdsch_HoppingConfig_r13 is not off\n"); 
    	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.frequency_hopping_flag  = 1-epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_pdsch_HoppingConfig_r13;
sharma's avatar
sharma committed
1862
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.redudency_version = 0;
1863
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.new_data_indication = UE_template->oldNDI_UL[harq_pid];
sharma's avatar
sharma committed
1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.harq_process = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.tpc = tpc;       
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.csi_request = cqi_req;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.ul_inex = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.dai_presence_flag = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.dl_assignment_index = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.srs_request = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.dci_subframe_repetition_number = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.tcp_bitmap = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.total_dci_length_include_padding = 29; // hard-coded for 10 MHz
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.number_of_tx_antenna_ports = 1;

1876
            hi_dci0_req->number_of_dci++;
sharma's avatar
sharma committed
1877 1878


1879 1880 1881
            LOG_I(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for BL/CE UE %d/%x, ulsch_frame %d, ulsch_subframe %d, UESS mpdcch narrowband %d\n",
                  harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP,
		  (int)epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_Narrowband_r13-1);
sharma's avatar
sharma committed
1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928


            fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus],
                                                 cqi_req,
                                                 cc,
                                                 UE_template->physicalConfigDedicated,
                                                 get_tmode(module_idP,CC_id,UE_id),
                                                 eNB->ul_handle,
                                                 rnti,
                                                 UE_template->first_rb_ul[harq_pid], // resource_block_start
                                                 UE_template->nb_rb_ul[harq_pid], // number_of_resource_blocks
                                                 UE_template->mcs_UL[harq_pid],
                                                 cshift, // cyclic_shift_2_for_drms
                                                 0, // frequency_hopping_enabled_flag
                                                 0, // frequency_hopping_bits
                                                 UE_template->oldNDI_UL[harq_pid], // new_data_indication
                                                 rvidx_tab[round&3], // redundancy_version
                                                 harq_pid, // harq_process_number
                                                 0, // ul_tx_mode
                                                 0, // current_tx_nb
                                                 0, // n_srs
                                                 UE_template->TBS_UL[harq_pid]
                                                 );
	    fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus],
						 UE_template->rach_resource_type>2 ? 2 : 1,
						 1, //total_number_of_repetitions
						 1, //repetition_number
						 (frameP*10)+subframeP);
	  

            ul_req_tmp->number_of_pdus++;
            eNB->ul_handle++;

            add_ue_ulsch_info(module_idP,
                              CC_id,
                              UE_id,
                              subframeP,
                              S_UL_SCHEDULED);

            LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP,CC_id,frameP,subframeP,UE_id);

          }
          else { // round > 0 => retransmission
            T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
              T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(0), T_INT(6),
              T_INT(round));

1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957
	    AssertFatal (UE_template->physicalConfigDedicated != NULL, 
			 "UE_template->physicalConfigDedicated is null\n");
	    AssertFatal (UE_template->physicalConfigDedicated->ext4 != NULL, 
			 "UE_template->physicalConfigDedicated->ext4 is null\n");
	    AssertFatal (UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11 != NULL, 
			 "UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11 is null\n");
	    AssertFatal (UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.present == EPDCCH_Config_r11__config_r11_PR_setup, 
	      "UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.present != setup\n");
	    AssertFatal (UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11 != NULL,
	      "UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11 = NULL\n");
	    EPDCCH_SetConfig_r11_t *epdcch_setconfig_r11 = UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0];
	    AssertFatal(epdcch_setconfig_r11 != NULL, "epdcch_setconfig_r11 is null\n");
	    AssertFatal(epdcch_setconfig_r11->ext2!=NULL, "epdcch_setconfig_r11->ext2 is null\n");
	    AssertFatal(epdcch_setconfig_r11->ext2->mpdcch_config_r13!=NULL,
			"epdcch_setconfig_r11->ext2->mpdcch_config_r13 is null");
	    AssertFatal(epdcch_setconfig_r11->ext2->mpdcch_config_r13!=NULL,
			"epdcch_setconfig_r11->ext2->mpdcch_config_r13 is null");
	    AssertFatal(epdcch_setconfig_r11->ext2->mpdcch_config_r13->present==EPDCCH_SetConfig_r11__ext2__mpdcch_config_r13_PR_setup, 
			"epdcch_setconfig_r11->ext2->mpdcch_config_r13->present is not setup\n");
	    AssertFatal(epdcch_setconfig_r11->ext2->numberPRB_Pairs_v1310!=NULL,
			"epdcch_setconfig_r11->ext2->numberPRB_Pairs_v1310 is null");
	    AssertFatal(epdcch_setconfig_r11->ext2->numberPRB_Pairs_v1310->present==EPDCCH_SetConfig_r11__ext2__numberPRB_Pairs_v1310_PR_setup, 
			"epdcch_setconfig_r11->ext2->numberPRB_Pairs_v1310->present is not setup\n");

	    LOG_I(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL 6-0A MPDCCH for BL/CE UE %d/%x, ulsch_frame %d, ulsch_subframe %d,UESS MPDCCH Narrowband %d\n",
                  harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP,(int)epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_Narrowband_r13-1);

            UE_template->first_rb_ul[harq_pid] = narrowband_to_first_rb (cc,
									 epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_Narrowband_r13-1);	     
1958
            hi_dci0_pdu                                                         = &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci+hi_dci0_req->number_of_hi];
1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993
            memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t));

	    hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE;
	    hi_dci0_pdu->pdu_size = (uint8_t) (2 + sizeof (nfapi_dl_config_mpdcch_pdu));
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.dci_format = (UE_template->rach_resource_type > 1) ? 5 : 4;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.ce_mode = (UE_template->rach_resource_type > 1) ? 2 : 1;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.mpdcch_narrowband = epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_Narrowband_r13-1; 

	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.number_of_prb_pairs = 6;       // checked above that it has to be this
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.resource_block_assignment = 0; // Note: this can be dynamic
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.mpdcch_transmission_type = epdcch_setconfig_r11->transmissionType_r11;  // distibuted

	    AssertFatal(UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.startSymbol_r11!=NULL,
	      "UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.startSymbol_r11 is null\n");

	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.start_symbol = *UE_template->physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.startSymbol_r11;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.ecce_index = 0;        // Note: this should be dynamic
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.aggreagation_level = 24;        // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.rnti_type = 4; // other
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.rnti = rnti;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.ce_mode = (UE_template->rach_resource_type < 3) ? 1 : 2;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.drms_scrambling_init = epdcch_setconfig_r11->dmrs_ScramblingSequenceInt_r11;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.initial_transmission_sf_io = (frameP * 10) + subframeP;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.transmission_power = 6000;     // 0dB
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.resource_block_start = UE_template->first_rb_ul[harq_pid];
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.number_of_resource_blocks = 6;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.mcs = 4;       // adjust according to size of RAR, 208 bits with N1A_PRB=3
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.pusch_repetition_levels = 0;
	    AssertFatal(epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_pdsch_HoppingConfig_r13==
			EPDCCH_SetConfig_r11__ext2__mpdcch_config_r13__setup__mpdcch_pdsch_HoppingConfig_r13_off,
			"epdcch_setconfig_r11->ext2->mpdcch_config_r13->mpdcch_pdsch_HoppingConfig_r13 is not off\n"); 
    	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.frequency_hopping_flag  = 1-epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_pdsch_HoppingConfig_r13;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.redudency_version = rvidx_tab[round&3];
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.new_data_indication = UE_template->oldNDI_UL[harq_pid];
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.harq_process = harq_pid;
1994 1995
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.tpc = tpc;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.csi_request = cqi_req;
1996 1997 1998 1999 2000 2001 2002 2003 2004
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.ul_inex = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.dai_presence_flag = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.dl_assignment_index = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.srs_request = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.dci_subframe_repetition_number = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.tcp_bitmap = 0;
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.total_dci_length_include_padding = 29; // hard-coded for 10 MHz
	    hi_dci0_pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.number_of_tx_antenna_ports = 1;

2005
	    hi_dci0_req->number_of_dci++;
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026
            fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus],
                                                 cqi_req,
                                                 cc,
                                                 UE_template->physicalConfigDedicated,
                                                 get_tmode(module_idP,CC_id,UE_id),
                                                 eNB->ul_handle,
                                                 rnti,
                                                 UE_template->first_rb_ul[harq_pid], // resource_block_start
                                                 UE_template->nb_rb_ul[harq_pid], // number_of_resource_blocks
                                                 UE_template->mcs_UL[harq_pid],
                                                 cshift, // cyclic_shift_2_for_drms
                                                 0, // frequency_hopping_enabled_flag
                                                 0, // frequency_hopping_bits
                                                 UE_template->oldNDI_UL[harq_pid], // new_data_indication
                                                 rvidx_tab[round&3], // redundancy_version
                                                 harq_pid, // harq_process_number
                                                 0, // ul_tx_mode
                                                 0, // current_tx_nb
                                                 0, // n_srs
                                                 UE_template->TBS_UL[harq_pid]
                                                 );
sharma's avatar
sharma committed
2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041
	    fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus],
						 UE_template->rach_resource_type>2 ? 2 : 1,
						 1, //total_number_of_repetitions
						 1, //repetition_number
						 (frameP*10)+subframeP);
            
	    ul_req_tmp->number_of_pdus++;
	    eNB->ul_handle++;

          }
        } // UE_is_to_be_scheduled
    } // ULCCs
  } // loop over UE_id
}
#endif