Commit 0b78a18d authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/sib19-ue-utilization' into integration_2024_w50 (!3019)

SIB19 utilization on UE

Following SIB19 initialization and scheduling on gNB (!2899 - merged)
and Receive SIB19 on nrUE (!2920 - merged), this merge request aims to
introduce the actual use of the SIB19 provided parameters by gNB in UE.
Changes needed for utilization include: initialization of position
coordinates parameters for UE (which are needed to calculate propagation
delay between UE and SAT), propagation delay calculations and timing
advance adjusts. Moreover, this change removes the now unused arguments
for ntn_koffset, ntn_ta_common and ntn_ta_commondrift
parents a8a79469 a049c53e
......@@ -1943,6 +1943,7 @@ target_link_libraries(lte-softmodem PRIVATE
target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt sctp)
target_link_libraries(lte-softmodem PRIVATE ${T_LIB})
target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(lte-softmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES} ${lapack_LIBRARIES})
if(E2_AGENT)
target_compile_definitions(lte-softmodem PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
......@@ -1998,6 +1999,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE
target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt sctp)
target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB})
target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(lte-uesoftmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES} ${lapack_LIBRARIES})
# force the generation of ASN.1 so that we don't need to wait during the build
target_link_libraries(lte-uesoftmodem PRIVATE
......@@ -2080,6 +2082,7 @@ add_executable(nr-uesoftmodem
${rrc_h}
${s1ap_h}
${OPENAIR_DIR}/executables/nr-uesoftmodem.c
${OPENAIR_DIR}/executables/position_interface.c
${OPENAIR_DIR}/executables/nr-ue.c
${OPENAIR_DIR}/executables/softmodem-common.c
${OPENAIR_DIR}/radio/COMMON/common_lib.c
......
......@@ -148,6 +148,13 @@ gNBs =
#ext2
#ntn_Config_r17
cellSpecificKoffset_r17 = 478;
ta-Common-r17 = 29314900;
positionX-r17 = 0;
positionY-r17 = 0;
positionZ-r17 = 32433846;
velocityVX-r17 = 0;
velocityVY-r17 = 0;
velocityVZ-r17 = 0;
}
);
......
......@@ -6,6 +6,12 @@ uicc0 = {
nssai_sst=1;
}
position0 = {
x = 0.0;
y = 0.0;
z = 6377900.0;
}
thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
#/* configuration for channel modelisation */
......@@ -34,4 +40,4 @@ channelmod = {
ds_tdl = 0;
}
);
};
};
\ No newline at end of file
......@@ -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 --ntn-koffset 478 --ntn-ta-common 477.48 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
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
depends_on:
- oai-gnb
networks:
......
......@@ -41,6 +41,7 @@
#include "PHY/MODULATION/nr_modulation.h"
#include "instrumentation.h"
#include "common/utils/threadPool/notified_fifo.h"
#include "position_interface.h"
/*
* NR SLOT PROCESSING SEQUENCE
......@@ -155,7 +156,9 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id)
ue->if_inst = nr_ue_if_module_init(UE_id);
ue->dci_thres = 0;
ue->target_Nid_cell = -1;
ue->timing_advance = ue->frame_parms.samples_per_subframe * get_nrUE_params()->ntn_ta_common;
ue->ntn_config_message = CALLOC(1, sizeof(*ue->ntn_config_message));
ue->ntn_config_message->update = false;
// initialize all signal buffers
init_nr_ue_signal(ue, nb_connected_gNB);
......@@ -481,8 +484,23 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action)
}
}
int tmp = openair0_write_reorder(&UE->rfdevice, proc->timestamp_tx, txp, rxtxD->writeBlockSize, fp->nb_antennas_tx, flags);
AssertFatal(tmp == rxtxD->writeBlockSize, "");
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);
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, txp, dummyBlockSize, fp->nb_antennas_tx, flags);
AssertFatal(tmp == dummyBlockSize, "");
writeTimestamp += dummyBlockSize;
writeBlockSize -= dummyBlockSize;
}
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, txp, writeBlockSize, fp->nb_antennas_tx, flags);
AssertFatal(tmp == writeBlockSize, "");
for (int i = 0; i < fp->nb_antennas_tx; i++)
memset(txp[i], 0, writeBlockSize);
}
void processSlotTX(void *arg)
......@@ -548,8 +566,8 @@ void processSlotTX(void *arg)
int slots_per_frame = (UE->sl_mode == 2) ? UE->SL_UE_PHY_PARAMS.sl_frame_params.slots_per_frame
: UE->frame_parms.slots_per_frame;
int next_slot = (proc->nr_slot_tx + 1) % slots_per_frame;
dynamic_barrier_join(&UE->process_slot_tx_barriers[next_slot]);
int next_slot_and_frame = proc->nr_slot_tx + 1 + proc->nr_slot_tx_offset + proc->frame_tx * slots_per_frame;
dynamic_barrier_join(&UE->process_slot_tx_barriers[next_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
RU_write(rxtxD, sl_tx_action);
free(rxtxD);
TracyCZoneEnd(ctx);
......@@ -824,8 +842,7 @@ void *UE_thread(void *arg)
int absolute_slot = 0, decoded_frame_rx = MAX_FRAME_NUMBER - 1, trashed_frames = 0;
int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME];
int num_ind_fifo = nb_slot_frame;
for(int i = 0; i < num_ind_fifo; i++) {
for(int i = 0; i < NUM_PROCESS_SLOT_TX_BARRIERS; i++) {
dynamic_barrier_init(&UE->process_slot_tx_barriers[i]);
}
int shiftForNextFrame = 0;
......@@ -836,13 +853,21 @@ void *UE_thread(void *arg)
if (get_softmodem_params()->sync_ref && UE->sl_mode == 2) {
UE->is_synchronized = 1;
} else {
//warm up the RF board
//warm up the RF board
int64_t tmp;
for (int i = 0; i < 50; i++)
readFrame(UE, &tmp, true);
}
double ntn_ta_common = 0;
int ntn_koffset = 0;
int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX;
int nr_slot_tx_offset = 0;
bool update_ntn_system_information = false;
while (!oai_exit) {
nr_slot_tx_offset = 0;
if (syncRunning) {
notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf);
......@@ -913,7 +938,7 @@ void *UE_thread(void *arg)
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 = get_nrUE_params()->ntn_ta_commondrift * 1e-6 * fp->samples_per_frame / get_nrUE_params()->time_sync_I;
UE->max_pos_acc = mac->ntn_ta.ntn_ta_commondrift * 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
......@@ -940,7 +965,7 @@ void *UE_thread(void *arg)
}
// We have resynchronized, maybe after RF loss so we need to purge any existing context
memset(tx_wait_for_dlsch, 0, sizeof(tx_wait_for_dlsch));
for (int i = 0; i < num_ind_fifo; i++) {
for (int i = 0; i < NUM_PROCESS_SLOT_TX_BARRIERS; i++) {
dynamic_barrier_reset(&UE->process_slot_tx_barriers[i]);
}
continue;
......@@ -954,14 +979,30 @@ 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;
nr_slot_tx_offset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset;
}
int slot_nr = absolute_slot % nb_slot_frame;
nr_rxtx_thread_data_t curMsg = {0};
curMsg.UE=UE;
// update thread index for received subframe
curMsg.proc.nr_slot_rx = slot_nr;
curMsg.proc.nr_slot_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
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.frame_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);
......@@ -1014,11 +1055,11 @@ void *UE_thread(void *arg)
}
// use previous timing_advance value to compute writeTimestamp
const openair0_timestamp writeTimestamp = rx_timestamp + fp->get_samples_slot_timestamp(slot_nr, fp, DURATION_RX_TO_TX)
const openair0_timestamp writeTimestamp = rx_timestamp + fp->get_samples_slot_timestamp(slot_nr, fp, duration_rx_to_tx)
- firstSymSamp - UE->N_TA_offset - timing_advance;
// 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 writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply;
if (UE->timing_advance != timing_advance) {
writeBlockSize -= UE->timing_advance - timing_advance;
timing_advance = UE->timing_advance;
......@@ -1044,15 +1085,22 @@ void *UE_thread(void *arg)
curMsgTx->proc.timestamp_tx = writeTimestamp;
curMsgTx->UE = UE;
curMsgTx->stream_status = stream_status;
curMsgTx->proc.nr_slot_tx_offset = nr_slot_tx_offset;
int sync_to_previous_thread = stream_status == STREAM_STATUS_SYNCED ? 1 : 0;
int slot = curMsgTx->proc.nr_slot_tx;
dynamic_barrier_update(&UE->process_slot_tx_barriers[slot],
int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame;
dynamic_barrier_update(&UE->process_slot_tx_barriers[slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS],
tx_wait_for_dlsch[slot] + sync_to_previous_thread,
start_process_slot_tx,
curMsgTx);
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;
......
......@@ -129,9 +129,6 @@ int otg_enabled;
double cpuf;
uint32_t N_RB_DL = 106;
// NTN cellSpecificKoffset-r17, but in slots for DL SCS
unsigned int NTN_UE_Koffset = 0;
int create_tasks_nrue(uint32_t ue_nb) {
LOG_D(NR_RRC, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb);
itti_wait_ready(1);
......@@ -518,9 +515,6 @@ int main(int argc, char **argv)
}
}
// NTN cellSpecificKoffset-r17, but in slots for DL SCS
NTN_UE_Koffset = nrUE_params.ntn_koffset << PHY_vars_UE_g[0][0]->frame_parms.numerology_index;
init_openair0();
lock_memory_to_ram();
......
......@@ -12,9 +12,6 @@
#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_KOFFSET "NTN cellSpecificKoffset-r17 (number of slots for a given subcarrier spacing of 15 kHz)\n"
#define CONFIG_HLP_NTN_TA_COMMON "NTN ta-Common, but given in ms\n"
#define CONFIG_HLP_NTN_TA_COMMONDRIFT "NTN ta-CommonDrift, but 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"
......@@ -67,9 +64,6 @@
{"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-koffset", CONFIG_HLP_NTN_KOFFSET, 0, .uptr=&(nrUE_params.ntn_koffset), .defuintval=0, TYPE_UINT, 0}, \
{"ntn-ta-common", CONFIG_HLP_NTN_TA_COMMON, 0, .dblptr=&(nrUE_params.ntn_ta_common), .defdblval=0.0, TYPE_DOUBLE, 0}, \
{"ntn-ta-commondrift", CONFIG_HLP_NTN_TA_COMMONDRIFT, 0, .dblptr=&(nrUE_params.ntn_ta_commondrift), .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}, \
}
......@@ -94,9 +88,6 @@ typedef struct {
int ldpc_offload_flag;
double time_sync_P;
double time_sync_I;
unsigned int ntn_koffset;
double ntn_ta_common;
double ntn_ta_commondrift;
int autonomous_ta;
int agc;
char *usrp_args;
......
/*
* 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
*/
#include "position_interface.h"
extern uint16_t NB_UE_INST;
static void read_position_coordinates(char *sectionName, position_t *position)
{
paramdef_t position_params[] = POSITION_CONFIG_PARAMS_DEF;
int ret = config_get(config_get_if(), position_params, sizeofArray(position_params), sectionName);
AssertFatal(ret >= 0, "configuration couldn't be performed for position name: %s", sectionName);
}
void get_position_coordinates(int Mod_id, position_t *position)
{
AssertFatal(Mod_id < NB_UE_INST, "Mod_id must be less than NB_UE_INST. Mod_id:%d NB_UE_INST:%d", Mod_id, NB_UE_INST);
char positionName[64];
snprintf(positionName, sizeof(positionName), "position%d", Mod_id);
read_position_coordinates(positionName, position);
}
\ No newline at end of file
/*
* 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 __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"
#define CONFIG_STRING_POSITION_Z "z"
#define HELP_STRING_POSITION "Postion coordinates (x, y, z) config params"
// Position parameters config
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
/* position configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
// 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} \
}
// clang-format on
typedef struct position {
double positionX;
double positionY;
double positionZ;
} position_t;
void get_position_coordinates(int Mod_id, position_t *position);
#endif
......@@ -51,7 +51,9 @@
#define FAPI_NR_DL_CONFIG_TYPE_CSI_RS 0x06
#define FAPI_NR_DL_CONFIG_TYPE_CSI_IM 0x07
#define FAPI_NR_CONFIG_TA_COMMAND 0x08
#define FAPI_NR_DL_CONFIG_TYPES 0x08
#define FAPI_NR_DL_NTN_CONFIG_PARAMS 0x09
#define FAPI_NR_DL_CONFIG_TYPES 0x09
#define FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED 0x01
#define FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED 0x02
......
......@@ -555,6 +555,19 @@ typedef struct {
bool is_rar;
} fapi_nr_ta_command_pdu;
typedef struct {
// N_common_ta_adj represents common propagation delay received in SIB19 (ms)
double N_common_ta_adj;
// N_UE_TA_adj calculated propagation delay from UE and SAT (ms)
double N_UE_TA_adj;
// drift rate of common ta in µs/s
double ntn_ta_commondrift;
// cell scheduling offset expressed in terms of 15kHz SCS
long cell_specific_k_offset;
double ntn_total_time_advance_ms;
} fapi_nr_dl_ntn_config_command_pdu;
typedef struct {
uint8_t pdu_type;
union {
......@@ -563,6 +576,7 @@ typedef struct {
fapi_nr_dl_config_csirs_pdu csirs_config_pdu;
fapi_nr_dl_config_csiim_pdu csiim_config_pdu;
fapi_nr_ta_command_pdu ta_command_pdu;
fapi_nr_dl_ntn_config_command_pdu ntn_config_command_pdu;
};
} fapi_nr_dl_config_request_pdu_t;
......
......@@ -338,6 +338,8 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
free_and_zero(ue->prs_vars[idx]);
}
free_and_zero(ue->ntn_config_message);
sl_ue_free(ue);
}
......
......@@ -85,6 +85,15 @@
#define UNUSED(x) (void)x;
#define NUM_DL_ACTORS 4
// Set the number of barriers for processSlotTX to 512. This value has to be at least 483 for NTN where
// DL-to-UL offset is up to 483. The selected value is also half of the frame range so that
// (slot + frame * slots_per_frame) % NUM_PROCESS_SLOT_TX_BARRIERS is contiguous between the last slot of
// frame 1023 and first slot of frame 0
// e.g. in numerology 1:
// (19 + 1023 * 20) % 512 = 511
// (0 + 0 * 20) % 512 = 0
#define NUM_PROCESS_SLOT_TX_BARRIERS 512
#include "impl_defs_top.h"
#include "impl_defs_nr.h"
#include "time_meas.h"
......@@ -322,6 +331,11 @@ typedef struct UE_NR_SCAN_INFO_s {
int32_t freq_offset_Hz[3][10];
} UE_NR_SCAN_INFO_t;
typedef struct {
bool update;
fapi_nr_dl_ntn_config_command_pdu ntn_config_params;
} ntn_config_message_t;
/// Top-level PHY Data Structure for UE
typedef struct PHY_VARS_NR_UE_s {
/// \brief Module ID indicator for this instance
......@@ -394,7 +408,6 @@ typedef struct PHY_VARS_NR_UE_s {
uint8_t prs_active_gNBs;
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
NR_UL_UE_HARQ_t ul_harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES];
//Paging parameters
uint32_t IMSImod1024;
uint32_t PF;
......@@ -523,7 +536,7 @@ typedef struct PHY_VARS_NR_UE_s {
void *phy_sim_pdsch_dl_ch_estimates_ext;
uint8_t *phy_sim_dlsch_b;
dynamic_barrier_t process_slot_tx_barriers[NR_MAX_SLOTS_PER_FRAME];
dynamic_barrier_t process_slot_tx_barriers[NUM_PROCESS_SLOT_TX_BARRIERS];
// Gain change required for automation RX gain change
int adjust_rxgain;
......@@ -533,6 +546,9 @@ typedef struct PHY_VARS_NR_UE_s {
sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS;
Actor_t sync_actor;
Actor_t dl_actors[NUM_DL_ACTORS];
ntn_config_message_t* ntn_config_message;
} PHY_VARS_NR_UE;
typedef struct {
......@@ -540,6 +556,10 @@ typedef struct {
int gNB_id;
/// NR slot index within frame_tx [0 .. slots_per_frame - 1] to act upon for transmission
int nr_slot_tx;
/// NR slot index tx offset to resume
/// in case of NTN, tx_offset can be changed dynamically via SIB19
/// we need to notify the right tx thread slot based on TX offset change
int nr_slot_tx_offset;
int rx_slot_type;
/// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission
int nr_slot_rx;
......
......@@ -276,20 +276,6 @@
/* - between reception of un uplink grant and its related transmission (k2) */
#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3)
/* When the OAI UE receives RX slot N, it starts sending TX slot N+DURATION_RX_TO_TX.
* Therefore DURATION_RX_TO_TX must not be larger than the minimum k1 and k2 values (NR_UE_CAPABILITY_SLOT_RX_TO_TX).
* In case of NTN, the propagation delay is so large, that the TX slot needs to be transmitted far in advance.
* Therefore, the NTN_UE_Koffset is added to DURATION_RX_TO_TX.
*
* Note: currently, the UE requires this to be a constant.
* But in case of NTN, Koffset is only known after receiving SIB19.
* Therefore, support should be added to allow changing DURATION_RX_TO_TX on reception of SIB19 (via FAPI-like interface).
* E.g. no transmission before successful reception of SIB19, and re-sync with disabled transmission if Koffset changes.
* When this has been implemented, the global variable NTN_UE_Koffset should be removed, too.
*/
extern unsigned int NTN_UE_Koffset;
#define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX + NTN_UE_Koffset)
#define NR_MAX_ULSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 6.1 UE procedure for receiving the physical uplink shared channel */
#define NR_MAX_DLSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 5.1 UE procedure for receiving the physical downlink shared channel */
#endif
......@@ -317,6 +303,6 @@ typedef struct {
#include "common/openairinterface5g_limits.h"
#include "assertions.h"
#endif //__PHY_IMPLEMENTATION_DEFS_H__
/**@}
#endif //__PHY_IMPLEMENTATION_DEFS_H__
/**@}
*/
......@@ -326,6 +326,19 @@ static void configure_dlsch(NR_UE_DLSCH_t *dlsch0,
}
}
static void configure_ntn_params(PHY_VARS_NR_UE *ue, fapi_nr_dl_ntn_config_command_pdu* ntn_params_message)
{
if (!ue->ntn_config_message) {
ue->ntn_config_message = CALLOC(1, sizeof(*ue->ntn_config_message));
}
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->update = true;
}
static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_command_pdu)
{
/* Time Alignment procedure
......@@ -451,6 +464,9 @@ static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac,
case FAPI_NR_CONFIG_TA_COMMAND:
configure_ta_command(phy, &pdu->ta_command_pdu);
break;
case FAPI_NR_DL_NTN_CONFIG_PARAMS:
configure_ntn_params(phy, &pdu->ntn_config_command_pdu);
break;
default:
LOG_W(PHY, "unhandled dl pdu type %d \n", pdu->pdu_type);
}
......
......@@ -729,8 +729,9 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) {
// don't wait anymore
LOG_E(NR_PHY, "Internal error nr_ue_dlsch_procedure() called but no active cw on slot %d, harq %d\n", nr_slot_rx, harq_pid);
const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]);
const int ack_nack_slot_and_frame =
(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
return false;
}
......@@ -865,8 +866,9 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
// DLSCH decoding finished! don't wait anymore in Tx process, we know if we should answer ACK/NACK PUCCH
if (dlsch[0].rnti_type == TYPE_C_RNTI_) {
const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]);
const int ack_nack_slot_and_frame =
(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
}
if (ue->phy_sim_dlsch_b)
......@@ -1148,8 +1150,9 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G);
else {
LOG_E(NR_PHY, "Demodulation impossible, internal error\n");
int ack_nack_slot = (proc->nr_slot_rx + dlsch_config->k1_feedback) % ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]);
const int ack_nack_slot_and_frame =
proc->nr_slot_rx + dlsch_config->k1_feedback + proc->frame_rx * ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
LOG_W(NR_PHY, "nr_ue_pdsch_procedures failed in slot %d\n", proc->nr_slot_rx);
}
......
......@@ -31,8 +31,9 @@
*/
#define _GNU_SOURCE
#define SPEED_OF_LIGHT 299792458
//#include "mac_defs.h"
#include "mac_defs.h"
#include <NR_MAC_gNB/mac_proto.h>
#include "NR_MAC_UE/mac_proto.h"
#include "NR_MAC-CellGroupConfig.h"
......@@ -41,6 +42,7 @@
#include "executables/softmodem-common.h"
#include "SCHED_NR/phy_frame_config_nr.h"
#include "oai_asn1.h"
#include "executables/position_interface.h"
void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table,
int mu,
......@@ -252,7 +254,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac,
mac->phy_config.Mod_id = mac->ue_id;
mac->phy_config.CC_id = cc_idP;
// carrier config
LOG_D(MAC, "[UE %d] Entering UE Config Common\n", mac->ue_id);
......@@ -1746,15 +1748,61 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
AssertFatal(!ret, "mutex failed %d\n", ret);
}
void nr_rrc_mac_config_req_sib19_r17(module_id_t module_id,
NR_SIB19_r17_t *sib19_r17)
// computes delay between ue and sat based on SIB19 ephemeris data
static double calculate_ue_sat_ta(const position_t *position_params, struct NR_PositionVelocity_r17 *sat_pos)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
// get UE position coordinates
double posx = position_params->positionX;
double posy = position_params->positionY;
double posz = position_params->positionZ;
// 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;
// ntn-Config-r17
UPDATE_IE(mac->sc_info.ntn_Config_r17, sib19_r17->ntn_Config_r17, NR_NTN_Config_r17_t);
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;
// TODO handle other SIB19 elements
return ta_ms;
}
void nr_rrc_mac_config_req_sib19_r17(module_id_t module_id, const position_t *pos, NR_SIB19_r17_t *sib19_r17)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
int ret = pthread_mutex_lock(&mac->if_mutex);
AssertFatal(!ret, "mutex failed %d\n", ret);
// update ntn_Config_r17 with received values
struct NR_NTN_Config_r17 *ntn_Config_r17 = mac->sc_info.ntn_Config_r17;
UPDATE_IE(ntn_Config_r17, sib19_r17->ntn_Config_r17, NR_NTN_Config_r17_t);
// populate ntn_ta structure from mac
// if ephemerisInfo_r17 present in SIB19
struct NR_EphemerisInfo_r17 *ephemeris_info = ntn_Config_r17->ephemerisInfo_r17;
if (ephemeris_info) {
struct NR_PositionVelocity_r17 *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)) {
mac->ntn_ta.N_UE_TA_adj = calculate_ue_sat_ta(pos, position_velocity);
}
}
// if cellSpecificKoffset_r17 is present
if (ntn_Config_r17->cellSpecificKoffset_r17) {
mac->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)
if (ntn_Config_r17->ta_Info_r17) {
mac->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)
mac->ntn_ta.ntn_ta_commondrift = *ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 * 0.2e-3;
}
mac->ntn_ta.ntn_params_changed = true;
ret = pthread_mutex_unlock(&mac->if_mutex);
AssertFatal(!ret, "mutex failed %d\n", ret);
}
static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
......
......@@ -485,7 +485,6 @@ typedef struct nr_lcordered_info_s {
bool lc_SRMask;
} nr_lcordered_info_t;
typedef struct {
uint8_t payload[NR_CCCH_PAYLOAD_SIZE_MAX];
} __attribute__ ((__packed__)) NR_CCCH_PDU;
......@@ -554,6 +553,19 @@ typedef struct {
A_SEQUENCE_OF(si_schedinfo_config_t) si_SchedInfo_list;
} si_schedInfo_t;
typedef struct ntn_timing_advance_components {
// N_common_ta_adj represents common propagation delay received in SIB19 (ms)
double N_common_ta_adj;
// N_UE_TA_adj calculated propagation delay from UE and SAT (ms)
double N_UE_TA_adj;
// drift rate of common ta in µs/s
double ntn_ta_commondrift;
// cell scheduling offset expressed in terms of 15kHz SCS
long cell_specific_k_offset;
bool ntn_params_changed;
} ntn_timing_advance_componets_t;
/*!\brief Top level UE MAC structure */
typedef struct NR_UE_MAC_INST_s {
module_id_t ue_id;
......@@ -623,6 +635,8 @@ typedef struct NR_UE_MAC_INST_s {
int p_Max_alt;
int n_ta_offset; // -1 not present, otherwise value to be applied
ntn_timing_advance_componets_t ntn_ta;
long pdsch_HARQ_ACK_Codebook;
NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config;
......@@ -661,5 +675,20 @@ typedef struct NR_UE_MAC_INST_s {
ue_mac_stats_t stats;
} NR_UE_MAC_INST_t;
static inline int GET_NTN_UE_K_OFFSET(const ntn_timing_advance_componets_t *ntn_ta, int scs)
{
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) * 2;
}
static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *ntn_ta)
{
return NR_UE_CAPABILITY_SLOT_RX_TO_TX + ntn_ta->cell_specific_k_offset;
}
/*@}*/
#endif /*__LAYER2_MAC_DEFS_H__ */
......@@ -91,8 +91,8 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
NR_SI_SchedulingInfo_v1700_t *si_SchedulingInfo_v1700,
NR_ServingCellConfigCommonSIB_t *scc);
void nr_rrc_mac_config_req_sib19_r17(module_id_t module_id,
NR_SIB19_r17_t *sib19_r17);
struct position; /* forward declaration */
void nr_rrc_mac_config_req_sib19_r17(module_id_t module_id, const struct position *pos, NR_SIB19_r17_t *sib19_r17);
void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause);
......
......@@ -70,6 +70,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
mac->p_Max = INT_MIN;
mac->p_Max_alt = INT_MIN;
mac->n_ta_offset = -1;
mac->ntn_ta.ntn_params_changed = false;
pthread_mutex_init(&mac->if_mutex, NULL);
reset_mac_inst(mac);
......@@ -86,29 +87,6 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
mac->pucch_power_control_initialized = false;
mac->pusch_power_control_initialized = false;
// Fake SIB19 reception for NTN
// TODO: remove this and implement the actual SIB19 reception instead!
if (get_nrUE_params()->ntn_koffset || get_nrUE_params()->ntn_ta_common || get_nrUE_params()->ntn_ta_commondrift) {
NR_SIB19_r17_t *sib19_r17 = calloc(1, sizeof(*sib19_r17));
sib19_r17->ntn_Config_r17 = calloc(1, sizeof(*sib19_r17->ntn_Config_r17));
// NTN cellSpecificKoffset-r17
if (get_nrUE_params()->ntn_koffset) {
asn1cCallocOne(sib19_r17->ntn_Config_r17->cellSpecificKoffset_r17, get_nrUE_params()->ntn_koffset);
}
// NTN ta-Common-r17
if (get_nrUE_params()->ntn_ta_common || get_nrUE_params()->ntn_ta_commondrift) {
sib19_r17->ntn_Config_r17->ta_Info_r17 = calloc(1, sizeof(*sib19_r17->ntn_Config_r17->ta_Info_r17));
sib19_r17->ntn_Config_r17->ta_Info_r17->ta_Common_r17 = get_nrUE_params()->ntn_ta_common / 4.072e-6; // ta-Common-r17 is in units of 4.072e-3 µs, ntn_ta_common is in ms
if (get_nrUE_params()->ntn_ta_commondrift)
asn1cCallocOne(sib19_r17->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17, get_nrUE_params()->ntn_ta_commondrift / 0.2e-3); // is in units of 0.2e-3 µs/s, ntn_ta_commondrift is in µs/s
}
nr_rrc_mac_config_req_sib19_r17(mac->ue_id, sib19_r17);
asn1cFreeStruc(asn_DEF_NR_SIB19_r17, sib19_r17);
}
}
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
......
......@@ -40,13 +40,8 @@
#include <executables/softmodem-common.h>
#include "openair2/LAYER2/RLC/rlc.h"
#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
static double get_ta_Common_ms(NR_NTN_Config_r17_t *ntn_Config_r17)
{
if (ntn_Config_r17 && ntn_Config_r17->ta_Info_r17)
return ntn_Config_r17->ta_Info_r17->ta_Common_r17 * 4.072e-6; // ta_Common_r17 is in units of 4.072e-3 µs
return 0.0;
}
int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac)
{
......@@ -621,7 +616,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_ta_Common_ms(mac->sc_info.ntn_Config_r17);
const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(&mac->ntn_ta);
const int mu = mac->current_UL_BWP->scs;
const int slots_per_ms = nr_slots_per_frame[mu] / 10;
......@@ -922,7 +917,7 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac)
NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__);
const double ta_Common_ms = get_ta_Common_ms(mac->sc_info.ntn_Config_r17);
const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(&mac->ntn_ta);
const int mu = mac->current_DL_BWP->scs;
const int slots_per_ms = nr_slots_per_frame[mu] / 10;
......
......@@ -147,13 +147,6 @@ static nr_dci_format_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
const uint8_t *dci_pdu,
const int slot);
static int get_NTN_UE_Koffset(NR_NTN_Config_r17_t *ntn_Config_r17, int scs)
{
if (ntn_Config_r17 && ntn_Config_r17->cellSpecificKoffset_r17)
return *ntn_Config_r17->cellSpecificKoffset_r17 << scs;
return 0;
}
int get_rnti_type(const NR_UE_MAC_INST_t *mac, const uint16_t rnti)
{
const RA_config_t *ra = &mac->ra;
......@@ -506,7 +499,7 @@ static int nr_ue_process_dci_ul_00(NR_UE_MAC_INST_t *mac,
frame_t frame_tx;
int slot_tx;
const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs);
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset)) {
LOG_E(MAC, "Cannot schedule PUSCH\n");
return -1;
......@@ -604,7 +597,7 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac,
tda_info.k2 = csi_K2;
}
const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs);
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset)) {
LOG_E(MAC, "Cannot schedule PUSCH\n");
return -1;
......@@ -921,14 +914,14 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
// according to TS 38.213 9.2.3
const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, dlsch_pdu->SubcarrierSpacing);
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing);
const uint16_t feedback_ti = 1 + dci->pdsch_to_harq_feedback_timing_indicator.val + ntn_ue_koffset;
if (rnti_type != TYPE_RA_RNTI_ && rnti_type != TYPE_SI_RNTI_) {
AssertFatal(feedback_ti > DURATION_RX_TO_TX,
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%d).\n",
AssertFatal(feedback_ti > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld).\n",
feedback_ti,
DURATION_RX_TO_TX);
GET_DURATION_RX_TO_TX(&mac->ntn_ta));
// set the harq status at MAC for feedback
const int tpc[] = {-1, 0, 1, 3};
set_harq_status(mac,
......@@ -1266,14 +1259,14 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
// according to TS 38.213 Table 9.2.3-1
const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, dlsch_pdu->SubcarrierSpacing);
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing);
const uint16_t feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset;
AssertFatal(feedback_ti > DURATION_RX_TO_TX,
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%d). Min feedback time set in config "
AssertFatal(feedback_ti > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config "
"file (min_rxtxtime).\n",
feedback_ti,
DURATION_RX_TO_TX);
GET_DURATION_RX_TO_TX(&mac->ntn_ta));
// set the harq status at MAC for feedback
const int tpc[] = {-1, 0, 1, 3};
......@@ -3453,7 +3446,7 @@ static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, in
ul_time_alignment->ta_command = ta;
ul_time_alignment->ta_apply = type;
const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs);
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
const int n_slots_frame = nr_slots_per_frame[mac->current_UL_BWP->scs];
ul_time_alignment->frame = (frame + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER;
ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame;
......@@ -4108,7 +4101,7 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n");
return;
}
const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs);
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset);
// TA command
......
......@@ -62,6 +62,8 @@
static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_frame_t slotP);
static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, 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);
static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac,
NR_SINGLE_ENTRY_PHR_MAC_CE *phr,
float P_CMAX,
......@@ -1266,9 +1268,9 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger
return;
}
AssertFatal(slot_offset > DURATION_RX_TO_TX,
"Slot offset between DCI and aperiodic SRS (%d) needs to be higher than DURATION_RX_TO_TX (%d)\n",
slot_offset, DURATION_RX_TO_TX);
AssertFatal(slot_offset > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
"Slot offset between DCI and aperiodic SRS (%d) needs to be higher than DURATION_RX_TO_TX (%ld)\n",
slot_offset, GET_DURATION_RX_TO_TX(&mac->ntn_ta));
int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs];
int sched_slot = (slot + slot_offset) % n_slots_frame;
NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->tdd_UL_DL_ConfigurationCommon;
......@@ -1368,6 +1370,11 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info
if (mac->ul_time_alignment.ta_apply != no_ta)
schedule_ta_command(dl_config, mac);
if (mac->ntn_ta.ntn_params_changed) {
mac->ntn_ta.ntn_params_changed = false;
schedule_ntn_config_command(dl_config, mac);
}
nr_scheduled_response_t scheduled_response = {.dl_config = dl_config,
.module_id = mac->ue_id,
......@@ -1732,7 +1739,7 @@ static uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, i
// PUSCH scheduler:
// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2,
// - where K2 is the offset between the slot in which UL DCI is received and the slot
// - in which ULSCH should be scheduled. K2 is configured in RRC configuration.
// - in which ULSCH should be scheduled. K2 is configured in RRC configuration.
// PUSCH Msg3 scheduler:
// - scheduled by RAR UL grant according to 8.3 of TS 38.213
// Note: Msg3 tx in the uplink symbols of mixed slot
......@@ -1772,24 +1779,24 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
AssertFatal(1 == 0, "Invalid numerology %i\n", mu);
}
AssertFatal((k2 + delta) > DURATION_RX_TO_TX,
"Slot offset (%ld) for Msg3 needs to be higher than DURATION_RX_TO_TX (%d). Please set min_rxtxtime at least to %d in gNB config file or gNBs.[0].min_rxtxtime=%d via command line.\n",
AssertFatal((k2 + delta) > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
"Slot offset (%ld) for Msg3 needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
k2,
DURATION_RX_TO_TX,
DURATION_RX_TO_TX,
DURATION_RX_TO_TX);
GET_DURATION_RX_TO_TX(&mac->ntn_ta),
GET_DURATION_RX_TO_TX(&mac->ntn_ta),
GET_DURATION_RX_TO_TX(&mac->ntn_ta));
*slot_tx = (current_slot + k2 + delta) % nr_slots_per_frame[mu];
*frame_tx = (current_frame + (current_slot + k2 + delta) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER;
} else {
AssertFatal(k2 > DURATION_RX_TO_TX,
"Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%d). Please set min_rxtxtime at least to %d in gNB config file or gNBs.[0].min_rxtxtime=%d via command line.\n",
AssertFatal(k2 > GET_DURATION_RX_TO_TX(&mac->ntn_ta),
"Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
k2,
DURATION_RX_TO_TX,
DURATION_RX_TO_TX,
DURATION_RX_TO_TX);
GET_DURATION_RX_TO_TX(&mac->ntn_ta),
GET_DURATION_RX_TO_TX(&mac->ntn_ta),
GET_DURATION_RX_TO_TX(&mac->ntn_ta));
if (k2 < 0) { // This can happen when a false DCI is received
LOG_W(PHY, "%d.%d. Received k2 %ld\n", current_frame, current_slot, k2);
......@@ -3591,6 +3598,17 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
return mac_ce_info.num_sdus > 0; // success if we got at least one sdu
}
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->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset;
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;
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_NTN_CONFIG_PARAMS;
dl_config->number_pdus += 1;
}
static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac)
{
NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
......
......@@ -62,6 +62,7 @@
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "executables/position_interface.h"
#ifndef CELLULAR
#include "RRC/NR/MESSAGES/asn1_msg.h"
......@@ -165,7 +166,7 @@ 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)
static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, instance_t ue_id, position_t *position)
{
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN);
......@@ -241,6 +242,14 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si)
SI_info->SInfo_r17.sib19_validity = true;
if (g_log->log_component[NR_RRC].level >= OAILOG_DEBUG)
xer_fprint(stdout, &asn_DEF_NR_SIB19_r17, (const void *)typeandinfo->choice.sib19_v1700);
// allocate memory for position coordinates
if (!position)
position = CALLOC(1, sizeof(*position));
// populate position with position from config file
get_position_coordinates(ue_id, position);
nr_rrc_mac_config_req_sib19_r17(ue_id, position, typeandinfo->choice.sib19_v1700);
nr_timer_start(&SI_info->SInfo_r17.sib19_timer);
break;
default:
......@@ -386,7 +395,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);
nr_decode_SI(SI_info, si, rrc->ue_id, rrc->position_coordinates);
}
}
if (rec_1530->otherConfig) {
......@@ -895,7 +904,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);
nr_decode_SI(SI_info, si, rrc->ue_id, rrc->position_coordinates);
break;
case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
default:
......
......@@ -196,6 +196,8 @@ typedef struct rrcPerNB {
NR_RSRP_Range_t s_measure;
} rrcPerNB_t;
/* forward declaration */
struct position;
typedef struct NR_UE_RRC_INST_s {
instance_t ue_id;
rrcPerNB_t perNB[NB_CNX_UE];
......@@ -236,6 +238,8 @@ typedef struct NR_UE_RRC_INST_s {
//Sidelink params
NR_SL_PreconfigurationNR_r16_t *sl_preconfig;
struct position *position_coordinates;
} NR_UE_RRC_INST_t;
#endif
......@@ -165,7 +165,7 @@ gNBs =
#ntn_Config_r17
# cellSpecificKoffset_r17 = 478; # GEO satellite
# cellSpecificKoffset_r17 = 40; # LEO satellite
# ta-Common-r17 = 29319745;
# ta-Common-r17 = 29314900;
# positionX-r17 = 0;
# positionY-r17 = 0;
# positionZ-r17 = 32433846;
......
......@@ -6,3 +6,9 @@ dnn= "oai";
nssai_sst=1;
nssai_sd=1;
}
position0 = {
x = 0.0;
y = 0.0;
z = 6377900.0;
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment