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

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

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

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

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

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

#include "T.h"

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

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

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

69
/*
70 71 72 73 74 75 76

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

//#define DIAG_PHY

81
///#define NS_PER_SLOT 500000
82

83
///#define PUCCH 1
84 85 86

//DCI_ALLOC_t dci_alloc[8];

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

91
/*
92 93 94 95 96 97 98 99 100 101
#if defined(SMBV) 
extern const char smbv_fname[];
extern unsigned short config_frames[4];
extern uint8_t smbv_frame_cnt;
#endif

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

102
*/
103

104 105 106



107 108 109 110
/* For NB-IoT, we put NPBCH in later part, since it would be scheduled by MAC scheduler
* It generates NRS/NPSS/NSSS
*
*/
111
void common_signal_procedures_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IoT_t *proc) 
112
{
113 114 115 116 117 118 119
  NB_IoT_DL_FRAME_PARMS   *fp       =  &eNB->frame_parms_NB_IoT;
  int                     **txdataF =  eNB->common_vars.txdataF[0];
  int                     subframe  =  proc->subframe_tx;
  int                     frame     =  proc->frame_tx;
  uint16_t                Ntti      =  10;                      //ntti = 10
  int                     RB_IoT_ID;                            // XXX should be initialized (RB reserved for NB-IoT, PRB index)
  int                     With_NSSS;                            // With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
  
  /*NSSS only happened in the even frame*/
  if(frame%2==0)
    {
      With_NSSS = 1;
    }
  else
    {
      With_NSSS = 0;
    }
    
  /*NPSS when subframe 5*/
  if(subframe == 5)
    {
      generate_npss_NB_IoT(txdataF,
135 136 137 138 139
                           AMP,
                           fp,
                           3,
                           0,
                           RB_IoT_ID);
140 141 142
    }
    
  /*NSSS when subframe 9 on even frame*/
Nick Ho's avatar
Nick Ho committed
143
  else if((subframe == 9)&&(With_NSSS == 1))
144
    {
Nick Ho's avatar
Nick Ho committed
145
      generate_sss_NB_IoT(txdataF,
146 147 148 149 150 151 152 153
                          AMP,
                          fp,
                          3,
                          0,
                          frame,
                          RB_IoT_ID);
    }

Nick Ho's avatar
Nick Ho committed
154 155 156 157
  else
  {
    /*NRS*/
    generate_pilots_NB_IoT(eNB,
158 159 160 161 162
                           txdataF,
                           AMP,
                           Ntti,
                           RB_IoT_ID,
                           With_NSSS);
Nick Ho's avatar
Nick Ho committed
163
  }
164 165 166
  
}

167
void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IoT_t *proc,UL_IND_t *UL_INFO)
168 169
{
  //RX processing for ue-specific resources (i
170

171
  uint32_t                  ret=0,i,j,k;
172
  uint32_t                  harq_pid;   // round;
173 174 175 176
  int                       sync_pos;
  uint16_t                  rnti=0;
  uint8_t                   access_mode;
  NB_IoT_DL_FRAME_PARMS     *fp=&eNB->frame_parms_NB_IoT;
177

178 179
  const int subframe    =   proc->subframe_rx;
  const int frame       =   proc->frame_rx;
180 181 182
  
  /*NB-IoT IF module Common setting*/

183 184 185 186
  UL_INFO->module_id    = eNB->Mod_id;
  UL_INFO->CC_id        = eNB->CC_id;
  UL_INFO->frame        =  frame;
  UL_INFO->subframe     = subframe;
187 188 189 190

  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),
191 192
    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));
193 194 195 196

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

  //check if any RB using in this UL subframe
197 198 199 200
  eNB->rb_mask_ul[0] = 0;
  eNB->rb_mask_ul[1] = 0;
  eNB->rb_mask_ul[2] = 0;
  eNB->rb_mask_ul[3] = 0;
201 202 203

  // 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.
204
  harq_pid = subframe2harq_pid_NB_IoT(fp,frame,subframe);
205 206 207
  // delete the cba
  // delete the srs
  /*Loop over the UE, i is the UE ID */
208
  for (i=0; i<NUMBER_OF_UE_MAX_NB_IoT; i++) 
