From 56785bde0c33b155f161e52c3679b4f621b9995c Mon Sep 17 00:00:00 2001
From: Guy De Souza <desouza@eurecom.fr>
Date: Mon, 30 Apr 2018 18:17:38 +0200
Subject: [PATCH] PBCH DMRS TX

---
 cmake_targets/CMakeLists.txt              |  3 +
 openair1/PHY/INIT/nr_init.c               |  3 +-
 openair1/PHY/NR_REFSIG/defs.h             | 35 ++++++++++++
 openair1/PHY/NR_REFSIG/nr_gen_mod_table.m |  5 +-
 openair1/PHY/NR_REFSIG/nr_gold.c          | 67 +++++++++++++++++++++++
 openair1/PHY/NR_REFSIG/nr_mod_table.h     | 23 +-------
 openair1/PHY/NR_TRANSPORT/nr_pbch.c       | 51 ++++++++++++++++-
 openair1/PHY/defs.h                       |  7 +++
 openair1/SCHED_NR/defs.h                  |  5 ++
 openair1/SCHED_NR/phy_procedures_nr_gNB.c |  3 +
 10 files changed, 174 insertions(+), 28 deletions(-)
 create mode 100644 openair1/PHY/NR_REFSIG/defs.h
 create mode 100644 openair1/PHY/NR_REFSIG/nr_gold.c

diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 22bf239259..570e588b71 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1262,6 +1262,9 @@ set(PHY_SRC_UE
   ${OPENAIR1_DIR}/PHY/INIT/nr_parms.c
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_pss.c
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sss.c
+  ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_pbch.c
+  ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold.c
+  ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c
   ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
   ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
   ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index 67d6720d64..85dcd51921 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -112,6 +112,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
         );*/
   LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_gNB][MOD %02"PRIu8"][]\n", gNB->Mod_id);
 
+  nr_init_pbch_dmrs(gNB);
 /*
   lte_gold(fp,gNB->lte_gold_table,fp->Nid_cell);
   generate_pcfich_reg_mapping(fp);
@@ -120,7 +121,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
   for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
     gNB->first_run_timing_advance[UE_id] =
       1; ///This flag used to be static. With multiple gNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here.
-    
+
     // clear whole structure
     bzero( &gNB->UE_stats[UE_id], sizeof(LTE_eNB_UE_stats) );
     
diff --git a/openair1/PHY/NR_REFSIG/defs.h b/openair1/PHY/NR_REFSIG/defs.h
new file mode 100644
index 0000000000..f1b382c29d
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/defs.h
@@ -0,0 +1,35 @@
+/*
+ * 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.h"
+
+
+/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS.
+@param PHY_VARS_gNB* gNB structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
+ */
+void nr_init_pbch_dmrs(PHY_VARS_gNB* gNB);
+
+
+#endif
diff --git a/openair1/PHY/NR_REFSIG/nr_gen_mod_table.m b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.m
index 9ff21defc2..ad03bc7d70 100644
--- a/openair1/PHY/NR_REFSIG/nr_gen_mod_table.m
+++ b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.m
@@ -3,9 +3,6 @@
 % 0        .. "0"
 % 1,2      .. BPSK(0),BPSK(1)
 
-% 2^15 /sqrt(2) K = 768;
-K = 768*sqrt(2)/2^15;
-
 % Amplitude for BPSK (\f$ 2^15 \times 1/\sqrt{2}\f$)
 BPSK = 23170;
 
@@ -14,7 +11,7 @@ for b = 0:1
 bpsk_table(b+1) = (1 - 2*b)*BPSK + 1j*(1-2*b)*BPSK;
 end
 
-table = round(K * [ 0; bpsk_table(:) ]);
+table = [ 0; bpsk_table(:) ];
 
 save mod_table.mat table
 
diff --git a/openair1/PHY/NR_REFSIG/nr_gold.c b/openair1/PHY/NR_REFSIG/nr_gold.c
new file mode 100644
index 0000000000..b070749fa1
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/nr_gold.c
@@ -0,0 +1,67 @@
+/*
+ * 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 "defs.h"
+
+void nr_init_pbch_dmrs(PHY_VARS_gNB* gNB)
+{
+
+  unsigned int n, x1, x2;
+  unsigned char Nid, i_ssb, i_ssb2;
+  unsigned char Lmax, l, n_hf, N_hf;
+  nfapi_config_request_t *cfg = &gNB->gNB_config;
+  NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
+
+  Nid = cfg->sch_config.physical_cell_id.value;
+
+  Lmax = (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;
+      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);
+        gNB->nr_gold_pbch_dmrs[n_hf][l][n] = x1 ^ x2;
+      }
+
+    }
+  }
+
+}
diff --git a/openair1/PHY/NR_REFSIG/nr_mod_table.h b/openair1/PHY/NR_REFSIG/nr_mod_table.h
index 8bc11c4298..513276e620 100644
--- a/openair1/PHY/NR_REFSIG/nr_mod_table.h
+++ b/openair1/PHY/NR_REFSIG/nr_mod_table.h
@@ -1,24 +1,3 @@
-/*
- * 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
- */
-
 #define MOD_TABLE_SIZE_SHORT 6
 #define MOD_TABLE_BPSK_OFFSET 1
-short nr_mod_table[MOD_TABLE_SIZE_SHORT] = {0,0,768,768,-768,-768};
+short nr_mod_table[MOD_TABLE_SIZE_SHORT] = {0,0,23170,23170,-23170,-23170};
diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c
index 7d3d44e1bd..7fdb6f095f 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c
@@ -37,4 +37,53 @@
 #include "PHY/extern.h"
 #include "PHY/sse_intrin.h"
 
