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

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

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

#include "T.h"

#include "assertions.h"
#include "msc.h"
67

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

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

74
/*
75 76 77 78 79 80 81

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

//#define DIAG_PHY

86
///#define NS_PER_SLOT 500000
87

88
///#define PUCCH 1
89 90 91

//DCI_ALLOC_t dci_alloc[8];

92 93 94
///#ifdef EMOS
///fifo_dump_emos_eNB emos_dump_eNB;
///#endif
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 210
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;
}
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 *eNB,eNB_rxtx_proc_t *proc) 
217
{
218 219
  //LTE_DL_FRAME_PARMS   *fp       =  &eNB->frame_parms_NB_IoT;
  LTE_DL_FRAME_PARMS   *fp       =  &eNB->frame_parms;
220
  NB_IoT_eNB_NPBCH_t   *broadcast_str = &eNB->npbch;
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
221
  //NB_IoT_eNB_NDLSCH_t  *sib1          = &eNB->ndlsch_SIB;
Matthieu Kanj's avatar
Matthieu Kanj committed
222
  //NB_IoT_eNB_NDLSCH_t  *ndlsch        = &eNB->ndlsch_SIB1;
223 224
  NB_IoT_eNB_NDLSCH_t *sib1          = eNB->ndlsch_SIB1;
  NB_IoT_eNB_NDLSCH_t  *sib23         = eNB->ndlsch_SIB23;
AlanLi's avatar
AlanLi committed
225

Matthieu Kanj's avatar
Matthieu Kanj committed
226 227
  uint8_t      *npbch_pdu =  broadcast_str->pdu;

228
  int                     **txdataF =  eNB->common_vars.txdataF[0];
Matthieu Kanj's avatar
Matthieu Kanj committed
229
  uint32_t                subframe  =  proc->subframe_tx;
Matthieu Kanj's avatar
Matthieu Kanj committed
230
  uint32_t                frame     =  proc->frame_tx;
231
  //uint16_t                Ntti      =  10;                      //ntti = 10
Matthieu Kanj's avatar
Matthieu Kanj committed
232
  int                     RB_IoT_ID=22;                          // XXX should be initialized (RB reserved for NB-IoT, PRB index)
233
  int                     With_NSSS=0;                            // With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
Matthieu Kanj's avatar
Matthieu Kanj committed
234 235

  uint32_t                hyper_frame=proc->HFN;
Matthieu Kanj's avatar
Matthieu Kanj committed
236

237
  fp->flag_free_sf =0;
Matthieu Kanj's avatar
Matthieu Kanj committed
238
  ////////////////////////////////////////////////////////////////////////////////////
AlanLi's avatar
AlanLi committed
239
  /*
Matthieu Kanj's avatar
Matthieu Kanj committed
240 241 242 243 244 245
  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);
AlanLi's avatar
AlanLi committed
246
     
Matthieu Kanj's avatar
Matthieu Kanj committed
247
      }
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
248

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

260
  if(frame%2==0)
Matthieu Kanj's avatar
Matthieu Kanj committed
261
  {
262
      With_NSSS = 1;
Matthieu Kanj's avatar
Matthieu Kanj committed
263
  } else {
264
      With_NSSS = 0;
Matthieu Kanj's avatar
Matthieu Kanj committed
265
  }
Matthieu Kanj's avatar
Matthieu Kanj committed
266 267 268
  /////////////////////////////////////////////////////////////////////////////////
  //////////////////////////////// NPSS && NSSS ////////////////////////////////// 
  /////////////////////////////////////////////////////////////////////////////////
269 270
  if(subframe == 5)
    {
271

272
      generate_npss_NB_IoT(txdataF,
273 274 275
                           AMP,
                           fp,
                           3,
276
                           10,
277
                           RB_IoT_ID);
278
   }
Matthieu Kanj's avatar
Matthieu Kanj committed
279
   else if((subframe == 9) && (With_NSSS == 1))
280
    {
281 282
    
      generate_sss_NB_IoT(txdataF,
283 284 285
                          AMP,
                          fp,
                          3,
286
                          18,
287 288
                          frame,
                          RB_IoT_ID);
Matthieu Kanj's avatar
Matthieu Kanj committed
289
      nsss_state = 1;
290
    }
Matthieu Kanj's avatar
Matthieu Kanj committed
291 292 293
    /////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////// MIB //////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////
294 295 296 297 298 299 300 301 302 303 304

    if(subframe == 0)
    {
      generate_npbch(broadcast_str,
                     txdataF,
                     AMP,
                     fp,
                     npbch_pdu,
                     frame%64,
                     RB_IoT_ID);
    }
Matthieu Kanj's avatar
Matthieu Kanj committed
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
    /////////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////// SIB1 ////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////
    int sib1_state = 0;
    if(subframe == 4)
    {
       sib1_state = generate_SIB1(sib1,
                      txdataF,
                      AMP,
                      fp,
                      frame,
                      subframe,
                      RB_IoT_ID,
                      0);
    }
    /////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////// SIB23 ////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////
    if( (subframe != 0) && (subframe != 5) && (sib1_state != 1) && (nsss_state != 1))
    {      
          generate_SIB23(sib23,
                         txdataF,
                         AMP,
                         fp,
                         frame,
                         subframe,
                         RB_IoT_ID);
    }
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
  
    if( (subframe != 0) && (subframe != 5) && (nsss_state != 1) && (fp->flag_free_sf == 0) )
    {
      NB_IoT_eNB_NPDCCH_t  *npdcch_str     = eNB->npdcch_DCI;
      NB_IoT_eNB_NDLSCH_t  *RAR            = eNB->ndlsch_RAR;
      /////////////////////////////////////////////////////////////////////////////////
      ///////////////////////////////////// NPDCCH ////////////////////////////////////
      /////////////////////////////////////////////////////////////////////////////////
      generate_NPDCCH_NB_IoT(npdcch_str,
                             txdataF,
                             AMP,
                             fp,
                             frame,
                             subframe,
                             RB_IoT_ID);
      /////////////////////////////////////////////////////////////////////////////////
      ///////////////////////////////////// NPDSCH ////////////////////////////////////
      /////////////////////////////////////////////////////////////////////////////////
      generate_NDLSCH_NB_IoT(RAR,
                             txdataF,
                             AMP,
                             fp,
                             frame,
                             subframe,
                             RB_IoT_ID);
      ///////////////////////////////////////////////////////////////////////////////////
    }
Matthieu Kanj's avatar
SIB23  
Matthieu Kanj committed
360

Matthieu Kanj's avatar
Matthieu Kanj committed
361 362 363 364 365 366
 generate_pilots_NB_IoT(eNB,
                           txdataF,
                           AMP,
                           subframe,
                           RB_IoT_ID,
                           With_NSSS);
Matthieu Kanj's avatar
Matthieu Kanj committed
367

368
  if(proc->frame_rx==1023 && proc->subframe_rx==9)
Matthieu Kanj's avatar
Matthieu Kanj committed
369
  {
Matthieu Kanj's avatar
Matthieu Kanj committed
370 371 372 373 374 375
      //printf("%d",hyper_frame);
      if(proc->HFN==1023)
      {             
           proc->HFN=0;
      }else{ 
           proc->HFN++;
376
           //printf("Update HFN:%d when frame:%d subframe:%d\n",proc->HFN,proc->frame_rx,proc->subframe_rx);
Matthieu Kanj's avatar
Matthieu Kanj committed
377
      }
Matthieu Kanj's avatar
Matthieu Kanj committed
378
  }
Matthieu Kanj's avatar
Matthieu Kanj committed
379

380
  
381 382
}

383
void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) //UL_IND_NB_IoT_t *UL_INFO)
384 385
{
  //RX processing for ue-specific resources (i
386
  //NB_IoT_DL_FRAME_PARMS     *fp=&eNB->frame_parms_NB_IoT;
387

388 389 390 391 392 393 394 395 396 397 398
  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;
  ////////////////////////////////////////////////////////////////////////////////////////
  */
