phy_procedures_lte_eNb_nb_iot.c 45.8 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"
Nick Ho's avatar
Nick Ho committed
34
#include "PHY/defs_nb_iot.h"
35
#include "PHY/extern.h" //where we get the global Sched_Rsp_t structure filled
36 37 38 39 40 41 42 43 44
#include "SCHED/defs.h"
#include "SCHED/extern.h"
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"

#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif

45 46 47
// for NB-IoT
#include "SCHED/defs_nb_iot.h"

48 49 50 51 52 53 54 55 56 57 58 59
//#define DEBUG_PHY_PROC (Already defined in cmake)
//#define DEBUG_ULSCH

#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/defs.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

#include "T.h"

#include "assertions.h"
#include "msc.h"
60

61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#include <time.h>

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


#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

//#define DIAG_PHY

#define NS_PER_SLOT 500000

#define PUCCH 1

//DCI_ALLOC_t dci_alloc[8];

#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif

#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


98 99 100 101 102 103 104 105 106 107 108 109

/* For NB-IoT, we put NPBCH in later part, since it would be scheduled by MAC scheduler
* It generates NRS/NPSS/NSSS
*
*/
void NB_common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) 
{
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int **txdataF = eNB->common_vars.txdataF[0];
  int subframe = proc->subframe_tx;
  int frame = proc->frame_tx;
  uint16_t Ntti = 10;//ntti = 10
110
  int RB_IoT_ID;// XXX should be initialized (RB reserved for NB-IoT, PRB index)
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
  int With_NSSS;// With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
  
  /*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,
                 AMP,
                 fp,
                 3,
                 0,
                 RB_IoT_ID);
    }
    
  /*NSSS when subframe 9 on even frame*/
Nick Ho's avatar
Nick Ho committed
135
  else if((subframe == 9)&&(With_NSSS == 1))
136
    {
Nick Ho's avatar
Nick Ho committed
137
      generate_sss_NB_IoT(txdataF,
138 139 140 141 142 143 144 145
                          AMP,
                          fp,
                          3,
                          0,
                          frame,
                          RB_IoT_ID);
    }

Nick Ho's avatar
Nick Ho committed
146 147 148 149 150 151 152 153 154 155
  else
  {
    /*NRS*/
    generate_pilots_NB_IoT(eNB,
               txdataF,
               AMP,
               Ntti,
               RB_IoT_ID,
               With_NSSS);
  }
156 157 158
  
}

Nick Ho's avatar
Nick Ho committed
159
void NB_phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,UL_IND_t *UL_INFO)
160 161
{
  //RX processing for ue-specific resources (i
162

163
  uint32_t ret=0,i,j,k;
164
  uint32_t harq_pid,round;
165 166 167 168 169 170 171 172 173 174
  int sync_pos;
  uint16_t rnti=0;
  uint8_t access_mode;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;

  const int subframe = proc->subframe_rx;
  const int frame    = proc->frame_rx;
  
  /*NB-IoT IF module Common setting*/

Nick Ho's avatar
Nick Ho committed
175 176 177 178
  UL_INFO->module_id = eNB->Mod_id;
  UL_INFO->CC_id = eNB->CC_id;
  UL_INFO->frame =  frame;
  UL_INFO->subframe = subframe;
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


  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),
    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
             eNB->frame_parms.samples_per_tti * 4));

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


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

  // 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.
  harq_pid = subframe2harq_pid(fp,frame,subframe);

  // delete the cba
  // delete the srs
  
  /*Loop over the UE, i is the UE ID */
