diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 22bf239259e9dee2f6d0dad8fff6664a53e69ff2..570e588b71443f121439746d7c8cb609ec8bce03 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 67d6720d645adbd361d0766638721221f4cbc77e..85dcd51921ee261b0b69122235c1d44d6c53b99b 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 0000000000000000000000000000000000000000..f1b382c29de517f1cd518f4e2cc982c57808a12a --- /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 9ff21defc2dfb80ed7785abe0b8ab0142f2809e7..ad03bc7d70327b636bc8229b5656b8b727d9497d 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 0000000000000000000000000000000000000000..b070749fa128fe3d45c8494e832ba42d7bcd5c82 --- /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 8bc11c429882fa879193b38551eae2b546b796a3..513276e62084b12cd200cb4f11e402d25eebff3e 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 7d3d44e1bd946a1f82cc168284c0faf10a82c7a3..7fdb6f095f92461600026fd542c5c6d3174445ab 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 113c0a614bbde1dfe08360380addcc58b051cb2c..83db0e039c93e778e6cd9295880499dbe8e8b681 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 97ffe24e3683c9193edf96b1f30c537a42065506..a22b2886d27faabbef251fca29cc76a7600059ce 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 8cbb3417773598cad76639addc0b9f5741021437..947ab9ee38720fd1d29f4e42b4bc46d12de6e485 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); } }