phy_procedures_lte_eNb_NB_IoT.c 72.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/LTE_TRANSPORT/defs_NB_IoT.h"
37
#include "PHY/LTE_TRANSPORT/proto_NB_IoT.h"
38
//#include "PHY/extern_NB_IoT.h" //where we get the global Sched_Rsp_t structure filled
39
//#include "SCHED/defs.h"
40 41 42
#include "SCHED/extern_NB_IoT.h"
//#include "PHY/LTE_TRANSPORT/if4_tools.h"
//#include "PHY/LTE_TRANSPORT/if5_tools.h"
43
#include "RRC/LITE/proto_NB_IoT.h"
44 45 46 47
#include "SIMULATION/TOOLS/defs.h"  // purpose: included for taus() function
//#ifdef EMOS
//#include "SCHED/phy_procedures_emos.h"
//#endif
48

49
// for NB-IoT
50
#include "SCHED/defs_NB_IoT.h"
51
#include "openair2/RRC/LITE/proto_NB_IoT.h"
52 53
#include "openair2/RRC/LITE/extern_NB_IoT.h"
#include "RRC/LITE/MESSAGES/asn1_msg_NB_IoT.h"
54 55 56
//#define DEBUG_PHY_PROC (Already defined in cmake)
//#define DEBUG_ULSCH

57 58
//#include "LAYER2/MAC/extern.h"
//#include "LAYER2/MAC/defs.h"
59 60 61 62 63 64 65
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

#include "T.h"

#include "assertions.h"
#include "msc.h"
66

67 68 69 70 71 72
#include <time.h>

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

73
/*
74 75 76 77 78 79 80

#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
81
*/
82 83 84

//#define DIAG_PHY

85
///#define NS_PER_SLOT 500000
86

87
///#define PUCCH 1
88 89 90

//DCI_ALLOC_t dci_alloc[8];

91 92 93
///#ifdef EMOS
///fifo_dump_emos_eNB emos_dump_eNB;
///#endif
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 206 207 208 209
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;
}
210 211


212

213 214 215



