From 89d0971d31d96e171e02dfc65be816c970688a61 Mon Sep 17 00:00:00 2001 From: Guy De Souza Date: Mon, 9 Jul 2018 14:59:45 +0200 Subject: [PATCH] PBCH payload interleaving --- openair1/PHY/INIT/nr_parms.c | 4 +- openair1/PHY/NR_TRANSPORT/nr_pbch.c | 94 +++++++++++++++++------ openair1/PHY/NR_TRANSPORT/nr_transport.h | 16 +++- openair1/PHY/defs_gNB.h | 3 +- openair1/PHY/defs_nr_common.h | 11 ++- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 9 +-- 6 files changed, 99 insertions(+), 38 deletions(-) diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 8512beb0d5..c54cab3017 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -146,7 +146,7 @@ int nr_init_frame_parms(nfapi_config_request_t* config, frame_parms->samples_per_subframe = (frame_parms->samples_per_subframe_wCP + (frame_parms->nb_prefix_samples0 * frame_parms->slots_per_subframe) + (frame_parms->nb_prefix_samples * frame_parms->slots_per_subframe * (frame_parms->symbols_per_slot - 1))); frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe; - + frame_parms->freq_range = (frame_parms->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; return 0; } @@ -283,7 +283,7 @@ int nr_init_frame_parms_ue(nfapi_config_request_t* config, //frame_parms->samples_per_subframe = (frame_parms->samples_per_subframe_wCP + (frame_parms->nb_prefix_samples0 * frame_parms->slots_per_subframe) + // (frame_parms->nb_prefix_samples * frame_parms->slots_per_subframe * (frame_parms->symbols_per_slot - 1))); frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe; - + frame_parms->freq_range = (frame_parms->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 24f9234e75..cfa34794e8 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -45,7 +45,6 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, int32_t **txdataF, int16_t amp, uint8_t ssb_start_symbol, - uint8_t nushift, nfapi_config_request_t* config, NR_DL_FRAME_PARMS *frame_parms) { @@ -53,11 +52,12 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, int16_t a; int16_t mod_dmrs[NR_PBCH_DMRS_LENGTH<<1]; uint8_t idx=0; + uint8_t nushift = config->sch_config.physical_cell_id.value &3; LOG_I(PHY, "PBCH DMRS mapping started at symbol %d shift %d\n", ssb_start_symbol+1, nushift); /// QPSK modulation - for (int m=0; m>1; m++) { + for (int m=0; m>5])>>((m<<1)&0x1f))&1)<<1) ^ (((gold_pbch_dmrs[((m<<1)+1)>>5])>>(((m<<1)+1)&0x1f))&1); mod_dmrs[m<<1] = nr_mod_table[(NR_MOD_TABLE_QPSK_OFFSET + idx)<<1]; mod_dmrs[(m<<1)+1] = nr_mod_table[((NR_MOD_TABLE_QPSK_OFFSET + idx)<<1) + 1]; @@ -134,22 +134,22 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, void nr_pbch_scrambling(uint32_t Nid, uint8_t nushift, uint8_t *pbch_a, - uint32_t length) + uint16_t M, + uint16_t length) { uint8_t reset, offset; uint32_t x1, x2, s=0; - uint64_t tmp=0; - uint8_t M = length - 3; // case Lmax = 4--> 29 reset = 1; // x1 is set in lte_gold_generic x2 = Nid; // The Gold sequence is shifted by nushift* M, so we skip (nushift*M /32) double words - for (int i=0; i<(uint16_t)ceil((nushift*M)/5); i++) { + for (int i=0; i<(uint16_t)ceil((nushift*M)/32); i++) { s = lte_gold_generic(&x1, &x2, reset); reset = 0; } + // Scrambling is now done with offset (nushift*M)%32 offset = (nushift*M)&0x1f; for (int i=0; ipbch_a[NR_PBCH_PDU_BITS-i-1] = pbch_pdu[i]; - - // Extra bits generation - sfn_4lsb = sfn&3; - for (int i=0; i<4; i++) - pbch->pbch_a[NR_PBCH_PDU_BITS+i] = (sfn_4lsb>>i)&1; // 4 lsb of sfn - - pbch->pbch_a[NR_PBCH_PDU_BITS+4] = n_hf; // half frame index bit - - pbch->pbch_a[NR_PBCH_PDU_BITS+5] = (config->sch_config.ssb_subcarrier_offset.value>>5)&1; //MSB of k0 -- Note the case Lssb=64 is not supported (FR2) + if (!(sfn&7)) + for (int i=0; i<(NR_PBCH_PDU_BITS>>3); i++) + pbch->pbch_a[(NR_POLAR_PBCH_PAYLOAD_BITS>>3)-i-1] = pbch_pdu[i]; #ifdef DEBUG_PBCH_ENCODING + printf("Byte endian fix:\n"); + for (int i=0; i<4; i++) + printf("pbch_a[%d]: 0x%08x\n", i, pbch->pbch_a[i]); +#endif + + // Extra byte generation + uint8_t *xbyte = pbch->pbch_a; + //memset((void*) xbyte, 0, 1); + for (int i=0; i<4; i++) + (*xbyte) ^= ((sfn>>i)&1)<>(3+i))&1)<<(5+i); // resp. 4th, 5th and 6th bits of ssb_index + else + (*xbyte) ^= ((config->sch_config.ssb_subcarrier_offset.value>>5)&1)<<5; //MSB of k_SSB +#ifdef DEBUG_PBCH_ENCODING + printf("Extra byte:\n"); + for (int i=0; i<4; i++) + printf("pbch_a[%d]: 0x%08x\n", i, pbch->pbch_a[i]); +#endif + + // Payload interleaving + uint32_t* input = (uint32_t*)pbch->pbch_a; + uint32_t* output = (uint32_t*)pbch->pbch_a_interleaved; + for (int i=0; i<32; i++) + (*output) |= (((*input)>>i)&1)<<(nr_pbch_payload_interleaver(i)); +#ifdef DEBUG_PBCH_ENCODING + printf("Interleaving:\n"); + for (int i=0; i<4; i++) + printf("pbch_a_interleaved[%d]: 0x%08x\n", i, pbch->pbch_a_interleaved[i]); #endif // Scrambling - nr_pbch_scrambling((uint32_t)config->sch_config.physical_cell_id.value, nushift, pbch->pbch_a, NR_POLAR_PBCH_PAYLOAD_BITS); + M = NR_POLAR_PBCH_PAYLOAD_BITS - 3; // case Lmax = 4--> 29 + nr_pbch_scrambling((uint32_t)config->sch_config.physical_cell_id.value, nushift, pbch->pbch_a_interleaved, M, NR_POLAR_PBCH_PAYLOAD_BITS); #ifdef DEBUG_PBCH_ENCODING #endif + /// CRC, coding and rate matching polar_encoder (pbch->pbch_a, pbch->pbch_e, &frame_parms->pbch_polar_params); #ifdef DEBUG_PBCH_ENCODING #endif + /// Scrambling + M = NR_POLAR_PBCH_E; + nr_pbch_scrambling((uint32_t)config->sch_config.physical_cell_id.value, nushift, pbch->pbch_a, M, NR_POLAR_PBCH_E); + /// QPSK modulation for (int i=0; i>1; i++){ idx = ((pbch->pbch_e[i<<1]&1)<<1) ^ (pbch->pbch_e[(i<<1)+1]&1); @@ -224,6 +271,7 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, } /// Resource mapping + nushift = config->sch_config.physical_cell_id.value &3; a = (config->rf_config.tx_antenna_ports.value == 1) ? amp : (amp*ONE_OVER_SQRT2_Q15)>>15; for (int aa = 0; aa < config->rf_config.tx_antenna_ports.value; aa++) diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport.h b/openair1/PHY/NR_TRANSPORT/nr_transport.h index 58a4344e9d..cfa3ecc9e9 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport.h @@ -62,7 +62,6 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, int32_t **txdataF, int16_t amp, uint8_t ssb_start_symbol, - uint8_t nushift, nfapi_config_request_t* config, NR_DL_FRAME_PARMS *frame_parms); @@ -74,7 +73,8 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, void nr_pbch_scrambling(uint32_t Nid, uint8_t nushift, uint8_t *pbch_a, - uint32_t length); + uint16_t M, + uint16_t length); /*! \fn int nr_generate_pbch @@ -87,11 +87,19 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, int32_t **txdataF, int16_t amp, uint8_t ssb_start_symbol, - uint8_t nushift, uint8_t n_hf, + uint8_t Lmax, + uint8_t ssb_index, int sfn, - int frame_mod8, nfapi_config_request_t* config, NR_DL_FRAME_PARMS *frame_parms); +/*! +\fn int nr_generate_pbch +\brief PBCH interleaving function +@param bit index i of the input payload +@returns the bit index of the output + */ +uint8_t nr_pbch_payload_interleaver(uint8_t i); + #endif /*__NR_TRANSPORT__H__*/ diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 9728d6b2d0..d4c68d32dd 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -38,7 +38,8 @@ typedef struct { - uint8_t pbch_a[NR_POLAR_PBCH_PAYLOAD_BITS]; + uint8_t pbch_a[NR_POLAR_PBCH_PAYLOAD_BITS>>3]; + uint8_t pbch_a_interleaved[NR_POLAR_PBCH_PAYLOAD_BITS>>3]; uint8_t pbch_e[NR_POLAR_PBCH_E]; } NR_gNB_PBCH; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 57b3159310..a7b90576bb 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -54,8 +54,8 @@ #define NR_PSS_LENGTH 127 #define NR_SSS_LENGTH 127 -#define NR_PBCH_DMRS_LENGTH 144 -#define NR_PBCH_DMRS_LENGTH_DWORD 5 // roundup(NR_PBCH_DMRS_LENGTH/32) +#define NR_PBCH_DMRS_LENGTH 144 // in mod symbols +#define NR_PBCH_DMRS_LENGTH_DWORD 10 // roundup(2(QPSK)*NR_PBCH_DMRS_LENGTH/32) #define NR_MAX_NUM_BWP 4 @@ -76,6 +76,11 @@ typedef enum{ nr_ssb_type_E } nr_ssb_type_e; +typedef enum { + nr_FR1 = 0, + nr_FR2 +} nr_frequency_range_e; + typedef struct NR_BWP_PARMS { /// Associated numerology index uint8_t numerology_index; @@ -88,6 +93,8 @@ typedef struct NR_BWP_PARMS { } NR_BWP_PARMS; typedef struct NR_DL_FRAME_PARMS { + /// frequency range + nr_frequency_range_e freq_range; /// Number of resource blocks (RB) in DL uint8_t N_RB_DL; /// Number of resource blocks (RB) in UL diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index e40d8e0a5c..fbdae6aa7e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -123,16 +123,13 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int subframe) { int **txdataF = gNB->common_vars.txdataF; uint8_t *pbch_pdu=&gNB->pbch_pdu[0]; int ss_subframe = (cfg->sch_config.half_frame_index.value)? 5 : 0; - int sfn = 10*frame + subframe; - int frame_mod8 = frame&7; - uint8_t Lmax, nushift, ssb_index=0, n_hf=0; + uint8_t Lmax, ssb_index=0, n_hf=0; LOG_D(PHY,"common_signal_procedures: frame %d, subframe %d\n",frame,subframe); int ssb_start_symbol = nr_get_ssb_start_symbol(cfg, fp); nr_set_ssb_first_subcarrier(cfg, fp); Lmax = (fp->dl_CarrierFreq < 3e9)? 4:8; - nushift = (Lmax < 8)? ssb_index&3 : ssb_index&7; if (subframe == ss_subframe) @@ -147,8 +144,8 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int subframe) { if (gNB->pbch_configured != 1)return; gNB->pbch_configured = 0; }*/ - nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF, AMP_OVER_2, ssb_start_symbol, nushift, cfg, fp); - nr_generate_pbch(&gNB->pbch, pbch_pdu, txdataF, AMP_OVER_2, ssb_start_symbol, nushift, sfn, n_hf, frame_mod8, cfg, fp); + nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF, AMP_OVER_2, ssb_start_symbol, cfg, fp); + nr_generate_pbch(&gNB->pbch, pbch_pdu, txdataF, AMP_OVER_2, ssb_start_symbol, n_hf, Lmax, ssb_index, frame, cfg, fp); } }