diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
index d1944d54367b42832fa3965515207c66b9f3f512..df3fa4d5e516476416fb077e4d9a26025445a1cc 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
@@ -5202,7 +5202,6 @@ void prepare_dl_decoding_format1_1A(DCI_format_t dci_format,
     if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti))
     {
         pdlsch0_harq->round    = 0;
-        pdlsch0_harq->first_tx = 1;
         pdlsch0_harq->status   = ACTIVE;
     }
     else //CRNTI
@@ -5214,28 +5213,37 @@ void prepare_dl_decoding_format1_1A(DCI_format_t dci_format,
 				 rnti,harq_pid,pdlsch0_harq->DCINdi);
     	}
 
-        // DCI has been toggled or this is the first transmission
-        if (ndi1!=pdlsch0_harq->DCINdi)
+        // NDI has been toggled or this is the first transmission
+        if ((ndi1!=pdlsch0_harq->DCINdi) || (pdlsch0_harq->first_tx==1))
         {
             pdlsch0_harq->round    = 0;
-            pdlsch0_harq->first_tx = 1;
+            pdlsch0_harq->first_tx = 0;
             pdlsch0_harq->status   = ACTIVE;
-        }
-
-        if( ((ndi1 == pdlsch0_harq->DCINdi) && (pdlsch0_harq->round == 0) && (pdlsch0_harq->first_tx!=1)) ||
-            ((rv1  != 0) && (pdlsch0_harq->round == 0))
-          )
-        {
-            LOG_D(PHY,"skip pdsch decoding and report ack\n");
-            // skip pdsch decoding and report ack
-            pdlsch0_harq->status   = SCH_IDLE;
-            pdlsch0->active       = 0;
-            pdlsch0->harq_ack[subframe].ack = 1;
-            pdlsch0->harq_ack[subframe].harq_id = harq_pid;
-            pdlsch0->harq_ack[subframe].send_harq_status = 1;
 
-            pdlsch0_harq->first_tx = 0;
         }
+
+	else if (rv1  != 0 )
+	//NDI has not been toggled but rv was increased by eNB: retransmission
+	  {
+	    if (pdlsch0_harq->status == SCH_IDLE)
+	    //packet was actually decoded in previous transmission (ACK was missed by eNB)
+	    //However, the round is not a good check as it might have been decoded in a retransmission prior to this one.
+	      {
+		LOG_D(PHY,"skip pdsch decoding and report ack\n");
+		// skip pdsch decoding and report ack
+		//pdlsch0_harq->status   = SCH_IDLE;
+		pdlsch0->active       = 0;
+		pdlsch0->harq_ack[subframe].ack = 1;
+		pdlsch0->harq_ack[subframe].harq_id = harq_pid;
+		pdlsch0->harq_ack[subframe].send_harq_status = 1;
+
+		//pdlsch0_harq->first_tx = 0;
+	      }
+	    else  //normal retransmission
+	      {
+		// nothing special to do
+	      }
+	  }
     }
 
     pdlsch0_harq->DCINdi = ndi1;
@@ -5820,17 +5828,19 @@ void prepare_dl_decoding_format2_2A(DCI_format_t dci_format,
             LOG_D(PHY,"Format 2 DCI First TX0: Clearing flag\n");
             dlsch0_harq->first_tx = 0;
           }
-        }else{
-         if(dlsch0_harq->round == 0) {
-#if 0
-            // skip pdsch decoding and report ack
-            pdlsch0->active       = 0;
-            pdlsch0->harq_ack[subframe].ack = 1;
-            pdlsch0->harq_ack[subframe].harq_id = harq_pid;
-            pdlsch0->harq_ack[subframe].send_harq_status = 1;
-#endif
-         }
-
+        }
+	else if (rv1  != 0 )
+	  //NDI has not been toggled but rv was increased by eNB: retransmission
+	  {
+	    if(dlsch0_harq->status == SCH_IDLE) {
+	      // skip pdsch decoding and report ack
+	      //dlsch0_harq->status   = SCH_IDLE;
+	      pdlsch0->active       = 0;
+	      pdlsch0->harq_ack[subframe].ack = 1;
+	      pdlsch0->harq_ack[subframe].harq_id = harq_pid;
+	      pdlsch0->harq_ack[subframe].send_harq_status = 1;
+	    }
+	  }
 
         // if Imcs in [29..31] TBS is assumed to be as determined from DCI transported in the latest
         // PDCCH for the same trasport block using Imcs in [0 .. 28]
