diff --git a/ci-scripts/conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf similarity index 90% rename from ci-scripts/conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf rename to ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf index 4e88f02b91..7a47d90975 100644 --- a/ci-scripts/conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf @@ -18,7 +18,8 @@ gNBs = sib1_tda = 5; min_rxtxtime = 6; - disable_harq = 1; + num_dlharq = 32; + num_ulharq = 32; servingCellConfigCommon = ( { @@ -28,11 +29,11 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 2150.43 MHz + 14 PRBs@15kHz SCS (same as initial BWP), points to Subcarrier 0 of RB#10 of SSB block - absoluteFrequencySSB = 430590; - dl_frequencyBand = 66; - # this is 2150.43 MHz - dl_absoluteFrequencyPointA = 430086; + # GSCN 6221 + absoluteFrequencySSB = 497770; + dl_frequencyBand = 254; + # this is 2486.15 MHz + dl_absoluteFrequencyPointA = 497230; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -52,9 +53,9 @@ gNBs = #uplinkConfigCommon #frequencyInfoUL - ul_frequencyBand = 66; - # this is 1750.43 MHz - ul_absoluteFrequencyPointA = 350086; + ul_frequencyBand = 254; + # this is 1612.65 MHz + ul_absoluteFrequencyPointA = 322530; #scs-SpecificCarrierList ul_offstToCarrier = 0; # subcarrierSpacing @@ -147,14 +148,15 @@ gNBs = #ext2 #ntn_Config_r17 - cellSpecificKoffset_r17 = 478; - ta-Common-r17 = 29314900; + cellSpecificKoffset_r17 = 40; + ta-Common-r17 = 4634000; # 18.87 ms + ta-CommonDrift-r17 = -230000; # -46 µs/s positionX-r17 = 0; - positionY-r17 = 0; - positionZ-r17 = 32433846; + positionY-r17 = -2166908; # -2816980.4 m + positionZ-r17 = 4910784; # 6384019.2 m velocityVX-r17 = 0; - velocityVY-r17 = 0; - velocityVZ-r17 = 0; + velocityVY-r17 = 115246; # 6914.76 m/s + velocityVZ-r17 = 50853; # 3051.18 m/s } ); @@ -196,8 +198,11 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; +# ulsch_max_frame_inactivity = 0; pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; + dl_max_mcs = 9; + ul_max_mcs = 9; } ); @@ -205,7 +210,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; - prach_dtx_threshold = 120; + prach_dtx_threshold = 150; pucch0_dtx_threshold = 150; ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } @@ -243,11 +248,28 @@ rfsimulator : { serveraddr = "server"; serverport = 4043; - options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; + options = ("chanmod"); #("saviq"); or/and "chanmod" + prop_delay = 20; IQfile = "/tmp/rfsimulator.iqs"; }; +channelmod = { + max_chan=10; + modellist="modellist_rfsimu_1"; + modellist_rfsimu_1 = ( + { + model_name = "rfsimu_channel_enB0" + type = "SAT_LEO_TRANS"; + noise_power_dB = -100; + }, + { + model_name = "rfsimu_channel_ue0" + type = "SAT_LEO_TRANS"; + noise_power_dB = -100; + } + ); +}; + security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen @@ -277,4 +299,3 @@ log_config : ngap_log_level ="debug"; f1ap_log_level ="debug"; }; - diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu0.25prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf similarity index 96% rename from targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu0.25prb.rfsim.conf rename to ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf index b206be672a..a9256ebfa1 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu0.25prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf @@ -28,11 +28,11 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # GSCN 6221 = 497770, (GSCN 6215 - 497290) + # GSCN 6221 absoluteFrequencySSB = 497770; dl_frequencyBand = 254; - # this is 2486.9 MHz - dl_absoluteFrequencyPointA = 497380; + # this is 2486.15 MHz + dl_absoluteFrequencyPointA = 497230; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -47,14 +47,14 @@ gNBs = # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 0; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPcontrolResourceSetZero = 2; initialDLBWPsearchSpaceZero = 0; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 254; - # this is 1613.4 MHz - ul_absoluteFrequencyPointA = 322680; + # this is 1612.65 MHz + ul_absoluteFrequencyPointA = 322530; #scs-SpecificCarrierList ul_offstToCarrier = 0; # subcarrierSpacing @@ -147,8 +147,8 @@ gNBs = #ext2 #ntn_Config_r17 - cellSpecificKoffset_r17 = 478; //GEO - ta-Common-r17 = 29319745; + cellSpecificKoffset_r17 = 478; + ta-Common-r17 = 58629666; # 238.74 ms positionX-r17 = 0; positionY-r17 = 0; positionZ-r17 = 32433846; @@ -196,8 +196,11 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; +# ulsch_max_frame_inactivity = 0; pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; + dl_max_mcs = 9; + ul_max_mcs = 9; } ); @@ -205,7 +208,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; - prach_dtx_threshold = 120; + prach_dtx_threshold = 150; pucch0_dtx_threshold = 150; ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } @@ -244,7 +247,7 @@ rfsimulator : serveraddr = "server"; serverport = 4043; options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; + prop_delay = 238.74; IQfile = "/tmp/rfsimulator.iqs"; }; @@ -277,4 +280,3 @@ log_config : ngap_log_level ="debug"; f1ap_log_level ="debug"; }; - diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml index 6017a69ed9..193b3a9064 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml @@ -86,7 +86,7 @@ services: cap_drop: - ALL environment: - USE_ADDITIONAL_OPTIONS: --rfsim --rfsimulator.prop_delay 238.74 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn @@ -94,7 +94,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s @@ -110,7 +110,7 @@ services: - NET_ADMIN # for interface bringup - NET_RAW # for ping environment: - USE_ADDITIONAL_OPTIONS: --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index e6a715a29a..b24b4940e5 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -221,15 +221,49 @@ Or by providing this the the command line parameters: ### gNB -The main parameter to cope with the large NTN propagation delay is the cellSpecificKoffset. -This parameter is the scheduling offset used for the timing relationships that are modified for NTN (see TS 38.213). +The main parameters to cope with the large NTN propagation delay are cellSpecificKoffset, ta-Common, ta-CommonDrift and the ephemeris data (satellite position and velocity vectors). + +The parameter `cellSpecificKoffset_r17` is the scheduling offset used for the timing relationships that are modified for NTN (see TS 38.213). The unit of the field Koffset is number of slots for a given subcarrier spacing of 15 kHz. -This parameter can be provided to the gNB in the conf file as `cellSpecificKoffset_r17` in the section `servingCellConfigCommon`. +The parameter `ta-Common-r17` is used to provide the propagation delay between the reference point (at the gNB) and the satellite. +The granularity of ta-Common is 4.072 × 10^(-3) µs. Values are given in unit of corresponding granularity. + +The parameter `ta-CommonDrift-r17` indicates the drift rate of the common TA. +The granularity of ta-CommonDrift is 0.2 × 10^(-3) µs/s. Values are given in unit of corresponding granularity. + +The satellite position and velocity vartors are provided using the following parameters: + +`positionX-r17`, `positionY-r17`, `positionZ-r17`: +X, Y, Z coordinate of satellite position state vector in ECEF. Unit is meter. +Step of 1.3 m. Actual value = field value * 1.3. + +`velocityVX-r17`, `velocityVY-r17`, `velocityVZ-r17`: +X, Y, Z coordinate of satellite velocity state vector in ECEF. Unit is meter/second. +Step of 0.06 m/s. Actual value = field value * 0.06. + +These parameters can be provided to the gNB in the conf file in the section `servingCellConfigCommon`: ``` ... - cellSpecificKoffset_r17 = 478; # GEO satellite -# cellSpecificKoffset_r17 = 40; # LEO satellite +# GEO satellite + cellSpecificKoffset_r17 = 478; + ta-Common-r17 = 58629666; # 238.74 ms + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; +# LEO satellite +# cellSpecificKoffset_r17 = 40; +# ta-Common-r17 = 4634000; # 18.87 ms +# ta-CommonDrift-r17 = -230000; # -46 µs/s +# positionX-r17 = 0; +# positionY-r17 = -2166908; # -2816980.4 m +# positionZ-r17 = 4910784; # 6384019.2 m +# velocityVX-r17 = 0; +# velocityVY-r17 = 115246; # 6914.76 m/s +# velocityVZ-r17 = 50853; # 3051.18 m/s ... ``` @@ -262,10 +296,11 @@ To enable this feature, the `disable_harq` flag has to be added to the gNB conf ... ``` -So with these modifications to the file `targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf` an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, transparent GEO satellite 5G NR NTN is this: +The settings for a transparent GEO satellite scenario are already provided in the file `ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf`. +Using this conf file, an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, transparent GEO satellite 5G NR NTN is this: ``` cd cmake_targets -sudo ./ran_build/build/nr-softmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf --rfsim --rfsimulator.prop_delay 238.74 +sudo ./ran_build/build/nr-softmodem -O ../ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf --rfsim ``` To configure NTN gNB with 32 HARQ processes in downlink and uplink, add these settings in conf files under section `gNBs.[0]` @@ -281,32 +316,43 @@ To simulate a LEO satellite channel model with rfsimulator in UL (DL is simulate @include "channelmod_rfsimu_LEO_satellite.conf" ``` -So with these modifications to the file `targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf` an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, trasparent LEO satellite 5G NR NTN is this: +The settings for a transparent LEO satellite scenario are already provided in the file `ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf`. +Using this conf file, an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, trasparent LEO satellite 5G NR NTN is this: ``` cd cmake_targets -sudo ./ran_build/build/nr-softmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf --rfsim --rfsimulator.prop_delay 20 +sudo ./ran_build/build/nr-softmodem -O ../ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf --rfsim ``` ### NR UE -At UE side, there are two main parameters to cope with the large NTN propagation delay, cellSpecificKoffset and ta-Common. -`cellSpecificKoffset` is the same as for gNB and can be provided to the UE via command line parameter `--ntn-koffset`. -`ta-Common` is a common timing advance and can be provided to the UE via command line parameter `--ntn-ta-common` in milliseconds. +At UE side, only few parameters have to be provided, as the UE receives most relevant parameters via SIB19 from the gNB. +But to calculate the UE specific TA, the UE position has to be provided in the `ue.conf` file. +Also the LEO channel model has to be configured, e.g. by using an `@include` statement, just like on the gNB side: +``` +... +position0 = { + x = 0.0; + y = 0.0; + z = 6377900.0; +} + +@include "channelmod_rfsimu_LEO_satellite.conf" +``` So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent GEO satellite 5G NR NTN is this: ``` cd cmake_targets -sudo ./ran_build/build/nr-uesoftmodem --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --rfsim --rfsimulator.prop_delay 238.74 --ntn-koffset 478 --ntn-ta-common 477.48 +sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 ``` -For LEO satellites a third parameter specifying the NTN propagation delay drift has ben added, ta-CommonDrift. -`ta-CommonDrift` provides the drift rate of the common timing advance and can be provided to the UE via command line parameter `--ntn-ta-commondrift` in microseconds per second. +For LEO satellite scenarios, the parameter `--ntn-initial-time-drift` must be provided via command line, as the UE needs this value to compensate for the time drift during initial sync, before SIB19 was received. +This parameter provides the drift rate of the complete DL timing (incl. feeder link and service link) in µs/s. Also, to perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` should be added in case of a LEO satellite scenario. So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent LEO satellite 5G NR NTN is this: ``` cd cmake_targets -sudo ./ran_build/build/nr-uesoftmodem --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/channelmod_rfsimu_LEO_satellite.conf --time-sync-I 0.2 --ntn-koffset 40 --ntn-ta-common 37.74 --ntn-ta-commondrift -50 --autonomous-ta +sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta ``` # Specific OAI modes diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 8332c2352f..a5c4f69ed5 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -491,9 +491,10 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action) openair0_timestamp writeTimestamp = proc->timestamp_tx; int writeBlockSize = rxtxD->writeBlockSize; - if ( writeBlockSize > fp->get_samples_per_slot(proc->nr_slot_tx, fp)) { - // if writeBlockSize gets longer that slot size, fill with dummy - const int dummyBlockSize = writeBlockSize - fp->get_samples_per_slot(proc->nr_slot_tx, fp); + // if writeBlockSize gets longer that slot size, fill with dummy + const int maxWriteBlockSize = fp->get_samples_per_slot(proc->nr_slot_tx, fp); + while (writeBlockSize > maxWriteBlockSize) { + const int dummyBlockSize = min(writeBlockSize - maxWriteBlockSize, maxWriteBlockSize); int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, txp, dummyBlockSize, fp->nb_antennas_tx, flags); AssertFatal(tmp == dummyBlockSize, ""); @@ -741,29 +742,32 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) } void *rxp[NB_ANTENNAS_RX]; + if (toTrash) + for (int i = 0; i < fp->nb_antennas_rx; i++) + rxp[i] = malloc16(fp->get_samples_per_slot(0, fp) * 4); for (int x = 0; x < num_frames * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; x++) { // two frames for initial sync for (int slot = 0; slot < fp->slots_per_subframe; slot++) { - for (int i = 0; i < fp->nb_antennas_rx; i++) { - if (toTrash) - rxp[i] = malloc16(fp->get_samples_per_slot(slot, fp) * 4); - else + if (!toTrash) + for (int i = 0; i < fp->nb_antennas_rx; i++) rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) + 4 * ((x * fp->samples_per_subframe) + fp->get_samples_slot_timestamp(slot, fp, 0)); - } int read_block_size = fp->get_samples_per_slot(slot, fp); int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, rxp, read_block_size, fp->nb_antennas_rx); UEscopeCopy(UE, ueTimeDomainSamplesBeforeSync, rxp[0], sizeof(c16_t), 1, read_block_size, 0); AssertFatal(read_block_size == tmp, ""); - if (IS_SOFTMODEM_RFSIM) - dummyWrite(UE, *timestamp, fp->get_samples_per_slot(slot, fp)); - if (toTrash) - for (int i = 0; i < fp->nb_antennas_rx; i++) - free(rxp[i]); + if (IS_SOFTMODEM_RFSIM) { + const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, NR_UE_CAPABILITY_SLOT_RX_TO_TX) - UE->N_TA_offset; + dummyWrite(UE, writeTimestamp, fp->get_samples_per_slot(slot, fp)); + } } } + + if (toTrash) + for (int i = 0; i < fp->nb_antennas_rx; i++) + free(rxp[i]); } static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, openair0_timestamp rx_offset) @@ -774,27 +778,18 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, opena LOG_I(PHY, "Resynchronizing RX by %ld samples\n", rx_offset); - if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { - // Resynchonize by slot (will work with numerology 1 only) - for (int size = rx_offset; size > 0; size -= fp->samples_per_subframe / 2) { - int unitTransfer = size > fp->samples_per_subframe / 2 ? fp->samples_per_subframe / 2 : size; - int tmp = - UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx); - DevAssert(unitTransfer == tmp); - } - } else { - *timestamp += fp->get_samples_per_slot(1, fp); - for (int size = rx_offset; size > 0; size -= fp->samples_per_subframe) { - int unitTransfer = size > fp->samples_per_subframe ? fp->samples_per_subframe : size; - // we write before read because gNB waits for UE to write and both executions halt - // this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot - if (IS_SOFTMODEM_RFSIM) - dummyWrite(UE, *timestamp, unitTransfer); - int res = - UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx); - DevAssert(unitTransfer == res); - *timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write + int slot = 0; + int size = rx_offset; + while (size > 0) { + const int unitTransfer = min(fp->get_samples_per_slot(slot, fp), size); + const int res = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx); + DevAssert(unitTransfer == res); + if (IS_SOFTMODEM_RFSIM) { + const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, NR_UE_CAPABILITY_SLOT_RX_TO_TX) - UE->N_TA_offset; + dummyWrite(UE, writeTimestamp, unitTransfer); } + slot = (slot + 1) % fp->slots_per_subframe; + size -= unitTransfer; } } @@ -814,6 +809,33 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) { return rem_samples + next_slot_first_symbol; } +static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, + NR_DL_FRAME_PARMS *fp, + int slot_nr, + bool *update_ntn_system_information, + int *duration_rx_to_tx, + int *timing_advance, + int *ntn_koffset) +{ + if (*update_ntn_system_information) { + *update_ntn_system_information = false; + + *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + UE->ntn_config_message->ntn_config_params.cell_specific_k_offset; + UE->timing_advance = fp->samples_per_subframe * UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms; + *timing_advance += + fp->get_samples_slot_timestamp(slot_nr, + fp, + UE->ntn_config_message->ntn_config_params.cell_specific_k_offset - *ntn_koffset); + *ntn_koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset; + + LOG_I(PHY, + "cell_specific_k_offset = %d ms, ntn_total_time_advance_ms = %f ms (%d samples)\n", + *ntn_koffset, + UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms, + UE->timing_advance); + } +} + void *UE_thread(void *arg) { //this thread should be over the processing thread to keep in real time @@ -869,7 +891,7 @@ void *UE_thread(void *arg) readFrame(UE, &tmp, true); } - double ntn_ta_common = 0; + double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift; int ntn_koffset = 0; int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX; @@ -958,8 +980,8 @@ void *UE_thread(void *arg) syncInFrame(UE, &sync_timestamp, intialSyncOffset); openair0_write_reorder_clear_context(&UE->rfdevice); if (get_nrUE_params()->time_sync_I) - // ntn_ta_commondrift is in µs/s, max_pos_acc * time_sync_I is in samples/frame - UE->max_pos_acc = mac->ntn_ta.ntn_ta_commondrift * 1e-6 * fp->samples_per_frame / get_nrUE_params()->time_sync_I; + // ntn_init_time_drift is in µs/s, max_pos_acc * time_sync_I is in samples/frame + UE->max_pos_acc = ntn_init_time_drift * 1e-6 * fp->samples_per_frame / get_nrUE_params()->time_sync_I; else UE->max_pos_acc = 0; shiftForNextFrame = -(UE->init_sync_frame + trashed_frames + 2) * UE->max_pos_acc * get_nrUE_params()->time_sync_I; // compensate for the time drift that happened during initial sync @@ -1000,16 +1022,6 @@ void *UE_thread(void *arg) absolute_slot++; TracyCFrameMark; - if (update_ntn_system_information) { - update_ntn_system_information = false; - int ta_offset = UE->frame_parms.samples_per_subframe * (UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms - ntn_ta_common); - - UE->timing_advance += ta_offset; - ntn_ta_common = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms; - ntn_koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset; - timing_advance = ntn_koffset * (UE->frame_parms.samples_per_subframe >> mac->current_UL_BWP->scs); - } - if (UE->ntn_config_message->update) { UE->ntn_config_message->update = false; update_ntn_system_information = true; @@ -1098,6 +1110,9 @@ void *UE_thread(void *arg) shiftForNextFrame = ret; pushNotifiedFIFO(&UE->dl_actors[curMsg.proc.nr_slot_rx % NUM_DL_ACTORS].fifo, newRx); + // apply new duration next run to avoid thread dead lock + apply_ntn_config(UE, fp, slot_nr, &update_ntn_system_information, &duration_rx_to_tx, &timing_advance, &ntn_koffset); + // Start TX slot processing here. It runs in parallel with RX slot processing // in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot notifiedFIFO_elt_t *newTx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), 0, 0, processSlotTX); @@ -1111,16 +1126,9 @@ void *UE_thread(void *arg) int slot = curMsgTx->proc.nr_slot_tx; int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame; - + int next_tx_slot_and_frame = absolute_slot + duration_rx_to_tx + 1; int wait_for_prev_slot = stream_status == STREAM_STATUS_SYNCED ? 1 : 0; - int next_duration_rx_to_tx = - update_ntn_system_information - ? NR_UE_CAPABILITY_SLOT_RX_TO_TX + UE->ntn_config_message->ntn_config_params.cell_specific_k_offset - : duration_rx_to_tx; - int next_nr_slot_tx = (absolute_slot + next_duration_rx_to_tx) % nb_slot_frame; - int next_frame_tx = ((absolute_slot + next_duration_rx_to_tx) / nb_slot_frame) % MAX_FRAME_NUMBER; - int next_tx_slot_and_frame = next_nr_slot_tx + next_frame_tx * UE->frame_parms.slots_per_frame + 1; dynamic_barrier_t *next_barrier = &UE->process_slot_tx_barriers[next_tx_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]; curMsgTx->next_barrier = next_barrier; dynamic_barrier_update(&UE->process_slot_tx_barriers[slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS], @@ -1129,10 +1137,6 @@ void *UE_thread(void *arg) newTx); stream_status = STREAM_STATUS_SYNCED; tx_wait_for_dlsch[slot] = 0; - // apply new duration next run to avoid thread dead lock - if (update_ntn_system_information) { - duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + UE->ntn_config_message->ntn_config_params.cell_specific_k_offset; - } } return NULL; diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 90e32d651b..f7e3b42a72 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -12,6 +12,7 @@ #define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n" #define CONFIG_HLP_TIME_SYNC_P "coefficient for Proportional part of time sync PI controller\n" #define CONFIG_HLP_TIME_SYNC_I "coefficient for Integrating part of time sync PI controller\n" +#define CONFIG_HLP_NTN_INIT_TIME_DRIFT "Initial NTN DL time drift (feeder link and service link), given in µs/s\n" #define CONFIG_HLP_AUTONOMOUS_TA "Autonomously update TA based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite)\n" #define CONFIG_HLP_AGC "Rx Gain control used for UE\n" @@ -62,6 +63,7 @@ {"num-ues", NULL, 0, .iptr=&(NB_UE_INST), .defuintval=1, TYPE_INT, 0}, \ {"time-sync-P", CONFIG_HLP_TIME_SYNC_P, 0, .dblptr=&(nrUE_params.time_sync_P), .defdblval=0.5, TYPE_DOUBLE, 0}, \ {"time-sync-I", CONFIG_HLP_TIME_SYNC_I, 0, .dblptr=&(nrUE_params.time_sync_I), .defdblval=0.0, TYPE_DOUBLE, 0}, \ + {"ntn-initial-time-drift", CONFIG_HLP_NTN_INIT_TIME_DRIFT, 0, .dblptr=&(nrUE_params.ntn_init_time_drift), .defdblval=0.0, TYPE_DOUBLE, 0}, \ {"autonomous-ta", CONFIG_HLP_AUTONOMOUS_TA, PARAMFLAG_BOOL, .iptr=&(nrUE_params.autonomous_ta), .defintval=0, TYPE_INT, 0}, \ {"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \ } @@ -85,6 +87,7 @@ typedef struct { int ssb_start_subcarrier; double time_sync_P; double time_sync_I; + double ntn_init_time_drift; int autonomous_ta; int agc; char *usrp_args; diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 730df2a495..9679caa18c 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -556,9 +556,9 @@ typedef struct { } fapi_nr_ta_command_pdu; typedef struct { - // N_common_ta_adj represents common propagation delay received in SIB19 (ms) + // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) double N_common_ta_adj; - // N_UE_TA_adj calculated propagation delay from UE and SAT (ms) + // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) double N_UE_TA_adj; // drift rate of common ta in µs/s double ntn_ta_commondrift; diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 7eba8f3467..5dc1e27f93 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -477,9 +477,11 @@ typedef struct { } nr_mac_rrc_config_mib_t; typedef struct { NR_SIB1_t *sib1; + bool can_start_ra; } nr_mac_rrc_config_sib1_t; typedef struct { NR_SIB19_r17_t *sib19; + bool can_start_ra; } nr_mac_rrc_config_other_sib_t; #endif /* RRC_MESSAGES_TYPES_H_ */ diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index be2fd03542..10af856770 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -132,6 +132,7 @@ #define GNB_CONFIG_STRING_EPHEMERIS_VELOCITY_VY "velocityVY-r17" #define GNB_CONFIG_STRING_EPHEMERIS_VELOCITY_VZ "velocityVZ-r17" #define GNB_CONFIG_STRING_TA_COMMON "ta-Common-r17" +#define GNB_CONFIG_STRING_TA_COMMONDRIFT "ta-CommonDrift-r17" #define CARRIERBANDWIDTH_OKVALUES {11,18,24,25,31,32,38,51,52,65,66,78,79,93,106,107,121,132,133,135,160,162,189,216,217,245,264,270,273} @@ -257,6 +258,7 @@ {GNB_CONFIG_STRING_EPHEMERIS_VELOCITY_VY,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVY_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_EPHEMERIS_VELOCITY_VZ,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVZ_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_TA_COMMON,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ta_Info_r17->ta_Common_r17,.defint64val=-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_TA_COMMONDRIFT,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,.defintval=-1,TYPE_INT64,0}} #define SCC_PATTERN2_STRING_CONFIG "pattern2" diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index bd34f2407c..b345277aec 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -185,6 +185,7 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17)); scc->ext2->ntn_Config_r17->ta_Info_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17)); + scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17)); scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_positionVelocity_r17; scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17 = @@ -528,7 +529,12 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) free(scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17); scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 = NULL; } + if (*scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 == 0) { + free(scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17); + scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 = NULL; + } if (scc->ext2->ntn_Config_r17->ta_Info_r17->ta_Common_r17 == -1) { + free(scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17); free(scc->ext2->ntn_Config_r17->ta_Info_r17); scc->ext2->ntn_Config_r17->ta_Info_r17 = NULL; } diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 60da9e6800..79f6aadf64 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -222,7 +222,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo } -// computes delay between ue and sat based on SIB19 ephemeris data +// computes round-trip-time between ue and sat based on SIB19 ephemeris data static double calculate_ue_sat_ta(const position_t *position_params, NR_PositionVelocity_r17_t *sat_pos) { // get UE position coordinates @@ -235,9 +235,8 @@ static double calculate_ue_sat_ta(const position_t *position_params, NR_Position double posy_0 = (double)sat_pos->positionY_r17 * 1.3; double posz_0 = (double)sat_pos->positionZ_r17 * 1.3; - double distance = sqrt(pow(posx - posx_0, 2) + pow(posy - posy_0, 2) + pow(posz - posz_0, 2)); - // this computation will ensure 3 decimal precision - double ta_ms = round(((distance / SPEED_OF_LIGHT) * 1000) * 1000.0) / 1000.0; + double distance = 2 * sqrt(pow(posx - posx_0, 2) + pow(posy - posy_0, 2) + pow(posz - posz_0, 2)); + double ta_ms = (distance / SPEED_OF_LIGHT) * 1000; return ta_ms; } @@ -1665,7 +1664,7 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t case T300_EXPIRY: reset_ra(mac, false); reset_mac_inst(mac); - mac->state = UE_SYNC; // still in sync but need to restart RA + mac->state = UE_PERFORMING_RA; // still in sync but need to restart RA break; case RE_ESTABLISHMENT: reset_mac_inst(mac); @@ -1730,7 +1729,7 @@ static void configure_si_schedulingInfo(NR_UE_MAC_INST_t *mac, } } -void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1) +void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); int ret = pthread_mutex_lock(&mac->if_mutex); @@ -1766,6 +1765,8 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si AssertFatal(mac->current_UL_BWP, "Couldn't find DL-BWP0\n"); configure_timeAlignmentTimer(&mac->time_alignment_timer, mac->timeAlignmentTimerCommon, mac->current_UL_BWP->scs); } + if (mac->state == UE_RECEIVING_SIB && can_start_ra) + mac->state = UE_PERFORMING_RA; // Setup the SSB to Rach Occasions mapping according to the config build_ssb_to_ro_map(mac); @@ -1776,7 +1777,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si AssertFatal(!ret, "mutex failed %d\n", ret); } -void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19) +void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, bool can_start_ra) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); int ret = pthread_mutex_lock(&mac->if_mutex); @@ -1789,6 +1790,8 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19) configure_ntn_ta(mac->ue_id, &mac->ntn_ta, ntn_Config_r17); } + if (mac->state == UE_RECEIVING_SIB && can_start_ra) + mac->state = UE_PERFORMING_RA; ret = pthread_mutex_unlock(&mac->if_mutex); AssertFatal(!ret, "mutex failed %d\n", ret); } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 7910fd2327..2ba5f992d4 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -165,7 +165,7 @@ // Define the UE L2 states with X-Macro #define NR_UE_L2_STATES \ UE_STATE(UE_NOT_SYNC) \ - UE_STATE(UE_SYNC) \ + UE_STATE(UE_RECEIVING_SIB) \ UE_STATE(UE_PERFORMING_RA) \ UE_STATE(UE_CONNECTED) \ UE_STATE(UE_DETACHING) @@ -554,9 +554,9 @@ typedef struct { } si_schedInfo_t; typedef struct ntn_timing_advance_components { - // N_common_ta_adj represents common propagation delay received in SIB19 (ms) + // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) double N_common_ta_adj; - // N_UE_TA_adj calculated propagation delay from UE and SAT (ms) + // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) double N_UE_TA_adj; // drift rate of common ta in µs/s double ntn_ta_commondrift; @@ -682,7 +682,7 @@ static inline int GET_NTN_UE_K_OFFSET(const ntn_timing_advance_componets_t *ntn_ static inline double GET_COMPLETE_TIME_ADVANCE_MS(const ntn_timing_advance_componets_t *ntn_ta) { - return (ntn_ta->N_common_ta_adj + ntn_ta->N_UE_TA_adj) * 2; + return ntn_ta->N_common_ta_adj + ntn_ta->N_UE_TA_adj; } static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *ntn_ta) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index b310bd4590..c2e8fd5885 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -85,10 +85,10 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, NR_MIB_t *mibP, int sched_sib1); -void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1); +void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra); struct position; /* forward declaration */ -void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17); +void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17, bool can_start_ra); void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index c5727acab8..b3174e3bd3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1038,7 +1038,7 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac) { LOG_W(NR_MAC, "Triggering new RA procedure for UE with RNTI %x\n", mac->crnti); - mac->state = UE_SYNC; + mac->state = UE_PERFORMING_RA; reset_ra(mac, false); mac->ra.msg3_C_RNTI = true; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 3533c04a12..1a59a89aed 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -223,10 +223,14 @@ void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id) if (mac->first_sync_frame == -1) mac->first_sync_frame = frame; - if(get_softmodem_params()->phy_test) + if (get_softmodem_params()->phy_test) mac->state = UE_CONNECTED; - else if(mac->state == UE_NOT_SYNC) - mac->state = UE_SYNC; + else if (mac->state == UE_NOT_SYNC) { + if (IS_SA_MODE(get_softmodem_params())) + mac->state = UE_RECEIVING_SIB; + else + mac->state = UE_PERFORMING_RA; + } } static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 37224a6dfd..e3407c95b3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1558,7 +1558,7 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) uint32_t gNB_index = ul_info->gNB_index; RA_config_t *ra = &mac->ra; - if(mac->state > UE_NOT_SYNC && mac->state < UE_CONNECTED) { + if (mac->state == UE_PERFORMING_RA) { nr_ue_get_rach(mac, cc_id, frame_tx, gNB_index, slot_tx); nr_ue_prach_scheduler(mac, frame_tx, slot_tx); } @@ -3605,9 +3605,10 @@ static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, { fapi_nr_dl_ntn_config_command_pdu *ntn_config_command_pdu = &dl_config->dl_config_list[dl_config->number_pdus].ntn_config_command_pdu; ntn_config_command_pdu->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset; + ntn_config_command_pdu->ntn_ta_commondrift = mac->ntn_ta.ntn_ta_commondrift; ntn_config_command_pdu->N_common_ta_adj = mac->ntn_ta.N_common_ta_adj; ntn_config_command_pdu->N_UE_TA_adj = mac->ntn_ta.N_UE_TA_adj; - ntn_config_command_pdu->ntn_total_time_advance_ms = (mac->ntn_ta.N_common_ta_adj + mac->ntn_ta.N_UE_TA_adj) * 2; + ntn_config_command_pdu->ntn_total_time_advance_ms = mac->ntn_ta.N_common_ta_adj + mac->ntn_ta.N_UE_TA_adj; dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_NTN_CONFIG_PARAMS; dl_config->number_pdus += 1; } diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index f512c7e6a7..f6dead1213 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -2349,6 +2349,19 @@ static long get_NR_UE_TimersAndConstants_t319(const nr_mac_timers_t *timer_confi } } +static bool is_ntn_band(int band) +{ + // TS 3GPP 38.101-5 V1807 Section 5.2.2 + if (band >= 254 && band <= 256) // FR1 NTN + return true; + + // TS 3GPP 38.101-5 V1807 Section 5.2.3 + if (band >= 510 && band <= 512) // FR2 NTN + return true; + + return false; +} + NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const f1ap_plmn_t *plmn, uint64_t cellID, @@ -2447,12 +2460,26 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, asn1cSeqAdd(&sib1->si_SchedulingInfo->schedulingInfoList.list,schedulingInfo);*/ - // sib19 scheduling info - // ensure ntn-config is initialized - if (scc->ext2 && scc->ext2->ntn_Config_r17) { + const NR_FreqBandIndicatorNR_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + if (is_ntn_band(band)) { sib1->nonCriticalExtension = CALLOC(1, sizeof(struct NR_SIB1_v1610_IEs)); sib1->nonCriticalExtension->nonCriticalExtension = CALLOC(1, sizeof(struct NR_SIB1_v1630_IEs)); sib1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension = CALLOC(1, sizeof(struct NR_SIB1_v1700_IEs)); + // If cell provides NTN access, set cellBarredNTN to notBarred. + struct NR_SIB1_v1700_IEs *sib1_v1700 = sib1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension; + sib1_v1700->cellBarredNTN_r17 = CALLOC(1, sizeof(long)); + *sib1_v1700->cellBarredNTN_r17 = NR_SIB1_v1700_IEs__cellBarredNTN_r17_notBarred; + } + + // sib19 scheduling info + // ensure ntn-config is initialized + if (scc->ext2 && scc->ext2->ntn_Config_r17) { + if (sib1->nonCriticalExtension == NULL) + sib1->nonCriticalExtension = CALLOC(1, sizeof(struct NR_SIB1_v1610_IEs)); + if (sib1->nonCriticalExtension->nonCriticalExtension == NULL) + sib1->nonCriticalExtension->nonCriticalExtension = CALLOC(1, sizeof(struct NR_SIB1_v1630_IEs)); + if (sib1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension == NULL) + sib1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension = CALLOC(1, sizeof(struct NR_SIB1_v1700_IEs)); struct NR_SI_SchedulingInfo_v1700 *sib_v17_scheduling_info = CALLOC(1, sizeof(struct NR_SI_SchedulingInfo_v1700)); @@ -2484,7 +2511,6 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, frequencyInfoDL->frequencyBandList.list.array[i]; } - const NR_FreqBandIndicatorNR_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; frequency_range_t frequency_range = band > 256 ? FR2 : FR1; sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA = get_ssb_offset_to_pointA(*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB, scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index cc97b448b5..b6aa5f0463 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -138,12 +138,14 @@ void process_msg_rcc_to_mac(MessageDef *msg) break; case NR_MAC_RRC_CONFIG_SIB1: { NR_SIB1_t *sib1 = NR_MAC_RRC_CONFIG_SIB1(msg).sib1; - nr_rrc_mac_config_req_sib1(ue_id, 0, sib1); + bool can_start_ra = NR_MAC_RRC_CONFIG_SIB1(msg).can_start_ra; + nr_rrc_mac_config_req_sib1(ue_id, 0, sib1, can_start_ra); SEQUENCE_free(&asn_DEF_NR_SIB1, NR_MAC_RRC_CONFIG_SIB1(msg).sib1, ASFM_FREE_EVERYTHING); } break; - case NR_MAC_RRC_CONFIG_OTHER_SIB: - nr_rrc_mac_config_other_sib(ue_id, NR_MAC_RRC_CONFIG_OTHER_SIB(msg).sib19); - break; + case NR_MAC_RRC_CONFIG_OTHER_SIB: { + bool can_start_ra = NR_MAC_RRC_CONFIG_OTHER_SIB(msg).can_start_ra; + nr_rrc_mac_config_other_sib(ue_id, NR_MAC_RRC_CONFIG_OTHER_SIB(msg).sib19, can_start_ra); + } break; default: LOG_E(NR_MAC, "Unexpected msg from RRC: %d\n", ITTI_MSG_ID(msg)); } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 3fbe3663f0..85adc82328 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -165,8 +165,9 @@ static void set_DRB_status(NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id, NR_R rrc->status_DRBs[drb_id - 1] = status; } -static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, instance_t ue_id) +static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc) { + instance_t ue_id = rrc->ue_id; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN); // Dump contents @@ -253,6 +254,7 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, if (sib19) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_OTHER_SIB); asn_copy(&asn_DEF_NR_SIB19_r17, (void **)&NR_MAC_RRC_CONFIG_OTHER_SIB(msg).sib19, sib19); + NR_MAC_RRC_CONFIG_OTHER_SIB(msg).can_start_ra = rrc->is_NTN_UE; itti_send_msg_to_task(TASK_MAC_UE, ue_id, msg); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_OUT); @@ -308,6 +310,22 @@ static void nr_rrc_configure_default_SI(NR_UE_RRC_SI_INFO *SI_info, } } +static bool verify_NTN_access(const NR_UE_RRC_SI_INFO *SI_info, const NR_SIB1_v1700_IEs_t *sib1_v1700) +{ + // SIB1 indicates if NTN access is present in the cell + bool ntn_access = false; + if (sib1_v1700 && sib1_v1700->cellBarredNTN_r17 + && *sib1_v1700->cellBarredNTN_r17 == NR_SIB1_v1700_IEs__cellBarredNTN_r17_notBarred) + ntn_access = true; + + uint32_t sib19_mask = 1 << NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19; + int sib19_present = SI_info->SInfo_r17.default_otherSI_map_r17 & sib19_mask; + + AssertFatal(!ntn_access || sib19_present, "NTN cell, but SIB19 not configured.\n"); + + return ntn_access && sib19_present; +} + static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_info, NR_SIB1_t *sib1) { if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) @@ -321,21 +339,26 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf nr_rrc_ue_prepare_RRCSetupRequest(rrc); } + NR_SIB1_v1700_IEs_t *sib1_v1700 = NULL; NR_SI_SchedulingInfo_v1700_t *si_SchedInfo_v1700 = NULL; if (sib1->nonCriticalExtension && sib1->nonCriticalExtension->nonCriticalExtension && sib1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension) { - si_SchedInfo_v1700 = sib1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->si_SchedulingInfo_v1700; + sib1_v1700 = sib1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension; + si_SchedInfo_v1700 = sib1_v1700->si_SchedulingInfo_v1700; } // configure default SI nr_rrc_configure_default_SI(SI_info, sib1->si_SchedulingInfo, si_SchedInfo_v1700); + rrc->is_NTN_UE = verify_NTN_access(SI_info, sib1_v1700); + // configure timers and constant nr_rrc_set_sib1_timers_and_constants(&rrc->timers_and_constants, sib1); // RRC storage of SIB1 timers and constants (eg needed in re-establishment) UPDATE_IE(rrc->timers_and_constants.sib1_TimersAndConstants, sib1->ue_TimersAndConstants, NR_UE_TimersAndConstants_t); MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_SIB1); NR_MAC_RRC_CONFIG_SIB1(msg).sib1 = sib1; + NR_MAC_RRC_CONFIG_SIB1(msg).can_start_ra = !rrc->is_NTN_UE; itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); } @@ -396,7 +419,7 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe SEQUENCE_free(&asn_DEF_NR_SystemInformation, si, 1); } else { LOG_I(NR_RRC, "[UE %ld] Decoding dedicatedSystemInformationDelivery\n", rrc->ue_id); - nr_decode_SI(SI_info, si, rrc->ue_id); + nr_decode_SI(SI_info, si, rrc); } } if (rec_1530->otherConfig) { @@ -958,7 +981,7 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: LOG_I(NR_RRC, "[UE %ld] Decoding SI\n", rrc->ue_id); NR_SystemInformation_t *si = bcch_message->message.choice.c1->choice.systemInformation; - nr_decode_SI(SI_info, si, rrc->ue_id); + nr_decode_SI(SI_info, si, rrc); break; case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: default: diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index fb320853e2..29c03afd5f 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -241,6 +241,8 @@ typedef struct NR_UE_RRC_INST_s { bool reconfig_after_reestab; //Sidelink params NR_SL_PreconfigurationNR_r16_t *sl_preconfig; + // NTN params + bool is_NTN_UE; } NR_UE_RRC_INST_t; #endif diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c index 91ad8b070d..cb8e75abdf 100644 --- a/radio/rfsimulator/apply_channelmod.c +++ b/radio/rfsimulator/apply_channelmod.c @@ -56,7 +56,7 @@ void rxAddInput(const c16_t *input_sig, - The ground station is located at the North Pole (positive Zaxis), and the satellite starts from the initial elevation angle 0° in the second quadrant of the YZplane. - Satellite moves in the clockwise direction in its circular orbit. */ - const double radius_earth = 6371e3; // m + const double radius_earth = 6377900; // m const double radius_sat = radius_earth + channelDesc->sat_height; const double GM_earth = 3.986e14; // m^3/s^2 const double w_sat = sqrt(GM_earth / (radius_sat * radius_sat * radius_sat)); // rad/s diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf index 60489ea6c2..67be3dbb44 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf @@ -148,7 +148,7 @@ gNBs = #ext2 #ntn_Config_r17 cellSpecificKoffset_r17 = 478; //GEO - ta-Common-r17 = 29319745; + ta-Common-r17 = 58629666; # 238.74 ms positionX-r17 = 0; positionY-r17 = 0; positionZ-r17 = 32433846; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf index edcee7ee98..5a14f4fae6 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf @@ -147,7 +147,7 @@ gNBs = #ext2 #ntn_Config_r17 cellSpecificKoffset_r17 = 478; //GEO - ta-Common-r17 = 29319745; + ta-Common-r17 = 58629666; # 238.74 ms positionX-r17 = 0; positionY-r17 = 0; positionZ-r17 = 32433846; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf index 67f8eb6e85..c4213eb0d3 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf @@ -147,7 +147,7 @@ gNBs = #ext2 #ntn_Config_r17 cellSpecificKoffset_r17 = 478; //GEO - ta-Common-r17 = 29319745; + ta-Common-r17 = 58629666; # 238.74 ms positionX-r17 = 0; positionY-r17 = 0; positionZ-r17 = 32433846; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf index 144e7d042b..013ca6663b 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf @@ -35,6 +35,8 @@ gNBs = sib1_tda = 5; min_rxtxtime = 6; # disable_harq = 1; +# num_dlharq = 32; +# num_ulharq = 32; servingCellConfigCommon = ( { @@ -163,8 +165,25 @@ gNBs = #ext2 #ntn_Config_r17 -# cellSpecificKoffset_r17 = 478; # GEO satellite -# cellSpecificKoffset_r17 = 40; # LEO satellite +# GEO satellite +# cellSpecificKoffset_r17 = 478; +# ta-Common-r17 = 58629666; # 238.74 ms +# positionX-r17 = 0; +# positionY-r17 = 0; +# positionZ-r17 = 32433846; +# velocityVX-r17 = 0; +# velocityVY-r17 = 0; +# velocityVZ-r17 = 0; +# LEO satellite +# cellSpecificKoffset_r17 = 40; +# ta-Common-r17 = 4634000; # 18.87 ms +# ta-CommonDrift-r17 = -230000; # -46 µs/s +# positionX-r17 = 0; +# positionY-r17 = -2166908; # -2816980.4 m +# positionZ-r17 = 4910784; # 6384019.2 m +# velocityVX-r17 = 0; +# velocityVY-r17 = 115246; # 6914.76 m/s +# velocityVZ-r17 = 50853; # 3051.18 m/s } ); @@ -208,6 +227,8 @@ MACRLCs = ( tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; +# dl_max_mcs = 9; +# ul_max_mcs = 9; } ); @@ -215,7 +236,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; - prach_dtx_threshold = 120; + prach_dtx_threshold = 150; pucch0_dtx_threshold = 150; ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf index fdb60c73fb..c9dfd6c58a 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf @@ -35,6 +35,8 @@ gNBs = sib1_tda = 5; min_rxtxtime = 6; # disable_harq = 1; +# num_dlharq = 32; +# num_ulharq = 32; servingCellConfigCommon = ( { @@ -163,15 +165,25 @@ gNBs = #ext2 #ntn_Config_r17 -# cellSpecificKoffset_r17 = 478; # GEO satellite -# cellSpecificKoffset_r17 = 40; # LEO satellite -# ta-Common-r17 = 29314900; +# GEO satellite +# cellSpecificKoffset_r17 = 478; +# ta-Common-r17 = 58629666; # 238.74 ms # positionX-r17 = 0; # positionY-r17 = 0; # positionZ-r17 = 32433846; # velocityVX-r17 = 0; # velocityVY-r17 = 0; # velocityVZ-r17 = 0; +# LEO satellite +# cellSpecificKoffset_r17 = 40; +# ta-Common-r17 = 4634000; # 18.87 ms +# ta-CommonDrift-r17 = -230000; # -46 µs/s +# positionX-r17 = 0; +# positionY-r17 = -2166908; # -2816980.4 m +# positionZ-r17 = 4910784; # 6384019.2 m +# velocityVX-r17 = 0; +# velocityVY-r17 = 115246; # 6914.76 m/s +# velocityVZ-r17 = 50853; # 3051.18 m/s } ); @@ -215,6 +227,8 @@ MACRLCs = ( tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; +# dl_max_mcs = 9; +# ul_max_mcs = 9; } ); @@ -222,7 +236,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; - prach_dtx_threshold = 120; + prach_dtx_threshold = 150; pucch0_dtx_threshold = 150; ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf index 115104e8f1..4cea93ea46 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf @@ -11,4 +11,6 @@ position0 = { x = 0.0; y = 0.0; z = 6377900.0; -} \ No newline at end of file +} + +@include "channelmod_rfsimu_LEO_satellite.conf"