216 217 218 219
/* For NB-IoT, we put NPBCH in later part, since it would be scheduled by MAC scheduler
* It generates NRS/NPSS/NSSS
*
*/
220
void common_signal_procedures_NB_IoT(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) 
221
{
222 223
  //LTE_DL_FRAME_PARMS   *fp       =  &eNB->frame_parms_NB_IoT;
  LTE_DL_FRAME_PARMS   *fp       =  &eNB->frame_parms;
224
  NB_IoT_eNB_NPBCH_t   *broadcast_str = &eNB->npbch;
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
225
  //NB_IoT_eNB_NDLSCH_t  *sib1          = &eNB->ndlsch_SIB;
AlanLi's avatar
AlanLi committed
226 227 228 229
 NB_IoT_eNB_NDLSCH_t  *ndlsch        = &eNB->ndlsch_SIB;
   NB_IoT_DL_eNB_SIB_t  *sib1          = &ndlsch->content_sib1;
   NB_IoT_DL_eNB_SIB_t  *sib23         = &ndlsch->content_sib23;

230 231
  int                     **txdataF =  eNB->common_vars.txdataF[0];
  int                     subframe  =  proc->subframe_tx;
Matthieu Kanj's avatar
Matthieu Kanj committed
232
  uint32_t                frame     =  proc->frame_tx;
233
  //uint16_t                Ntti      =  10;                      //ntti = 10
Matthieu Kanj's avatar
Matthieu Kanj committed
234
  int                     RB_IoT_ID=22 ;                          // XXX should be initialized (RB reserved for NB-IoT, PRB index)
235
  int                     With_NSSS=0;                            // With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
Matthieu Kanj's avatar
Matthieu Kanj committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249

 
  uint32_t                hyper_frame=proc->HFN;
////////////////////////////////////////////////////////////////////////////////////
  rrc_eNB_carrier_data_NB_IoT_t *carrier = &eNB_rrc_inst_NB_IoT->carrier[0];
      if(frame%64==0 && subframe ==0)
      {//printf("dooooo MIB");

     
       do_MIB_NB_IoT(carrier,1,frame,hyper_frame);
       /* for(int i = 0; i<5;i++)
         printf("%02X ",eNB_rrc_inst_NB_IoT->carrier[0].MIB_NB_IoT[i]);
        printf("\n");*/
      }
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
250

251
     if(frame%64==1 && subframe ==0)
Matthieu Kanj's avatar
Matthieu Kanj committed
252
      {     
Matthieu Kanj's avatar
Matthieu Kanj committed
253
       do_SIB1_NB_IoT_x(0,0,carrier,208,92,1,3584,28,2,hyper_frame);
254
      }
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
255
      
Matthieu Kanj's avatar
Matthieu Kanj committed
256
/////////////////////////////////////////////////////////////////////////////////
257
  //uint8_t      *control_region_size = get_NB_IoT_SIB1_eutracontrolregionsize();
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
258
  //int           G=0;
Matthieu Kanj's avatar
Matthieu Kanj committed
259
  
260

261
 //NSSS only happened in the even frame
262 263 264 265 266 267 268 269
  if(frame%2==0)
    {
      With_NSSS = 1;
    }
  else
    {
      With_NSSS = 0;
    }
270
   
271
    
272 273
  if(subframe == 5)
    {
274

275
      generate_npss_NB_IoT(txdataF,
276 277 278
                           AMP,
                           fp,
                           3,
279
                           10,
280
                           RB_IoT_ID);
281 282
   }
   else if((subframe == 9)&&(With_NSSS == 1))
283
    {
284 285
    
      generate_sss_NB_IoT(txdataF,
286 287 288
                          AMP,
                          fp,
                          3,
289
                          18,
290 291 292 293
                          frame,
                          RB_IoT_ID);
    }

AlanLi's avatar
AlanLi committed
294 295 296 297 298 299 300
  //uint8_t      *npbch_pdu =  get_NB_IoT_MIB();
  uint8_t      *npbch_pdu =  broadcast_str->pdu;
  //uint8_t      *sib1_pdu = get_NB_IoT_SIB1();
  uint8_t      *sib1_pdu  = sib1->pdu;
  //uint8_t      *sib23_pdu =  get_NB_IoT_SIB23();
  uint8_t      *sib23_pdu = sib23->pdu;
  
301 302 303

    if(subframe == 0)
    {
AlanLi's avatar
AlanLi committed
304 305 306 307
      LOG_I(PHY,"MIB NB-IoT content:\n");
           for(int i = 0; i<6;i++)
           printf("%02X",broadcast_str->pdu[i]);
           printf("\n");
Matthieu Kanj's avatar
Matthieu Kanj committed
308

309 310 311 312 313 314 315 316
      generate_npbch(broadcast_str,
                     txdataF,
                     AMP,
                     fp,
                     npbch_pdu,
                     frame%64,
                     RB_IoT_ID);
    }
Matthieu Kanj's avatar
Matthieu Kanj committed
317 318


319
      ///////////////////////////////////////////////////////// SIB1 ////////////////////////////////////
Matthieu Kanj's avatar
Matthieu Kanj committed
320
    if((subframe == 4)  && (frame%2==0) && (frame%32<16) )   ////if((subframe != 0)  && (subframe != 4) && (subframe != 9) ) 
321
    {
AlanLi's avatar
AlanLi committed
322 323 324 325 326 327
        LOG_I(PHY,"SIB1 NB-IoT content:\n");
        for(int i = 0; i<6;i++)
        printf("%02X",sib1->pdu[i]);
        printf("\n");
        

328
        if( frame%32 == 0 )
Matthieu Kanj's avatar
Matthieu Kanj committed
329
        {
330 331 332
            dlsch_encoding_NB_IoT(sib1_pdu,
                                  sib1,
                                  8,                      ///// number_of_subframes_required
Matthieu Kanj's avatar
Matthieu Kanj committed
333 334
                                  236,
                                  1);                   //////////// G*2
335 336
        
        
337
             dlsch_sib_scrambling_NB_IoT(fp,
338
                                         sib1,
339
                                         1888,
340
                                         frame,
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
341
                                         subframe*2);
342
        }
Matthieu Kanj's avatar
Matthieu Kanj committed
343

344 345 346 347 348 349
        dlsch_modulation_NB_IoT(txdataF,
                                AMP,
                                fp,
                                3,                          // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
                                sib1,
                                236,                       // number of bits per subframe
350 351
                               ((frame%32)/2),
                               4,       
352 353
                                RB_IoT_ID);
        
Matthieu Kanj's avatar
Matthieu Kanj committed
354
        }
355
        ///////////////////////////////////////////////////////// END ////////////////////////////////////////////////////////
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
356 357
        
  //////////////////////////////////////////////////// SIB23 ////////////////////////////////////////////////////////////////////////
Matthieu Kanj's avatar
Matthieu Kanj committed
358
  if( (subframe >0) && (subframe !=5) && (With_NSSS == 0) && (frame%2==1) && (frame%64<16) )   ////if((subframe != 0)  && (subframe != 4) && (subframe != 9) ) 
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
359
  {
AlanLi's avatar
AlanLi committed
360 361 362 363 364
        LOG_I(PHY,"SIB2 NB-IoT content:\n");
        for(int i = 0; i<6;i++)
        printf("%02X",sib23->pdu[i]);
        printf("\n");

Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
365 366 367 368 369
        if( subframe == 1 )
        {
            dlsch_encoding_NB_IoT(sib23_pdu,
                                  sib23,
                                  8,                      ///// number_of_subframes_required
Matthieu Kanj's avatar
Matthieu Kanj committed
370 371
                                  236,
                                  2);                   //////////// G*2
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
        
        
            dlsch_sib_scrambling_NB_IoT(fp,                    // is called only in subframe 4
                                         sib23,
                                         1888,            //////   total_bits
                                         frame,
                                         subframe*2);
        }

        if( subframe < 5 )
        {

        dlsch_modulation_NB_IoT(txdataF,
                                AMP,
                                fp,
                                3,                          // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
                                sib23,
                                236,                       // number of bits per subframe
                               (subframe-1),///npdsch_data_subframe, data per subframe//subframe index of the data table of npdsch channel (G*Nsf) ((frame%32)/2),values are between 0..Nsf        
                                subframe,
                                RB_IoT_ID);
       } else {

         dlsch_modulation_NB_IoT(txdataF,
                                AMP,
                                fp,
                                3,                          // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
399
                                sib23,
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
400 401 402 403 404 405 406 407 408 409
                                236,                       // number of bits per subframe
                               (subframe-2),///npdsch_data_subframe, data per subframe//subframe index of the data table of npdsch channel (G*Nsf) ((frame%32)/2),values are between 0..Nsf        
                                subframe,
                                RB_IoT_ID);

       }
        
  }
  //////////////////////////////////////////////////// END ////////////////////////////////////////////////////////////////////////

Matthieu Kanj's avatar
Matthieu Kanj committed
410 411 412 413 414 415
 generate_pilots_NB_IoT(eNB,
                           txdataF,
                           AMP,
                           subframe,
                           RB_IoT_ID,
                           With_NSSS);
Matthieu Kanj's avatar
Matthieu Kanj committed
416

Matthieu Kanj's avatar
Matthieu Kanj committed
417 418 419 420 421 422 423 424 425 426
   if(frame==1023 && subframe==9)
  {
  //printf("%d",hyper_frame);
  if(proc->HFN==1023)
        {             
    proc->HFN=0;
  }else{ 
    proc->HFN++;
  }
  }
Matthieu Kanj's avatar
Matthieu Kanj committed
427

428
  
429 430
}