209
    {
210

211 212 213 214 215
      // delete srs 
      // delete Pucch procedure
      // check for Msg3
      if (eNB->mac_enabled==1) 
        {
216
          if (eNB->UE_stats[i].mode == RA_RESPONSE_NB_IoT) 
217 218 219 220 221
            {
	             /*Process Msg3 TODO*/
              //process_Msg3(eNB,proc,i,harq_pid);
            }
        }
222

223
      eNB->pusch_stats_rb[i][(frame*10)+subframe]    = -63;
224
      eNB->pusch_stats_round[i][(frame*10)+subframe] = 0;
225
      eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = -63;
226

227
      /*Check if this UE is has ULSCH scheduling*/
228 229 230
      if ((eNB->nulsch[i]) &&
          (eNB->nulsch[i]->rnti>0) &&
          (eNB->nulsch[i]->harq_process->subframe_scheduling_flag==1)) 
231 232
        {
          // UE is has ULSCH scheduling
233
          //////////////////////////////////////round = eNB->nulsch[i]->harq_process->round; //commented to remove warning, to be added if round is used
234
          /*NB-IoT The nb_rb always set to 1 */
235
          for (int rb=0;rb<=eNB->nulsch[i]->harq_process->nb_rb;rb++) 
236
            {
237 238
	             int rb2 = rb+eNB->nulsch[i]->harq_process->first_rb;
               eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
239
            }
240

241
          /*Log for what kind of the ULSCH Reception*/
242

243 244
          /*Calculate for LTE C-RS*/
          //nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
245

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

248
          if (fp->frame_type == FDD_NB_IoT ) 
249 250 251
            {
              int sf = (subframe<4) ? (subframe+6) : (subframe-4);
              /*After Downlink Data transmission, simply have a notice to received ACK from PUCCH, I think it's not use for now */
252
              if (eNB->ndlsch[i]->subframe_tx[sf]>0) // we have downlink transmission
253
                { 
254
                  eNB->nulsch[i]->harq_process->O_ACK = 1;
255 256 257
                } 
              else 
                {
258
                  eNB->nulsch[i]->harq_process->O_ACK = 0;
259 260
                }
            }
261

262
          eNB->pusch_stats_rb[i][(frame*10)+subframe]    = eNB->nulsch[i]->harq_process->nb_rb;
263
          eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->nulsch[i]->harq_process->round;
264
          eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = eNB->nulsch[i]->harq_process->mcs;
265 266
/*
  need for rx_ulsch function for NB_IoT
267

268 269 270
          rx_ulsch(eNB,proc,
                  eNB->UE_stats[i].sector,  // this is the effective sector id
                  i,
271
                  eNB->nulsch,
272
                  0);
273
*/
274
          ret = ulsch_decoding_NB_IoT(eNB,proc,
275 276 277 278
                                      i,
                                      0, // control_only_flag
                                      eNB->nulsch[i]->harq_process->V_UL_DAI,
			                                eNB->nulsch[i]->harq_process->nb_rb>20 ? 1 : 0);
279

280
          //compute the expected ULSCH RX power (for the stats)
281 282 283
          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;
284 285
          if (eNB->nulsch[i]->harq_process->cqi_crc_status == 1) {

286
              extract_CQI(eNB->nulsch[i]->harq_process->o,
287 288 289 290 291
                          eNB->nulsch[i]->harq_process->uci_format,
                          &eNB->UE_stats[i],
                          fp->N_RB_DL,
                          &rnti, &access_mode);
            
292
              eNB->UE_stats[i].rank = eNB->nulsch[i]->harq_process->o_RI[0];
293
          }
294

295 296 297 298 299 300 301 302
          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),
303
                T_INT(harq_pid));
304

305 306 307 308
              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++;
309

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

312 313 314
          if (eNB->nulsch[i]->Msg3_flag == 1) 
          {
	             /*dump_ulsch(eNB,proc,i);
315 316
	             exit(-1);*/

317 318 319 320 321 322 323 324 325 326 327
               /*In NB-IoT MSG3 */
                // activate retransmission for Msg3 (signalled to UE PHY by DCI
                eNB->nulsch[(uint32_t)i]->Msg3_active = 1;
                /* Need to check the procedure for NB-IoT (MSG3) retransmission
                get_Msg3_alloc_ret(fp,subframe,frame,&eNB->ulsch[i]->Msg3_frame,&eNB->ulsch[i]->Msg3_subframe);
                mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, eNB->ulsch[i]->rnti,eNB->ulsch[i]->Msg3_frame, eNB->ulsch[i]->Msg3_subframe);
                */
                T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
                  T_INT(i), T_INT(eNB->nulsch[i]->rnti), T_INT(0 /* 0 is for retransmission*/),
                  T_INT(eNB->nulsch[i]->Msg3_frame), T_INT(eNB->nulsch[i]->Msg3_subframe));     
          } // This is Msg3 error