204 205
  for (i=0; i<NUMBER_OF_UE_MAX; i++) 
    {
206

207 208 209 210 211 212 213 214 215 216 217 218
      // delete srs 
      // delete Pucch procedure

      // check for Msg3
      if (eNB->mac_enabled==1) 
        {
          if (eNB->UE_stats[i].mode == RA_RESPONSE) 
            {
	             /*Process Msg3 TODO*/
              //process_Msg3(eNB,proc,i,harq_pid);
            }
        }
219

220 221 222
      eNB->pusch_stats_rb[i][(frame*10)+subframe] = -63;
      eNB->pusch_stats_round[i][(frame*10)+subframe] = 0;
      eNB->pusch_stats_mcs[i][(frame*10)+subframe] = -63;
223

224 225 226 227 228 229 230 231 232 233 234 235 236
      /*Check if this UE is has ULSCH scheduling*/
      if ((eNB->ulsch[i]) &&
          (eNB->ulsch[i]->rnti>0) &&
          (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) 
        {
          // UE is has ULSCH scheduling
          round = eNB->ulsch[i]->harq_processes[harq_pid]->round;
          /*NB-IoT The nb_rb always set to 1 */
          for (int rb=0;rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;rb++) 
            {
	           int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
              eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
            }
237

238
          /*Log for what kind of the ULSCH Reception*/
239

240 241
          /*Calculate for LTE C-RS*/
          //nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
242

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
          //eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +nPRS)%12;

          if (fp->frame_type == FDD ) 
            {
              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 */
              if (eNB->dlsch[i][0]->subframe_tx[sf]>0) // we have downlink transmission
                { 
                  eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
                } 
              else 
                {
                  eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
                }
            }
258

259 260 261
          eNB->pusch_stats_rb[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
          eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->round;
          eNB->pusch_stats_mcs[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->mcs;
262

263 264 265 266 267
          rx_ulsch(eNB,proc,
                  eNB->UE_stats[i].sector,  // this is the effective sector id
                  i,
                  eNB->ulsch,
                  0);
268

269
          ret = ulsch_decoding(eNB,proc,
270 271 272
                             i,
                             0, // control_only_flag
                             eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI,
273
			                       eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
274

275 276 277 278 279 280 281 282 283 284 285 286 287
          //compute the expected ULSCH RX power (for the stats)
          eNB->ulsch[(uint32_t)i]->harq_processes[harq_pid]->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered
          eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
          eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
          if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) 
            {
              extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,
                        eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,
                        &eNB->UE_stats[i],
                      fp->N_RB_DL,
                      &rnti, &access_mode);
              eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0];
            }
288

289 290 291 292
          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->ulsch[i]->rnti),
                T_INT(harq_pid));
293

294 295 296 297
              eNB->UE_stats[i].ulsch_round_errors[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
              eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
              eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 0;
              eNB->ulsch[i]->harq_processes[harq_pid]->round++;
298

299
              LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->round);
300

301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
          if (eNB->ulsch[i]->Msg3_flag == 1) 
            {
	           /*dump_ulsch(eNB,proc,i);
	             exit(-1);*/

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

349
          // Delete MSG3  log for the PHICH 
350

351
          for (j=0; j<fp->nb_antennas_rx; j++)
352 353 354 355 356 357 358 359
          //this is the RSSI per RB
          eNB->UE_stats[i].UL_rssi[j] =
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]*
                     (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/
                     fp->ofdm_symbol_size) -
            eNB->rx_total_gain_dB -
            hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 -
            get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100;
360 361 362 363 364
          //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;*/
          eNB->ulsch[i]->harq_processes[harq_pid]->round = 0;
          eNB->UE_stats[i].ulsch_consecutive_errors = 0;
365

366
          if (eNB->ulsch[i]->Msg3_flag == 1) 
367
            {
368 369 370 371 372 373 374
	            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
Nick Ho's avatar
Nick Ho committed
375 376 377 378 379 380 381
                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag= 0;
                      UL_INFO->crc_ind.number_of_crcs++;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.rnti= eNB->ulsch[i]->rnti;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->data = eNB->ulsch[i]->harq_processes[harq_pid]->b;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_indication_rel8.length = eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3;
                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.harq_pid = harq_pid;
                      UL_INFO->RX_NPUSCH.number_of_pdus++;
382
                    }
383

384 385 386 387 388 389 390 391 392 393 394
	                /* 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*/
395
	    
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
	            } // mac_enabled==1

            eNB->UE_stats[i].mode = PUSCH;
            eNB->ulsch[i]->Msg3_flag = 0;

	          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
                for (j=0; j<eNB->dlsch[i][0]->Mlimit; j++) 
                  {
                    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;
                  }

                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;

                for (j=0; j<eNB->ulsch[i]->Mlimit; j++) 
                  {
                    eNB->UE_stats[i].ulsch_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;
                  }
              }
425

426 427 428 429 430 431 432
            eNB->UE_stats[i].dlsch_sliding_cnt=0;
            eNB->UE_stats[i].dlsch_NAK_round0=0;
            eNB->UE_stats[i].dlsch_mcs_offset=0;
          } // Msg3_flag==1
	       else 
          {  // Msg3_flag == 0
	          if (eNB->mac_enabled==1) 
433 434
              {
                  // store successful Uplink data in UL_Info instead rx_sdu
Nick Ho's avatar
Nick Ho committed
435 436 437 438 439 440 441
                  (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag= 0;
                  UL_INFO->crc_ind.number_of_crcs++;
                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.rnti= eNB->ulsch[i]->rnti;
                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->data = eNB->ulsch[i]->harq_processes[harq_pid]->b;
                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_indication_rel8.length = eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3;
                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.harq_pid  = harq_pid;
                  UL_INFO->RX_NPUSCH.number_of_pdus++;
442
	    
443 444
	            } // mac_enabled==1
          } // Msg3_flag == 0
445

446
            // estimate timing advance for MAC
447 448 449 450 451
              sync_pos = lte_est_timing_advance_pusch(eNB,i);
              eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check

      }  // ulsch not in error

452

453
      // Process HARQ only in NPUSCH
Nick Ho's avatar
Nick Ho committed
454
      /*process_HARQ_feedback(i,
455 456 457 458
                            eNB,proc,
                            1, // pusch_flag
                            0,
                            0,
Nick Ho's avatar
Nick Ho committed
459
                            0);*/
460

461

462 463
      

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

466 467 468 469 470 471

    // update ULSCH statistics for tracing




472
  } // loop i=0 ... NUMBER_OF_UE_MAX-1
473 474 475 476 477

}

#undef DEBUG_PHY_PROC

478
/*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
479

480
void NB_generate_eNB_dlsch_params(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
481
{
482
  int UE_id = -1;
483
  NB_DL_FRAME_PARMS *fp=&eNB->frame_parms_nb_iot;
Nick Ho's avatar
Nick Ho committed
484
  int frame = proc->frame_tx;
485
  int subframe = proc->subframe_tx;
486 487
  DCI_CONTENT *DCI_Content; 
  DCI_format_NB_t DCI_format;
488
  NB_IoT_eNB_NDLSCH_t *ndlsch;
489

490
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
Nick Ho's avatar
Nick Ho committed
491

492

493
  // check DCI format is N1 (format 0)
494 495
  if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0)
    {
496
      //check DCI format N1 is for RAR  rnti_type  in FAPI specs table 4-45
497
      if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type == 1)
498
        {
499

500 501 502
    	  //mapping the fapi parameters to the oai parameters

          DCI_format = DCIFormatN1_RAR;
503 504 505 506 507 508 509

          //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;
510
          DCI_Content->DCIN1_RAR.RepNum			= dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
511 512 513 514
          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;

515

516
          // fill the dlsch_ra_NB sructure for RAR, and packed the DCI PDU
517 518 519 520 521

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

          LOG_D(PHY,"Generating dlsch params for RA_RNTI and packing DCI\n");
522 523 524 525 526 527
          NB_generate_eNB_dlsch_params_from_dci(eNB,
                                                frame,
                                                subframe,
                                                DCI_Content,
                                                dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
                                                DCI_format,
528
                                                ndlsch,
529
                                                fp,
530 531
                                                dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
												dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol
532 533 534
                                                );

          //eNB->dlsch_ra_NB->nCCE[subframe] = eNB->DCI_pdu->dci_alloc.firstCCE;
535
        }
536
      else
537 538 539 540
        { //managing data

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

543 544 545 546

    	  //mapping the fapi parameters to the oai parameters

    	  	  DCI_format = DCIFormatN1;
547

548 549 550 551 552 553
              //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;
554
              DCI_Content->DCIN1.RepNum			= dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
555 556 557 558
              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;

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

564
              //parameters we don't consider pdsch config dedicated since not calling the phy config dedicated step2
565 566

        	  LOG_D(PHY,"Generating dlsch params for DCIN1 data and packing DCI\n");
567 568 569 570 571 572
              NB_generate_eNB_dlsch_params_from_dci(eNB,
                                                    frame,
                                                    subframe,
                                                    DCI_Content,
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
                                                    DCI_format,
573
                                                    ndlsch,
574
                                                    fp,
575 576
                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
													dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol
577 578 579
                                                    ); 

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


582 583 584 585 586 587 588 589 590
        }
    }
  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
591 592 593 594 595 596


}



597
void NB_generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu) {
598

599
  int UE_id = -1;
600
  int harq_pid = 0;
Nick Ho's avatar
Nick Ho committed
601

602 603
  DCI_CONTENT *DCI_Content;
  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
604 605

  //mapping the fapi parameters to the OAI parameters
606 607 608 609 610 611 612 613 614
  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;
615 616


617 618 619

  UE_id = find_ue_NB(hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti, eNB);
  AssertFatal(UE_id == -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
620 621


Nick Ho's avatar
Nick Ho committed
622 623
  /*Log for generate ULSCH DCI*/