431
void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) //UL_IND_NB_IoT_t *UL_INFO)
432 433
{
  //RX processing for ue-specific resources (i
434
  //NB_IoT_DL_FRAME_PARMS     *fp=&eNB->frame_parms_NB_IoT;
435

436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
  const int subframe    =   proc->subframe_rx;
  const int frame       =   proc->frame_rx;
/*
  ///////////////////// do we need this part for NB-IoT ///////////////////////////////////
  //check if any RB using in this UL subframe
  eNB->rb_mask_ul[0] = 0;
  eNB->rb_mask_ul[1] = 0;
  eNB->rb_mask_ul[2] = 0;
  eNB->rb_mask_ul[3] = 0;
  ////////////////////////////////////////////////////////////////////////////////////////
  */
  uint8_t data_or_control=0;

  pthread_mutex_lock(&eNB->UL_INFO_mutex);

  // Fix me here, these should be locked
  eNB->UL_INFO.RX_NPUSCH.number_of_pdus  = 0;
  eNB->UL_INFO.crc_ind.number_of_crcs = 0;

  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
 // if (nfapi_mode == 0 || nfapi_mode == 1) { // If PNF or monolithic
      npusch_procedures(eNB,proc,data_or_control);
  //}          

     
}

/////////////////////////////////////////////////////////// backup ////////////////////////////////////////////////////////
/*void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc, UL_IND_NB_IoT_t *UL_INFO)
{
  //RX processing for ue-specific resources (i
467
  uint32_t                  ret=0,i,j,k;
468
  uint32_t                  harq_pid;   // round;
469 470 471 472
  int                       sync_pos;
  uint16_t                  rnti=0;
  uint8_t                   access_mode;
  NB_IoT_DL_FRAME_PARMS     *fp=&eNB->frame_parms_NB_IoT;
473

474 475
  const int subframe    =   proc->subframe_rx;
  const int frame       =   proc->frame_rx;
476 477

  // add hyper subframe here
478
  
479
  //NB-IoT IF module Common setting//
480

481 482 483 484
  UL_INFO->module_id    = eNB->Mod_id;
  UL_INFO->CC_id        = eNB->CC_id;
  UL_INFO->frame        =  frame;
  UL_INFO->subframe     = subframe;
485 486 487 488

  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),
489 490
    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));
491 492 493 494

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

  //check if any RB using in this UL subframe
495 496 497 498
  eNB->rb_mask_ul[0] = 0;
  eNB->rb_mask_ul[1] = 0;
  eNB->rb_mask_ul[2] = 0;
  eNB->rb_mask_ul[3] = 0;
499 500 501

  // 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.
502
  harq_pid = subframe2harq_pid_NB_IoT(fp,frame,subframe);
503 504
  // delete the cba
  // delete the srs
505
  //Loop over the UE, i is the UE ID //
506
  for (i=0; i<NUMBER_OF_UE_MAX_NB_IoT; i++) 
507
    {
508

509 510 511 512 513
      // delete srs 
      // delete Pucch procedure
      // check for Msg3
      if (eNB->mac_enabled==1) 
        {
514
          if (eNB->UE_stats[i].mode == RA_RESPONSE_NB_IoT) 
515
            {
516
               ///Process Msg3 TODO///
517 518 519
              //process_Msg3(eNB,proc,i,harq_pid);
            }
        }
520

521
      eNB->pusch_stats_rb[i][(frame*10)+subframe]    = -63;
522
      eNB->pusch_stats_round[i][(frame*10)+subframe] = 0;
523
      eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = -63;
524

525
      //Check if this UE is has ULSCH scheduling///
526 527 528
      if ((eNB->nulsch[i]) &&
          (eNB->nulsch[i]->rnti>0) &&
          (eNB->nulsch[i]->harq_process->subframe_scheduling_flag==1)) 
529 530
        {
          // UE is has ULSCH scheduling
531
          //////////////////////////////////////round = eNB->nulsch[i]->harq_process->round; //commented to remove warning, to be added if round is used
532
          //NB-IoT The nb_rb always set to 1 //
533
          for (int rb=0;rb<=eNB->nulsch[i]->harq_process->nb_rb;rb++) 
534
            {
535
               int rb2 = rb+eNB->nulsch[i]->harq_process->first_rb;
536
               eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
537
            }
538

539
          //Log for what kind of the ULSCH Reception//
540

541
          //Calculate for LTE C-RS//
542
          //nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
543

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

546
          if (fp->frame_type == FDD_NB_IoT ) 
547 548
            {
              int sf = (subframe<4) ? (subframe+6) : (subframe-4);
549
              //After Downlink Data transmission, simply have a notice to received ACK from PUCCH, I think it's not use for now //
550
              if (eNB->ndlsch[i]->subframe_tx[sf]>0) // we have downlink transmission
551
                { 
552
                  eNB->nulsch[i]->harq_process->O_ACK = 1;
553 554 555
                } 
              else 
                {
556
                  eNB->nulsch[i]->harq_process->O_ACK = 0;
557 558
                }
            }
559

560
          eNB->pusch_stats_rb[i][(frame*10)+subframe]    = eNB->nulsch[i]->harq_process->nb_rb;
561
          eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->nulsch[i]->harq_process->round;
562
          eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = eNB->nulsch[i]->harq_process->mcs;
563

564 565
  

566 567
          rx_ulsch_NB_IoT(eNB,
                          proc,
568 569 570 571 572
                          eNB->UE_stats[i].sector,  // this is the effective sector id
                          i,
                          eNB->nulsch,
                          0);

573
          ret = ulsch_decoding_NB_IoT(eNB,proc,
574 575 576
                                      i,
                                      0, // control_only_flag
                                      eNB->nulsch[i]->harq_process->V_UL_DAI,
577
                                      eNB->nulsch[i]->harq_process->nb_rb>20 ? 1 : 0);
578

579
          //compute the expected ULSCH RX power (for the stats)
580 581 582
          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;
583 584
          if (eNB->nulsch[i]->harq_process->cqi_crc_status == 1) {

585 586 587 588 589
              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);
590
            
591
              eNB->UE_stats[i].rank = eNB->nulsch[i]->harq_process->o_RI[0];
592
          }
593

594 595 596 597 598 599 600 601
          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),
602
                T_INT(harq_pid));
603

604 605 606 607
              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++;
608

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

611 612
          if (eNB->nulsch[i]->Msg3_flag == 1) 
          {
613 614
               ///dump_ulsch(eNB,proc,i);
               //exit(-1);//
615

616
               //In NB-IoT MSG3 //
617 618
                // activate retransmission for Msg3 (signalled to UE PHY by DCI
                eNB->nulsch[(uint32_t)i]->Msg3_active = 1;
619 620 621 622
                // 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);
                
623
                T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
624
                  T_INT(i), T_INT(eNB->nulsch[i]->rnti), T_INT(0),
625 626
                  T_INT(eNB->nulsch[i]->Msg3_frame), T_INT(eNB->nulsch[i]->Msg3_subframe));     
          } // This is Msg3 error
627
          else 
628 629
          { //normal ULSCH
              if (eNB->nulsch[i]->harq_process->round== eNB->nulsch[i]->Mlimit) 
630
                {
631 632
                  eNB->nulsch[i]->harq_process->round=0;
                  eNB->nulsch[i]->harq_process->phich_active=0;
633
                  eNB->UE_stats[i].ulsch_errors[harq_pid]++;
634
                  eNB->UE_stats[i].ulsch_consecutive_errors++; 
635 636 637 638
                  //if (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb > 20) {
                 //   dump_ulsch(eNB,proc,i);
                 // exit(-1);
                  //}
639 640
                  // indicate error to MAC
                  if (eNB->mac_enabled == 1)
641
                    {
642
                      //instead rx_sdu to report The Uplink data not received successfully to MAC
643
                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag = 1;
Nick Ho's avatar
Nick Ho committed
644
                       UL_INFO->crc_ind.number_of_crcs++;
645 646 647 648
                      (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
649
                       UL_INFO->RX_NPUSCH.number_of_pdus++;
650
                    }
651 652 653 654 655
                }
            }
        }  // ulsch in error
        else 
          {
656
            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),
657
              T_INT(harq_pid));
658

659
          // Delete MSG3  log for the PHICH 
660

661
          for (j=0; j<fp->nb_antennas_rx; j++)
662 663
          //this is the RSSI per RB
          eNB->UE_stats[i].UL_rssi[j] =
664
            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 -
665
            hundred_times_log10_NPRB_NB_IoT[eNB->nulsch[i]->harq_process->nb_rb-1]/100 -
666
            get_hundred_times_delta_IF_eNB_NB_IoT(eNB,i,harq_pid, 0)/100;
667
          //for NB-IoT PHICH not work
668 669
          //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
          //eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 1;//
670
          eNB->nulsch[i]->harq_process->round = 0;
671
          eNB->UE_stats[i].ulsch_consecutive_errors = 0;
672

673
          if (eNB->nulsch[i]->Msg3_flag == 1) 
674
            {
675
              if (eNB->mac_enabled==1) 
676
                {
677 678 679
                  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)
680 681
                    {
                      // store successful MSG3 in UL_Info instead rx_sdu
682
                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
Nick Ho's avatar
Nick Ho committed
683
                      UL_INFO->crc_ind.number_of_crcs++;
684 685 686 687
                      (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
688
                      UL_INFO->RX_NPUSCH.number_of_pdus++;
689
                    }
690

691
                  // Need check if this needed in NB-IoT
692
                  // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
693 694 695 696 697 698 699 700 701
               //   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///
702 703
      
              } // mac_enabled==1
704

705
            eNB->UE_stats[i].mode     = PUSCH;
706
            eNB->nulsch[i]->Msg3_flag = 0;
707

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

710
            //Init HARQ parameters, need to check//
711 712
            for (k=0; k<8; k++) 
              { //harq_processes
713
                for (j=0; j<eNB->ndlsch[i]->Mlimit; j++) 
714
                  {
715 716 717
                    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;
718 719
                  }

720 721 722
                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;
723

724
                for (j=0; j<eNB->nulsch[i]->Mlimit; j++) 
725
                  {
726 727 728 729
                    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;
730 731
                  }
              }
732

733 734 735
            eNB->UE_stats[i].dlsch_sliding_cnt  = 0;
            eNB->UE_stats[i].dlsch_NAK_round0   = 0;
            eNB->UE_stats[i].dlsch_mcs_offset   = 0;
736
          } // Msg3_flag==1
737
         else 
738
          {  // Msg3_flag == 0
739
            if (eNB->mac_enabled == 1) 
740 741
              {
                  // store successful Uplink data in UL_Info instead rx_sdu
742
                  (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
Nick Ho's avatar
Nick Ho committed
743
                  UL_INFO->crc_ind.number_of_crcs++;
744 745 746 747
                  (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
748
                  UL_INFO->RX_NPUSCH.number_of_pdus++;
749 750
      
              } // mac_enabled==1
751
          } // Msg3_flag == 0
752

753
            // estimate timing advance for MAC
754
              sync_pos                               = NB_IoT_est_timing_advance_pusch(eNB,i);
755 756 757 758
              eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check

      }  // ulsch not in error

759

760
      // Process HARQ only in NPUSCH
761 762 763 764 765 766
      //process_HARQ_feedback(i,
      //                      eNB,proc,
       //                     1, // pusch_flag
        //                    0,
         //                   0,
          //                  0);/
767

768

769 770
      

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

773 774 775 776 777 778

    // update ULSCH statistics for tracing




779
  } // loop i=0 ... NUMBER_OF_UE_MAX-1
780 781

}
782
////////////////////////////////////////////////////////////////end backup ////////////////////////////////////////////////
783 784 785

#undef DEBUG_PHY_PROC

786 787
/////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
788

789
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
790
{
791 792 793 794 795 796 797 798
  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;
799

Nick Ho's avatar
Nick Ho committed
800

801

802 803
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));

804
  // check DCI format is N1 (format 0)
805 806
  if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0)
    {
807
      //check DCI format N1 is for RAR  rnti_type  in FAPI specs table 4-45
808
      if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type == 1)
809
        {
810

811
        //mapping the fapi parameters to the oai parameters
812 813

          DCI_format = DCIFormatN1_RAR;
814 815 816 817 818 819 820

          //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;
821
          DCI_Content->DCIN1_RAR.RepNum         = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
822 823 824 825
          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;

826 827
          //TODO calculate the number of common repetitions
          //fp->nprach_config_common.number_repetition_RA = see TS 36.213 Table 16.1-3
828

829
          // fill the dlsch_ra_NB structure for RAR, and packed the DCI PDU
830

831 832
          ndlsch               =  eNB->ndlsch_ra;
          ndlsch->ndlsch_type  =  RAR;
833 834

          LOG_D(PHY,"Generating dlsch params for RA_RNTI and packing DCI\n");
835 836 837 838 839 840 841 842 843
          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,
844
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol);
845 846

          //eNB->dlsch_ra_NB->nCCE[subframe] = eNB->DCI_pdu->dci_alloc.firstCCE;
847
        }
848
      else
849 850
        { //managing data

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

855

856
            //mapping the fapi parameters to the oai parameters
857

858
            DCI_format = DCIFormatN1;
859

860 861 862 863 864 865
              //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;
866
              DCI_Content->DCIN1.RepNum         = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
867 868 869 870
              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;

871 872 873 874 875 876 877 878 879 880

              //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
              {
881
                //see TS 36.213 Table 16.1-1
882 883 884
              }


885 886
              //fill the ndlsch structure for UE and packed the DCI PD

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

890
              //parameters we don't consider pdsch config dedicated since not calling the phy config dedicated step2
891

892
            LOG_D(PHY,"Generating dlsch params for DCIN1 data and packing DCI\n");
893 894 895 896 897 898 899 900 901
            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,
902
                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol); 
903 904

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


907 908 909 910 911 912 913 914 915
        }
    }
  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
916 917 918 919 920 921


}



922
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) {
923

924
  int UE_id = -1;
925
  //int harq_pid = 0;
Nick Ho's avatar
Nick Ho committed
926

927 928
  DCI_CONTENT *DCI_Content;
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
929 930

  //mapping the fapi parameters to the OAI parameters
931 932 933 934 935 936 937 938 939
  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;
940 941


942

943
  UE_id = find_ue_NB_IoT(hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti, eNB);
944
  AssertFatal(UE_id == -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
945 946


Nick Ho's avatar
Nick Ho committed
947 948
  /*Log for generate ULSCH DCI*/

