NR UE: wrap all direct trx_*() function calls in nr_ue_ru_*() functions
This commit is contained in:
@@ -371,3 +371,155 @@ void nrue_ru_end(void)
|
|||||||
openair0_dev[ru_id].trx_end_func(&openair0_dev[ru_id]);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,5 +40,11 @@ void nrue_init_openair0(void);
|
|||||||
|
|
||||||
void nrue_ru_start(void);
|
void nrue_ru_start(void);
|
||||||
void nrue_ru_end(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
|
#endif
|
||||||
|
|||||||
+26
-68
@@ -23,6 +23,7 @@
|
|||||||
#define _GNU_SOURCE // For pthread_setname_np
|
#define _GNU_SOURCE // For pthread_setname_np
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <openair1/PHY/impl_defs_top.h>
|
#include <openair1/PHY/impl_defs_top.h>
|
||||||
|
#include "executables/nr-ue-ru.h"
|
||||||
#include "executables/nr-uesoftmodem.h"
|
#include "executables/nr-uesoftmodem.h"
|
||||||
#include "PHY/INIT/nr_phy_init.h"
|
#include "PHY/INIT/nr_phy_init.h"
|
||||||
#include "NR_MAC_UE/mac_proto.h"
|
#include "NR_MAC_UE/mac_proto.h"
|
||||||
@@ -201,38 +202,10 @@ typedef struct {
|
|||||||
int rx_offset;
|
int rx_offset;
|
||||||
} syncData_t;
|
} 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) {
|
static void UE_synch(void *arg) {
|
||||||
syncData_t *syncD = (syncData_t *)arg;
|
syncData_t *syncD = (syncData_t *)arg;
|
||||||
PHY_VARS_NR_UE *UE = syncD->UE;
|
PHY_VARS_NR_UE *UE = syncD->UE;
|
||||||
UE->is_synchronized = 0;
|
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) {
|
if (UE->target_Nid_cell != -1) {
|
||||||
LOG_W(NR_PHY, "Starting re-sync detection for target Nid_cell %i\n", UE->target_Nid_cell);
|
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;
|
UE->freq_offset = freq_offset - UE->dl_Doppler_shift;
|
||||||
} else {
|
} else {
|
||||||
// rerun with new cell parameters and frequency-offset
|
// rerun with new cell parameters and frequency-offset
|
||||||
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
|
nrue_ru_set_freq(UE, ul_carrier, dl_carrier, freq_offset);
|
||||||
dev0->trx_set_freq_func(dev0, cfg0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_nrUE_params()->agc) {
|
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,
|
LOG_I(PHY, "Got synch: hw_slot_offset %d, carrier off %d Hz\n", hw_slot_offset, freq_offset);
|
||||||
"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]);
|
|
||||||
|
|
||||||
UE->is_synchronized = 1;
|
UE->is_synchronized = 1;
|
||||||
} else {
|
} else {
|
||||||
int gain_change = 0;
|
int gain_change = 0;
|
||||||
if (get_nrUE_params()->agc)
|
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)
|
if (gain_change)
|
||||||
LOG_I(PHY, "synch retry: Rx gain increased \n");
|
LOG_I(PHY, "synch retry: Rx gain increased \n");
|
||||||
else
|
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;
|
PHY_VARS_NR_UE *UE = rxtxD->UE;
|
||||||
const fapi_nr_config_request_t *cfg = &UE->nrUE_config;
|
const fapi_nr_config_request_t *cfg = &UE->nrUE_config;
|
||||||
const UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
|
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;
|
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||||
if (UE->sl_mode == 2)
|
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;
|
radio_tx_burst_flag_t flags = TX_BURST_INVALID;
|
||||||
|
|
||||||
if (UE->received_config_request) {
|
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;
|
flags = TX_BURST_MIDDLE;
|
||||||
// In case of Sidelink, USRP write needed only in case transmission
|
// 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.
|
// 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);
|
const int maxWriteBlockSize = get_samples_per_slot(proc->nr_slot_tx, fp);
|
||||||
while (writeBlockSize > maxWriteBlockSize) {
|
while (writeBlockSize > maxWriteBlockSize) {
|
||||||
const int dummyBlockSize = min(writeBlockSize - maxWriteBlockSize, 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, "");
|
AssertFatal(tmp == dummyBlockSize, "");
|
||||||
|
|
||||||
writeTimestamp += 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);
|
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, "");
|
AssertFatal(tmp == writeBlockSize, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,12 +496,9 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
|
|||||||
ul_CarrierFreq,
|
ul_CarrierFreq,
|
||||||
cfg->dl_frequency,
|
cfg->dl_frequency,
|
||||||
UE->target_Nid_cell);
|
UE->target_Nid_cell);
|
||||||
openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card];
|
nrue_ru_set_freq(UE, ul_CarrierFreq, dl_CarrierFreq, 0);
|
||||||
openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card];
|
|
||||||
fp->dl_CarrierFreq = dl_CarrierFreq;
|
fp->dl_CarrierFreq = dl_CarrierFreq;
|
||||||
fp->ul_CarrierFreq = ul_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);
|
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)
|
void dummyWrite(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, int writeBlockSize)
|
||||||
{
|
{
|
||||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||||
openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card];
|
|
||||||
if (UE->sl_mode == 2)
|
if (UE->sl_mode == 2)
|
||||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
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++)
|
for (int i = 0; i < fp->nb_antennas_tx; i++)
|
||||||
dummy_tx[i]=dummy_tx_data[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, "");
|
AssertFatal(writeBlockSize == tmp, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration_rx_to_tx, bool toTrash)
|
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;
|
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||||
openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card];
|
|
||||||
// two frames for initial sync
|
// two frames for initial sync
|
||||||
int num_frames = 2;
|
int num_frames = 2;
|
||||||
// In Sidelink worst case SL-SSB can be sent once in 16 frames
|
// 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));
|
((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 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);
|
UEscopeCopy(UE, ueTimeDomainSamplesBeforeSync, rxp[0], sizeof(c16_t), 1, read_block_size, 0);
|
||||||
AssertFatal(read_block_size == tmp, "");
|
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)
|
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;
|
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||||
openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card];
|
|
||||||
if (UE->sl_mode == 2)
|
if (UE->sl_mode == 2)
|
||||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
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;
|
int size = rx_offset;
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
const int unitTransfer = min(get_samples_per_slot(slot, fp), size);
|
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);
|
DevAssert(unitTransfer == res);
|
||||||
if (IS_SOFTMODEM_RFSIM) {
|
if (IS_SOFTMODEM_RFSIM) {
|
||||||
int ta = UE->timing_advance + UE->timing_advance_ntn;
|
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)
|
void *UE_thread(void *arg)
|
||||||
{
|
{
|
||||||
//this thread should be over the processing thread to keep in real time
|
//this thread should be over the processing thread to keep in real time
|
||||||
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
|
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];
|
|
||||||
// int tx_enabled = 0;
|
// int tx_enabled = 0;
|
||||||
void *rxp[NB_ANTENNAS_RX];
|
void *rxp[NB_ANTENNAS_RX];
|
||||||
enum stream_status_e stream_status = STREAM_STATUS_UNSYNC;
|
enum stream_status_e stream_status = STREAM_STATUS_UNSYNC;
|
||||||
@@ -814,7 +770,7 @@ void *UE_thread(void *arg)
|
|||||||
UE->is_synchronized = 1;
|
UE->is_synchronized = 1;
|
||||||
} else {
|
} else {
|
||||||
//warm up the RF board
|
//warm up the RF board
|
||||||
int64_t tmp;
|
openair0_timestamp_t tmp;
|
||||||
for (int i = 0; i < 50; i++)
|
for (int i = 0; i < 50; i++)
|
||||||
readFrame(UE, &tmp, duration_rx_to_tx, true);
|
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
|
/* For IQ recorder-player we force synchronization to happen in a fixed duration so that
|
||||||
the replay runs in sync with recorded samples.
|
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;
|
const unsigned int sync_in_frames = cfg0->recplay_conf->u_f_sync;
|
||||||
while (trashed_frames != sync_in_frames) {
|
while (trashed_frames != sync_in_frames) {
|
||||||
readFrame(UE, &sync_timestamp, duration_rx_to_tx, true);
|
readFrame(UE, &sync_timestamp, duration_rx_to_tx, true);
|
||||||
@@ -895,16 +853,16 @@ void *UE_thread(void *arg)
|
|||||||
if (stream_status == STREAM_STATUS_UNSYNC) {
|
if (stream_status == STREAM_STATUS_UNSYNC) {
|
||||||
stream_status = STREAM_STATUS_SYNCING;
|
stream_status = STREAM_STATUS_SYNCING;
|
||||||
syncInFrame(UE, &sync_timestamp, duration_rx_to_tx, intialSyncOffset);
|
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
|
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);
|
LOG_I(PHY, "max_pos_acc = %d, shiftForNextFrame = %d\n", UE->max_pos_acc, shiftForNextFrame);
|
||||||
// read in first symbol
|
// read in first symbol
|
||||||
AssertFatal(fp->ofdm_symbol_size + fp->nb_prefix_samples0
|
AssertFatal(fp->ofdm_symbol_size + fp->nb_prefix_samples0
|
||||||
== dev0->trx_read_func(dev0,
|
== nrue_ru_read(UE,
|
||||||
&sync_timestamp,
|
&sync_timestamp,
|
||||||
(void **)UE->common_vars.rxdata,
|
(void **)UE->common_vars.rxdata,
|
||||||
fp->ofdm_symbol_size + fp->nb_prefix_samples0,
|
fp->ofdm_symbol_size + fp->nb_prefix_samples0,
|
||||||
fp->nb_antennas_rx),
|
fp->nb_antennas_rx),
|
||||||
"");
|
"");
|
||||||
// we have the decoded frame index in the return of the synch process
|
// we have the decoded frame index in the return of the synch process
|
||||||
// and we shifted above to the first slot of next frame
|
// 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;
|
const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply;
|
||||||
openair0_timestamp_t rx_timestamp;
|
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};
|
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);
|
UEscopeCopyWithMetadata(UE, ueTimeDomainSamples, rxp[0] - firstSymSamp * sizeof(c16_t), sizeof(c16_t), 1, readBlockSize, 0, &meta);
|
||||||
AssertFatal(readBlockSize == tmp, "");
|
AssertFatal(readBlockSize == tmp, "");
|
||||||
@@ -1020,7 +978,7 @@ void *UE_thread(void *arg)
|
|||||||
|
|
||||||
if (first_symbols > 0) {
|
if (first_symbols > 0) {
|
||||||
openair0_timestamp_t ignore_timestamp;
|
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, "");
|
AssertFatal(first_symbols == tmp, "");
|
||||||
|
|
||||||
} else
|
} else
|
||||||
@@ -1033,8 +991,8 @@ void *UE_thread(void *arg)
|
|||||||
|
|
||||||
// Calculate TX deadline, approximately 1 symbol before the first sample should be written
|
// 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 uint64_t samples_diff = writeTimestamp - rx_timestamp - fp->ofdm_symbol_size;
|
||||||
const float deadline_us = samples_diff / cfg0->sample_rate * 1e6;
|
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 / 1e3 + deadline_us;
|
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
|
// 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;
|
int writeBlockSize = get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply;
|
||||||
|
|||||||
@@ -129,9 +129,7 @@ extern uint64_t get_nrUE_optmask(void);
|
|||||||
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
|
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
|
||||||
extern nrUE_params_t *get_nrUE_params(void);
|
extern nrUE_params_t *get_nrUE_params(void);
|
||||||
|
|
||||||
|
|
||||||
// In nr-ue.c
|
// 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 fill_ue_band_info(void);
|
||||||
extern void init_NR_UE(int, char *, char *, char *, int);
|
extern void init_NR_UE(int, char *, char *, char *, int);
|
||||||
extern void init_NR_UE_threads(PHY_VARS_NR_UE *ue);
|
extern void init_NR_UE_threads(PHY_VARS_NR_UE *ue);
|
||||||
|
|||||||
@@ -187,7 +187,19 @@ static void writerEnqueue(re_order_t *ctx, openair0_timestamp_t timestamp, void
|
|||||||
pthread_mutex_unlock(&ctx->mutex_store);
|
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;
|
bool found = false;
|
||||||
re_order_t *ctx = &device->reOrder;
|
re_order_t *ctx = &device->reOrder;
|
||||||
@@ -209,7 +221,11 @@ static void writerProcessWaitingQueue(openair0_device_t *device)
|
|||||||
pthread_mutex_unlock(&ctx->mutex_store);
|
pthread_mutex_unlock(&ctx->mutex_store);
|
||||||
found = true;
|
found = true;
|
||||||
if (flags || IS_SOFTMODEM_RFSIM) {
|
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)
|
if (wroteSamples != nsamps)
|
||||||
LOG_E(HW, "Failed to write to rf\n");
|
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
|
// 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
|
// 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;
|
int wroteSamples = 0;
|
||||||
re_order_t *ctx = &device->reOrder;
|
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) {
|
if (pthread_mutex_trylock(&ctx->mutex_write) == 0) {
|
||||||
// We have the write exclusivity
|
// We have the write exclusivity
|
||||||
if (llabs(timestamp - ctx->nextTS) < MAX_GAP) { // We are writing in sequence of the previous write
|
if (llabs(timestamp - ctx->nextTS) < MAX_GAP) { // We are writing in sequence of the previous write
|
||||||
if (flags || IS_SOFTMODEM_RFSIM)
|
if (flags || IS_SOFTMODEM_RFSIM) {
|
||||||
wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags);
|
if (UE)
|
||||||
else
|
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;
|
wroteSamples = nsamps;
|
||||||
ctx->nextTS = timestamp + nsamps;
|
ctx->nextTS = timestamp + nsamps;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, flags);
|
writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, flags);
|
||||||
}
|
}
|
||||||
writerProcessWaitingQueue(device);
|
writerProcessWaitingQueue(UE, device);
|
||||||
pthread_mutex_unlock(&ctx->mutex_write);
|
pthread_mutex_unlock(&ctx->mutex_write);
|
||||||
return wroteSamples ? wroteSamples : nsamps;
|
return wroteSamples ? wroteSamples : nsamps;
|
||||||
}
|
}
|
||||||
writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, flags);
|
writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, flags);
|
||||||
if (pthread_mutex_trylock(&ctx->mutex_write) == 0) {
|
if (pthread_mutex_trylock(&ctx->mutex_write) == 0) {
|
||||||
writerProcessWaitingQueue(device);
|
writerProcessWaitingQueue(UE, device);
|
||||||
pthread_mutex_unlock(&ctx->mutex_write);
|
pthread_mutex_unlock(&ctx->mutex_write);
|
||||||
}
|
}
|
||||||
return nsamps;
|
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)
|
void openair0_write_reorder_clear_context(openair0_device_t *device)
|
||||||
{
|
{
|
||||||
LOG_I(HW, "received write reorder clear context\n");
|
LOG_I(HW, "received write reorder clear context\n");
|
||||||
|
|||||||
@@ -419,6 +419,12 @@ struct openair0_device {
|
|||||||
/* !brief RF frontend parameters set by application */
|
/* !brief RF frontend parameters set by application */
|
||||||
openair0_config_t *openair0_cfg;
|
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 */
|
/* !brief ETH params set by application */
|
||||||
eth_params_t *eth_params;
|
eth_params_t *eth_params;
|
||||||
//! record player data, definition in record_player.h
|
//! record player data, definition in record_player.h
|
||||||
|
|||||||
Reference in New Issue
Block a user