624 625
  NB_generate_eNB_ulsch_params_from_dci(eNB,
                                        proc,
626 627
                                        DCI_Content,
                                        hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti,
628 629
                                        DCIFormatN0,
                                        UE_id,
630 631
                                        hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.aggregation_level,
										hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.start_symbol
632 633
                                        );  

Nick Ho's avatar
Nick Ho committed
634 635
  
  //LOG for ULSCH DCI Resource allocation
636
  //CBA is not used in NB-IoT
637
    eNB->nulsch[(uint32_t)UE_id]->harq_process->subframe_scheduling_flag = 1;
Nick Ho's avatar
Nick Ho committed
638 639 640
  
}

641 642


643 644 645
/*
 * for NB-IoT ndlsch procedure
 * this function is called by the PHy procedure TX in 3 possible occasion:
646
 * 1) we manage BCCH pdu (SI)
647 648
 * 2) we manage RA dlsch pdu
 * 3) UE-specific dlsch pdu
649 650 651 652
 * ** 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
 */
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
void npdsch_procedures(PHY_VARS_eNB *eNB,
						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
									)
{
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
  LTE_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_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];
  //uint8_t DLSCH_pdu_rar[256];
  int i;




  LOG_D(PHY,
	"[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);

682
  if(ndlsch_harq->round == 0) { //first transmission so we encode... because we generate the sequence
683 684 685 686 687 688 689 690

    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
691
  	   * 2)all the parameters for getting the MSG3 should be given by the UL_CONFIG.request (all inside the next schedule_response function)
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
  	   *
  	   */

    	  //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???
      DLSCH_pdu = DLSCH_pdu_tmp;
      for (i=0; i<input_buffer_length; i++)
	DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
    }
  }
  else {
	  //We are doing a retransmission (harq round > 0

#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
#endif
#endif
  }

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


721 722 723 724 725 726 727 728 729 730 731 732 733 734
	  //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;
	  }


735 736 737 738 739 740 741 742 743 744 745 746 747 748
	 /*
	  * 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)
	 */
749 750 751 752 753 754


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

    /*
755 756 757 758 759 760 761 762
     *
     * 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
763 764
     * NB: switch case of G is the same for npdsch and npdcch
     *
765 766 767 768 769 770 771 772
     * 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
773
     * (is the starting OFDM for the NPDSCH transmission in the first slot in a subframe k)
774 775
     * 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)
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
     * Nsf needed as an input (number of subframe)-->inside harq_process of ndlsch
     */

    switch(ndlsch->npdsch_start_symbol)
    {
  	  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;

    }

    start_meas(&eNB->dlsch_encoding_stats);

    LOG_I(PHY, "NB-IoT Encoding step\n");

803 804 805 806 807 808 809 810
//    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);
811 812 813 814 815 816 817 818 819 820


    stop_meas(&eNB->dlsch_encoding_stats);

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

    start_meas(&eNB->dlsch_scrambling_stats);
    LOG_I(PHY, "NB-IoT Scrambling step\n");