949 950 951 952 953 954 955
  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,
956
                                            hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.start_symbol);  
957

Nick Ho's avatar
Nick Ho committed
958 959
  
  //LOG for ULSCH DCI Resource allocation
960
  //CBA is not used in NB-IoT
961
    eNB->nulsch[UE_id]->harq_process->subframe_scheduling_flag = 1;
Nick Ho's avatar
Nick Ho committed
962 963 964
  
}

965 966


967 968 969
/*
 * for NB-IoT ndlsch procedure
 * this function is called by the PHy procedure TX in 3 possible occasion:
970
 * 1) we manage BCCH pdu (SI)
971 972
 * 2) we manage RA dlsch pdu
 * 3) UE-specific dlsch pdu
973 974 975 976
 * ** 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
 */
977
void npdsch_procedures(PHY_VARS_eNB_NB_IoT      *eNB,
978 979 980 981 982
                       eNB_rxtx_proc_t   *proc,     //Context data structure for RX/TX portion of subframe processing
                       NB_IoT_eNB_NDLSCH_t      *ndlsch,
                       //int num_pdcch_symbols,            //(BCOM says are not needed
                       uint8_t                  *pdu
                       )
983
{
984 985 986 987 988 989 990 991
  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];
992
  //uint8_t DLSCH_pdu_rar[256];
