From 69f391f2b84aafaf66f4eb5ddebf5947a20b36df Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Thu, 15 May 2025 17:08:59 +0200 Subject: [PATCH 1/2] Fix for the ULDLduplex issue for NTN bands Duplex is assumed to be static but for NTN bands, it is not static. TxRX Duplex is defined in section 5.4.4 of 38.101-5 (for NTN) specs v1809 n256 190 MHz, 165 to 215 MHz n255 -101.5 MHz, -72.5 to -130.5 MHz n254 862 - 885 MHz --- common/utils/nr/nr_common.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 8e6a16c97d..c3d0c881b3 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -459,10 +459,36 @@ bool compare_relative_ul_channel_bw(int nr_band, int scs, int channel_bandwidth, return rel_bw > limit; } +static bool check_delta_duplex(int index, uint64_t dlfreq_khz, uint64_t ulfreq_khz) +{ + int uldl_min_offset = nr_bandtable[index].dl_min - nr_bandtable[index].ul_min; + int txrx_offset = dlfreq_khz - ulfreq_khz; + LOG_I(NR_PHY, "dlfreq:%ld ulfreq:%ld deltaduplex:%d khz, uldl_min_offset:%d khz\n", + dlfreq_khz, ulfreq_khz, txrx_offset, uldl_min_offset); + if (txrx_offset == uldl_min_offset) + return true; + + int band = nr_bandtable[index].band; + + // TBD.. Delta duplex is also a range for these bands n26, n91-n94, n109. + // TBD .. Add the checks later + + // Refer to section 5.4.4 in spec 38.101-5 + if (band == 256 && txrx_offset >= 165000 && txrx_offset <= 215000) + return true; + if (band == 255 && txrx_offset >= -130500 && txrx_offset <= -72500) + return true; + if (band == 254 && txrx_offset >= 862000 && txrx_offset <= 885000) + return true; + + return false; +} + uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) { const int64_t dl_freq_khz = downlink_frequency / 1000; const int32_t delta_duplex_khz = delta_duplex / 1000; + const int64_t ul_freq_khz = dl_freq_khz + delta_duplex_khz; uint64_t center_freq_diff_khz = UINT64_MAX; // 2^64 uint16_t current_band = 0; @@ -472,9 +498,10 @@ uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max) continue; - int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min; + if (ul_freq_khz < nr_bandtable[ind].ul_min || ul_freq_khz > nr_bandtable[ind].ul_max) + continue; - if (current_offset_khz != delta_duplex_khz) + if (!check_delta_duplex(ind, dl_freq_khz, ul_freq_khz)) continue; int64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2; From 40fae6136c2a3dca84dd1705b03f798c26541c12 Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Thu, 30 Oct 2025 16:37:39 +0100 Subject: [PATCH 2/2] Added the check for non-NTN bands --- common/utils/nr/nr_common.c | 33 ++++++++++++++++++++------------- common/utils/nr/nr_common.h | 2 +- openair1/PHY/INIT/nr_init.c | 2 +- openair1/PHY/INIT/nr_parms.c | 20 +++++--------------- 4 files changed, 27 insertions(+), 30 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index c3d0c881b3..53fc42837b 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -459,7 +459,7 @@ bool compare_relative_ul_channel_bw(int nr_band, int scs, int channel_bandwidth, return rel_bw > limit; } -static bool check_delta_duplex(int index, uint64_t dlfreq_khz, uint64_t ulfreq_khz) +static bool check_delta_duplex(int index, uint64_t dlfreq_khz, uint64_t ulfreq_khz, int64_t dlbw, int64_t ulbw) { int uldl_min_offset = nr_bandtable[index].dl_min - nr_bandtable[index].ul_min; int txrx_offset = dlfreq_khz - ulfreq_khz; @@ -470,9 +470,6 @@ static bool check_delta_duplex(int index, uint64_t dlfreq_khz, uint64_t ulfreq_k int band = nr_bandtable[index].band; - // TBD.. Delta duplex is also a range for these bands n26, n91-n94, n109. - // TBD .. Add the checks later - // Refer to section 5.4.4 in spec 38.101-5 if (band == 256 && txrx_offset >= 165000 && txrx_offset <= 215000) return true; @@ -481,16 +478,31 @@ static bool check_delta_duplex(int index, uint64_t dlfreq_khz, uint64_t ulfreq_k if (band == 254 && txrx_offset >= 862000 && txrx_offset <= 885000) return true; + // Refer to section 5.4.4 in spec 38.101-1 for these bands 24, 91-94, 109 + if (band == 24 && (txrx_offset == -101500 || txrx_offset == -120500)) + return true; + //Delta duplex is also a range for these bands n91-n94, n109. + if ((band >= 91 && band <= 94) || band == 109) { + dlbw = ((dlbw / 1000) + 1) * 1000; + ulbw = ((ulbw / 1000) + 1) * 1000; + int lower_limit = nr_bandtable[index].dl_min - nr_bandtable[index].ul_max + ((dlbw + ulbw) >> 1); + int upper_limit = nr_bandtable[index].dl_max - nr_bandtable[index].ul_min - ((dlbw + ulbw) >> 1); + LOG_I(NR_PHY, "Band %d dlbw:%ld Khz, ulbw: %ld Khz RXTX lower limit:%d khz, upper limit:%d khz\n", + band, dlbw, ulbw, lower_limit, upper_limit); + + if (txrx_offset >= lower_limit && txrx_offset <= upper_limit) + return true; + } + return false; } -uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex, int64_t dlbw, int64_t ulbw) { const int64_t dl_freq_khz = downlink_frequency / 1000; const int32_t delta_duplex_khz = delta_duplex / 1000; const int64_t ul_freq_khz = dl_freq_khz + delta_duplex_khz; - uint64_t center_freq_diff_khz = UINT64_MAX; // 2^64 uint16_t current_band = 0; for (int ind = 0; ind < sizeofArray(nr_bandtable); ind++) { @@ -501,15 +513,10 @@ uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) if (ul_freq_khz < nr_bandtable[ind].ul_min || ul_freq_khz > nr_bandtable[ind].ul_max) continue; - if (!check_delta_duplex(ind, dl_freq_khz, ul_freq_khz)) + if (!check_delta_duplex(ind, dl_freq_khz, ul_freq_khz, dlbw, ulbw)) continue; - int64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2; - - if (labs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ - current_band = nr_bandtable[ind].band; - center_freq_diff_khz = labs(dl_freq_khz - center_frequency_khz); - } + current_band = nr_bandtable[ind].band; } printf("DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n", diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index e0d68a45ad..2e796bac23 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -285,7 +285,7 @@ int get_coreset_num_cces(uint8_t *FreqDomainResource, int duration); int get_nr_table_idx(int nr_bandP, uint8_t scs_index); int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index); frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index); -uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex); +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex, int64_t dlbw, int64_t ulbw); int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize); diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 778903be91..edf9a5c6ee 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -375,7 +375,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ; int32_t dlul_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; - fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset); + fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset, dl_bw_khz, ul_bw_khz); LOG_I(PHY, "DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, dlul_offset); diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 2ace21eab5..cc31dc173a 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -379,15 +379,13 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->N_RB_SL = config->carrier_config.sl_grid_size[fp->numerology_index]; fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index); - int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index); + int64_t uplink_frequency_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; uplink_frequency_offset *= 1000; - LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset); + LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %ld Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset); AssertFatal(fp->frame_type==config->cell_config.frame_duplex_type, "Invalid duplex type (frame_type %d,cell_config.frame_duplex_type %d) in config request file for band %d\n", fp->frame_type,config->cell_config.frame_duplex_type,fp->nr_band); - AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset), "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + uplink_frequency_offset); - LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",fp->numerology_index, fp->N_RB_DL, Ncp); @@ -508,7 +506,7 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, fp->ofdm_offset_divisor = ofdm_offset_divisor; fp->threequarter_fs = threequarter_fs; - fp->nr_band = get_band(config->sl_carrier_config.sl_frequency, 0); + fp->nr_band = get_band(config->sl_carrier_config.sl_frequency, 0, 0, 0); fp->att_rx = 0; fp->att_tx = 0; @@ -522,8 +520,6 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, fp->Ncp = config->sl_bwp_config.sl_cyclic_prefix; fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index); - int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index); - uplink_frequency_offset *= 1000; uint64_t bw_khz = (12 * config->sl_carrier_config.sl_grid_size) * (15 << config->sl_bwp_config.sl_scs); // REfer to section 3GPP spec 38.101 5.4E.2.1 @@ -539,20 +535,14 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, LOG_D(PHY, "CarrierFreq %lu Hz\n", fp->sl_CarrierFreq); LOG_I(PHY, - "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz SL frequency %lu Hz: band %d, uldl offset %d Hz\n", + "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz SL frequency %lu Hz: band %d\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->sl_CarrierFreq, - fp->nr_band, - uplink_frequency_offset); + fp->nr_band); AssertFatal(fp->frame_type == TDD, "Sidelink bands only support TDD"); - AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset), - "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", - fp->nr_band, - fp->ul_CarrierFreq, - fp->dl_CarrierFreq + uplink_frequency_offset); LOG_I(PHY, "Initializing frame parms for mu %d, N_RB %d, Ncp %d\n", fp->numerology_index, fp->N_RB_DL, fp->Ncp);