/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

/*! \file PHY/LTE_TRANSPORT/dci_tools.c
 * \brief PHY Support routines (eNB/UE) for filling PDSCH/PUSCH/DLSCH/ULSCH data structures based on DCI PDUs generated by eNB MAC scheduler.
 * \author R. Knopp
 * \date 2011
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr
 * \note
 * \warning
 */

#include "PHY/defs_eNB.h"
#include "PHY/phy_extern.h"
#include "SCHED/sched_eNB.h"
#ifdef DEBUG_DCI_TOOLS
  #include "PHY/phy_vars.h"
#endif
#include "assertions.h"
#include "nfapi_interface.h"

//#define DEBUG_HARQ




#include "LAYER2/MAC/mac.h"

//#define DEBUG_DCI
#include "dci_tools_common_extern.h"
#include "transport_proto.h"

//#undef LOG_D
//#define LOG_D(A,B...) printf(B)

int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type) {
  uint16_t i;
  int16_t first_free_index=-1;
  AssertFatal(eNB!=NULL,"eNB is null\n");

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    AssertFatal(eNB->dlsch[i]!=NULL,"eNB->dlsch[%d] is null\n",i);
    AssertFatal(eNB->dlsch[i]!=NULL,"eNB->dlsch[%d][0] is null\n",i);
    LOG_D(PHY,"searching for rnti %x : UE index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,eNB->dlsch[i][0]->harq_mask,eNB->dlsch[i][0]->rnti,first_free_index);

    if ((eNB->dlsch[i][0]->harq_mask >0) &&
        (eNB->dlsch[i][0]->rnti==rnti))       return i;
    else if ((eNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i;
  }

  if (type == SEARCH_EXIST)
    return -1;

  if (first_free_index != -1)
    eNB->dlsch[first_free_index][0]->rnti = 0;

  return first_free_index;
}


int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type) {
  uint16_t i;
  int16_t first_free_index=-1;
  AssertFatal(eNB!=NULL,"eNB is null\n");

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    AssertFatal(eNB->ulsch[i]!=NULL,"eNB->ulsch[%d] is null\n",i);

    if ((eNB->ulsch[i]->harq_mask >0) &&
        (eNB->ulsch[i]->rnti==rnti))       return i;
    else if ((eNB->ulsch[i]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i;
  }

  if (type == SEARCH_EXIST)
    return -1;

  if (first_free_index != -1)
    eNB->ulsch[first_free_index]->rnti = 0;

  return first_free_index;
}





void fill_pdcch_order(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,DCI_ALLOC_t *dci_alloc,nfapi_dl_config_dci_dl_pdu *pdu) {
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  uint8_t        *dci_pdu = &dci_alloc->dci_pdu[0];
  nfapi_dl_config_dci_dl_pdu_rel8_t *rel8 = &pdu->dci_dl_pdu_rel8;
  dci_alloc->firstCCE = rel8->cce_idx;
  dci_alloc->L = rel8->aggregation_level;
  dci_alloc->rnti = rel8->rnti;
  dci_alloc->harq_pid = rel8->harq_process;
  dci_alloc->ra_flag = 0;
  dci_alloc->format = format1A;
  LOG_D (PHY, "NFAPI: DCI format %d, nCCE %d, L %d, rnti %x,harq_pid %d\n", rel8->dci_format, rel8->cce_idx, rel8->aggregation_level, rel8->rnti, rel8->harq_process);

  switch (fp->N_RB_DL) {
    case 6:
      if (fp->frame_type == TDD) {
        dci_alloc->dci_length                         = sizeof_DCI1A_1_5MHz_TDD_1_6_t;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->type     = 1;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->mcs      = rel8->mcs_1;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->TPC      = rel8->tpc;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid = rel8->harq_process;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->padding  = 0;
      } else {
        dci_alloc->dci_length                         = sizeof_DCI1A_1_5MHz_FDD_t;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->type         = 1;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->vrb_type     = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->mcs          = rel8->mcs_1;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->ndi          = rel8->new_data_indicator_1;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rv           = rel8->redundancy_version_1;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->padding      = 0;
        //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      }

      break;

    case 25:
      if (fp->frame_type == TDD) {
        dci_alloc->dci_length                         = sizeof_DCI1A_5MHz_TDD_1_6_t;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->type       = 1;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type   = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->mcs        = rel8->mcs_1;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->ndi        = rel8->new_data_indicator_1;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rballoc    = rel8->resource_block_coding;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rv         = rel8->redundancy_version_1;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->TPC        = rel8->tpc;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid   = rel8->harq_process;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->dai        = rel8->downlink_assignment_index;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->padding    = 0;
        //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      } else {
        dci_alloc->dci_length                         = sizeof_DCI1A_5MHz_FDD_t;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->type           = 1;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->vrb_type       = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->mcs            = rel8->mcs_1;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->ndi            = rel8->new_data_indicator_1;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->rballoc        = rel8->resource_block_coding;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->rv             = rel8->redundancy_version_1;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->TPC            = rel8->tpc;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->harq_pid       = rel8->harq_process;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->padding        = 0;
        //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      }

      break;

    case 50:
      if (fp->frame_type == TDD) {
        dci_alloc->dci_length                         = sizeof_DCI1A_10MHz_TDD_1_6_t;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->type      = 1;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->vrb_type  = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->mcs       = rel8->mcs_1;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->TPC       = rel8->tpc;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->harq_pid  = rel8->harq_process;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->padding   = 0;
        //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      } else {
        dci_alloc->dci_length                         = sizeof_DCI1A_10MHz_FDD_t;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->type          = 1;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->vrb_type      = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->ndi           = rel8->new_data_indicator_1;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->padding       = 0;
        //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      }

      break;

    case 100:
      if (fp->frame_type == TDD) {
        dci_alloc->dci_length                         = sizeof_DCI1A_20MHz_TDD_1_6_t;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->type      = 1;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->vrb_type  = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->mcs       = rel8->mcs_1;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->TPC       = rel8->tpc;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->harq_pid  = rel8->harq_process;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->padding   = 0;
        //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      } else {
        dci_alloc->dci_length                         = sizeof_DCI1A_20MHz_FDD_t;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->type          = 1;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->vrb_type      = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->ndi           = rel8->new_data_indicator_1;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->padding       = 0;
        //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      }

      break;
  }

  LOG_T(PHY,"%d.%d: DCI 1A: rnti %x, PDCCH order to do PRACH\n",
        proc->frame_tx, proc->subframe_tx, rel8->rnti);
}

void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,
                        int frame,
                        int subframe,
                        L1_rxtx_proc_t *proc,
                        DCI_ALLOC_t *dci_alloc,
                        nfapi_dl_config_dci_dl_pdu *pdu) {
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  uint8_t        *dci_pdu = &dci_alloc->dci_pdu[0];
  nfapi_dl_config_dci_dl_pdu_rel8_t *rel8 = &pdu->dci_dl_pdu_rel8;

  /* check if this is a DCI 1A PDCCH order for RAPROC */
  if (rel8->dci_format == NFAPI_DL_DCI_FORMAT_1A && rel8->rnti_type == 1) {
    int             full_rb;

    switch (fp->N_RB_DL) {
      case 6:
        full_rb = 63;
        break;

      case 25:
        full_rb = 511;
        break;

      case 50:
        full_rb = 2047;
        break;

      case 100:
        full_rb = 8191;
        break;

      default:
        abort ();
    }

    if (rel8->resource_block_coding == full_rb)
      return fill_pdcch_order (eNB, proc, dci_alloc, pdu);
  }

  LTE_eNB_DLSCH_t *dlsch0=NULL,*dlsch1=NULL;
  LTE_DL_eNB_HARQ_t *dlsch0_harq=NULL,*dlsch1_harq=NULL;
  int beamforming_mode = 0;
  int UE_id=-1;
  int NPRB;
  int TB0_active;
  int TB1_active;
  uint16_t DL_pmi_single=0; // This should be taken from DLSCH parameters for PUSCH precoding
  uint8_t I_mcs = 0;
  dci_alloc->firstCCE = rel8->cce_idx;
  dci_alloc->L = rel8->aggregation_level;
  dci_alloc->rnti = rel8->rnti;
  dci_alloc->harq_pid = rel8->harq_process;
  dci_alloc->ra_flag = 0;
  LOG_D(PHY,"NFAPI: SFN/SF:%04d%d proc:TX:[SFN/SF:%04d%d] DCI format %d, nCCE %d, L %d, rnti %x, harq_pid %d\n",
        frame,subframe,proc->frame_tx,proc->subframe_tx,rel8->dci_format,rel8->cce_idx,rel8->aggregation_level,rel8->rnti,rel8->harq_process);

  if ((rel8->rnti_type == 2 ) && (rel8->rnti != SI_RNTI) && (rel8->rnti != P_RNTI)) dci_alloc->ra_flag = 1;

  UE_id = find_dlsch(rel8->rnti,eNB,SEARCH_EXIST_OR_FREE);

  if( (UE_id<0) || (UE_id>=NUMBER_OF_UE_MAX) ) {
    LOG_E(PHY,"illegal UE_id found!!! rnti %04x UE_id %d\n",rel8->rnti,UE_id);
    return;
  }

  //AssertFatal(UE_id!=-1,"no free or exiting dlsch_context\n");
  //AssertFatal(UE_id<NUMBER_OF_UE_MAX,"returned UE_id %d >= %d(NUMBER_OF_UE_MAX)\n",UE_id,NUMBER_OF_UE_MAX);
  dlsch0 = eNB->dlsch[UE_id][0];
  dlsch1 = eNB->dlsch[UE_id][1];
  dlsch0->ue_type = 0;
  dlsch1->ue_type = 0;
  beamforming_mode                          = eNB->transmission_mode[(uint8_t)UE_id]<7?0:eNB->transmission_mode[(uint8_t)UE_id];
  dlsch0_harq                               = dlsch0->harq_processes[rel8->harq_process];
  dlsch0_harq->codeword                     = 0;
  dlsch1_harq                               = dlsch1->harq_processes[rel8->harq_process];
  dlsch1_harq->codeword                     = 1;
  dlsch0->subframe_tx[subframe]             = 1;
  LOG_D(PHY,"NFAPI: SFN/SF:%04d%d proc:TX:SFN/SF:%04d%d dlsch0[rnti:%x harq_mask:%04x] dci_pdu[rnti:%x rnti_type:%d harq_process:%d ndi1:%d] dlsch0_harq[round:%d harq_mask:%x ndi:%d]\n",
        frame,subframe,
        proc->frame_tx,proc->subframe_tx,
        dlsch0->rnti,dlsch0->harq_mask,
        rel8->rnti, rel8->rnti_type, rel8->harq_process, rel8->new_data_indicator_1,
        dlsch0_harq->round, dlsch0->harq_mask, dlsch0_harq->ndi);

  if (dlsch0->rnti != rel8->rnti) { // if rnti of dlsch is not the same as in the config, this is a new entry
    dlsch0_harq->round=0;
    dlsch0->harq_mask=0;
  }

  if ((dlsch0->harq_mask & (1 << rel8->harq_process)) > 0) {
    if (rel8->new_data_indicator_1 != dlsch0_harq->ndi)
      dlsch0_harq->round = 0;
  } else {                      // process is inactive, so activate and set round to 0
    dlsch0_harq->round = 0;
  }

  dlsch0_harq->ndi = rel8->new_data_indicator_1;
#ifdef PHY_TX_THREAD
  dlsch0->active[subframe]        = 1;
#else
  dlsch0->active        = 1;
#endif

  if (rel8->rnti_type == 2)
    dlsch0_harq->round    = 0;

  LOG_D(PHY,"NFAPI: rel8[rnti %x dci_format %d harq_process %d ndi1 %d rnti type %d] dlsch0[rnti %x harq_mask %x] dlsch0_harq[round %d ndi %d]\n",
        rel8->rnti,rel8->dci_format,rel8->harq_process, rel8->new_data_indicator_1, rel8->rnti_type,
        dlsch0->rnti,dlsch0->harq_mask,
        dlsch0_harq->round,dlsch0_harq->ndi
       );

  switch (rel8->dci_format) {
    case NFAPI_DL_DCI_FORMAT_1A:
      AssertFatal(rel8->resource_block_coding < 8192, "SFN/SF:%04d%d proc:TX:SFN/SF:%04d%d: rel8->resource_block_coding (%p) %u >= 8192 (rnti %x, rnti_type %d, format %d, harq_id %d\n",
                  frame,subframe,proc->frame_tx,subframe,
                  &rel8->resource_block_coding,rel8->resource_block_coding,rel8->rnti,rel8->rnti_type,rel8->dci_format,rel8->harq_process);
      dci_alloc->format = format1A;

      switch (fp->N_RB_DL) {
        case 6:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                         = sizeof_DCI1A_1_5MHz_TDD_1_6_t;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->type     = 1;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type = rel8->virtual_resource_block_assignment_flag;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->mcs      = rel8->mcs_1;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
            ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->padding  = 0;
          } else {
            dci_alloc->dci_length                         = sizeof_DCI1A_1_5MHz_FDD_t;
            ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->type         = 1;
            ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->vrb_type     = rel8->virtual_resource_block_assignment_flag;
            ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->mcs          = rel8->mcs_1;
            ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->ndi          = rel8->new_data_indicator_1;
            ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
            ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rv           = rel8->redundancy_version_1;
            ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
            ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
            ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->padding      = 0;
            //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          AssertFatal (rel8->virtual_resource_block_assignment_flag == LOCALIZED, "Distributed RB allocation not done yet\n");
          dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT6[rel8->resource_block_coding];
          dlsch0_harq->vrb_type = rel8->virtual_resource_block_assignment_flag;
          dlsch0_harq->nb_rb = RIV2nb_rb_LUT6[rel8->resource_block_coding]; //NPRB;
          break;

        case 25:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                         = sizeof_DCI1A_5MHz_TDD_1_6_t;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->type       = 1;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type   = rel8->virtual_resource_block_assignment_flag;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->mcs        = rel8->mcs_1;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->ndi        = rel8->new_data_indicator_1;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rballoc    = rel8->resource_block_coding;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rv         = rel8->redundancy_version_1;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->TPC        = rel8->tpc;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid   = rel8->harq_process;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->dai        = rel8->downlink_assignment_index;
            ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->padding    = 0;
            //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                         = sizeof_DCI1A_5MHz_FDD_t;
            ((DCI1A_5MHz_FDD_t *)dci_pdu)->type           = 1;
            ((DCI1A_5MHz_FDD_t *)dci_pdu)->vrb_type       = rel8->virtual_resource_block_assignment_flag;
            ((DCI1A_5MHz_FDD_t *)dci_pdu)->mcs            = rel8->mcs_1;
            ((DCI1A_5MHz_FDD_t *)dci_pdu)->ndi            = rel8->new_data_indicator_1;
            ((DCI1A_5MHz_FDD_t *)dci_pdu)->rballoc        = rel8->resource_block_coding;
            ((DCI1A_5MHz_FDD_t *)dci_pdu)->rv             = rel8->redundancy_version_1;
            ((DCI1A_5MHz_FDD_t *)dci_pdu)->TPC            = rel8->tpc;
            ((DCI1A_5MHz_FDD_t *)dci_pdu)->harq_pid       = rel8->harq_process;
            ((DCI1A_5MHz_FDD_t *)dci_pdu)->padding        = 0;
            //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          AssertFatal (rel8->virtual_resource_block_assignment_flag == LOCALIZED, "Distributed RB allocation not done yet\n");
          dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT25[rel8->resource_block_coding];
          dlsch0_harq->vrb_type = rel8->virtual_resource_block_assignment_flag;
          dlsch0_harq->nb_rb = RIV2nb_rb_LUT25[rel8->resource_block_coding];        //NPRB;
          break;

        case 50:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                         = sizeof_DCI1A_10MHz_TDD_1_6_t;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->type      = 1;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->vrb_type  = rel8->virtual_resource_block_assignment_flag;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->mcs       = rel8->mcs_1;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->TPC       = rel8->tpc;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->harq_pid  = rel8->harq_process;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
            ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->padding   = 0;
            //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                         = sizeof_DCI1A_10MHz_FDD_t;
            ((DCI1A_10MHz_FDD_t *)dci_pdu)->type          = 1;
            ((DCI1A_10MHz_FDD_t *)dci_pdu)->vrb_type      = rel8->virtual_resource_block_assignment_flag;
            ((DCI1A_10MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
            ((DCI1A_10MHz_FDD_t *)dci_pdu)->ndi           = rel8->new_data_indicator_1;
            ((DCI1A_10MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
            ((DCI1A_10MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
            ((DCI1A_10MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
            ((DCI1A_10MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
            ((DCI1A_10MHz_FDD_t *)dci_pdu)->padding       = 0;
            //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          AssertFatal (rel8->virtual_resource_block_assignment_flag == LOCALIZED, "Distributed RB allocation not done yet\n");
          dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT50_0[rel8->resource_block_coding];
          dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT50_1[rel8->resource_block_coding];
          dlsch0_harq->vrb_type = rel8->virtual_resource_block_assignment_flag;
          dlsch0_harq->nb_rb = RIV2nb_rb_LUT50[rel8->resource_block_coding];        //NPRB;
          break;

        case 100:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                         = sizeof_DCI1A_20MHz_TDD_1_6_t;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->type      = 1;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->vrb_type  = rel8->virtual_resource_block_assignment_flag;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->mcs       = rel8->mcs_1;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->TPC       = rel8->tpc;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->harq_pid  = rel8->harq_process;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
            ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->padding   = 0;
            //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                         = sizeof_DCI1A_20MHz_FDD_t;
            ((DCI1A_20MHz_FDD_t *)dci_pdu)->type          = 1;
            ((DCI1A_20MHz_FDD_t *)dci_pdu)->vrb_type      = rel8->virtual_resource_block_assignment_flag;
            ((DCI1A_20MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
            ((DCI1A_20MHz_FDD_t *)dci_pdu)->ndi           = rel8->new_data_indicator_1;
            ((DCI1A_20MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
            ((DCI1A_20MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
            ((DCI1A_20MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
            ((DCI1A_20MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
            ((DCI1A_20MHz_FDD_t *)dci_pdu)->padding       = 0;
            //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          AssertFatal (rel8->virtual_resource_block_assignment_flag == LOCALIZED, "Distributed RB allocation not done yet\n");
          dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT100_0[rel8->resource_block_coding];
          dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT100_1[rel8->resource_block_coding];
          dlsch0_harq->rb_alloc[2] = localRIV2alloc_LUT100_2[rel8->resource_block_coding];
          dlsch0_harq->rb_alloc[3] = localRIV2alloc_LUT100_3[rel8->resource_block_coding];
          dlsch0_harq->vrb_type = rel8->virtual_resource_block_assignment_flag;
          dlsch0_harq->nb_rb = RIV2nb_rb_LUT100[rel8->resource_block_coding];       //NPRB;
          break;
      }

      if (rel8->rnti_type == 2) {
        // see 36-212 V8.6.0 p. 45
        NPRB = (rel8->tpc & 1) + 2;
        // 36-213 sec.7.1.7.2 p.26
        I_mcs     = rel8->mcs_1;
      } else {
        NPRB      = dlsch0_harq->nb_rb;
        I_mcs     = get_I_TBS(rel8->mcs_1);
      }

      AssertFatal(NPRB>0,"DCI 1A: NPRB = 0 (rnti %x, rnti type %d, tpc %d, round %d, resource_block_coding %d, harq process %d)\n",rel8->rnti,rel8->rnti_type,rel8->tpc,dlsch0_harq->round,
                  rel8->resource_block_coding,rel8->harq_process);
      dlsch0_harq->rvidx         = rel8->redundancy_version_1;
      dlsch0_harq->Nl            = 1;
      dlsch0_harq->mimo_mode     = (fp->nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI;
      dlsch0_harq->dl_power_off  = 1;
      dlsch0_harq->mcs             = rel8->mcs_1;
      dlsch0_harq->Qm              = 2;
      dlsch0_harq->TBS             = TBStable[I_mcs][NPRB-1];
      dlsch0->harq_ids[frame%2][subframe]   = rel8->harq_process;
#ifdef PHY_TX_THREAD
      dlsch0->active[subframe]     = 1;
#else
      dlsch0->active               = 1;
#endif
      dlsch0->rnti                 = rel8->rnti;

      //dlsch0->harq_ids[subframe]   = rel8->harq_process;

      if (dlsch0_harq->round == 0)
        dlsch0_harq->status = ACTIVE;

      dlsch0->harq_mask |= (1 << rel8->harq_process);

      if (rel8->rnti_type == 1) LOG_D(PHY,"DCI 1A: round %d, mcs %d, TBS %d, rballoc %x, rv %d, rnti %x, harq process %d\n",dlsch0_harq->round,rel8->mcs_1,dlsch0_harq->TBS,rel8->resource_block_coding,
                                        rel8->redundancy_version_1,rel8->rnti,rel8->harq_process);

      break;

    case NFAPI_DL_DCI_FORMAT_1:
      dci_alloc->format           = format1;
#ifdef PHY_TX_THREAD
      dlsch0->active[subframe]    = 1;
#else
      dlsch0->active              = 1;
#endif
      LOG_D(PHY,"SFN/SF:%04d%d proc:TX:SFN/SF:%04d%d: Programming DLSCH for Format 1 DCI, harq_pid %d\n",frame,subframe,proc->frame_tx,subframe,rel8->harq_process);

      switch (fp->N_RB_DL) {
        case 6:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                     = sizeof_DCI1_1_5MHz_TDD_t;
            ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
            ((DCI1_1_5MHz_TDD_t *)dci_pdu)->mcs       = rel8->mcs_1;
            ((DCI1_1_5MHz_TDD_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
            ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
            ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
            ((DCI1_1_5MHz_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
            ((DCI1_1_5MHz_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
            ((DCI1_1_5MHz_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
            ((DCI1_1_5MHz_TDD_t *)dci_pdu)->padding   = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                         = sizeof_DCI1_1_5MHz_FDD_t;
            ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rah           = rel8->resource_allocation_type;
            ((DCI1_1_5MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
            ((DCI1_1_5MHz_FDD_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
            ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
            ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
            ((DCI1_1_5MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
            ((DCI1_1_5MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
            ((DCI1_1_5MHz_FDD_t *)dci_pdu)->padding       = 0;
            //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          break;

        case 25:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                      = sizeof_DCI1_5MHz_TDD_t;
            ((DCI1_5MHz_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
            ((DCI1_5MHz_TDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
            ((DCI1_5MHz_TDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
            ((DCI1_5MHz_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI1_5MHz_TDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
            ((DCI1_5MHz_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI1_5MHz_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI1_5MHz_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
            ((DCI1_5MHz_TDD_t *)dci_pdu)->padding  = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                  = sizeof_DCI1_5MHz_FDD_t;
            ((DCI1_5MHz_FDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
            ((DCI1_5MHz_FDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
            ((DCI1_5MHz_FDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
            ((DCI1_5MHz_FDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI1_5MHz_FDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
            ((DCI1_5MHz_FDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI1_5MHz_FDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI1_5MHz_FDD_t *)dci_pdu)->padding  = 0;
            //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          break;

        case 50:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                       = sizeof_DCI1_10MHz_TDD_t;
            ((DCI1_10MHz_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
            ((DCI1_10MHz_TDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
            ((DCI1_10MHz_TDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
            ((DCI1_10MHz_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI1_10MHz_TDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
            ((DCI1_10MHz_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI1_10MHz_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI1_10MHz_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
            ((DCI1_10MHz_TDD_t *)dci_pdu)->padding  = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                   = sizeof_DCI1_10MHz_FDD_t;
            ((DCI1_10MHz_FDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
            ((DCI1_10MHz_FDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
            ((DCI1_10MHz_FDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
            ((DCI1_10MHz_FDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI1_10MHz_FDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
            ((DCI1_10MHz_FDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI1_10MHz_FDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI1_10MHz_FDD_t *)dci_pdu)->padding  = 0;
          }

          break;

        case 100:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                       = sizeof_DCI1_20MHz_TDD_t;
            ((DCI1_20MHz_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
            ((DCI1_20MHz_TDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
            ((DCI1_20MHz_TDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
            ((DCI1_20MHz_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI1_20MHz_TDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
            ((DCI1_20MHz_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI1_20MHz_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI1_20MHz_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
            ((DCI1_20MHz_TDD_t *)dci_pdu)->padding  = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                   = sizeof_DCI1_20MHz_FDD_t;
            ((DCI1_20MHz_FDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
            ((DCI1_20MHz_FDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
            ((DCI1_20MHz_FDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
            ((DCI1_20MHz_FDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI1_20MHz_FDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
            ((DCI1_20MHz_FDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI1_20MHz_FDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI1_20MHz_FDD_t *)dci_pdu)->padding  = 0;
          }

          break;
      }

      AssertFatal (rel8->harq_process < 8, "Format 1: harq_pid=%d >= 8\n", rel8->harq_process);
      dlsch0_harq = dlsch0->harq_processes[rel8->harq_process];
      dlsch0_harq->codeword = 0;
      // printf("DCI: Setting subframe_tx for subframe %d\n",subframe);
      dlsch0->subframe_tx[subframe] = 1;
      conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch0_harq->rb_alloc);
      dlsch0_harq->nb_rb = conv_nprb (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL);
      NPRB = dlsch0_harq->nb_rb;
      AssertFatal (NPRB > 0, "NPRB == 0\n");
      dlsch0_harq->rvidx = rel8->redundancy_version_1;
      dlsch0_harq->Nl = 1;

      //    dlsch[0]->layer_index = 0;
      if (beamforming_mode == 0)
        dlsch0_harq->mimo_mode = (fp->nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI;
      else if (beamforming_mode == 7)
        dlsch0_harq->mimo_mode = TM7;
      else
        LOG_E (PHY, "Invalid beamforming mode %dL\n", beamforming_mode);

      dlsch0_harq->dl_power_off = 1;
#ifdef PHY_TX_THREAD
      dlsch0->active[subframe] = 1;
#else
      dlsch0->active = 1;
#endif

      if (dlsch0_harq->round == 0) {
        dlsch0_harq->status = ACTIVE;
        //            printf("Setting DLSCH process %d to ACTIVE\n",rel8->harq_process);
        // MCS and TBS don't change across HARQ rounds
        dlsch0_harq->mcs = rel8->mcs_1;
        dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
        dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][NPRB - 1];
      }

      LOG_D(PHY,"DCI: Set harq_ids[%d] to %d (%p)\n",subframe,rel8->harq_process,dlsch0);
      dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process;
      dlsch0->harq_mask |= (1 << rel8->harq_process);
      dlsch0->rnti = rel8->rnti;
      break;

    case NFAPI_DL_DCI_FORMAT_2A:
      dci_alloc->format = format2A;

      switch (fp->N_RB_DL) {
        case 6:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                         = sizeof_DCI2A_1_5MHz_2A_TDD_t;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1     = rel8->mcs_1;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2     = rel8->mcs_2;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->ndi1     = rel8->new_data_indicator_1;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->ndi2     = rel8->new_data_indicator_2;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rv1      = rel8->redundancy_version_1;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rv2      = rel8->redundancy_version_2;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->tb_swap  = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
            /* there is no padding in this structure, it is exactly 32 bits */
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                         = sizeof_DCI2A_1_5MHz_2A_FDD_t;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rah          = rel8->resource_allocation_type;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->mcs1         = rel8->mcs_1;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->mcs2         = rel8->mcs_2;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->ndi1         = rel8->new_data_indicator_1;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->ndi2         = rel8->new_data_indicator_2;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rv1          = rel8->redundancy_version_1;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rv2          = rel8->redundancy_version_2;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap      = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->padding      = 0;
            //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          break;

        case 25:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                        = sizeof_DCI2A_5MHz_2A_TDD_t;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
            ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                           = sizeof_DCI2A_5MHz_2A_FDD_t;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rah           = rel8->resource_allocation_type;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->mcs1          = rel8->mcs_1;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->mcs2          = rel8->mcs_2;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->ndi1          = rel8->new_data_indicator_1;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->ndi2          = rel8->new_data_indicator_2;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rv1           = rel8->redundancy_version_1;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rv2           = rel8->redundancy_version_2;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->tb_swap       = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->padding       = 0;
            //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          break;

        case 50:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                        = sizeof_DCI2A_10MHz_2A_TDD_t;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs1     = rel8->mcs_1;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs2     = rel8->mcs_2;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->ndi1     = rel8->new_data_indicator_1;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->ndi2     = rel8->new_data_indicator_2;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rv1      = rel8->redundancy_version_1;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rv2      = rel8->redundancy_version_2;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->tb_swap  = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
            ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->padding  = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                        = sizeof_DCI2A_10MHz_2A_FDD_t;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->TPC       = rel8->tpc;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->padding   = 0;
          }

          break;

        case 100:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                        = sizeof_DCI2A_20MHz_2A_TDD_t;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                           = sizeof_DCI2A_20MHz_2A_FDD_t;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rah          = rel8->resource_allocation_type;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->mcs1         = rel8->mcs_1;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->mcs2         = rel8->mcs_2;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->ndi1         = rel8->new_data_indicator_1;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->ndi2         = rel8->new_data_indicator_2;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rv1          = rel8->redundancy_version_1;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rv2          = rel8->redundancy_version_2;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
            ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->tb_swap      = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->padding      = 0;
          }

          break;
      }

      AssertFatal (rel8->harq_process < 8, "Format 2_2A: harq_pid=%d >= 8\n", rel8->harq_process);

      // Flip the TB to codeword mapping as described in 5.3.3.1.5 of 36-212 V11.3.0
      // note that we must set tbswap=0 in eNB scheduler if one TB is deactivated

      // This must be set as in TM4, does not work properly now.
      if (rel8->transport_block_to_codeword_swap_flag == 1) {
        dlsch0 = eNB->dlsch[UE_id][1];
        dlsch1 = eNB->dlsch[UE_id][0];
      }

      dlsch0_harq = dlsch0->harq_processes[rel8->harq_process];
      dlsch1_harq = dlsch1->harq_processes[rel8->harq_process];
      dlsch0->subframe_tx[subframe] = 1;
      dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process;
      dlsch1->harq_ids[frame%2][subframe] = rel8->harq_process;
      //    printf("Setting DLSCH harq id %d to subframe %d\n",harq_pid,subframe);
      conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch0_harq->rb_alloc);
      dlsch1_harq->rb_alloc[0] = dlsch0_harq->rb_alloc[0];
      dlsch0_harq->nb_rb = conv_nprb (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL);
      dlsch1_harq->nb_rb = dlsch0_harq->nb_rb;
      AssertFatal (dlsch0_harq->nb_rb > 0, "nb_rb=0\n");
      dlsch0_harq->mcs = rel8->mcs_1;
      dlsch1_harq->mcs = rel8->mcs_2;
      dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
      dlsch1_harq->Qm = get_Qm (rel8->mcs_2);
      dlsch0_harq->rvidx = rel8->redundancy_version_1;
      dlsch1_harq->rvidx = rel8->redundancy_version_2;
      // assume both TBs are active
      dlsch0_harq->Nl        = 1;
      dlsch1_harq->Nl        = 1;
#ifdef PHY_TX_THREAD
      dlsch0->active[subframe] = 1;
      dlsch1->active[subframe] = 1;
#else
      dlsch0->active = 1;
      dlsch1->active = 1;
#endif
      dlsch0->harq_mask                         |= (1<<rel8->harq_process);
      dlsch1->harq_mask                         |= (1<<rel8->harq_process);

      // check if either TB is disabled (see 36-213 V11.3 Section )
      if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) {
#ifdef PHY_TX_THREAD
        dlsch0->active[subframe] = 0;
#else
        dlsch0->active = 0;
#endif
        dlsch0->harq_mask                         &= ~(1<<rel8->harq_process);
      }

      if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) {
#ifdef PHY_TX_THREAD
        dlsch1->active[subframe]= 0;
#else
        dlsch1->active = 0;
#endif
        dlsch1->harq_mask                         &= ~(1<<rel8->harq_process);
      }

      // dlsch0_harq->dl_power_off = 0;
      // dlsch1_harq->dl_power_off = 0;

      if (fp->nb_antenna_ports_eNB == 2) {
        dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
        dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][dlsch0_harq->nb_rb - 1];
#ifdef PHY_TX_THREAD

        if ((dlsch0->active[subframe]==1) && (dlsch1->active[subframe]==1)) {
#else

        if ((dlsch0->active==1) && (dlsch1->active==1)) {
#endif
          dlsch0_harq->mimo_mode = LARGE_CDD;
          dlsch1_harq->mimo_mode = LARGE_CDD;
          dlsch0_harq->dl_power_off = 1;
          dlsch1_harq->dl_power_off = 1;
        } else {
          dlsch0_harq->mimo_mode = ALAMOUTI;
          dlsch1_harq->mimo_mode = ALAMOUTI;
        }
      } else if (fp->nb_antenna_ports_eNB == 4) { // 4 antenna case
#ifdef PHY_TX_THREAD
        if ((dlsch0->active[subframe]==1) && (dlsch1->active[subframe]==1)) {
#else

        if ((dlsch0->active==1) && (dlsch1->active==1)) {
#endif

          switch (rel8->precoding_information) {
            case 0:                // one layer per transport block
              dlsch0_harq->mimo_mode = LARGE_CDD;
              dlsch1_harq->mimo_mode = LARGE_CDD;
              dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
              dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
              dlsch0_harq->dl_power_off = 1;
              dlsch1_harq->dl_power_off = 1;
              break;

            case 1:                // one-layers on TB 0, two on TB 1
              dlsch0_harq->mimo_mode = LARGE_CDD;
              dlsch1_harq->mimo_mode = LARGE_CDD;
              dlsch1_harq->Nl = 2;
              dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][(dlsch1_harq->nb_rb << 1) - 1];
              dlsch0_harq->dl_power_off = 1;
              dlsch1_harq->dl_power_off = 1;
              break;

            case 2:                // two-layers on TB 0, two on TB 1
              dlsch0_harq->mimo_mode = LARGE_CDD;
              dlsch1_harq->mimo_mode = LARGE_CDD;
              dlsch0_harq->Nl = 2;
              dlsch0_harq->dl_power_off = 1;
              dlsch1_harq->dl_power_off = 1;

              if (fp->N_RB_DL <= 56) {
                dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][(dlsch0_harq->nb_rb << 1) - 1];
                dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][(dlsch1_harq->nb_rb << 1) - 1];
              } else {
                LOG_E (PHY, "Add implementation of Table 7.1.7.2.2-1 for two-layer TBS conversion with N_RB_DL > 56\n");
              }

              break;

            case 3:                //
              LOG_E (PHY, "Illegal value (3) for TPMI in Format 2A DCI\n");
              break;
          }

#ifdef PHY_TX_THREAD
        } else if (dlsch0->active[subframe] == 1) {
#else
        } else if (dlsch0->active == 1) {
#endif

          switch (rel8->precoding_information) {
            case 0:                // one layer per transport block
              dlsch0_harq->mimo_mode = ALAMOUTI;
              dlsch1_harq->mimo_mode = ALAMOUTI;
              dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
              break;

            case 1:                // two-layers on TB 0
              dlsch0_harq->mimo_mode = LARGE_CDD;
              dlsch0_harq->Nl = 2;
              dlsch0_harq->dl_power_off = 1;
              dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][(dlsch0_harq->nb_rb << 1) - 1];
              break;

            case 2:                // two-layers on TB 0, two on TB 1
            case 3:                //
              LOG_E (PHY, "Illegal value %d for TPMI in Format 2A DCI with one transport block enabled\n", rel8->precoding_information);
              break;
          }

#ifdef PHY_TX_THREAD
        } else if (dlsch1->active[subframe] == 1) {
#else
        } else if (dlsch1->active == 1) {
#endif

          switch (rel8->precoding_information) {
            case 0:                // one layer per transport block
              dlsch0_harq->mimo_mode = ALAMOUTI;
              dlsch1_harq->mimo_mode = ALAMOUTI;
              dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][dlsch1_harq->nb_rb - 1];
              break;

            case 1:                // two-layers on TB 0
              dlsch1_harq->mimo_mode = LARGE_CDD;
              dlsch1_harq->Nl = 2;
              dlsch1_harq->dl_power_off = 1;
              dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][(dlsch1_harq->nb_rb << 1) - 1];
              break;

            case 2:                // two-layers on TB 0, two on TB 1
            case 3:                //
              LOG_E (PHY, "Illegal value %d for TPMI in Format 2A DCI with one transport block enabled\n", rel8->precoding_information);
              break;
          }
        }
      } else {
        LOG_E (PHY, "Illegal number of antennas for eNB %d\n", fp->nb_antenna_ports_eNB);
      }

      // reset HARQ process if this is the first transmission
#ifdef PHY_TX_THREAD

      if ((dlsch0->active[subframe]==1) && (dlsch0_harq->round == 0))
#else
      if ((dlsch0->active==1) && (dlsch0_harq->round == 0))
#endif
        dlsch0_harq->status = ACTIVE;

#ifdef PHY_TX_THREAD

      if ((dlsch1->active[subframe]==1) && (dlsch1_harq->round == 0))
#else
      if ((dlsch1->active==1) && (dlsch1_harq->round == 0))
#endif
        dlsch1_harq->status = ACTIVE;

      dlsch0->rnti = rel8->rnti;
      dlsch1->rnti = rel8->rnti;
      break;

    case NFAPI_DL_DCI_FORMAT_2:
      dci_alloc->format = format2;

      switch (fp->N_RB_DL) {
        case 6:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                       = sizeof_DCI2_1_5MHz_2A_TDD_t;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1     = rel8->mcs_1;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2     = rel8->mcs_2;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->ndi1     = rel8->new_data_indicator_1;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->ndi2     = rel8->new_data_indicator_2;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->rv1      = rel8->redundancy_version_1;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->rv2      = rel8->redundancy_version_2;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->tb_swap  = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->tpmi     = rel8->precoding_information;
            ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->padding  = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                         = sizeof_DCI2_1_5MHz_2A_FDD_t;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->mcs1         = rel8->mcs_1;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->mcs2         = rel8->mcs_2;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->ndi1         = rel8->new_data_indicator_1;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->ndi2         = rel8->new_data_indicator_2;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->rv1          = rel8->redundancy_version_1;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->rv2          = rel8->redundancy_version_2;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap      = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tpmi         = rel8->precoding_information;
            ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->padding      = 0;
            //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          break;

        case 25:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                        = sizeof_DCI2_5MHz_2A_TDD_t;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tpmi      = rel8->precoding_information;
            ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                           = sizeof_DCI2_5MHz_2A_FDD_t;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rah           = rel8->resource_allocation_type;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs1          = rel8->mcs_1;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs2          = rel8->mcs_2;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->ndi1          = rel8->new_data_indicator_1;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->ndi2          = rel8->new_data_indicator_2;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv1           = rel8->redundancy_version_1;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv2           = rel8->redundancy_version_2;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tb_swap       = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tpmi          = rel8->precoding_information;
            ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->padding       = 0;
            //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          }

          break;

        case 50:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                        = sizeof_DCI2_10MHz_2A_TDD_t;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs1     = rel8->mcs_1;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs2     = rel8->mcs_2;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->ndi1     = rel8->new_data_indicator_1;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->ndi2     = rel8->new_data_indicator_2;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rv1      = rel8->redundancy_version_1;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rv2      = rel8->redundancy_version_2;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tb_swap  = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tpmi     = rel8->precoding_information;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->padding  = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                        = sizeof_DCI2_10MHz_2A_FDD_t;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->TPC       = rel8->tpc;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
            ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tpmi      = rel8->precoding_information;
            ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
          }

          break;

        case 100:
          if (fp->frame_type == TDD) {
            dci_alloc->dci_length                        = sizeof_DCI2_20MHz_2A_TDD_t;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tpmi      = rel8->precoding_information;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
            //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
          } else {
            dci_alloc->dci_length                           = sizeof_DCI2_20MHz_2A_FDD_t;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rah          = rel8->resource_allocation_type;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->mcs1         = rel8->mcs_1;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->mcs2         = rel8->mcs_2;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->ndi1         = rel8->new_data_indicator_1;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->ndi2         = rel8->new_data_indicator_2;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rv1          = rel8->redundancy_version_1;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rv2          = rel8->redundancy_version_2;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
            ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tb_swap      = rel8->transport_block_to_codeword_swap_flag;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tpmi         = rel8->precoding_information;
            ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->padding      = 0;
          }

          break;
      }

      AssertFatal (rel8->harq_process >= 8, "Format 2_2A: harq_pid=%d >= 8\n", rel8->harq_process);
      // Flip the TB to codeword mapping as described in 5.3.3.1.5 of 36-212 V11.3.0
      // note that we must set tbswap=0 in eNB scheduler if one TB is deactivated
      TB0_active = 1;
      TB1_active = 1;

      if ((rel8->redundancy_version_1 == 1) && (rel8->mcs_1 == 0)) {
        TB0_active = 0;
      }

      if ((rel8->redundancy_version_2 == 1) && (rel8->mcs_2 == 0)) {
        TB1_active = 0;
      }

#ifdef DEBUG_HARQ
      printf ("RV0 = %d, RV1 = %d. MCS0 = %d, MCS1=%d\n", rel8->redundancy_version_1, rel8->redundancy_version_2, rel8->mcs_1, rel8->mcs_2);
#endif

      if (TB0_active && TB1_active && rel8->transport_block_to_codeword_swap_flag==0) {
#ifdef PHY_TX_THREAD
        dlsch0->active[subframe] = 1;
        dlsch1->active[subframe] = 1;
#else
        dlsch0->active = 1;
        dlsch1->active = 1;
#endif
        dlsch0->harq_mask                         |= (1<<rel8->harq_process);
        dlsch1->harq_mask                         |= (1<<rel8->harq_process);
        dlsch0_harq = dlsch0->harq_processes[rel8->harq_process];
        dlsch1_harq = dlsch1->harq_processes[rel8->harq_process];
        dlsch0_harq->mcs = rel8->mcs_1;
        dlsch1_harq->mcs = rel8->mcs_2;
        dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
        dlsch1_harq->Qm = get_Qm (rel8->mcs_2);
        dlsch0_harq->rvidx = rel8->redundancy_version_1;
        dlsch1_harq->rvidx = rel8->redundancy_version_2;
        dlsch0_harq->status = ACTIVE;
        dlsch1_harq->status = ACTIVE;
        dlsch0_harq->codeword = 0;
        dlsch1_harq->codeword = 1;
#ifdef DEBUG_HARQ
        printf ("\n ENB: BOTH ACTIVE\n");
#endif
      } else if (TB0_active && TB1_active && rel8->transport_block_to_codeword_swap_flag == 1) {
        dlsch0 = eNB->dlsch[UE_id][1];
        dlsch1 = eNB->dlsch[UE_id][0];
#ifdef PHY_TX_THREAD
        dlsch0->active[subframe] = 1;
        dlsch1->active[subframe] = 1;
#else
        dlsch0->active = 1;
        dlsch1->active = 1;
#endif
        dlsch0->harq_mask |= (1 << rel8->harq_process);
        dlsch1->harq_mask |= (1 << rel8->harq_process);
        dlsch1_harq = dlsch1->harq_processes[rel8->harq_process];
        dlsch0_harq->mcs = rel8->mcs_1;
        dlsch1_harq->mcs = rel8->mcs_2;
        dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
        dlsch1_harq->Qm = get_Qm (rel8->mcs_2);
        dlsch0_harq->rvidx = rel8->redundancy_version_1;
        dlsch1_harq->rvidx = rel8->redundancy_version_2;
        dlsch0_harq->status = ACTIVE;
        dlsch1_harq->status = ACTIVE;
        dlsch0_harq->codeword=1;
        dlsch1_harq->codeword=0;
      } else if (TB0_active && (TB1_active==0)) {
#ifdef PHY_TX_THREAD
        dlsch0->active[subframe] = 1;
#else
        dlsch0->active = 1;
#endif
        dlsch0->harq_mask                         |= (1<<rel8->harq_process);
        dlsch0_harq = dlsch0->harq_processes[rel8->harq_process];
        dlsch0_harq->mcs = rel8->mcs_1;
        dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
        dlsch0_harq->rvidx = rel8->redundancy_version_1;
        dlsch0_harq->status = ACTIVE;
        dlsch0_harq->codeword = 0;
        dlsch1 = NULL;
        dlsch1_harq = NULL;
#ifdef DEBUG_HARQ
        printf ("\n ENB: TB1 is deactivated, retransmit TB0 transmit in TM6\n");
#endif
      } else if ((TB0_active==0) && TB1_active) {
#ifdef PHY_TX_THREAD
        dlsch1->active[subframe] = 1;
#else
        dlsch1->active = 1;
#endif
        dlsch1->harq_mask                         |= (1<<rel8->harq_process);
        dlsch1_harq = dlsch1->harq_processes[rel8->harq_process];
        dlsch1_harq->mcs = rel8->mcs_2;
        dlsch1_harq->Qm = get_Qm (rel8->mcs_2);
        dlsch1_harq->rvidx = rel8->redundancy_version_2;
        dlsch1_harq->status = ACTIVE;
        dlsch1_harq->codeword = 0;
        dlsch0 = NULL;
        dlsch0_harq = NULL;
#ifdef DEBUG_HARQ
        printf ("\n ENB: TB0 is deactivated, retransmit TB1 transmit in TM6\n");
#endif
      }

      if (dlsch0 != NULL) {
        dlsch0->subframe_tx[subframe] = 1;
        dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process;
      }

      if (dlsch1_harq != NULL) {
        dlsch1->harq_ids[frame%2][subframe] = rel8->harq_process;
      }

      if (dlsch0 != NULL) {
        conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch0_harq->rb_alloc);
        dlsch0_harq->nb_rb = conv_nprb (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL);

        if (dlsch1 != NULL) {
          dlsch1_harq->rb_alloc[0] = dlsch0_harq->rb_alloc[0];
          dlsch1_harq->nb_rb = dlsch0_harq->nb_rb;
        }
      } else if ((dlsch0 == NULL) && (dlsch1 != NULL)) {
        conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch1_harq->rb_alloc);
        dlsch1_harq->nb_rb = conv_nprb (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL);
      }

      // assume both TBs are active
      if (dlsch0_harq != NULL)
        dlsch0_harq->Nl = 1;

      if (dlsch1_harq != NULL)
        dlsch1_harq->Nl = 1;

      // check if either TB is disabled (see 36-213 V11.3 Section )

      if (fp->nb_antenna_ports_eNB == 2) {
        if ((dlsch0 != NULL) && (dlsch1 != NULL)) {       //two CW active
          dlsch0_harq->dl_power_off = 1;
          dlsch1_harq->dl_power_off = 1;
          dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
          dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][dlsch1_harq->nb_rb - 1];

          switch (rel8->precoding_information) {
            case 0:
              dlsch0_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODING1;
              dlsch1_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODING1;
              dlsch0_harq->pmi_alloc = pmi_extend (fp, 0, 1);
              dlsch1_harq->pmi_alloc = pmi_extend (fp, 0, 1);
              break;

            case 1:
              dlsch0_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODINGj;
              dlsch1_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODINGj;
              dlsch0_harq->pmi_alloc = pmi_extend (fp, 1, 1);
              dlsch0_harq->pmi_alloc = pmi_extend (fp, 1, 1);
              break;

            case 2:                // PUSCH precoding
              dlsch0_harq->mimo_mode = DUALSTREAM_PUSCH_PRECODING;
              dlsch0_harq->pmi_alloc = DL_pmi_single;
              dlsch1_harq->mimo_mode = DUALSTREAM_PUSCH_PRECODING;
              dlsch1_harq->pmi_alloc = DL_pmi_single;
              break;

            default:
              break;
          }
        } else if ((dlsch0 != NULL) && (dlsch1 == NULL)) {        // only CW 0 active
          dlsch0_harq->dl_power_off = 1;
          dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];

          switch (rel8->precoding_information) {
            case 0:
              dlsch0_harq->mimo_mode = ALAMOUTI;
              break;

            case 1:
              dlsch0_harq->mimo_mode = UNIFORM_PRECODING11;
              dlsch0_harq->pmi_alloc = pmi_extend (fp, 0, 0);
              break;

            case 2:
              dlsch0_harq->mimo_mode = UNIFORM_PRECODING1m1;
              dlsch0_harq->pmi_alloc = pmi_extend (fp, 1, 0);
              break;

            case 3:
              dlsch0_harq->mimo_mode = UNIFORM_PRECODING1j;
              dlsch0_harq->pmi_alloc = pmi_extend (fp, 2, 0);
              break;

            case 4:
              dlsch0_harq->mimo_mode = UNIFORM_PRECODING1mj;
              dlsch0_harq->pmi_alloc = pmi_extend (fp, 3, 0);
              break;

            case 5:
              dlsch0_harq->mimo_mode = PUSCH_PRECODING0;
              dlsch0_harq->pmi_alloc = DL_pmi_single;
              break;

            case 6:
              dlsch0_harq->mimo_mode = PUSCH_PRECODING1;
              dlsch0_harq->pmi_alloc = DL_pmi_single;
              break;
          }
        } else if ((dlsch0 == NULL) && (dlsch1 != NULL)) {
          dlsch1_harq->dl_power_off = 1;
          dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][dlsch1_harq->nb_rb - 1];

          switch (rel8->precoding_information) {
            case 0:
              dlsch1_harq->mimo_mode = ALAMOUTI;
              break;

            case 1:
              dlsch1_harq->mimo_mode = UNIFORM_PRECODING11;
              dlsch1_harq->pmi_alloc = pmi_extend (fp, 0, 0);
              break;

            case 2:
              dlsch1_harq->mimo_mode = UNIFORM_PRECODING1m1;
              dlsch1_harq->pmi_alloc = pmi_extend (fp, 1, 0);
              break;

            case 3:
              dlsch1_harq->mimo_mode = UNIFORM_PRECODING1j;
              dlsch1_harq->pmi_alloc = pmi_extend (fp, 2, 0);
              break;

            case 4:
              dlsch1_harq->mimo_mode = UNIFORM_PRECODING1mj;
              dlsch1_harq->pmi_alloc = pmi_extend (fp, 3, 0);
              break;

            case 5:
              dlsch1_harq->mimo_mode = PUSCH_PRECODING0;
              dlsch1_harq->pmi_alloc = DL_pmi_single;
              break;

            case 6:
              dlsch1_harq->mimo_mode = PUSCH_PRECODING1;
              dlsch1_harq->pmi_alloc = DL_pmi_single;
              break;
          }
        }
      } else if (fp->nb_antenna_ports_eNB == 4) {
        // fill in later
      }

      // reset HARQ process if this is the first transmission
      /* if (dlsch0_harq->round == 0)
         dlsch0_harq->status = ACTIVE;

         if (dlsch1_harq->round == 0)
         dlsch1_harq->status = ACTIVE; */
      if (dlsch0_harq != NULL)
        dlsch0->rnti = rel8->rnti;

      if (dlsch1 != NULL)
        dlsch1->rnti = rel8->rnti;

      break;
  }

  if (dlsch0_harq) {
    dlsch0_harq->frame    = frame;
    dlsch0_harq->subframe = subframe;
  }

  if (dlsch1_harq) {
    dlsch1_harq->frame    = frame;
    dlsch1_harq->subframe = subframe;
  }

#ifdef DEBUG_DCI

  if (dlsch0) {
    printf ("dlsch0 eNB: dlsch0   %p\n", dlsch0);
    printf ("dlsch0 eNB: rnti     %x\n", dlsch0->rnti);
    printf ("dlsch0 eNB: NBRB     %d\n", dlsch0_harq->nb_rb);
    printf ("dlsch0 eNB: rballoc  %x\n", dlsch0_harq->rb_alloc[0]);
    printf ("dlsch0 eNB: harq_pid %d\n", harq_pid);
    printf ("dlsch0 eNB: round    %d\n", dlsch0_harq->round);
    printf ("dlsch0 eNB: rvidx    %d\n", dlsch0_harq->rvidx);
    printf ("dlsch0 eNB: TBS      %d (NPRB %d)\n", dlsch0_harq->TBS, NPRB);
    printf ("dlsch0 eNB: mcs      %d\n", dlsch0_harq->mcs);
    printf ("dlsch0 eNB: tpmi %d\n", rel8->precoding_information);
    printf ("dlsch0 eNB: mimo_mode %d\n", dlsch0_harq->mimo_mode);
  }

  if (dlsch1) {
    printf ("dlsch1 eNB: dlsch1   %p\n", dlsch1);
    printf ("dlsch1 eNB: rnti     %x\n", dlsch1->rnti);
    printf ("dlsch1 eNB: NBRB     %d\n", dlsch1_harq->nb_rb);
    printf ("dlsch1 eNB: rballoc  %x\n", dlsch1_harq->rb_alloc[0]);
    printf ("dlsch1 eNB: harq_pid %d\n", harq_pid);
    printf ("dlsch1 eNB: round    %d\n", dlsch1_harq->round);
    printf ("dlsch1 eNB: rvidx    %d\n", dlsch1_harq->rvidx);
    printf ("dlsch1 eNB: TBS      %d (NPRB %d)\n", dlsch1_harq->TBS, NPRB);
    printf ("dlsch1 eNB: mcs      %d\n", dlsch1_harq->mcs);
    printf ("dlsch1 eNB: tpmi %d\n", rel8->precoding_information);
    printf ("dlsch1 eNB: mimo_mode %d\n", dlsch1_harq->mimo_mode);
  }

#endif
  //printf("DCI %d.%d rnti %d harq %d TBS %d\n", frame, subframe, rel8->rnti, rel8->harq_process, dlsch0_harq->TBS);
#if T_TRACER

  if (dlsch0->active)
    T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(0), T_INT(frame), T_INT(subframe),
      T_INT(rel8->rnti), T_INT(rel8->dci_format), T_INT(rel8->harq_process),
      T_INT(rel8->mcs_1), T_INT(dlsch0_harq->TBS));

#endif
}


void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dci_alloc,nfapi_dl_config_mpdcch_pdu *pdu) {
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  uint8_t        *dci_pdu = &dci_alloc->dci_pdu[0];
  nfapi_dl_config_mpdcch_pdu_rel13_t *rel13 = &pdu->mpdcch_pdu_rel13;
  LTE_eNB_DLSCH_t *dlsch0 = NULL;
  LTE_DL_eNB_HARQ_t *dlsch0_harq = NULL;
  int             UE_id;
  int             subframe = proc->subframe_tx;
  int             frame = proc->frame_tx;
  dci_alloc->firstCCE = rel13->ecce_index;
  dci_alloc->L = rel13->aggregation_level;
  dci_alloc->rnti = rel13->rnti;
  dci_alloc->harq_pid = rel13->harq_process;
  dci_alloc->narrowband = rel13->mpdcch_narrow_band;
  dci_alloc->number_of_prb_pairs = rel13->number_of_prb_pairs;
  dci_alloc->resource_block_assignment = rel13->resource_block_assignment;
  dci_alloc->transmission_type = rel13->mpdcch_tansmission_type;
  dci_alloc->start_symbol = rel13->start_symbol;
  dci_alloc->ce_mode = rel13->ce_mode;
  dci_alloc->dmrs_scrambling_init = rel13->drms_scrambling_init;
  dci_alloc->i0 = rel13->initial_transmission_sf_io;
  UE_id = find_dlsch (rel13->rnti, eNB, SEARCH_EXIST_OR_FREE);
  AssertFatal (UE_id != -1, "no free or exiting dlsch_context\n");
  AssertFatal (UE_id < NUMBER_OF_UE_MAX, "returned UE_id %d >= %d(NUMBER_OF_UE_MAX)\n", UE_id, NUMBER_OF_UE_MAX);
  dlsch0 = eNB->dlsch[UE_id][0];
  dlsch0_harq = dlsch0->harq_processes[rel13->harq_process];
  dci_alloc->ra_flag = 0;

  if (rel13->rnti_type == 2) {
    dci_alloc->ra_flag = 1;
  }

  AssertFatal (fp->frame_type == FDD, "TDD is not supported yet for eMTC\n");
  AssertFatal (fp->N_RB_DL == 25 || fp->N_RB_DL == 50 || fp->N_RB_DL == 100, "eMTC only with N_RB_DL = 25,50,100\n");

  switch (rel13->dci_format) {
    case 10:                     // Format 6-1A
      dci_alloc->format = format6_1A;

      switch (fp->N_RB_DL) {
        case 25:
          dci_alloc->dci_length = sizeof_DCI6_1A_5MHz_t;
          ((DCI6_1A_5MHz_t *) dci_pdu)->type = 1;
          ((DCI6_1A_5MHz_t *) dci_pdu)->hopping = rel13->frequency_hopping_enabled_flag;
          ((DCI6_1A_5MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
          ((DCI6_1A_5MHz_t *) dci_pdu)->mcs = rel13->mcs;
          ((DCI6_1A_5MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
          ((DCI6_1A_5MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
          ((DCI6_1A_5MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
          ((DCI6_1A_5MHz_t *) dci_pdu)->rv = rel13->redundancy_version;
          ((DCI6_1A_5MHz_t *) dci_pdu)->TPC = rel13->tpc;
          ((DCI6_1A_5MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
          ((DCI6_1A_5MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
          ((DCI6_1A_5MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
          break;

        case 50:
          dci_alloc->dci_length = sizeof_DCI6_1A_10MHz_t;
          ((DCI6_1A_10MHz_t *) dci_pdu)->type = 1;
          ((DCI6_1A_10MHz_t *) dci_pdu)->hopping = rel13->frequency_hopping_enabled_flag;
          ((DCI6_1A_10MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding&31;
          ((DCI6_1A_10MHz_t *) dci_pdu)->narrowband = rel13->resource_block_coding>>5;
          ((DCI6_1A_10MHz_t *) dci_pdu)->mcs = rel13->mcs;
          ((DCI6_1A_10MHz_t *) dci_pdu)->rep = (rel13->pdsch_reptition_levels);
          ((DCI6_1A_10MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
          ((DCI6_1A_10MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
          ((DCI6_1A_10MHz_t *) dci_pdu)->rv = rel13->redundancy_version;
          ((DCI6_1A_10MHz_t *) dci_pdu)->TPC = rel13->tpc;
          ((DCI6_1A_10MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
          ((DCI6_1A_10MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
          ((DCI6_1A_10MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
          LOG_D(PHY,
                "Frame %d, Subframe %d : Programming Format 6-1A DCI, type %d, hopping %d, narrowband %d, rballoc %x, mcs %d, rep %d, harq_pid %d, ndi %d, rv %d, TPC %d, srs_req %d, harq_ack_off %d, dci_rep r%d => %x\n",
                frame,subframe,
                ((DCI6_1A_10MHz_t *) dci_pdu)->type,
                ((DCI6_1A_10MHz_t *) dci_pdu)->hopping,
                ((DCI6_1A_10MHz_t *) dci_pdu)->narrowband,
                ((DCI6_1A_10MHz_t *) dci_pdu)->rballoc,
                ((DCI6_1A_10MHz_t *) dci_pdu)->mcs,
                ((DCI6_1A_10MHz_t *) dci_pdu)->rep,
                ((DCI6_1A_10MHz_t *) dci_pdu)->harq_pid,
                ((DCI6_1A_10MHz_t *) dci_pdu)->ndi,
                ((DCI6_1A_10MHz_t *) dci_pdu)->rv,
                ((DCI6_1A_10MHz_t *) dci_pdu)->TPC,
                ((DCI6_1A_10MHz_t *) dci_pdu)->srs_req,
                ((DCI6_1A_10MHz_t *) dci_pdu)->harq_ack_off,
                ((DCI6_1A_10MHz_t *) dci_pdu)->dci_rep,
                ((uint32_t *)dci_pdu)[0]);
          break;

        case 100:
          dci_alloc->dci_length = sizeof_DCI6_1A_20MHz_t;
          ((DCI6_1A_20MHz_t *) dci_pdu)->type = 1;
          ((DCI6_1A_20MHz_t *) dci_pdu)->hopping = rel13->frequency_hopping_enabled_flag;
          ((DCI6_1A_20MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
          ((DCI6_1A_20MHz_t *) dci_pdu)->mcs = rel13->mcs;
          ((DCI6_1A_20MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
          ((DCI6_1A_20MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
          ((DCI6_1A_20MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
          ((DCI6_1A_20MHz_t *) dci_pdu)->rv = rel13->redundancy_version;
          ((DCI6_1A_20MHz_t *) dci_pdu)->TPC = rel13->tpc;
          ((DCI6_1A_20MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
          ((DCI6_1A_20MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
          ((DCI6_1A_20MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
          break;
      }

      break;

    case 11:                     // Format 6-1B
      dci_alloc->format = format6_1B;

      switch (fp->N_RB_DL) {
        case 25:
          dci_alloc->dci_length = sizeof_DCI6_1B_5MHz_t;
          ((DCI6_1B_5MHz_t *) dci_pdu)->type = 1;
          ((DCI6_1B_5MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
          ((DCI6_1B_5MHz_t *) dci_pdu)->mcs = rel13->mcs;
          ((DCI6_1B_5MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
          ((DCI6_1B_5MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
          ((DCI6_1B_5MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
          ((DCI6_1B_5MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
          ((DCI6_1B_5MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
          break;

        case 50:
          dci_alloc->dci_length = sizeof_DCI6_1B_10MHz_t;
          ((DCI6_1B_10MHz_t *) dci_pdu)->type = 1;
          ((DCI6_1B_10MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
          ((DCI6_1B_10MHz_t *) dci_pdu)->mcs = rel13->mcs;
          ((DCI6_1B_10MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
          ((DCI6_1B_10MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
          ((DCI6_1B_10MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
          ((DCI6_1B_10MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
          ((DCI6_1B_10MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
          break;

        case 100:
          dci_alloc->dci_length = sizeof_DCI6_1B_20MHz_t;
          ((DCI6_1B_20MHz_t *) dci_pdu)->type = 1;
          ((DCI6_1B_20MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
          ((DCI6_1B_20MHz_t *) dci_pdu)->mcs = rel13->mcs;
          ((DCI6_1B_20MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
          ((DCI6_1B_20MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
          ((DCI6_1B_20MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
          ((DCI6_1B_20MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
          ((DCI6_1B_20MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
          break;
      }

    case 12:                     // Format 6-2
      dci_alloc->format = format6_2;

      switch (fp->N_RB_DL) {
        case 25:
          dci_alloc->dci_length = sizeof_DCI6_2_5MHz_t;

          if (rel13->paging_direct_indication_differentiation_flag == 0) {
            ((DCI6_2_di_5MHz_t *) dci_pdu)->type = 0;
            ((DCI6_2_di_5MHz_t *) dci_pdu)->di_info = rel13->direct_indication;
          } else {
            ((DCI6_2_paging_5MHz_t *) dci_pdu)->type = 1;
            ((DCI6_2_paging_5MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
            ((DCI6_2_paging_5MHz_t *) dci_pdu)->mcs = rel13->mcs;
            ((DCI6_2_paging_5MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
            ((DCI6_2_paging_5MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
          }

          break;

        case 50:
          dci_alloc->dci_length = sizeof_DCI6_2_10MHz_t;

          if (rel13->paging_direct_indication_differentiation_flag == 0) {
            ((DCI6_2_di_10MHz_t *) dci_pdu)->type = 0;
            ((DCI6_2_di_10MHz_t *) dci_pdu)->di_info = rel13->direct_indication;
          } else {
            ((DCI6_2_paging_10MHz_t *) dci_pdu)->type = 1;
            ((DCI6_2_paging_10MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
            ((DCI6_2_paging_10MHz_t *) dci_pdu)->mcs = rel13->mcs;
            ((DCI6_2_paging_10MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
            ((DCI6_2_paging_10MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
          }

          break;

        case 100:
          dci_alloc->dci_length = sizeof_DCI6_2_20MHz_t;

          if (rel13->paging_direct_indication_differentiation_flag == 0) {
            ((DCI6_2_di_20MHz_t *) dci_pdu)->type = 0;
            ((DCI6_2_di_20MHz_t *) dci_pdu)->di_info = rel13->direct_indication;
          } else {
            ((DCI6_2_paging_20MHz_t *) dci_pdu)->type = 1;
            ((DCI6_2_paging_20MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
            ((DCI6_2_paging_20MHz_t *) dci_pdu)->mcs = rel13->mcs;
            ((DCI6_2_paging_20MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
            ((DCI6_2_paging_20MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
          }

          break;
      }
  }

  AssertFatal (rel13->harq_process < 8, "ERROR: Format 6_1A: harq_pid=%d >= 8\n", rel13->harq_process);
  dlsch0->ue_type = rel13->ce_mode;
  dlsch0_harq = dlsch0->harq_processes[rel13->harq_process];
  dlsch0_harq->codeword = 0;
  // printf("DCI: Setting subframe_tx for subframe %d\n",subframe);
  dlsch0->subframe_tx[(subframe + 2) % 10] = 1;
  LOG_D(PHY,"PDSCH : resource_block_coding %x\n",rel13->resource_block_coding);
  conv_eMTC_rballoc (rel13->resource_block_coding,
                     fp->N_RB_DL,
                     dlsch0_harq->rb_alloc);
  dlsch0_harq->nb_rb = RIV2nb_rb_LUT6[rel13->resource_block_coding & 31];       // this is the 6PRB RIV
  dlsch0_harq->rvidx = rel13->redundancy_version;
  dlsch0_harq->Nl = 1;
  //    dlsch[0]->layer_index = 0;
  //  if (beamforming_mode == 0)
  dlsch0_harq->mimo_mode = (fp->nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI;
  //else if (beamforming_mode == 7)
  //  dlsch0_harq->mimo_mode = TM7;
  //else
  //LOG_E(PHY,"Invalid beamforming mode %dL\n", beamforming_mode);
  dlsch0_harq->dl_power_off = 1;
  dlsch0->subframe_tx[subframe] = 1;

  if (dlsch0->rnti != rel13->rnti) {     // if rnti of dlsch is not the same as in the config, this is a new entry
    dlsch0_harq->round = 0;
    dlsch0->harq_mask =0;
    printf("*********************** rnti %x => %x, pos %d\n",rel13->rnti,dlsch0->rnti,UE_id);
  }

  if ((dlsch0->harq_mask & (1 << rel13->harq_process)) > 0) {
    if ((rel13->new_data_indicator != dlsch0_harq->ndi)||(dci_alloc->ra_flag==1))
      dlsch0_harq->round = 0;
  } else {                      // process is inactive, so activate and set round to 0
    dlsch0_harq->round = 0;
  }

  dlsch0_harq->ndi = rel13->new_data_indicator;

  if (dlsch0_harq->round == 0) {
    dlsch0_harq->status = ACTIVE;
    dlsch0_harq->mcs = rel13->mcs;

    if (dci_alloc->ra_flag == 0) // get TBS from table using mcs and nb_rb
      dlsch0_harq->TBS         = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1];
    else if (rel13->tpc == 0)  //N1A_PRB=2, get TBS from table using mcs and nb_rb=2
      dlsch0_harq->TBS         = TBStable[get_I_TBS(dlsch0_harq->mcs)][1];
    else if (rel13->tpc == 1)  //N1A_PRB=3, get TBS from table using mcs and nb_rb=3
      dlsch0_harq->TBS         = TBStable[get_I_TBS(dlsch0_harq->mcs)][2];
    else AssertFatal(1==0,"Don't know how to set TBS (TPC %d)\n",rel13->tpc);

    LOG_D(PHY,"fill_mdci_and_dlsch : TBS = %d(%d) %p, %x\n",dlsch0_harq->TBS,dlsch0_harq->mcs,dlsch0,rel13->rnti);
  }

  dlsch0->active = 1;
  dlsch0->harq_mask |= (1 << rel13->harq_process);
  dlsch0_harq->frame    = (subframe >= 8) ? ((frame + 1) & 1023) : frame;
  dlsch0_harq->subframe = (subframe + 2) % 10;
  LOG_D(PHY,"Setting DLSCH UEid %d harq_ids[%d] from %d to %d\n",UE_id,dlsch0_harq->subframe,dlsch0->harq_ids[frame%2][dlsch0_harq->subframe],rel13->harq_process);
  dlsch0->harq_ids[dlsch0_harq->frame%2][dlsch0_harq->subframe] = rel13->harq_process;
  dlsch0_harq->pdsch_start = rel13->start_symbol;
  LOG_D(PHY,"Setting DLSCH harq %d round %d to active for %d.%d\n",rel13->harq_process,dlsch0_harq->round,dlsch0_harq->frame,dlsch0_harq->subframe);
  dlsch0->rnti = rel13->rnti;
  dlsch0_harq->Qm = get_Qm(rel13->mcs);
}

void fill_dci0(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc,
               DCI_ALLOC_t *dci_alloc,nfapi_hi_dci0_dci_pdu *pdu) {
  LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
  uint32_t        cqi_req = pdu->dci_pdu_rel8.cqi_csi_request;
  uint32_t        dai = pdu->dci_pdu_rel8.dl_assignment_index;
  uint32_t        cshift = pdu->dci_pdu_rel8.cyclic_shift_2_for_drms;
  uint32_t        TPC = pdu->dci_pdu_rel8.tpc;
  uint32_t        mcs = pdu->dci_pdu_rel8.mcs_1;
  uint32_t        hopping = pdu->dci_pdu_rel8.frequency_hopping_enabled_flag;
  uint32_t        rballoc = computeRIV (frame_parms->N_RB_DL,
                                        pdu->dci_pdu_rel8.resource_block_start,
                                        pdu->dci_pdu_rel8.number_of_resource_block);
  uint32_t        ndi = pdu->dci_pdu_rel8.new_data_indication_1;
  uint16_t UE_id   = -1;
#ifdef T_TRACER
  T(T_ENB_PHY_ULSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
    T_INT(pdu->dci_pdu_rel8.rnti), T_INT(pdu->dci_pdu_rel8.harq_pid),
    T_INT(mcs), T_INT(-1 /* TODO: remove round? */),
    T_INT(pdu->dci_pdu_rel8.resource_block_start),
    T_INT(pdu->dci_pdu_rel8.number_of_resource_block),
    T_INT(get_TBS_UL(mcs, pdu->dci_pdu_rel8.number_of_resource_block) * 8),
    T_INT(pdu->dci_pdu_rel8.aggregation_level),
    T_INT(pdu->dci_pdu_rel8.cce_index));
#endif
  void           *dci_pdu = (void *) dci_alloc->dci_pdu;
  LOG_D(PHY,"SFN/SF:%04d%d DCI0[rnti %x cqi %d mcs %d hopping %d rballoc %x (%d,%d) ndi %d TPC %d cshift %d]\n",
        frame,subframe,
        pdu->dci_pdu_rel8.rnti,cqi_req, mcs,hopping,rballoc,
        pdu->dci_pdu_rel8.resource_block_start,
        pdu->dci_pdu_rel8.number_of_resource_block, ndi,TPC,cshift);
  dci_alloc->format = format0;
  dci_alloc->firstCCE = pdu->dci_pdu_rel8.cce_index;
  dci_alloc->L = pdu->dci_pdu_rel8.aggregation_level;
  dci_alloc->rnti = pdu->dci_pdu_rel8.rnti;
  dci_alloc->ra_flag = 0;

  switch (frame_parms->N_RB_DL) {
    case 6:
      if (frame_parms->frame_type == TDD) {
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->dai = dai;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->cshift = cshift;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->TPC = TPC;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->mcs = mcs;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->ndi = ndi;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->hopping = hopping;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->type = 0;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_1_5MHz_TDD_1_6_t;
      } else {
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->cshift = cshift;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->TPC = TPC;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->mcs = mcs;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->ndi = ndi;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->hopping = hopping;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->type = 0;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_1_5MHz_FDD_t;
      }

      break;

    case 25:
      if (frame_parms->frame_type == TDD) {
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->dai = dai;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->cshift = cshift;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->TPC = TPC;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->mcs = mcs;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->ndi = ndi;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->hopping = hopping;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->type = 0;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_5MHz_TDD_1_6_t;
      } else {
        ((DCI0_5MHz_FDD_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->cshift = cshift;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->TPC = TPC;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->mcs = mcs;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->ndi = ndi;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->hopping = hopping;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->type = 0;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_5MHz_FDD_t;
      }

      break;

    case 50:
      if (frame_parms->frame_type == TDD) {
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->dai = dai;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->cshift = cshift;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->TPC = TPC;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->mcs = mcs;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->ndi = ndi;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->hopping = hopping;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->type = 0;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_10MHz_TDD_1_6_t;
      } else {
        ((DCI0_10MHz_FDD_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->cshift = cshift;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->TPC = TPC;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->mcs = mcs;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->ndi = ndi;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->hopping = hopping;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->type = 0;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_10MHz_FDD_t;
      }

      break;

    case 100:
      if (frame_parms->frame_type == TDD) {
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->dai = dai;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->cshift = cshift;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->TPC = TPC;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->mcs = mcs;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->ndi = ndi;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->hopping = hopping;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->type = 0;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_20MHz_TDD_1_6_t;
      } else {
        ((DCI0_20MHz_FDD_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->cshift = cshift;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->TPC = TPC;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->mcs = mcs;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->ndi = ndi;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->hopping = hopping;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->type = 0;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_20MHz_FDD_t;
      }

      //printf("eNB: rb_alloc (20 MHz dci) %d\n",rballoc);
      break;

    default:
      LOG_E (PHY, "Invalid N_RB_DL %d\n", frame_parms->N_RB_DL);
      DevParam (frame_parms->N_RB_DL, 0, 0);
      break;
  }

  if(frame_parms->frame_type == TDD) {
    UE_id = find_ulsch(pdu->dci_pdu_rel8.rnti, eNB,SEARCH_EXIST_OR_FREE);

    if(UE_id != -1) {
      eNB->ulsch[UE_id]->harq_processes[pdu->dci_pdu_rel8.harq_pid]->V_UL_DAI = dai +1;
    }
  }
}

int get_narrowband_index(int N_RB_UL,int rb) {
  switch (N_RB_UL) {
    case 6: // 6 PRBs, N_NB=1, i_0=0
    case 25: // 25 PRBs, N_NB=4, i_0=0
      return(rb/6);
      break;

    case 50: // 50 PRBs, N_NB=8, i_0=1
    case 75: // 75 PRBs, N_NB=12, i_0=1
    case 15: // 15 PRBs, N_NB=2, i_0=1
      AssertFatal(rb>=1,"rb %d is not possible for %d PRBs\n",rb,N_RB_UL);
      return((rb-1)/6);
      break;

    case 100: // 100 PRBs, N_NB=16, i_0=2
      AssertFatal(rb>=2,"rb %d is not possible for %d PRBs\n",rb,N_RB_UL);
      return(rb-2/6);
      break;

    default:
      AssertFatal(1==0,"Impossible N_RB_UL %d\n",N_RB_UL);
      break;
  }
}

void fill_ulsch(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_ulsch_pdu *ulsch_pdu,int frame,int subframe) {
  uint8_t harq_pid;
  //uint8_t UE_id;
  boolean_t new_ulsch = (find_ulsch(ulsch_pdu->ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST)==-1) ? TRUE : FALSE;
  //AssertFatal((UE_id=find_ulsch(ulsch_pdu->ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE))>=0,
  //        "No existing/free UE ULSCH for rnti %x\n",ulsch_pdu->ulsch_pdu_rel8.rnti);
  LTE_eNB_ULSCH_t *ulsch=eNB->ulsch[UE_id];
  LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
  int use_srs = 0;
  harq_pid = ulsch_pdu->ulsch_pdu_rel8.harq_process_number;
  ulsch->harq_mask |= 1 << harq_pid;
  LOG_D(PHY,"Filling ULSCH : ue_type %d, harq_pid %d\n",ulsch->ue_type,harq_pid);
  ulsch->ue_type = ulsch_pdu->ulsch_pdu_rel13.ue_type;
  AssertFatal(harq_pid ==0 || ulsch->ue_type == NOCE, "Harq PID is not zero for BL/CE UE\n");

  if(ulsch_pdu->ulsch_pdu_rel13.repetition_number >1)	// Fill the Harq process parameters in the first Rep only
  {
	  return;
  }

  ulsch->harq_processes[harq_pid]->frame                                 = frame;
  ulsch->harq_processes[harq_pid]->subframe                              = subframe;
  ulsch->harq_processes[harq_pid]->handled                               = 0;
  ulsch->harq_processes[harq_pid]->repetition_number                     = ulsch_pdu->ulsch_pdu_rel13.repetition_number ;
  ulsch->harq_processes[harq_pid]->total_number_of_repetitions           = ulsch_pdu->ulsch_pdu_rel13.total_number_of_repetitions ;
  ulsch->harq_processes[harq_pid]->first_rb                              = ulsch_pdu->ulsch_pdu_rel8.resource_block_start;
  ulsch->harq_processes[harq_pid]->nb_rb                                 = ulsch_pdu->ulsch_pdu_rel8.number_of_resource_blocks;
  ulsch->harq_processes[harq_pid]->dci_alloc                             = 1;
  ulsch->harq_processes[harq_pid]->rar_alloc                             = 0;
  ulsch->harq_processes[harq_pid]->n_DMRS                                = ulsch_pdu->ulsch_pdu_rel8.cyclic_shift_2_for_drms;
  ulsch->harq_processes[harq_pid]->Nsymb_pusch                           = 12-(frame_parms->Ncp<<1)-(use_srs==0?0:1);
  ulsch->harq_processes[harq_pid]->srs_active                            = use_srs;

  //Mapping of cyclic shift field in DCI format0 to n_DMRS2 (3GPP 36.211, Table 5.5.2.1.1-1)
  if(ulsch->harq_processes[harq_pid]->n_DMRS == 0)
    ulsch->harq_processes[harq_pid]->n_DMRS2 = 0;
  else if(ulsch->harq_processes[harq_pid]->n_DMRS == 1)
    ulsch->harq_processes[harq_pid]->n_DMRS2 = 6;
  else if(ulsch->harq_processes[harq_pid]->n_DMRS == 2)
    ulsch->harq_processes[harq_pid]->n_DMRS2 = 3;
  else if(ulsch->harq_processes[harq_pid]->n_DMRS == 3)
    ulsch->harq_processes[harq_pid]->n_DMRS2 = 4;
  else if(ulsch->harq_processes[harq_pid]->n_DMRS == 4)
    ulsch->harq_processes[harq_pid]->n_DMRS2 = 2;
  else if(ulsch->harq_processes[harq_pid]->n_DMRS == 5)
    ulsch->harq_processes[harq_pid]->n_DMRS2 = 8;
  else if(ulsch->harq_processes[harq_pid]->n_DMRS == 6)
    ulsch->harq_processes[harq_pid]->n_DMRS2 = 10;
  else if(ulsch->harq_processes[harq_pid]->n_DMRS == 7)
    ulsch->harq_processes[harq_pid]->n_DMRS2 = 9;

  LOG_D(PHY,
        "[eNB %d][PUSCH %d] Frame %d, Subframe %d Programming PUSCH with n_DMRS2 %d (cshift %d) ulsch:ndi:%d ulsch_pdu:ndi:%d new_ulsch:%d status:%d ulsch_pdu:rvidx:%d ulsch_pdu->ulsch_pdu_rel8.size %d\n",
        eNB->Mod_id,harq_pid,frame,subframe,
        ulsch->harq_processes[harq_pid]->n_DMRS2,
        ulsch->harq_processes[harq_pid]->n_DMRS,
        ulsch->harq_processes[harq_pid]->ndi, ulsch_pdu->ulsch_pdu_rel8.new_data_indication, new_ulsch, ulsch->harq_processes[harq_pid]->status,
        ulsch_pdu->ulsch_pdu_rel8.redundancy_version,
        ulsch_pdu->ulsch_pdu_rel8.size);
  ulsch->harq_processes[harq_pid]->rvidx = ulsch_pdu->ulsch_pdu_rel8.redundancy_version;

  if(ulsch_pdu->ulsch_pdu_rel8.modulation_type!=0)
    ulsch->harq_processes[harq_pid]->Qm    = ulsch_pdu->ulsch_pdu_rel8.modulation_type;

  // Set O_ACK to 0 by default, will be set of DLSCH is scheduled and needs to be
  ulsch->harq_processes[harq_pid]->O_ACK         = 0;

  if ((ulsch->harq_processes[harq_pid]->status == SCH_IDLE) ||
      (ulsch->harq_processes[harq_pid]->ndi    != ulsch_pdu->ulsch_pdu_rel8.new_data_indication) ||
      (new_ulsch == TRUE)) {
    ulsch->harq_processes[harq_pid]->status        = ACTIVE;
    ulsch->harq_processes[harq_pid]->TBS           = ulsch_pdu->ulsch_pdu_rel8.size<<3;
    ulsch->harq_processes[harq_pid]->Msc_initial   = 12*ulsch_pdu->ulsch_pdu_rel8.number_of_resource_blocks;
    ulsch->harq_processes[harq_pid]->Nsymb_initial = ulsch->harq_processes[harq_pid]->Nsymb_pusch;
    ulsch->harq_processes[harq_pid]->round         = 0;
    ulsch->harq_processes[harq_pid]->ndi           = ulsch_pdu->ulsch_pdu_rel8.new_data_indication;
    // note here, the CQI bits need to be kept constant as in initial transmission
    // set to 0 in initial transmission, and don't touch them during retransmissions
    // will be set if MAC has activated ULSCH_CQI_RI_PDU or ULSCH_CQI_HARQ_RI_PDU
    ulsch->harq_processes[harq_pid]->Or1           = 0;
    ulsch->harq_processes[harq_pid]->Or2           = 0;
  } else {
    ulsch->harq_processes[harq_pid]->round++;
    ulsch->harq_processes[harq_pid]->TBS           = ulsch_pdu->ulsch_pdu_rel8.size<<3;
    ulsch->harq_processes[harq_pid]->Msc_initial   = 12*ulsch_pdu->ulsch_pdu_rel8.number_of_resource_blocks;
    ulsch->harq_processes[harq_pid]->Or1           = 0;
    ulsch->harq_processes[harq_pid]->Or2           = 0;
  }

  ulsch->rnti = ulsch_pdu->ulsch_pdu_rel8.rnti;
  LOG_D(PHY,"Filling ULSCH %x (UE_id %d) (new_ulsch %d) for Frame %d, Subframe %d : harq_pid %d, status %d, handled %d, first_rb %d, nb_rb %d, rvidx %d, Qm %d, TBS %d, round %d \n",
        ulsch->rnti,
        UE_id,
        new_ulsch,
        frame,
        subframe,
        harq_pid,
        ulsch->harq_processes[harq_pid]->status,
        ulsch->harq_processes[harq_pid]->handled,
        ulsch->harq_processes[harq_pid]->first_rb,
        ulsch->harq_processes[harq_pid]->nb_rb,
        ulsch->harq_processes[harq_pid]->rvidx,
        ulsch->harq_processes[harq_pid]->Qm,
        ulsch->harq_processes[harq_pid]->TBS,
        ulsch->harq_processes[harq_pid]->round);
}



int get_first_rb_in_narrowband(int N_RB_UL,
                               int rb) {
  switch (N_RB_UL) {
    case 6: // 6 PRBs, N_NB=1, i_0=0
    case 25: // 25 PRBs, N_NB=4, i_0=0
      return(rb - 6*(rb/6));
      break;

    case 50: // 50 PRBs, N_NB=8, i_0=1
    case 75: // 75 PRBs, N_NB=12, i_0=1
    case 15: // 15 PRBs, N_NB=2, i_0=1
      AssertFatal(rb>=1,"rb %d is not possible for %d PRBs\n",rb,N_RB_UL);
      return(rb-1-(6*((rb-1)/6)));
      break;

    case 100: // 100 PRBs, N_NB=16, i_0=2
      AssertFatal(rb>=2,"rb %d is not possible for %d PRBs\n",rb,N_RB_UL);
      return(rb-2-(6*((rb-2)/6)));
      break;

    default:
      AssertFatal(1==0,"Impossible N_RB_UL %d\n",N_RB_UL);
      break;
  }
}

void fill_mpdcch_dci0 (PHY_VARS_eNB *eNB,
                       L1_rxtx_proc_t *proc,
                       mDCI_ALLOC_t *dci_alloc,
                       nfapi_hi_dci0_mpdcch_dci_pdu *pdu) {
  LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
  nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *rel13 = &pdu->mpdcch_dci_pdu_rel13;
  uint32_t        cqi_req = rel13->csi_request;
  uint32_t        TPC = rel13->tpc;
  uint32_t        mcs = rel13->mcs;
  uint32_t        hopping = rel13->frequency_hopping_flag;
  uint32_t        narrowband = get_narrowband_index(frame_parms->N_RB_UL,rel13->resource_block_start);
  uint32_t        rballoc = computeRIV (6,
                                        get_first_rb_in_narrowband(frame_parms->N_RB_UL,rel13->resource_block_start),
                                        rel13->number_of_resource_blocks);
  uint32_t        ndi = rel13->new_data_indication;
#ifdef T_TRACER
  T (T_ENB_PHY_ULSCH_UE_DCI, T_INT (eNB->Mod_id), T_INT (proc->frame_tx), T_INT (proc->subframe_tx),
     T_INT (rel13->rnti), T_INT (((proc->frame_tx * 10 + proc->subframe_tx + 4) % 8) /* TODO: correct harq pid */ ),
     T_INT (mcs), T_INT (-1 /* TODO: remove round? */ ),
     T_INT (rel13->resource_block_start),
     T_INT (rel13->number_of_resource_blocks),
     T_INT (get_TBS_UL (mcs, rel13->number_of_resource_blocks) * 8), T_INT (rel13->aggreagation_level), T_INT (rel13->ecce_index));
#endif
  void           *dci_pdu = (void *) dci_alloc->dci_pdu;
  AssertFatal(rel13->ce_mode == 1 && rel13->dci_format == 4, "dci format 5 (CE_modeB) not supported yet\n");
  LOG_D (PHY, "Filling DCI6-0A with cqi %d, mcs %d, hopping %d, rballoc %x (%d,%d) ndi %d TPC %d\n", cqi_req,
         mcs, hopping, rballoc, rel13->resource_block_start, rel13->number_of_resource_blocks, ndi, TPC);
  dci_alloc->format = format6_0A;
  dci_alloc->firstCCE = rel13->ecce_index;
  dci_alloc->L = rel13->aggreagation_level;
  dci_alloc->rnti = rel13->rnti;
  dci_alloc->harq_pid = rel13->harq_process;
  dci_alloc->narrowband = rel13->mpdcch_narrowband;
  dci_alloc->number_of_prb_pairs = rel13->number_of_prb_pairs;
  dci_alloc->resource_block_assignment = rel13->resource_block_assignment;
  dci_alloc->transmission_type = rel13->mpdcch_transmission_type;
  dci_alloc->start_symbol = rel13->start_symbol;
  dci_alloc->ce_mode = rel13->ce_mode;
  dci_alloc->dmrs_scrambling_init = rel13->drms_scrambling_init;
  dci_alloc->i0 = rel13->initial_transmission_sf_io;

  switch (frame_parms->N_RB_DL) {
    case 6:
      if (frame_parms->frame_type == TDD) {
        AssertFatal(1==0,"TDD not supported for eMTC yet\n");
      } else {
        AssertFatal(1==0,"6 PRBS not supported for eMTC\n");
      }

      break;

    case 25:
      if (frame_parms->frame_type == TDD) {
        AssertFatal(1==0,"TDD not supported for eMTC yet\n");
      } else {
        dci_alloc->dci_length = sizeof_DCI6_0A_5MHz_t;
        ((DCI6_0A_5MHz_t *) dci_pdu)->type = 0;
        ((DCI6_0A_5MHz_t *) dci_pdu)->hopping = hopping;
        ((DCI6_0A_5MHz_t *) dci_pdu)->rballoc = rballoc;
        ((DCI6_0A_5MHz_t *) dci_pdu)->narrowband = narrowband;
        ((DCI6_0A_5MHz_t *) dci_pdu)->mcs = mcs;
        ((DCI6_0A_5MHz_t *) dci_pdu)->rep = rel13->pusch_repetition_levels;
        ((DCI6_0A_5MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_0A_5MHz_t *) dci_pdu)->ndi = ndi;
        ((DCI6_0A_5MHz_t *) dci_pdu)->rv_idx = rel13->redudency_version;
        ((DCI6_0A_5MHz_t *) dci_pdu)->TPC = TPC;
        ((DCI6_0A_5MHz_t *) dci_pdu)->csi_req = cqi_req;
        ((DCI6_0A_5MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
        ((DCI6_0A_5MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
      }

      break;

    case 50:
      if (frame_parms->frame_type == TDD) {
        AssertFatal(1==0,"TDD not supported for eMTC yet\n");
      } else {
        dci_alloc->dci_length = sizeof_DCI6_0A_10MHz_t;
        ((DCI6_0A_10MHz_t *) dci_pdu)->type = 0;
        ((DCI6_0A_10MHz_t *) dci_pdu)->hopping = hopping;
        ((DCI6_0A_10MHz_t *) dci_pdu)->rballoc = rballoc;
        ((DCI6_0A_10MHz_t *) dci_pdu)->narrowband = narrowband;
        ((DCI6_0A_10MHz_t *) dci_pdu)->mcs = mcs;
        ((DCI6_0A_10MHz_t *) dci_pdu)->rep = rel13->pusch_repetition_levels;
        ((DCI6_0A_10MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_0A_10MHz_t *) dci_pdu)->ndi = ndi;
        ((DCI6_0A_10MHz_t *) dci_pdu)->rv_idx = rel13->redudency_version;
        ((DCI6_0A_10MHz_t *) dci_pdu)->TPC = TPC;
        ((DCI6_0A_10MHz_t *) dci_pdu)->csi_req = cqi_req;
        ((DCI6_0A_10MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
        ((DCI6_0A_10MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
        LOG_D(PHY,
              "Frame %d, Subframe %d : Programming Format 6-0A DCI, type %d, hopping %d, narrowband %d, rballoc %x, mcs %d, rep %d, harq_pid %d, ndi %d, rv %d, TPC %d, csi_req %d, srs_req %d, dci_rep r%d => %x\n",
              proc->frame_tx,proc->subframe_tx,
              ((DCI6_0A_10MHz_t *) dci_pdu)->type,
              ((DCI6_0A_10MHz_t *) dci_pdu)->hopping,
              ((DCI6_0A_10MHz_t *) dci_pdu)->narrowband,
              ((DCI6_0A_10MHz_t *) dci_pdu)->rballoc,
              ((DCI6_0A_10MHz_t *) dci_pdu)->mcs,
              ((DCI6_0A_10MHz_t *) dci_pdu)->rep,
              ((DCI6_0A_10MHz_t *) dci_pdu)->harq_pid,
              ((DCI6_0A_10MHz_t *) dci_pdu)->ndi,
              ((DCI6_0A_10MHz_t *) dci_pdu)->rv_idx,
              ((DCI6_0A_10MHz_t *) dci_pdu)->TPC,
              ((DCI6_0A_10MHz_t *) dci_pdu)->csi_req,
              ((DCI6_0A_10MHz_t *) dci_pdu)->srs_req,
              ((DCI6_0A_10MHz_t *) dci_pdu)->dci_rep,
              ((uint32_t *)dci_pdu)[0]);
      }

      break;

    case 100:
      if (frame_parms->frame_type == TDD) {
        AssertFatal(1==0,"TDD not supported for eMTC yet\n");
      } else {
        dci_alloc->dci_length = sizeof_DCI6_0A_20MHz_t;
        ((DCI6_0A_20MHz_t *) dci_pdu)->type = 0;
        ((DCI6_0A_20MHz_t *) dci_pdu)->hopping = hopping;
        ((DCI6_0A_20MHz_t *) dci_pdu)->rballoc = rballoc;
        ((DCI6_0A_20MHz_t *) dci_pdu)->narrowband = narrowband;
        ((DCI6_0A_20MHz_t *) dci_pdu)->mcs = rel13->mcs;
        ((DCI6_0A_20MHz_t *) dci_pdu)->rep = rel13->pusch_repetition_levels;
        ((DCI6_0A_20MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_0A_20MHz_t *) dci_pdu)->ndi = ndi;
        ((DCI6_0A_20MHz_t *) dci_pdu)->rv_idx = rel13->redudency_version;
        ((DCI6_0A_20MHz_t *) dci_pdu)->TPC = TPC;
        ((DCI6_0A_20MHz_t *) dci_pdu)->csi_req = cqi_req;
        ((DCI6_0A_20MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
        ((DCI6_0A_20MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
      }

      //printf("eNB: rb_alloc (20 MHz dci) %d\n",rballoc);
      break;

    default:
      LOG_E (PHY, "Invalid N_RB_DL %d\n", frame_parms->N_RB_DL);
      DevParam (frame_parms->N_RB_DL, 0, 0);
      break;
  }
}