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

22 23 24 25 26 27 28 29 30 31
/*! \file phy_procedures_lte_eNB.c
 * \brief Implementation of eNB procedures from 36.213 LTE specifications
 * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas, Michele Paffetti, Nick Ho
 * \date 2011
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk, michele.paffetti@studio.unibo.it, nick133371@gmail.com
 * \note
 * \warning
 */
32

33
//#include "PHY/defs.h"
34
#include "PHY/defs_NB_IoT.h"
35
#include "PHY/LTE_ESTIMATION/defs_NB_IoT.h"
36
//#include "PHY/extern_NB_IoT.h" //where we get the global Sched_Rsp_t structure filled
37
//#include "SCHED/defs.h"
38 39 40
#include "SCHED/extern_NB_IoT.h"
//#include "PHY/LTE_TRANSPORT/if4_tools.h"
//#include "PHY/LTE_TRANSPORT/if5_tools.h"
41
#include "RRC/LITE/proto_NB_IoT.h"
42 43 44 45
#include "SIMULATION/TOOLS/defs.h"  // purpose: included for taus() function
//#ifdef EMOS
//#include "SCHED/phy_procedures_emos.h"
//#endif
46

47
// for NB-IoT
48
#include "SCHED/defs_NB_IoT.h"
49

50 51 52
//#define DEBUG_PHY_PROC (Already defined in cmake)
//#define DEBUG_ULSCH

53 54
//#include "LAYER2/MAC/extern.h"
//#include "LAYER2/MAC/defs.h"
55 56 57 58 59 60 61
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

#include "T.h"

#include "assertions.h"
#include "msc.h"
62

63 64 65 66 67 68
#include <time.h>

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

69
/*
70 71 72 73 74 75 76

#if defined(FLEXRAN_AGENT_SB_IF)
//Agent-related headers
#include "ENB_APP/flexran_agent_extern.h"
#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
#endif
77
*/
78 79 80

//#define DIAG_PHY

81
///#define NS_PER_SLOT 500000
82

83
///#define PUCCH 1
84 85 86

//DCI_ALLOC_t dci_alloc[8];

87 88 89
///#ifdef EMOS
///fifo_dump_emos_eNB emos_dump_eNB;
///#endif
90

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
int npdsch_rep_to_array[3]      = {4,8,16}; //TS 36.213 Table 16.4.1.3-3
int sib1_startFrame_to_array[4] = {0,16,32,48};//TS 36.213 Table 16.4.1.3-4

//New----------------------------------------------------
//return -1 whenever no SIB1-NB transmission occur.
//return sib1_startFrame when transmission occur in the current frame
uint32_t is_SIB1_NB_IoT(const frame_t          frameP,
                        long                   schedulingInfoSIB1,   //from the mib
                        int                    physCellId,           //by configuration
                        NB_IoT_eNB_NDLSCH_t   *ndlsch_SIB1
                        )
{
  uint8_t    nb_rep=0; // number of sib1-nb repetitions within the 256 radio frames
  uint32_t   sib1_startFrame;
  uint32_t   sib1_period_NB_IoT = 256;//from specs TS 36.331 (rf)
  uint8_t    index;
  int        offset;
  int        period_nb; // the number of the actual period over the 1024 frames

        if(schedulingInfoSIB1 > 11 || schedulingInfoSIB1 < 0){
          LOG_E(RRC, "is_SIB1_NB_IoT: schedulingInfoSIB1 value not allowed");
          return 0;
        }


        //SIB1-NB period number
        period_nb = (int) frameP/sib1_period_NB_IoT;


        //number of repetitions
        nb_rep = npdsch_rep_to_array[schedulingInfoSIB1%3];

        //based on number of rep. and the physical cell id we derive the starting radio frame (TS 36.213 Table 16.4.1.3-3/4)
        switch(nb_rep)
        {
        case 4:
          //physCellId%4 possible value are 0,1,2,3
          sib1_startFrame = sib1_startFrame_to_array[physCellId%4];
          break;
        case 8:
          //physCellId%2possible value are 0,1
          sib1_startFrame = sib1_startFrame_to_array[physCellId%2];
          break;
        case 16:
          //physCellId%2 possible value are 0,1
          if(physCellId%2 == 0)
            sib1_startFrame = 0;
          else
            sib1_startFrame = 1; // the only case in which the starting frame is odd
          break;
        default:
          LOG_E(RRC, "Number of repetitions %d not allowed", nb_rep);
          return -1;
        }

        //check the actual frame w.r.t SIB1-NB starting frame
        if(frameP < sib1_startFrame + period_nb*256){
          LOG_T(RRC, "the actual frame %d is before the SIB1-NB starting frame %d of the period--> bcch_sdu_legnth = 0", frameP, sib1_startFrame + period_nb*256);
          return -1;
        }


        //calculate offset between SIB1-NB repetitions (repetitions are equally spaced)
        offset = (sib1_period_NB_IoT-(16*nb_rep))/nb_rep;

        //loop over the SIB1-NB period
        for( int i = 0; i < nb_rep; i++)
        {
          //find the correct sib1-nb repetition interval in which the actual frame is

          //this is the start frame of a repetition
          index = sib1_startFrame+ i*(16+offset) + period_nb*256;

          //the actual frame is in a gap between two consecutive repetitions
          if(frameP < index)
          {
              ndlsch_SIB1->sib1_rep_start      = 0;
              ndlsch_SIB1->relative_sib1_frame = 0;
                return -1;
          }
          //this is needed for ndlsch_procedure
          else if(frameP == index)
          {
            //the actual frame is the start of a new repetition (SIB1-NB should be retransmitted)
            ndlsch_SIB1->sib1_rep_start      = 1;
            ndlsch_SIB1->relative_sib1_frame = 1;
            return sib1_startFrame;
          }
          else
            ndlsch_SIB1->sib1_rep_start = 0;

          //check in the current SIB1_NB repetition
          if(frameP>= index && frameP <= (index+15))
          {
            //find if the actual frame is one of the "every other frame in 16 continuous frame" in which SIB1-NB is transmitted

            for(int y = 0; y < 16; y += 2) //every other frame (increment by 2)
            {
              if(frameP == index + y)
              {
                //this flag tell which is the number of the current frame w.r.t the 8th (over the continuous 16) in a repetition
                ndlsch_SIB1->relative_sib1_frame = y/2 + 1; //1st, 2nd, 3rd,...
                return sib1_startFrame;
              }
            }

            //if we are here means that the frame was inside the repetition interval but not considered for SIB1-NB transmission
            ndlsch_SIB1->relative_sib1_frame = 0;
            return -1;
         }

        }

        return -1;
}
206 207


208

209 210 211



