From 6f2b2eeb495ab9e1aeba070cd78cc8ead09acb98 Mon Sep 17 00:00:00 2001
From: Matthieu Kanj <Matthieu.kanj@b-com.com>
Date: Thu, 7 Feb 2019 16:02:51 +0100
Subject: [PATCH] optimization of NPUSCH

---
 openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h     |  25 +-
 .../LTE_TRANSPORT/ulsch_demodulation_NB_IoT.c | 379 +++++++++++-------
 2 files changed, 255 insertions(+), 149 deletions(-)

diff --git a/openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h
index 17a47f2a43..dead578777 100644
--- a/openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h
+++ b/openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h
@@ -358,7 +358,28 @@ int32_t dlsch_encoding_NB_IoT(unsigned char              *a,
                               unsigned int               G);         // G (number of available RE) is implicitly multiplied by 2 (since only QPSK modulation)
  
 
-
+void get_pilots_position(uint8_t npusch_format,uint8_t  subcarrier_spacing,uint8_t *pilot_pos1,uint8_t *pilot_pos2,uint8_t *pilots_slot);
+
+void UL_channel_estimation_NB_IoT(PHY_VARS_eNB        *eNB,
+                                  LTE_DL_FRAME_PARMS  *fp,
+                                  uint16_t            UL_RB_ID_NB_IoT,
+                                  uint16_t            Nsc_RU,
+                                  uint8_t             pilot_pos1,
+                                  uint8_t             pilot_pos2,
+                                  uint16_t            ul_sc_start,
+                                  uint8_t             Qm,
+                                  uint16_t            N_SF_per_word,
+                                  uint8_t             rx_subframe);
+
+void get_llr_per_sf_NB_IoT(PHY_VARS_eNB        *eNB,
+                           LTE_DL_FRAME_PARMS  *fp,
+                           uint8_t             npusch_format,
+                           uint8_t             counter_sf,
+                           uint16_t            N_SF_per_word,
+                           uint8_t             pilot_pos1,
+                           uint8_t             pilot_pos2,
+                           uint16_t            ul_sc_start,
+                           uint16_t            Nsc_RU);
 
 
 uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB             *eNB,
@@ -372,7 +393,7 @@ uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB             *eNB,
 void ulsch_extract_rbs_single_NB_IoT(int32_t **rxdataF,
                                      int32_t **rxdataF_ext, 
                                      uint16_t UL_RB_ID_NB_IoT, // index of UL NB_IoT resource block !!! may be defined twice : in frame_parms and in NB_IoT_UL_eNB_HARQ_t
-                                     uint8_t N_sc_RU, // number of subcarriers in UL 
+                                     uint16_t N_sc_RU, // number of subcarriers in UL 
                                      uint8_t l,
                                      uint8_t Ns,
                                      LTE_DL_FRAME_PARMS *frame_parms);
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation_NB_IoT.c
index 75ac894f87..83bbd389d3 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation_NB_IoT.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation_NB_IoT.c
@@ -616,7 +616,7 @@ void ulsch_detection_mrc_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,
 void ulsch_extract_rbs_single_NB_IoT(int32_t **rxdataF,
                                      int32_t **rxdataF_ext, 
                                      uint16_t UL_RB_ID_NB_IoT, // index of UL NB_IoT resource block !!! may be defined twice : in frame_parms and in NB_IoT_UL_eNB_HARQ_t
-                                     uint8_t N_sc_RU, // number of subcarriers in UL 
+                                     uint16_t N_sc_RU, // number of subcarriers in UL 
                                      uint8_t l,
                                      uint8_t Ns,
                                      LTE_DL_FRAME_PARMS *frame_parms)
