diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 544b550944..a3e0dcd580 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1298,6 +1298,47 @@ uint8_t get_long_prach_dur(unsigned int format, unsigned int mu) return (prach_dur_subframes * num_slots_subframe); } +// Table 38.211 6.3.3.2-1 +uint8_t get_PRACH_k_bar(unsigned int delta_f_RA_PRACH, unsigned int delta_f_PUSCH) +{ + uint8_t k_bar = 0; + if (delta_f_RA_PRACH > 3) { // Rel 15 max PRACH SCS is 120 kHz, 4 and 5 are 1.25 and 5 kHz + // long formats + DevAssert(delta_f_PUSCH < 3); + DevAssert(delta_f_RA_PRACH < 6); + const uint8_t k_bar_table[3][2] = {{7, 12}, + {1, 10}, + {133, 7}}; + + k_bar = k_bar_table[delta_f_PUSCH][delta_f_RA_PRACH - 4]; + } else { + if (delta_f_RA_PRACH == 3 && delta_f_PUSCH == 4) // \delta f_RA == 120 kHz AND \delta f == 480 kHz + k_bar = 1; + else if (delta_f_RA_PRACH == 3 && delta_f_PUSCH == 5) // \delta f_RA == 120 kHz AND \delta f == 960 kHz + k_bar = 23; + else + k_bar = 2; + } + return k_bar; +} + +// K according to 38.211 5.3.2 +unsigned int get_prach_K(int prach_sequence_length, int prach_fmt_id, int pusch_mu, int prach_mu) +{ + unsigned int K = 1; + if (prach_sequence_length == 0) { + if (prach_fmt_id == 3) + K = (15 << pusch_mu) / 5; + else + K = (15 << pusch_mu) / 1.25; + } else if (prach_sequence_length == 1) { + K = (15 << pusch_mu) / (15 << prach_mu); + } else { + AssertFatal(0, "Invalid PRACH sequence length %d\n", prach_sequence_length); + } + return K; +} + int get_delay_idx(int delay, int max_delay_comp) { int delay_idx = max_delay_comp + delay; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 37fcd6e010..5d5c6a363c 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -288,6 +288,8 @@ int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_ unsigned short get_m_srs(int c_srs, int b_srs); unsigned short get_N_b_srs(int c_srs, int b_srs); uint8_t get_long_prach_dur(unsigned int format, unsigned int num_slots_subframe); +uint8_t get_PRACH_k_bar(unsigned int delta_f_RA_PRACH, unsigned int delta_f_PUSCH); +unsigned int get_prach_K(int prach_sequence_length, int prach_fmt_id, int pusch_mu, int prach_mu); int get_slot_idx_in_period(const int slot, const frame_structure_t *fs); diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 5b890e95ac..858257893f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -165,6 +165,7 @@ void rx_nr_prach_ru(RU_t *ru, int16_t *prach[ru->nb_rx]; int prach_sequence_length = ru->config.prach_config.prach_sequence_length.value; int msg1_frequencystart = ru->config.prach_config.num_prach_fd_occasions_list[numRA].k1.value; + const uint8_t prach_mu = ru->config.prach_config.prach_sub_c_spacing.value; int sample_offset_slot; if (prachStartSymbol == 0) { @@ -391,18 +392,9 @@ void rx_nr_prach_ru(RU_t *ru, LOG_D(PHY, "rx_prach: Doing PRACH FFT for nb_rx:%d Ncp:%d dftlen:%d\n", ru->nb_rx, Ncp, dftlen); } - // Note: Assumes PUSCH SCS @ 30 kHz, take values for formats 0-2 and adjust for others below - int kbar = 1; - int K = 24; - if (prach_sequence_length == 0 && prachFormat == 3) { - K=4; - kbar=10; - } - else if (prach_sequence_length == 1) { - // Note: Assumes that PRACH SCS is same as PUSCH SCS - K=1; - kbar=2; - } + const unsigned int K = get_prach_K(prach_sequence_length, prachFormat, fp->numerology_index, prach_mu); + const uint8_t kbar = get_PRACH_k_bar(prach_mu, fp->numerology_index); + int n_ra_prb = msg1_frequencystart; int k = (12*n_ra_prb) - 6*fp->N_RB_UL; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index bd140ed8ff..c2953dd196 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -66,7 +66,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t c16_t prachF_tmp[(4688 + 4 * 24576) * 4] __attribute__((aligned(32))) = {0}; int Ncp = 0; - int prach_start, prach_sequence_length, prach_len, dftlen, mu, kbar, K, n_ra_prb, k, prachStartSymbol, sample_offset_slot; + int prach_start, prach_sequence_length, prach_len, dftlen, mu, n_ra_prb, k, prachStartSymbol, sample_offset_slot; fd_occasion = 0; prach_len = 0; @@ -83,9 +83,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t n_ra_prb = nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].k1,//prach_pdu->freq_msg1; NCS = prach_pdu->num_cs; prach_fmt_id = prach_pdu->prach_format; - preamble_index = prach_pdu->ra_PreambleIndex; - kbar = 1; - K = 24; + preamble_index = prach_pdu->ra_PreambleIndex; k = 12*n_ra_prb - 6*fp->N_RB_UL; prachStartSymbol = prach_pdu->prach_start_symbol; @@ -214,15 +212,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t // nsymb = (frame_parms->Ncp==0) ? 14:12; // subframe_offset = (unsigned int)frame_parms->ofdm_symbol_size*slot*nsymb; - if (prach_sequence_length == 0 && prach_fmt_id == 3) { - K = 4; - kbar = 10; - } else if (prach_sequence_length == 1) { - K = 1; - kbar = 2; - } + const unsigned int K = get_prach_K(prach_sequence_length, prach_fmt_id, fp->numerology_index, mu); + const uint8_t kbar = get_PRACH_k_bar(mu, fp->numerology_index); - if (k<0) + if (k < 0) k += fp->ofdm_symbol_size; k *= K; @@ -265,7 +258,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t break; default: - AssertFatal(1==0, "Illegal PRACH format %d for sequence length 839\n", prach_fmt_id); + AssertFatal(1 == 0, "Illegal PRACH format %d for sequence length 839\n", prach_fmt_id); break; } } else { diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 03245be78a..ce00f6ae9e 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -562,6 +562,7 @@ int main(int argc, char **argv){ prach_config->num_prach_fd_occasions_list[fd_occasion].k1.value = msg1_frequencystart; prach_config->restricted_set_config.value = restrictedSetConfig; prach_config->prach_sequence_length.value = prach_sequence_length; + prach_config->prach_sub_c_spacing.value = mu; prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs)); prach_pdu->prach_format = prach_format;