212 213 214 215
/* For NB-IoT, we put NPBCH in later part, since it would be scheduled by MAC scheduler
* It generates NRS/NPSS/NSSS
*
*/
216
void common_signal_procedures_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc) 
217
{
218 219 220 221 222 223 224
  NB_IoT_DL_FRAME_PARMS   *fp       =  &eNB->frame_parms_NB_IoT;
  int                     **txdataF =  eNB->common_vars.txdataF[0];
  int                     subframe  =  proc->subframe_tx;
  int                     frame     =  proc->frame_tx;
  uint16_t                Ntti      =  10;                      //ntti = 10
  int                     RB_IoT_ID;                            // XXX should be initialized (RB reserved for NB-IoT, PRB index)
  int                     With_NSSS;                            // With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
  
  /*NSSS only happened in the even frame*/
  if(frame%2==0)
    {
      With_NSSS = 1;
    }
  else
    {
      With_NSSS = 0;
    }
    
  /*NPSS when subframe 5*/
  if(subframe == 5)
    {
      generate_npss_NB_IoT(txdataF,
240 241 242 243 244
                           AMP,
                           fp,
                           3,
                           0,
                           RB_IoT_ID);
245 246 247
    }
    
  /*NSSS when subframe 9 on even frame*/
Nick Ho's avatar
Nick Ho committed
248
  else if((subframe == 9)&&(With_NSSS == 1))
249
    {
Nick Ho's avatar
Nick Ho committed
250
      generate_sss_NB_IoT(txdataF,
251 252 253 254 255 256 257 258
                          AMP,
                          fp,
                          3,
                          0,
                          frame,
                          RB_IoT_ID);
    }

Nick Ho's avatar
Nick Ho committed
259 260 261 262
  else
  {
    /*NRS*/
    generate_pilots_NB_IoT(eNB,
263 264 265 266 267
                           txdataF,
                           AMP,
                           Ntti,
                           RB_IoT_ID,
                           With_NSSS);
Nick Ho's avatar
Nick Ho committed
268
  }
269 270 271
  
}

272
void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc,UL_IND_t *UL_INFO)
273 274
{
  //RX processing for ue-specific resources (i
275

276
  uint32_t                  ret=0,i,j,k;
277
  uint32_t                  harq_pid;   // round;
278 279 280 281
  int                       sync_pos;
  uint16_t                  rnti=0;
  uint8_t                   access_mode;
  NB_IoT_DL_FRAME_PARMS     *fp=&eNB->frame_parms_NB_IoT;
282

283 284
  const int subframe    =   proc->subframe_rx;
  const int frame       =   proc->frame_rx;
285 286

  // add hyper subframe here
287 288 289
  
  /*NB-IoT IF module Common setting*/

290 291 292 293
  UL_INFO->module_id    = eNB->Mod_id;
  UL_INFO->CC_id        = eNB->CC_id;
  UL_INFO->frame        =  frame;
  UL_INFO->subframe     = subframe;
294 295 296 297

  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));

  T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
298 299
    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms_NB_IoT.samples_per_tti],
             eNB->frame_parms_NB_IoT.samples_per_tti * 4));
300 301 302 303

  //if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return;

  //check if any RB using in this UL subframe
304 305 306 307
  eNB->rb_mask_ul[0] = 0;
  eNB->rb_mask_ul[1] = 0;
  eNB->rb_mask_ul[2] = 0;
  eNB->rb_mask_ul[3] = 0;
308 309 310

  // Check for active processes in current subframe
  // NB-IoT subframe2harq_pid is in dci_tools, always set the frame type to FDD, this would become simpler.
311
  harq_pid = subframe2harq_pid_NB_IoT(fp,frame,subframe);
312 313 314
  // delete the cba
  // delete the srs
  /*Loop over the UE, i is the UE ID */
315
  for (i=0; i<NUMBER_OF_UE_MAX_NB_IoT; i++) 
316
    {
317

318 319 320 321 322
      // delete srs 
      // delete Pucch procedure
      // check for Msg3
      if (eNB->mac_enabled==1) 
        {
323
          if (eNB->UE_stats[i].mode == RA_RESPONSE_NB_IoT) 
324 325 326 327 328
            {
	             /*Process Msg3 TODO*/
              //process_Msg3(eNB,proc,i,harq_pid);
            }
        }
329

330
      eNB->pusch_stats_rb[i][(frame*10)+subframe]    = -63;
331
      eNB->pusch_stats_round[i][(frame*10)+subframe] = 0;
332
      eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = -63;
333

334
      /*Check if this UE is has ULSCH scheduling*/
335 336 337
      if ((eNB->nulsch[i]) &&
          (eNB->nulsch[i]->rnti>0) &&
          (eNB->nulsch[i]->harq_process->subframe_scheduling_flag==1)) 
338 339
        {
          // UE is has ULSCH scheduling
340
          //////////////////////////////////////round = eNB->nulsch[i]->harq_process->round; //commented to remove warning, to be added if round is used
341
          /*NB-IoT The nb_rb always set to 1 */
342
          for (int rb=0;rb<=eNB->nulsch[i]->harq_process->nb_rb;rb++) 
343
            {
344 345
	             int rb2 = rb+eNB->nulsch[i]->harq_process->first_rb;
               eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
346
            }
347

348
          /*Log for what kind of the ULSCH Reception*/
349

350 351
          /*Calculate for LTE C-RS*/
          //nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
352

353 354
          //eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +nPRS)%12;

355
          if (fp->frame_type == FDD_NB_IoT ) 
356 357 358
            {
              int sf = (subframe<4) ? (subframe+6) : (subframe-4);
              /*After Downlink Data transmission, simply have a notice to received ACK from PUCCH, I think it's not use for now */
359
              if (eNB->ndlsch[i]->subframe_tx[sf]>0) // we have downlink transmission
360
                { 
361
                  eNB->nulsch[i]->harq_process->O_ACK = 1;
362 363 364
                } 
              else 
                {
365
                  eNB->nulsch[i]->harq_process->O_ACK = 0;
366 367
                }
            }
368

369
          eNB->pusch_stats_rb[i][(frame*10)+subframe]    = eNB->nulsch[i]->harq_process->nb_rb;
370
          eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->nulsch[i]->harq_process->round;
371
          eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = eNB->nulsch[i]->harq_process->mcs;
372

373 374 375 376 377 378 379 380
  

          rx_ulsch_NB_IoT(eNB,proc,
                          eNB->UE_stats[i].sector,  // this is the effective sector id
                          i,
                          eNB->nulsch,
                          0);

381
          ret = ulsch_decoding_NB_IoT(eNB,proc,
382 383 384 385
                                      i,
                                      0, // control_only_flag
                                      eNB->nulsch[i]->harq_process->V_UL_DAI,
			                                eNB->nulsch[i]->harq_process->nb_rb>20 ? 1 : 0);
386

387
          //compute the expected ULSCH RX power (for the stats)
388 389 390
          eNB->nulsch[(uint32_t)i]->harq_process->delta_TF = get_hundred_times_delta_IF_eNB_NB_IoT(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered
          eNB->UE_stats[i].nulsch_decoding_attempts[harq_pid][eNB->nulsch[i]->harq_process->round]++;
          eNB->nulsch[i]->harq_process->subframe_scheduling_flag=0;
391 392
          if (eNB->nulsch[i]->harq_process->cqi_crc_status == 1) {

393 394 395 396 397
              extract_CQI_NB_IoT(eNB->nulsch[i]->harq_process->o,
                                 eNB->nulsch[i]->harq_process->uci_format,
                                 &eNB->UE_stats[i],
                                 fp->N_RB_DL,
                                 &rnti, &access_mode);
398
            
399
              eNB->UE_stats[i].rank = eNB->nulsch[i]->harq_process->o_RI[0];
400
          }
401

402 403 404 405 406 407 408 409
          if (ret == (1+MAX_TURBO_ITERATIONS)) {

              T(T_ENB_PHY_ULSCH_UE_NACK,
                T_INT(eNB->Mod_id),
                T_INT(frame),
                T_INT(subframe),
                T_INT(i),
                T_INT(eNB->nulsch[i]->rnti),
410
                T_INT(harq_pid));
411

412 413 414 415
              eNB->UE_stats[i].ulsch_round_errors[harq_pid][eNB->nulsch[i]->harq_process->round]++;
              eNB->nulsch[i]->harq_process->phich_active = 1;
              eNB->nulsch[i]->harq_process->phich_ACK = 0;
              eNB->nulsch[i]->harq_process->round++;
416

417
              LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,eNB->nulsch[i]->harq_process->round);
418

419 420 421
          if (eNB->nulsch[i]->Msg3_flag == 1) 
          {
	             /*dump_ulsch(eNB,proc,i);
422 423
	             exit(-1);*/

424 425 426 427 428 429 430 431 432 433 434
               /*In NB-IoT MSG3 */
                // activate retransmission for Msg3 (signalled to UE PHY by DCI
                eNB->nulsch[(uint32_t)i]->Msg3_active = 1;
                /* Need to check the procedure for NB-IoT (MSG3) retransmission
                get_Msg3_alloc_ret(fp,subframe,frame,&eNB->ulsch[i]->Msg3_frame,&eNB->ulsch[i]->Msg3_subframe);
                mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, eNB->ulsch[i]->rnti,eNB->ulsch[i]->Msg3_frame, eNB->ulsch[i]->Msg3_subframe);
                */
                T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
                  T_INT(i), T_INT(eNB->nulsch[i]->rnti), T_INT(0 /* 0 is for retransmission*/),
                  T_INT(eNB->nulsch[i]->Msg3_frame), T_INT(eNB->nulsch[i]->Msg3_subframe));     
          } // This is Msg3 error
435
          else 
436 437
          { //normal ULSCH
              if (eNB->nulsch[i]->harq_process->round== eNB->nulsch[i]->Mlimit) 
438
                {
439 440
                  eNB->nulsch[i]->harq_process->round=0;
                  eNB->nulsch[i]->harq_process->phich_active=0;
441
                  eNB->UE_stats[i].ulsch_errors[harq_pid]++;
442 443 444
                  eNB->UE_stats[i].ulsch_consecutive_errors++; 
                  /*if (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb > 20) {
		                dump_ulsch(eNB,proc,i);
445
	 	              exit(-1);
446 447 448
                  }*/
	                // indicate error to MAC
	                if (eNB->mac_enabled == 1)
449
                    {
450
                      //instead rx_sdu to report The Uplink data not received successfully to MAC
451
                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag = 1;
Nick Ho's avatar
Nick Ho committed
452
                       UL_INFO->crc_ind.number_of_crcs++;
453 454 455 456
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.rnti      = eNB->nulsch[i]->rnti;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->data                        = NULL;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_indication_rel8.length   = 0;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.harq_pid  = harq_pid;
Nick Ho's avatar
Nick Ho committed
457
                       UL_INFO->RX_NPUSCH.number_of_pdus++;
458
                    }
459 460 461 462 463
                }
            }
        }  // ulsch in error
        else 
          {
464
            T(T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(eNB->nulsch[i]->rnti),
465
              T_INT(harq_pid));
466

467
          // Delete MSG3  log for the PHICH 
468

469
          for (j=0; j<fp->nb_antennas_rx; j++)
470 471
          //this is the RSSI per RB
          eNB->UE_stats[i].UL_rssi[j] =
472
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j] * (eNB->nulsch[i]->harq_process->nb_rb*12) / fp->ofdm_symbol_size) - eNB->rx_total_gain_dB -
473
            hundred_times_log10_NPRB_NB_IoT[eNB->nulsch[i]->harq_process->nb_rb-1]/100 -