Matthieu Kanj's avatar
Matthieu Kanj committed
399
  
400

Matthieu Kanj's avatar
Matthieu Kanj committed
401
  npusch_procedures(eNB,proc);
402

403 404 405 406 407 408 409 410 411

  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
412
     
413 414 415 416 417 418 419 420 421
  //}          

     
}

/////////////////////////////////////////////////////////// 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
422
  uint32_t                  ret=0,i,j,k;
423
  uint32_t                  harq_pid;   // round;
424 425 426 427
  int                       sync_pos;
  uint16_t                  rnti=0;
  uint8_t                   access_mode;
  NB_IoT_DL_FRAME_PARMS     *fp=&eNB->frame_parms_NB_IoT;
428

429 430
  const int subframe    =   proc->subframe_rx;
  const int frame       =   proc->frame_rx;
431 432

  // add hyper subframe here
433
  
434
  //NB-IoT IF module Common setting//
435

436 437 438 439
  UL_INFO->module_id    = eNB->Mod_id;
  UL_INFO->CC_id        = eNB->CC_id;
  UL_INFO->frame        =  frame;
  UL_INFO->subframe     = subframe;
440 441 442 443

  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),
444 445
    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));
446 447 448 449

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

  //check if any RB using in this UL subframe
450 451 452 453
  eNB->rb_mask_ul[0] = 0;
  eNB->rb_mask_ul[1] = 0;
  eNB->rb_mask_ul[2] = 0;
  eNB->rb_mask_ul[3] = 0;
454 455 456

  // 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.
457
  harq_pid = subframe2harq_pid_NB_IoT(fp,frame,subframe);
458 459
  // delete the cba
  // delete the srs
460
  //Loop over the UE, i is the UE ID //
461
  for (i=0; i<NUMBER_OF_UE_MAX_NB_IoT; i++) 