328
          else 
329 330
          { //normal ULSCH
              if (eNB->nulsch[i]->harq_process->round== eNB->nulsch[i]->Mlimit) 
331
                {
332 333
                  eNB->nulsch[i]->harq_process->round=0;
                  eNB->nulsch[i]->harq_process->phich_active=0;
334
                  eNB->UE_stats[i].ulsch_errors[harq_pid]++;
335 336 337
                  eNB->UE_stats[i].ulsch_consecutive_errors++; 
                  /*if (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb > 20) {
		                dump_ulsch(eNB,proc,i);
338
	 	              exit(-1);
339 340 341
                  }*/
	                // indicate error to MAC
	                if (eNB->mac_enabled == 1)
342
                    {
343
                      //instead rx_sdu to report The Uplink data not received successfully to MAC
344
                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag = 1;
Nick Ho's avatar
Nick Ho committed
345
                       UL_INFO->crc_ind.number_of_crcs++;
346 347 348 349
                      (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
350
                       UL_INFO->RX_NPUSCH.number_of_pdus++;
351
                    }
352 353 354 355 356
                }
            }
        }  // ulsch in error
        else 
          {
357
            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),
358
              T_INT(harq_pid));
359

360
          // Delete MSG3  log for the PHICH 
361

362
          for (j=0; j<fp->nb_antennas_rx; j++)
363 364
          //this is the RSSI per RB
          eNB->UE_stats[i].UL_rssi[j] =
365
            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 -
366
            hundred_times_log10_NPRB_NB_IoT[eNB->nulsch[i]->harq_process->nb_rb-1]/100 -
367
            get_hundred_times_delta_IF_eNB_NB_IoT(eNB,i,harq_pid, 0)/100;
368 369 370
          //for NB-IoT PHICH not work
	        /*eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
          eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 1;*/
371
          eNB->nulsch[i]->harq_process->round = 0;
372
          eNB->UE_stats[i].ulsch_consecutive_errors = 0;
373

374
          if (eNB->nulsch[i]->Msg3_flag == 1) 
375
            {
376 377 378 379 380 381 382
	            if (eNB->mac_enabled==1) 
                {
	                LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
		                    eNB->Mod_id,frame,harq_pid,i);
	                if (eNB->mac_enabled)
                    {
                      // store successful MSG3 in UL_Info instead rx_sdu
383
                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
Nick Ho's avatar
Nick Ho committed
384
                      UL_INFO->crc_ind.number_of_crcs++;
385 386 387 388
                      (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
389
                      UL_INFO->RX_NPUSCH.number_of_pdus++;
390
                    }
391

392 393 394 395 396 397 398 399 400 401 402
	                /* Need check if this needed in NB-IoT
	                // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
	                if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	               eNB->UE_stats[i].mode = PRACH;
	               mac_xface->cancel_ra_proc(eNB->Mod_id,
					       eNB->CC_id,
					       frame,
					       eNB->UE_stats[i].crnti);
	               mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
	               eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
	               } // Msg3_flag == 0*/
403
	    
404 405
	            } // mac_enabled==1

406
            eNB->UE_stats[i].mode     = PUSCH;
407
            eNB->nulsch[i]->Msg3_flag = 0;
408 409 410 411 412 413

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

            /*Init HARQ parameters, need to check*/
            for (k=0; k<8; k++) 
              { //harq_processes
414
                for (j=0; j<eNB->ndlsch[i]->Mlimit; j++) 
415
                  {
416 417 418
                    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;
419 420
                  }

421 422 423
                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;
424

425
                for (j=0; j<eNB->nulsch[i]->Mlimit; j++) 
426
                  {
427 428 429 430
                    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;
431 432
                  }
              }
433

434 435 436
            eNB->UE_stats[i].dlsch_sliding_cnt  = 0;
            eNB->UE_stats[i].dlsch_NAK_round0   = 0;
            eNB->UE_stats[i].dlsch_mcs_offset   = 0;
437 438 439
          } // Msg3_flag==1
	       else 
          {  // Msg3_flag == 0
440
	          if (eNB->mac_enabled == 1) 
441 442
              {
                  // store successful Uplink data in UL_Info instead rx_sdu
443
                  (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
Nick Ho's avatar
Nick Ho committed
444
                  UL_INFO->crc_ind.number_of_crcs++;
445 446 447 448
                  (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
449
                  UL_INFO->RX_NPUSCH.number_of_pdus++;
450
	    
451 452
	            } // mac_enabled==1
          } // Msg3_flag == 0
453

454
            // estimate timing advance for MAC
455
              sync_pos                               = NB_IoT_est_timing_advance_pusch(eNB,i);
456 457 458 459
              eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check

      }  // ulsch not in error

460

461
      // Process HARQ only in NPUSCH
Nick Ho's avatar
Nick Ho committed
462
      /*process_HARQ_feedback(i,
463 464 465 466
                            eNB,proc,
                            1, // pusch_flag
                            0,
                            0,
Nick Ho's avatar
Nick Ho committed
467
                            0);*/
468

469

470 471
      

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

474 475 476 477 478 479

    // update ULSCH statistics for tracing




480
  } // loop i=0 ... NUMBER_OF_UE_MAX-1
