make explicit return of the clock drift to shift the corresponding number of samples
remove corresponding global variables
This commit is contained in:
+88
-84
@@ -439,11 +439,13 @@ static void UE_synch(void *arg) {
|
||||
|
||||
uint64_t dl_carrier, ul_carrier;
|
||||
nr_get_carrier_frequencies(UE, &dl_carrier, &ul_carrier);
|
||||
|
||||
if (nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa) == 0) {
|
||||
nr_initial_sync_t ret = nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa);
|
||||
if (!ret.cell_notdetected) {
|
||||
syncD->rx_offset = ret.rx_offset;
|
||||
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
|
||||
hw_slot_offset = ((UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) +
|
||||
round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0);
|
||||
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);
|
||||
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
// todo: the freq_offset computed on DL shall be scaled before being applied to UL
|
||||
@@ -462,7 +464,6 @@ static void UE_synch(void *arg) {
|
||||
else
|
||||
UE->is_synchronized = 1;
|
||||
} else {
|
||||
|
||||
if (UE->UE_scan_carrier == 1) {
|
||||
|
||||
if (freq_offset >= 0)
|
||||
@@ -607,8 +608,9 @@ void processSlotTX(void *arg)
|
||||
RU_write(rxtxD);
|
||||
}
|
||||
|
||||
static void 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)
|
||||
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;
|
||||
if (IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa) {
|
||||
|
||||
// Start synchronization with a target gNB
|
||||
@@ -636,20 +638,16 @@ static void UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *pro
|
||||
UE->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
|
||||
uint64_t a=rdtsc_oai();
|
||||
pbch_pdcch_processing(UE, proc, phy_data);
|
||||
sampleShift = pbch_pdcch_processing(UE, proc, phy_data);
|
||||
if (phy_data->dlsch[0].active && phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_) {
|
||||
// indicate to tx thread to wait for DLSCH decoding
|
||||
const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch[0].dlsch_config.k1_feedback) % UE->frame_parms.slots_per_frame;
|
||||
LOG_D(NR_PHY, "Adding one event to wait after decoding slot %d, for futre tx slot %d\n", proc->nr_slot_rx, ack_nack_slot);
|
||||
tx_wait_for_dlsch[ack_nack_slot]++;
|
||||
}
|
||||
|
||||
LOG_D(PHY, "In %s: slot %d, time %llu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc_oai()-a)/3500);
|
||||
}
|
||||
|
||||
ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx);
|
||||
return;
|
||||
return sampleShift;
|
||||
}
|
||||
|
||||
void UE_dl_processing(void *arg) {
|
||||
@@ -710,37 +708,39 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash)
|
||||
|
||||
}
|
||||
|
||||
void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
|
||||
LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset);
|
||||
|
||||
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
|
||||
// Resynchonize by slot (will work with numerology 1 only)
|
||||
for ( int size=UE->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 ;
|
||||
AssertFatal(unitTransfer ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
}
|
||||
} else {
|
||||
*timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms);
|
||||
for ( int size=UE->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 ;
|
||||
// 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);
|
||||
AssertFatal(unitTransfer ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
*timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write
|
||||
}
|
||||
static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int rx_offset)
|
||||
{
|
||||
LOG_I(PHY, "Resynchronizing RX by %d 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;
|
||||
AssertFatal(unitTransfer
|
||||
== UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx),
|
||||
"");
|
||||
}
|
||||
} 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;
|
||||
// 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);
|
||||
AssertFatal(unitTransfer
|
||||
== UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx),
|
||||
"");
|
||||
*timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
@@ -764,8 +764,6 @@ 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;
|
||||
// int tx_enabled = 0;
|
||||
openair0_timestamp timestamp = 0;
|
||||
openair0_timestamp writeTimestamp = 0;
|
||||
void *rxp[NB_ANTENNAS_RX];
|
||||
int start_rx_stream = 0;
|
||||
fapi_nr_config_request_t *cfg = &UE->nrUE_config;
|
||||
@@ -796,9 +794,10 @@ void *UE_thread(void *arg)
|
||||
for(int i=0; i < num_ind_fifo; i++) {
|
||||
initNotifiedFIFO(UE->tx_resume_ind_fifo + i);
|
||||
}
|
||||
|
||||
int shiftForNextFrame = 0;
|
||||
int intialSyncOffset = 0;
|
||||
openair0_timestamp sync_timestamp;
|
||||
while (!oai_exit) {
|
||||
|
||||
if (syncRunning) {
|
||||
notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool));
|
||||
|
||||
@@ -806,25 +805,28 @@ void *UE_thread(void *arg)
|
||||
syncRunning=false;
|
||||
if (UE->is_synchronized) {
|
||||
decoded_frame_rx = mac->mib_frame;
|
||||
LOG_I(PHY,"UE synchronized decoded_frame_rx=%d UE->init_sync_frame=%d trashed_frames=%d\n",
|
||||
LOG_A(PHY,
|
||||
"UE synchronized! decoded_frame_rx=%d UE->init_sync_frame=%d trashed_frames=%d\n",
|
||||
decoded_frame_rx,
|
||||
UE->init_sync_frame,
|
||||
trashed_frames);
|
||||
// shift the frame index with all the frames we trashed meanwhile we perform the synch search
|
||||
decoded_frame_rx = (decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER;
|
||||
syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(res);
|
||||
intialSyncOffset = syncMsg->rx_offset;
|
||||
}
|
||||
delNotifiedFIFO_elt(res);
|
||||
start_rx_stream=0;
|
||||
} else {
|
||||
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
|
||||
// For IQ recorder/player we force synchronization to happen in 280 ms
|
||||
// For IQ recorder-player we force synchronization to happen in 280 ms
|
||||
while (trashed_frames != 28) {
|
||||
readFrame(UE, ×tamp, true);
|
||||
trashed_frames+=2;
|
||||
readFrame(UE, &sync_timestamp, true);
|
||||
trashed_frames += 2;
|
||||
}
|
||||
} else {
|
||||
readFrame(UE, ×tamp, true);
|
||||
trashed_frames+=2;
|
||||
readFrame(UE, &sync_timestamp, true);
|
||||
trashed_frames += 2;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -833,7 +835,7 @@ void *UE_thread(void *arg)
|
||||
AssertFatal(!syncRunning, "At this point synchronization can't be running\n");
|
||||
|
||||
if (!UE->is_synchronized) {
|
||||
readFrame(UE, ×tamp, false);
|
||||
readFrame(UE, &sync_timestamp, false);
|
||||
notifiedFIFO_elt_t *Msg = newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch);
|
||||
syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg);
|
||||
syncMsg->UE = UE;
|
||||
@@ -846,16 +848,16 @@ void *UE_thread(void *arg)
|
||||
|
||||
if (start_rx_stream == 0) {
|
||||
start_rx_stream=1;
|
||||
syncInFrame(UE, ×tamp);
|
||||
UE->rx_offset=0;
|
||||
UE->time_sync_cell=0;
|
||||
syncInFrame(UE, &sync_timestamp, intialSyncOffset);
|
||||
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 ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
AssertFatal(UE->frame_parms.ofdm_symbol_size + UE->frame_parms.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),
|
||||
"");
|
||||
// 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++;
|
||||
@@ -871,7 +873,7 @@ void *UE_thread(void *arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// start of normal case, the UE is in sync
|
||||
absolute_slot++;
|
||||
|
||||
int slot_nr = absolute_slot % nb_slot_frame;
|
||||
@@ -893,26 +895,21 @@ void *UE_thread(void *arg)
|
||||
|
||||
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)];
|
||||
rxp[i] = (void *)&UE->common_vars
|
||||
.rxdata[i][firstSymSamp + UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, 0)];
|
||||
|
||||
int readBlockSize, writeBlockSize;
|
||||
|
||||
readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms);
|
||||
writeBlockSize = UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms);
|
||||
if (UE->apply_timing_offset && (slot_nr == nb_slot_frame - 1)) {
|
||||
const int sampShift = -(UE->rx_offset>>1);
|
||||
readBlockSize -= sampShift;
|
||||
writeBlockSize -= sampShift;
|
||||
UE->apply_timing_offset = false;
|
||||
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;
|
||||
shiftForNextFrame = 0; // We will get a new measured offset if we decode PBCH
|
||||
}
|
||||
|
||||
AssertFatal(readBlockSize ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
rxp,
|
||||
readBlockSize,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
const int readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms) - iq_shift_to_apply;
|
||||
openair0_timestamp rx_timestamp;
|
||||
AssertFatal(readBlockSize
|
||||
== UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, UE->frame_parms.nb_antennas_rx),
|
||||
"");
|
||||
|
||||
if(slot_nr == (nb_slot_frame - 1)) {
|
||||
// read in first symbol of next frame and adjust for timing drift
|
||||
@@ -931,11 +928,13 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
// use previous timing_advance value to compute writeTimestamp
|
||||
writeTimestamp = 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 + UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, 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;
|
||||
if (UE->timing_advance != timing_advance) {
|
||||
writeBlockSize -= UE->timing_advance - timing_advance;
|
||||
timing_advance = UE->timing_advance;
|
||||
@@ -948,7 +947,12 @@ void *UE_thread(void *arg)
|
||||
notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_rx, NULL, UE_dl_processing);
|
||||
nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newRx);
|
||||
*curMsgRx = (nr_rxtx_thread_data_t){.proc = curMsg.proc, .UE = UE};
|
||||
UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data);
|
||||
int ret = UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data);
|
||||
if (ret)
|
||||
// if ret is 0, no rx_offset has been computed,
|
||||
// or the computed value is 0 = no offset to do
|
||||
// we store it to apply the drift compensation at beginning of next frame
|
||||
shiftForNextFrame = ret;
|
||||
pushTpool(&(get_nrUE_params()->Tpool), newRx);
|
||||
|
||||
// Start TX slot processing here. It runs in parallel with RX slot processing
|
||||
|
||||
Reference in New Issue
Block a user