474
            get_hundred_times_delta_IF_eNB_NB_IoT(eNB,i,harq_pid, 0)/100;
475 476 477
          //for NB-IoT PHICH not work
	        /*eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
          eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 1;*/
478
          eNB->nulsch[i]->harq_process->round = 0;
479
          eNB->UE_stats[i].ulsch_consecutive_errors = 0;
480

481
          if (eNB->nulsch[i]->Msg3_flag == 1) 
482
            {
483 484 485 486 487 488 489
	            if (eNB->mac_enabled==1) 
                {
	                LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
		                    eNB->Mod_id,frame,harq_pid,i);
	                if (eNB->mac_enabled)
                    {
                      // store successful MSG3 in UL_Info instead rx_sdu
490
                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
Nick Ho's avatar
Nick Ho committed
491
                      UL_INFO->crc_ind.number_of_crcs++;
492 493 494 495
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.rnti       = eNB->nulsch[i]->rnti;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->data                         = eNB->nulsch[i]->harq_process->b;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_indication_rel8.length    = eNB->nulsch[i]->harq_process->TBS>>3;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.harq_pid   = harq_pid;
Nick Ho's avatar
Nick Ho committed
496
                      UL_INFO->RX_NPUSCH.number_of_pdus++;
497
                    }
498

499 500 501 502 503 504 505 506 507 508 509
	                /* Need check if this needed in NB-IoT
	                // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
	                if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	               eNB->UE_stats[i].mode = PRACH;
	               mac_xface->cancel_ra_proc(eNB->Mod_id,
					       eNB->CC_id,
					       frame,
					       eNB->UE_stats[i].crnti);
	               mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
	               eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
	               } // Msg3_flag == 0*/
510
	    
511 512
	            } // mac_enabled==1

513
            eNB->UE_stats[i].mode     = PUSCH;
514
            eNB->nulsch[i]->Msg3_flag = 0;
515 516 517 518 519 520

	          LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",eNB->Mod_id,frame,subframe,i);

            /*Init HARQ parameters, need to check*/
            for (k=0; k<8; k++) 
              { //harq_processes
521
                for (j=0; j<eNB->ndlsch[i]->Mlimit; j++) 
522
                  {
523 524 525
                    eNB->UE_stats[i].dlsch_NAK[k][j]    = 0;
                    eNB->UE_stats[i].dlsch_ACK[k][j]    = 0;
                    eNB->UE_stats[i].dlsch_trials[k][j] = 0;
526 527
                  }

528 529 530
                eNB->UE_stats[i].dlsch_l2_errors[k]       = 0;
                eNB->UE_stats[i].ulsch_errors[k]          = 0;
                eNB->UE_stats[i].ulsch_consecutive_errors = 0;
531

532
                for (j=0; j<eNB->nulsch[i]->Mlimit; j++) 
533
                  {
534 535 536 537
                    eNB->UE_stats[i].nulsch_decoding_attempts[k][j]     = 0;
                    eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j] = 0;
                    eNB->UE_stats[i].ulsch_round_errors[k][j]           = 0;
                    eNB->UE_stats[i].ulsch_round_fer[k][j]              = 0;
538 539
                  }
              }
540

541 542 543
            eNB->UE_stats[i].dlsch_sliding_cnt  = 0;
            eNB->UE_stats[i].dlsch_NAK_round0   = 0;
            eNB->UE_stats[i].dlsch_mcs_offset   = 0;
544 545 546
          } // Msg3_flag==1
	       else 
          {  // Msg3_flag == 0
547
	          if (eNB->mac_enabled == 1) 
548 549
              {
                  // store successful Uplink data in UL_Info instead rx_sdu
550
                  (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
Nick Ho's avatar
Nick Ho committed
551
                  UL_INFO->crc_ind.number_of_crcs++;
552 553 554 555
                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.rnti       = eNB->nulsch[i]->rnti;
                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->data                         = eNB->nulsch[i]->harq_process->b;
                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_indication_rel8.length    = eNB->nulsch[i]->harq_process->TBS>>3;
                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.harq_pid   = harq_pid;
Nick Ho's avatar
Nick Ho committed
556
                  UL_INFO->RX_NPUSCH.number_of_pdus++;
557
	    
558 559
	            } // mac_enabled==1
          } // Msg3_flag == 0
560

561
            // estimate timing advance for MAC
562
              sync_pos                               = NB_IoT_est_timing_advance_pusch(eNB,i);
563 564 565 566
              eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check

      }  // ulsch not in error