462
    {
463

464 465 466 467 468
      // delete srs 
      // delete Pucch procedure
      // check for Msg3
      if (eNB->mac_enabled==1) 
        {
469
          if (eNB->UE_stats[i].mode == RA_RESPONSE_NB_IoT) 
470
            {
471
               ///Process Msg3 TODO///
472 473 474
              //process_Msg3(eNB,proc,i,harq_pid);
            }
        }
475

476
      eNB->pusch_stats_rb[i][(frame*10)+subframe]    = -63;
477
      eNB->pusch_stats_round[i][(frame*10)+subframe] = 0;
478
      eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = -63;
479

480
      //Check if this UE is has ULSCH scheduling///
481 482 483
      if ((eNB->nulsch[i]) &&
          (eNB->nulsch[i]->rnti>0) &&
          (eNB->nulsch[i]->harq_process->subframe_scheduling_flag==1)) 
484 485
        {
          // UE is has ULSCH scheduling
486
          //////////////////////////////////////round = eNB->nulsch[i]->harq_process->round; //commented to remove warning, to be added if round is used
487
          //NB-IoT The nb_rb always set to 1 //
488
          for (int rb=0;rb<=eNB->nulsch[i]->harq_process->nb_rb;rb++) 
489
            {
490
               int rb2 = rb+eNB->nulsch[i]->harq_process->first_rb;
491
               eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
492
            }
493

494
          //Log for what kind of the ULSCH Reception//
495

496
          //Calculate for LTE C-RS//
497
          //nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
498

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

501
          if (fp->frame_type == FDD_NB_IoT ) 
502 503
            {
              int sf = (subframe<4) ? (subframe+6) : (subframe-4);
504
              //After Downlink Data transmission, simply have a notice to received ACK from PUCCH, I think it's not use for now //
505
              if (eNB->ndlsch[i]->subframe_tx[sf]>0) // we have downlink transmission
506
                { 
507
                  eNB->nulsch[i]->harq_process->O_ACK = 1;
508 509 510
                } 
              else 
                {
511
                  eNB->nulsch[i]->harq_process->O_ACK = 0;
512 513
                }
            }
514

515
          eNB->pusch_stats_rb[i][(frame*10)+subframe]    = eNB->nulsch[i]->harq_process->nb_rb;
516
          eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->nulsch[i]->harq_process->round;
517
          eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = eNB->nulsch[i]->harq_process->mcs;
518

519 520
  

521 522
          rx_ulsch_NB_IoT(eNB,
                          proc,
523 524 525 526 527
                          eNB->UE_stats[i].sector,  // this is the effective sector id
                          i,
                          eNB->nulsch,
                          0);

528
          ret = ulsch_decoding_NB_IoT(eNB,proc,
529 530 531
                                      i,
                                      0, // control_only_flag
                                      eNB->nulsch[i]->harq_process->V_UL_DAI,
532
                                      eNB->nulsch[i]->harq_process->nb_rb>20 ? 1 : 0);
533

534
          //compute the expected ULSCH RX power (for the stats)
535 536 537
          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;
538 539
          if (eNB->nulsch[i]->harq_process->cqi_crc_status == 1) {

540 541 542 543 544
              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);
545
            
546
              eNB->UE_stats[i].rank = eNB->nulsch[i]->harq_process->o_RI[0];
547
          }
548

549 550 551 552 553 554 555 556
          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),
557
                T_INT(harq_pid));
558

559 560 561 562
              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++;
563

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

566 567
          if (eNB->nulsch[i]->Msg3_flag == 1) 
          {
568 569
               ///dump_ulsch(eNB,proc,i);
               //exit(-1);//
570

571
               //In NB-IoT MSG3 //
572 573
                // activate retransmission for Msg3 (signalled to UE PHY by DCI
                eNB->nulsch[(uint32_t)i]->Msg3_active = 1;
574 575 576 577
                // 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);
                
578
                T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
579
                  T_INT(i), T_INT(eNB->nulsch[i]->rnti), T_INT(0),
580 581
                  T_INT(eNB->nulsch[i]->Msg3_frame), T_INT(eNB->nulsch[i]->Msg3_subframe));     
          } // This is Msg3 error
582
          else 
583 584
          { //normal ULSCH
              if (eNB->nulsch[i]->harq_process->round== eNB->nulsch[i]->Mlimit) 
585
                {
586 587
                  eNB->nulsch[i]->harq_process->round=0;
                  eNB->nulsch[i]->harq_process->phich_active=0;
588
                  eNB->UE_stats[i].ulsch_errors[harq_pid]++;
589
                  eNB->UE_stats[i].ulsch_consecutive_errors++; 
590 591 592 593
                  //if (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb > 20) {
                 //   dump_ulsch(eNB,proc,i);
                 // exit(-1);
                  //}
594 595
                  // indicate error to MAC
                  if (eNB->mac_enabled == 1)
596
                    {
597
                      //instead rx_sdu to report The Uplink data not received successfully to MAC
598
                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag = 1;
Nick Ho's avatar
Nick Ho committed
599
                       UL_INFO->crc_ind.number_of_crcs++;
600 601 602 603
                      (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
604
                       UL_INFO->RX_NPUSCH.number_of_pdus++;
605
                    }
606 607 608 609 610
                }
            }
        }  // ulsch in error
        else 
          {
611
            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),
612
              T_INT(harq_pid));
613

614
          // Delete MSG3  log for the PHICH 
615

616
          for (j=0; j<fp->nb_antennas_rx; j++)
617 618
          //this is the RSSI per RB
          eNB->UE_stats[i].UL_rssi[j] =