@@ -5852,7 +5862,6 @@ void prepare_dl_decoding_format2_2A(DCI_format_t dci_format,
         else if (mcs1<=31)
             dlsch0_harq->Qm = (mcs1-28)<<1;
       }
-    }
 
    //   printf("[DCI UE 3]: dlsch0_harq status %d , dlsch1_harq status %d\n", dlsch0_harq->status, dlsch1_harq->status);
 
@@ -5866,18 +5875,19 @@ void prepare_dl_decoding_format2_2A(DCI_format_t dci_format,
             LOG_D(PHY,"Format 2 DCI First TX1: Clearing flag\n");
             dlsch1_harq->first_tx = 0;
           }
-        }else{
-#if 0
-         if(dlsch1_harq->round == 0) {
-            // skip pdsch decoding and report ack
-        //  printf("Switching to IDLE\n");
-            pdlsch1->active       = 0;
-            pdlsch1->harq_ack[subframe].ack = 1;
-            pdlsch1->harq_ack[subframe].harq_id = harq_pid;
-            pdlsch1->harq_ack[subframe].send_harq_status = 1;
-         }
-#endif
         }
+	else if (rv1  != 0 )
+	//NDI has not been toggled but rv was increased by eNB: retransmission
+	  {
+	    if(dlsch1_harq->status == SCH_IDLE) {
+	      // skip pdsch decoding and report ack
+	      //dlsch1_harq->status   = SCH_IDLE;
+	      pdlsch1->active       = 0;
+	      pdlsch1->harq_ack[subframe].ack = 1;
+	      pdlsch1->harq_ack[subframe].harq_id = harq_pid;
+	      pdlsch1->harq_ack[subframe].send_harq_status = 1;
+	    }
+	  }
 
         // if Imcs in [29..31] TBS is assumed to be as determined from DCI transported in the latest
         // PDCCH for the same trasport block using Imcs in [0 .. 28]