481 482 483 484 485

}

#undef DEBUG_PHY_PROC

486
/*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
487

488
void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IoT_t * proc,nfapi_dl_config_request_pdu_t *dl_config_pdu) 
Nick Ho's avatar
Nick Ho committed
489
{
490
  int UE_id = -1;
491
  NB_IoT_DL_FRAME_PARMS *fp=&eNB->frame_parms_NB_IoT;
Nick Ho's avatar
Nick Ho committed
492
  int frame = proc->frame_tx;
493
  int subframe = proc->subframe_tx;
494
  DCI_CONTENT *DCI_Content; 
495
  DCI_format_NB_IoT_t DCI_format;
496
  NB_IoT_eNB_NDLSCH_t *ndlsch;
497
  NB_IoT_eNB_NPDCCH_t *npdcch;
498

499
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
Nick Ho's avatar
Nick Ho committed
500

501

502
  // check DCI format is N1 (format 0)
503 504
  if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0)
    {
505
      //check DCI format N1 is for RAR  rnti_type  in FAPI specs table 4-45
506
      if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type == 1)
507
        {
508

509 510 511
    	  //mapping the fapi parameters to the oai parameters

          DCI_format = DCIFormatN1_RAR;
512 513 514 515 516 517 518

          //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;
519
          DCI_Content->DCIN1_RAR.RepNum			= dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
520 521 522 523
          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;

524 525
          //TODO calculate the number of common repetitions
          //fp->nprach_config_common.number_repetition_RA = see TS 36.213 Table 16.1-3
526

527
          // fill the dlsch_ra_NB structure for RAR, and packed the DCI PDU
528 529 530 531 532

          ndlsch= eNB->ndlsch_ra;
          ndlsch->ndlsch_type = RAR;

          LOG_D(PHY,"Generating dlsch params for RA_RNTI and packing DCI\n");
533 534 535 536 537 538 539 540 541 542
          generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
                                                    frame,
                                                    subframe,
                                                    DCI_Content,
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
                                                    DCI_format,
                                                    ndlsch,
                                                    fp,
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
												                            dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol);
543 544

          //eNB->dlsch_ra_NB->nCCE[subframe] = eNB->DCI_pdu->dci_alloc.firstCCE;
545
        }
546
      else
547 548 549
        { //managing data

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

553

554
    	  	  //mapping the fapi parameters to the oai parameters
555 556

    	  	  DCI_format = DCIFormatN1;
557

558 559 560 561 562 563
              //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;
564
              DCI_Content->DCIN1.RepNum			= dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
565 566 567 568
              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;

569 570 571 572 573 574 575 576 577 578 579 580 581 582

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

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


583 584 585 586 587
              //fill the ndlsch structure for UE and packed the DCI PD

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

588
              //parameters we don't consider pdsch config dedicated since not calling the phy config dedicated step2
589 590

        	  LOG_D(PHY,"Generating dlsch params for DCIN1 data and packing DCI\n");
591 592 593 594 595 596 597 598 599 600
            generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
                                                      frame,
                                                      subframe,
                                                      DCI_Content,
                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
                                                      DCI_format,
                                                      ndlsch,
                                                      fp,
                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
													                            dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol); 
601 602

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


605 606 607 608 609 610 611 612 613
        }
    }
  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
614 615 616 617 618 619


}



620
void generate_eNB_ulsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IoT_t *proc,nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu) {
621

622
  int UE_id = -1;
623
  //int harq_pid = 0;
Nick Ho's avatar
Nick Ho committed
624

625 626
  DCI_CONTENT *DCI_Content;
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
627 628

  //mapping the fapi parameters to the OAI parameters
629 630 631 632 633 634 635 636 637
  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;
638 639


640

641
  UE_id = find_ue_NB_IoT(hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti, eNB);
642
  AssertFatal(UE_id == -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
643 644


Nick Ho's avatar
Nick Ho committed
645 646
  /*Log for generate ULSCH DCI*/