-//#define DEBUG_PBCH 1
+#define DEBUG_PBCH
+
+short nr_mod_table[MOD_TABLE_SIZE_SHORT] = {0,0,23170,23170,-23170,-23170};
+
+int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs,
+                          int32_t **txdataF,
+                          int16_t amp,
+                          uint8_t ssb_start_symbol,
+                          nfapi_config_request_t* config,
+                          NR_DL_FRAME_PARMS *frame_parms)
+{
+  int m,k,l;
+  int a, aa;
+  uint16_t mod_dmrs[2 * NR_PBCH_DMRS_LENGTH];
+
+
+  /// BPSK modulation
+  for (m=0; m<NR_PBCH_DMRS_LENGTH; m++) {
+    mod_dmrs[2*m] = nr_mod_table[2*(1 + (*(gold_pbch_dmrs + m/32))&(1<<(m&0xf)) )];
+    mod_dmrs[2*m + 1] = nr_mod_table[2*(1 + (*(gold_pbch_dmrs + m/32))&(1<<(m&0xf)) ) + 1];
+#ifdef DEBUG_PBCH
+  printf("m %d  mod_dmrs %d %d", m, mod_dmrs[2*m], mod_dmrs[2*m + 1]);
+#endif
+  }
+
+  /// Resource mapping
+  a = (config->rf_config.tx_antenna_ports.value == 1) ? amp : (amp*ONE_OVER_SQRT2_Q15)>>15;
+
+  for (aa = 0; aa < config->rf_config.tx_antenna_ports.value; aa++)
+  {
+
+    // PBCH DMRS are mapped
+    k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; //and
+    l = ssb_start_symbol + 1;
+
+    for (m = 0; m < NR_PBCH_DMRS_LENGTH; m++) {
+      ((int16_t*)txdataF[aa])[2*(l*frame_parms->ofdm_symbol_size + k)] = (a * mod_dmrs[2*m]) >> 15;
+      ((int16_t*)txdataF[aa])[2*(l*frame_parms->ofdm_symbol_size + k) + 1] = (a * mod_dmrs[2*m + 1]) >> 15;
+#ifdef DEBUG_PBCH
+  int idx = 2*(l*frame_parms->ofdm_symbol_size + k);
+  printf("aa %d m %d  txdataF  %d %d %d", aa, m, txdataF[aa][idx], txdataF[aa][idx+1]);
+#endif
+      k++;
+
+      if (k >= frame_parms->ofdm_symbol_size)
+        k-=frame_parms->ofdm_symbol_size;
+    }
+  }
+  return (0);
+}
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 113c0a614b..83db0e039c 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -134,6 +134,7 @@ static inline void* malloc16_clear( size_t size )
 #include "PHY/CODING/defs.h"
 #include "PHY/TOOLS/defs.h"
 #include "platform_types.h"
+
 #define MAX_NUM_RU_PER_eNB 64 
 
 #include "PHY/LTE_TRANSPORT/defs.h"
@@ -169,6 +170,9 @@ static inline void* malloc16_clear( size_t size )
 
 #define nr_subframe_t lte_subframe_t
 
+#define NR_PBCH_DMRS_LENGTH 144
+#define NR_PBCH_DMRS_LENGTH_DWORD 5 // roundup(NR_PBCH_DMRS_LENGTH/32)
+
 typedef enum{
   nr_ssb_type_A = 0,
   nr_ssb_type_B,
@@ -1989,6 +1993,9 @@ typedef struct PHY_VARS_gNB_s {
   int16_t d_pss[NR_PSS_LENGTH];
   int16_t d_sss[NR_SSS_LENGTH];
 
+  /// PBCH DMRS sequence
+  uint32_t nr_gold_pbch_dmrs[2][64][NR_PBCH_DMRS_LENGTH_DWORD];
+
   /// Indicator set to 0 after first SR
   uint8_t first_sr[NUMBER_OF_UE_MAX];
 
diff --git a/openair1/SCHED_NR/defs.h b/openair1/SCHED_NR/defs.h
index 97ffe24e36..a22b2886d2 100644
--- a/openair1/SCHED_NR/defs.h
+++ b/openair1/SCHED_NR/defs.h
@@ -45,6 +45,11 @@ int nr_generate_sss(  int16_t *d_sss,
                       uint8_t ssb_start_symbol,
                       nfapi_config_request_t* config,
                       NR_DL_FRAME_PARMS *frame_parms);
+int nr_generate_pbch_dmrs(uint32_t gold_sequence,
+                          int32_t **txdataF,
+                          int16_t amp,
+                          nfapi_config_request_t* config,
+                          NR_DL_FRAME_PARMS *frame_parms);
 void nr_set_ssb_first_subcarrier(nfapi_config_request_t *cfg, NR_DL_FRAME_PARMS *fp);
 
 #endif
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 8cbb341777..947ab9ee38 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -126,11 +126,14 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int subframe) {
   int ssb_start_symbol = nr_get_ssb_start_symbol(cfg, fp);
   nr_set_ssb_first_subcarrier(cfg, fp);
 
+
   if (subframe == ss_subframe)
   {
+    // Current implementation is based on SSB in first half frame, first candidate
     LOG_I(PHY,"SS TX: frame %d, subframe %d, start_symbol %d\n",frame,subframe, ssb_start_symbol);
     nr_generate_pss(gNB->d_pss, txdataF, AMP, ssb_start_symbol, cfg, fp);
     nr_generate_sss(gNB->d_sss, txdataF, AMP_OVER_2, ssb_start_symbol, cfg, fp);
+    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][0],txdataF, AMP_OVER_2, ssb_start_symbol, cfg, fp);
   }
 
 }
-- 
GitLab