diff --git a/openair1/PHY/LTE_TRANSPORT/phich_common.c b/openair1/PHY/LTE_TRANSPORT/phich_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..a3bc5250d5f79699e693cc77fd4855905a946801
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/phich_common.c
@@ -0,0 +1,383 @@
+/*
+ * 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.1  (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
+ */
+
+/*! \file PHY/LTE_TRANSPORT/phich_common.c
+* \brief Top-level routines for generating and decoding  the PHICH/HI physical/transport channel V8.6 2009-03
+* \author R. Knopp
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: knopp@eurecom.fr
+* \note
+* \warning
+*/
+
+#include "PHY/defs_eNB.h"
+
+
+uint8_t get_mi(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe)
+{
+
+  // for FDD
+  if (frame_parms->frame_type == FDD)
+    return 1;
+
+  // for TDD
+  switch (frame_parms->tdd_config) {
+
+  case 0:
+    if ((subframe==0) || (subframe==5))
+      return(2);
+    else return(1);
+
+    break;
+
+  case 1:
+    if ((subframe==0) || (subframe==5))
+      return(0);
+    else return(1);
+
+    break;
+
+  case 2:
+    if ((subframe==3) || (subframe==8))
+      return(1);
+    else return(0);
+
+    break;
+
+  case 3:
+    if ((subframe==0) || (subframe==8) || (subframe==9))
+      return(1);
+    else return(0);
+
+    break;
+
+  case 4:
+    if ((subframe==8) || (subframe==9))
+      return(1);
+    else return(0);
+
+    break;
+
+  case 5:
+    if (subframe==8)
+      return(1);
+    else return(0);
+
+    break;
+
+  case 6:
+    return(1);
+    break;
+
+  default:
+    return(0);
+  }
+}
+
+unsigned char subframe2_ul_harq(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
+{
+
+  if (frame_parms->frame_type == FDD)
+    return(subframe&7);
+
+  switch (frame_parms->tdd_config) {
+  case 3:
+    if ( (subframe == 8) || (subframe == 9) ) {
+      return(subframe-8);
+    } else if (subframe==0)
+      return(2);
+    else {
+      LOG_E(PHY,"phich.c: subframe2_ul_harq, illegal subframe %d for tdd_config %d\n",
+            subframe,frame_parms->tdd_config);
+      return(0);
+    }
+
+    break;
+
+  case 4:
+     if ( (subframe == 8) || (subframe == 9) ) {
+       return(subframe-8);
+     } else {
+       LOG_E(PHY,"phich.c: subframe2_ul_harq, illegal subframe %d for tdd_config %d\n",
+             subframe,frame_parms->tdd_config);
+       return(0);
+     }
+
+     break;
+
+  }
+
+  return(0);
+}
+
+int phich_frame2_pusch_frame(LTE_DL_FRAME_PARMS *frame_parms, int frame, int subframe)
+{
+  int pusch_frame;
+
+  if (frame_parms->frame_type == FDD) {
+    pusch_frame = subframe<4 ? frame + 1024 - 1 : frame;
+  } else {
+    // Note this is not true, but it doesn't matter, the frame number is irrelevant for TDD!
+    pusch_frame = (frame);
+  }
+
+  //LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n", frame, subframe, pusch_frame);
+  return pusch_frame % 1024;
+}
+
+uint8_t phich_subframe2_pusch_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe)
+{
+  uint8_t pusch_subframe = 255;
+
+  if (frame_parms->frame_type == FDD)
+    return subframe < 4 ? subframe + 6 : subframe - 4;
+
+  switch (frame_parms->tdd_config) {
+  case 0:
+    if (subframe == 0)
+      pusch_subframe = (3);
+    else if (subframe == 5) {
+      pusch_subframe = (8);
+    } else if (subframe == 6)
+      pusch_subframe = (2);
+    else if (subframe == 1)
+      pusch_subframe = (7);
+    else {
+      AssertFatal(1==0,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
+		  subframe,frame_parms->tdd_config);
+      pusch_subframe = (0);
+    }
+
+    break;
+
+  case 1:
+    if (subframe == 6)
+      pusch_subframe = (2);
+    else if (subframe == 9)
+      pusch_subframe = (3);
+    else if (subframe == 1)
+      pusch_subframe = (7);
+    else if (subframe == 4)
+      pusch_subframe = (8);
+    else {
+      AssertFatal(1==0,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
+            subframe,frame_parms->tdd_config);
+      pusch_subframe = (0);
+    }
+
+    break;
+
+  case 2:
+    if (subframe == 8)
+      pusch_subframe = (2);
+    else if (subframe == 3)
+      pusch_subframe = (7);
+    else {
+      AssertFatal(1==0,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
+            subframe,frame_parms->tdd_config);
+      pusch_subframe = (0);
+    }
+
+    break;
+
+  case 3:
+    if ( (subframe == 8) || (subframe == 9) ) {
+      pusch_subframe = (subframe-6);
+    } else if (subframe==0)
+      pusch_subframe = (4);
+    else {
+      AssertFatal(1==0,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
+            subframe,frame_parms->tdd_config);
+      pusch_subframe = (0);
+    }
+
+    break;
+
+  case 4:
+    if ( (subframe == 8) || (subframe == 9) ) {
+      pusch_subframe = (subframe-6);
+    } else {
+      AssertFatal(1==0,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
+            subframe,frame_parms->tdd_config);
+      pusch_subframe = (0);
+    }
+
+    break;
+
+  case 5:
+    if (subframe == 8) {
+      pusch_subframe = (2);
+    } else {
+      AssertFatal(1==0,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
+            subframe,frame_parms->tdd_config);
+      pusch_subframe = (0);
+    }
+
+    break;
+
+  case 6:
+    if (subframe == 6) {
+      pusch_subframe = (2);
+    } else if (subframe == 9) {
+      pusch_subframe = (3);
+    } else if (subframe == 0) {
+      pusch_subframe = (4);
+    } else if (subframe == 1) {
+      pusch_subframe = (7);
+    } else if (subframe == 5) {
+      pusch_subframe = (8);
+    } else {
+      AssertFatal(1==0,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
+            subframe,frame_parms->tdd_config);
+      pusch_subframe = (0);
+    }
+
+    break;
+
+  default:
+    AssertFatal(1==0, "no implementation for TDD UL/DL-config = %d!\n", frame_parms->tdd_config);
+    pusch_subframe = (0);
+  }
+
+  LOG_D(PHY, "subframe  %d: PUSCH subframe = %d\n", subframe, pusch_subframe);
+  return pusch_subframe;
+}
+
+int check_pcfich(LTE_DL_FRAME_PARMS *frame_parms,uint16_t reg)
+{
+
+  if ((reg == frame_parms->pcfich_reg[0]) ||
+      (reg == frame_parms->pcfich_reg[1]) ||
+      (reg == frame_parms->pcfich_reg[2]) ||
+      (reg == frame_parms->pcfich_reg[3]))
+    return(1);
+
+  return(0);
+}
+
+void generate_phich_reg_mapping(LTE_DL_FRAME_PARMS *frame_parms)
+{
+
+  unsigned short n0 = (frame_parms->N_RB_DL * 2) - 4;  // 2 REG per RB less the 4 used by PCFICH in first symbol
+  unsigned short n1 = (frame_parms->N_RB_DL * 3);      // 3 REG per RB in second and third symbol
+  unsigned short n2 = n1;
+  unsigned short mprime = 0;
+  unsigned short Ngroup_PHICH;
+  //  uint16_t *phich_reg = frame_parms->phich_reg;
+  uint16_t *pcfich_reg = frame_parms->pcfich_reg;
+
+  // compute Ngroup_PHICH (see formula at beginning of Section 6.9 in 36-211
+  Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48;
+
+
+  if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0)
+    Ngroup_PHICH++;
+
+  // check if Extended prefix
+  if (frame_parms->Ncp == 1) {
+    Ngroup_PHICH<<=1;
+  }
+
+#ifdef DEBUG_PHICH
+  LOG_D(PHY,"Ngroup_PHICH %d (phich_config_common.phich_resource %d,phich_config_common.phich_duration %s, NidCell %d,Ncp %d, frame_type %d), smallest pcfich REG %d, n0 %d, n1 %d (first PHICH REG %d)\n",
+    ((frame_parms->Ncp == NORMAL)?Ngroup_PHICH:(Ngroup_PHICH>>1)),
+    frame_parms->phich_config_common.phich_resource,
+    frame_parms->phich_config_common.phich_duration==normal?"normal":"extended",
+    frame_parms->Nid_cell,frame_parms->Ncp,frame_parms->frame_type,
+    pcfich_reg[frame_parms->pcfich_first_reg_idx],
+    n0,
+    n1,
+    ((frame_parms->Nid_cell))%n0);
+#endif
+
+  // This is the algorithm from Section 6.9.3 in 36-211, it works only for normal PHICH duration for now ...
+
+  for (mprime=0; 
+       mprime<((frame_parms->Ncp == NORMAL)?Ngroup_PHICH:(Ngroup_PHICH>>1)); 
+       mprime++) {
+
+    if (frame_parms->phich_config_common.phich_duration==normal) { // normal PHICH duration
+
+      frame_parms->phich_reg[mprime][0] = (frame_parms->Nid_cell + mprime)%n0;
+
+      if (frame_parms->phich_reg[mprime][0]>=pcfich_reg[frame_parms->pcfich_first_reg_idx])
+        frame_parms->phich_reg[mprime][0]++;
+
+      if (frame_parms->phich_reg[mprime][0]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+1)&3])
+        frame_parms->phich_reg[mprime][0]++;
+
+      if (frame_parms->phich_reg[mprime][0]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+2)&3])
+        frame_parms->phich_reg[mprime][0]++;
+
+      if (frame_parms->phich_reg[mprime][0]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+3)&3])
+        frame_parms->phich_reg[mprime][0]++;
+
+      frame_parms->phich_reg[mprime][1] = (frame_parms->Nid_cell + mprime + (n0/3))%n0;
+
+      
+      if (frame_parms->phich_reg[mprime][1]>=pcfich_reg[frame_parms->pcfich_first_reg_idx])
+        frame_parms->phich_reg[mprime][1]++;
+      
+      if (frame_parms->phich_reg[mprime][1]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+1)&3])
+        frame_parms->phich_reg[mprime][1]++;
+
+      if (frame_parms->phich_reg[mprime][1]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+2)&3])
+        frame_parms->phich_reg[mprime][1]++;
+
+      if (frame_parms->phich_reg[mprime][1]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+3)&3])
+        frame_parms->phich_reg[mprime][1]++;
+      
+
+      frame_parms->phich_reg[mprime][2] = (frame_parms->Nid_cell + mprime + (2*n0/3))%n0;
+      
+      if (frame_parms->phich_reg[mprime][2]>=pcfich_reg[frame_parms->pcfich_first_reg_idx])
+        frame_parms->phich_reg[mprime][2]++;
+
+      if (frame_parms->phich_reg[mprime][2]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+1)&3])
+        frame_parms->phich_reg[mprime][2]++;
+
+      if (frame_parms->phich_reg[mprime][2]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+2)&3])
+        frame_parms->phich_reg[mprime][2]++;
+
+      if (frame_parms->phich_reg[mprime][2]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+3)&3])
+        frame_parms->phich_reg[mprime][2]++;
+      
+#ifdef DEBUG_PHICH
+      printf("phich_reg :%d => %d,%d,%d\n",mprime,frame_parms->phich_reg[mprime][0],frame_parms->phich_reg[mprime][1],frame_parms->phich_reg[mprime][2]);
+#endif
+    } else { // extended PHICH duration
+      frame_parms->phich_reg[mprime<<1][0] = (frame_parms->Nid_cell + mprime)%n0;
+      frame_parms->phich_reg[1+(mprime<<1)][0] = (frame_parms->Nid_cell + mprime)%n0;
+
+      frame_parms->phich_reg[mprime<<1][1] = ((frame_parms->Nid_cell*n1/n0) + mprime + (n1/3))%n1;
+      frame_parms->phich_reg[mprime<<1][2] = ((frame_parms->Nid_cell*n2/n0) + mprime + (2*n2/3))%n2;
+
+      frame_parms->phich_reg[1+(mprime<<1)][1] = ((frame_parms->Nid_cell*n1/n0) + mprime + (n1/3))%n1;
+      frame_parms->phich_reg[1+(mprime<<1)][2] = ((frame_parms->Nid_cell*n2/n0) + mprime + (2*n2/3))%n2;
+      //#ifdef DEBUG_PHICH
+      printf("phich_reg :%d => %d,%d,%d\n",mprime<<1,frame_parms->phich_reg[mprime<<1][0],frame_parms->phich_reg[mprime][1],frame_parms->phich_reg[mprime][2]);
+      printf("phich_reg :%d => %d,%d,%d\n",1+(mprime<<1),frame_parms->phich_reg[1+(mprime<<1)][0],frame_parms->phich_reg[1+(mprime<<1)][1],frame_parms->phich_reg[1+(mprime<<1)][2]);
+      //#endif
+    }
+  } // mprime loop
+}  // num_pdcch_symbols loop