647 648 649 650 651 652 653 654
  generate_eNB_ulsch_params_from_dci_NB_IoT(eNB,
                                            proc,
                                            DCI_Content,
                                            hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti,
                                            DCIFormatN0,
                                            UE_id,
                                            hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.aggregation_level,
										                        hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.start_symbol);  
655

Nick Ho's avatar
Nick Ho committed
656 657
  
  //LOG for ULSCH DCI Resource allocation
658
  //CBA is not used in NB-IoT
659
    eNB->nulsch[(uint32_t)UE_id]->harq_process->subframe_scheduling_flag = 1;
Nick Ho's avatar
Nick Ho committed
660 661 662
  
}

663 664


665 666 667
/*
 * for NB-IoT ndlsch procedure
 * this function is called by the PHy procedure TX in 3 possible occasion:
668
 * 1) we manage BCCH pdu (SI)
669 670
 * 2) we manage RA dlsch pdu
 * 3) UE-specific dlsch pdu
671 672 673 674
 * ** 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
 */
675
void npdsch_procedures(PHY_VARS_eNB_NB_IoT *eNB,
676
						eNB_rxtx_proc_NB_IoT_t *proc, //Context data structure for RX/TX portion of subframe processing
677 678 679 680 681 682 683
						NB_IoT_eNB_NDLSCH_t *ndlsch,
						//int num_pdcch_symbols, (BCOM says are not needed
						uint8_t* pdu
									)
{
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
684
  NB_IoT_DL_eNB_HARQ_t *ndlsch_harq =ndlsch->harq_process;
685
  int input_buffer_length = ndlsch_harq->TBS/8; // get in byte //the TBS is set in generate_dlsch_param
686
  NB_IoT_DL_FRAME_PARMS *fp=&eNB->frame_parms_NB_IoT;
687 688 689 690 691 692 693
  int G;
  uint8_t *DLSCH_pdu=NULL;
  uint8_t DLSCH_pdu_tmp[input_buffer_length+4]; //[768*8];
  //uint8_t DLSCH_pdu_rar[256];
  int i;

  LOG_D(PHY,
694 695 696 697 698 699 700
	      "[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
        );
701

702
  if(ndlsch_harq->round == 0) { //first transmission so we encode... because we generate the sequence
703 704 705 706 707 708 709 710

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

    	  DLSCH_pdu =pdu;

  	  /*
  	   * 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
711
  	   * 2)all the parameters for getting the MSG3 should be given by the UL_CONFIG.request (all inside the next schedule_response function)
712 713 714 715 716 717 718 719 720 721 722
  	   *
  	   */

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

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

724
      DLSCH_pdu = DLSCH_pdu_tmp;
725

726
      for (i=0; i<input_buffer_length; i++)
727 728

	       DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
729 730 731 732
    }
  }
  else {
	  //We are doing a retransmission (harq round > 0
733 734
    #ifdef DEBUG_PHY_PROC
    #ifdef DEBUG_DLSCH
735
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
736 737
    #endif
    #endif
738 739 740 741 742
  }

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