567

568
      // Process HARQ only in NPUSCH
Nick Ho's avatar
Nick Ho committed
569
      /*process_HARQ_feedback(i,
570 571 572 573
                            eNB,proc,
                            1, // pusch_flag
                            0,
                            0,
Nick Ho's avatar
Nick Ho committed
574
                            0);*/
575

576

577 578
      

579
    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
Nick Ho's avatar
Nick Ho committed
580

581 582 583 584 585 586

    // update ULSCH statistics for tracing




587
  } // loop i=0 ... NUMBER_OF_UE_MAX-1
588 589 590 591 592

}

#undef DEBUG_PHY_PROC

593
/*Generate eNB ndlsch params for NB-IoT from the NPDCCH PDU of the DCI, modify the input to the Sched Rsp variable*/
Nick Ho's avatar
Nick Ho committed
594

595
void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t * proc,nfapi_dl_config_request_pdu_t *dl_config_pdu) 
Nick Ho's avatar
Nick Ho committed
596
{
597 598 599 600 601 602 603 604
  int                      UE_id         =  -1;
  NB_IoT_DL_FRAME_PARMS    *fp           =  &eNB->frame_parms_NB_IoT;
  int                      frame         =  proc->frame_tx;
  int                      subframe      =  proc->subframe_tx;
  DCI_CONTENT              *DCI_Content; 
  DCI_format_NB_IoT_t      DCI_format;
  NB_IoT_eNB_NDLSCH_t      *ndlsch;
  NB_IoT_eNB_NPDCCH_t      *npdcch;
605

Nick Ho's avatar
Nick Ho committed
606

607

608 609
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));

610
  // check DCI format is N1 (format 0)
611 612
  if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0)
    {
613
      //check DCI format N1 is for RAR  rnti_type  in FAPI specs table 4-45
614
      if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type == 1)
615
        {
616

617 618 619
    	  //mapping the fapi parameters to the oai parameters

          DCI_format = DCIFormatN1_RAR;
620 621 622 623 624 625 626

          //DCI format N1 to RAR
          DCI_Content->DCIN1_RAR.type           = 1;
          DCI_Content->DCIN1_RAR.orderIndicator = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication;
          DCI_Content->DCIN1_RAR.Scheddly       = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay;
          DCI_Content->DCIN1_RAR.ResAssign      = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment;
          DCI_Content->DCIN1_RAR.mcs            = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs;
627
          DCI_Content->DCIN1_RAR.RepNum			    = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
628 629 630 631
          DCI_Content->DCIN1_RAR.ndi            = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator;
          DCI_Content->DCIN1_RAR.HARQackRes     = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource;
          DCI_Content->DCIN1_RAR.DCIRep         = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number;

632 633
          //TODO calculate the number of common repetitions
          //fp->nprach_config_common.number_repetition_RA = see TS 36.213 Table 16.1-3
634

635
          // fill the dlsch_ra_NB structure for RAR, and packed the DCI PDU
636

637 638
          ndlsch               =  eNB->ndlsch_ra;
          ndlsch->ndlsch_type  =  RAR;
639 640

          LOG_D(PHY,"Generating dlsch params for RA_RNTI and packing DCI\n");
641 642 643 644 645 646 647 648 649 650
          generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
                                                    frame,
                                                    subframe,
                                                    DCI_Content,
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
                                                    DCI_format,
                                                    ndlsch,
                                                    fp,
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
												                            dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol);
651 652

          //eNB->dlsch_ra_NB->nCCE[subframe] = eNB->DCI_pdu->dci_alloc.firstCCE;
653
        }
654
      else
655 656 657
        { //managing data

    	  //TODO target/SIMU/USER?init_lte/init_lte_eNB we should allocate the ndlsch structures
658
    	  UE_id = find_ue_NB_IoT(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti, eNB);
659
    	  AssertFatal(UE_id != -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
660

661

662
    	  	  //mapping the fapi parameters to the oai parameters
663 664

    	  	  DCI_format = DCIFormatN1;
665

666 667 668 669 670 671
              //DCI format N1 to DLSCH
              DCI_Content->DCIN1.type           = 1;
              DCI_Content->DCIN1.orderIndicator = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication;
              DCI_Content->DCIN1.Scheddly       = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay;
              DCI_Content->DCIN1.ResAssign      = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment;
              DCI_Content->DCIN1.mcs            = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs;
672
              DCI_Content->DCIN1.RepNum			    = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
673 674 675 676
              DCI_Content->DCIN1.ndi            = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator;
              DCI_Content->DCIN1.HARQackRes     = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource;
              DCI_Content->DCIN1.DCIRep         = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number;

677 678 679 680 681 682 683 684 685 686 687 688 689 690

              //set the NPDCCH UE-specific structure  (calculate R)
              npdcch=eNB->npdcch[(uint8_t)UE_id];
              AssertFatal(npdcch != NULL, "NPDCCH structure for UE specific is not exist\n");
              npdcch->repetition_idx = 0; //this is used for the encoding mechanism to understand that is the first transmission

              if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level) //whenever aggregation level is =1 we have only 1 repetition for USS
              npdcch->repetition_number = 1;
              else
              {
            	  //see TS 36.213 Table 16.1-1
              }


691 692 693 694 695
              //fill the ndlsch structure for UE and packed the DCI PD

        	  ndlsch = eNB->ndlsch[(uint8_t)UE_id]; //in the old implementation they also consider UE_id = 1;
        	  ndlsch->ndlsch_type = UE_Data;

696
              //parameters we don't consider pdsch config dedicated since not calling the phy config dedicated step2
697 698

        	  LOG_D(PHY,"Generating dlsch params for DCIN1 data and packing DCI\n");
699 700 701 702 703 704 705 706 707 708
            generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
                                                      frame,
                                                      subframe,
                                                      DCI_Content,
                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
                                                      DCI_format,
                                                      ndlsch,
                                                      fp,
                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
													                            dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol); 
709 710

              //eNB->ndlsch[(uint8_t)UE_id]->nCCE[subframe] = eNB->DCI_pdu->dci_alloc[i].firstCCE;
711 712


713 714 715 716 717 718 719 720 721
        }
    }
  else if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 1)
    { 
      DCI_format = DCIFormatN2;
      LOG_D(PHY,"Paging procedure not implemented\n");
    }
  else
    LOG_E(PHY,"unknown DCI format for NB-IoT DL\n");
Nick Ho's avatar
Nick Ho committed
722 723 724 725 726 727


}