619
            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 -
620
            hundred_times_log10_NPRB_NB_IoT[eNB->nulsch[i]->harq_process->nb_rb-1]/100 -
621
            get_hundred_times_delta_IF_eNB_NB_IoT(eNB,i,harq_pid, 0)/100;
622
          //for NB-IoT PHICH not work
623 624
          //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
          //eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 1;//
625
          eNB->nulsch[i]->harq_process->round = 0;
626
          eNB->UE_stats[i].ulsch_consecutive_errors = 0;
627

628
          if (eNB->nulsch[i]->Msg3_flag == 1) 
629
            {
630
              if (eNB->mac_enabled==1) 
631
                {
632 633 634
                  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)
635 636
                    {
                      // store successful MSG3 in UL_Info instead rx_sdu
637
                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
Nick Ho's avatar
Nick Ho committed
638
                      UL_INFO->crc_ind.number_of_crcs++;
639 640 641 642
                      (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
643
                      UL_INFO->RX_NPUSCH.number_of_pdus++;
644
                    }
645

646
                  // Need check if this needed in NB-IoT
647
                  // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
648 649 650 651 652 653 654 655 656
               //   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///
657 658
      
              } // mac_enabled==1
659

660
            eNB->UE_stats[i].mode     = PUSCH;
661
            eNB->nulsch[i]->Msg3_flag = 0;
662

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

665
            //Init HARQ parameters, need to check//
666 667
            for (k=0; k<8; k++) 
              { //harq_processes
668
                for (j=0; j<eNB->ndlsch[i]->Mlimit; j++) 
669
                  {
670 671 672
                    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;
673 674
                  }

675 676 677
                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;
678

679
                for (j=0; j<eNB->nulsch[i]->Mlimit; j++) 
680
                  {
681 682 683 684
                    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;
685 686
                  }
              }
687

688 689 690
            eNB->UE_stats[i].dlsch_sliding_cnt  = 0;
            eNB->UE_stats[i].dlsch_NAK_round0   = 0;
            eNB->UE_stats[i].dlsch_mcs_offset   = 0;
691
          } // Msg3_flag==1
692
         else 
693
          {  // Msg3_flag == 0
694
            if (eNB->mac_enabled == 1) 
695 696
              {
                  // store successful Uplink data in UL_Info instead rx_sdu
697
                  (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
Nick Ho's avatar
Nick Ho committed
698
                  UL_INFO->crc_ind.number_of_crcs++;
699 700 701 702
                  (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
703
                  UL_INFO->RX_NPUSCH.number_of_pdus++;
704 705
      
              } // mac_enabled==1
706
          } // Msg3_flag == 0
707

708
            // estimate timing advance for MAC
709
              sync_pos                               = NB_IoT_est_timing_advance_pusch(eNB,i);
710 711 712 713
              eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check

      }  // ulsch not in error

714

715
      // Process HARQ only in NPUSCH
716 717 718 719 720 721
      //process_HARQ_feedback(i,
      //                      eNB,proc,
       //                     1, // pusch_flag
        //                    0,
         //                   0,
          //                  0);/
722

723

724 725
      

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

728 729 730 731 732 733

    // update ULSCH statistics for tracing




734
  } // loop i=0 ... NUMBER_OF_UE_MAX-1
735 736

}
737
////////////////////////////////////////////////////////////////end backup ////////////////////////////////////////////////
738 739 740

#undef DEBUG_PHY_PROC

741 742
/////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
743

744
void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t * proc,nfapi_dl_config_request_pdu_t *dl_config_pdu) 
Nick Ho's avatar
Nick Ho committed
745
{
746
  int                      UE_id         =  -1;
747
  LTE_DL_FRAME_PARMS    *fp           =  &eNB->frame_parms;
748 749 750 751 752 753
  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;
754

755
  eNB->DCI_pdu = (DCI_PDU_NB_IoT*)malloc(sizeof(DCI_PDU_NB_IoT));
756

757 758
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));

759
  // check DCI format is N1 (format 0)
760 761
  if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0)
    {
762
      //check DCI format N1 is for RAR  rnti_type  in FAPI specs table 4-45
763
      if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type == 1)
764
        {
765

766
        //mapping the fapi parameters to the oai parameters
767 768

          DCI_format = DCIFormatN1_RAR;
769 770 771 772 773 774 775

          //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;
776
          DCI_Content->DCIN1_RAR.RepNum         = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
777 778 779 780
          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;

Nick Ho's avatar
Nick Ho committed
781

782 783
          //TODO calculate the number of common repetitions
          //fp->nprach_config_common.number_repetition_RA = see TS 36.213 Table 16.1-3
784

785
          // fill the dlsch_ra_NB structure for RAR, and packed the DCI PDU
786

787
          ndlsch               =  eNB->ndlsch_RAR;
788
          ndlsch->ndlsch_type  =  RAR;
789

790 791 792
          ndlsch->rnti         =  dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti;

          npdcch               =  eNB->npdcch_DCI;
793
           
Nick Ho's avatar
Nick Ho committed
794
          LOG_D(PHY,"Generating pdcch params for DCIN1 RAR and packing DCI\n");
795 796
          //LOG_I(PHY,"Rep of DCI is : %d\n",DCI_Content->DCIN1_RAR.RepNum);

797
          //LOG_I(PHY,"Generating dlsch params for RA_RNTI and packing DCI\n");
798 799 800 801 802 803
          generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
                                                    frame,
                                                    subframe,
                                                    DCI_Content,
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
                                                    DCI_format,
804
                                                    npdcch,
805 806
                                                    fp,
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
807 808
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol,
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.ncce_index);
809