743 744 745 746 747 748 749 750 751 752 753 754 755 756
	  //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;
	  }


757 758 759 760 761 762 763 764 765 766 767 768 769 770
	 /*
	  * in any case inside the encoding procedure is re-checked if this is round 0 or no
	  * in the case of harq_process round = 0 --> generate the sequence and put it into the parameter *c[r]
	  * otherwise do nothing(only rate maching)
	  */


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


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

    /*
777 778 779 780 781 782 783 784
     *
     * REASONING:
	 * Encoding procedure will generate a Table with encoded data ( in ndlsch structure)
	 * The table will go in input to the scrambling
	 * --we should take care if there are repetitions of data or not because scrambling should be called at the first frame and subframe in which each repetition
	 * 	begin (see params Nf, Ns)
     *
     * we should have as an iput parameter also G for the encoding based on the switch/case over eutracontrolRegionSize (if exist) and operationModeInfo if defined
785 786
     * NB: switch case of G is the same for npdsch and npdcch
     *
787 788 789 790 791 792 793 794
     * npdsch_start symbol index
     * -refers to TS 36.213 ch 16.4.1.4:
     * -if subframe k is a subframe for receiving the SIB1-NB
     *	-- if operationModeInfo set to 00 or 01 (in band) --> npdsch_start_sysmbol = 3
     *	-- otherwise --> npdsch_start_symbol = 0
     * -if the k subframe is not for SIB1-NB
     *	--npdsch_start_symbol = eutracontrolregionsize (defined for in-band operating mode (mode 0,1 for FAPI specs) and take values 1,2,3 [units in number of OFDM symbol])
     * - otherwise --> npdsch_start_symbol = 0
795
     * (is the starting OFDM for the NPDSCH transmission in the first slot in a subframe k)
796 797
     * 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)
798 799 800 801 802 803 804
     * Nsf needed as an input (number of subframe)-->inside harq_process of ndlsch
     */

    switch(ndlsch->npdsch_start_symbol)
    {
  	  case 0:
  		  G = 304;
805
	 	  break;
806 807
  	  case 1:
  		  G = 240;
808
  		break;
809 810
  	  case 2:
  		  G = 224;
811
  		break;
812 813
  	  case 3:
  		  G =200;
814
  		break;
815 816
  	  default:
  		  LOG_E (PHY,"npdsch_start_index has unwanted value\n");
817
  		break;
818 819

    }
820
    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
821 822
    LOG_I(PHY, "NB-IoT Encoding step\n");

823 824 825 826 827 828 829 830
    //    eNB->te(eNB,
    //	    DLSCH_pdu,
    //	    num_pdcch_symbols,
    //	    dlsch,
    //	    frame,subframe,
    //	    &eNB->dlsch_rate_matching_stats,
    //	    &eNB->dlsch_turbo_encoding_stats,
    //	    &eNB->dlsch_interleaving_stats);
831 832


833
   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
834 835 836 837

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

838
   // start_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
839 840
    LOG_I(PHY, "NB-IoT Scrambling step\n");

841 842 843 844 845 846
    /*
     * SOME RELEVANT FACTS:
     *
     *
     */

847 848 849 850 851 852 853 854 855 856 857 858 859
      //    dlsch_scrambling(fp,
      //		     0,
      //		     dlsch,
      //		     get_G(fp,
      //			   dlsch_harq->nb_rb,
      //			   dlsch_harq->rb_alloc,
      //			   get_Qm(dlsch_harq->mcs),
      //			   dlsch_harq->Nl,
      //			   num_pdcch_symbols,
      //			   frame,subframe,
      //			   0),
      //		     0,
      //		     subframe<<1);
860

861
    //stop_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
862 863 864


    //modulation-------------------------------------------
865
    //start_meas_NB_IoT(&eNB->dlsch_modulation_stats);
866 867
    LOG_I(PHY, "NB-IoT Modulation step\n");

868 869 870 871 872 873 874
    //    dlsch_modulation(eNB,
    //		     eNB->common_vars.txdataF[0],
    //		     AMP,
    //		     subframe,
    //		     num_pdcch_symbols,
    //		     dlsch,
    //		     dlsch1);
875

876
    //stop_meas_NB_IoT(&eNB->dlsch_modulation_stats);
877 878 879 880 881
  }