728
void generate_eNB_ulsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc,nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu) {
729

730
  int UE_id = -1;
731
  //int harq_pid = 0;
Nick Ho's avatar
Nick Ho committed
732

733 734
  DCI_CONTENT *DCI_Content;
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
735 736

  //mapping the fapi parameters to the OAI parameters
737 738 739 740 741 742 743 744 745
  DCI_Content->DCIN0.type       = 0;
  DCI_Content->DCIN0.scind      = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.subcarrier_indication;
  DCI_Content->DCIN0.ResAssign  = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.subcarrier_indication;
  DCI_Content->DCIN0.mcs        = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.mcs;
  DCI_Content->DCIN0.ndi        = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.new_data_indicator;
  DCI_Content->DCIN0.Scheddly   = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.scheduling_delay;
  DCI_Content->DCIN0.RepNum     = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.repetition_number;
  DCI_Content->DCIN0.rv         = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.redudancy_version;
  DCI_Content->DCIN0.DCIRep     = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.dci_subframe_repetition_number;
746 747


748

749
  UE_id = find_ue_NB_IoT(hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti, eNB);
750
  AssertFatal(UE_id == -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
751 752


Nick Ho's avatar
Nick Ho committed
753 754
  /*Log for generate ULSCH DCI*/

755 756 757 758 759 760 761 762
  generate_eNB_ulsch_params_from_dci_NB_IoT(eNB,
                                            proc,
                                            DCI_Content,
                                            hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti,
                                            DCIFormatN0,
                                            UE_id,
                                            hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.aggregation_level,
										                        hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.start_symbol);  
763

Nick Ho's avatar
Nick Ho committed
764 765
  
  //LOG for ULSCH DCI Resource allocation
766
  //CBA is not used in NB-IoT
767
    eNB->nulsch[UE_id]->harq_process->subframe_scheduling_flag = 1;
Nick Ho's avatar
Nick Ho committed
768 769 770
  
}

771 772


773 774 775
/*
 * for NB-IoT ndlsch procedure
 * this function is called by the PHy procedure TX in 3 possible occasion:
776
 * 1) we manage BCCH pdu (SI)
777 778
 * 2) we manage RA dlsch pdu
 * 3) UE-specific dlsch pdu
779 780 781 782
 * ** we need to know if exist and which value has the eutracontrolRegionSize (TS 36.213 ch 16.4.1.4) whenever we are in In-band mode
 * ** CQI and PMI are not present in NB-IoT
 * ** redundancy version exist only in UL for NB-IoT and not in DL
 */
783
void npdsch_procedures(PHY_VARS_eNB_NB_IoT      *eNB,
784
						           eNB_rxtx_proc_t   *proc,     //Context data structure for RX/TX portion of subframe processing
785 786 787 788
						           NB_IoT_eNB_NDLSCH_t      *ndlsch,
						           //int num_pdcch_symbols,            //(BCOM says are not needed
						           uint8_t                  *pdu
									     )
789
{
790 791 792 793 794 795 796 797
  int                     frame                   =   proc->frame_tx;
  int                     subframe                =   proc->subframe_tx;
  NB_IoT_DL_eNB_HARQ_t    *ndlsch_harq            =   ndlsch->harq_process;
  int                     input_buffer_length     =   ndlsch_harq->TBS/8;         // get in byte //the TBS is set in generate_dlsch_param
  NB_IoT_DL_FRAME_PARMS   *fp                     =   &eNB->frame_parms_NB_IoT;
  int                     G;
  uint8_t                 *DLSCH_pdu              =   NULL;
  uint8_t                 DLSCH_pdu_tmp[input_buffer_length+4];                   //[768*8];
798
  //uint8_t DLSCH_pdu_rar[256];
799
  int                     i;
800 801

  LOG_D(PHY,
802 803 804 805 806 807 808
	      "[eNB %"PRIu8"][PDSCH rnti%"PRIx16"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", mcs %"PRIu8"(round %"PRIu8")\n",
	      eNB->Mod_id,
	      ndlsch->rnti,
	      frame, subframe, input_buffer_length,
	      ndlsch_harq->mcs,
	      ndlsch_harq->round
        );
809

810
  if(ndlsch_harq->round == 0) { //first transmission so we encode... because we generate the sequence
811

812
    if (eNB->mac_enabled == 1) { // set in lte-softmodem/main line 1646
813

814
    	  DLSCH_pdu = pdu;
815 816 817 818

  	  /*
  	   * we don't need to manage the RAR here since should be managed in the MAC layer for two reasons:
  	   * 1)we should receive directly the pdu containing the RAR from the MAC in the schedule_response
819
  	   * 2)all the parameters for getting the MSG3 should be given by the UL_CONFIG.request (all inside the next schedule_response function)
820 821 822 823 824 825 826 827 828 829 830
  	   *
  	   */

    	  //fill_rar shouduld be in the MAC
    	  //cancel ra procedure should be in the mac
    	  //scheduling request not implemented in NB-IoT
    	  //nulsch_param configuration for MSG3 should be considered in handling UL_Config.request
    	  //(in particular the nulsch structure for RAR is distinguished based on the harq_process->rar_alloc and the particular subframe in which we should have Msg3)
    }

    else {  //XXX we should change taus function???
831

832
      DLSCH_pdu = DLSCH_pdu_tmp;
833

834
      for (i=0; i<input_buffer_length; i++)
835 836

	       DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
837 838 839 840
    }
  }
  else {
	  //We are doing a retransmission (harq round > 0
841 842
    #ifdef DEBUG_PHY_PROC
    #ifdef DEBUG_DLSCH
843
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
844 845
    #endif
    #endif
846 847 848 849 850
  }

  if (eNB->abstraction_flag==0) { // used for simulation of the PHY??


851 852 853 854 855 856 857 858 859 860 861 862 863 864
	  //we can distinguish among the different kind of NDLSCH structure (example)
	  switch(ndlsch->ndlsch_type)
	  {
	  case SIB1:
		  break;
	  case SI_Message:
		  break;
	  case RAR: //maybe not needed
		  break;
	  case UE_Data: //maybe not needed
		  break;
	  }


865 866 867 868 869 870 871 872 873 874 875 876 877 878
	 /*
	  * in any case inside the encoding procedure is re-checked if this is round 0 or no
	  * in the case of harq_process round = 0 --> generate the sequence and put it into the parameter *c[r]
	  * otherwise do nothing(only rate maching)
	  */


	/*
	 * REASONING:
	 * Encoding procedure will generate a Table with encoded data ( in ndlsch structure)
	 * The table will go in input to the scrambling
	 * --we should take care if there are repetitions of data or not because scrambling should be called at the first frame and subframe in which each repetition
	 * begin (see params Nf, Ns)
	 */
879 880 881 882 883 884


    // 36-212
    //encoding---------------------------

    /*
885 886 887 888 889 890 891 892
     *
     * REASONING:
	 * Encoding procedure will generate a Table with encoded data ( in ndlsch structure)
	 * The table will go in input to the scrambling
	 * --we should take care if there are repetitions of data or not because scrambling should be called at the first frame and subframe in which each repetition
	 * 	begin (see params Nf, Ns)
     *
     * we should have as an iput parameter also G for the encoding based on the switch/case over eutracontrolRegionSize (if exist) and operationModeInfo if defined
893 894
     * NB: switch case of G is the same for npdsch and npdcch
     *
895 896 897 898 899 900 901 902
     * npdsch_start symbol index
     * -refers to TS 36.213 ch 16.4.1.4:
     * -if subframe k is a subframe for receiving the SIB1-NB
     *	-- if operationModeInfo set to 00 or 01 (in band) --> npdsch_start_sysmbol = 3
     *	-- otherwise --> npdsch_start_symbol = 0
     * -if the k subframe is not for SIB1-NB
     *	--npdsch_start_symbol = eutracontrolregionsize (defined for in-band operating mode (mode 0,1 for FAPI specs) and take values 1,2,3 [units in number of OFDM symbol])
     * - otherwise --> npdsch_start_symbol = 0
903
     * (is the starting OFDM for the NPDSCH transmission in the first slot in a subframe k)
904 905
     * FAPI style:
     * npdsch_start symbol is stored in the ndlsch structure from the reception of the NPDLSCH PDU in the DL_CONFIG.request (so should be set by the MAC and put inside the schedule response)
906 907 908 909 910 911 912
     * Nsf needed as an input (number of subframe)-->inside harq_process of ndlsch
     */

    switch(ndlsch->npdsch_start_symbol)
    {
  	  case 0:
  		  G = 304;
913
	 	  break;
914 915
  	  case 1:
  		  G = 240;
916
  		break;
917 918
  	  case 2:
  		  G = 224;
919
  		break;
920 921
  	  case 3:
  		  G =200;
922
  		break;
923 924
  	  default:
  		  LOG_E (PHY,"npdsch_start_index has unwanted value\n");
925
  		break;
926 927

    }
928
    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
929 930
    LOG_I(PHY, "NB-IoT Encoding step\n");

931 932 933 934 935 936 937 938
    //    eNB->te(eNB,
    //	    DLSCH_pdu,
    //	    num_pdcch_symbols,
    //	    dlsch,
    //	    frame,subframe,
    //	    &eNB->dlsch_rate_matching_stats,
    //	    &eNB->dlsch_turbo_encoding_stats,
    //	    &eNB->dlsch_interleaving_stats);
939 940


941
   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
942 943 944 945

    // 36-211
    //scrambling-------------------------------------------

946
   // start_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
947 948
    LOG_I(PHY, "NB-IoT Scrambling step\n");

949 950 951 952 953 954
    /*
     * SOME RELEVANT FACTS:
     *
     *
     */

955 956 957 958 959 960 961 962 963 964 965 966 967
      //    dlsch_scrambling(fp,
      //		     0,
      //		     dlsch,
      //		     get_G(fp,
      //			   dlsch_harq->nb_rb,
      //			   dlsch_harq->rb_alloc,
      //			   get_Qm(dlsch_harq->mcs),
      //			   dlsch_harq->Nl,
      //			   num_pdcch_symbols,
      //			   frame,subframe,
      //			   0),
      //		     0,
      //		     subframe<<1);
968

969
    //stop_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
970 971 972


    //modulation-------------------------------------------
973
    //start_meas_NB_IoT(&eNB->dlsch_modulation_stats);
974 975
    LOG_I(PHY, "NB-IoT Modulation step\n");

976 977 978 979 980 981 982
    //    dlsch_modulation(eNB,
    //		     eNB->common_vars.txdataF[0],
    //		     AMP,
    //		     subframe,
    //		     num_pdcch_symbols,
    //		     dlsch,
    //		     dlsch1);
983

984
    //stop_meas_NB_IoT(&eNB->dlsch_modulation_stats);
985 986 987 988 989
  }


#ifdef PHY_ABSTRACTION
  else {
990
    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
991 992 993
    //dlsch_encoding_emul(eNB,
			//DLSCH_pdu,
			//dlsch);
994
   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
995 996 997 998 999
  }

#endif
  ndlsch->active = 0;
}
1000 1001


1002
extern int oai_exit;
1003 1004

/*
1005
 * ASSUMPTION
1006 1007 1008
 *
 * The MAC schedule the schedule_response in a SUBFRAME BASE (at least because otherwise we have problem with our assumptions on SI transmission)
 *
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
 *Since in FAPI specs seems to not manage the information for the sceduling of system information:
 * Assume that the MAC layer manage the scheduling for the System information (SI messages) transmission while MIB and SIB1 are done directly at PHY layer
 * This means that the MAC scheduler will send to the PHY the NDLSCH PDU and MIB PDU (DL_CONFIG.request)each time they should be transmitted. In particular:
 ***MIB-NB
 *schedule_response containing a n-BCH PDU is transmitted only at the beginning of the MIB period, then repetitions are made directly by the PHY layer (see FAPI specs pag 94 N-BCH 3.2.4.2)
 *if no new N-BCH PDU is trasmitted at SFN mod 64=0 then stop MIB transmission
 ***SIB1-NB
 *schedule response containing a NDLSCH pdu (with appropiate configuration) will be transmitted only at the beginning of each SIB1-NB period (256 rf)
 *then repetitions are managed directly by the PHY layer
 *if no new NDLSCH pdu (configured for SIB1-NB) at SFN mod 256 = 0 is transmitted. stop SIB1-NB transmission
 ****SI Messages
 * -schedule_response is transmitted by the MAC in every subframe needed for the SI transmission (NDLSCH should have a proper configuration)
1021
 * -if the schedule_response carry any SDU for SI-Message (SDU!= NULL)--> put the SDU in the PHY buffer to be encoded ecc... and start the transmission
1022 1023
 * -if the schedule_response not carry any SDU (SDU == NULL) but NDLSCH is properly set for SI, then PHY continue transmit the remaining part of the previous SDU
 * (this because the PHY layer have no logic of repetition_pattern, si_window ecc.. so should be continuously instructed the PHY when to transmit.
1024
 *
1025 1026 1027 1028
 * Furthermore, SI messages are transmitted in more that 1 subframe (2 or 8) and therefore MAC layer need to count how many subframes are available in the current frame for transmit it
 * and take in consideration that other frames are needed before starting the transmission of a new one)
 *
 *
1029
 *We assume that whenever the NDLSCH pdu is a BCCH type, we consider as if it's a SIB1 while in other case can be data or SI-message depending on the RNTI
1030 1031 1032
 *
 * **relevant aspects for the System information Transmission (Table 4-47 NDLSCH FAPi specs)
 * 1)RNTI type = 0 (contains a BCCH)
1033 1034
 * 2)Repetition number == scheduling info SIB1 mapped into 4-8-16
 * 3)RNTI (0xFFFF = SI-RNTI)
1035 1036 1037
 * (see schedule_response implementation)
 *
 */
1038 1039 1040 1041 1042 1043 1044

/*
 * This function is triggered by the schedule_response
 * (the frequency at which is transmitted to the PHY depends on the MAC scheduler implementation)
 * (in OAI in principle is every subframe)
 */

1045
void phy_procedures_eNB_TX_NB_IoT(PHY_VARS_eNB_NB_IoT     *eNB,
1046
         	 	 	 	 	                eNB_rxtx_proc_t  *proc,
1047
							                    int                     do_meas)
1048
{
1049 1050 1051 1052 1053 1054 1055 1056
  int                    frame           = proc->frame_tx;
  int                    subframe        = proc->subframe_tx;
  uint32_t               aa;
  DCI_PDU_NB_IoT         *dci_pdu        = eNB->DCI_pdu;
  NB_IoT_DL_FRAME_PARMS  *fp             = &eNB->frame_parms_NB_IoT;
  int8_t                 UE_id           = 0;
  int                    **txdataF       = eNB->common_vars.txdataF[0];
  uint32_t               sib1_startFrame = -1;
1057
  //NB_IoT_eNB_NPDCCH_t*npdcch;
1058

1059
  if(do_meas == 1)
1060
    //start_meas_NB_IoT(&eNB->phy_proc_tx);
1061 1062


1063
  /*the original scheduler "eNB_dlsch_ulsch_scheduler" now is no more done here but is triggered directly from UL_Indication (IF-Module Function)*/
1064

1065
  // clear the transmit data array for the current subframe
1066 1067 1068 1069 1070 1071
  for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) 
    {      
      memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
                  0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
    } 

1072
  //generate NPSS/NSSS
1073
  common_signal_procedures_NB_IoT(eNB,proc);
1074

1075
    //Generate MIB
1076
    if(subframe ==0 && (eNB->npbch != NULL))
1077 1078
     {
          if(eNB->npbch->pdu != NULL)
1079 1080
          {
        	  //BCOM function
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
        	  /*
        	   * -the function get the MIB pdu and schedule the transmission over the 64 radio frame
        	   * -need to check the subframe #0 (since encoding functions only check the frame)
        	   * this functions should be called every frame (the function will transmit the remaining part of MIB)
        	   * ( XXX Should check when the schedule_responce is transmitted by MAC scheduler)
        	   * RB-ID only for the case of in-band operation but should be always considered
        	   * (in stand alone i can put whatever the number)in other case consider the PRB index in the Table R&Shwartz pag 9
        	   *
        	   */

1091 1092 1093 1094 1095 1096 1097
    		    generate_npbch(eNB->npbch,
                           txdataF,
                           AMP,
                           fp,
						               eNB->npbch->pdu,
                           frame%64,
                           fp->NB_IoT_RB_ID);
1098
                        
1099 1100 1101 1102 1103
          }

          //In the last frame in which the MIB-NB should be transmitted after we point to NULL since maybe we stop MIB trasnmission
          //this should be in line with FAPI specs pag 94 (BCH procedure in Downlink 3.2.4.2 for NB-IoT)
          if(frame%64 == 63)
1104
          {
1105
        	  eNB->npbch->pdu = NULL;
1106
          }
1107
      }
Nick Ho's avatar
Nick Ho committed
1108

1109

1110
    //Check for SIB1-NB transmission
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
    /*
     *
     * the function should be called for each frame
     * Parameters needed:
     * -sib1-NB pdu if new one (should be given by the MAC at the start of each SIB1-NB period)
     * -when start a new SIB1-NB repetition (sib1_rep_start)
     * -the frame number relative to the 16 continuous frame within a repetition (relative_sib1_frame) 1st, 2nd ...
     *
     * we check that the transmission should occurr in subframe #4
     *
     * consider that if at the start of the new SIB1-NB period the MAC will not send an NPDSCH for the SIB1-NB transmission then SIB1-NB will be not transmitted (pdu = NULL)
     *
     */
1124
    if(subframe == 4 && eNB->ndlsch_SIB1 != NULL && eNB->ndlsch_SIB1->harq_process->status == ACTIVE_NB_IoT)
1125
    {
1126
      //check if current frame is for SIB1-NB transmission (if yes get the starting frame of SIB1-NB) and set the flag for the encoding
1127 1128 1129 1130
      sib1_startFrame = is_SIB1_NB_IoT(frame,
    		  	  	  	  	  	           (long)eNB->ndlsch_SIB1->harq_process->repetition_number,
								                       fp->Nid_cell,
								                       eNB->ndlsch_SIB1); //set the flags
1131
								                   
1132 1133
  	  if(sib1_startFrame != -1 && eNB->ndlsch_SIB1->harq_process->pdu != NULL)
  	  {
1134 1135 1136 1137
    	   npdsch_procedures(eNB,
          				         proc,
					                 eNB->ndlsch_SIB1, //since we have no DCI for system information, this is filled directly when we receive the NDLSCH pdu from DL_CONFIG.request message
					                 eNB->ndlsch_SIB1->harq_process->pdu);
1138
  	  }
1139

1140
  	  //at the end of the period we put the PDU to NULL since we have to wait for the new one from the MAC for starting the next SIB1-NB transmission
1141
  	  if((frame-sib1_startFrame)%256 == 255)
1142
  	  {
1143 1144 1145
  		    //whenever we will not receive a new sdu from MAC at the start of the next SIB1-NB period we prevent future SIB1-NB transmission (may just only of the two condition is necessary)
  		    eNB->ndlsch_SIB1->harq_process->status = DISABLED;
  		    eNB->ndlsch_SIB1->harq_process->pdu = NULL;
1146
  	  }
1147

1148
    }
1149

1150 1151

    //Check for SI transmission
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
    /*
     *Parameters needed:
     * -total number of subframes for the transmission (2-8) (inside the NDLSCH structure --> HARQ process -->resource_assignment)
     * XXX: in reality this flag is not needed because is enough to check if the PDU is NULL (continue the transmission) or not (new SI transmission)
     * -SI_start (inside ndlsch structure): flag for indicate the starting of the SI transmission within the SI window (new PDU is received by the MAC) otherwise the PHY continue to transmit
     *  what have in its buffer (so check the remaining encoded data continuously)
     *
     * SI transmission should not occurr in reserved subframes
     * subframe = 0 (MIB-NB)
     * subframe = 4 (SIB1-NB) but depends on the frame
     * subframe = 5 (NPSS)
     * subframe = 9 (NSSS) but depends on the frame (if is even)
     *
1165 1166
     * [This condition should be known by the MAC layer so it should trigger an DLSCH pdu only at proper instants]
     *
1167 1168 1169 1170
     * XXX Important: in the case the SI-window finish the PHY layer should have also being able to conclude all the SI transmission in time
     * (because this is managed by the MAC layer that stops transmitting the SDU to PHY in advance because is counting the remaining subframe for the transmission)
     *
     *
1171
     *XXX important: set the flag HARQ process->status to DISABLE when PHY finished the SI-transmission over the 2 or 8 subframes
1172 1173 1174
     *XXX important: whenever we enter for some error in the ndlsch_procedure with a pdu that is NULL but all the data of the SI have been transmitted (pdu_buffer_index = 0)
     *XXX  --> generate error
     *XXX: the npdlsch_procedure in this case should be only called when is triggered by the MAC schedule_response (use the status flag set by the schedule_response)
1175
     *
1176
     */
1177

1178
	if(eNB->ndlsch_SI->harq_process->status == ACTIVE_NB_IoT && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4)) //condition on SIB1-NB