821 822 823 824 825 826
    /*
     * SOME RELEVANT FACTS:
     *
     *
     */

827 828 829 830 831 832 833 834 835 836 837 838 839
//    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);
840 841 842 843 844 845 846 847

    stop_meas(&eNB->dlsch_scrambling_stats);


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

848 849 850 851 852 853 854
//    dlsch_modulation(eNB,
//		     eNB->common_vars.txdataF[0],
//		     AMP,
//		     subframe,
//		     num_pdcch_symbols,
//		     dlsch,
//		     dlsch1);
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871

    stop_meas(&eNB->dlsch_modulation_stats);
  }


#ifdef PHY_ABSTRACTION
  else {
    start_meas(&eNB->dlsch_encoding_stats);
    //dlsch_encoding_emul(eNB,
			//DLSCH_pdu,
			//dlsch);
    stop_meas(&eNB->dlsch_encoding_stats);
  }

#endif
  ndlsch->active = 0;
}
872 873


Nick Ho's avatar
Nick Ho committed
874

875
extern int oai_exit;
876

877

878
/*
879
 * ASSUMPTION
880 881 882
 *
 * The MAC schedule the schedule_response in a SUBFRAME BASE (at least because otherwise we have problem with our assumptions on SI transmission)
 *
883 884 885 886 887 888 889 890 891 892 893 894
 *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)
895
 * -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
896 897
 * -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.
898
 *
899 900 901 902
 * 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)
 *
 *
903
 *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
904 905 906
 *
 * **relevant aspects for the System information Transmission (Table 4-47 NDLSCH FAPi specs)
 * 1)RNTI type = 0 (contains a BCCH)
907 908
 * 2)Repetition number == scheduling info SIB1 mapped into 4-8-16
 * 3)RNTI (0xFFFF = SI-RNTI)
909 910 911
 * (see schedule_response implementation)
 *
 */
912 913 914 915 916 917 918

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

919
void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
920
         	 	 	 	 	  eNB_rxtx_proc_t *proc,
921
							  int do_meas)
922
{
923 924
  int frame = proc->frame_tx;
  int subframe = proc->subframe_tx;
925
  uint32_t i,aa;
926
  DCI_PDU_NB *dci_pdu = eNB->DCI_pdu;
927
  NB_DL_FRAME_PARMS *fp = &eNB->frame_parms_nb_iot;
928 929 930
  int8_t UE_id = 0;
  uint8_t ul_subframe;
  uint32_t ul_frame;
Nick Ho's avatar
Nick Ho committed
931
  int **txdataF = eNB->common_vars.txdataF[0];
932 933 934
  uint32_t sib1_startFrame = -1;


Nick Ho's avatar
Nick Ho committed
935

936 937 938 939 940

  if(do_meas == 1)
    start_meas(&eNB->phy_proc_tx);


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

943
  // clear the transmit data array for the current subframe
944 945 946 947 948 949
  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));
    } 

950 951
  //generate NPSS/NSSS
  NB_common_signal_procedures(eNB,proc);
952

953
    //Generate MIB
954 955 956
    if(subframe==0 && (eNB->npbch != NULL))
     {
          if(eNB->npbch->pdu != NULL)
957 958
          {
        	  //BCOM function
959 960 961 962 963 964 965 966 967 968
        	  /*
        	   * -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
        	   *
        	   */

969
    		generate_npbch(&eNB->npbch,
Nick Ho's avatar
Nick Ho committed
970 971 972
                         txdataF,
                         AMP,
                         fp,
973
						 eNB->npbch->pdu,
974
                         frame%64,
975
                         fp->NB_IoT_RB_ID
976
                         );
977 978 979 980 981
          }

          //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)
982
          {
983
        	  eNB->npbch->pdu = NULL;
984
          }
985
      }
Nick Ho's avatar
Nick Ho committed
986

987

988
    //Check for SIB1-NB transmission
989 990 991 992 993 994 995 996 997 998 999 1000 1001
    /*
     *
     * 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)
     *
     */