810
        //printf("PHY_vars_eNB_g[0][0]->ndlsch_RAR->rnti = %d\n",PHY_vars_eNB_g[0][0]->ndlsch_RAR->rnti);
811
          //eNB->dlsch_ra_NB->nCCE[subframe] = eNB->DCI_pdu->dci_alloc.firstCCE;
812
        }
813
      else
814 815
        { //managing data

816 817 818
        //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");
819

820

821
            //mapping the fapi parameters to the oai parameters
822

823
            DCI_format = DCIFormatN1;
824

825 826 827 828 829 830
              //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;
831
              DCI_Content->DCIN1.RepNum         = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
832 833 834 835
              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;

836 837 838 839

              //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");
Matthieu Kanj's avatar
Matthieu Kanj committed
840
              npdcch->repetition_idx[(uint8_t)UE_id] = 0; //this is used for the encoding mechanism to understand that is the first transmission
841 842

              if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level) //whenever aggregation level is =1 we have only 1 repetition for USS
Matthieu Kanj's avatar
Matthieu Kanj committed
843
              npdcch->repetition_number[(uint8_t)UE_id] = 1;
844 845
              else
              {
846
                //see TS 36.213 Table 16.1-1
847 848 849
              }


850 851
              //fill the ndlsch structure for UE and packed the DCI PD

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

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

Nick Ho's avatar
Nick Ho committed
857
            LOG_I(PHY,"Generating dlsch params for DCIN1 data and packing DCI\n");
858 859 860 861 862 863
            generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
                                                      frame,
                                                      subframe,
                                                      DCI_Content,
                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
                                                      DCI_format,
864
                                                      npdcch,
865 866
                                                      fp,
                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
867 868
                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol,
                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.ncce_index);
869 870

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


873 874 875 876 877 878 879 880 881
        }
    }
  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
882 883 884 885 886 887


}



888
void generate_eNB_ulsch_params_NB_IoT(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu) {
889

890
  int UE_id = -1;
891
  //int harq_pid = 0;
Nick Ho's avatar
Nick Ho committed
892

893 894
  DCI_CONTENT *DCI_Content;
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
895 896

  //mapping the fapi parameters to the OAI parameters
897 898 899 900 901 902 903 904 905
  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;
906 907


908

909
  UE_id = find_ue_NB_IoT(hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti, eNB);
910
  AssertFatal(UE_id == -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
911 912


Nick Ho's avatar
Nick Ho committed
913 914
  /*Log for generate ULSCH DCI*/

915 916 917 918 919 920 921
  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,
922
                                            hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.start_symbol);  
923

Nick Ho's avatar
Nick Ho committed
924 925
  
  //LOG for ULSCH DCI Resource allocation
926
  //CBA is not used in NB-IoT
927
    eNB->nulsch[UE_id]->harq_process->subframe_scheduling_flag = 1;
Nick Ho's avatar
Nick Ho committed
928 929 930
  
}

931 932


933 934 935
/*
 * for NB-IoT ndlsch procedure
 * this function is called by the PHy procedure TX in 3 possible occasion:
936
 * 1) we manage BCCH pdu (SI)
937 938
 * 2) we manage RA dlsch pdu
 * 3) UE-specific dlsch pdu
939 940 941 942
 * ** 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
 */
943
void npdsch_procedures(PHY_VARS_eNB_NB_IoT      *eNB,
944 945 946 947 948
                       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
                       )
949
{
950 951 952 953 954 955 956 957
  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];
958
  //uint8_t DLSCH_pdu_rar[256];
959
  int                     i;
960 961

  LOG_D(PHY,
962 963 964 965 966 967
        "[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
968
        );
969

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

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

974
        DLSCH_pdu = pdu;
975

976 977 978 979 980 981
      /*
       * 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)
       *
       */
982

983 984 985 986 987
        //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)
988 989 990
    }

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

992
      DLSCH_pdu = DLSCH_pdu_tmp;
993

994
      for (i=0; i<input_buffer_length; i++)
995

996
         DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
997 998 999
    }
  }
  else {
1000
    //We are doing a retransmission (harq round > 0
1001 1002
    #ifdef DEBUG_PHY_PROC
    #ifdef DEBUG_DLSCH
1003
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
1004 1005
    #endif
    #endif
1006 1007 1008 1009 1010
  }

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


1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
    //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;
    }
1023 1024


1025 1026 1027 1028 1029
   /*
    * 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)
    */
1030 1031


1032 1033 1034 1035 1036 1037 1038
  /*
   * 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)
   */
