Merge remote-tracking branch 'origin/nr_ue_sib19_ta' into integration_2025_w50 (!3638)

NR UE: calculate TA based on SIB19 information in NTN mode, if autonomous TA is not enabled

To achieve the goal, the hyper frame number (HFN) is introduced at the NR UE
PHY, MAC and RRC layers.

Besides this, we also implemented an orbit propagation to improve the accuracy
of N_UE_TA_adj, and a fix to keep the N_TA from RAR and MAC CE.

Fixes #981
This commit is contained in:
Jaroslava Fiedlerova
2025-12-08 12:04:31 +01:00
30 changed files with 313 additions and 181 deletions
@@ -123,7 +123,7 @@ services:
--rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod
--rfsimulator.serveraddr 192.168.71.140
--time-sync-I 0.1 --ntn-initial-time-drift -46
--autonomous-ta --initial-fo 57340 --cont-fo-comp 2
--initial-fo 57340 --cont-fo-comp 2
--log_config.global_log_options level,nocolor,time
--num-ul-actors 1
depends_on:
+3 -1
View File
@@ -352,7 +352,9 @@ These modes of operation are supported:
- Formats 0,1,2,3, A1-A3, B1-B3
* NTN
- TA adjustemt based on ntn-Config-r17 information
- Autonomous TA adjustemt between SIB19 receptions based on DL time tracking
- Different TA adjustemt algorithms between SIB19 receptions:
- Autonomous TA adjustemt based on DL time tracking
- Standard compliant epoch time based TA adjustment including orbital propagation
- UL Doppler pre-compensation based on continuous DL FO estimation
* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported)
* Highly efficient 3GPP compliant polar encoder and decoder
+4 -2
View File
@@ -356,7 +356,9 @@ sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF
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.
To perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` can be added.
If that parameter is omitted, the TA is continuously computed based on the SIB19 information.
For LEO satellite scenario we assume the LO to be very accurate and the main FO contribution comes from Doppler shift.
Therefore, we use the command line parameter `--cont-fo-comp 2` to continuously compensate the DL Doppler and pre-compensate the UL Doppler.
@@ -367,7 +369,7 @@ For other information on optional NR UE command line options, please refer [here
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 -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 --initial-fo 57340 --cont-fo-comp 2
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 --initial-fo 57340 --cont-fo-comp 2
```
# Specific OAI modes
+76 -39
View File
@@ -434,8 +434,10 @@ void processSlotTX(void *arg)
nr_sidelink_indication_t sl_indication = {.module_id = UE->Mod_id,
.gNB_index = proc->gNB_id,
.cc_id = UE->CC_id,
.hfn_tx = proc->hfn_tx,
.frame_tx = proc->frame_tx,
.slot_tx = proc->nr_slot_tx,
.hfn_rx = proc->hfn_rx,
.frame_rx = proc->frame_rx,
.slot_rx = proc->nr_slot_rx,
.slot_type = SIDELINK_SLOT_TYPE_TX,
@@ -669,8 +671,8 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_r
AssertFatal(read_block_size == tmp, "");
if (IS_SOFTMODEM_RFSIM) {
const openair0_timestamp writeTimestamp =
*timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance;
const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx)
- UE->N_TA_offset - UE->timing_advance - UE->timing_advance_ntn;
dummyWrite(UE, writeTimestamp, fp->get_samples_per_slot(slot, fp));
}
}
@@ -696,8 +698,8 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int d
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, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance;
const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx)
- UE->N_TA_offset - UE->timing_advance - UE->timing_advance_ntn;
dummyWrite(UE, writeTimestamp, unitTransfer);
}
slot = (slot + 1) % fp->slots_per_subframe;
@@ -721,8 +723,61 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
return rem_samples + next_slot_first_symbol;
}
#define SPEED_OF_LIGHT 299792458
static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx)
{
const fapi_nr_dl_ntn_config_command_pdu *ntn_config_params = &UE->ntn_config_message->ntn_config_params;
const int abs_subframe_epoch = ntn_config_params->epoch_subframe
+ ntn_config_params->epoch_sfn * 10
+ ntn_config_params->epoch_hfn * 10240;
const int ms_since_epoch = abs_subframe_tx - abs_subframe_epoch;
const double omega = ntn_config_params->omega;
const double cos_wt = cos(omega * ms_since_epoch);
const double sin_wt = sin(omega * ms_since_epoch);
const position_t pos_sat_0 = ntn_config_params->pos_sat_0;
const position_t pos_sat_90 = ntn_config_params->pos_sat_90;
const position_t pos_sat = {pos_sat_0.X * cos_wt + pos_sat_90.X * sin_wt,
pos_sat_0.Y * cos_wt + pos_sat_90.Y * sin_wt,
pos_sat_0.Z * cos_wt + pos_sat_90.Z * sin_wt};
position_t pos_ue = {0};
get_position_coordinates(UE->Mod_id, &pos_ue);
// calculate directional vector from SAT to UE
const position_t dir_sat_ue = {pos_ue.X - pos_sat.X, pos_ue.Y - pos_sat.Y, pos_ue.Z - pos_sat.Z};
// calculate distance between SAT and UE
const double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z);
// calculate round-trip-time (factor 2) between SAT and UE in ms (factor 1000)
const double N_UE_TA_adj = 2000 * distance / SPEED_OF_LIGHT;
const double N_common_ta_adj = ntn_config_params->N_common_ta_adj;
const double N_common_ta_drift = ntn_config_params->N_common_ta_drift;
const double N_common_ta_drift_variant = ntn_config_params->N_common_ta_drift_variant;
UE->timing_advance_ntn = (N_UE_TA_adj + N_common_ta_adj
+ N_common_ta_drift * ms_since_epoch / 1e6
+ N_common_ta_drift_variant * ((int64_t)ms_since_epoch * ms_since_epoch) / 1e9)
* fp->samples_per_subframe;
LOG_D(PHY,
"N_UE_TA_adj = %f ms, N_common_ta_adj = %f ms, N_common_ta_drift = %f µs/s, N_common_ta_drift_variant = %f µs/s², ms_since_epoch = %d ms, "
"computed timing_advance_ntn = %d samples\n",
N_UE_TA_adj,
N_common_ta_adj,
N_common_ta_drift,
N_common_ta_drift_variant,
ms_since_epoch,
UE->timing_advance_ntn);
}
static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
NR_DL_FRAME_PARMS *fp,
int hfn_rx,
int frame_rx,
int slot_rx,
int *duration_rx_to_tx,
@@ -742,34 +797,8 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
*timing_advance -= fp->get_samples_slot_timestamp(slot_rx, fp, (*ntn_koffset - koffset) << mu);
*ntn_koffset = koffset;
const int abs_subframe_tx = 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
const int abs_subframe_epoch =
10 * UE->ntn_config_message->ntn_config_params.epoch_sfn + UE->ntn_config_message->ntn_config_params.epoch_subframe;
int ms_since_epoch = abs_subframe_tx - abs_subframe_epoch;
// cope with sfn wrap-around
// this currently limits us to epoch times that are not more than 5.12 seconds in the future (allowed are up to 10.24 seconds)
// and ntn-UlSyncValidityDuration < 5.12 seconds (allowed are up to 900 seconds)
// TODO: fix this limitation by introducing the hyper frame number HFN
if (ms_since_epoch < -5120)
ms_since_epoch += 10240;
else if (ms_since_epoch > 5120)
ms_since_epoch -= 10240;
const double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms;
const double total_ta_drift = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift; // µs/s
const double total_ta_drift_variant = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift_variant; // µs/s²
UE->timing_advance = fp->samples_per_subframe * (total_ta_ms + (total_ta_drift / 1000.0) * (ms_since_epoch / 1000.0) + (total_ta_drift_variant / 1000.0) * (ms_since_epoch / 1000.0) * (ms_since_epoch / 1000.0));
LOG_I(PHY,
"k_offset = %d ms (%d slots), total_ta_ms = %f ms, total_ta_drift = %f µs/s, total_ta_drift_variant = %f µs/s², ms_since_epoch = %d ms, computed "
"timing_advance = %d samples\n",
*ntn_koffset,
*ntn_koffset << mu,
total_ta_ms,
total_ta_drift,
total_ta_drift_variant,
ms_since_epoch,
UE->timing_advance);
const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
apply_ntn_timing_advance(UE, fp, abs_subframe_tx);
}
}
@@ -809,7 +838,7 @@ void *UE_thread(void *arg)
int ntn_koffset = 0;
int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX;
int timing_advance = UE->timing_advance;
int timing_advance = UE->timing_advance + UE->timing_advance_ntn;
UE->N_TA_offset = determine_N_TA_offset(UE);
NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
@@ -968,6 +997,8 @@ void *UE_thread(void *arg)
curMsg.proc.nr_slot_tx = (absolute_slot + duration_rx_to_tx) % nb_slot_frame;
curMsg.proc.frame_rx = (absolute_slot / nb_slot_frame) % MAX_FRAME_NUMBER;
curMsg.proc.frame_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) % MAX_FRAME_NUMBER;
curMsg.proc.hfn_rx = (absolute_slot / nb_slot_frame) / MAX_FRAME_NUMBER;
curMsg.proc.hfn_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) / MAX_FRAME_NUMBER;
if (UE->received_config_request) {
if (UE->sl_mode) {
curMsg.proc.rx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_rx, TDD);
@@ -990,12 +1021,18 @@ void *UE_thread(void *arg)
if (slot_nr == nb_slot_frame - 1) {
// we shift of half of measured drift, at each beginning of frame for both rx and tx
iq_shift_to_apply = shiftForNextFrame;
// TODO: remove this autonomous TA and use up-to-date values of ta-Common, ta-CommonDrift and ta-CommonDriftVariant from received SIB19 instead
if (get_nrUE_params()->autonomous_ta)
UE->timing_advance -= 2 * shiftForNextFrame;
// autonomous timing advance calculation, which does not use SIB19 information
if (ntn_koffset && get_nrUE_params()->autonomous_ta)
UE->timing_advance_ntn -= 2 * shiftForNextFrame;
shiftForNextFrame = -round(UE->max_pos_acc * get_nrUE_params()->time_sync_I);
}
// Calculate new TA based on SIB19 information for each subframe in NTN mode, if "autonomous_ta" is not enabled
if (ntn_koffset && !get_nrUE_params()->autonomous_ta && (absolute_slot + duration_rx_to_tx) % fp->slots_per_subframe == 0) {
const int abs_subframe_tx = (absolute_slot + duration_rx_to_tx) / fp->slots_per_subframe;
apply_ntn_timing_advance(UE, fp, abs_subframe_tx);
}
const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply;
openair0_timestamp rx_timestamp;
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx);
@@ -1035,7 +1072,7 @@ void *UE_thread(void *arg)
// but use current UE->timing_advance value to compute writeBlockSize
int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply;
int new_timing_advance = UE->timing_advance;
int new_timing_advance = UE->timing_advance + UE->timing_advance_ntn;
if (new_timing_advance != timing_advance) {
writeBlockSize -= new_timing_advance - timing_advance;
timing_advance = new_timing_advance;
@@ -1048,7 +1085,7 @@ void *UE_thread(void *arg)
}
if (curMsg.proc.nr_slot_rx == 0)
nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_rx, curMsg.proc.gNB_id);
nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.hfn_rx, curMsg.proc.frame_rx, curMsg.proc.gNB_id);
// RX slot processing. We launch and forget.
notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, NULL, UE_dl_processing);
@@ -1064,7 +1101,7 @@ void *UE_thread(void *arg)
}
// apply new NTN timing information
apply_ntn_config(UE, fp, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
apply_ntn_config(UE, fp, curMsg.proc.hfn_rx, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, &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
+1
View File
@@ -20,6 +20,7 @@
*/
#include "position_interface.h"
#include "executables/nr-uesoftmodem.h"
static void read_position_coordinates(char *sectionName, position_t *position)
{
-5
View File
@@ -22,11 +22,6 @@
#ifndef __POSITION_INTERFACE__H__
#define __POSITION_INTERFACE__H__
#include <executables/nr-softmodem-common.h>
#include <executables/softmodem-common.h>
#include "PHY/defs_nr_UE.h"
#include "executables/nr-uesoftmodem.h"
/* position configuration parameters name */
#define CONFIG_STRING_POSITION_X "x"
#define CONFIG_STRING_POSITION_Y "y"
@@ -24,6 +24,7 @@
#include "PHY/impl_defs_top.h"
#include "PHY/impl_defs_nr.h"
#include "common/utils/nr/nr_common.h"
#include "executables/position_interface.h"
#define NFAPI_UE_MAX_NUM_CB 8
#define NFAPI_MAX_NUM_UL_PDU 255
@@ -562,18 +563,26 @@ typedef struct {
} fapi_nr_ta_command_pdu;
typedef struct {
int epoch_hfn;
int epoch_sfn;
int epoch_subframe;
// orbital angular velocity in rad/ms
double omega;
// satellite position at epoch time
position_t pos_sat_0;
// satellite position at 90° orbit
position_t pos_sat_90;
// N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms)
double N_common_ta_adj;
// drift rate of common ta in µs/s
double N_common_ta_drift;
// change rate of common ta drift in µs/s²
double N_common_ta_drift_variant;
// cell scheduling offset expressed in terms of 15kHz SCS
long cell_specific_k_offset;
// ntn_total_time_advance_ms represents the complete round-trip-time between gNB and UE via SAT
double ntn_total_time_advance_ms;
// drift rate of ntn_total_time_advance_ms in µs/s
double ntn_total_time_advance_drift;
// change rate of ntn_total_time_advance_ms drift in µs/s²
double ntn_total_time_advance_drift_variant;
} fapi_nr_dl_ntn_config_command_pdu;
typedef struct {
@@ -324,7 +324,7 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc,
int32_t sync_pos = -1; // sync_pos_frame = -1;
int32_t metric_tdd_ncp = 0;
uint8_t phase_tdd_ncp;
uint8_t phase_tdd_ncp = 0;
double im, re;
int ret = -1;
uint16_t rx_slss_id = 65535;
+6 -2
View File
@@ -467,7 +467,8 @@ typedef struct PHY_VARS_NR_UE_s {
/// Timing Advance updates variables
/// Timing advance update computed from the TA command signalled from gNB
int timing_advance;
int timing_advance; /// corresponds to N_TA
int timing_advance_ntn; /// corresponds to N_common_TA_adj + N_UE_TA_adj
int N_TA_offset; ///timing offset used in TDD
int ta_frame;
int ta_slot;
@@ -538,11 +539,14 @@ typedef struct {
/// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission
int nr_slot_rx;
int tx_slot_type;
//#endif
/// frame to act upon for transmission
int frame_tx;
/// frame to act upon for reception
int frame_rx;
/// hyper frame number to act upon for transmission
int hfn_tx;
/// hyper frame number to act upon for reception
int hfn_rx;
} UE_nr_rxtx_proc_t;
typedef struct {
+11 -3
View File
@@ -95,12 +95,20 @@ static void configure_ntn_params(PHY_VARS_NR_UE *ue, fapi_nr_dl_ntn_config_comma
ue->ntn_config_message = CALLOC(1, sizeof(*ue->ntn_config_message));
}
ue->ntn_config_message->ntn_config_params.epoch_hfn = ntn_params_message->epoch_hfn;
ue->ntn_config_message->ntn_config_params.epoch_sfn = ntn_params_message->epoch_sfn;
ue->ntn_config_message->ntn_config_params.epoch_subframe = ntn_params_message->epoch_subframe;
ue->ntn_config_message->ntn_config_params.omega = ntn_params_message->omega;
ue->ntn_config_message->ntn_config_params.pos_sat_0 = ntn_params_message->pos_sat_0;
ue->ntn_config_message->ntn_config_params.pos_sat_90 = ntn_params_message->pos_sat_90;
ue->ntn_config_message->ntn_config_params.N_common_ta_adj = ntn_params_message->N_common_ta_adj;
ue->ntn_config_message->ntn_config_params.N_common_ta_drift = ntn_params_message->N_common_ta_drift;
ue->ntn_config_message->ntn_config_params.N_common_ta_drift_variant = ntn_params_message->N_common_ta_drift_variant;
ue->ntn_config_message->ntn_config_params.cell_specific_k_offset = ntn_params_message->cell_specific_k_offset;
ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms = ntn_params_message->ntn_total_time_advance_ms;
ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift = ntn_params_message->ntn_total_time_advance_drift;
ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift_variant = ntn_params_message->ntn_total_time_advance_drift_variant;
ue->ntn_config_message->update = true;
}
@@ -95,6 +95,7 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
dl_ind->gNB_index = proc->gNB_id;
dl_ind->module_id = ue->Mod_id;
dl_ind->cc_id = ue->CC_id;
dl_ind->hfn = proc->hfn_rx;
dl_ind->frame = proc->frame_rx;
dl_ind->slot = proc->nr_slot_rx;
dl_ind->phy_data = phy_data;
@@ -44,8 +44,10 @@ void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
sl_ind->gNB_index = proc->gNB_id;
sl_ind->module_id = ue->Mod_id;
sl_ind->cc_id = ue->CC_id;
sl_ind->hfn_rx = proc->hfn_rx;
sl_ind->frame_rx = proc->frame_rx;
sl_ind->slot_rx = proc->nr_slot_rx;
sl_ind->hfn_tx = proc->hfn_tx;
sl_ind->frame_tx = proc->frame_tx;
sl_ind->slot_tx = proc->nr_slot_tx;
sl_ind->phy_data = phy_data;
+1 -1
View File
@@ -965,7 +965,7 @@ int main(int argc, char **argv)
//Configure UE
NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc);
nr_rrc_mac_config_req_mib(0, 0, mib->message.choice.mib, false, false);
nr_rrc_mac_config_req_cg(0, 0, UE_CellGroup, UE_Capability_nr);
nr_rrc_mac_config_req_cg(0, 0, 0, 0, UE_CellGroup, UE_Capability_nr);
asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, UE_CellGroup);
@@ -163,6 +163,7 @@ typedef uint32_t channel_t;
int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const int CC_id,
const uint8_t gNB_index,
const int hfn,
const frame_t frame,
const int slot,
const rnti_t rnti,
+2
View File
@@ -121,6 +121,7 @@ typedef struct RrcMacBcchDataInd_s {
} RrcMacBcchDataInd;
typedef struct NRRrcMacBcchDataInd_s {
uint32_t hfn;
uint32_t frame;
uint8_t slot;
uint32_t sdu_size;
@@ -134,6 +135,7 @@ typedef struct NRRrcMacBcchDataInd_s {
} NRRrcMacBcchDataInd;
typedef struct NRRrcMacSBcchDataInd_s {
uint32_t hfn;
uint32_t frame;
uint8_t slot;
uint32_t sdu_size;
+5
View File
@@ -438,6 +438,7 @@ typedef struct rrc_subframe_process_s {
} RrcSubframeProcess;
typedef struct nrrrc_frame_process_s {
int hfn;
int frame;
int gnb_id;
} NRRrcFrameProcess;
@@ -475,6 +476,8 @@ typedef struct {
typedef struct {
NR_CellGroupConfig_t *cellGroupConfig;
NR_UE_NR_Capability_t *UE_NR_Capability;
int hfn;
int frame;
} nr_mac_rrc_config_cg_t;
typedef struct {
NR_BCCH_BCH_Message_t *bcch;
@@ -487,6 +490,8 @@ typedef struct {
} nr_mac_rrc_config_sib1_t;
typedef struct {
NR_SIB19_r17_t *sib19;
int hfn;
int frame;
bool can_start_ra;
} nr_mac_rrc_config_other_sib_t;
+56 -51
View File
@@ -31,7 +31,6 @@
*/
#define _GNU_SOURCE
#define SPEED_OF_LIGHT 299792458
#include "mac_defs.h"
#include "NR_MAC_UE/mac_proto.h"
@@ -41,7 +40,6 @@
#include "executables/softmodem-common.h"
#include "SCHED_NR/phy_frame_config_nr.h"
#include "oai_asn1.h"
#include "executables/position_interface.h"
#define ASIGN_P_VAL(dst, src) \
do { \
@@ -266,56 +264,61 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
}
// computes round-trip-time between ue and sat based on SIB19 ephemeris data
static void calculate_ue_sat_ta(const position_t *position_params,
const NR_PositionVelocity_r17_t *sat_pos,
ntn_timing_advance_componets_t *ntn_ta)
// prepare data for orbit propagation based on SIB19 ephemeris data to be able to compute the round-trip-time between ue and sat
static void prepare_ue_sat_ta(const NR_PositionVelocity_r17_t *sat_pos, ntn_timing_advance_componets_t *ntn_ta)
{
// get UE position coordinates
const position_t pos_ue = *position_params;
// get sat position coordinates
const position_t pos_sat = {sat_pos->positionX_r17 * 1.3, sat_pos->positionY_r17 * 1.3, sat_pos->positionZ_r17 * 1.3};
// calculate directional vector from SAT to UE
const position_t dir_sat_ue = {pos_ue.X - pos_sat.X, pos_ue.Y - pos_sat.Y, pos_ue.Z - pos_sat.Z};
// calculate distance between SAT and UE
double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z);
// get sat velocity vector
const position_t vel_sat = {sat_pos->velocityVX_r17 * 0.06, sat_pos->velocityVY_r17 * 0.06, sat_pos->velocityVZ_r17 * 0.06};
// calculate SAT velocity towards UE
double velocity = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance;
// calculate SAT acceleration towards UE
// calculate orbital radius
const double radius_2 = pos_sat.X * pos_sat.X + pos_sat.Y * pos_sat.Y + pos_sat.Z * pos_sat.Z;
const double radius = sqrt(radius_2);
// calculate sat velocity magnitude
const double vel_sat_2 = vel_sat.X * vel_sat.X + vel_sat.Y * vel_sat.Y + vel_sat.Z * vel_sat.Z;
const double acceleration =
-(pos_sat.X * dir_sat_ue.X + pos_sat.Y * dir_sat_ue.Y + pos_sat.Z * dir_sat_ue.Z) * vel_sat_2 / (radius_2 * distance);
const double vel_mag = sqrt(vel_sat_2);
LOG_D(NR_MAC, "Satellite velocity towards UE: %f m/s, acceleration towards UE: %f m/s²\n", velocity, acceleration);
// calculate angular velocity in rad/ms
const double omega = vel_mag / (radius * 1000);
ntn_ta->N_UE_TA_adj = (2 * distance / SPEED_OF_LIGHT) * 1e3; // in ms
ntn_ta->N_UE_TA_drift = (2 * -velocity / SPEED_OF_LIGHT) * 1e6; // in µs/s
ntn_ta->N_UE_TA_drift_variant = (2 * acceleration / SPEED_OF_LIGHT) * 1e6; // in µs/s²
// calculate sat position in 90° orbit
position_t pos_sat_90 = pos_sat;
if (vel_mag) {
const double scaling = radius / vel_mag;
pos_sat_90 = (position_t){vel_sat.X * scaling, vel_sat.Y * scaling, vel_sat.Z * scaling};
}
LOG_I(NR_MAC,
"Satellite angular velocity = %e rad/ms, sat_pos = {%f, %f, %f}, sat_pos_90 = {%f, %f, %f}\n",
omega,
pos_sat.X,
pos_sat.Y,
pos_sat.Z,
pos_sat_90.X,
pos_sat_90.Y,
pos_sat_90.Z);
ntn_ta->omega = omega;
ntn_ta->pos_sat_0 = pos_sat;
ntn_ta->pos_sat_90 = pos_sat_90;
}
// populate ntn_ta structure from mac
static void configure_ntn_ta(module_id_t module_id,
ntn_timing_advance_componets_t *ntn_ta,
const NR_NTN_Config_r17_t *ntn_Config_r17)
static void configure_ntn_ta(ntn_timing_advance_componets_t *ntn_ta, const NR_NTN_Config_r17_t *ntn_Config_r17, int hfn, int frame)
{
if (!ntn_Config_r17)
return;
position_t position_params = {0};
get_position_coordinates(module_id, &position_params);
// epochTime_r17 must be present (this is assured by function `eval_epoch_time()`)
const NR_EpochTime_r17_t *epoch_time_r17 = ntn_Config_r17->epochTime_r17;
AssertFatal(epoch_time_r17, "epoch_time_r17 should not be NULL here\n");
if (epoch_time_r17->sfn_r17 >= frame)
ntn_ta->epoch_hfn = hfn;
else
ntn_ta->epoch_hfn = hfn + 1;
ntn_ta->epoch_sfn = epoch_time_r17->sfn_r17;
ntn_ta->epoch_subframe = epoch_time_r17->subFrameNR_r17;
@@ -325,17 +328,17 @@ static void configure_ntn_ta(module_id_t module_id,
if (ephemeris_info->present == NR_EphemerisInfo_r17_PR_positionVelocity_r17) {
const NR_PositionVelocity_r17_t *position_velocity = ephemeris_info->choice.positionVelocity_r17;
AssertFatal(position_velocity, "position_velocity should not be NULL here\n");
calculate_ue_sat_ta(&position_params, position_velocity, ntn_ta);
prepare_ue_sat_ta(position_velocity, ntn_ta);
} else {
LOG_W(NR_MAC, "NR UE currently supports only ephemerisInfo_r17 of type positionVelocity_r17\n");
ntn_ta->N_UE_TA_adj = 0;
ntn_ta->N_UE_TA_drift = 0;
ntn_ta->N_UE_TA_drift_variant = 0;
ntn_ta->omega = 0;
ntn_ta->pos_sat_0 = (position_t){0, 0, 0};
ntn_ta->pos_sat_90 = (position_t){0, 0, 0};
}
} else { // Need R - Release if not present
ntn_ta->N_UE_TA_adj = 0;
ntn_ta->N_UE_TA_drift = 0;
ntn_ta->N_UE_TA_drift_variant = 0;
ntn_ta->omega = 0;
ntn_ta->pos_sat_0 = (position_t){0, 0, 0};
ntn_ta->pos_sat_90 = (position_t){0, 0, 0};
}
// handle cellSpecificKoffset_r17
@@ -366,21 +369,19 @@ static void configure_ntn_ta(module_id_t module_id,
ntn_ta->ntn_params_changed = true;
LOG_D(NR_MAC,
"SIB19 Rxd. Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, N_Common_Ta: %fms, drift: %fµs/s, variant %fµs/s², "
"N_UE_TA: %fms, drift: %fµs/s, variant %fµs/s²\n",
LOG_I(NR_MAC,
"SIB19 Rxd. Epoch HFN: %d, Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, "
"N_Common_Ta: %fms, drift: %fµs/s, variant %fµs/s²\n",
ntn_ta->epoch_hfn,
ntn_ta->epoch_sfn,
ntn_ta->epoch_subframe,
ntn_ta->cell_specific_k_offset,
ntn_ta->N_common_ta_adj,
ntn_ta->N_common_ta_drift,
ntn_ta->N_common_ta_drift_variant,
ntn_ta->N_UE_TA_adj,
ntn_ta->N_UE_TA_drift,
ntn_ta->N_UE_TA_drift_variant);
ntn_ta->N_common_ta_drift_variant);
}
static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t *scc, int cc_idP)
static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t *scc, int cc_idP, int hfn, int frame)
{
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
@@ -555,7 +556,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
// NTN Config
if (scc->ext2) {
UPDATE_IE(mac->sc_info.ntn_Config_r17, scc->ext2->ntn_Config_r17, NR_NTN_Config_r17_t);
configure_ntn_ta(mac->ue_id, &mac->ntn_ta, mac->sc_info.ntn_Config_r17);
configure_ntn_ta(&mac->ntn_ta, mac->sc_info.ntn_Config_r17, hfn, frame);
} else {
asn1cFreeStruc(asn_DEF_NR_NTN_Config_r17, mac->sc_info.ntn_Config_r17);
}
@@ -1947,7 +1948,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, bool can_start_ra)
void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, int hfn, int frame, bool can_start_ra)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
int ret = pthread_mutex_lock(&mac->if_mutex);
@@ -1956,7 +1957,7 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, b
if (sib19) {
// update ntn_Config_r17 with received values
UPDATE_IE(mac->sc_info.ntn_Config_r17, sib19->ntn_Config_r17, NR_NTN_Config_r17_t);
configure_ntn_ta(mac->ue_id, &mac->ntn_ta, mac->sc_info.ntn_Config_r17);
configure_ntn_ta(&mac->ntn_ta, mac->sc_info.ntn_Config_r17, hfn, frame);
}
if (mac->state == UE_RECEIVING_SIB && can_start_ra)
mac->state = UE_PERFORMING_RA;
@@ -1966,6 +1967,8 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, b
static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
int cc_idP,
int hfn,
int frame,
const NR_ReconfigurationWithSync_t *reconfWithSync)
{
reset_mac_inst(mac);
@@ -1985,7 +1988,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
mac->physCellId = *scc->physCellId;
mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position;
UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
config_common_ue(mac, scc, cc_idP);
config_common_ue(mac, scc, cc_idP, hfn, frame);
// Build the list of all the valid/transmitted SSBs according to the config
LOG_D(NR_MAC,"Build SSB list\n");
build_ssb_list(mac);
@@ -2754,6 +2757,8 @@ static void handle_mac_uecap_info(NR_UE_MAC_INST_t *mac, NR_UE_NR_Capability_t *
void nr_rrc_mac_config_req_cg(module_id_t module_id,
int cc_idP,
int hfn,
int frame,
NR_CellGroupConfig_t *cell_group_config,
NR_UE_NR_Capability_t *ue_Capability)
{
@@ -2772,7 +2777,7 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
mac->servCellIndex = spCellConfig->servCellIndex ? *spCellConfig->servCellIndex : 0;
if (spCellConfig->reconfigurationWithSync) {
LOG_A(NR_MAC, "Received reconfigurationWithSync\n");
handle_reconfiguration_with_sync(mac, cc_idP, spCellConfig->reconfigurationWithSync);
handle_reconfiguration_with_sync(mac, cc_idP, hfn, frame, spCellConfig->reconfigurationWithSync);
}
if (scd) {
mac->tag_Id = scd->tag_Id;
+11 -21
View File
@@ -62,6 +62,8 @@
#include "NR_MeasConfig.h"
#include "NR_ServingCellConfigCommonSIB.h"
/* position_t */
#include "executables/position_interface.h"
// ==========
// NR UE defs
@@ -543,21 +545,24 @@ typedef struct {
} si_schedInfo_t;
typedef struct ntn_timing_advance_components {
int epoch_hfn;
int epoch_sfn;
int epoch_subframe;
// orbital angular velocity in rad/ms
double omega;
// satellite position at epoch time
position_t pos_sat_0;
// satellite position at 90° orbit
position_t pos_sat_90;
// N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms)
double N_common_ta_adj;
// drift rate of common ta in µs/s
double N_common_ta_drift;
// change rate of common ta drift in µs/s²
double N_common_ta_drift_variant;
// N_UE_TA_adj calculated round-trip-time between UE and SAT (ms)
double N_UE_TA_adj;
// drift rate of N_UE_TA in µs/s
double N_UE_TA_drift;
// change rate of N_UE_TA drift in µs/s²
double N_UE_TA_drift_variant;
// cell scheduling offset expressed in terms of 15kHz SCS
long cell_specific_k_offset;
@@ -678,20 +683,5 @@ static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *n
return NR_UE_CAPABILITY_SLOT_RX_TO_TX + (ntn_ta->cell_specific_k_offset << scs);
}
static inline double get_total_TA_ms(const ntn_timing_advance_componets_t *ntn_ta)
{
return ntn_ta->N_common_ta_adj + ntn_ta->N_UE_TA_adj;
}
static inline double get_total_TA_drift(const ntn_timing_advance_componets_t *ntn_ta)
{
return ntn_ta->N_common_ta_drift + ntn_ta->N_UE_TA_drift;
}
static inline double get_total_TA_drift_variant(const ntn_timing_advance_componets_t *ntn_ta)
{
return ntn_ta->N_common_ta_drift_variant + ntn_ta->N_UE_TA_drift_variant;
}
/*@}*/
#endif /*__LAYER2_MAC_DEFS_H__ */
+4 -1
View File
@@ -73,6 +73,7 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
uint8_t ack_nack,
uint8_t *pduP,
uint32_t pdu_len,
int hfn,
int frame,
int slot);
@@ -82,6 +83,8 @@ void nr_release_mac_config_logicalChannelBearer(NR_UE_MAC_INST_t *mac, long chan
void nr_rrc_mac_config_req_cg(module_id_t module_id,
int cc_idP,
int hfn,
int frame,
NR_CellGroupConfig_t *cell_group_config,
NR_UE_NR_Capability_t *ue_Capability);
@@ -90,7 +93,7 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mibP
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, bool can_start_ra);
void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17, int hfn, int frame, bool can_start_ra);
void nr_rrc_mac_resume_rb(module_id_t module_id, bool is_srb, int rb_id);
void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause);
+10 -21
View File
@@ -777,13 +777,12 @@ static int nr_get_RA_window_4Step(long ra_ResponseWindow)
return 0;
}
static void setup_ra_response_window(RA_config_t *ra,
int slots_per_frame,
NR_NTN_Config_r17_t *ntn_Config_r17,
static void setup_ra_response_window(NR_UE_MAC_INST_t *mac,
RA_config_t *ra,
NR_RACH_ConfigGeneric_t *configGeneric,
NR_RACH_ConfigGenericTwoStepRA_r16_t *twostep,
ntn_timing_advance_componets_t *ntn_ta)
NR_RACH_ConfigGenericTwoStepRA_r16_t *twostep)
{
const int slots_per_frame = mac->frame_structure.numb_slots_frame;
int respwind_value = 0;
if (ra->ra_type == RA_2_STEP) {
long *msgB_ResponseWindow = twostep->msgB_ResponseWindow_r16;
@@ -816,13 +815,8 @@ static void setup_ra_response_window(RA_config_t *ra,
LOG_E(NR_MAC, "RA-ResponseWindow need to be configured to a value lower than or equal to 10 ms\n");
}
int ta_Common_slots = 0;
if (ntn_Config_r17) {
const double ta_Common_ms = get_total_TA_ms(ntn_ta);
ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_frame / 10);
}
ra->response_window_setup_time = respwind_value + ta_Common_slots;
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
ra->response_window_setup_time = respwind_value + ntn_ue_koffset;
}
// Random Access procedure initialization as per 5.1.1 and initialization of variables specific
@@ -1026,12 +1020,8 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame)
else
ra->num_fd_occasions = 1 << rach_ConfigGeneric->msg1_FDM;
setup_ra_response_window(ra,
mac->frame_structure.numb_slots_frame,
mac->sc_info.ntn_Config_r17,
rach_ConfigGeneric,
twostep_generic,
&mac->ntn_ta);
setup_ra_response_window(mac, ra, rach_ConfigGeneric, twostep_generic);
return true;
}
@@ -1039,16 +1029,15 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s
{
RA_config_t *ra = &mac->ra;
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
const double ta_Common_ms = get_total_TA_ms(&mac->ntn_ta);
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
const int slots_per_ms = mac->frame_structure.numb_slots_frame / 10;
// start contention resolution timer
const int RA_contention_resolution_timer_ms = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) << 3;
const int RA_contention_resolution_timer_slots = RA_contention_resolution_timer_ms * slots_per_ms;
const int ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_ms);
// timer step 1 slot and timer target given by ra_ContentionResolutionTimer + ta-Common-r17
nr_timer_setup(&ra->contention_resolution_timer, RA_contention_resolution_timer_slots + ta_Common_slots, 1);
nr_timer_setup(&ra->contention_resolution_timer, RA_contention_resolution_timer_slots + ntn_ue_koffset, 1);
nr_timer_start(&ra->contention_resolution_timer);
ra->ra_state = nrRA_WAIT_CONTENTION_RESOLUTION;
+3 -2
View File
@@ -361,12 +361,13 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
uint8_t ack_nack,
uint8_t *pduP,
uint32_t pdu_len,
int hfn,
int frame,
int slot)
{
if(ack_nack) {
LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n");
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, hfn, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
if (mac->get_sib1)
mac->get_sib1 = false;
for (int i = 0; i < MAX_SI_GROUPS; i++) {
@@ -383,7 +384,7 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
}
else {
LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (%s)\n", mac->get_sib1 ? "SIB1" : "other SI");
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0);
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, hfn, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0);
}
}
+10 -3
View File
@@ -2848,12 +2848,19 @@ 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->epoch_hfn = mac->ntn_ta.epoch_hfn;
ntn_config_command_pdu->epoch_sfn = mac->ntn_ta.epoch_sfn;
ntn_config_command_pdu->epoch_subframe = mac->ntn_ta.epoch_subframe;
ntn_config_command_pdu->omega = mac->ntn_ta.omega;
ntn_config_command_pdu->pos_sat_0 = mac->ntn_ta.pos_sat_0;
ntn_config_command_pdu->pos_sat_90 = mac->ntn_ta.pos_sat_90;
ntn_config_command_pdu->N_common_ta_adj = mac->ntn_ta.N_common_ta_adj;
ntn_config_command_pdu->N_common_ta_drift = mac->ntn_ta.N_common_ta_drift;
ntn_config_command_pdu->N_common_ta_drift_variant = mac->ntn_ta.N_common_ta_drift_variant;
ntn_config_command_pdu->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset;
ntn_config_command_pdu->ntn_total_time_advance_ms = get_total_TA_ms(&mac->ntn_ta);
ntn_config_command_pdu->ntn_total_time_advance_drift = get_total_TA_drift(&mac->ntn_ta);
ntn_config_command_pdu->ntn_total_time_advance_drift_variant = get_total_TA_drift_variant(&mac->ntn_ta);
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_NTN_CONFIG_PARAMS;
dl_config->number_pdus += 1;
+10 -4
View File
@@ -123,7 +123,7 @@ static int handle_bcch_bch(NR_UE_MAC_INST_t *mac,
else
mac->frequency_range = FR1;
// fixed 3 bytes MIB PDU
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, cell_id, ssb_arfcn, NR_BCCH_BCH, (uint8_t *) pduP, 3);
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, 0, cell_id, ssb_arfcn, NR_BCCH_BCH, (uint8_t *) pduP, 3);
return 0;
}
@@ -134,10 +134,11 @@ static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac,
uint8_t ack_nack,
uint8_t *pduP,
uint32_t pdu_len,
int hfn,
int frame,
int slot)
{
nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len, frame, slot);
nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len, hfn, frame, slot);
return 0;
}
@@ -301,6 +302,7 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio
rx_indication_body.pdsch_pdu.ack_nack,
rx_indication_body.pdsch_pdu.pdu,
rx_indication_body.pdsch_pdu.pdu_length,
dl_info->hfn,
dl_info->frame,
dl_info->slot)) << FAPI_NR_RX_PDU_TYPE_SIB;
break;
@@ -389,6 +391,7 @@ static void handle_sl_bch(int ue_id,
sl_nr_ue_mac_params_t *sl_mac,
uint8_t *const sl_mib,
const uint8_t len,
int hfn_rx,
uint16_t frame_rx,
uint16_t slot_rx,
uint16_t rx_slss_id)
@@ -421,7 +424,7 @@ static void handle_sl_bch(int ue_id,
sl_mac->decoded_DFN = frame;
sl_mac->decoded_slot = slot;
nr_mac_rrc_data_ind_ue(ue_id, 0, 0, frame_rx, slot_rx, 0, rx_slss_id, 0, NR_SBCCH_SL_BCH, (uint8_t *)sl_mib, len);
nr_mac_rrc_data_ind_ue(ue_id, 0, 0, hfn_rx, frame_rx, slot_rx, 0, rx_slss_id, 0, NR_SBCCH_SL_BCH, (uint8_t *)sl_mib, len);
return;
}
@@ -433,6 +436,7 @@ if PSBCH rx - handle_psbch()
if PSSCH DATa rx - handle slsch()
*/
void sl_nr_process_rx_ind(int ue_id,
int hfn,
uint32_t frame,
uint32_t slot,
sl_nr_ue_mac_params_t *sl_mac,
@@ -456,6 +460,7 @@ void sl_nr_process_rx_ind(int ue_id,
sl_mac,
rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.psbch_payload,
4,
hfn,
frame,
slot,
rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.rx_slss_id);
@@ -488,11 +493,12 @@ void nr_ue_sl_indication(nr_sidelink_indication_t *sl_indication)
uint16_t slot = sl_indication->slot_rx;
uint16_t frame = sl_indication->frame_rx;
int hfn = sl_indication->hfn_rx;
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
if (sl_indication->rx_ind) {
sl_nr_process_rx_ind(ue_id, frame, slot, sl_mac, sl_indication->rx_ind);
sl_nr_process_rx_ind(ue_id, hfn, frame, slot, sl_mac, sl_indication->rx_ind);
} else {
nr_ue_sidelink_scheduler(sl_indication, mac);
}
@@ -56,6 +56,8 @@ typedef struct {
uint32_t gNB_index;
/// component carrier id
int cc_id;
/// hyper frame number
int hfn;
/// frame
frame_t frame;
/// slot
@@ -101,10 +103,14 @@ typedef struct {
uint32_t gNB_index;
/// component carrier id
int cc_id;
/// hyper frame number rx
int hfn_rx;
/// frame rx
frame_t frame_rx;
/// slot rx
uint32_t slot_rx;
/// hyper frame number tx
int hfn_tx;
/// frame tx
frame_t frame_tx;
/// slot tx
+16 -4
View File
@@ -59,6 +59,7 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const
void nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const int CC_id,
const uint8_t gNB_index,
const int hfn,
const frame_t frame,
const int slot,
const rnti_t rnti,
@@ -97,6 +98,7 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id,
else {
NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu_size = 0;
}
NR_RRC_MAC_BCCH_DATA_IND (message_p).hfn = hfn;
NR_RRC_MAC_BCCH_DATA_IND (message_p).frame = frame; //frameP
NR_RRC_MAC_BCCH_DATA_IND (message_p).slot = slot;
NR_RRC_MAC_BCCH_DATA_IND (message_p).gnb_index = gNB_index;
@@ -120,6 +122,7 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id,
message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_SBCCH_DATA_IND);
memset(NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE);
memcpy(NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu, pduP, sdu_size);
NR_RRC_MAC_SBCCH_DATA_IND (message_p).hfn = hfn;
NR_RRC_MAC_SBCCH_DATA_IND (message_p).frame = frame; //frameP
NR_RRC_MAC_SBCCH_DATA_IND (message_p).slot = slot;
NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu_size = sdu_size;
@@ -139,7 +142,12 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id)
nr_rrc_mac_config_req_reset(instance_id, msg->payload.config_reset.cause);
break;
case NR_MAC_RRC_CONFIG_CG:
nr_rrc_mac_config_req_cg(instance_id, 0, msg->payload.config_cg.cellGroupConfig, msg->payload.config_cg.UE_NR_Capability);
nr_rrc_mac_config_req_cg(instance_id,
0,
msg->payload.config_cg.hfn,
msg->payload.config_cg.frame,
msg->payload.config_cg.cellGroupConfig,
msg->payload.config_cg.UE_NR_Capability);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, msg->payload.config_cg.cellGroupConfig);
break;
case NR_MAC_RRC_CONFIG_MIB:
@@ -157,8 +165,11 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id)
SEQUENCE_free(&asn_DEF_NR_SIB1, msg->payload.config_sib1.sib1, ASFM_FREE_EVERYTHING);
} break;
case NR_MAC_RRC_CONFIG_OTHER_SIB: {
bool can_start_ra = msg->payload.config_other_sib.can_start_ra;
nr_rrc_mac_config_other_sib(instance_id, msg->payload.config_other_sib.sib19, can_start_ra);
nr_rrc_mac_config_other_sib(instance_id,
msg->payload.config_other_sib.sib19,
msg->payload.config_other_sib.hfn,
msg->payload.config_other_sib.frame,
msg->payload.config_other_sib.can_start_ra);
} break;
case NR_MAC_RRC_RESUME_RB:
nr_rrc_mac_resume_rb(instance_id, msg->payload.resume_rb.is_srb, msg->payload.resume_rb.rb_id);
@@ -183,10 +194,11 @@ void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p);
}
void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id)
void nr_ue_rrc_timer_trigger(int instance, int hfn, int frame, int gnb_id)
{
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NRRRC_FRAME_PROCESS);
NRRRC_FRAME_PROCESS(message_p).hfn = hfn;
NRRRC_FRAME_PROCESS(message_p).frame = frame;
NRRRC_FRAME_PROCESS(message_p).gnb_id = gnb_id;
LOG_D(NR_RRC, "RRC timer trigger: frame %d\n", frame);
+2 -1
View File
@@ -29,6 +29,7 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const
void nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const int CC_id,
const uint8_t gNB_index,
const int hfn,
const frame_t frame,
const int slot,
const rnti_t rnti,
@@ -45,7 +46,7 @@ void nr_mac_rrc_meas_ind_ue(module_id_t module_id,
int rsrp_dBm);
void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id);
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload);
void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id);
void nr_ue_rrc_timer_trigger(int instance, int hfn, int frame, int gnb_id);
void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success);
void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id);
#endif
+12 -3
View File
@@ -292,7 +292,7 @@ static void nr_rrc_process_ntnconfig(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *S
nr_timer_start(&SI_info->SInfo_r17.sib19_timer);
}
static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc, int frame)
static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc, int hfn, int frame)
{
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN);
@@ -381,6 +381,8 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si,
rrc_msg.payload_type = NR_MAC_RRC_CONFIG_OTHER_SIB;
nr_mac_rrc_config_other_sib_t *sib19_msg = &rrc_msg.payload.config_other_sib;
asn_copy(&asn_DEF_NR_SIB19_r17, (void **)&sib19_msg->sib19, sib19);
sib19_msg->hfn = hfn;
sib19_msg->frame = frame;
sib19_msg->can_start_ra = rrc->is_NTN_UE;
nr_rrc_send_msg_to_mac(rrc, &rrc_msg);
}
@@ -776,6 +778,8 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc,
nr_mac_rrc_config_cg_t *mac_msg = &rrc_msg.payload.config_cg;
mac_msg->cellGroupConfig = cellGroupConfig;
mac_msg->UE_NR_Capability = rrc->UECap.UE_NR_Capability;
mac_msg->hfn = rrc->current_hfn;
mac_msg->frame = rrc->current_frame;
nr_rrc_send_msg_to_mac(rrc, &rrc_msg);
}
@@ -824,7 +828,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, rrc->current_frame);
nr_decode_SI(SI_info, si, rrc, rrc->current_hfn, rrc->current_frame);
}
}
if (rec_1530->otherConfig) {
@@ -1182,6 +1186,8 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_
nr_mac_rrc_config_cg_t *config_cg = &rrc_msg.payload.config_cg;
config_cg->cellGroupConfig = cellGroupConfig;
config_cg->UE_NR_Capability = rrc->UECap.UE_NR_Capability;
config_cg->hfn = rrc->current_hfn;
config_cg->frame = rrc->current_frame;
nr_rrc_send_msg_to_mac(rrc, &rrc_msg);
}
}
@@ -1611,6 +1617,7 @@ static void nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc,
const uint8_t Sdu_len,
const uint8_t rsrq,
const uint8_t rsrp,
int hfn,
int frame,
int slot)
{
@@ -1650,7 +1657,7 @@ static void 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] %d:%d Decoding SI\n", rrc->ue_id, frame, slot);
NR_SystemInformation_t *si = bcch_message->message.choice.c1->choice.systemInformation;
nr_decode_SI(SI_info, si, rrc, frame);
nr_decode_SI(SI_info, si, rrc, hfn, frame);
break;
case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
default:
@@ -2640,6 +2647,7 @@ void *rrc_nrue(void *notUsed)
} break;
case NRRRC_FRAME_PROCESS:
rrc->current_hfn = NRRRC_FRAME_PROCESS(msg_p).hfn;
rrc->current_frame = NRRRC_FRAME_PROCESS(msg_p).frame;
LOG_D(NR_RRC, "Received %s: frame %d\n", ITTI_MSG_NAME(msg_p), rrc->current_frame);
// increase the timers every 10ms (every new frame)
@@ -2698,6 +2706,7 @@ void *rrc_nrue(void *notUsed)
bcch->sdu_size,
bcch->rsrq,
bcch->rsrp,
bcch->hfn,
bcch->frame,
bcch->slot);
break;
+1
View File
@@ -262,6 +262,7 @@ typedef struct NR_UE_RRC_INST_s {
// 5G-S-TMSI
uint64_t fiveG_S_TMSI;
// Frame timing received from MAC
int current_hfn;
int current_frame;
//Sidelink params
+1 -1
View File
@@ -73,7 +73,7 @@ int get_from_lte_ue_fd();
void nr_rrc_SI_timers(NR_UE_RRC_SI_INFO *SInfo);
void init_SI_timers(NR_UE_RRC_SI_INFO *SInfo);
void nr_ue_rrc_timer_trigger(int module_id, int frame, int gnb_id);
void nr_ue_rrc_timer_trigger(int module_id, int hfn, int frame, int gnb_id);
void handle_t300_expiry(NR_UE_RRC_INST_t *rrc);
void handle_t430_expiry(NR_UE_RRC_INST_t *rrc);
+40 -7
View File
@@ -99,21 +99,54 @@ void rxAddInput(const c16_t *input_sig,
double vel_sat_gnb = 0;
double acc_sat_gnb = 0;
if (channelDesc->modelid == SAT_LEO_TRANS) {
const double acc_sat_x = 0;
const double acc_sat_y = -w_sat * w_sat * radius_sat * sin(w_sat * t);
const double acc_sat_z = -w_sat * w_sat * radius_sat * cos(w_sat * t);
const double t5 = t + 5;
const double t10 = t + 10;
const double pos_gnb_x = 0;
const double pos_gnb_y = 0;
const double pos_gnb_z = radius_earth;
const double pos_sat_x5 = 0;
const double pos_sat_y5 = radius_sat * sin(w_sat * t5);
const double pos_sat_z5 = radius_sat * cos(w_sat * t5);
const double pos_sat_x10 = 0;
const double pos_sat_y10 = radius_sat * sin(w_sat * t10);
const double pos_sat_z10 = radius_sat * cos(w_sat * t10);
const double dir_sat_gnb_x = pos_gnb_x - pos_sat_x;
const double dir_sat_gnb_y = pos_gnb_y - pos_sat_y;
const double dir_sat_gnb_z = pos_gnb_z - pos_sat_z;
const double dir_sat_gnb_x5 = pos_gnb_x - pos_sat_x5;
const double dir_sat_gnb_y5 = pos_gnb_y - pos_sat_y5;
const double dir_sat_gnb_z5 = pos_gnb_z - pos_sat_z5;
const double dir_sat_gnb_x10 = pos_gnb_x - pos_sat_x10;
const double dir_sat_gnb_y10 = pos_gnb_y - pos_sat_y10;
const double dir_sat_gnb_z10 = pos_gnb_z - pos_sat_z10;
dist_sat_gnb = sqrt(dir_sat_gnb_x * dir_sat_gnb_x + dir_sat_gnb_y * dir_sat_gnb_y + dir_sat_gnb_z * dir_sat_gnb_z);
vel_sat_gnb = (vel_sat_x * dir_sat_gnb_x + vel_sat_y * dir_sat_gnb_y + vel_sat_z * dir_sat_gnb_z) / dist_sat_gnb;
acc_sat_gnb = (acc_sat_x * dir_sat_gnb_x + acc_sat_y * dir_sat_gnb_y + acc_sat_z * dir_sat_gnb_z) / dist_sat_gnb;
const double dist_sat_gnb5 = sqrt(dir_sat_gnb_x5 * dir_sat_gnb_x5 + dir_sat_gnb_y5 * dir_sat_gnb_y5 + dir_sat_gnb_z5 * dir_sat_gnb_z5);
const double dist_sat_gnb10 = sqrt(dir_sat_gnb_x10 * dir_sat_gnb_x10 + dir_sat_gnb_y10 * dir_sat_gnb_y10 + dir_sat_gnb_z10 * dir_sat_gnb_z10);
// calculate vel_sat_gnb and acc_sat_gnb, so the delay is correct for epoch_time, epoch_time + 5 seconds and epoch_time + 10 seconds
//
// dist_sat_gnb = dist_sat_gnb + 0 * vel_sat_gnb + 0 * acc_sat_gnb;
// dist_sat_gnb5 = dist_sat_gnb + 5 * vel_sat_gnb + 25 * acc_sat_gnb;
// dist_sat_gnb10 = dist_sat_gnb + 10 * vel_sat_gnb + 100 * acc_sat_gnb;
//
// vel_sat_gnb = (dist_sat_gnb5 - dist_sat_gnb) / 5 - 5 * acc_sat_gnb;
// acc_sat_gnb = (dist_sat_gnb10 - dist_sat_gnb) / 100 - vel_sat_gnb / 10;
//
// vel_sat_gnb = (dist_sat_gnb5 - dist_sat_gnb) / 5 - 5 * ((dist_sat_gnb10 - dist_sat_gnb) / 100 - vel_sat_gnb / 10);
vel_sat_gnb = 2 * (dist_sat_gnb5 - dist_sat_gnb) / 5 - (dist_sat_gnb10 - dist_sat_gnb) / 10;
acc_sat_gnb = (dist_sat_gnb10 - dist_sat_gnb) / 50 - (dist_sat_gnb5 - dist_sat_gnb) / 25;
// in the moment when the satellite disappears behind the horizon acc_sat_gnb might become negative, what is invalid
if (acc_sat_gnb < 0)
acc_sat_gnb = 0;
}
const double prop_delay = (dist_ue_sat + dist_sat_gnb) / c;
@@ -128,7 +161,7 @@ void rxAddInput(const c16_t *input_sig,
last_TS = TS;
LOG_I(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z);
LOG_I(HW, "Uplink delay %f ms, Doppler shift UE->SAT %f kHz\n", prop_delay * 1000, f_Doppler_shift_ue_sat / 1000);
LOG_I(HW, "Satellite velocity towards gNB: %f m/s, acceleration towards gNB: %f m/s²\n", vel_sat_gnb, acc_sat_gnb);
LOG_I(HW, "Satellite velocity towards gNB: %f m/s, acceleration towards gNB: %f m/s²\n", -vel_sat_gnb, acc_sat_gnb);
}
const int samples_per_subframe = channelDesc->sampling_rate / 1000;
@@ -138,7 +171,7 @@ void rxAddInput(const c16_t *input_sig,
.sfn = (abs_subframe / 10 + 1) % 1024,
.subframe = 0,
.delay = 2 * dist_sat_gnb / (c * 4.072e-9),
.drift = 2 * -vel_sat_gnb / (c * 0.2e-9),
.drift = 2 * vel_sat_gnb / (c * 0.2e-9),
.accel = 2 * acc_sat_gnb / (c * 0.2e-10),
.position.X = pos_sat_x / 1.3,
.position.Y = pos_sat_y / 1.3,