1179 1180
	{
	    if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
1181
	    {
1182 1183 1184 1185
	      if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5 && subframe != 9)
	       {
    		  //check if the PDU != NULL will be done inside just for understanding if a new SI message need to be transmitted or not
    		  npdsch_procedures(eNB,
1186 1187 1188
            					      proc,
								            eNB->ndlsch_SI, //since we have no DCI for system information, this is filled directly when we receive the DL_CONFIG.request message
								            eNB->ndlsch_SI->harq_process->pdu);
1189

1190
    		  eNB->ndlsch_SI->harq_process->status = DISABLED_NB_IoT;
1191 1192
	    	}

1193 1194 1195 1196 1197 1198 1199 1200
	     } else {//this frame not foresee the transmission of NSSS (subframe 9 is available)
	    
	    	      if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5)
	    	      {
	    		         npdsch_procedures(eNB,
	            					             proc,
									                   eNB->ndlsch_SI, //since we have no DCI for system information, this is filled directly when we receive the DL_CONFIG.request message
									                   eNB->ndlsch_SI->harq_process->pdu);
1201

1202
	    		         eNB->ndlsch_SI->harq_process->status = DISABLED_NB_IoT;
1203

1204 1205
	    	      }
	         }
1206

1207
	}
1208

1209
      ///check for RAR transmission