1039 1040 1041 1042 1043 1044


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

    /*
1045 1046
     *
     * REASONING:
1047 1048 1049 1050
   * 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)
1051 1052
     *
     * 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
1053 1054
     * NB: switch case of G is the same for npdsch and npdcch
     *
1055 1056 1057
     * 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
1058 1059
     *  -- if operationModeInfo set to 00 or 01 (in band) --> npdsch_start_sysmbol = 3
     *  -- otherwise --> npdsch_start_symbol = 0
1060
     * -if the k subframe is not for SIB1-NB
1061
     *  --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])
1062
     * - otherwise --> npdsch_start_symbol = 0
1063
     * (is the starting OFDM for the NPDSCH transmission in the first slot in a subframe k)
1064 1065
     * 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)
1066 1067 1068 1069 1070
     * Nsf needed as an input (number of subframe)-->inside harq_process of ndlsch
     */

    switch(ndlsch->npdsch_start_symbol)
    {
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
      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;
1086 1087

    }
1088
    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
1089 1090
    LOG_I(PHY, "NB-IoT Encoding step\n");

1091
    //    eNB->te(eNB,
1092 1093 1094 1095 1096 1097 1098
    //      DLSCH_pdu,
    //      num_pdcch_symbols,
    //      dlsch,
    //      frame,subframe,
    //      &eNB->dlsch_rate_matching_stats,
    //      &eNB->dlsch_turbo_encoding_stats,
    //      &eNB->dlsch_interleaving_stats);
1099 1100


1101
   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
1102 1103 1104 1105

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

1106
   // start_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
1107 1108
    LOG_I(PHY, "NB-IoT Scrambling step\n");

1109 1110 1111 1112 1113 1114
    /*
     * SOME RELEVANT FACTS:
     *
     *
     */

1115
      //    dlsch_scrambling(fp,
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
      //         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);
1128

1129
    //stop_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
1130 1131 1132


    //modulation-------------------------------------------
1133
    //start_meas_NB_IoT(&eNB->dlsch_modulation_stats);
1134 1135
    LOG_I(PHY, "NB-IoT Modulation step\n");

1136
    //    dlsch_modulation(eNB,
1137 1138 1139 1140 1141 1142
    //         eNB->common_vars.txdataF[0],
    //         AMP,
    //         subframe,
    //         num_pdcch_symbols,
    //         dlsch,
    //         dlsch1);
1143

1144
    //stop_meas_NB_IoT(&eNB->dlsch_modulation_stats);
1145 1146 1147 1148 1149
  }


#ifdef PHY_ABSTRACTION
  else {
1150
    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
1151
    //dlsch_encoding_emul(eNB,
1152 1153
      //DLSCH_pdu,
      //dlsch);
1154
   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
1155 1156 1157 1158 1159
  }

#endif
  ndlsch->active = 0;
}
1160 1161


1162
extern int oai_exit;
1163 1164

/*
1165
 * ASSUMPTION
1166 1167 1168
 *
 * The MAC schedule the schedule_response in a SUBFRAME BASE (at least because otherwise we have problem with our assumptions on SI transmission)
 *
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
 *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)
1181
 * -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
1182 1183
 * -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.
1184
 *
1185 1186 1187 1188
 * 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)
 *
 *
1189
 *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
1190 1191 1192
 *
 * **relevant aspects for the System information Transmission (Table 4-47 NDLSCH FAPi specs)
 * 1)RNTI type = 0 (contains a BCCH)
1193 1194
 * 2)Repetition number == scheduling info SIB1 mapped into 4-8-16
 * 3)RNTI (0xFFFF = SI-RNTI)
1195 1196 1197
 * (see schedule_response implementation)
 *
 */
1198 1199 1200 1201 1202 1203 1204

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

1205
void phy_procedures_eNB_TX_NB_IoT(PHY_VARS_eNB_NB_IoT     *eNB,
1206 1207
                                  eNB_rxtx_proc_t  *proc,
                                  int                     do_meas)
1208
{
1209 1210 1211 1212 1213 1214 1215 1216
  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;
1217
  //NB_IoT_eNB_NPDCCH_t*npdcch;
1218

1219
  if(do_meas == 1)
1220
    //start_meas_NB_IoT(&eNB->phy_proc_tx);
1221 1222


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

1225
  // clear the transmit data array for the current subframe
1226 1227 1228 1229 1230 1231
  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));
    } 

1232
  //generate NPSS/NSSS
1233
 // common_signal_procedures_NB_IoT(eNB,proc);  // to uncomment after NB-IoT testing
1234

1235
    //Generate MIB
1236
    if(subframe ==0 && (eNB->npbch != NULL))
1237 1238
     {
          if(eNB->npbch->pdu != NULL)
1239
          {
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249
            //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
             *
             */
Matthieu Kanj's avatar
Matthieu Kanj committed
1250
/*
1251
            generate_npbch(eNB->npbch,
1252 1253 1254
                           txdataF,
                           AMP,
                           fp,
1255
                           eNB->npbch->pdu,
1256
                           frame%64,
Matthieu Kanj's avatar
Matthieu Kanj committed
1257
                           fp->NB_IoT_RB_ID);*/
1258
                        
1259 1260 1261 1262 1263
          }

          //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)
1264
          {
1265
            eNB->npbch->pdu = NULL;
1266
          }
1267
      }
