Merge remote-tracking branch 'origin/ntn_continuous_sib19_updates' into integration_2025_w27 (!3398)
continuously update SIB19 information for rfsim NTN LEO scenarios Contains mainly these changes: - gNB: add function nr_update_sib19() allowing to update SIB19 information - rfsimulator: update SIB19 contents every frame for LEO channel simulations - NR UE: improve initial timing advance calculation from SIB19 Before, we only considered ta_Common_r17 and the SAT position from SIB19 to compute the initial timing advance value. This is good enough if the satellite does not move too fast (e.g. GEO satellite). Now we also consider ta_CommonDrift_r17, ta_CommonDriftVariant_r17 and the SAT velocity together with the epoch time from SIB19. This improves the accuracy of the initial TA computation, esp. for LEO satellite scenarios.
This commit is contained in:
+36
-17
@@ -908,7 +908,8 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
|
||||
static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
int slot_nr,
|
||||
int frame_rx,
|
||||
int slot_rx,
|
||||
int *duration_rx_to_tx,
|
||||
int *timing_advance,
|
||||
int *ntn_koffset)
|
||||
@@ -916,22 +917,43 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
|
||||
if (UE->ntn_config_message->update) {
|
||||
UE->ntn_config_message->update = false;
|
||||
|
||||
double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms;
|
||||
UE->timing_advance = fp->samples_per_subframe * total_ta_ms;
|
||||
const int mu = fp->numerology_index;
|
||||
const int koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset;
|
||||
|
||||
int mu = fp->numerology_index;
|
||||
int koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset;
|
||||
if (*ntn_koffset != koffset) {
|
||||
*duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
|
||||
*timing_advance += fp->get_samples_slot_timestamp(slot_nr, fp, (koffset - *ntn_koffset) << mu);
|
||||
*ntn_koffset = koffset;
|
||||
}
|
||||
*duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
|
||||
if (koffset > *ntn_koffset)
|
||||
*timing_advance += fp->get_samples_slot_timestamp(slot_rx, fp, (koffset - *ntn_koffset) << mu);
|
||||
else if (koffset < *ntn_koffset)
|
||||
*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), ntn_total_time_advance_ms = %f ms (%d samples)\n",
|
||||
"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);
|
||||
}
|
||||
}
|
||||
@@ -1088,9 +1110,6 @@ void *UE_thread(void *arg)
|
||||
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
|
||||
LOG_D(PHY, "max_pos_acc = %d, shiftForNextFrame = %d\n", UE->max_pos_acc, 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;
|
||||
// read in first symbol
|
||||
AssertFatal(fp->ofdm_symbol_size + fp->nb_prefix_samples0
|
||||
== UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
@@ -1215,8 +1234,8 @@ void *UE_thread(void *arg)
|
||||
UE->N_TA_offset = new_N_TA_offset;
|
||||
}
|
||||
|
||||
if (curMsg.proc.nr_slot_tx == 0)
|
||||
nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_tx, curMsg.proc.gNB_id);
|
||||
if (curMsg.proc.nr_slot_rx == 0)
|
||||
nr_ue_rrc_timer_trigger(UE->Mod_id, 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);
|
||||
@@ -1232,7 +1251,7 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
// apply new NTN timing information
|
||||
apply_ntn_config(UE, fp, slot_nr, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
|
||||
apply_ntn_config(UE, fp, 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
|
||||
|
||||
@@ -41,16 +41,16 @@
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
// clang-format off
|
||||
#define POSITION_CONFIG_PARAMS_DEF { \
|
||||
{CONFIG_STRING_POSITION_X, HELP_STRING_POSITION, 0, .dblptr=&(position->positionX), .defuintval=0, TYPE_DOUBLE, 0}, \
|
||||
{CONFIG_STRING_POSITION_Y, HELP_STRING_POSITION, 0, .dblptr=&(position->positionY), .defuintval=0, TYPE_DOUBLE, 0}, \
|
||||
{CONFIG_STRING_POSITION_Z, HELP_STRING_POSITION, 0, .dblptr=&(position->positionZ), .defuintval=0, TYPE_DOUBLE, 0} \
|
||||
{CONFIG_STRING_POSITION_X, HELP_STRING_POSITION, 0, .dblptr=&(position->X), .defuintval=0, TYPE_DOUBLE, 0}, \
|
||||
{CONFIG_STRING_POSITION_Y, HELP_STRING_POSITION, 0, .dblptr=&(position->Y), .defuintval=0, TYPE_DOUBLE, 0}, \
|
||||
{CONFIG_STRING_POSITION_Z, HELP_STRING_POSITION, 0, .dblptr=&(position->Z), .defuintval=0, TYPE_DOUBLE, 0} \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
typedef struct position {
|
||||
double positionX;
|
||||
double positionY;
|
||||
double positionZ;
|
||||
double X;
|
||||
double Y;
|
||||
double Z;
|
||||
} position_t;
|
||||
|
||||
void get_position_coordinates(int Mod_id, position_t *position);
|
||||
|
||||
@@ -557,16 +557,18 @@ typedef struct {
|
||||
} fapi_nr_ta_command_pdu;
|
||||
|
||||
typedef struct {
|
||||
// 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 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;
|
||||
int epoch_sfn;
|
||||
int epoch_subframe;
|
||||
|
||||
// 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 {
|
||||
|
||||
@@ -352,10 +352,12 @@ 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_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.cell_specific_k_offset = ntn_params_message->cell_specific_k_offset;
|
||||
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.ntn_ta_commondrift = ntn_params_message->ntn_ta_commondrift;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,3 +60,5 @@ MESSAGE_DEF(NR_RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacCcch
|
||||
MESSAGE_DEF(NR_RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacBcchDataInd, nr_rrc_mac_bcch_data_ind)
|
||||
MESSAGE_DEF(NR_RRC_MAC_SBCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSBcchDataInd, nr_rrc_mac_sbcch_data_ind)
|
||||
|
||||
// Message to GNB_APP to update SIB19 satellite position information
|
||||
MESSAGE_DEF(GNB_SAT_POSITION_UPDATE, MESSAGE_PRIORITY_MED, gnb_sat_position_update_t, gnb_sat_position_update)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <LTE_DRX-Config.h>
|
||||
#include "OCTET_STRING.h"
|
||||
#include "NR_MAC_gNB/mac_config.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
// Defines to access message fields.
|
||||
@@ -61,6 +62,8 @@
|
||||
|
||||
#define RRC_MAC_DRX_CONFIG_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_drx_config_req
|
||||
|
||||
#define GNB_SAT_POSITION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.gnb_sat_position_update
|
||||
|
||||
// Some constants from "LAYER2/MAC/defs.h"
|
||||
#define BCCH_SDU_SIZE (512)
|
||||
#define BCCH_SDU_MBMS_SIZE (512)
|
||||
|
||||
@@ -212,6 +212,11 @@ void *gNB_app_task(void *args_p)
|
||||
LOG_I(GNB_APP, " Received %s: timer_id %ld\n", msg_name, TIMER_HAS_EXPIRED(msg_p).timer_id);
|
||||
break;
|
||||
|
||||
case GNB_SAT_POSITION_UPDATE:
|
||||
LOG_I(GNB_APP, " Received GNB_SAT_POSITION_UPDATE message\n");
|
||||
nr_update_sib19(&GNB_SAT_POSITION_UPDATE(msg_p));
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(GNB_APP, "Received unexpected message %s\n", msg_name);
|
||||
break;
|
||||
|
||||
@@ -221,11 +221,18 @@ 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_Common_r17 = -1;
|
||||
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 =
|
||||
calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17));
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionX_r17 = LONG_MAX;
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionY_r17 = LONG_MAX;
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionZ_r17 = LONG_MAX;
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVX_r17 = LONG_MAX;
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVY_r17 = LONG_MAX;
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVZ_r17 = LONG_MAX;
|
||||
}
|
||||
void prepare_msgA_scc(NR_ServingCellConfigCommon_t *scc) {
|
||||
NR_BWP_UplinkCommon_t *initialUplinkBWP = scc->uplinkConfigCommon->initialUplinkBWP;
|
||||
|
||||
@@ -267,59 +267,104 @@ 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 double calculate_ue_sat_ta(const position_t *position_params, NR_PositionVelocity_r17_t *sat_pos)
|
||||
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)
|
||||
{
|
||||
// get UE position coordinates
|
||||
double posx = position_params->positionX;
|
||||
double posy = position_params->positionY;
|
||||
double posz = position_params->positionZ;
|
||||
const position_t pos_ue = *position_params;
|
||||
|
||||
// get sat position coordinates
|
||||
double posx_0 = (double)sat_pos->positionX_r17 * 1.3;
|
||||
double posy_0 = (double)sat_pos->positionY_r17 * 1.3;
|
||||
double posz_0 = (double)sat_pos->positionZ_r17 * 1.3;
|
||||
const position_t pos_sat = {sat_pos->positionX_r17 * 1.3, sat_pos->positionY_r17 * 1.3, sat_pos->positionZ_r17 * 1.3};
|
||||
|
||||
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;
|
||||
// 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};
|
||||
|
||||
return ta_ms;
|
||||
// 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;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// populate ntn_ta structure from mac
|
||||
void configure_ntn_ta(module_id_t module_id, ntn_timing_advance_componets_t *ntn_ta, NR_NTN_Config_r17_t *ntn_Config_r17)
|
||||
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)
|
||||
{
|
||||
if (!ntn_Config_r17)
|
||||
return;
|
||||
|
||||
position_t position_params = {0};
|
||||
get_position_coordinates(module_id, &position_params);
|
||||
|
||||
// if ephemerisInfo_r17 present in SIB19
|
||||
NR_EphemerisInfo_r17_t *ephemeris_info = ntn_Config_r17->ephemerisInfo_r17;
|
||||
// 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");
|
||||
ntn_ta->epoch_sfn = epoch_time_r17->sfn_r17;
|
||||
ntn_ta->epoch_subframe = epoch_time_r17->subFrameNR_r17;
|
||||
|
||||
// handle ephemerisInfo_r17
|
||||
const NR_EphemerisInfo_r17_t *ephemeris_info = ntn_Config_r17->ephemerisInfo_r17;
|
||||
if (ephemeris_info) {
|
||||
NR_PositionVelocity_r17_t *position_velocity = ephemeris_info->choice.positionVelocity_r17;
|
||||
if (position_velocity
|
||||
&& (position_velocity->positionX_r17 != 0 || position_velocity->positionY_r17 != 0
|
||||
|| position_velocity->positionZ_r17 != 0)) {
|
||||
ntn_ta->N_UE_TA_adj = calculate_ue_sat_ta(&position_params, position_velocity);
|
||||
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);
|
||||
} 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;
|
||||
}
|
||||
} else { // Need R - Release if not present
|
||||
ntn_ta->N_UE_TA_adj = 0;
|
||||
ntn_ta->N_UE_TA_drift = 0;
|
||||
}
|
||||
// if cellSpecificKoffset_r17 is present
|
||||
if (ntn_Config_r17->cellSpecificKoffset_r17) {
|
||||
|
||||
// handle cellSpecificKoffset_r17
|
||||
if (ntn_Config_r17->cellSpecificKoffset_r17)
|
||||
ntn_ta->cell_specific_k_offset = *ntn_Config_r17->cellSpecificKoffset_r17;
|
||||
}
|
||||
// Check if ta_Info_r17 is present and convert directly ta_Common_r17 (is in units of 4.072e-3 µs)
|
||||
else // Need R - Release if not present
|
||||
ntn_ta->cell_specific_k_offset = 0;
|
||||
|
||||
// Check if ta_Info_r17 is present and convert the time units
|
||||
if (ntn_Config_r17->ta_Info_r17) {
|
||||
// ta_Common_r17 (is in units of 4.072e-3 µs)
|
||||
ntn_ta->N_common_ta_adj = ntn_Config_r17->ta_Info_r17->ta_Common_r17 * 4.072e-6;
|
||||
// ta_CommonDrift_r17 (is in units of 0.2e-3 µs/s)
|
||||
if (ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17)
|
||||
ntn_ta->ntn_ta_commondrift = *ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 * 0.2e-3;
|
||||
ntn_ta->N_common_ta_drift = *ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 * 0.2e-3;
|
||||
else // Need R - Release if not present
|
||||
ntn_ta->N_common_ta_drift = 0;
|
||||
// ta_CommonDriftVariant_r17 (is in units of 0.2e-4 µs/s²)
|
||||
if (ntn_Config_r17->ta_Info_r17->ta_CommonDriftVariant_r17)
|
||||
ntn_ta->N_common_ta_drift_variant = *ntn_Config_r17->ta_Info_r17->ta_CommonDriftVariant_r17 * 0.2e-4;
|
||||
else // Need R - Release if not present
|
||||
ntn_ta->N_common_ta_drift_variant = 0;
|
||||
} else { // Need R - Release if not present
|
||||
ntn_ta->N_common_ta_adj = 0;
|
||||
ntn_ta->N_common_ta_drift = 0;
|
||||
ntn_ta->N_common_ta_drift_variant = 0;
|
||||
}
|
||||
|
||||
ntn_ta->ntn_params_changed = true;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"SIB19 Rxd. k_offset:%ld, N_Common_Ta:%f,drift:%f,N_UE_TA:%f \n",
|
||||
"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\n",
|
||||
ntn_ta->epoch_sfn,
|
||||
ntn_ta->epoch_subframe,
|
||||
ntn_ta->cell_specific_k_offset,
|
||||
ntn_ta->N_common_ta_adj,
|
||||
ntn_ta->ntn_ta_commondrift,
|
||||
ntn_ta->N_UE_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);
|
||||
}
|
||||
|
||||
static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t *scc, int cc_idP)
|
||||
@@ -1875,10 +1920,8 @@ 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
|
||||
NR_NTN_Config_r17_t *ntn_Config_r17 = mac->sc_info.ntn_Config_r17;
|
||||
UPDATE_IE(ntn_Config_r17, sib19->ntn_Config_r17, NR_NTN_Config_r17_t);
|
||||
|
||||
configure_ntn_ta(mac->ue_id, &mac->ntn_ta, ntn_Config_r17);
|
||||
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);
|
||||
}
|
||||
if (mac->state == UE_RECEIVING_SIB && can_start_ra)
|
||||
mac->state = UE_PERFORMING_RA;
|
||||
|
||||
@@ -528,12 +528,19 @@ typedef struct {
|
||||
} si_schedInfo_t;
|
||||
|
||||
typedef struct ntn_timing_advance_components {
|
||||
int epoch_sfn;
|
||||
int epoch_subframe;
|
||||
|
||||
// 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 common ta in µs/s
|
||||
double ntn_ta_commondrift;
|
||||
// drift rate of N_UE_TA in µs/s
|
||||
double N_UE_TA_drift;
|
||||
// cell scheduling offset expressed in terms of 15kHz SCS
|
||||
long cell_specific_k_offset;
|
||||
|
||||
@@ -652,15 +659,20 @@ static inline int GET_NTN_UE_K_OFFSET(const ntn_timing_advance_componets_t *ntn_
|
||||
return (int)ntn_ta->cell_specific_k_offset << scs;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *ntn_ta, int scs)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
#endif /*__LAYER2_MAC_DEFS_H__ */
|
||||
|
||||
@@ -818,7 +818,7 @@ static void setup_ra_response_window(RA_config_t *ra,
|
||||
|
||||
int ta_Common_slots = 0;
|
||||
if (ntn_Config_r17) {
|
||||
const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(ntn_ta);
|
||||
const double ta_Common_ms = get_total_TA_ms(ntn_ta);
|
||||
ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_frame / 10);
|
||||
}
|
||||
|
||||
@@ -1066,7 +1066,7 @@ 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_COMPLETE_TIME_ADVANCE_MS(&mac->ntn_ta);
|
||||
const double ta_Common_ms = get_total_TA_ms(&mac->ntn_ta);
|
||||
const int slots_per_ms = mac->frame_structure.numb_slots_frame / 10;
|
||||
|
||||
// start contention resolution timer
|
||||
|
||||
@@ -2848,11 +2848,14 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
|
||||
static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
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_sfn = mac->ntn_ta.epoch_sfn;
|
||||
ntn_config_command_pdu->epoch_subframe = mac->ntn_ta.epoch_subframe;
|
||||
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;
|
||||
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 = mac->ntn_ta.N_common_ta_drift_variant;
|
||||
|
||||
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_NTN_CONFIG_PARAMS;
|
||||
dl_config->number_pdus += 1;
|
||||
}
|
||||
|
||||
@@ -927,6 +927,96 @@ bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nr_update_sib19(const gnb_sat_position_update_t *sat_position)
|
||||
{
|
||||
gNB_MAC_INST *nrmac = RC.nrmac[0];
|
||||
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
|
||||
if (!scc || !scc->ext2 || !scc->ext2->ntn_Config_r17)
|
||||
return false;
|
||||
|
||||
const vector_t *pos = &sat_position->position;
|
||||
const vector_t *vel = &sat_position->velocity;
|
||||
|
||||
LOG_D(NR_MAC, "SFN = %d, SubFrame = %d\n", sat_position->sfn, sat_position->subframe);
|
||||
LOG_D(NR_MAC, "TA_Common: value %d, %f msec\n", sat_position->delay, sat_position->delay * 4.072e-6);
|
||||
LOG_D(NR_MAC, "TA_CommonDrift: value %d, = %f µsec/sec\n", sat_position->drift, sat_position->drift * 0.2e-3);
|
||||
LOG_D(NR_MAC, "TA_CommonDriftVariant: value %d, %f µsec/sec^2\n", sat_position->accel, sat_position->accel * 0.2e-4);
|
||||
LOG_D(NR_MAC, "SAT Position: values %d/%d/%d, %.3f/%3f/%3f metres in X/Y/Z\n", pos->X, pos->Y, pos->Z, pos->X * 1.3, pos->Y * 1.3, pos->Z * 1.3);
|
||||
LOG_D(NR_MAC, "SAT Velocity: values %d/%d/%d, %.3f/%3f/%3f m/s in X/Y/Z\n", vel->X, vel->Y, vel->Z, vel->X * 0.06, vel->Y * 0.06, vel->Z * 0.06);
|
||||
|
||||
NR_SCHED_LOCK(&nrmac->sched_lock);
|
||||
|
||||
if (!scc->ext2->ntn_Config_r17->epochTime_r17)
|
||||
scc->ext2->ntn_Config_r17->epochTime_r17 = calloc (1, sizeof(*scc->ext2->ntn_Config_r17->epochTime_r17));
|
||||
|
||||
NR_EpochTime_r17_t *epoch_time_r17 = scc->ext2->ntn_Config_r17->epochTime_r17;
|
||||
epoch_time_r17->sfn_r17 = sat_position->sfn;
|
||||
epoch_time_r17->subFrameNR_r17 = sat_position->subframe;
|
||||
|
||||
if (!scc->ext2->ntn_Config_r17->ta_Info_r17)
|
||||
scc->ext2->ntn_Config_r17->ta_Info_r17 = calloc(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17));
|
||||
|
||||
NR_TA_Info_r17_t *sib19_ta_info = scc->ext2->ntn_Config_r17->ta_Info_r17;
|
||||
|
||||
// SIB19 provides Round trip delay on feeder link (between gNB and SAT).
|
||||
sib19_ta_info->ta_Common_r17 = sat_position->delay;
|
||||
|
||||
if (sat_position->drift) {
|
||||
if (!sib19_ta_info->ta_CommonDrift_r17)
|
||||
sib19_ta_info->ta_CommonDrift_r17 = calloc(1, sizeof(*sib19_ta_info->ta_CommonDrift_r17));
|
||||
*sib19_ta_info->ta_CommonDrift_r17 = sat_position->drift;
|
||||
} else
|
||||
free_and_zero(sib19_ta_info->ta_CommonDrift_r17);
|
||||
|
||||
if (sat_position->accel) {
|
||||
if (!sib19_ta_info->ta_CommonDriftVariant_r17)
|
||||
sib19_ta_info->ta_CommonDriftVariant_r17 = calloc(1, sizeof(*sib19_ta_info->ta_CommonDriftVariant_r17));
|
||||
*sib19_ta_info->ta_CommonDriftVariant_r17 = sat_position->accel;
|
||||
} else
|
||||
free_and_zero(sib19_ta_info->ta_CommonDriftVariant_r17);
|
||||
|
||||
// Currently PositionVelocity is supported and not yet the OrbitalParams
|
||||
if (!scc->ext2->ntn_Config_r17->ephemerisInfo_r17) {
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = calloc(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17));
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_NOTHING;
|
||||
}
|
||||
if (scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present == NR_EphemerisInfo_r17_PR_orbital_r17) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_Orbital_r17, scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.orbital_r17);
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.orbital_r17 = NULL;
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_NOTHING;
|
||||
}
|
||||
if (!scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17)
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17 =
|
||||
calloc(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17));
|
||||
|
||||
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_positionVelocity_r17;
|
||||
NR_PositionVelocity_r17_t *sib19_PosVel = scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17;
|
||||
|
||||
sib19_PosVel->positionX_r17 = pos->X;
|
||||
sib19_PosVel->positionY_r17 = pos->Y;
|
||||
sib19_PosVel->positionZ_r17 = pos->Z;
|
||||
sib19_PosVel->velocityVX_r17 = vel->X;
|
||||
sib19_PosVel->velocityVY_r17 = vel->Y;
|
||||
sib19_PosVel->velocityVZ_r17 = vel->Z;
|
||||
|
||||
NR_SystemInformation_IEs_t *sysInfov17 = calloc(1, sizeof(*sysInfov17)); // for othersibs
|
||||
struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type_du = calloc(1, sizeof(*type_du));
|
||||
type_du->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700;
|
||||
NR_SIB19_r17_t *sib19 = get_SIB19_NR(cc->ServingCellConfigCommon);
|
||||
type_du->choice.sib19_v1700 = sib19;
|
||||
add_sib_to_systeminformation(sysInfov17, type_du);
|
||||
|
||||
cc->other_sib_bcch_length[1] = encode_sysinfo_ie(sysInfov17, cc->other_sib_bcch_pdu[1], sizeof(cc->other_sib_bcch_pdu[1]));
|
||||
AssertFatal(cc->other_sib_bcch_length[1] > 0, "could not encode SIB19\n");
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SystemInformation_IEs, sysInfov17);
|
||||
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void prepare_du_configuration_update(gNB_MAC_INST *mac,
|
||||
f1ap_served_cell_info_t *info,
|
||||
NR_BCCH_BCH_Message_t *mib,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __LAYER2_NR_MAC_CONFIG_H__
|
||||
#define __LAYER2_NR_MAC_CONFIG_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct vector_s {
|
||||
int X;
|
||||
int Y;
|
||||
int Z;
|
||||
} vector_t;
|
||||
|
||||
// Format similar to values sent in SIB19
|
||||
typedef struct gnb_sat_position_update_s {
|
||||
int sfn;
|
||||
int subframe;
|
||||
uint32_t delay;
|
||||
int drift;
|
||||
uint32_t accel;
|
||||
vector_t position;
|
||||
vector_t velocity;
|
||||
} gnb_sat_position_update_t;
|
||||
|
||||
bool nr_update_sib19(const gnb_sat_position_update_t *sat_position);
|
||||
|
||||
#endif /*__LAYER2_NR_MAC_CONFIG_H__*/
|
||||
@@ -88,6 +88,7 @@
|
||||
|
||||
/* MAC */
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "LAYER2/NR_MAC_gNB/mac_config.h"
|
||||
#include "NR_TAG.h"
|
||||
|
||||
/* Defs */
|
||||
|
||||
@@ -195,7 +195,7 @@ static void get_epochtime_from_sib19scheduling(NR_UE_RRC_SI_INFO *SI_info, int *
|
||||
int slot = slot_end_sib19_window % N;
|
||||
*subframe = ceil(slot / slots_per_subframe);
|
||||
|
||||
LOG_D(NR_RRC,
|
||||
LOG_I(NR_RRC,
|
||||
"Get EPOCHTIME: x:%d, N:%d, slot_endw:%d, frame:%d, subframe:%d , slot:%d\n",
|
||||
x,
|
||||
N,
|
||||
@@ -228,7 +228,7 @@ static int eval_epoch_time(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntnc
|
||||
// after the frame where the message indicating the epochTime is received
|
||||
// i.e. Epochframe can be present or future SFN
|
||||
diff_frames = (epoch_frame - frame + 1024) % 1024; // According to 38.331 Epochtime is defined for serving cell like this
|
||||
LOG_D(NR_RRC, "Epoch frame %d, ahead by %d frames\n", epoch_frame, diff_frames);
|
||||
LOG_I(NR_RRC, "Epoch frame %d, ahead by %d frames\n", epoch_frame, diff_frames);
|
||||
return diff_frames;
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ static int get_ntn_timervalues(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *
|
||||
int expire_before_ms = ((val430 >= 120) ? 10000 : 2000);
|
||||
int diff = *val430_ms - expire_before_ms;
|
||||
int sib19_timer_ms = (diff > 0) ? diff : ((*val430_ms - sib19_periodicity_ms) > 0) ? (*val430_ms - sib19_periodicity_ms) : 0;
|
||||
LOG_D(NR_RRC, "val430:%d s, T430:%d ms, sib19_timer:%d ms\n", val430, *val430_ms, sib19_timer_ms);
|
||||
LOG_I(NR_RRC, "val430:%d s, T430:%d ms, sib19_timer:%d ms\n", val430, *val430_ms, sib19_timer_ms);
|
||||
return sib19_timer_ms;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <complex.h>
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include <openair1/SIMULATION/TOOLS/sim.h>
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_config.h"
|
||||
#include "rfsimulator.h"
|
||||
|
||||
/*
|
||||
@@ -95,7 +96,13 @@ void rxAddInput(const c16_t *input_sig,
|
||||
const double vel_ue_sat = (vel_sat_x * dir_ue_sat_x + vel_sat_y * dir_ue_sat_y + vel_sat_z * dir_ue_sat_z) / dist_ue_sat;
|
||||
|
||||
double dist_sat_gnb = 0;
|
||||
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 pos_gnb_x = 0;
|
||||
const double pos_gnb_y = 0;
|
||||
const double pos_gnb_z = radius_earth;
|
||||
@@ -105,6 +112,8 @@ void rxAddInput(const c16_t *input_sig,
|
||||
const double dir_sat_gnb_z = pos_gnb_z - pos_sat_z;
|
||||
|
||||
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 prop_delay = (dist_ue_sat + dist_sat_gnb) / c;
|
||||
@@ -117,8 +126,33 @@ void rxAddInput(const c16_t *input_sig,
|
||||
|
||||
if(TS - last_TS >= channelDesc->sampling_rate) {
|
||||
last_TS = TS;
|
||||
LOG_D(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_D(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 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);
|
||||
}
|
||||
|
||||
const int samples_per_subframe = channelDesc->sampling_rate / 1000;
|
||||
const int abs_subframe = TS / samples_per_subframe;
|
||||
if (abs_subframe % 10 == 0) { // update SIB19 information for the next frame
|
||||
gnb_sat_position_update_t sat_position = {
|
||||
.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),
|
||||
.accel = 2 * acc_sat_gnb / (c * 0.2e-10),
|
||||
.position.X = pos_sat_x / 1.3,
|
||||
.position.Y = pos_sat_y / 1.3,
|
||||
.position.Z = pos_sat_z / 1.3,
|
||||
.velocity.X = vel_sat_x / 0.06,
|
||||
.velocity.Y = vel_sat_y / 0.06,
|
||||
.velocity.Z = vel_sat_z / 0.06,
|
||||
};
|
||||
// Here we update the SIB19 information directly in the gNB MAC layer.
|
||||
// Without rf-simulaor, in a real system or with an external channel emulator, the SIB19 updates would
|
||||
// be provided via an external interface (e.g. O-RAN E2 interface) to the MAC layer (in the O-DU).
|
||||
// We do it directly here, because we can, and an E2 Interface implementation (e.g using FlexRIC)
|
||||
// would pull too many dependencies into rf-simulator, just for updating SIB19.
|
||||
nr_update_sib19(&sat_position);
|
||||
}
|
||||
} else {
|
||||
const double dir_sat_ue_x = pos_ue_x - pos_sat_x;
|
||||
@@ -151,8 +185,8 @@ void rxAddInput(const c16_t *input_sig,
|
||||
|
||||
if(TS - last_TS >= channelDesc->sampling_rate) {
|
||||
last_TS = TS;
|
||||
LOG_D(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_D(HW, "Downlink delay %f ms, Doppler shift SAT->UE %f kHz\n", prop_delay * 1000, f_Doppler_shift_sat_ue / 1000);
|
||||
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, "Downlink delay %f ms, Doppler shift SAT->UE %f kHz\n", prop_delay * 1000, f_Doppler_shift_sat_ue / 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user