1210
      if(eNB->ndlsch_ra != NULL && eNB->ndlsch_ra->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4)) //condition on SIB1-NB
1211
      {
1212 1213 1214 1215
  	    if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
  	     {
  	      if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5 && subframe != 9)
  	       {
1216

1217
  	    	  npdsch_procedures(eNB,
1218 1219 1220
            					        proc,
								              eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
								              eNB->ndlsch_ra->harq_process->pdu);
Nick Ho's avatar
Nick Ho committed
1221

1222 1223 1224 1225 1226 1227 1228 1229 1230
  	    	  //it should be activated only when we receive the proper DCIN1_RAR
  	    	  eNB->ndlsch_ra->active= 0;
  	       }
  	     }
	    else //this frame not foresee the transmission of NSSS (subframe 9 is available)
	    {
	    	if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5)
	    	   {
	  	    	  npdsch_procedures(eNB,
1231 1232 1233
	            					        proc,
									              eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
									              eNB->ndlsch_ra->harq_process->pdu);
Nick Ho's avatar
Nick Ho committed
1234

1235 1236
	  	    	  //it should be activated only when we receive the proper DCIN1_RAR
	  	    	  eNB->ndlsch_ra->active= 0; // maybe this is already done inside the ndlsch_procedure
1237

1238 1239 1240
	    	   }
	    }
      }