@@ -1255,91 +1255,39 @@ void ulsch_channel_level_NB_IoT(int32_t **drs_ch_estimates_ext,
 #endif
 }
 
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////// generalization of RX procedures //////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-int32_t llr_msg5[16]; 
-int32_t y_msg5[16];
-
-uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
-                            eNB_rxtx_proc_t         *proc,
-                            uint8_t                 eNB_id,                    // this is the effective sector id
-                            uint8_t                 UE_id,
-                            uint16_t                UL_RB_ID_NB_IoT,           // 22 , to be included in // to be replaced by NB_IoT_start ??     
-                            uint8_t                 rx_subframe,               //  received subframe 
-                            uint32_t                rx_frame)                  //  received frame 
+//////////////////////////////////////////////////////////////////////////////////////
+void get_pilots_position(uint8_t npusch_format,uint8_t  subcarrier_spacing,uint8_t *pilot_pos1,uint8_t *pilot_pos2,uint8_t *pilots_slot)
 {
-      
-      LTE_eNB_PUSCH       *pusch_vars   =  eNB->pusch_vars[UE_id];
-      LTE_eNB_COMMON      *common_vars  =  &eNB->common_vars;
-      //NB_IoT_DL_FRAME_PARMS  *frame_parms  =  &eNB->frame_parms;
-      LTE_DL_FRAME_PARMS     *fp  =  &eNB->frame_parms; 
-      // NB_IoT_eNB_NULSCH_t    **ulsch_NB_IoT   =  &eNB->ulsch_NB_IoT[0];//[0][0]; 
-      NB_IoT_eNB_NULSCH_t     *ulsch_NB_IoT     = eNB->ulsch_NB_IoT[0];
-      NB_IoT_UL_eNB_HARQ_t    *ulsch_harq       = ulsch_NB_IoT->harq_process;
 
-  if (ulsch_NB_IoT->Msg3_active  == 1)    
-  {    
-      uint8_t      npusch_format         = ulsch_NB_IoT->npusch_format;           /// 0 or 1 -> format 1 or format 2         
-      uint8_t      subcarrier_spacing    = ulsch_harq->subcarrier_spacing;        // can be set as fix value //values are OK // 0 (3.75 KHz) or 1 (15 KHz)
-      uint16_t     I_sc                  = ulsch_harq->subcarrier_indication;     // Isc =0->18 , or 0->47 // format 2, 0->3 or 0->7
-      uint16_t     I_mcs                 = ulsch_harq->mcs;                       // values 0->10
-      uint16_t     Nsc_RU                = get_UL_N_ru_NB_IoT(I_mcs,ulsch_harq->resource_assignment,ulsch_NB_IoT->Msg3_flag);
-      uint16_t     N_UL_slots            = get_UL_slots_per_RU_NB_IoT(subcarrier_spacing,I_sc,npusch_format)*Nsc_RU;           // N_UL_slots per word
-      uint16_t     N_SF_per_word         = N_UL_slots/2;
-
-      if(ulsch_NB_IoT->flag_vars == 1)
-      {
-        ulsch_NB_IoT->counter_sf          = N_SF_per_word;
-        ulsch_NB_IoT->counter_repetitions = get_UL_N_rep_NB_IoT(ulsch_harq->repetition_number);
+      uint8_t      pilot_pos1_format1_15k     = 3, pilot_pos2_format1_15k   = 10;      // holds for npusch format 1, and 15 kHz subcarrier bandwidth
+      uint8_t      pilot_pos1_format2_15k     = 2, pilot_pos2_format2_15k   = 9;       // holds for npusch format 2, and 15 kHz subcarrier bandwidth 
+      uint8_t      pilot_pos1_format1_3_75k   = 4, pilot_pos2_format1_3_75k = 11;      // holds for npusch format 1, and 3.75 kHz subcarrier bandwidth
+      uint8_t      pilot_pos1_format2_3_75k   = 0, pilot_pos2_format2_3_75k = 7;       // holds for npusch format 2, and 3.75 kHz subcarrier bandwidth 
 
-        ulsch_NB_IoT->flag_vars = 0;
-      }
-      
-      if(ulsch_NB_IoT->counter_sf == N_SF_per_word)                // initialization for scrambling
-      {
-          ulsch_NB_IoT->Msg3_subframe   =   rx_subframe;      // first received subframe 
-          ulsch_NB_IoT->Msg3_frame      =   rx_frame;         // first received frame
-      }
-
-       uint8_t     pilot_pos1, pilot_pos2;                                      // holds for npusch format 1, and 15 kHz subcarrier bandwidth
-      int16_t      *llrp, *llrp2;
-      uint32_t     l,ii=0;
-      uint32_t     rnti_tmp                   = ulsch_NB_IoT->rnti;                   
-      uint16_t     ul_sc_start                = get_UL_sc_index_start_NB_IoT(subcarrier_spacing,I_sc,npusch_format);
-      uint8_t      Qm                         = get_Qm_UL_NB_IoT(I_mcs,Nsc_RU,I_sc,ulsch_NB_IoT->Msg3_flag);
-      uint8_t      pilot_pos1_format1_15k     = 3, pilot_pos2_format1_15k = 10;      // holds for npusch format 1, and 15 kHz subcarrier bandwidth
-      uint8_t      pilot_pos1_format2_15k     = 2, pilot_pos2_format2_15k = 9;       // holds for npusch format 2, and 15 kHz subcarrier bandwidth 
-      uint8_t      pilot_pos1_format1_3_75k   = 4, pilot_pos2_format1_3_75k = 11;    // holds for npusch format 1, and 3.75 kHz subcarrier bandwidth
-      uint8_t      pilot_pos1_format2_3_75k   = 0,pilot_pos2_format2_3_75k = 7;      // holds for npusch format 2, and 3.75 kHz subcarrier bandwidth 
-      uint8_t      pilots_slot                =0;        
-
-      //void get_pilots_position(uint8_t npusch_format,uint8_t  subcarrier_spacing,pilot_pos1,pilot_pos2)
       switch(npusch_format + subcarrier_spacing*2)
       {
         case 0:    // data
-                pilot_pos1 = pilot_pos1_format1_3_75k; 
-                pilot_pos2 = pilot_pos2_format1_3_75k;
-                pilots_slot=1;
+                *pilot_pos1 = pilot_pos1_format1_3_75k; 
+                *pilot_pos2 = pilot_pos2_format1_3_75k;
+                *pilots_slot=1;
         break;
 
         case 1:    // ACK
-                pilot_pos1 = pilot_pos1_format2_3_75k; 
-                pilot_pos2 = pilot_pos2_format2_3_75k;
-                pilots_slot=3;
+                *pilot_pos1 = pilot_pos1_format2_3_75k; 
+                *pilot_pos2 = pilot_pos2_format2_3_75k;
+                *pilots_slot=3;
         break;
 
         case 2:   // data 
-                pilot_pos1 = pilot_pos1_format1_15k; 
-                pilot_pos2 = pilot_pos2_format1_15k;
-                pilots_slot=1;
+                *pilot_pos1 = pilot_pos1_format1_15k; 
+                *pilot_pos2 = pilot_pos2_format1_15k;
+                *pilots_slot=1;
         break;
 
         case 3:  // ACK
-                pilot_pos1 = pilot_pos1_format2_15k; 
-                pilot_pos2 = pilot_pos2_format2_15k;
-                pilots_slot=3;
+                *pilot_pos1 = pilot_pos1_format2_15k; 
+                *pilot_pos2 = pilot_pos2_format2_15k;
+                *pilots_slot=3;
         break;
 
         default:
@@ -1347,23 +1295,42 @@ uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
         break;
       }
 
-      for (l=0; l<fp->symbols_per_tti; l++)
+}
+//////////////////////////////////////////////////////////////////////////////////////
+void UL_channel_estimation_NB_IoT(PHY_VARS_eNB        *eNB,
+                                  LTE_DL_FRAME_PARMS  *fp,
+                                  uint16_t            UL_RB_ID_NB_IoT,
+                                  uint16_t            Nsc_RU,
+                                  uint8_t             pilot_pos1,
+                                  uint8_t             pilot_pos2,
+                                  uint16_t            ul_sc_start,
+                                  uint8_t             Qm,
+                                  uint16_t            N_SF_per_word,
+                                  uint8_t             rx_subframe)
+{
+     LTE_eNB_PUSCH           *pusch_vars      =  eNB->pusch_vars[0]; // UE_id
+     LTE_eNB_COMMON          *common_vars     =  &eNB->common_vars;  
+     NB_IoT_eNB_NULSCH_t     *ulsch_NB_IoT    =  eNB->ulsch_NB_IoT[0];
+
+     int l=0;
+
+     for (l=0; l<fp->symbols_per_tti; l++)
       { 
             
-             ulsch_extract_rbs_single_NB_IoT(common_vars->rxdataF[eNB_id],
-                                             pusch_vars->rxdataF_ext[eNB_id],
-                                             UL_RB_ID_NB_IoT,      //ulsch[UE_id]->harq_process->UL_RB_ID_NB_IoT, // index of UL NB_IoT resource block 
-                                             Nsc_RU, //1, //ulsch_NB_IoT[0]->harq_process->N_sc_RU, // number of subcarriers in UL  //////////////// high level parameter
-                                             l%(fp->symbols_per_tti/2),           // (0..13)
-                                             l/(fp->symbols_per_tti/2),           // (0,1)
+             ulsch_extract_rbs_single_NB_IoT(common_vars->rxdataF[0],      // common_vars->rxdataF[eNB_id],
+                                             pusch_vars->rxdataF_ext[0],   // pusch_vars->rxdataF_ext[eNB_id]
+                                             UL_RB_ID_NB_IoT,              //ulsch[UE_id]->harq_process->UL_RB_ID_NB_IoT, // index of UL NB_IoT resource block 
+                                             Nsc_RU,                       //1, //ulsch_NB_IoT[0]->harq_process->N_sc_RU, // number of subcarriers in UL  //////////////// high level parameter
+                                             l%(fp->symbols_per_tti/2),    // (0..13)
+                                             l/(fp->symbols_per_tti/2),    // (0,1)
                                              fp);
-            if(npusch_format == 0)
+            if(ulsch_NB_IoT->npusch_format == 0)      // format 1
             {
-                      ul_chest_tmp_NB_IoT(pusch_vars->rxdataF_ext[eNB_id],
-                                          pusch_vars->drs_ch_estimates[eNB_id],
-                                          l%(fp->symbols_per_tti/2),          //symbol within slot 
+                      ul_chest_tmp_NB_IoT(pusch_vars->rxdataF_ext[0],       // pusch_vars->rxdataF_ext[eNB_id],
+                                          pusch_vars->drs_ch_estimates[0],  // pusch_vars->drs_ch_estimates[eNB_id]
+                                          l%(fp->symbols_per_tti/2),        //symbol within slot 
                                           l/(fp->symbols_per_tti/2),
-                                          ulsch_NB_IoT->counter_sf,  // counter_msg
+                                          ulsch_NB_IoT->counter_sf,         // counter_msg
                                           pilot_pos1,
                                           pilot_pos2,
                                           ul_sc_start,
@@ -1377,47 +1344,37 @@ uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
                                             l%(fp->symbols_per_tti/2),        //symbol within slot 
                                             l/(fp->symbols_per_tti/2), 
                                             ulsch_NB_IoT->counter_sf,         //counter_msg, 
-                                            npusch_format,                    // proc->flag_msg5, 
+                                            ulsch_NB_IoT->npusch_format,      // proc->flag_msg5, 
                                             rx_subframe,
                                             Qm,                               // =1
-                                            ul_sc_start,                       // = 0   
+                                            ul_sc_start,                      // = 0   
                                             fp); 
             }
       }
-      /////////////////////////////////////// Equalization ///////////////////////////////////
-      for (l=0; l<fp->symbols_per_tti; l++)
-      { 
-              ul_chequal_tmp_NB_IoT(pusch_vars->rxdataF_ext[eNB_id],
-                                    pusch_vars->rxdataF_comp[eNB_id],
-                                    pusch_vars->drs_ch_estimates[eNB_id],
-                                    l%(fp->symbols_per_tti/2),               //symbol within slot 
-                                    l/(fp->symbols_per_tti/2),
-                                    fp);
-      }
-      ////////////////////////////////////// End Equalization /////////////////////////////////
 
-      ///////////////////////////////////////// Rotation       ////////////////////////////////
-      for (l=0; l<fp->symbols_per_tti; l++)
-      { 
-           /// In case of 1 subcarrier: BPSK and QPSK should be rotated by pi/2 and pi/4, respectively 
-            rotate_single_carrier_NB_IoT(eNB, 
-                                         fp, 
-                                         pusch_vars->rxdataF_comp[eNB_id], 
-                                         UE_id, // UE ID
-                                         l, 
-                                         ulsch_NB_IoT->counter_sf,   //counter_msg,
-                                         ul_sc_start,
-                                         Qm,
-                                         N_SF_per_word,
-                                         npusch_format); // or data
-      }
-      //////////////////////////////////////////End rotation ///////////////////////////////////
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void get_llr_per_sf_NB_IoT(PHY_VARS_eNB        *eNB,
+                           LTE_DL_FRAME_PARMS  *fp,
+                           uint8_t             npusch_format,
+                           uint8_t             counter_sf,
+                           uint16_t            N_SF_per_word,
+                           uint8_t             pilot_pos1,
+                           uint8_t             pilot_pos2,
+                           uint16_t            ul_sc_start,
+                           uint16_t            Nsc_RU)
+{
+      LTE_eNB_PUSCH           *pusch_vars      =  eNB->pusch_vars[0]; // UE_id
+      int16_t                 *llrp;
+      uint32_t                l,ii=0; 
 
-      if(npusch_format == 0)
+      if(npusch_format == 0)   // format 1
       { 
-             llrp = (int16_t*)&pusch_vars->llr[0+ (N_SF_per_word-ulsch_NB_IoT->counter_sf)*24];  /// 24= 12 symbols/SF * 2 // since Real and im
-      } else {
-              llrp = (int16_t*)&pusch_vars->llr[0+ (2-ulsch_NB_IoT->counter_sf)*16]; // 16 = 8 symbols/SF * 2 // since real and im
+             llrp = (int16_t*)&pusch_vars->llr[0+ (N_SF_per_word-counter_sf)*24];  /// 24= 12 symbols/SF * 2 // since Real and im
+
+      } else {                      // format 2        
+
+              llrp = (int16_t*)&pusch_vars->llr[0+ (2-counter_sf)*16]; // 16 = 8 symbols/SF * 2 // since real and im
       }
 
       for (l=0; l<fp->symbols_per_tti; l++)
@@ -1434,21 +1391,42 @@ uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
  
           ulsch_qpsk_llr_NB_IoT(eNB, 
                                 fp,
-                                pusch_vars->rxdataF_comp[eNB_id],
+                                pusch_vars->rxdataF_comp[0],    // pusch_vars->rxdataF_comp[eNB_id],
                                 pusch_vars->llr,
                                 l, 
-                                UE_id, // UE ID
+                                0, // UE ID
                                 ul_sc_start,
                                 Nsc_RU,
                                 &llrp[ii*2]); 
           ii++;
       }
-      
-      /////////////////////////////////////////////////  NPUSH DECOD //////////////////////////////////////
-      if(ulsch_NB_IoT->counter_sf == 1)
-      {   
-          int16_t         *ulsch_llr    = eNB->pusch_vars[eNB_id]->llr;             //UE_id=0
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void decode_NPUSCH_msg_NB_IoT(PHY_VARS_eNB        *eNB,
+                              LTE_DL_FRAME_PARMS  *fp,
+                              eNB_rxtx_proc_t     *proc,
+                              uint8_t             npusch_format,
+                              uint16_t            N_SF_per_word,
+                              uint16_t            Nsc_RU,
+                              uint16_t            N_UL_slots,
+                              uint8_t             Qm,
+                              uint8_t             pilots_slot,
+                              uint32_t            rnti_tmp,
+                              uint8_t             rx_subframe,
+                              uint32_t            rx_frame)
+{
+      LTE_eNB_PUSCH       *pusch_vars   =  eNB->pusch_vars[0];                  //  eNB->pusch_vars[UE_id];
+
+      NB_IoT_eNB_NULSCH_t     *ulsch_NB_IoT     = eNB->ulsch_NB_IoT[0];
+      NB_IoT_UL_eNB_HARQ_t    *ulsch_harq       = ulsch_NB_IoT->harq_process;
+
+      int16_t         *ulsch_llr    = eNB->pusch_vars[0]->llr;  // eNB->pusch_vars[eNB_id]->llr;      //UE_id=0
+          
           
+
           unsigned int    A      = (ulsch_harq->TBS)*8;
           uint8_t         rvdx   = ulsch_harq->rvidx;
           unsigned int    j,j2; //i2,
@@ -1459,7 +1437,6 @@ uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
           uint32_t        x1, x2, s=0;
           int16_t         y[6*14*1200] __attribute__((aligned(32)));
           uint8_t         ytag[14*1200];
-          //int16_t         cseq[6*14*1200];
           uint8_t      reset;
           uint8_t      counter_ack;       // ack counter for decision ack/nack
           int32_t      counter_ack_soft;
@@ -1549,7 +1526,7 @@ uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
               }
                     ///////////////////////////////// desin  multi-tone
                               //if multi-RU
-/// deinterleaving
+             /// deinterleaving
 
               j  = 0;
               j2 = 0;
@@ -1565,7 +1542,6 @@ uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
                    ep[6] = yp[6];
                    ep[7] = yp[7];
               }
-/////
               /// decoding
               r=0;
               Kr=0;
@@ -1720,20 +1696,16 @@ uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
                   }
               }////////////  r loop end  ////////////
 
-         //     uint8_t *msg3 = &eNB->msg3_pdu[0];
-             // printf("pdu[0] = %d \n",ulsch_harq->b[0]);
-              
 
-           /*   int m =0;
-              for(m=0; m<6;m++)
-              { 
+          } else {   //////////////////////////////////// ACK //////////////////////////////
 
-                    msg3[m]=ulsch_harq->b[2+m];
-              }*/
+                int32_t     llr_msg5[16]; 
+                int32_t     y_msg5[16];
+                int16_t     *llrp2;
+                int         l=0;
 
-          } else {   //////////////////////////////////// ACK //////////////////////////////
+                llrp2 = (int16_t*)&pusch_vars->llr[0];
 
-                llrp2 = (int16_t*)&pusch_vars->llr[0]; 
                 for (l=0;l<16;l++) /// Add real and imaginary parts of BPSK constellation
                 {
                     llr_msg5[l] = llrp2[l<<1] + llrp2[(l<<1)+1];
@@ -1799,19 +1771,132 @@ uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
                 printf("\n\n\n");
           } 
 
-          /////  if last sf of the word
-          ulsch_NB_IoT->counter_repetitions--;
+      /////  if last sf of the word
+      ulsch_NB_IoT->counter_repetitions--;
 
-          if(ulsch_NB_IoT->Msg3_flag == 1)
-          {
-              ulsch_harq->rvidx =  (ulsch_NB_IoT->counter_repetitions % 2)*2;        // rvidx toogle for new code word
-          } // else {}       for other npusch cases ??
+      if(ulsch_NB_IoT->Msg3_flag == 1)
+      {
+          ulsch_harq->rvidx =  (ulsch_NB_IoT->counter_repetitions % 2)*2;        // rvidx toogle for new code word
+      } // else {}       for other npusch cases ??
 
-          if( (ulsch_NB_IoT->counter_sf == 1) && (ulsch_NB_IoT->counter_repetitions == 0) )
-          {
-            ulsch_NB_IoT->Msg3_active  = 0;
-            ulsch_NB_IoT->Msg3_flag    = 0;
-          }  
+      if( (ulsch_NB_IoT->counter_sf == 1) && (ulsch_NB_IoT->counter_repetitions == 0) )
+      {
+        ulsch_NB_IoT->Msg3_active  = 0;
+        ulsch_NB_IoT->Msg3_flag    = 0;
+      } 
+
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////// generalization of RX procedures //////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+uint8_t rx_ulsch_Gen_NB_IoT(PHY_VARS_eNB            *eNB,
+                            eNB_rxtx_proc_t         *proc,
+                            uint8_t                 eNB_id,                    // this is the effective sector id
+                            uint8_t                 UE_id,
+                            uint16_t                UL_RB_ID_NB_IoT,           // 22 , to be included in // to be replaced by NB_IoT_start ??     
+                            uint8_t                 rx_subframe,               //  received subframe 
+                            uint32_t                rx_frame)                  //  received frame 
+{
+      
+      LTE_eNB_PUSCH       *pusch_vars   =  eNB->pusch_vars[UE_id];
+      LTE_eNB_COMMON      *common_vars  =  &eNB->common_vars;
+      //NB_IoT_DL_FRAME_PARMS  *frame_parms  =  &eNB->frame_parms;
+      LTE_DL_FRAME_PARMS     *fp  =  &eNB->frame_parms; 
+      // NB_IoT_eNB_NULSCH_t    **ulsch_NB_IoT   =  &eNB->ulsch_NB_IoT[0];//[0][0]; 
+      NB_IoT_eNB_NULSCH_t     *ulsch_NB_IoT     = eNB->ulsch_NB_IoT[0];
+      NB_IoT_UL_eNB_HARQ_t    *ulsch_harq       = ulsch_NB_IoT->harq_process;
+
+  if (ulsch_NB_IoT->Msg3_active  == 1)    
+  {    
+      uint8_t      npusch_format         = ulsch_NB_IoT->npusch_format;           /// 0 or 1 -> format 1 or format 2         
+      uint8_t      subcarrier_spacing    = ulsch_harq->subcarrier_spacing;        // can be set as fix value //values are OK // 0 (3.75 KHz) or 1 (15 KHz)
+      uint16_t     I_sc                  = ulsch_harq->subcarrier_indication;     // Isc =0->18 , or 0->47 // format 2, 0->3 or 0->7
+      uint16_t     I_mcs                 = ulsch_harq->mcs;                       // values 0->10
+      uint16_t     Nsc_RU                = get_UL_N_ru_NB_IoT(I_mcs,ulsch_harq->resource_assignment,ulsch_NB_IoT->Msg3_flag);
+      uint16_t     N_UL_slots            = get_UL_slots_per_RU_NB_IoT(subcarrier_spacing,I_sc,npusch_format)*Nsc_RU;           // N_UL_slots per word
+      uint16_t     N_SF_per_word         = N_UL_slots/2;
+
+      if(ulsch_NB_IoT->flag_vars == 1)
+      {
+        ulsch_NB_IoT->counter_sf          = N_SF_per_word;
+        ulsch_NB_IoT->counter_repetitions = get_UL_N_rep_NB_IoT(ulsch_harq->repetition_number);
+
+        ulsch_NB_IoT->flag_vars = 0;
+      }
+      
+      if(ulsch_NB_IoT->counter_sf == N_SF_per_word)                // initialization for scrambling
+      {
+          ulsch_NB_IoT->Msg3_subframe   =   rx_subframe;      // first received subframe 
+          ulsch_NB_IoT->Msg3_frame      =   rx_frame;         // first received frame
+      }
+
+      uint8_t     pilot_pos1, pilot_pos2, pilots_slot;                                      // holds for npusch format 1, and 15 kHz subcarrier bandwidth
+      uint32_t     l;
+      uint32_t     rnti_tmp                   = ulsch_NB_IoT->rnti;                   
+      uint16_t     ul_sc_start                = get_UL_sc_index_start_NB_IoT(subcarrier_spacing,I_sc,npusch_format);
+      uint8_t      Qm                         = get_Qm_UL_NB_IoT(I_mcs,Nsc_RU,I_sc,ulsch_NB_IoT->Msg3_flag);              
+
+      get_pilots_position(npusch_format, subcarrier_spacing, &pilot_pos1, &pilot_pos2, &pilots_slot);
+      
+                           ////////////////////// channel estimation per SF ////////////////////     
+      UL_channel_estimation_NB_IoT(eNB, fp, UL_RB_ID_NB_IoT, Nsc_RU, pilot_pos1, pilot_pos2, ul_sc_start, Qm, N_SF_per_word, rx_subframe);
+     
+                           //////////////////////// Equalization  per SF ///////////////////////
+      for (l=0; l<fp->symbols_per_tti; l++)
+      { 
+              ul_chequal_tmp_NB_IoT(pusch_vars->rxdataF_ext[eNB_id],
+                                    pusch_vars->rxdataF_comp[eNB_id],
+                                    pusch_vars->drs_ch_estimates[eNB_id],
+                                    l%(fp->symbols_per_tti/2),               //symbol within slot 
+                                    l/(fp->symbols_per_tti/2),
+                                    fp);
+      } 
+
+                          ///////////////////// Rotation /////////////////
+      for (l=0; l<fp->symbols_per_tti; l++)
+      { 
+           /// In case of 1 subcarrier: BPSK and QPSK should be rotated by pi/2 and pi/4, respectively 
+            rotate_single_carrier_NB_IoT(eNB, 
+                                         fp, 
+                                         pusch_vars->rxdataF_comp[eNB_id], 
+                                         UE_id, // UE ID
+                                         l, 
+                                         ulsch_NB_IoT->counter_sf,   //counter_msg,
+                                         ul_sc_start,
+                                         Qm,
+                                         N_SF_per_word,
+                                         npusch_format); // or data
+      }
+            ////////////////////// get LLR values per SF /////////////////////////
+      get_llr_per_sf_NB_IoT(eNB,
+                            fp,
+                            npusch_format,
+                            ulsch_NB_IoT->counter_sf,
+                            N_SF_per_word,
+                            pilot_pos1,
+                            pilot_pos2,
+                            ul_sc_start,
+                            Nsc_RU);
+      
+      
+      /////////////////////////////////////////////////  NPUSH DECOD //////////////////////////////////////
+      if(ulsch_NB_IoT->counter_sf == 1)
+      {   
+          decode_NPUSCH_msg_NB_IoT(eNB,
+                                   fp,
+                                   proc,
+                                   npusch_format,
+                                   N_SF_per_word,
+                                   Nsc_RU,
+                                   N_UL_slots,
+                                   Qm,
+                                   pilots_slot,
+                                   rnti_tmp,
+                                   rx_subframe,
+                                   rx_frame);
           
       } // NPUSH decode end
 
-- 
2.26.2