993
  int                     i;
994 995

  LOG_D(PHY,
996 997 998 999 1000 1001
        "[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
1002
        );
1003

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

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

1008
        DLSCH_pdu = pdu;
1009

1010 1011 1012 1013 1014 1015
      /*
       * 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
       * 2)all the parameters for getting the MSG3 should be given by the UL_CONFIG.request (all inside the next schedule_response function)
       *
       */
1016

1017 1018 1019 1020 1021
        //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)
1022 1023 1024
    }

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

1026
      DLSCH_pdu = DLSCH_pdu_tmp;
1027

1028
      for (i=0; i<input_buffer_length; i++)
1029

1030
         DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
1031 1032 1033
    }
  }
  else {
1034
    //We are doing a retransmission (harq round > 0
1035 1036
    #ifdef DEBUG_PHY_PROC
    #ifdef DEBUG_DLSCH
1037
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
1038 1039
    #endif
    #endif
1040 1041 1042 1043 1044
  }

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


1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
    //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;
    }
1057 1058


1059 1060 1061 1062 1063
   /*
    * 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)
    */
1064 1065


1066 1067 1068 1069 1070 1071 1072
  /*
   * 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)
   */
1073 1074 1075 1076 1077 1078


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

    /*
1079 1080
     *
     * REASONING:
1081 1082 1083 1084
   * 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)
1085 1086
     *
     * 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
1087 1088
     * NB: switch case of G is the same for npdsch and npdcch
     *
1089 1090 1091
     * 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
1092 1093
     *  -- if operationModeInfo set to 00 or 01 (in band) --> npdsch_start_sysmbol = 3
     *  -- otherwise --> npdsch_start_symbol = 0
1094
     * -if the k subframe is not for SIB1-NB
1095
     *  --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])
1096
     * - otherwise --> npdsch_start_symbol = 0
1097
     * (is the starting OFDM for the NPDSCH transmission in the first slot in a subframe k)
1098 1099
     * 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)
1100 1101 1102 1103 1104
     * Nsf needed as an input (number of subframe)-->inside harq_process of ndlsch
     */

    switch(ndlsch->npdsch_start_symbol)
    {
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
      case 0:
        G = 304;
      break;
      case 1:
        G = 240;
      break;
      case 2:
        G = 224;
      break;
      case 3:
        G =200;
      break;
      default:
        LOG_E (PHY,"npdsch_start_index has unwanted value\n");
      break;
1120 1121

    }