@@ -6974,11 +6984,15 @@ int generate_ue_dlsch_params_from_dci(int frame,
         dlsch0_harq->mimo_mode   = SISO;
 
 
-      if (dlsch0_harq->DCINdi != ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi) {
+      if ((dlsch0_harq->DCINdi != ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi) ||
+	(dlsch0_harq->first_tx==1)) {
 
         dlsch0_harq->round = 0;
+	dlsch0_harq->first_tx = 0;
         dlsch0_harq->status = ACTIVE;
-      } else if (dlsch0_harq->status == SCH_IDLE) { // we got an Ndi = 0 for a previously decoded process,
+      }
+      /*
+	else if (dlsch0_harq->status == SCH_IDLE) { // we got same ndi for a previously decoded process,
         // this happens if either another harq process in the same
         // is NAK or an ACK was not received
 
@@ -6988,6 +7002,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
         dlsch0->active = 0;
         return(0);
       }
+      */
 
       dlsch0_harq->DCINdi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi;
       dlsch0_harq->mcs    = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->mcs;
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
index 42b01a2ccc2fe043aab23789311049f2ef32a56e..49a73007741fa0826f94bd7ae59dc0ff1865425d 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
@@ -3410,7 +3410,7 @@ void dlsch_channel_level(int **dl_ch_estimates_ext,
 
   short rb;
   unsigned char aatx,aarx,nre=12,symbol_mod;
-  __m128i *dl_ch128, avg128D, coeff128;
+  __m128i *dl_ch128, avg128D;
 
   symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
 
@@ -3421,11 +3421,10 @@ void dlsch_channel_level(int **dl_ch_estimates_ext,
   else
     nre=12;
 
-  double one_over_nb_re = 0.0;
-  one_over_nb_re = 1/((double)(nb_rb*nre));
-  int16_t one_over_nb_re_q1_15 = (int16_t)(one_over_nb_re * (double)(1<<15) );
-  coeff128 = _mm_set_epi16(one_over_nb_re_q1_15,one_over_nb_re_q1_15,one_over_nb_re_q1_15,one_over_nb_re_q1_15,
-                            one_over_nb_re_q1_15,one_over_nb_re_q1_15,one_over_nb_re_q1_15,one_over_nb_re_q1_15);
+  //nb_rb*nre = y * 2^x
+  int16_t x = factor2(nb_rb*nre);
+  int16_t y = (nb_rb*nre)/(1<<x);
+  //printf("nb_rb*nre = %d = %d * 2^(%d)\n",nb_rb*nre,y,x);
 
   for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
@@ -3438,14 +3437,18 @@ void dlsch_channel_level(int **dl_ch_estimates_ext,
       for (rb=0;rb<nb_rb;rb++) {
         //      printf("rb %d : ",rb);
         //      print_shorts("ch",&dl_ch128[0]);
-        avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[0],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[0], coeff128),15)));
-        avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[1],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[1], coeff128),15)));
+	avg128D = _mm_add_epi32(avg128D,_mm_srai_epi16(_mm_madd_epi16(dl_ch128[0],dl_ch128[0]),x));
+	avg128D = _mm_add_epi32(avg128D,_mm_srai_epi16(_mm_madd_epi16(dl_ch128[1],dl_ch128[1]),x));
+
+        //avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[0],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[0], coeff128),15)));
+        //avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[1],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[1], coeff128),15)));
 
         if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) {
           dl_ch128+=2;
         }
         else {
-          avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[2],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[2], coeff128),15)));
+	  avg128D = _mm_add_epi32(avg128D,_mm_srai_epi16(_mm_madd_epi16(dl_ch128[2],dl_ch128[2]),x));
+          //avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[2],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[2], coeff128),15)));
           dl_ch128+=3;
         }
         /*
@@ -3457,11 +3460,11 @@ void dlsch_channel_level(int **dl_ch_estimates_ext,
         */
       }
 
-      avg[(aatx<<1)+aarx] =(((int32_t*)&avg128D)[0] +
-                            ((int32_t*)&avg128D)[1] +
-                            ((int32_t*)&avg128D)[2] +
-                            ((int32_t*)&avg128D)[3]);
-                //  printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
+      avg[(aatx<<1)+aarx] =  (((int32_t*)&avg128D)[0] +
+			      ((int32_t*)&avg128D)[1] +
+			      ((int32_t*)&avg128D)[2] +
+			      ((int32_t*)&avg128D)[3])/y;
+      //printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
     }
 
   _mm_empty();
diff --git a/openair1/PHY/TOOLS/defs.h b/openair1/PHY/TOOLS/defs.h
index 542b8edba5820b37c9e4d343fef07dfc6715414a..a90a8b718cfc36ec6ccbd3927eae8f70ae3abfea 100644
--- a/openair1/PHY/TOOLS/defs.h
+++ b/openair1/PHY/TOOLS/defs.h
@@ -338,6 +338,9 @@ uint8_t log2_approx64(unsigned long long int x);
 int16_t invSqrt(int16_t x);
 uint32_t angle(struct complex16 perrror);
 