#ifdef PHY_ABSTRACTION
  else {
882
    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
883 884 885
    //dlsch_encoding_emul(eNB,
			//DLSCH_pdu,
			//dlsch);
886
   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
887 888 889 890 891
  }

#endif
  ndlsch->active = 0;
}
892 893


894
extern int oai_exit;
895 896

/*
897
 * ASSUMPTION
898 899 900
 *
 * The MAC schedule the schedule_response in a SUBFRAME BASE (at least because otherwise we have problem with our assumptions on SI transmission)
 *
901 902 903 904 905 906 907 908 909 910 911 912
 *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)
913
 * -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
914 915
 * -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.
916
 *
917 918 919 920
 * 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)
 *
 *
921
 *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
922 923 924
 *
 * **relevant aspects for the System information Transmission (Table 4-47 NDLSCH FAPi specs)
 * 1)RNTI type = 0 (contains a BCCH)
925 926
 * 2)Repetition number == scheduling info SIB1 mapped into 4-8-16
 * 3)RNTI (0xFFFF = SI-RNTI)
927 928 929
 * (see schedule_response implementation)
 *
 */
930 931 932 933 934 935 936

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

937 938 939
void phy_procedures_eNB_TX_NB_IoT(PHY_VARS_eNB_NB_IoT     *eNB,
         	 	 	 	 	                eNB_rxtx_proc_NB_IoT_t  *proc,
							                    int                     do_meas)
940
{
941 942 943 944 945 946 947 948
  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;
949
  //NB_IoT_eNB_NPDCCH_t*npdcch;
950

951
  if(do_meas == 1)
952
    //start_meas_NB_IoT(&eNB->phy_proc_tx);
953 954


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

957
  // clear the transmit data array for the current subframe
958 959 960 961 962 963
  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));
    } 

964
  //generate NPSS/NSSS
965
  common_signal_procedures_NB_IoT(eNB,proc);
966

967
    //Generate MIB
968
    if(subframe ==0 && (eNB->npbch != NULL))
969 970
     {
          if(eNB->npbch->pdu != NULL)
971 972
          {
        	  //BCOM function
973 974 975 976 977 978 979 980 981 982
        	  /*
        	   * -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
        	   *
        	   */

983 984 985 986 987 988 989
    		    generate_npbch(eNB->npbch,
                           txdataF,
                           AMP,
                           fp,
						               eNB->npbch->pdu,
                           frame%64,
                           fp->NB_IoT_RB_ID);
990
                        
991 992 993 994 995
          }

          //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)
996
          {
997
        	  eNB->npbch->pdu = NULL;
998
          }
999
      }
Nick Ho's avatar
Nick Ho committed
1000

1001

1002
    //Check for SIB1-NB transmission
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
    /*
     *
     * 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)
     *
     */
1016
    if(subframe == 4 && eNB->ndlsch_SIB1 != NULL && eNB->ndlsch_SIB1->harq_process->status == ACTIVE_NB_IoT)
1017
    {
1018
      //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
1019 1020 1021 1022
      sib1_startFrame = is_SIB1_NB_IoT(frame,
    		  	  	  	  	  	           (long)eNB->ndlsch_SIB1->harq_process->repetition_number,
								                       fp->Nid_cell,
								                       eNB->ndlsch_SIB1); //set the flags
1023
								                   
1024 1025
  	  if(sib1_startFrame != -1 && eNB->ndlsch_SIB1->harq_process->pdu != NULL)
  	  {
1026 1027 1028 1029
    	   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);
1030
  	  }
1031

1032
  	  //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
1033
  	  if((frame-sib1_startFrame)%256 == 255)
1034
  	  {
1035 1036 1037
  		    //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;
1038
  	  }
1039

1040
    }
1041

1042 1043

    //Check for SI transmission
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
    /*
     *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)
     *
1057 1058
     * [This condition should be known by the MAC layer so it should trigger an DLSCH pdu only at proper instants]
     *
1059 1060 1061 1062
     * 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)
     *
     *
1063
     *XXX important: set the flag HARQ process->status to DISABLE when PHY finished the SI-transmission over the 2 or 8 subframes
1064 1065 1066
     *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)
1067
     *
1068
     */
1069

1070
	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