1122
    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
1123 1124
    LOG_I(PHY, "NB-IoT Encoding step\n");

1125
    //    eNB->te(eNB,
1126 1127 1128 1129 1130 1131 1132
    //      DLSCH_pdu,
    //      num_pdcch_symbols,
    //      dlsch,
    //      frame,subframe,
    //      &eNB->dlsch_rate_matching_stats,
    //      &eNB->dlsch_turbo_encoding_stats,
    //      &eNB->dlsch_interleaving_stats);
1133 1134


1135
   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
1136 1137 1138 1139

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

1140
   // start_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
1141 1142
    LOG_I(PHY, "NB-IoT Scrambling step\n");

1143 1144 1145 1146 1147 1148
    /*
     * SOME RELEVANT FACTS:
     *
     *
     */

1149
      //    dlsch_scrambling(fp,
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
      //         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);
1162

1163
    //stop_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
1164 1165 1166


    //modulation-------------------------------------------
1167
    //start_meas_NB_IoT(&eNB->dlsch_modulation_stats);
1168 1169
    LOG_I(PHY, "NB-IoT Modulation step\n");

1170
    //    dlsch_modulation(eNB,
1171 1172 1173 1174 1175 1176
    //         eNB->common_vars.txdataF[0],
    //         AMP,
    //         subframe,
    //         num_pdcch_symbols,
    //         dlsch,
    //         dlsch1);
1177

1178
    //stop_meas_NB_IoT(&eNB->dlsch_modulation_stats);
1179 1180 1181 1182 1183
  }


#ifdef PHY_ABSTRACTION
  else {
1184
    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
1185
    //dlsch_encoding_emul(eNB,
1186 1187
      //DLSCH_pdu,
      //dlsch);
1188
   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
1189 1190 1191 1192 1193
  }

#endif
  ndlsch->active = 0;
}
1194 1195


1196
extern int oai_exit;
1197 1198

/*
1199
 * ASSUMPTION
1200 1201 1202
 *
 * The MAC schedule the schedule_response in a SUBFRAME BASE (at least because otherwise we have problem with our assumptions on SI transmission)
 *
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214
 *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)
1215
 * -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
1216 1217
 * -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.
1218
 *
1219 1220 1221 1222
 * 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)
 *
 *
1223
 *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
1224 1225 1226
 *
 * **relevant aspects for the System information Transmission (Table 4-47 NDLSCH FAPi specs)
 * 1)RNTI type = 0 (contains a BCCH)
1227 1228
 * 2)Repetition number == scheduling info SIB1 mapped into 4-8-16
 * 3)RNTI (0xFFFF = SI-RNTI)
1229 1230 1231
 * (see schedule_response implementation)
 *
 */
1232 1233 1234 1235 1236 1237 1238

/*
 * 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)
 */

1239
void phy_procedures_eNB_TX_NB_IoT(PHY_VARS_eNB_NB_IoT     *eNB,
1240 1241
                                  eNB_rxtx_proc_t  *proc,
                                  int                     do_meas)
1242
{
1243 1244 1245 1246 1247 1248 1249 1250
  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;
1251
  //NB_IoT_eNB_NPDCCH_t*npdcch;
1252

1253
  if(do_meas == 1)
1254
    //start_meas_NB_IoT(&eNB->phy_proc_tx);
1255 1256


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

1259
  // clear the transmit data array for the current subframe
1260 1261 1262 1263 1264 1265
  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));
    } 

1266
  //generate NPSS/NSSS
1267
 // common_signal_procedures_NB_IoT(eNB,proc);  // to uncomment after NB-IoT testing
1268

1269
    //Generate MIB
1270
    if(subframe ==0 && (eNB->npbch != NULL))
1271 1272
     {
          if(eNB->npbch->pdu != NULL)
1273
          {
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
            //BCOM function
            /*
             * -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
             *
             */

            generate_npbch(eNB->npbch,
1286 1287 1288
                           txdataF,
                           AMP,
                           fp,
1289
                           eNB->npbch->pdu,
1290 1291
                           frame%64,
                           fp->NB_IoT_RB_ID);
1292
                        
1293 1294 1295 1296 1297
          }

          //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)
1298
          {
1299
            eNB->npbch->pdu = NULL;
1300
          }
1301
      }
