Merge branch 'develop' of https://gitlab.eurecom.fr/oai/openairinterface5g into maki
This commit is contained in:
@@ -405,7 +405,6 @@ int main ( int argc, char **argv )
|
||||
#if T_TRACER
|
||||
T_Config_Init();
|
||||
#endif
|
||||
//randominit (0);
|
||||
set_taus_seed (0);
|
||||
printf("configuring for RAU/RRU\n");
|
||||
|
||||
|
||||
@@ -492,7 +492,6 @@ int main( int argc, char **argv ) {
|
||||
#if T_TRACER
|
||||
T_Config_Init();
|
||||
#endif
|
||||
//randominit (0);
|
||||
set_taus_seed (0);
|
||||
cpuf=get_cpu_freq_GHz();
|
||||
pthread_cond_init(&sync_cond,NULL);
|
||||
|
||||
@@ -119,10 +119,9 @@ static void tx_func(processingData_L1tx_t *info)
|
||||
pushNotifiedFIFO(&gNB->resp_L1, res);
|
||||
|
||||
int tx_slot_type = nr_slot_select(cfg, frame_tx, slot_tx);
|
||||
// TODO check for analog_beam_list is a workaround while no beam API for beam
|
||||
// selection is implemented
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx || IS_SOFTMODEM_RFSIM
|
||||
|| cfg->analog_beamforming_ve.analog_beam_list) {
|
||||
// TODO check for analog_bf_vendor_ext set to 1 is a workaround while no beam API for beam selection is implemented
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx
|
||||
|| IS_SOFTMODEM_RFSIM || cfg->analog_beamforming_ve.analog_bf_vendor_ext.value) {
|
||||
start_meas(&info->gNB->phy_proc_tx);
|
||||
phy_procedures_gNB_TX(info->gNB,
|
||||
&sched_response.DL_req,
|
||||
|
||||
+16
-21
@@ -247,7 +247,7 @@ int connect_rau(RU_t *ru) {
|
||||
void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
if (ru == RC.ru[0])
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx & 0xffffffff);
|
||||
int offset = ru->nr_frame_parms->get_samples_slot_timestamp(slot,ru->nr_frame_parms,0);
|
||||
int offset = get_samples_slot_timestamp(ru->nr_frame_parms, slot);
|
||||
void *buffs[ru->nb_tx];
|
||||
for (int aid = 0; aid < ru->nb_tx; aid++)
|
||||
buffs[aid] = (void*)&ru->common.txdata[aid][offset];
|
||||
@@ -260,15 +260,9 @@ void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
timestamp,
|
||||
buffs[0],
|
||||
buffs[1],
|
||||
10 * log10((double)signal_energy(buffs[0], ru->nr_frame_parms->get_samples_per_slot(slot, ru->nr_frame_parms))),
|
||||
10 * log10((double)signal_energy(buffs[0], get_samples_per_slot(slot, ru->nr_frame_parms))),
|
||||
(int)txmeas.tv_nsec);
|
||||
ru->ifdevice.trx_write_func2(&ru->ifdevice,
|
||||
timestamp,
|
||||
buffs,
|
||||
0,
|
||||
ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms),
|
||||
0,
|
||||
ru->nb_tx);
|
||||
ru->ifdevice.trx_write_func2(&ru->ifdevice, timestamp, buffs, 0, get_samples_per_slot(slot, ru->nr_frame_parms), 0, ru->nb_tx);
|
||||
}
|
||||
|
||||
// southbound IF4p5 fronthaul
|
||||
@@ -295,11 +289,11 @@ void fh_if5_south_in(RU_t *ru,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 );
|
||||
start_meas(&ru->rx_fhaul);
|
||||
|
||||
ru->ifdevice.trx_read_func2(&ru->ifdevice, &proc->timestamp_rx, NULL, fp->get_samples_per_slot(*tti, fp));
|
||||
ru->ifdevice.trx_read_func2(&ru->ifdevice, &proc->timestamp_rx, NULL, get_samples_per_slot(*tti, fp));
|
||||
if (proc->first_rx == 1)
|
||||
ru->ts_offset = proc->timestamp_rx;
|
||||
proc->frame_rx = ((proc->timestamp_rx - ru->ts_offset) / (fp->samples_per_subframe * 10)) & 1023;
|
||||
proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx - ru->ts_offset, fp);
|
||||
proc->tti_rx = get_slot_from_timestamp(proc->timestamp_rx - ru->ts_offset, fp);
|
||||
|
||||
if (proc->first_rx == 0) {
|
||||
if (proc->tti_rx != *tti) {
|
||||
@@ -383,7 +377,7 @@ void fh_if4p5_south_in(RU_t *ru,
|
||||
//caculate timestamp_rx, timestamp_tx based on frame and subframe
|
||||
proc->tti_rx = sl;
|
||||
proc->frame_rx = f;
|
||||
proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(proc->tti_rx, fp, 0);
|
||||
proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10) + get_samples_slot_timestamp(fp, proc->tti_rx);
|
||||
// proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_subframe);
|
||||
proc->tti_tx = (sl+ru->sl_ahead)%fp->slots_per_frame;
|
||||
proc->frame_tx = (sl > (fp->slots_per_frame - 1 - (ru->sl_ahead))) ? (f + 1) & 1023 : f;
|
||||
@@ -528,7 +522,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
proc->frame_tx_unwrap += 1024;
|
||||
|
||||
proc->timestamp_tx =
|
||||
((uint64_t)frame_tx + proc->frame_tx_unwrap) * fp->samples_per_subframe * 10 + fp->get_samples_slot_timestamp(slot_tx, fp, 0);
|
||||
((uint64_t)frame_tx + proc->frame_tx_unwrap) * fp->samples_per_subframe * 10 + get_samples_slot_timestamp(fp, slot_tx);
|
||||
LOG_D(PHY, "RU %d/%d TST %lu, frame %d, subframe %d\n", ru->idx, 0, proc->timestamp_tx, frame_tx, slot_tx);
|
||||
|
||||
// dump VCD output for first RU in list
|
||||
@@ -566,14 +560,14 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
openair0_config_t *cfg = &ru->openair0_cfg;
|
||||
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot, fp);
|
||||
uint32_t samples_per_slot = get_samples_per_slot(*slot, fp);
|
||||
AssertFatal(*slot < fp->slots_per_frame && *slot >= 0, "slot %d is illegal (%d)\n", *slot, fp->slots_per_frame);
|
||||
|
||||
start_meas(&ru->rx_fhaul);
|
||||
int nb = ru->nb_rx * ru->num_beams_period;
|
||||
void *rxp[nb];
|
||||
for (int i = 0; i < nb; i++)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot, fp, 0)];
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][get_samples_slot_timestamp(fp, *slot)];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1);
|
||||
openair0_timestamp old_ts = proc->timestamp_rx;
|
||||
@@ -590,7 +584,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n", samples_per_slot, rxs);
|
||||
|
||||
if (proc->first_rx != 1) {
|
||||
uint32_t samples_per_slot_prev = fp->get_samples_per_slot((*slot - 1) % fp->slots_per_frame, fp);
|
||||
uint32_t samples_per_slot_prev = get_samples_per_slot((*slot - 1) % fp->slots_per_frame, fp);
|
||||
|
||||
if (proc->timestamp_rx - old_ts != samples_per_slot_prev) {
|
||||
LOG_D(PHY,
|
||||
@@ -609,7 +603,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
|
||||
// in fact the following line is the same as long as the timestamp_rx is synchronized to GPS.
|
||||
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
|
||||
proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx,fp);
|
||||
proc->tti_rx = get_slot_from_timestamp(proc->timestamp_rx, fp);
|
||||
// synchronize first reception to frame 0 subframe 0
|
||||
LOG_D(PHY,
|
||||
"RU %d/%d TS %ld, GPS %f, SR %f, frame %d, slot %d.%d / %d\n",
|
||||
@@ -725,9 +719,9 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
T_INT(frame),
|
||||
T_INT(slot),
|
||||
T_INT(0),
|
||||
T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot, fp, 0)], fp->get_samples_per_slot(slot, fp) * 4));
|
||||
T_BUFFER(&ru->common.txdata[0][get_samples_slot_timestamp(fp, slot)], get_samples_per_slot(slot, fp) * 4));
|
||||
int sf_extension = 0;
|
||||
int siglen=fp->get_samples_per_slot(slot,fp);
|
||||
int siglen = get_samples_per_slot(slot, fp);
|
||||
radio_tx_burst_flag_t flags_burst = TX_BURST_INVALID;
|
||||
radio_tx_gpio_flag_t flags_gpio = 0;
|
||||
|
||||
@@ -786,7 +780,7 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
int nt = ru->nb_tx * ru->num_beams_period;
|
||||
void *txp[nt];
|
||||
for (int i = 0; i < nt; i++)
|
||||
txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot, fp, 0)] - sf_extension * sizeof(int32_t);
|
||||
txp[i] = (void *)&ru->common.txdata[i][get_samples_slot_timestamp(fp, slot)] - sf_extension * sizeof(int32_t);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp + ru->ts_offset) & 0xffffffff);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1);
|
||||
@@ -902,6 +896,7 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_
|
||||
}
|
||||
}
|
||||
|
||||
split7->prach_fftSize = prach_config->prach_sequence_length.value == 0 ? 10 : 8; // need to handle 5kHz cases better than this
|
||||
split7->fftSize = log2(fp->ofdm_symbol_size);
|
||||
|
||||
// M-plane related parameters
|
||||
@@ -1176,7 +1171,7 @@ void *ru_thread(void *param)
|
||||
}
|
||||
proc->timestamp_tx = proc->timestamp_rx;
|
||||
for (int i = proc->tti_rx; i < proc->tti_rx + ru->sl_ahead; i++)
|
||||
proc->timestamp_tx += fp->get_samples_per_slot(i % fp->slots_per_frame, fp);
|
||||
proc->timestamp_tx += get_samples_per_slot(i % fp->slots_per_frame, fp);
|
||||
proc->tti_tx = (proc->tti_rx + ru->sl_ahead) % fp->slots_per_frame;
|
||||
proc->frame_tx = proc->tti_rx > proc->tti_tx ? (proc->frame_rx + 1) & 1023 : proc->frame_rx;
|
||||
LOG_D(PHY,
|
||||
|
||||
@@ -546,7 +546,6 @@ int main( int argc, char **argv ) {
|
||||
#if T_TRACER
|
||||
T_Config_Init();
|
||||
#endif
|
||||
//randominit (0);
|
||||
set_taus_seed (0);
|
||||
|
||||
cpuf=get_cpu_freq_GHz();
|
||||
|
||||
+109
-98
@@ -19,11 +19,11 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#define _GNU_SOURCE // For pthread_setname_np
|
||||
#include <pthread.h>
|
||||
#include <openair1/PHY/impl_defs_top.h>
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "PHY/phy_extern_nr_ue.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "NR_MAC_UE/mac_proto.h"
|
||||
#include "RRC/NR_UE/rrc_proto.h"
|
||||
@@ -176,8 +176,7 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id)
|
||||
ue->dci_thres = 0;
|
||||
ue->target_Nid_cell = -1;
|
||||
|
||||
ue->ntn_config_message = CALLOC(1, sizeof(*ue->ntn_config_message));
|
||||
ue->ntn_config_message->update = false;
|
||||
ue->nrUE_config.ntn_config.params_changed = false;
|
||||
|
||||
// initialize all signal buffers
|
||||
init_nr_ue_signal(ue, nb_connected_gNB);
|
||||
@@ -257,7 +256,7 @@ static void UE_synch(void *arg) {
|
||||
+ round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0);
|
||||
|
||||
if (get_nrUE_params()->cont_fo_comp) {
|
||||
UE->freq_offset = freq_offset;
|
||||
UE->freq_offset = freq_offset - UE->dl_Doppler_shift;
|
||||
} else {
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
|
||||
@@ -383,7 +382,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
|
||||
openair0_timestamp writeTimestamp = proc->timestamp_tx;
|
||||
int writeBlockSize = rxtxD->writeBlockSize;
|
||||
// if writeBlockSize gets longer that slot size, fill with dummy
|
||||
const int maxWriteBlockSize = fp->get_samples_per_slot(proc->nr_slot_tx, fp);
|
||||
const int maxWriteBlockSize = get_samples_per_slot(proc->nr_slot_tx, fp);
|
||||
while (writeBlockSize > maxWriteBlockSize) {
|
||||
const int dummyBlockSize = min(writeBlockSize - maxWriteBlockSize, maxWriteBlockSize);
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, dummyBlockSize, fp->nb_antennas_tx, flags);
|
||||
@@ -398,8 +397,15 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
|
||||
double ul_freq_offset = -UE->freq_offset * ((double)fp->ul_CarrierFreq / (double)fp->dl_CarrierFreq);
|
||||
if (get_nrUE_params()->cont_fo_comp == 2) // different from LO frequency error compensation, Doppler UL pre-compensation has to be negative
|
||||
ul_freq_offset = -ul_freq_offset;
|
||||
else if (get_nrUE_params()->cont_fo_comp == 3) // do not consider residual DL FO for UL pre-compensation at all
|
||||
ul_freq_offset = 0;
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++)
|
||||
nr_fo_compensation(ul_freq_offset, fp->samples_per_subframe, writeTimestamp, txp[i], txp[i], writeBlockSize);
|
||||
nr_fo_compensation(UE->ul_Doppler_shift + ul_freq_offset,
|
||||
fp->samples_per_subframe,
|
||||
writeTimestamp,
|
||||
txp[i],
|
||||
txp[i],
|
||||
writeBlockSize);
|
||||
}
|
||||
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, writeBlockSize, fp->nb_antennas_tx, flags);
|
||||
@@ -423,7 +429,7 @@ void processSlotTX(void *arg)
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
c16_t *txp[fp->nb_antennas_tx];
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++) {
|
||||
txp[i] = UE->common_vars.txData[i] + fp->get_samples_slot_timestamp(proc->nr_slot_tx, fp, 0);
|
||||
txp[i] = UE->common_vars.txData[i] + get_samples_slot_timestamp(fp, proc->nr_slot_tx);
|
||||
}
|
||||
|
||||
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT) {
|
||||
@@ -434,8 +440,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,
|
||||
@@ -506,6 +514,15 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
|
||||
uint64_t dl_CarrierFreq = get_carrier_frequency(fp->N_RB_DL, fp->numerology_index, cfg->dl_frequency);
|
||||
uint64_t ul_CarrierFreq = get_carrier_frequency(fp->N_RB_UL, fp->numerology_index, cfg->uplink_frequency);
|
||||
if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) {
|
||||
LOG_I(NR_PHY,
|
||||
"[UE %d] RF frequency change: dl %lu->%lu Hz, ul %lu->%lu Hz (from dl_frequency=%u kHz, target_Nid_cell=%d)\n",
|
||||
UE->Mod_id,
|
||||
fp->dl_CarrierFreq,
|
||||
dl_CarrierFreq,
|
||||
fp->ul_CarrierFreq,
|
||||
ul_CarrierFreq,
|
||||
cfg->dl_frequency,
|
||||
UE->target_Nid_cell);
|
||||
fp->dl_CarrierFreq = dl_CarrierFreq;
|
||||
fp->ul_CarrierFreq = ul_CarrierFreq;
|
||||
nr_rf_card_config_freq(&UE->openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0);
|
||||
@@ -513,6 +530,12 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
|
||||
init_symbol_rotation(fp);
|
||||
}
|
||||
|
||||
// Apply Doppler based on NTN-Config for target cell
|
||||
if (UE->nrUE_config.ntn_config.is_targetcell)
|
||||
apply_ntn_timing_advance_and_doppler(UE, fp, -1);
|
||||
// Apply NTN DL Doppler as initial FO
|
||||
UE->initial_fo = UE->dl_Doppler_shift;
|
||||
|
||||
/* Clearing UE harq while DL actors are active causes race condition.
|
||||
So we let the current execution to complete here.*/
|
||||
for (int i = 0; i < get_nrUE_params()->num_dl_actors; i++) {
|
||||
@@ -654,24 +677,25 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_r
|
||||
void *rxp[NB_ANTENNAS_RX];
|
||||
if (toTrash)
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = malloc16(fp->get_samples_per_slot(0, fp) * 4);
|
||||
rxp[i] = malloc16(get_samples_per_slot(0, fp) * 4);
|
||||
|
||||
for (int x = 0; x < num_frames * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; x++) { // two frames for initial sync
|
||||
for (int slot = 0; slot < fp->slots_per_subframe; slot++) {
|
||||
if (!toTrash)
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = ((void *)&UE->common_vars.rxdata[i][0])
|
||||
+ 4 * ((x * fp->samples_per_subframe) + fp->get_samples_slot_timestamp(slot, fp, 0));
|
||||
rxp[i] =
|
||||
((void *)&UE->common_vars.rxdata[i][0]) + 4 * ((x * fp->samples_per_subframe) + get_samples_slot_timestamp(fp, slot));
|
||||
|
||||
int read_block_size = fp->get_samples_per_slot(slot, fp);
|
||||
int read_block_size = get_samples_per_slot(slot, fp);
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, rxp, read_block_size, fp->nb_antennas_rx);
|
||||
UEscopeCopy(UE, ueTimeDomainSamplesBeforeSync, rxp[0], sizeof(c16_t), 1, read_block_size, 0);
|
||||
AssertFatal(read_block_size == tmp, "");
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
int ta = UE->timing_advance + UE->timing_advance_ntn;
|
||||
const openair0_timestamp writeTimestamp =
|
||||
*timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance;
|
||||
dummyWrite(UE, writeTimestamp, fp->get_samples_per_slot(slot, fp));
|
||||
*timestamp + get_samples_slot_duration(fp, slot, duration_rx_to_tx) - UE->N_TA_offset - ta;
|
||||
dummyWrite(UE, writeTimestamp, get_samples_per_slot(slot, fp));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -692,12 +716,13 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int d
|
||||
int slot = 0;
|
||||
int size = rx_offset;
|
||||
while (size > 0) {
|
||||
const int unitTransfer = min(fp->get_samples_per_slot(slot, fp), size);
|
||||
const int unitTransfer = min(get_samples_per_slot(slot, fp), size);
|
||||
const int res = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx);
|
||||
DevAssert(unitTransfer == res);
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
int ta = UE->timing_advance + UE->timing_advance_ntn;
|
||||
const openair0_timestamp writeTimestamp =
|
||||
*timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance;
|
||||
*timestamp + get_samples_slot_duration(fp, slot, duration_rx_to_tx) - UE->N_TA_offset - ta;
|
||||
dummyWrite(UE, writeTimestamp, unitTransfer);
|
||||
}
|
||||
slot = (slot + 1) % fp->slots_per_subframe;
|
||||
@@ -706,73 +731,17 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int d
|
||||
}
|
||||
|
||||
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
if (fp->numerology_index == 0)
|
||||
return fp->nb_prefix_samples0 + fp->ofdm_symbol_size;
|
||||
int num_samples = (slot%(fp->slots_per_subframe/2)) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
|
||||
num_samples += fp->ofdm_symbol_size;
|
||||
return num_samples;
|
||||
return get_samples_symbol_duration(fp, slot, 0, 1);
|
||||
}
|
||||
|
||||
static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
int rem_samples = fp->get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp);
|
||||
int rem_samples = get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp);
|
||||
int next_slot_first_symbol = 0;
|
||||
if (slot < (fp->slots_per_frame-1))
|
||||
next_slot_first_symbol = get_firstSymSamp(slot+1, fp);
|
||||
return rem_samples + next_slot_first_symbol;
|
||||
}
|
||||
|
||||
static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
int frame_rx,
|
||||
int slot_rx,
|
||||
int *duration_rx_to_tx,
|
||||
int *timing_advance,
|
||||
int *ntn_koffset)
|
||||
{
|
||||
if (UE->ntn_config_message->update) {
|
||||
UE->ntn_config_message->update = false;
|
||||
|
||||
const int mu = fp->numerology_index;
|
||||
const int koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset;
|
||||
|
||||
*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), 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);
|
||||
}
|
||||
}
|
||||
|
||||
void *UE_thread(void *arg)
|
||||
{
|
||||
//this thread should be over the processing thread to keep in real time
|
||||
@@ -805,11 +774,17 @@ void *UE_thread(void *arg)
|
||||
notifiedFIFO_t freeBlocks;
|
||||
initNotifiedFIFO_nothreadSafe(&freeBlocks);
|
||||
|
||||
double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift;
|
||||
int ntn_koffset = 0;
|
||||
const double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift;
|
||||
if (get_nrUE_params()->time_sync_I)
|
||||
// ntn_init_time_drift is in µs/s, max_pos_acc * time_sync_I is in samples/frame
|
||||
UE->max_pos_acc = ntn_init_time_drift * 1e-6 * fp->samples_per_frame / get_nrUE_params()->time_sync_I;
|
||||
else
|
||||
UE->max_pos_acc = 0;
|
||||
|
||||
bool ntn_targetcell = false;
|
||||
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);
|
||||
|
||||
@@ -903,10 +878,6 @@ void *UE_thread(void *arg)
|
||||
syncMsg->UE = UE;
|
||||
memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
|
||||
pushNotifiedFIFO(&UE->sync_actor.fifo, Msg);
|
||||
if (ntn_koffset == 0) { // reset timing_advance for TN
|
||||
timing_advance = 0;
|
||||
UE->timing_advance = 0;
|
||||
}
|
||||
trashed_frames = 0;
|
||||
syncRunning = true;
|
||||
continue;
|
||||
@@ -916,13 +887,8 @@ void *UE_thread(void *arg)
|
||||
stream_status = STREAM_STATUS_SYNCING;
|
||||
syncInFrame(UE, &sync_timestamp, duration_rx_to_tx, intialSyncOffset);
|
||||
openair0_write_reorder_clear_context(&UE->rfdevice);
|
||||
if (get_nrUE_params()->time_sync_I)
|
||||
// ntn_init_time_drift is in µs/s, max_pos_acc * time_sync_I is in samples/frame
|
||||
UE->max_pos_acc = ntn_init_time_drift * 1e-6 * fp->samples_per_frame / get_nrUE_params()->time_sync_I;
|
||||
else
|
||||
UE->max_pos_acc = 0;
|
||||
shiftForNextFrame = -(UE->init_sync_frame + trashed_frames + 2) * UE->max_pos_acc * get_nrUE_params()->time_sync_I; // compensate for the time drift that happened during initial sync
|
||||
LOG_D(PHY, "max_pos_acc = %d, shiftForNextFrame = %d\n", UE->max_pos_acc, shiftForNextFrame);
|
||||
LOG_I(PHY, "max_pos_acc = %d, shiftForNextFrame = %d\n", UE->max_pos_acc, shiftForNextFrame);
|
||||
// read in first symbol
|
||||
AssertFatal(fp->ofdm_symbol_size + fp->nb_prefix_samples0
|
||||
== UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
@@ -934,12 +900,35 @@ void *UE_thread(void *arg)
|
||||
// we have the decoded frame index in the return of the synch process
|
||||
// and we shifted above to the first slot of next frame
|
||||
decoded_frame_rx = (decoded_frame_rx + 1) % MAX_FRAME_NUMBER;
|
||||
const int prev_frame_rx = (absolute_slot / nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
const int prev_hfn_rx = (absolute_slot / nb_slot_frame) / MAX_FRAME_NUMBER;
|
||||
int decoded_hfn_rx = prev_hfn_rx;
|
||||
if (decoded_frame_rx <= prev_frame_rx)
|
||||
decoded_hfn_rx++;
|
||||
// we do ++ first in the regular processing, so it will be begin of frame;
|
||||
absolute_slot = decoded_frame_rx * nb_slot_frame - 1;
|
||||
absolute_slot = (decoded_hfn_rx * MAX_FRAME_NUMBER + decoded_frame_rx) * nb_slot_frame - 1;
|
||||
if (UE->sl_mode == 2) {
|
||||
// Set to the slot where the SL-SSB was decoded
|
||||
absolute_slot += UE->SL_UE_PHY_PARAMS.sync_params.slot_offset;
|
||||
}
|
||||
// With the correct frame and slot numbers, we can now fix the UL timing
|
||||
fix_ntn_epoch_hfn(UE, decoded_hfn_rx, decoded_frame_rx);
|
||||
if (UE->nrUE_config.ntn_config.params_changed) {
|
||||
apply_ntn_config(UE,
|
||||
fp,
|
||||
decoded_hfn_rx,
|
||||
decoded_frame_rx,
|
||||
0,
|
||||
&duration_rx_to_tx,
|
||||
&timing_advance,
|
||||
&ntn_koffset,
|
||||
&ntn_targetcell);
|
||||
} else {
|
||||
const int abs_subframe_tx = (absolute_slot + 1 + duration_rx_to_tx) / fp->slots_per_subframe;
|
||||
apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
|
||||
ntn_targetcell = false;
|
||||
}
|
||||
UE->timing_advance = 0;
|
||||
// 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_PROCESS_SLOT_TX_BARRIERS; i++) {
|
||||
@@ -968,6 +957,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);
|
||||
@@ -984,18 +975,25 @@ void *UE_thread(void *arg)
|
||||
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, fp);
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp + fp->get_samples_slot_timestamp(slot_nr, fp, 0)];
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp + get_samples_slot_timestamp(fp, slot_nr)];
|
||||
|
||||
int iq_shift_to_apply = 0;
|
||||
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 && !ntn_targetcell && !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_and_doppler(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);
|
||||
@@ -1025,8 +1023,8 @@ 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)
|
||||
- firstSymSamp - UE->N_TA_offset - timing_advance;
|
||||
const openair0_timestamp writeTimestamp =
|
||||
rx_timestamp + get_samples_slot_duration(fp, slot_nr, duration_rx_to_tx) - firstSymSamp - UE->N_TA_offset - timing_advance;
|
||||
|
||||
// Calculate TX deadline, approximately 1 symbol before the first sample should be written
|
||||
const uint64_t samples_diff = writeTimestamp - rx_timestamp - fp->ofdm_symbol_size;
|
||||
@@ -1034,8 +1032,8 @@ void *UE_thread(void *arg)
|
||||
const uint64_t absolute_deadline_us = current_time.tv_sec * 1e6 + current_time.tv_nsec / 1e3 + deadline_us;
|
||||
|
||||
// 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 writeBlockSize = 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 + UE->timing_advance_ntn;
|
||||
if (new_timing_advance != timing_advance) {
|
||||
writeBlockSize -= new_timing_advance - timing_advance;
|
||||
timing_advance = new_timing_advance;
|
||||
@@ -1046,9 +1044,14 @@ void *UE_thread(void *arg)
|
||||
writeBlockSize -= new_N_TA_offset - UE->N_TA_offset;
|
||||
UE->N_TA_offset = new_N_TA_offset;
|
||||
}
|
||||
if (writeBlockSize < 0) {
|
||||
timing_advance += writeBlockSize - 1;
|
||||
LOG_I(PHY, "writeBlockSize is %d, setting it to 1 and changing timing_advance to %d\n", writeBlockSize, timing_advance);
|
||||
writeBlockSize = 1;
|
||||
}
|
||||
|
||||
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 +1067,15 @@ 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,
|
||||
&ntn_targetcell);
|
||||
|
||||
// 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
|
||||
@@ -1078,7 +1089,7 @@ void *UE_thread(void *arg)
|
||||
curMsgTx->absolute_deadline_us = absolute_deadline_us;
|
||||
|
||||
int slot = curMsgTx->proc.nr_slot_tx;
|
||||
int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame;
|
||||
int slot_and_frame = slot + curMsgTx->proc.frame_tx * nb_slot_frame;
|
||||
int next_tx_slot_and_frame = absolute_slot + duration_rx_to_tx + 1;
|
||||
int wait_for_prev_slot = stream_status == STREAM_STATUS_SYNCED ? 1 : 0;
|
||||
|
||||
|
||||
@@ -340,7 +340,6 @@ int main(int argc, char **argv)
|
||||
T_Config_Init();
|
||||
#endif
|
||||
initTpool(get_softmodem_params()->threadPoolConfig, &(nrUE_params.Tpool), cpumeas(CPUMEAS_GETSTATE));
|
||||
//randominit (0);
|
||||
set_taus_seed (0);
|
||||
|
||||
if (!has_cap_sys_nice())
|
||||
|
||||
@@ -21,7 +21,7 @@ extern uint16_t ue_id_g;
|
||||
#define CONFIG_HLP_INITIAL_FO "Initially compensated DL frequency offset (e.g. known Doppler shift in NTN LEO scenario)\n"
|
||||
#define CONFIG_HLP_FREQ_SYNC_P "coefficient for Proportional part of continuous frequency offset compensation PI controller\n"
|
||||
#define CONFIG_HLP_FREQ_SYNC_I "coefficient for Integrating part of continuous frequency offset compensation PI controller\n"
|
||||
#define CONFIG_HLP_CONT_FO_COMP "Enable continuous frequency offset (FO) estimation and compensation and specify main FO source (1 = local oscillator, 2 = Doppler shift)\n"
|
||||
#define CONFIG_HLP_CONT_FO_COMP "Enable continuous frequency offset (FO) estimation and (pre-)compensation and specify main FO source (1 = local oscillator, 2 = Doppler shift, 3 = Don't consider residual DL FO in UL FO pre-compensation)\n"
|
||||
#define CONFIG_HLP_AGC "Rx Gain control used for UE\n"
|
||||
#define CONFIG_HLP_NUM_UL_ACTORS "Number of UL actors to use. Set to 0 to disable UL actor framework and do processing inline\n"
|
||||
#define CONFIG_HLP_NUM_DL_ACTORS "Number of DL actors to use. Set to 0 to disable DL actor framework and do processing inline\n"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "position_interface.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
|
||||
static void read_position_coordinates(char *sectionName, position_t *position)
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user