SL PSBCH: MAC->PHY cfg, PSBCH scheduler + supporting functions + enable system testing & scope
- Phy config update and Sidelink frame parameters initialisation - PSBCH scheduler to trigger TX PSBCH/RX PSBCH actions - Sidelink indication with rx ind to trigger send SL-MIB to MAC - Enable Scope for PSBCH use -d or --dqt - Enable system testing of PSBCH for example using RFSIMULATOR: - UE1 is a SYNCRONISATION SOURCE UE which transmits PSBCH started using command - sudo ./nr-uesoftmodem --sl-mode 2 --sync-ref 4 --rfsim --rfsimulator.serveraddr server - UE2 syncs onto UE1 during sidelink search, gets the timing and continues to receive PSBCH started using command - sudo ./nr-uesoftmodem --sl-mode 2 --rfsim --rfsimulator.serveraddr 127.0.0.1 - In the default use case 2 Sidelink SSBs sent over 16 frames. - In case SL-SSB configuration needs to be changed use -O option in the above command like -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sidelink_preconfig_1txpool.conf
This commit is contained in:
+204
-100
@@ -364,14 +364,24 @@ static void UE_synch(void *arg) {
|
||||
LOG_I(PHY, "[UE thread Synch] Running Initial Synch \n");
|
||||
|
||||
uint64_t dl_carrier, ul_carrier;
|
||||
nr_get_carrier_frequencies(UE, &dl_carrier, &ul_carrier);
|
||||
nr_initial_sync_t ret = nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa, syncD->gscnInfo, syncD->numGscn);
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
nr_initial_sync_t ret = {false, 0, 0};
|
||||
if (UE->sl_mode == 2) {
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
dl_carrier = fp->sl_CarrierFreq;
|
||||
ul_carrier = fp->sl_CarrierFreq;
|
||||
ret = sl_nr_slss_search(UE, &syncD->proc, SL_NR_SSB_REPETITION_IN_FRAMES);
|
||||
} else {
|
||||
nr_get_carrier_frequencies(UE, &dl_carrier, &ul_carrier);
|
||||
ret = nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa, syncD->gscnInfo, syncD->numGscn);
|
||||
}
|
||||
|
||||
if (ret.cell_detected) {
|
||||
syncD->rx_offset = ret.rx_offset;
|
||||
const int freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
|
||||
const int hw_slot_offset =
|
||||
((ret.rx_offset << 1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe)
|
||||
+ round((float)((ret.rx_offset << 1) % UE->frame_parms.samples_per_subframe) / UE->frame_parms.samples_per_slot0);
|
||||
((ret.rx_offset << 1) / fp->samples_per_subframe * fp->slots_per_subframe)
|
||||
+ round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0);
|
||||
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
// todo: the freq_offset computed on DL shall be scaled before being applied to UL
|
||||
@@ -390,15 +400,19 @@ static void UE_synch(void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
|
||||
|
||||
static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action)
|
||||
{
|
||||
PHY_VARS_NR_UE *UE = rxtxD->UE;
|
||||
const UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
void *txp[NB_ANTENNAS_TX];
|
||||
int slot = proc->nr_slot_tx;
|
||||
for (int i = 0; i < UE->frame_parms.nb_antennas_tx; i++)
|
||||
txp[i] = (void *)&UE->common_vars.txData[i][UE->frame_parms.get_samples_slot_timestamp(slot, &UE->frame_parms, 0)];
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++)
|
||||
txp[i] = (void *)&UE->common_vars.txData[i][fp->get_samples_slot_timestamp(slot, fp, 0)];
|
||||
|
||||
radio_tx_burst_flag_t flags = TX_BURST_INVALID;
|
||||
|
||||
@@ -406,27 +420,33 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
|
||||
if (mac->phy_config_request_sent &&
|
||||
openair0_cfg[0].duplex_mode == duplex_mode_TDD &&
|
||||
!get_softmodem_params()->continuous_tx) {
|
||||
int slots_frame = UE->frame_parms.slots_per_frame;
|
||||
int curr_slot = nr_ue_slot_select(&UE->nrUE_config, slot);
|
||||
if (curr_slot != NR_DOWNLINK_SLOT) {
|
||||
int next_slot = nr_ue_slot_select(&UE->nrUE_config, (slot + 1) % slots_frame);
|
||||
int prev_slot = nr_ue_slot_select(&UE->nrUE_config, (slot + slots_frame - 1) % slots_frame);
|
||||
if (prev_slot == NR_DOWNLINK_SLOT)
|
||||
flags = TX_BURST_START;
|
||||
else if (next_slot == NR_DOWNLINK_SLOT)
|
||||
flags = TX_BURST_END;
|
||||
else
|
||||
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.
|
||||
if (UE->sl_mode == 2) {
|
||||
if (sl_tx_action)
|
||||
flags = TX_BURST_START_AND_END;
|
||||
} else {
|
||||
int slots_frame = fp->slots_per_frame;
|
||||
int curr_slot = nr_ue_slot_select(&UE->nrUE_config, slot);
|
||||
if (curr_slot != NR_DOWNLINK_SLOT) {
|
||||
int next_slot = nr_ue_slot_select(&UE->nrUE_config, (slot + 1) % slots_frame);
|
||||
int prev_slot = nr_ue_slot_select(&UE->nrUE_config, (slot + slots_frame - 1) % slots_frame);
|
||||
if (prev_slot == NR_DOWNLINK_SLOT)
|
||||
flags = TX_BURST_START;
|
||||
else if (next_slot == NR_DOWNLINK_SLOT)
|
||||
flags = TX_BURST_END;
|
||||
else
|
||||
flags = TX_BURST_MIDDLE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
flags = TX_BURST_MIDDLE;
|
||||
}
|
||||
|
||||
int tmp =
|
||||
openair0_write_reorder(&UE->rfdevice, proc->timestamp_tx, txp, rxtxD->writeBlockSize, UE->frame_parms.nb_antennas_tx, flags);
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, proc->timestamp_tx, txp, rxtxD->writeBlockSize, fp->nb_antennas_tx, flags);
|
||||
AssertFatal(tmp == rxtxD->writeBlockSize, "");
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++)
|
||||
memset(txp[i], 0, rxtxD->writeBlockSize);
|
||||
}
|
||||
|
||||
@@ -436,6 +456,7 @@ void processSlotTX(void *arg)
|
||||
const UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
|
||||
PHY_VARS_NR_UE *UE = rxtxD->UE;
|
||||
nr_phy_data_tx_t phy_data = {0};
|
||||
bool sl_tx_action = false;
|
||||
|
||||
// Force sequential execution, even if we launch in // for all slots
|
||||
// at least ULstatus variable is a pure race condition that is quickly detected by assert() in the code because one thread sets it
|
||||
@@ -486,35 +507,72 @@ void processSlotTX(void *arg)
|
||||
"Internal error: extra event on Tx waiting queue for slot %d, event comes from rx slot %d\n",
|
||||
proc->nr_slot_tx,
|
||||
*(int *)NotifiedFifoData(res));
|
||||
// trigger L2 to run ue_scheduler thru IF module
|
||||
// [TODO] mapping right after NR initial sync
|
||||
if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
|
||||
start_meas(&UE->ue_ul_indication_stats);
|
||||
nr_uplink_indication_t ul_indication = {.module_id = UE->Mod_id,
|
||||
.gNB_index = proc->gNB_id,
|
||||
.cc_id = UE->CC_id,
|
||||
.frame = proc->frame_tx,
|
||||
.slot = proc->nr_slot_tx,
|
||||
.phy_data = &phy_data};
|
||||
|
||||
UE->if_inst->ul_indication(&ul_indication);
|
||||
stop_meas(&UE->ue_ul_indication_stats);
|
||||
if (UE->sl_mode == 2 && proc->tx_slot_type == NR_SIDELINK_SLOT) {
|
||||
// trigger L2 to run ue_sidelink_scheduler thru IF module
|
||||
if (UE->if_inst != NULL && UE->if_inst->sl_indication != NULL) {
|
||||
start_meas(&UE->ue_ul_indication_stats);
|
||||
nr_sidelink_indication_t sl_indication = {.module_id = UE->Mod_id,
|
||||
.gNB_index = proc->gNB_id,
|
||||
.cc_id = UE->CC_id,
|
||||
.frame_tx = proc->frame_tx,
|
||||
.slot_tx = proc->nr_slot_tx,
|
||||
.frame_rx = proc->frame_rx,
|
||||
.slot_rx = proc->nr_slot_rx,
|
||||
.slot_type = SIDELINK_SLOT_TYPE_TX,
|
||||
.phy_data = &phy_data};
|
||||
|
||||
UE->if_inst->sl_indication(&sl_indication);
|
||||
stop_meas(&UE->ue_ul_indication_stats);
|
||||
}
|
||||
|
||||
if (phy_data.sl_tx_action) {
|
||||
|
||||
AssertFatal((phy_data.sl_tx_action >= SL_NR_CONFIG_TYPE_TX_PSBCH &&
|
||||
phy_data.sl_tx_action < SL_NR_CONFIG_TYPE_TX_MAXIMUM), "Incorrect SL TX Action Scheduled\n");
|
||||
|
||||
phy_procedures_nrUE_SL_TX(UE, proc, &phy_data);
|
||||
|
||||
sl_tx_action = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
// trigger L2 to run ue_scheduler thru IF module
|
||||
// [TODO] mapping right after NR initial sync
|
||||
if (UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
|
||||
start_meas(&UE->ue_ul_indication_stats);
|
||||
nr_uplink_indication_t ul_indication = {.module_id = UE->Mod_id,
|
||||
.gNB_index = proc->gNB_id,
|
||||
.cc_id = UE->CC_id,
|
||||
.frame = proc->frame_tx,
|
||||
.slot = proc->nr_slot_tx,
|
||||
.phy_data = &phy_data};
|
||||
|
||||
UE->if_inst->ul_indication(&ul_indication);
|
||||
stop_meas(&UE->ue_ul_indication_stats);
|
||||
}
|
||||
|
||||
phy_procedures_nrUE_TX(UE, proc, &phy_data);
|
||||
}
|
||||
|
||||
phy_procedures_nrUE_TX(UE, proc, &phy_data);
|
||||
}
|
||||
|
||||
notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(int), 0, NULL, NULL);
|
||||
int *msgData = (int *)NotifiedFifoData(newElt);
|
||||
int newslot = (proc->nr_slot_tx + 1) % UE->frame_parms.slots_per_frame;
|
||||
int slots_per_frame = (UE->sl_mode == 2) ? UE->SL_UE_PHY_PARAMS.sl_frame_params.slots_per_frame
|
||||
: UE->frame_parms.slots_per_frame;
|
||||
int newslot = (proc->nr_slot_tx + 1) % slots_per_frame;
|
||||
*msgData = newslot;
|
||||
pushNotifiedFIFO(UE->tx_resume_ind_fifo + newslot, newElt);
|
||||
RU_write(rxtxD);
|
||||
RU_write(rxtxD, sl_tx_action);
|
||||
}
|
||||
|
||||
static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc, int *tx_wait_for_dlsch, nr_phy_data_t *phy_data)
|
||||
{
|
||||
int sampleShift = 0;
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
if (IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa) {
|
||||
|
||||
// Start synchronization with a target gNB
|
||||
@@ -527,11 +585,11 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc
|
||||
}
|
||||
|
||||
/* send tick to RLC and PDCP every ms */
|
||||
if (proc->nr_slot_rx % UE->frame_parms.slots_per_subframe == 0) {
|
||||
if (proc->nr_slot_rx % fp->slots_per_subframe == 0) {
|
||||
void nr_rlc_tick(int frame, int subframe);
|
||||
void nr_pdcp_tick(int frame, int subframe);
|
||||
nr_rlc_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe);
|
||||
nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe);
|
||||
nr_rlc_tick(proc->frame_rx, proc->nr_slot_rx / fp->slots_per_subframe);
|
||||
nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / fp->slots_per_subframe);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,7 +609,26 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc
|
||||
}
|
||||
}
|
||||
|
||||
ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx);
|
||||
if (UE->sl_mode == 2) {
|
||||
if (proc->rx_slot_type == NR_SIDELINK_SLOT) {
|
||||
phy_data->sl_rx_action = 0;
|
||||
if (UE->if_inst != NULL && UE->if_inst->sl_indication != NULL) {
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
nr_fill_sl_indication(&sl_indication, NULL, NULL, proc, UE, phy_data);
|
||||
UE->if_inst->sl_indication(&sl_indication);
|
||||
}
|
||||
|
||||
if (phy_data->sl_rx_action) {
|
||||
|
||||
AssertFatal((phy_data->sl_rx_action >= SL_NR_CONFIG_TYPE_RX_PSBCH &&
|
||||
phy_data->sl_rx_action < SL_NR_CONFIG_TYPE_RX_MAXIMUM), "Incorrect SL RX Action Scheduled\n");
|
||||
|
||||
sampleShift = psbch_pscch_processing(UE, proc, phy_data);
|
||||
}
|
||||
}
|
||||
} else
|
||||
ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx);
|
||||
|
||||
return sampleShift;
|
||||
}
|
||||
|
||||
@@ -561,80 +638,86 @@ void UE_dl_processing(void *arg) {
|
||||
PHY_VARS_NR_UE *UE = rxtxD->UE;
|
||||
nr_phy_data_t *phy_data = &rxtxD->phy_data;
|
||||
|
||||
pdsch_processing(UE, proc, phy_data);
|
||||
if (!UE->sl_mode)
|
||||
pdsch_processing(UE, proc, phy_data);
|
||||
}
|
||||
|
||||
void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) {
|
||||
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
|
||||
int16_t dummy_tx_data[UE->frame_parms.nb_antennas_tx][2*writeBlockSize]; // 2 because the function we call use pairs of int16_t implicitly as complex numbers
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
void *dummy_tx[fp->nb_antennas_tx];
|
||||
// 2 because the function we call use pairs of int16_t implicitly as complex numbers
|
||||
int16_t dummy_tx_data[fp->nb_antennas_tx][2 * writeBlockSize];
|
||||
memset(dummy_tx_data, 0, sizeof(dummy_tx_data));
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++)
|
||||
dummy_tx[i]=dummy_tx_data[i];
|
||||
|
||||
int tmp = UE->rfdevice.trx_write_func(&UE->rfdevice, timestamp, dummy_tx, writeBlockSize, UE->frame_parms.nb_antennas_tx, 4);
|
||||
int tmp = UE->rfdevice.trx_write_func(&UE->rfdevice, timestamp, dummy_tx, writeBlockSize, fp->nb_antennas_tx, 4);
|
||||
AssertFatal(writeBlockSize == tmp, "");
|
||||
}
|
||||
|
||||
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) {
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
// two frames for initial sync
|
||||
int num_frames = 2;
|
||||
// In Sidelink worst case SL-SSB can be sent once in 16 frames
|
||||
if (UE->sl_mode == 2) {
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
num_frames = SL_NR_PSBCH_REPETITION_IN_FRAMES;
|
||||
}
|
||||
|
||||
void *rxp[NB_ANTENNAS_RX];
|
||||
|
||||
for(int x=0; x<20; x++) { // two frames for initial sync
|
||||
for (int slot=0; slot<UE->frame_parms.slots_per_subframe; slot ++ ) {
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) {
|
||||
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++) {
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++) {
|
||||
if (toTrash)
|
||||
rxp[i]=malloc16(UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms)*4);
|
||||
rxp[i] = malloc16(fp->get_samples_per_slot(slot, fp) * 4);
|
||||
else
|
||||
rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) +
|
||||
4*((x*UE->frame_parms.samples_per_subframe)+
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot,&UE->frame_parms,0));
|
||||
rxp[i] = ((void *)&UE->common_vars.rxdata[i][0])
|
||||
+ 4 * ((x * fp->samples_per_subframe) + fp->get_samples_slot_timestamp(slot, fp, 0));
|
||||
}
|
||||
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
rxp,
|
||||
UE->frame_parms.get_samples_per_slot(slot, &UE->frame_parms),
|
||||
UE->frame_parms.nb_antennas_rx);
|
||||
AssertFatal(UE->frame_parms.get_samples_per_slot(slot, &UE->frame_parms) == tmp, "");
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, rxp, fp->get_samples_per_slot(slot, fp), fp->nb_antennas_rx);
|
||||
AssertFatal(fp->get_samples_per_slot(slot, fp) == tmp, "");
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM)
|
||||
dummyWrite(UE,*timestamp, UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms));
|
||||
dummyWrite(UE, *timestamp, fp->get_samples_per_slot(slot, fp));
|
||||
if (toTrash)
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
free(rxp[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, openair0_timestamp rx_offset)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
LOG_I(PHY, "Resynchronizing RX by %ld samples\n", rx_offset);
|
||||
|
||||
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
|
||||
// Resynchonize by slot (will work with numerology 1 only)
|
||||
for (int size = rx_offset; size > 0; size -= UE->frame_parms.samples_per_subframe / 2) {
|
||||
int unitTransfer = size > UE->frame_parms.samples_per_subframe / 2 ? UE->frame_parms.samples_per_subframe / 2 : size;
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx);
|
||||
for (int size = rx_offset; size > 0; size -= fp->samples_per_subframe / 2) {
|
||||
int unitTransfer = size > fp->samples_per_subframe / 2 ? fp->samples_per_subframe / 2 : size;
|
||||
int tmp =
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx);
|
||||
DevAssert(unitTransfer == tmp);
|
||||
}
|
||||
} else {
|
||||
*timestamp += UE->frame_parms.get_samples_per_slot(1, &UE->frame_parms);
|
||||
for (int size = rx_offset; size > 0; size -= UE->frame_parms.samples_per_subframe) {
|
||||
int unitTransfer = size > UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size;
|
||||
*timestamp += fp->get_samples_per_slot(1, fp);
|
||||
for (int size = rx_offset; size > 0; size -= fp->samples_per_subframe) {
|
||||
int unitTransfer = size > fp->samples_per_subframe ? fp->samples_per_subframe : size;
|
||||
// we write before read because gNB waits for UE to write and both executions halt
|
||||
// this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot
|
||||
if (IS_SOFTMODEM_RFSIM)
|
||||
dummyWrite(UE, *timestamp, unitTransfer);
|
||||
int res = UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx);
|
||||
int res =
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx);
|
||||
DevAssert(unitTransfer == res);
|
||||
*timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write
|
||||
}
|
||||
@@ -667,6 +750,13 @@ void *UE_thread(void *arg)
|
||||
fapi_nr_config_request_t *cfg = &UE->nrUE_config;
|
||||
int tmp = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]);
|
||||
AssertFatal(tmp == 0, "Could not load the device\n");
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
sl_nr_phy_config_request_t *sl_cfg = NULL;
|
||||
if (UE->sl_mode == 2) {
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
sl_cfg = &UE->SL_UE_PHY_PARAMS.sl_config;
|
||||
}
|
||||
|
||||
UE->rfdevice.host_type = RAU_HOST;
|
||||
UE->is_synchronized = 0;
|
||||
int tmp2 = UE->rfdevice.trx_start_func(&UE->rfdevice);
|
||||
@@ -682,7 +772,7 @@ void *UE_thread(void *arg)
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
|
||||
bool syncRunning = false;
|
||||
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
|
||||
const int nb_slot_frame = fp->slots_per_frame;
|
||||
int absolute_slot = 0, decoded_frame_rx = INT_MAX, trashed_frames = 0;
|
||||
int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME];
|
||||
|
||||
@@ -693,6 +783,11 @@ void *UE_thread(void *arg)
|
||||
int shiftForNextFrame = 0;
|
||||
int intialSyncOffset = 0;
|
||||
openair0_timestamp sync_timestamp;
|
||||
|
||||
if (get_softmodem_params()->sync_ref && UE->sl_mode == 2) {
|
||||
UE->is_synchronized = 1;
|
||||
}
|
||||
|
||||
while (!oai_exit) {
|
||||
if (syncRunning) {
|
||||
notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool));
|
||||
@@ -701,7 +796,10 @@ void *UE_thread(void *arg)
|
||||
syncRunning = false;
|
||||
if (UE->is_synchronized) {
|
||||
UE->synch_request.received_synch_request = 0;
|
||||
decoded_frame_rx = mac->mib_frame;
|
||||
if (UE->sl_mode == 2)
|
||||
decoded_frame_rx = UE->SL_UE_PHY_PARAMS.sync_params.DFN;
|
||||
else
|
||||
decoded_frame_rx = mac->mib_frame;
|
||||
LOG_A(PHY,
|
||||
"UE synchronized! decoded_frame_rx=%d UE->init_sync_frame=%d trashed_frames=%d\n",
|
||||
decoded_frame_rx,
|
||||
@@ -723,7 +821,7 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
} else {
|
||||
readFrame(UE, &sync_timestamp, true);
|
||||
trashed_frames += 2;
|
||||
trashed_frames += ((UE->sl_mode == 2) ? SL_NR_PSBCH_REPETITION_IN_FRAMES : 2);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -763,18 +861,22 @@ void *UE_thread(void *arg)
|
||||
openair0_write_reorder_clear_context(&UE->rfdevice);
|
||||
shiftForNextFrame = 0; // will be used to track clock drift
|
||||
// read in first symbol
|
||||
AssertFatal(UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0
|
||||
AssertFatal(fp->ofdm_symbol_size + fp->nb_prefix_samples0
|
||||
== UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
&sync_timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0,
|
||||
UE->frame_parms.nb_antennas_rx),
|
||||
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
|
||||
decoded_frame_rx++;
|
||||
// we do ++ first in the regular processing, so it will be begin of frame;
|
||||
absolute_slot = 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;
|
||||
}
|
||||
// We have resynchronized, maybe after RF loss so we need to purge any existing context
|
||||
memset(tx_wait_for_dlsch, 0, sizeof(tx_wait_for_dlsch));
|
||||
for (int i = 0; i < num_ind_fifo; i++) {
|
||||
@@ -797,18 +899,22 @@ void *UE_thread(void *arg)
|
||||
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;
|
||||
if (mac->phy_config_request_sent) {
|
||||
curMsg.proc.rx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_rx);
|
||||
curMsg.proc.tx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_tx);
|
||||
if (UE->sl_mode) {
|
||||
curMsg.proc.rx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_rx, TDD);
|
||||
curMsg.proc.tx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_tx, TDD);
|
||||
} else {
|
||||
curMsg.proc.rx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_rx);
|
||||
curMsg.proc.tx_slot_type = nr_ue_slot_select(cfg, curMsg.proc.nr_slot_tx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
curMsg.proc.rx_slot_type = NR_DOWNLINK_SLOT;
|
||||
curMsg.proc.tx_slot_type = NR_DOWNLINK_SLOT;
|
||||
}
|
||||
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms);
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars
|
||||
.rxdata[i][firstSymSamp + UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, 0)];
|
||||
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)];
|
||||
|
||||
int iq_shift_to_apply = 0;
|
||||
if (slot_nr == nb_slot_frame - 1) {
|
||||
@@ -817,14 +923,14 @@ void *UE_thread(void *arg)
|
||||
shiftForNextFrame = 0; // We will get a new measured offset if we decode PBCH
|
||||
}
|
||||
|
||||
const int readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms) - iq_shift_to_apply;
|
||||
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, UE->frame_parms.nb_antennas_rx);
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx);
|
||||
AssertFatal(readBlockSize == tmp, "");
|
||||
|
||||
if(slot_nr == (nb_slot_frame - 1)) {
|
||||
// read in first symbol of next frame and adjust for timing drift
|
||||
int first_symbols = UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0; // first symbol of every frames
|
||||
int first_symbols = fp->ofdm_symbol_size + fp->nb_prefix_samples0; // first symbol of every frames
|
||||
|
||||
if (first_symbols > 0) {
|
||||
openair0_timestamp ignore_timestamp;
|
||||
@@ -832,7 +938,7 @@ void *UE_thread(void *arg)
|
||||
&ignore_timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
first_symbols,
|
||||
UE->frame_parms.nb_antennas_rx);
|
||||
fp->nb_antennas_rx);
|
||||
AssertFatal(first_symbols == tmp, "");
|
||||
|
||||
} else
|
||||
@@ -840,13 +946,11 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
// use previous timing_advance value to compute writeTimestamp
|
||||
const openair0_timestamp writeTimestamp =
|
||||
rx_timestamp + UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, DURATION_RX_TO_TX) - firstSymSamp
|
||||
- UE->N_TA_offset - timing_advance;
|
||||
const openair0_timestamp writeTimestamp = rx_timestamp + fp->get_samples_slot_timestamp(slot_nr, fp, DURATION_RX_TO_TX)
|
||||
- firstSymSamp - UE->N_TA_offset - timing_advance;
|
||||
|
||||
// but use current UE->timing_advance value to compute writeBlockSize
|
||||
int writeBlockSize =
|
||||
UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms) - iq_shift_to_apply;
|
||||
int writeBlockSize = fp->get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, fp) - iq_shift_to_apply;
|
||||
if (UE->timing_advance != timing_advance) {
|
||||
writeBlockSize -= UE->timing_advance - timing_advance;
|
||||
timing_advance = UE->timing_advance;
|
||||
@@ -895,7 +999,7 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(i);
|
||||
mac->if_module = nr_ue_if_module_init(i);
|
||||
AssertFatal(mac->if_module, "can not initialize IF module\n");
|
||||
if (!get_softmodem_params()->sa) {
|
||||
if (!get_softmodem_params()->sa || !get_softmodem_params()->sl_mode) {
|
||||
init_nsa_message(rrc_inst, reconfig_file, rbconfig_file);
|
||||
nr_rlc_activate_srb0(mac_inst->crnti, NULL, send_srb0_rrc);
|
||||
}
|
||||
|
||||
@@ -315,13 +315,17 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
|
||||
|
||||
}
|
||||
|
||||
void init_openair0(void) {
|
||||
void init_openair0()
|
||||
{
|
||||
int card;
|
||||
int freq_off = 0;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms;
|
||||
bool is_sidelink = (get_softmodem_params()->sl_mode) ? true : false;
|
||||
if (is_sidelink)
|
||||
frame_parms = &PHY_vars_UE_g[0][0]->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
for (card=0; card<MAX_CARDS; card++) {
|
||||
uint64_t dl_carrier, ul_carrier, sl_carrier;
|
||||
uint64_t dl_carrier, ul_carrier;
|
||||
openair0_cfg[card].configFilename = NULL;
|
||||
openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
|
||||
openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3;
|
||||
@@ -347,15 +351,14 @@ void init_openair0(void) {
|
||||
openair0_cfg[card].rx_num_channels,
|
||||
duplex_mode[openair0_cfg[card].duplex_mode]);
|
||||
|
||||
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
|
||||
if (is_sidelink) {
|
||||
dl_carrier = frame_parms->dl_CarrierFreq;
|
||||
ul_carrier = frame_parms->ul_CarrierFreq;
|
||||
} else
|
||||
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
|
||||
|
||||
nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off);
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
nr_get_carrier_frequencies_sl(PHY_vars_UE_g[0][0], &sl_carrier);
|
||||
nr_rf_card_config_freq(&openair0_cfg[card], sl_carrier, sl_carrier, freq_off);
|
||||
}
|
||||
|
||||
nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off);
|
||||
|
||||
openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
|
||||
@@ -511,7 +514,7 @@ int main(int argc, char **argv)
|
||||
ue_id_g = (node_number == 0) ? 0 : node_number - 2;
|
||||
AssertFatal(ue_id_g >= 0, "UE id is expected to be nonnegative.\n");
|
||||
|
||||
if(node_number == 0)
|
||||
if (node_number == 0)
|
||||
init_pdcp(0);
|
||||
else
|
||||
init_pdcp(mode_offset + ue_id_g);
|
||||
@@ -540,7 +543,8 @@ int main(int argc, char **argv)
|
||||
set_options(CC_id, UE[CC_id]);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
|
||||
if (get_softmodem_params()->sa) { // set frame config to initial values from command line and assume that the SSB is centered on the grid
|
||||
if (get_softmodem_params()->sa || get_softmodem_params()->sl_mode) { // set frame config to initial values from command line
|
||||
// and assume that the SSB is centered on the grid
|
||||
uint16_t nr_band = get_softmodem_params()->band;
|
||||
mac->nr_band = nr_band;
|
||||
mac->ssb_start_subcarrier = UE[CC_id]->frame_parms.ssb_start_subcarrier;
|
||||
@@ -549,8 +553,7 @@ int main(int argc, char **argv)
|
||||
uplink_frequency_offset[CC_id][0],
|
||||
get_softmodem_params()->numerology,
|
||||
nr_band);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
DevAssert(mac->if_module != NULL && mac->if_module->phy_config_request != NULL);
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
mac->phy_config_request_sent = true;
|
||||
@@ -559,7 +562,24 @@ int main(int argc, char **argv)
|
||||
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, mac->nr_band);
|
||||
}
|
||||
|
||||
UE[CC_id]->sl_mode = get_softmodem_params()->sl_mode;
|
||||
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
|
||||
|
||||
if (UE[CC_id]->sl_mode) {
|
||||
AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
|
||||
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
|
||||
nr_sl_phy_config_t *phycfg = &mac->SL_MAC_PARAMS->sl_phy_config;
|
||||
phycfg->sl_config_req.sl_carrier_config.sl_num_rx_ant = get_nrUE_params()->nb_antennas_rx;
|
||||
phycfg->sl_config_req.sl_carrier_config.sl_num_tx_ant = get_nrUE_params()->nb_antennas_tx;
|
||||
mac->if_module->sl_phy_config_request(phycfg);
|
||||
mac->phy_config_request_sent = true;
|
||||
sl_nr_ue_phy_params_t *sl_phy = &UE[CC_id]->SL_UE_PHY_PARAMS;
|
||||
nr_init_frame_parms_ue_sl(&sl_phy->sl_frame_params,
|
||||
&sl_phy->sl_config,
|
||||
get_softmodem_params()->threequarter_fs,
|
||||
get_nrUE_params()->ofdm_offset_divisor);
|
||||
sl_ue_phy_init(UE[CC_id]);
|
||||
}
|
||||
}
|
||||
|
||||
init_openair0();
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n"
|
||||
#define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/<the value>). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n"
|
||||
#define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n"
|
||||
|
||||
/***************************************************************************************************************************************/
|
||||
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
|
||||
when calling config_get or config_getlist functions */
|
||||
|
||||
Reference in New Issue
Block a user