1241 1242


1243
      //check for UE specific transmission
1244 1245
      /*
       * Delays between DCI transmission and NDLSCH transmission are taken in consideration by the MAC scheduler by sending in the proper subframe the scheduler_response
1246 1247
       * (TS 36.213 ch 16.4.1: DCI format N1, N2, ending in subframe n intended for the UE, the UE shall decode, starting from subframe n+5 DL subframe,
       * the corresponding NPDSCH transmission over the N consecutive NB/IoT DL subframes according to NPDCCH information)
1248 1249 1250 1251
       * Transmission over more subframe and Repetitions are managed directly by the PHY layer
       * We should have only 1 ue-specific ndlsch structure active at each time (active flag is set = 1 only at the corresponding NDLSCH pdu reception and not at the DCI time
       * (NDLSCH transmission should be compliant with the FAPI procedure Figure 3-49)
       *
1252 1253 1254 1255 1256 1257 1258 1259
       * XXX how are managed the transmission and repetitions over the NPDSCH:
       * -repetitions over the NPDSCH channel are defined inside the DCI
       * -need to know the repetition number R (see specs)
       * -repetition are made following a pattern rule (e.g. 00, 11 ...) (see specs)
       * --whenever R>4 then repetition pattern rule changes
       * -possibility to have DL-GAP (OPTIONAL) otherwise no gap in DCI transmission
       *
       * XXX During repetitions of DCI or NDLSCH we receive no schedule_response form MAC
1260 1261
       *
       */
1262

1263
      //this should give only 1 result (since only 1 ndlsch procedure is activated at once) so we brak after the transmission
1264
      for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
1265
      {
1266
    	  if(eNB->ndlsch[(uint8_t)UE_id] != NULL && eNB->ndlsch[(uint8_t)UE_id]->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4)) //condition on sib1-NB
1267
    	  {
1268 1269
    	  	if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
    	  	  {
1270
    	  	    if( subframe!= 0 && subframe != 5 && subframe != 9)
1271 1272
    	  	     {
    	  	    	npdsch_procedures(eNB,
1273 1274 1275
                						      proc,
										              eNB->ndlsch[(uint8_t)UE_id],
										              eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
1276 1277 1278 1279 1280
    	  	    	break;
    	  	       }
    	  	     }
    	    else //this frame not foresee the transmission of NSSS (subframe 9 is available)
    	    {
1281
    	    	if( subframe!= 0 && subframe != 5)
1282 1283
    	    	   {
    	  	    	npdsch_procedures(eNB,
1284 1285 1286
                						      proc,
										              eNB->ndlsch[(uint8_t)UE_id],
										              eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
1287 1288 1289 1290
    	  	    	break;

    	    	   }
    	    }
1291
    	  }
1292

1293

1294
      }
1295 1296


1297 1298 1299
      //no dedicated phy config


1300 1301 1302
      /*If we have DCI to generate do it now
       *
       * DCI in NB-IoT are transmitted over NPDCCH search spaces as described in TS 36.213 ch 16.6
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
       *
       * Don-t care about the concept of search space since will be managed by the MAC.
       * MAC also evaluate the starting position of NPDCCH transmission and will send the corresponding scheduling_response
       *
       *
       * The PHY layer should evaluate R (repetitions of DCI) based on:
       *  -L (aggregation level) --> inside the NPDCCH PDU
       *  -Rmax
       *  -DCI subframe repetition number (2 bits) --> inside the NPDCCH PDU
       *  -TS 36.213 Table 16.6/1/2/3
       *
       *
       *  The higher layer parms (Rmax):
       * -npdcch-NumRepetitions (UE-specific) [inside the NPDCCH UE-specific strucuture] --> configured through phyconfigDedicated
1317
       * -npdcch-NumRepetitionPaging (common)
1318
       * -npdcch-NumRepetitions-RA (common) [inside the NB_IoT_DL_FRAME_PARMS-> nprach_ParametersList] --> configured in phy_config_sib2
1319
       *
1320
       *  PROBLEM: in FAPI specs seems there is no way to trasnmit Rmax to the PHY (waiting for answers)
1321
       *
1322
       * *Rmax is also needed for evaluate the scheduling delay for NDLSCH (see scheduling delay field in NPDCCH PDU FAPI)
1323
       *
1324 1325 1326 1327 1328
       * *Scrambling re-initialization is needed at the beginning of the Search Space or every 4th NPDCCH subframe (See TS 36.211)
       * (this is taken in cosideration by the NPDCCH parameter "scrambling re-initialization batch index" in FAPI specs (Table 4-45)
       *
       ****whenever we have aggregation level = 1 for UE-specific the R is always = 1 (see table 16.6-1)
       ****DCI DL transmission should not happen in case of reference signals or SI messages (this function should be triggered every subframe)
1329 1330 1331
       *
       * */

1332

1333
      for(UE_id = 0 ; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
1334
      {
1335
    	  if(eNB->npdcch[(uint8_t)UE_id] != NULL && eNB->npdcch[(uint8_t)UE_id]->rnti == dci_pdu->dci_alloc->rnti && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4))
1336 1337 1338 1339 1340 1341
    	  {
      	  	if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
      	  	  {
      	  	    if( subframe!= 0 && subframe != 5 && subframe != 9)
      	  	     {

1342 1343 1344 1345 1346 1347 1348 1349 1350
      	  	    	generate_dci_top_NB_IoT(eNB->npdcch[(uint8_t)UE_id],
    		      		  	  	                dci_pdu->Num_dci,
    		  					                      dci_pdu->dci_alloc,
    		  					                      AMP,
    		  					                      fp,
    		  					                      eNB->common_vars.txdataF[0],
    		  					                      subframe,
    		  					                      dci_pdu->npdcch_start_symbol); //this parameter depends by eutraControlRegionSize (see TS36.213 16.6.1)
      	  	    	                        eNB->npdcch[(uint8_t)UE_id]->repetition_idx++; //can do also inside also the management
1351 1352 1353 1354 1355 1356 1357 1358

    		  	  	  break;
      	  	     }
      	  	  }
      	  else //this frame not foresee the transmission of NSSS (subframe 9 is available)
      	     {
      	     if( subframe!= 0 && subframe != 5)
      	      {
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
   	  	    	  generate_dci_top_NB_IoT(eNB->npdcch[(uint8_t)UE_id],
 		      		  	  	                  dci_pdu->Num_dci,
 		  					                        dci_pdu->dci_alloc,
 		  					                        AMP,
 		  					                        fp,
 		  					                        eNB->common_vars.txdataF[0],
 		  					                        subframe,
 		  					                        dci_pdu->npdcch_start_symbol); //this parameter depends by eutraControlRegionSize (see TS36.213 16.6.1)
   	  	    	  
                eNB->npdcch[(uint8_t)UE_id]->repetition_idx++; //can do also inside also the management
1369 1370 1371 1372 1373 1374 1375

 		  	  	  break;
      	      }

      	     }
      	   }
    	  }
1376

1377
}