1071 1072
	{
	    if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
1073
	    {
1074 1075 1076 1077
	      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,
1078 1079 1080
            					      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);
1081

1082
    		  eNB->ndlsch_SI->harq_process->status = DISABLED_NB_IoT;
1083 1084
	    	}

1085 1086 1087 1088 1089 1090 1091 1092
	     } 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);
1093

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

1096 1097
	    	      }
	         }
1098

1099
	}
1100

1101
      ///check for RAR transmission
1102
      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
1103
      {
1104 1105 1106 1107
  	    if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
  	     {
  	      if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5 && subframe != 9)
  	       {
1108

1109
  	    	  npdsch_procedures(eNB,
1110 1111 1112
            					        proc,
								              eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
								              eNB->ndlsch_ra->harq_process->pdu);
Nick Ho's avatar
Nick Ho committed
1113

1114 1115 1116 1117 1118 1119 1120 1121 1122
  	    	  //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,
1123 1124 1125
	            					        proc,
									              eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
									              eNB->ndlsch_ra->harq_process->pdu);
Nick Ho's avatar
Nick Ho committed
1126

1127 1128
	  	    	  //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
1129

1130 1131 1132
	    	   }
	    }
      }
1133 1134


1135
      //check for UE specific transmission
1136 1137
      /*
       * Delays between DCI transmission and NDLSCH transmission are taken in consideration by the MAC scheduler by sending in the proper subframe the scheduler_response
1138 1139
       * (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)
1140 1141 1142 1143
       * 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)
       *
1144 1145 1146 1147 1148 1149 1150 1151
       * 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
1152 1153
       *
       */
1154

1155
      //this should give only 1 result (since only 1 ndlsch procedure is activated at once) so we brak after the transmission
1156
      for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
1157
      {
1158
    	  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
1159
    	  {
1160 1161
    	  	if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
    	  	  {
1162
    	  	    if( subframe!= 0 && subframe != 5 && subframe != 9)
1163 1164
    	  	     {
    	  	    	npdsch_procedures(eNB,
1165 1166 1167
                						      proc,
										              eNB->ndlsch[(uint8_t)UE_id],
										              eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
1168 1169 1170 1171 1172
    	  	    	break;
    	  	       }
    	  	     }
    	    else //this frame not foresee the transmission of NSSS (subframe 9 is available)
    	    {
1173
    	    	if( subframe!= 0 && subframe != 5)
1174 1175
    	    	   {
    	  	    	npdsch_procedures(eNB,
1176 1177 1178
                						      proc,
										              eNB->ndlsch[(uint8_t)UE_id],
										              eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
1179 1180 1181 1182
    	  	    	break;

    	    	   }
    	    }
1183
    	  }
1184

1185

1186
      }
1187 1188


1189 1190 1191
      //no dedicated phy config


1192 1193 1194
      /*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
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
       *
       * 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
1209
       * -npdcch-NumRepetitionPaging (common)
1210
       * -npdcch-NumRepetitions-RA (common) [inside the NB_IoT_DL_FRAME_PARMS-> nprach_ParametersList] --> configured in phy_config_sib2
1211
       *
1212
       *  PROBLEM: in FAPI specs seems there is no way to trasnmit Rmax to the PHY (waiting for answers)
1213
       *
1214
       * *Rmax is also needed for evaluate the scheduling delay for NDLSCH (see scheduling delay field in NPDCCH PDU FAPI)
1215
       *
1216 1217 1218 1219 1220
       * *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)
1221 1222 1223
       *
       * */

1224

1225
      for(UE_id = 0 ; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
1226
      {
1227
    	  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))
1228 1229 1230 1231 1232 1233
    	  {
      	  	if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
      	  	  {
      	  	    if( subframe!= 0 && subframe != 5 && subframe != 9)
      	  	     {

1234 1235 1236 1237 1238 1239 1240 1241 1242
      	  	    	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
1243 1244 1245 1246 1247 1248 1249 1250

    		  	  	  break;
      	  	     }
      	  	  }
      	  else //this frame not foresee the transmission of NSSS (subframe 9 is available)
      	     {
      	     if( subframe!= 0 && subframe != 5)
      	      {
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
   	  	    	  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
1261 1262 1263 1264 1265 1266 1267

 		  	  	  break;
      	      }

      	     }
      	   }
    	  }
1268

1269
}