1002
    if(subframe == 4 && eNB->ndlsch_SIB1 != NULL && eNB->ndlsch_SIB1->harq_process->status == ACTIVE)
1003
    {
1004
      //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
1005 1006 1007 1008 1009
      sib1_startFrame = is_SIB1_NB(frame,
    		  	  	  	  	  	  eNB->ndlsch_SIB1->harq_process->repetition_number,
								  fp->Nid_cell,
								  eNB->ndlsch_SIB1 //set the flags
								  );
1010

1011 1012 1013 1014
  	  if(sib1_startFrame != -1 && eNB->ndlsch_SIB1->harq_process->pdu != NULL)
  	  {
    	npdsch_procedures(eNB,
          				  proc,
1015
					      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
1016 1017
					      eNB->ndlsch_SIB1->harq_process->pdu);
  	  }
1018

1019
  	  //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
1020
  	  if((frame-sib1_startFrame)%256 == 255)
1021 1022 1023
  	  {
  		//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;
1024
  		eNB->ndlsch_SIB1->harq_process->pdu = NULL;
1025
  	  }
1026

1027
    }
1028

1029 1030

    //Check for SI transmission
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
    /*
     *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)
     *
1044 1045
     * [This condition should be known by the MAC layer so it should trigger an DLSCH pdu only at proper instants]
     *
1046 1047 1048 1049
     * 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)
     *
     *
1050
     *XXX important: set the flag HARQ process->status to DISABLE when PHY finished the SI-transmission over the 2 or 8 subframes
1051 1052 1053
     *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)
1054
     *
1055
     */
1056

1057
	if(eNB->ndlsch_SI->harq_process->status == ACTIVE && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE || subframe != 4)) //condition on SIB1-NB
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
	{
	    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;
	    	}
	      }
	    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;

	    	   }
	    }

	}
1087

1088

1089

1090
      ///check for RAR transmission
1091
      if(eNB->ndlsch_ra != NULL && eNB->ndlsch_ra->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE || subframe != 4)) //condition on SIB1-NB
1092
      {
1093 1094 1095 1096
  	    if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
  	     {
  	      if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5 && subframe != 9)
  	       {
1097

1098 1099 1100 1101
  	    	  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);
Nick Ho's avatar
Nick Ho committed
1102

1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114
  	    	  //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);
Nick Ho's avatar
Nick Ho committed
1115

1116 1117
	  	    	  //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
1118

1119 1120 1121
	    	   }
	    }
      }
1122 1123


1124 1125 1126 1127 1128 1129 1130 1131 1132
      /*
       * Delays between DCI transmission and NDLSCH transmission are taken in consideration by the MAC scheduler by sending in the proper subframe the scheduler_response
       * 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)
       *
       * XXX how are managed the transmission and repetitions???
       *
       */
1133

1134
      //this should give only 1 result (since only 1 ndlsch procedure is activated at once) so we brak after the transmission
1135 1136
      for (int UE_id = 0; i < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
      {
1137
    	  if(eNB->ndlsch[(uint8_t)UE_id] != NULL && eNB->ndlsch[(uint8_t)UE_id]->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE || subframe != 4)) //condition on sib1-NB
1138
    	  {
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
    	  	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[(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(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5)
    	    	   {
    	  	    	npdsch_procedures(eNB,
                						proc,
										eNB->ndlsch[(uint8_t)UE_id],
										eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
    	  	    	break;

    	    	   }
    	    }
1162
    	  }
1163

1164 1165
    	  //we don't care about subframe TX for the PUCCH since not defined by NB-IoT
      }
1166 1167


1168 1169 1170 1171 1172
      //no dedicated phy config


      /*If we have DCI to generate do it now*/
      generate_dci_top_NB(
1173
    		  	  	  	  eNB->npdcch,
1174 1175 1176 1177 1178
    		  	  	  	  dci_pdu->Num_dci,
						  dci_pdu->dci_alloc,
						  AMP,
						  fp,
						  eNB->common_vars.txdataF[0],
1179 1180
						  subframe,
						  dci_pdu->npdcch_start_symbol); //this parameter depends by eutraControlRegionSize (see TS36.213 16.6.1)
1181

1182
}