Nick Ho's avatar
Nick Ho committed
1302

1303

1304
    //Check for SIB1-NB transmission
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
    /*
     *
     * 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)
     *
     */
1318
    if(subframe == 4 && eNB->ndlsch_SIB1 != NULL && eNB->ndlsch_SIB1->harq_process->status == ACTIVE_NB_IoT)
1319
    {
1320
      //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
1321
      sib1_startFrame = is_SIB1_NB_IoT(frame,
1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
                                       (long)eNB->ndlsch_SIB1->harq_process->repetition_number,
                                       fp->Nid_cell,
                                       eNB->ndlsch_SIB1); //set the flags
                                   
      if(sib1_startFrame != -1 && eNB->ndlsch_SIB1->harq_process->pdu != NULL)
      {
         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);
      }

      //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
      if((frame-sib1_startFrame)%256 == 255)
      {
          //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;
      }
1341

1342
    }
1343

1344 1345

    //Check for SI transmission
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358
    /*
     *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)
     *
1359 1360
     * [This condition should be known by the MAC layer so it should trigger an DLSCH pdu only at proper instants]
     *
1361 1362 1363 1364
     * 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)
     *
     *
1365
     *XXX important: set the flag HARQ process->status to DISABLE when PHY finished the SI-transmission over the 2 or 8 subframes
1366 1367 1368
     *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)
1369
     *
1370
     */
1371

1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
  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
  {
      if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
      {
        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,
                            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);

          eNB->ndlsch_SI->harq_process->status = DISABLED_NB_IoT;
        }

       } 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);

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

              }
           }

  }
1402

1403
      ///check for RAR transmission
1404
      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
1405
      {
1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433
        if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
         {
          if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5 && subframe != 9)
           {

            npdsch_procedures(eNB,
                              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);

            //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,
                                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);

              //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

           }
      }
1434
      }
1435 1436


1437
      //check for UE specific transmission
1438 1439
      /*
       * Delays between DCI transmission and NDLSCH transmission are taken in consideration by the MAC scheduler by sending in the proper subframe the scheduler_response
1440 1441
       * (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)
1442 1443 1444 1445
       * 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)
       *
1446 1447 1448 1449 1450 1451 1452 1453
       * 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
1454 1455
       *
       */
1456

1457
      //this should give only 1 result (since only 1 ndlsch procedure is activated at once) so we brak after the transmission
1458
      for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
1459
      {
1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485
        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
        {
          if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
            {
              if( subframe!= 0 && subframe != 5 && subframe != 9)
               {
                npdsch_procedures(eNB,
                                  proc,
                                  eNB->ndlsch[(uint8_t)UE_id],
                                  eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
                break;
                 }
               }
          else //this frame not foresee the transmission of NSSS (subframe 9 is available)
          {
            if( subframe!= 0 && subframe != 5)
               {
                npdsch_procedures(eNB,
                                  proc,
                                  eNB->ndlsch[(uint8_t)UE_id],
                                  eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
                break;

               }
          }
        }
1486

1487

1488
      }
1489 1490


1491 1492 1493
      //no dedicated phy config


1494 1495 1496
      /*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
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
       *
       * 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
1511
       * -npdcch-NumRepetitionPaging (common)
1512
       * -npdcch-NumRepetitions-RA (common) [inside the NB_IoT_DL_FRAME_PARMS-> nprach_ParametersList] --> configured in phy_config_sib2
1513
       *
1514
       *  PROBLEM: in FAPI specs seems there is no way to trasnmit Rmax to the PHY (waiting for answers)
1515
       *
1516
       * *Rmax is also needed for evaluate the scheduling delay for NDLSCH (see scheduling delay field in NPDCCH PDU FAPI)
1517
       *
1518 1519 1520 1521 1522
       * *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)
1523 1524 1525
       *
       * */

1526

1527
      for(UE_id = 0 ; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
1528
      {
1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
        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))
        {
            if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
              {
                if( subframe!= 0 && subframe != 5 && subframe != 9)
                 {

                  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

                  break;
                 }
              }
          else //this frame not foresee the transmission of NSSS (subframe 9 is available)
             {
             if( subframe!= 0 && subframe != 5)
              {
                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)
                
1562
                eNB->npdcch[(uint8_t)UE_id]->repetition_idx++; //can do also inside also the management
1563

1564 1565
              break;
              }
1566

1567 1568 1569
             }
           }
        }
1570

1571 1572
}

Matthieu Kanj's avatar
Matthieu Kanj committed
1573
uint32_t rx_nprach_NB_IoT(PHY_VARS_eNB *eNB, int frame, uint8_t subframe, uint16_t *rnti, uint16_t *preamble_index, uint16_t *timing_advance) {
1574 1575

  uint32_t estimated_TA; 
Matthieu Kanj's avatar
Matthieu Kanj committed
1576
  //int frame,frame_mod;    // subframe,
Matthieu Kanj's avatar
Matthieu Kanj committed
1577
 // subframe = eNB->proc.subframe_prach; 
Matthieu Kanj's avatar
Matthieu Kanj committed
1578
 // frame = eNB->proc.frame_prach;
1579 1580

  //printf("frame = %i \n sf = %i\n",frame,subframe); 
Matthieu Kanj's avatar
Matthieu Kanj committed
1581
 // frame_mod = 0;//(frame)%32; 
1582
  //if (subframe==1 && frame_mod==0 && frame!=0){
Matthieu Kanj's avatar
Matthieu Kanj committed
1583
 //if (frame_mod==0 && frame!=0){
1584
    //printf("\n frame_in = %i\n",frame); 
Matthieu Kanj's avatar
Matthieu Kanj committed
1585
    estimated_TA = process_nprach_NB_IoT(eNB,frame,subframe,rnti,preamble_index,timing_advance);
1586
    //printf("estim = %i\n",estimated_TA);
Matthieu Kanj's avatar
Matthieu Kanj committed
1587
 // }
1588
  return estimated_TA;
1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691
}


