From 1a039eecbd021c4a886f00e7ab8d0ca413d4e50c Mon Sep 17 00:00:00 2001
From: Hongzhi Wang <hongzhi.wang@tcl.com>
Date: Tue, 12 Jun 2018 17:36:45 +0200
Subject: [PATCH] ue missing files

---
 openair1/PHY/NR_REFSIG/nr_dmrs_rx.c           | 158 +++++++++++
 openair1/PHY/NR_REFSIG/nr_gold_ue.c           | 115 ++++++++
 openair1/PHY/NR_REFSIG/refsig_defs_ue.h       |  43 +++
 openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h    |  86 ++++++
 .../nr_dl_channel_estimation.c                | 262 ++++++++++++++++++
 openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h |  60 ++++
 .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c     |   3 +-
 7 files changed, 726 insertions(+), 1 deletion(-)
 create mode 100644 openair1/PHY/NR_REFSIG/nr_dmrs_rx.c
 create mode 100644 openair1/PHY/NR_REFSIG/nr_gold_ue.c
 create mode 100644 openair1/PHY/NR_REFSIG/refsig_defs_ue.h
 create mode 100644 openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h
 create mode 100644 openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
 create mode 100644 openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h

diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c
new file mode 100644
index 0000000000..b02afcc9b7
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c
@@ -0,0 +1,158 @@
+/*
+ * 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
+ */
+
+/*! \file PHY/NR_REFSIG/nr_dl_dmrs.c
+* \brief Top-level routines for generating DMRS from 38-211
+* \author
+* \date 2018
+* \version 0.1
+* \company Eurecom
+* \email:
+* \note
+* \warning
+*/
+
+//#define DEBUG_DL_DMRS
+//#define NR_PBCH_DMRS_LENGTH_DWORD 5
+//#define NR_PBCH_DMRS_LENGTH 144
+
+#ifdef USER_MODE
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#include "refsig_defs_ue.h"
+#include "PHY/defs_nr_UE.h"
+#include "log.h"
+
+/*Table 7.4.1.1.2-1/2 from 38.211 */
+int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1}};
+int wt1[8][2] = {{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1}};
+int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1},{1,1},{1,-1},{1,1},{1,1}};
+int wt2[12][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1}};
+
+short nr_mod_table[14] = {0,0,23170,23170,-23170,-23170,23170,23170,23170,-23170,-23170,23170,-23170,-23170};
+//extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT];
+
+
+int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue,
+						unsigned int ncp,
+						unsigned int Ns,
+						unsigned int nr_gold_pdsch[2][20][2][21],
+						int32_t *output,
+						unsigned short p,
+						int length_dmrs,
+						unsigned short nb_pdsch_rb)
+{
+  int32_t qpsk[4],nqpsk[4],*qpsk_p, n;
+  int w,mprime,ind,l,ind_dword,ind_qpsk_symb,kp,lp, config_type, k;
+  short pamp;
+
+  typedef int array_of_w[2];
+  array_of_w *wf;
+  array_of_w *wt;
+
+  config_type = 1;
+  printf("dmrs config type %d port %d\n", config_type, p);
+
+  // Compute the correct pilot amplitude, sqrt_rho_b = Q3.13
+  pamp = 23170; //ONE_OVER_SQRT2_Q15;
+
+  // This includes complex conjugate for channel estimation
+  ((short *)&qpsk[0])[0] = pamp;
+  ((short *)&qpsk[0])[1] = -pamp;
+  ((short *)&qpsk[1])[0] = -pamp;
+  ((short *)&qpsk[1])[1] = -pamp;
+  ((short *)&qpsk[2])[0] = pamp;
+  ((short *)&qpsk[2])[1] = pamp;
+  ((short *)&qpsk[3])[0] = -pamp;
+  ((short *)&qpsk[3])[1] = pamp;
+
+  ((short *)&nqpsk[0])[0] = -pamp;
+  ((short *)&nqpsk[0])[1] = pamp;
+  ((short *)&nqpsk[1])[0] = pamp;
+  ((short *)&nqpsk[1])[1] = pamp;
+  ((short *)&nqpsk[2])[0] = -pamp;
+  ((short *)&nqpsk[2])[1] = -pamp;
+  ((short *)&nqpsk[3])[0] = pamp;
+  ((short *)&nqpsk[3])[1] = -pamp;
+
+  wf = (config_type==0) ? wf1 : wf2;
+  wt = (config_type==0) ? wt1 : wt2;
+
+  if (config_type > 1)
+      LOG_E(PHY,"Bad PDSCH DMRS config type %d\n", config_type);
+
+  if ((p>=1000) && (p<((config_type==0) ? 1008 : 1012))) {
+      if (/*ue->frame_parms.Ncp == NORMAL*/ncp ==0) {
+
+        // r_n from 38.211 7.4.1.1
+        for (n=0; n<nb_pdsch_rb*((config_type==0) ? 3:2); n++) {
+        	for (lp =0; lp<length_dmrs; lp++){
+        		for (kp=0; kp<2; kp++){
+        			w = (wf[p-1000][kp])*(wt[p-1000][lp]);
+        			qpsk_p = (w==1) ? qpsk : nqpsk;
+
+        			ind = 2*n+kp;
+        			ind_dword = ind>>4;
+        			ind_qpsk_symb = ind&0xf;
+
+        			output[k] = qpsk_p[(ue->nr_gold_pdsch[0][Ns][lp][ind_dword]>>(2*ind_qpsk_symb))&3];
+
+
+#ifdef DEBUG_DL_DMRS
+          LOG_I(PHY,"Ns %d, p %d, ind_dword %d, ind_qpsk_symbol %d\n",
+                Ns,p,idx_dword,idx_qpsk_symb);
+          LOG_I(PHY,"index = %d\n",(nr_gold_pdsch[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+#endif
+
+          	  	  	k++;
+        		}
+        	}
+        }
+      } else {
+        LOG_E(PHY,"extended cp not supported for PDSCH DMRS yet\n");
+      }
+  } else {
+    LOG_E(PHY,"Illegal p %d PDSCH DMRS port\n",p);
+  }
+
+  return(0);
+}
+
+int nr_pbch_dmrs_rx(unsigned int *nr_gold_pbch,
+					int32_t *output	)
+{
+	int m;
+
+	/// BPSK modulation
+    for (m=0; m<NR_PBCH_DMRS_LENGTH; m++) {
+      output[m<<1] = nr_mod_table[((1 + ((nr_gold_pbch[m>>5]&(1<<(m&0x1f)))>>(m&0x1f)))<<1)];
+      output[(m<<1)+1] = nr_mod_table[((1 + ((nr_gold_pbch[m>>5]&(1<<(m&0x1f)))>>(m&0x1f)))<<1) + 1];
+#ifdef DEBUG_PBCH
+    printf("nr_gold_pbch[m>>5] %x\n",nr_gold_pbch[m>>5]);
+    printf("m %d  output %d %d\n", m, output[2*m], output[2*m+1]);
+#endif
+    }
+
+  return(0);
+}
+
diff --git a/openair1/PHY/NR_REFSIG/nr_gold_ue.c b/openair1/PHY/NR_REFSIG/nr_gold_ue.c
new file mode 100644
index 0000000000..48187714f4
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/nr_gold_ue.c
@@ -0,0 +1,115 @@
+/*
+ * 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
+ */
+
+#include "refsig_defs_ue.h"
+
+void nr_gold_pbch(PHY_VARS_NR_UE* ue)
+{
+
+  unsigned int n, x1, x2;
+  unsigned char Nid, i_ssb, i_ssb2;
+  unsigned char Lmax, l, n_hf, N_hf;
+
+  Nid = ue->frame_parms.Nid_cell;
+
+  Lmax = 8; //(fp->dl_CarrierFreq < 3e9)? 4:8;
+  N_hf = (Lmax == 4)? 2:1;
+
+  for (n_hf = 0; n_hf < N_hf; n_hf++) {
+
+    for (l = 0; l < Lmax ; l++) {
+      i_ssb = l & (Lmax-1);
+      i_ssb2 = (i_ssb<<2) + n_hf;
+
+      x1 = 1 + (1<<31);
+      x2 = (1<<11) * (i_ssb2 + 1) * ((Nid>>2) + 1) + (1<<6) * (i_ssb2 + 1) + (Nid&3);
+      x2 = x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
+
+      // skip first 50 double words (1600 bits)
+      for (n = 1; n < 50; n++) {
+        x1 = (x1>>1) ^ (x1>>4);
+        x1 = x1 ^ (x1<<31) ^ (x1<<28);
+        x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+        x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+      }
+
+      for (n=0; n<NR_PBCH_DMRS_LENGTH_DWORD; n++) {
+        x1 = (x1>>1) ^ (x1>>4);
+        x1 = x1 ^ (x1<<31) ^ (x1<<28);
+        x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+        x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+        ue->nr_gold_pbch[n_hf][l][n] = x1 ^ x2;
+      }
+
+    }
+  }
+
+}
+
+void nr_gold_pdsch(/*LTE_DL_FRAME_PARMS *frame_parms*/unsigned short lbar,unsigned int nr_gold_pdsch[2][20][2][21],unsigned int Nid_cell, unsigned short *n_idDMRS, unsigned short length_dmrs)
+{
+
+  unsigned char ns,l;
+  unsigned int n,x1,x2,x2tmp0,x2tmp1, x2tmp2,x2s;
+  int nscid;
+  unsigned int nid;
+
+  /// to be updated from higher layer
+  unsigned short lbar = 0;
+
+  for (nscid=0; nscid<2; nscid++) {
+    if (n_idDMRS)
+      nid = n_idDMRS[nscid];
+    else
+      nid = Nid_cell;
+
+    for (ns=0; ns<20; ns++) {
+
+      for (l=0; l<length_dmrs; l++) {
+
+    	x2tmp0 = ((14*ns+(lbar+l)+1)*((nid<<1)+1))<<17;
+        x2 = (x2tmp0+(nid<<1))%(1<<31);  //cinit
+
+        x1 = 1+ (1<<31);
+        x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
+
+        // skip first 50 double words (1600 bits)
+        for (n=1; n<50; n++) {
+          x1 = (x1>>1) ^ (x1>>4);
+          x1 = x1 ^ (x1<<31) ^ (x1<<28);
+          x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+          x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+            //printf("x1 : %x, x2 : %x\n",x1,x2);
+        }
+
+        for (n=0; n<14; n++) {
+          x1 = (x1>>1) ^ (x1>>4);
+          x1 = x1 ^ (x1<<31) ^ (x1<<28);
+          x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+          x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+          nr_gold_pdsch[nscid][ns][l][n] = x1^x2;
+            //printf("n=%d : c %x\n",n,x1^x2);
+        }
+
+      }
+    }
+  }
+}
diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h
new file mode 100644
index 0000000000..4cbc2e0db7
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h
@@ -0,0 +1,43 @@
+/*
+ * 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
+ */
+
+/* Definitions for LTE Reference signals */
+/* Author R. Knopp / EURECOM / OpenAirInterface.org */
+#ifndef __NR_REFSIG_DEFS__H__
+#define __NR_REFSIG_DEFS__H__
+#include "PHY/defs_nr_UE.h"
+
+
+/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS.
+@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
+ */
+int nr_pbch_dmrs_rx(unsigned int *nr_gold_pbch,	int32_t *output	);
+
+/*int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue,
+						unsigned int ncp,
+						unsigned int Ns,
+						unsigned int nr_gold_pdsch[2][20][2][21],
+						int32_t *output,
+						unsigned short p,
+						int length_dmrs,
+						unsigned short nb_pdsch_rb);*/
+
+#endif
diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h
new file mode 100644
index 0000000000..a37a591d2f
--- /dev/null
+++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h
@@ -0,0 +1,86 @@
+short filt16a_l0[16] = {
+16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r0[16] = {
+0,0,0,0,0,4096,8192,12288,16384,20480,24576,28672,0,0,0,0};
+
+short filt16a_m0[16] = {
+0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,-12288,0,0,0,0};
+
+short filt16a_l1[16] = {
+20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r1[16] = {
+0,0,0,0,0,0,4096,8192,12288,16384,20480,24576,0,0,0,0};
+
+short filt16a_m1[16] = {
+-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,0,0,0,0};
+
+short filt16a_l2[16] = {
+24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r2[16] = {
+0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0};
+
+short filt16a_m2[16] = {
+-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,0,0,0,0};
+
+short filt16a_l3[16] = {
+28672,24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r3[16] = {
+0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0};
+
+short filt16a_m3[16] = {
+-12288,-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0};
+
+short filt16a_l0_dc[16] = {
+16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r0_dc[16] = {
+0,0,0,0,0,3276,9830,13107,16384,19660,22937,26214,0,0,0,0};
+
+short filt16a_m0_dc[16] = {
+0,4096,8192,12288,16384,13107,6553,3276,0,-3277,-6554,-9831,0,0,0,0};
+
+short filt16a_l1_dc[16] = {
+16384,12288,8192,4096,0,-4096,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r1_dc[16] = {
+0,0,0,0,0,0,6553,9830,13107,16384,19660,22937,0,0,0,0};
+
+short filt16a_m1_dc[16] = {
+-4096,0,4096,8192,12288,16384,9830,6553,3276,0,-3277,-6554,0,0,0,0};
+
+short filt16a_l2_dc[16] = {
+26214,22937,19660,16384,13107,9830,6553,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r2_dc[16] = {
+0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0};
+
+short filt16a_m2_dc[16] = {
+-6554,-3277,0,3276,6553,6553,16384,12288,8192,4096,0,-4096,0,0,0,0};
+
+short filt16a_l3_dc[16] = {
+26214,22937,19660,16384,13107,9830,3276,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r3_dc[16] = {
+0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0};
+
+short filt16a_m3_dc[16] = {
+-9831,-6554,-3277,0,3276,6553,9830,16384,12288,8192,4096,0,0,0,0,0};
+
+short filt16a_1[16] = {
+16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384};
+
+short filt16a_2l0[16] = {
+16384,12288,8192,4096,-4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_2r0[16] = {
+0,4096,8192,12288,16384,20480,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_2l1[16] = {
+20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_2r1[16] = {
+-4096,0,4096,8192,12288,16384,0,0,0,0,0,0,0,0,0,0};
diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
new file mode 100644
index 0000000000..2a9b847e1e
--- /dev/null
+++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
@@ -0,0 +1,262 @@
+/*
+ * 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
+ */
+
+#ifdef USER_MODE
+#include <string.h>
+#endif
+//#include "defs.h"
+//#include "SCHED/defs.h"
+#include "PHY/defs_nr_UE.h"
+#include "filt16a_32.h"
+#include "T.h"
+#define DEBUG_CH
+
+int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
+                              uint8_t eNB_id,
+                              uint8_t eNB_offset,
+                              unsigned char Ns,
+                              unsigned char p,
+                              unsigned char l,
+                              unsigned char symbol)
+{
+  int pilot[2][200] __attribute__((aligned(16)));
+  unsigned char nu,aarx;
+  unsigned short k;
+  unsigned int rb,pilot_cnt;
+  int16_t ch[2],*pil,*rxF,*dl_ch,*dl_ch_prev,*fl,*fm,*f2l,*fr,f1,*f2r,*fl_dc,*fm_dc,*fr_dc;
+  int ch_offset,symbol_offset;
+
+  uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1];
+
+  uint8_t nushift;
+  uint8_t previous_thread_id = ue->current_thread_id[Ns>>1]==0 ? (RX_NB_TH-1):(ue->current_thread_id[Ns>>1]-1);
+  int **dl_ch_estimates         =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset];
+  int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF;
+
+
+  // recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation
+  nushift =  Nid_cell%4;
+
+  if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage
+    ch_offset     = ue->frame_parms.ofdm_symbol_size ;
+  else
+    ch_offset     = ue->frame_parms.ofdm_symbol_size*symbol;
+
+  symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
+
+  k = nushift;
+
+#ifdef DEBUG_CH
+  printf("PBCH Channel Estimation : ThreadId %d, eNB_offset %d cell_id %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d\n",ue->current_thread_id[Ns>>1], eNB_offset,Nid_cell,ch_offset,ue->frame_parms.ofdm_symbol_size,
+         ue->frame_parms.Ncp,l,Ns,k);
+#endif
+
+  switch (k) {
+  case 0:
+        fl = filt16a_l0;
+        fm = filt16a_m0;
+        fr = filt16a_r0;
+        fl_dc = filt16a_l0;
+        fm_dc = filt16a_m0;
+        fr_dc = filt16a_r0;
+        f1 = filt16a_1;
+        f2l = filt16a_2l0;
+        f2r = filt16a_2r0;
+        break;
+
+  case 1:
+        fl = filt16a_l1;
+        fm = filt16a_m1;
+        fr = filt16a_r1;
+        fl_dc = filt16a_l1;
+        fm_dc = filt16a_m1;
+        fr_dc = filt16a_r1;
+        f1 = filt16a_1;
+        f2l = filt16a_2l1;
+        f2r = filt16a_2r1;
+        break;
+
+  case 2:
+        fl = filt16a_l2;
+        fm = filt16a_m2;
+        fr = filt16a_r2;
+        fl_dc = filt16a_l2;
+        fm_dc = filt16a_m2;
+        fr_dc = filt16a_r2;
+        f1 = filt16a_1;
+        f2l = filt16a_2l0;
+        f2r = filt16a_2r0;
+        break;
+
+  case 3:
+        fl = filt16a_l3;
+        fm = filt16a_m3;
+        fr = filt16a_r3;
+        fl_dc = filt16a_l3;
+        fm_dc = filt16a_m3;
+        fr_dc = filt16a_r3;
+        f1 = filt16a_1;
+        f2l = filt16a_2l1;
+        f2r = filt16a_2r1;
+        break;
+
+  default:
+    msg("pbch_channel_estimation: k=%d -> ERROR\n",k);
+    return(-1);
+    break;
+  }
+
+
+
+  // generate pilot
+  nr_pbch_dmrs_rx(ue->nr_gold_pbch,
+					  &pilot[p][0]);
+
+  for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
+
+    pil   = (int16_t *)&pilot[p][0];
+    rxF   = (int16_t *)&rxdataF[aarx][((symbol_offset+k+ue->frame_parms.first_carrier_offset))];
+    dl_ch = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset];
+
+    memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size));
+    if (ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha
+      multadd_complex_vector_real_scalar(dl_ch-(ue->frame_parms.ofdm_symbol_size<<1),
+                                         ue->ch_est_alpha,dl_ch-(ue->frame_parms.ofdm_symbol_size<<1),
+                                         1,ue->frame_parms.ofdm_symbol_size);
+#ifdef DEBUG_CH
+    printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset);
+#endif
+    if ((ue->frame_parms.N_RB_DL&1)==0) {
+
+      // Treat first 2 pilots specially (left edge)
+      ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+      ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+#ifdef DEBUG_CH
+      printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
+      printf("pilot 0 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+#endif
+      multadd_real_vector_complex_scalar(fl,
+                                         ch,
+                                         dl_ch,
+                                         16);
+      pil+=2;
+      rxF+=8;
+      for (int i= 0; i<8; i++)
+      printf("dl_ch %d %d\n", dl_ch+i, *(dl_ch+i));
+      //dl_ch+=6;
+      printf("after dl_ch %d %d\n", dl_ch, *(dl_ch));
+
+      ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+      ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+#ifdef DEBUG_CH
+      printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+#endif
+      multadd_real_vector_complex_scalar(fm,
+                                         ch,
+                                         dl_ch,
+                                         16);
+      //printf("after dl_ch %d %d\n", dl_ch, *(dl_ch));
+      for (int i= 0; i<16; i++)
+            printf("dl_ch %d %d\n", dl_ch+i, *(dl_ch+i));
+
+      pil+=2;
+      rxF+=8;
+      //dl_ch+=6;
+      printf("after 6 dl_ch %d %d\n", dl_ch, *(dl_ch));
+
+      ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+      ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+
+      #ifdef DEBUG_CH
+            printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+      #endif
+
+      multadd_real_vector_complex_scalar(fr,
+                                         ch,
+                                         dl_ch,
+                                         16);
+      pil+=2;
+      rxF+=8;
+      dl_ch+=16;
+
+      for (pilot_cnt=6; pilot_cnt<((ue->frame_parms.N_RB_DL)-1); pilot_cnt+=6) {
+
+
+
+        ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+        ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+#ifdef DEBUG_CH
+	printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+#endif
+        multadd_real_vector_complex_scalar(fl,
+                                           ch,
+                                           dl_ch,
+                                           16);
+
+        for (int i= 0; i<8; i++)
+                    printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i));
+
+        pil+=2;
+        rxF+=8;
+        //dl_ch+=6;
+
+        ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+        ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+#ifdef DEBUG_CH
+	printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+#endif
+        multadd_real_vector_complex_scalar(fm,
+                                           ch,
+                                           dl_ch,
+                                           16);
+        pil+=2;
+        rxF+=8;
+        //dl_ch+=6;
+
+        ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+        ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+
+        #ifdef DEBUG_CH
+              printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+        #endif
+
+        multadd_real_vector_complex_scalar(fr,
+                                           ch,
+                                           dl_ch,
+                                           16);
+        pil+=2;
+        rxF+=8;
+        dl_ch+=16;
+
+      }
+
+
+    }
+
+
+    printf("dl_ch %d\n", dl_ch);
+
+
+  }
+
+  return(0);
+}
+
diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h
new file mode 100644
index 0000000000..7ec222727b
--- /dev/null
+++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h
@@ -0,0 +1,60 @@
+/*
+ * 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
+ */
+
+#ifndef __LTE_ESTIMATION_DEFS__H__
+#define __LTE_ESTIMATION_DEFS__H__
+
+
+#include "PHY/defs_nr_UE.h"
+#include "PHY/defs_gNB.h"
+/** @addtogroup _PHY_PARAMETER_ESTIMATION_BLOCKS_
+ * @{
+ */
+
+/*!\brief Timing drift hysterisis in samples*/
+#define SYNCH_HYST 2
+
+/*!
+\brief This function performs channel estimation including frequency and temporal interpolation
+\param phy_vars_ue Pointer to UE PHY variables
+\param eNB_id Index of target eNB
+\param eNB_offset Offset for interfering eNB (in terms cell ID mod 3)
+\param Ns slot number (0..19)
+\param p antenna port
+\param l symbol within slot
+\param symbol symbol within frame
+*/
+int nr_dl_channel_estimation(PHY_VARS_NR_UE *ue,
+                              uint8_t eNB_id,
+                              uint8_t eNB_offset,
+                              unsigned char Ns,
+                              unsigned char p,
+                              unsigned char l,
+                              unsigned char symbol);
+
+int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
+                              uint8_t eNB_id,
+                              uint8_t eNB_offset,
+                              unsigned char Ns,
+                              unsigned char p,
+                              unsigned char l,
+                              unsigned char symbol);
+#endif
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
index a2373b8ef2..ccc031ed84 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
@@ -257,7 +257,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
 
     set_default_frame_parms_single(config,&ue->frame_parms);
     nr_init_frame_parms_ue(config,&ue->frame_parms);
-    //generate_dmrs_pbch(ue->dmrs_pbch_bitmap_nr, frame_parms->Nid_cell);
+
+    nr_gold_pbch(ue);
     ret = pbch_detection(ue,mode);
     //   write_output("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
 
-- 
GitLab