+/// computes the number of factors 2 in x
+unsigned char factor2(unsigned int x);
+
 /*!\fn int32_t phy_phase_compensation_top (uint32_t pilot_type, uint32_t initial_pilot,
         uint32_t last_pilot, int32_t ignore_prefix);
 Compensate the phase rotation of the RF. WARNING: This function is currently unused. It has not been tested!
diff --git a/openair1/PHY/TOOLS/log2_approx.c b/openair1/PHY/TOOLS/log2_approx.c
index 0317a97d2f5d6fa1b3dd068dc97aee9d42612f0d..bd4d5d04ab87fec8fad51b0026163fa1a3bce3c2 100644
--- a/openair1/PHY/TOOLS/log2_approx.c
+++ b/openair1/PHY/TOOLS/log2_approx.c
@@ -37,6 +37,26 @@ unsigned char log2_approx(unsigned int x)
   return(l2);
 }
 
+unsigned char factor2(unsigned int x)
+{
+
+  int i;
+  unsigned char l2;
+
+  l2=0;
+
+  for (i=0; i<31; i++)
+    if ((x&(1<<i)) != 0)
+      break;
+
+  l2 = i;
+
+  //printf("factor2(%d) = %d\n",x,l2);
+  return(l2);
+}
+
+
+
 unsigned char log2_approx64(unsigned long long int x)
 {
 
diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c
index 873edc8343d9274113b5d00e1a2a0ed5901f4366..b152b89ef1ee1c94cfea7841094c58ed4704998c 100644
--- a/openair1/SIMULATION/LTE_PHY/dlsim.c
+++ b/openair1/SIMULATION/LTE_PHY/dlsim.c
@@ -1396,6 +1396,7 @@ int main(int argc, char **argv)
   int DLSCH_RB_ALLOC = 0;
 
   int log_level = LOG_ERR;
+  int dci_received;
 
 #if defined(__arm__)
   FILE    *proc_fd = NULL;
@@ -2330,10 +2331,10 @@ int main(int argc, char **argv)
 
         //if (trials%100==0)
         eNB2UE[0]->first_run = 1;
+	UE->dlsch[subframe&0x1][eNB_id][0]->harq_ack[subframe].ack = 0;
+	UE->dlsch[subframe&0x1][eNB_id][1]->harq_ack[subframe].ack = 0;
 
-        UE->dlsch_errors[0] = 1;
-
-        while ((round < num_rounds) && (UE->dlsch_errors[0] > 0)) {
+        while ((round < num_rounds) && (UE->dlsch[subframe&0x1][eNB_id][0]->harq_ack[subframe].ack == 0)) {
 	  //	  printf("Trial %d, round %d\n",trials,round);
           round_trials[round]++;
 
@@ -2509,7 +2510,7 @@ int main(int argc, char **argv)
 	  UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[subframe&1];
 	  proc->subframe_rx = subframe;
 	  UE->UE_mode[0] = PUSCH;
-	  UE->dlsch_errors[0] = 0;
+
 	  // first symbol has to be done separately in one-shot mode
 	  slot_fep(UE,
 		   0,
@@ -2550,12 +2551,15 @@ int main(int argc, char **argv)
 	    }
 	  }
 
+	  dci_received = UE->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->dci_received;
+
 	  phy_procedures_UE_RX(UE,proc,0,0,dci_flag,normal_txrx,no_relay,NULL);
 
-	  if (UE->dlsch[subframe&0x1][0][0]->active == 0) {
+	  dci_received = dci_received - UE->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->dci_received;
+
+	  if (dci_flag && (dci_received == 0)) {
 	    //printf("DCI not received\n");
 	    dci_errors[round]++;
-	    UE->dlsch_errors[0] = 1;
 
 	    /*
 	    write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1);
@@ -2626,7 +2630,7 @@ int main(int argc, char **argv)
 
 
 
-          if (UE->dlsch_errors[0] == 0) {
+          if (UE->dlsch[subframe&0x1][eNB_id][0]->harq_ack[subframe].ack == 1) {
 
             avg_iter += UE->dlsch[subframe&0x1][eNB_id][0]->last_iteration_cnt;
             iter_trials++;
@@ -2906,15 +2910,15 @@ int main(int argc, char **argv)
              errs2[0],
              round_trials[0],
              errs[1],
-             round_trials[0],
+             round_trials[1],
              errs[2],
-             round_trials[0],
+             round_trials[2],
              errs[3],
-             round_trials[0],
+             round_trials[3],
              (double)errs[0]/(round_trials[0]),
-             (double)errs[1]/(round_trials[0]),
-             (double)errs[2]/(round_trials[0]),
-             (double)errs[3]/(round_trials[0]),
+             (double)errs[1]/(round_trials[1]),
+             (double)errs[2]/(round_trials[2]),
+             (double)errs[3]/(round_trials[3]),
              dci_errors[0]+dci_errors[1]+dci_errors[2]+dci_errors[3],
              round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3],
              (double)(dci_errors[0]+dci_errors[1]+dci_errors[2]+dci_errors[3])/(round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3]),