Nick Ho's avatar
Nick Ho committed
1268

1269

1270
    //Check for SIB1-NB transmission
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
    /*
     *
     * 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)
     *
     */
1284
    if(subframe == 4 && eNB->ndlsch_SIB1 != NULL && eNB->ndlsch_SIB1->harq_process->status == ACTIVE_NB_IoT)
1285
    {
1286
      //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
1287
      sib1_startFrame = is_SIB1_NB_IoT(frame,
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
                                       (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;
      }
1307

1308
    }
1309

1310 1311

    //Check for SI transmission
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
    /*
     *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)
     *
1325 1326
     * [This condition should be known by the MAC layer so it should trigger an DLSCH pdu only at proper instants]
     *
1327 1328 1329 1330
     * 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)
     *
     *
1331
     *XXX important: set the flag HARQ process->status to DISABLE when PHY finished the SI-transmission over the 2 or 8 subframes
1332 1333 1334
     *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)
1335
     *
1336
     */
1337

1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367
  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;

              }
           }

  }
1368

1369
      ///check for RAR transmission
1370
      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
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
        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

           }
      }
1400
      }
1401 1402


1403
      //check for UE specific transmission
1404 1405
      /*
       * Delays between DCI transmission and NDLSCH transmission are taken in consideration by the MAC scheduler by sending in the proper subframe the scheduler_response
1406 1407
       * (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)
1408 1409 1410 1411
       * 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)
       *
1412 1413 1414 1415 1416 1417 1418 1419
       * 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
1420 1421
       *
       */
1422

1423
      //this should give only 1 result (since only 1 ndlsch procedure is activated at once) so we brak after the transmission
1424
      for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
1425
      {
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451
        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;

               }
          }
        }
1452

1453

1454
      }
1455 1456


1457 1458 1459
      //no dedicated phy config


1460 1461 1462
      /*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
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
       *
       * 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
1477
       * -npdcch-NumRepetitionPaging (common)
1478
       * -npdcch-NumRepetitions-RA (common) [inside the NB_IoT_DL_FRAME_PARMS-> nprach_ParametersList] --> configured in phy_config_sib2
1479
       *
1480
       *  PROBLEM: in FAPI specs seems there is no way to trasnmit Rmax to the PHY (waiting for answers)
1481
       *
1482
       * *Rmax is also needed for evaluate the scheduling delay for NDLSCH (see scheduling delay field in NPDCCH PDU FAPI)
1483
       *
1484 1485 1486 1487 1488
       * *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)
1489 1490 1491
       *
       * */

1492

1493
      for(UE_id = 0 ; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
1494
      {
Matthieu Kanj's avatar
Matthieu Kanj committed
1495
        if(eNB->npdcch[(uint8_t)UE_id] != NULL && eNB->npdcch[(uint8_t)UE_id]->rnti[(uint8_t)UE_id] == dci_pdu->dci_alloc->rnti && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4))
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
        {
            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)
Matthieu Kanj's avatar
Matthieu Kanj committed
1510
                                          eNB->npdcch[(uint8_t)UE_id]->repetition_idx[(uint8_t)UE_id]++; //can do also inside also the management
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527

                  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)
                
Matthieu Kanj's avatar
Matthieu Kanj committed
1528
                eNB->npdcch[(uint8_t)UE_id]->repetition_idx[(uint8_t)UE_id]++; //can do also inside also the management
1529

1530 1531
              break;
              }
1532

1533 1534 1535
             }
           }
        }
1536

1537 1538
}

Matthieu Kanj's avatar
Matthieu Kanj committed
1539
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) {
1540 1541

  uint32_t estimated_TA; 
Matthieu Kanj's avatar
Matthieu Kanj committed
1542
  //int frame,frame_mod;    // subframe,
Matthieu Kanj's avatar
Matthieu Kanj committed
1543
 // subframe = eNB->proc.subframe_prach; 
Matthieu Kanj's avatar
Matthieu Kanj committed
1544 1545
 // frame = eNB->proc.frame_prach;
    estimated_TA = process_nprach_NB_IoT(eNB,frame,subframe,rnti,preamble_index,timing_advance);
1546
    //printf("estim = %i\n",estimated_TA);
Matthieu Kanj's avatar
Matthieu Kanj committed
1547
 // }
1548
  return estimated_TA;
1549 1550 1551
}


Matthieu Kanj's avatar
Matthieu Kanj committed
1552
void fill_crc_indication_NB_IoT(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe,uint8_t crc_flag, uint8_t ACK_NACK) {
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563

  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;
Matthieu Kanj's avatar
Matthieu Kanj committed
1564 1565 1566
  ///////////////////////pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
  pdu->rx_ue_information.rnti                         = eNB->ulsch_NB_IoT[0]->rnti;              /// OK
  //////////////////////////pdu->crc_indication_rel8.tl.tag                     = NFAPI_CRC_INDICATION_REL8_TAG;
1567 1568
  pdu->crc_indication_rel8.crc_flag                   = crc_flag;

Matthieu Kanj's avatar
Matthieu Kanj committed
1569 1570 1571 1572 1573 1574
  if(ACK_NACK == 1)
  {
      eNB->UL_INFO.crc_ind.number_of_crcs++;
  } else {
     eNB->UL_INFO.crc_ind.number_of_crcs =0;
  }
1575 1576 1577 1578 1579
  //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);
}

