From 8e18e5b3aae529912ceb43669bde1f44ee7a1c87 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 13 Aug 2025 14:42:04 +0200 Subject: [PATCH] NR UE: wrap all direct trx_*() function calls in nr_ue_ru_*() functions --- executables/nr-ue-ru.c | 152 +++++++++++++++++++++++++++++++++++ executables/nr-ue-ru.h | 6 ++ executables/nr-ue.c | 94 ++++++---------------- executables/nr-uesoftmodem.h | 2 - radio/COMMON/common_lib.c | 46 +++++++++-- radio/COMMON/common_lib.h | 6 ++ 6 files changed, 228 insertions(+), 78 deletions(-) diff --git a/executables/nr-ue-ru.c b/executables/nr-ue-ru.c index c4dcfdf888..daedc1b02e 100644 --- a/executables/nr-ue-ru.c +++ b/executables/nr-ue-ru.c @@ -371,3 +371,155 @@ void nrue_ru_end(void) openair0_dev[ru_id].trx_end_func(&openair0_dev[ru_id]); } } + +void nrue_ru_set_freq(PHY_VARS_NR_UE *UE, uint64_t ul_carrier, uint64_t dl_carrier, int freq_offset) +{ + int current_cell_id = nrue_rus[UE->rf_map.card].used_by_cell; + NR_DL_FRAME_PARMS *fp0 = &nrue_cell_fp[current_cell_id]; + uint64_t dl_carrier_distance = + fp0->dl_CarrierFreq > dl_carrier ? fp0->dl_CarrierFreq - dl_carrier : dl_carrier - fp0->dl_CarrierFreq; + uint64_t ul_carrier_distance = + fp0->ul_CarrierFreq > ul_carrier ? fp0->ul_CarrierFreq - ul_carrier : ul_carrier - fp0->ul_CarrierFreq; + uint64_t carrier_distance = dl_carrier_distance + ul_carrier_distance; + + for (int ru_id = 0; carrier_distance != 0 && ru_id < nrue_ru_count; ru_id++) { + int cell_id = nrue_rus[ru_id].used_by_cell; + if (cell_id < 0) // skip RUs that have no cell definition + continue; + if (nrue_cells[cell_id].used_by_ue >= 0) // skip cells that are already used by an UE + continue; + + fp0 = &nrue_cell_fp[cell_id]; + uint64_t this_dl_carrier_distance = + fp0->dl_CarrierFreq > dl_carrier ? fp0->dl_CarrierFreq - dl_carrier : dl_carrier - fp0->dl_CarrierFreq; + uint64_t this_ul_carrier_distance = + fp0->ul_CarrierFreq > ul_carrier ? fp0->ul_CarrierFreq - ul_carrier : ul_carrier - fp0->ul_CarrierFreq; + uint64_t this_carrier_distance = this_dl_carrier_distance + this_ul_carrier_distance; + if (this_carrier_distance < carrier_distance) { + UE->rf_map.card = ru_id; + carrier_distance = this_carrier_distance; + } + } + + nrue_cells[current_cell_id].used_by_ue = -1; + current_cell_id = nrue_rus[UE->rf_map.card].used_by_cell; + nrue_cells[current_cell_id].used_by_ue = UE->Mod_id; + + openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; + openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; + nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset); + dev0->trx_set_freq_func(dev0, cfg0); +} + +int nrue_ru_adjust_rx_gain(PHY_VARS_NR_UE *UE, int gain_change) +{ + openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; + openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; + + // Increase the RX gain by the value determined by adjust_rxgain + cfg0->rx_gain[0] += gain_change; + + // Set new RX gain. + int ret_gain = dev0->trx_set_gains_func(dev0, cfg0); + // APPLY RX gain again if crossed the MAX RX gain threshold + if (ret_gain < 0) { + gain_change += ret_gain; + cfg0->rx_gain[0] += ret_gain; + ret_gain = dev0->trx_set_gains_func(dev0, cfg0); + } + + int applied_rxgain = cfg0->rx_gain[0] - cfg0->rx_gain_offset[0]; + LOG_I(HW, "Rxgain adjusted by %d dB, RX gain: %d dB \n", gain_change, applied_rxgain); + + return gain_change; +} + +int nrue_ru_read(PHY_VARS_NR_UE *UE, openair0_timestamp_t *ptimestamp, void **buff, int nsamps, int num_antennas) +{ + openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; + openair0_timestamp_t tmp_timestamp; + int ret = dev0->trx_read_func(dev0, &tmp_timestamp, buff, nsamps, num_antennas); + if (!dev0->firstTS_initialized) { + dev0->firstTS = tmp_timestamp; + dev0->firstTS_initialized = true; + } + *ptimestamp = tmp_timestamp - dev0->firstTS; + + if (UE->Mod_id != 0) + return ret; + + // UE 0 needs to read from all RUs that are not used by any other UE + + void *tmp_buf[num_antennas]; + uint32_t tmp_samples[nsamps]; + for (int ant = 0; ant < num_antennas; ant++) + tmp_buf[ant] = tmp_samples; + + for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) { + int cell_id = nrue_rus[ru_id].used_by_cell; + if (cell_id < 0) // skip RUs that have no cell definition + continue; + int ue_id = nrue_cells[cell_id].used_by_ue; + if (ue_id >= 0) // skip cells that are already used by an UE + continue; + + dev0 = &openair0_dev[ru_id]; + dev0->trx_read_func(dev0, &tmp_timestamp, tmp_buf, nsamps, num_antennas); + if (!dev0->firstTS_initialized) { + dev0->firstTS = tmp_timestamp; + dev0->firstTS_initialized = true; + } + } + + return ret; +} + +int nrue_ru_write(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, void **buff, int nsamps, int num_antennas, int flags) +{ + openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; + int ret = dev0->trx_write_func(dev0, timestamp + dev0->firstTS, buff, nsamps, num_antennas, flags); + + if (UE->Mod_id != 0) + return ret; + + // UE 0 needs to write to all RUs that are not used by any other UE + + void *tmp_buf[num_antennas]; + uint32_t tmp_samples[nsamps]; + memset(tmp_samples, 0, sizeof(tmp_samples)); + for (int ant = 0; ant < num_antennas; ant++) + tmp_buf[ant] = tmp_samples; + + for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) { + int cell_id = nrue_rus[ru_id].used_by_cell; + if (cell_id < 0) // skip RUs that have no cell definition + continue; + int ue_id = nrue_cells[cell_id].used_by_ue; + if (ue_id >= 0) // skip cells that are already used by an UE + continue; + + dev0 = &openair0_dev[ru_id]; + dev0->trx_write_func(dev0, timestamp + dev0->firstTS, tmp_buf, nsamps, num_antennas, flags); + } + return ret; +} + +int openair0_write_reorder_common(PHY_VARS_NR_UE *UE, + openair0_device_t *device, + openair0_timestamp_t timestamp, + void **txp, + int nsamps, + int nbAnt, + int flags); + +int nrue_ru_write_reorder(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, void **txp, int nsamps, int nbAnt, int flags) +{ + openair0_device_t *device = &openair0_dev[UE->rf_map.card]; + return openair0_write_reorder_common(UE, device, timestamp, txp, nsamps, nbAnt, flags); +} + +void nrue_ru_write_reorder_clear_context(PHY_VARS_NR_UE *UE) +{ + openair0_device_t *device = &openair0_dev[UE->rf_map.card]; + openair0_write_reorder_clear_context(device); +} diff --git a/executables/nr-ue-ru.h b/executables/nr-ue-ru.h index 91b86d487b..9fe3fc3bd9 100644 --- a/executables/nr-ue-ru.h +++ b/executables/nr-ue-ru.h @@ -40,5 +40,11 @@ void nrue_init_openair0(void); void nrue_ru_start(void); void nrue_ru_end(void); +void nrue_ru_set_freq(PHY_VARS_NR_UE *UE, uint64_t ul_carrier, uint64_t dl_carrier, int freq_offset); +int nrue_ru_adjust_rx_gain(PHY_VARS_NR_UE *UE, int gain_change); +int nrue_ru_read(PHY_VARS_NR_UE *UE, openair0_timestamp_t *ptimestamp, void **buff, int nsamps, int num_antennas); +int nrue_ru_write(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, void **buff, int nsamps, int num_antennas, int flags); +int nrue_ru_write_reorder(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, void **txp, int nsamps, int nbAnt, int flags); +void nrue_ru_write_reorder_clear_context(PHY_VARS_NR_UE *UE); #endif diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 16fb246185..2a7ed2ab0f 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -23,6 +23,7 @@ #define _GNU_SOURCE // For pthread_setname_np #include #include +#include "executables/nr-ue-ru.h" #include "executables/nr-uesoftmodem.h" #include "PHY/INIT/nr_phy_init.h" #include "NR_MAC_UE/mac_proto.h" @@ -201,38 +202,10 @@ typedef struct { int rx_offset; } syncData_t; -extern openair0_config_t openair0_cfg[MAX_CARDS]; -extern openair0_device_t openair0_dev[MAX_CARDS]; - -static int nr_ue_adjust_rx_gain(PHY_VARS_NR_UE *UE, int gain_change) -{ - openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; - openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; - - // Increase the RX gain by the value determined by adjust_rxgain - cfg0->rx_gain[0] += gain_change; - - // Set new RX gain. - int ret_gain = dev0->trx_set_gains_func(dev0, cfg0); - // APPLY RX gain again if crossed the MAX RX gain threshold - if (ret_gain < 0) { - gain_change += ret_gain; - cfg0->rx_gain[0] += ret_gain; - ret_gain = dev0->trx_set_gains_func(dev0, cfg0); - } - - int applied_rxgain = cfg0->rx_gain[0] - cfg0->rx_gain_offset[0]; - LOG_I(PHY, "Rxgain adjusted by %d dB, RX gain: %d dB \n", gain_change, applied_rxgain); - - return gain_change; -} - static void UE_synch(void *arg) { syncData_t *syncD = (syncData_t *)arg; PHY_VARS_NR_UE *UE = syncD->UE; UE->is_synchronized = 0; - openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; - openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; if (UE->target_Nid_cell != -1) { LOG_W(NR_PHY, "Starting re-sync detection for target Nid_cell %i\n", UE->target_Nid_cell); @@ -266,27 +239,20 @@ static void UE_synch(void *arg) { 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); - dev0->trx_set_freq_func(dev0, cfg0); + nrue_ru_set_freq(UE, ul_carrier, dl_carrier, freq_offset); } if (get_nrUE_params()->agc) { - nr_ue_adjust_rx_gain(UE, UE->adjust_rxgain); + nrue_ru_adjust_rx_gain(UE, UE->adjust_rxgain); } - LOG_I(PHY, - "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %f (DL %f Hz, UL %f Hz)\n", - hw_slot_offset, - freq_offset, - cfg0->rx_gain[0] - cfg0->rx_gain_offset[0], - cfg0->rx_freq[0], - cfg0->tx_freq[0]); + LOG_I(PHY, "Got synch: hw_slot_offset %d, carrier off %d Hz\n", hw_slot_offset, freq_offset); UE->is_synchronized = 1; } else { int gain_change = 0; if (get_nrUE_params()->agc) - gain_change = nr_ue_adjust_rx_gain(UE, INCREASE_IN_RXGAIN); + gain_change = nrue_ru_adjust_rx_gain(UE, INCREASE_IN_RXGAIN); if (gain_change) LOG_I(PHY, "synch retry: Rx gain increased \n"); else @@ -331,8 +297,6 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx PHY_VARS_NR_UE *UE = rxtxD->UE; const fapi_nr_config_request_t *cfg = &UE->nrUE_config; const UE_nr_rxtx_proc_t *proc = &rxtxD->proc; - openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; - openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; NR_DL_FRAME_PARMS *fp = &UE->frame_parms; if (UE->sl_mode == 2) @@ -343,7 +307,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx radio_tx_burst_flag_t flags = TX_BURST_INVALID; if (UE->received_config_request) { - if (cfg0->duplex_mode == duplex_mode_FDD || get_softmodem_params()->continuous_tx) { + if (fp->frame_type == FDD || get_softmodem_params()->continuous_tx) { flags = TX_BURST_MIDDLE; // In case of Sidelink, USRP write needed only in case transmission // needs to be done in this slot and not based on tdd ULDL configuration. @@ -394,7 +358,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx 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(dev0, writeTimestamp, (void **)txp, dummyBlockSize, fp->nb_antennas_tx, flags); + int tmp = nrue_ru_write_reorder(UE, writeTimestamp, (void **)txp, dummyBlockSize, fp->nb_antennas_tx, flags); AssertFatal(tmp == dummyBlockSize, ""); writeTimestamp += dummyBlockSize; @@ -417,7 +381,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx writeBlockSize); } - int tmp = openair0_write_reorder(dev0, writeTimestamp, (void **)txp, writeBlockSize, fp->nb_antennas_tx, flags); + int tmp = nrue_ru_write_reorder(UE, writeTimestamp, (void **)txp, writeBlockSize, fp->nb_antennas_tx, flags); AssertFatal(tmp == writeBlockSize, ""); } @@ -532,12 +496,9 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE) ul_CarrierFreq, cfg->dl_frequency, UE->target_Nid_cell); - openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; - openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; + nrue_ru_set_freq(UE, ul_CarrierFreq, dl_CarrierFreq, 0); fp->dl_CarrierFreq = dl_CarrierFreq; fp->ul_CarrierFreq = ul_CarrierFreq; - nr_rf_card_config_freq(cfg0, ul_CarrierFreq, dl_CarrierFreq, 0); - dev0->trx_set_freq_func(dev0, cfg0); init_symbol_rotation(fp); } @@ -661,7 +622,6 @@ void UE_dl_processing(void *arg) { void dummyWrite(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, int writeBlockSize) { NR_DL_FRAME_PARMS *fp = &UE->frame_parms; - openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; if (UE->sl_mode == 2) fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params; @@ -672,14 +632,13 @@ void dummyWrite(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, int writeBlo for (int i = 0; i < fp->nb_antennas_tx; i++) dummy_tx[i]=dummy_tx_data[i]; - int tmp = dev0->trx_write_func(dev0, timestamp, dummy_tx, writeBlockSize, fp->nb_antennas_tx, 4); + int tmp = nrue_ru_write(UE, timestamp, dummy_tx, writeBlockSize, fp->nb_antennas_tx, 4); AssertFatal(writeBlockSize == tmp, ""); } void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration_rx_to_tx, bool toTrash) { NR_DL_FRAME_PARMS *fp = &UE->frame_parms; - openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; // two frames for initial sync int num_frames = 2; // In Sidelink worst case SL-SSB can be sent once in 16 frames @@ -701,7 +660,7 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration ((void *)&UE->common_vars.rxdata[i][0]) + 4 * ((x * fp->samples_per_subframe) + get_samples_slot_timestamp(fp, slot)); int read_block_size = get_samples_per_slot(slot, fp); - int tmp = dev0->trx_read_func(dev0, timestamp, rxp, read_block_size, fp->nb_antennas_rx); + int tmp = nrue_ru_read(UE, 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, ""); @@ -722,7 +681,6 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration_rx_to_tx, openair0_timestamp_t rx_offset) { NR_DL_FRAME_PARMS *fp = &UE->frame_parms; - openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; if (UE->sl_mode == 2) fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params; @@ -732,7 +690,7 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int int size = rx_offset; while (size > 0) { const int unitTransfer = min(get_samples_per_slot(slot, fp), size); - const int res = dev0->trx_read_func(dev0, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx); + const int res = nrue_ru_read(UE, 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; @@ -760,9 +718,7 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) { void *UE_thread(void *arg) { //this thread should be over the processing thread to keep in real time - PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg; - openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; - openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card]; + PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *)arg; // int tx_enabled = 0; void *rxp[NB_ANTENNAS_RX]; enum stream_status_e stream_status = STREAM_STATUS_UNSYNC; @@ -814,7 +770,7 @@ void *UE_thread(void *arg) UE->is_synchronized = 1; } else { //warm up the RF board - int64_t tmp; + openair0_timestamp_t tmp; for (int i = 0; i < 50; i++) readFrame(UE, &tmp, duration_rx_to_tx, true); } @@ -854,6 +810,8 @@ void *UE_thread(void *arg) /* For IQ recorder-player we force synchronization to happen in a fixed duration so that the replay runs in sync with recorded samples. */ + extern openair0_config_t openair0_cfg[MAX_CARDS]; + openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; const unsigned int sync_in_frames = cfg0->recplay_conf->u_f_sync; while (trashed_frames != sync_in_frames) { readFrame(UE, &sync_timestamp, duration_rx_to_tx, true); @@ -895,16 +853,16 @@ void *UE_thread(void *arg) if (stream_status == STREAM_STATUS_UNSYNC) { stream_status = STREAM_STATUS_SYNCING; syncInFrame(UE, &sync_timestamp, duration_rx_to_tx, intialSyncOffset); - openair0_write_reorder_clear_context(dev0); + nrue_ru_write_reorder_clear_context(UE); 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_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 - == dev0->trx_read_func(dev0, - &sync_timestamp, - (void **)UE->common_vars.rxdata, - fp->ofdm_symbol_size + fp->nb_prefix_samples0, - fp->nb_antennas_rx), + == nrue_ru_read(UE, + &sync_timestamp, + (void **)UE->common_vars.rxdata, + fp->ofdm_symbol_size + fp->nb_prefix_samples0, + fp->nb_antennas_rx), ""); // we have the decoded frame index in the return of the synch process // and we shifted above to the first slot of next frame @@ -1005,7 +963,7 @@ void *UE_thread(void *arg) const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply; openair0_timestamp_t rx_timestamp; - int tmp = dev0->trx_read_func(dev0, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx); + int tmp = nrue_ru_read(UE, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx); metadata meta = {.slot = curMsg.proc.nr_slot_rx, .frame = curMsg.proc.frame_rx}; UEscopeCopyWithMetadata(UE, ueTimeDomainSamples, rxp[0] - firstSymSamp * sizeof(c16_t), sizeof(c16_t), 1, readBlockSize, 0, &meta); AssertFatal(readBlockSize == tmp, ""); @@ -1020,7 +978,7 @@ void *UE_thread(void *arg) if (first_symbols > 0) { openair0_timestamp_t ignore_timestamp; - int tmp = dev0->trx_read_func(dev0, &ignore_timestamp, (void **)UE->common_vars.rxdata, first_symbols, fp->nb_antennas_rx); + int tmp = nrue_ru_read(UE, &ignore_timestamp, (void **)UE->common_vars.rxdata, first_symbols, fp->nb_antennas_rx); AssertFatal(first_symbols == tmp, ""); } else @@ -1033,8 +991,8 @@ void *UE_thread(void *arg) // 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; - const float deadline_us = samples_diff / cfg0->sample_rate * 1e6; - const uint64_t absolute_deadline_us = current_time.tv_sec * 1e6 + current_time.tv_nsec / 1e3 + deadline_us; + const float deadline_us = samples_diff * 1e3 / fp->samples_per_subframe; + const uint64_t absolute_deadline_us = current_time.tv_sec * 1e6 + current_time.tv_nsec * 1e-3 + deadline_us; // but use current UE->timing_advance value to compute writeBlockSize int writeBlockSize = get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply; diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index b78142cdd6..4ae96e9c59 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -129,9 +129,7 @@ extern uint64_t get_nrUE_optmask(void); extern uint64_t set_nrUE_optmask(uint64_t bitmask); extern nrUE_params_t *get_nrUE_params(void); - // In nr-ue.c -extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg); extern void fill_ue_band_info(void); extern void init_NR_UE(int, char *, char *, char *, int); extern void init_NR_UE_threads(PHY_VARS_NR_UE *ue); diff --git a/radio/COMMON/common_lib.c b/radio/COMMON/common_lib.c index 104546b795..a7cd226ddc 100644 --- a/radio/COMMON/common_lib.c +++ b/radio/COMMON/common_lib.c @@ -187,7 +187,19 @@ static void writerEnqueue(re_order_t *ctx, openair0_timestamp_t timestamp, void pthread_mutex_unlock(&ctx->mutex_store); } -static void writerProcessWaitingQueue(openair0_device_t *device) +typedef struct PHY_VARS_NR_UE_s PHY_VARS_NR_UE; +__attribute__((weak)) int nrue_ru_write(PHY_VARS_NR_UE *UE, + openair0_timestamp_t timestamp, + void **txp, + int nsamps, + int nbAnt, + int flags) +{ + AssertFatal(0, "this weak function implementation should never be called!\n"); + return 0; +} + +static void writerProcessWaitingQueue(PHY_VARS_NR_UE *UE, openair0_device_t *device) { bool found = false; re_order_t *ctx = &device->reOrder; @@ -209,7 +221,11 @@ static void writerProcessWaitingQueue(openair0_device_t *device) pthread_mutex_unlock(&ctx->mutex_store); found = true; if (flags || IS_SOFTMODEM_RFSIM) { - int wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags); + int wroteSamples; + if (UE) + wroteSamples = nrue_ru_write(UE, timestamp, txp, nsamps, nbAnt, flags); + else + wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags); if (wroteSamples != nsamps) LOG_E(HW, "Failed to write to rf\n"); } @@ -226,7 +242,13 @@ static void writerProcessWaitingQueue(openair0_device_t *device) // but to make zerocopy and agnostic design, we need to make a proper ring buffer with mutex protection // mutex (or atomic flags) will be mandatory because this out order system root cause is there are several writer threads -int openair0_write_reorder(openair0_device_t *device, openair0_timestamp_t timestamp, void **txp, int nsamps, int nbAnt, int flags) +int openair0_write_reorder_common(PHY_VARS_NR_UE *UE, + openair0_device_t *device, + openair0_timestamp_t timestamp, + void **txp, + int nsamps, + int nbAnt, + int flags) { int wroteSamples = 0; re_order_t *ctx = &device->reOrder; @@ -240,27 +262,35 @@ int openair0_write_reorder(openair0_device_t *device, openair0_timestamp_t times if (pthread_mutex_trylock(&ctx->mutex_write) == 0) { // We have the write exclusivity if (llabs(timestamp - ctx->nextTS) < MAX_GAP) { // We are writing in sequence of the previous write - if (flags || IS_SOFTMODEM_RFSIM) - wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags); - else + if (flags || IS_SOFTMODEM_RFSIM) { + if (UE) + wroteSamples = nrue_ru_write(UE, timestamp, txp, nsamps, nbAnt, flags); + else + wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags); + } else wroteSamples = nsamps; ctx->nextTS = timestamp + nsamps; } else { writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, flags); } - writerProcessWaitingQueue(device); + writerProcessWaitingQueue(UE, device); pthread_mutex_unlock(&ctx->mutex_write); return wroteSamples ? wroteSamples : nsamps; } writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, flags); if (pthread_mutex_trylock(&ctx->mutex_write) == 0) { - writerProcessWaitingQueue(device); + writerProcessWaitingQueue(UE, device); pthread_mutex_unlock(&ctx->mutex_write); } return nsamps; } +int openair0_write_reorder(openair0_device_t *device, openair0_timestamp_t timestamp, void **txp, int nsamps, int nbAnt, int flags) +{ + return openair0_write_reorder_common(NULL, device, timestamp, txp, nsamps, nbAnt, flags); +} + void openair0_write_reorder_clear_context(openair0_device_t *device) { LOG_I(HW, "received write reorder clear context\n"); diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h index 53eb8b475b..76c5697c3f 100644 --- a/radio/COMMON/common_lib.h +++ b/radio/COMMON/common_lib.h @@ -419,6 +419,12 @@ struct openair0_device { /* !brief RF frontend parameters set by application */ openair0_config_t *openair0_cfg; + /* !brief timestamp of first read */ + openair0_timestamp_t firstTS; + + /* !brief flag indicating that firstTS was initialized */ + bool firstTS_initialized; + /* !brief ETH params set by application */ eth_params_t *eth_params; //! record player data, definition in record_player.h