void fill_crc_indication_NB_IoT(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe,uint8_t crc_flag) {

  pthread_mutex_lock(&eNB->UL_INFO_mutex);
  // nfapi_crc_indication_pdu_t* crc_pdu_list
  nfapi_crc_indication_pdu_t *pdu =   &eNB->UL_INFO.crc_ind.crc_pdu_list[0]; //[eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs];

  ///eNB->UL_INFO.crc_ind.sfn_sf                         = frame<<4 | subframe;
  //eNB->UL_INFO.crc_ind.header.message_id              = NFAPI_CRC_INDICATION;
  //eNB->UL_INFO.crc_ind.crc_indication_body.tl.tag     = NFAPI_CRC_INDICATION_BODY_TAG;

  //pdu->instance_length                                = 0; // don't know what to do with this
  //  pdu->rx_ue_information.handle                       = handle;
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
  pdu->rx_ue_information.rnti                         = eNB->ulsch[UE_id]->rnti;
  pdu->crc_indication_rel8.tl.tag                     = NFAPI_CRC_INDICATION_REL8_TAG;
  pdu->crc_indication_rel8.crc_flag                   = crc_flag;

  eNB->UL_INFO.crc_ind.number_of_crcs++;

  //LOG_D(PHY, "%s() rnti:%04x crcs:%d crc_flag:%d\n", __FUNCTION__, pdu->rx_ue_information.rnti, eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs, crc_flag);

  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}


void npusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t data_or_control)
{
  
  uint32_t i;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  NB_IoT_eNB_NULSCH_t *ulsch_NB_IoT;
  NB_IoT_UL_eNB_HARQ_t *ulsch_harq;

  const int subframerx = proc->subframe_rx;
  const int framerx    = proc->frame_rx;

  for (i=0; i<NUMBER_OF_UE_MAX; i++)
  {
      ulsch_NB_IoT = eNB->ulsch_NB_IoT[i];
      ulsch_harq = ulsch_NB_IoT->harq_process;

      // if eNB is ready to receive UL data 
      // define a flag to trigger on or off the decoding process
      //if ((ulsch) && (ulsch->rnti>0) && (ulsch_harq->status == ACTIVE) && (ulsch_harq->frame == frame) && (ulsch_harq->subframe == subframe) && (ulsch_harq->handled == 0))
      if ((ulsch_NB_IoT) && (ulsch_NB_IoT->rnti>0)) // && (ulsch_harq->frame == framerx) && (ulsch_harq->subframe == subframerx))  
      {
                     /*
                     // UE has ULSCH scheduling
                     for (int rb=0; rb<=ulsch_harq->nb_rb; rb++)
                     {
                          int rb2 = rb+ulsch_harq->first_rb;
                          eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
                     }
                     */
                    //rx_ulsch(eNB,proc, i);
                    /*ret = ulsch_decoding(eNB,proc,
                                        i,
                                        0, // control_only_flag
                                        ulsch_harq->V_UL_DAI,
                                        ulsch_harq->nb_rb>20 ? 1 : 0);*/
                    // fill_ulsch_cqi_indication(eNB,frame,subframe,ulsch_harq,ulsch->rnti);

                  ////// nulsch_config should be provided before calling the rx_ulsch function
                     /*typedef struct {
                              nfapi_tl_t tl;  
                              uint8_t nulsch_format;         --> this parameter is needed 
                              uint32_t handle;
                              uint16_t size;
                              uint16_t rnti;                 --> this parameter is needed 
                              uint8_t subcarrier_indication; --> this parameter is needed 
                              uint8_t resource_assignment;
                              uint8_t mcs;                    --> this parameter is needed 
                              uint8_t redudancy_version;     
                              uint8_t repetition_number;     --> this parameter is needed 
                              uint8_t new_data_indication;
                              uint8_t n_srs;
                              uint16_t scrambling_sequence_initialization_cinit;   --> this parameter is needed 
                              uint16_t sf_idx;                                     
                              nfapi_ul_config_ue_information ue_information;
                              nfapi_ul_config_nb_harq_information nb_harq_information;
                            } nfapi_ul_config_nulsch_pdu_rel13_t;
                            #define NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG 0x205F
                      */
                    rx_ulsch_Gen_NB_IoT(eNB,
                                         proc,
                                         0,                         // this is the effective sector id
                                         0,
                                         ulsch_NB_IoT,
                                         1,                         //npusch_format,             // 1, 2  
                                         22,                        // 22 , to be included in // to be replaced by NB_IoT_start ??
                                         1,                         // 0 (3.75 KHz) or 1 (15 KHz)
                                         65522,                     //= 65522
                                         proc->subframe_dscr_msg3,  // first received subframe 
                                         proc->frame_dscr_msg3,     // first received frame
                                         16,                        //  total number of occupied slots
                                         11,
                                         1,
                                         2, 
                                         88,                        //  A = TBS
                                         proc->counter_msg3,                          // proc->counter_msg3
Matthieu Kanj's avatar
Matthieu Kanj committed
1692 1693
                                         subframerx,
                                         0, 
1694 1695 1696 1697 1698 1699 1700 1701
                                         data_or_control);                        // data (0) or control (1)

         }

                
                
   }  // for UE loop

1702
}