Matthieu Kanj's avatar
Matthieu Kanj committed
1580
void fill_rx_indication_NB_IoT(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t data_or_control, uint8_t msg3_flag, uint8_t ACK_NACK)
1581 1582 1583 1584 1585
{
      nfapi_rx_indication_pdu_t *pdu;

      pthread_mutex_lock(&eNB->UL_INFO_mutex);

Matthieu Kanj's avatar
Matthieu Kanj committed
1586 1587 1588 1589 1590 1591 1592
      
      if(ACK_NACK == 1)
      { 
          eNB->UL_INFO.RX_NPUSCH.number_of_pdus  = 1;
      } else {
          eNB->UL_INFO.RX_NPUSCH.number_of_pdus  = 0;
      }
1593 1594 1595 1596 1597 1598 1599 1600 1601 1602
      //eNB->UL_INFO.RX_NPUSCH.rx_pdu_list.rx_ue_information.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;   // do we need this ?? 
      //eNB->UL_INFO.RX_NPUSCH.rx_pdu_list.rx_ue_information.rnti = rnti;  // rnti should be got from eNB structure
      //pdu                                    = &eNB->UL_INFO.RX_NPUSCH.rx_pdu_list[eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus];
      pdu                                    = &eNB->UL_INFO.RX_NPUSCH.rx_pdu_list[0];
      //  pdu->rx_ue_information.handle          = eNB->ulsch[UE_id]->handle;
      // pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
      //pdu->rx_indication_rel8.tl.tag         = NFAPI_RX_INDICATION_REL8_TAG;
      pdu->rx_ue_information.rnti            = eNB->ulsch_NB_IoT[0]->rnti;
     

Matthieu Kanj's avatar
Matthieu Kanj committed
1603
      /*if(msg3_flag == 1)
1604 1605 1606 1607 1608 1609 1610 1611 1612
      {
          pdu->rx_indication_rel8.length         = 6; //eNB->ulsch_NB_IoT[0]->harq_process->TBS>>3;
          int m =0;
          for(m=0; m<6;m++)
          { 
              pdu->data[m]  = eNB->ulsch_NB_IoT[0]->harq_process->b[2+m];
              printf(" pdu content = %d \n", eNB->ulsch_NB_IoT[0]->harq_process->b[2+m]);
          }        
          
Matthieu Kanj's avatar
Matthieu Kanj committed
1613 1614
      } else { */  
          pdu->rx_indication_rel8.length         = eNB->ulsch_NB_IoT[0]->harq_process->TBS/8; //eNB->ulsch_NB_IoT[0]->harq_process->TBS>>3;
1615
          pdu->data  = eNB->ulsch_NB_IoT[0]->harq_process->b;
Matthieu Kanj's avatar
Matthieu Kanj committed
1616
      //}
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627
      //pdu->data                              = eNB->ulsch_NB_IoT[UE_id]->harq_processes[harq_pid]->b;   
      //eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++;
      //eNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | subframe;

      // do we need to transmit timing ?? however, the nfapi structure does not include timing paramters !!!!!

      pthread_mutex_unlock(&eNB->UL_INFO_mutex);

}


1628

Matthieu Kanj's avatar
Matthieu Kanj committed
1629
void npusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
1630 1631 1632 1633
{
  
  uint32_t i;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
Matthieu Kanj's avatar
Matthieu Kanj committed
1634 1635 1636 1637
  NB_IoT_eNB_NULSCH_t *nulsch;
  NB_IoT_UL_eNB_HARQ_t *nulsch_harq;
  nulsch = eNB->ulsch_NB_IoT[0];
  nulsch_harq = nulsch->harq_process;
1638

1639 1640
  const int rx_subframe   =   proc->subframe_rx;
  const int rx_frame      =   proc->frame_rx;
1641

1642
  int   RB_IoT_ID         = 22;
Matthieu Kanj's avatar
Matthieu Kanj committed
1643 1644
  //for (i=0; i<NUMBER_OF_UE_MAX; i++)
  for (i=0; i<1; i++)
1645
  {
Matthieu Kanj's avatar
Matthieu Kanj committed
1646 1647
      //ulsch_NB_IoT = eNB->ulsch_NB_IoT[i];
      //ulsch_harq = ulsch_NB_IoT->harq_process;
1648 1649
      // if eNB is ready to receive UL data 
      // define a flag to trigger on or off the decoding process
Matthieu Kanj's avatar
Matthieu Kanj committed
1650 1651 1652 1653 1654 1655 1656
     rx_ulsch_Gen_NB_IoT(eNB,
                           proc,
                           0,                         // this is the effective sector id
                           0,
                           RB_IoT_ID,                        // 22 , to be included in // to be replaced by NB_IoT_start ??
                           rx_subframe,  // first received subframe 
                           rx_frame);     // first received frame
1657 1658
   }  // for UE loop

1659
}