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
|
||||
|
||||
@@ -33,29 +33,22 @@
|
||||
// The adjustment is performed once per frame based on the
|
||||
// last channel estimate of the receiver
|
||||
|
||||
void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
module_id_t gNB_id,
|
||||
const int estimateSz,
|
||||
struct complex16 dl_ch_estimates_time[][estimateSz],
|
||||
uint8_t frame,
|
||||
uint8_t subframe,
|
||||
unsigned char clear,
|
||||
short coef)
|
||||
int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
module_id_t gNB_id,
|
||||
const int estimateSz,
|
||||
struct complex16 dl_ch_estimates_time[][estimateSz],
|
||||
uint8_t frame,
|
||||
uint8_t slot,
|
||||
short coef)
|
||||
{
|
||||
|
||||
static int count_max_pos_ok = 0;
|
||||
static int first_time = 1;
|
||||
int max_val = 0, max_pos = 0;
|
||||
const int sync_pos = 0;
|
||||
uint8_t sync_offset = 0;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN);
|
||||
|
||||
short ncoef = 32767 - coef;
|
||||
|
||||
LOG_D(PHY,"AbsSubframe %d: rx_offset (before) = %d\n",subframe,ue->rx_offset);
|
||||
|
||||
// search for maximum position within the cyclic prefix
|
||||
for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) {
|
||||
int temp = 0;
|
||||
@@ -74,53 +67,32 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
}
|
||||
|
||||
// filter position to reduce jitter
|
||||
if (clear == 1)
|
||||
ue->max_pos_fil = max_pos << 15;
|
||||
else
|
||||
ue->max_pos_fil = ((ue->max_pos_fil * coef) >> 15) + (max_pos * ncoef);
|
||||
ue->max_pos_avg = ((ue->max_pos_avg * coef) >> 15) + (max_pos * ncoef);
|
||||
|
||||
// do not filter to have proactive timing adjustment
|
||||
//ue->max_pos_fil = max_pos << 15;
|
||||
|
||||
int diff = (ue->max_pos_fil >> 15) - sync_pos;
|
||||
int diff = ue->max_pos_avg >> 15;
|
||||
|
||||
if (frame_parms->freq_range==nr_FR2)
|
||||
sync_offset = 2;
|
||||
else
|
||||
sync_offset = 0;
|
||||
|
||||
if ( abs(diff) < (SYNCH_HYST+sync_offset) )
|
||||
ue->rx_offset = 0;
|
||||
else
|
||||
ue->rx_offset = diff;
|
||||
int sampleShift = 0;
|
||||
if (abs(diff) > (NR_SYNCH_HYST + sync_offset))
|
||||
sampleShift = diff;
|
||||
|
||||
const int sample_shift = -(ue->rx_offset>>1);
|
||||
const int sample_shift = -(sampleShift / 2);
|
||||
// reset IIR filter for next offset calculation
|
||||
ue->max_pos_fil += sample_shift * 32768;
|
||||
ue->max_pos_avg += sample_shift * 32768;
|
||||
|
||||
if(abs(diff)<5)
|
||||
count_max_pos_ok ++;
|
||||
else
|
||||
count_max_pos_ok = 0;
|
||||
|
||||
//printf("adjust sync count_max_pos_ok = %d\n",count_max_pos_ok);
|
||||
|
||||
if(count_max_pos_ok > 10 && first_time == 1) {
|
||||
first_time = 0;
|
||||
ue->time_sync_cell = 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PHY
|
||||
LOG_I(PHY,"AbsSubframe %d: diff = %i, rx_offset (final) = %i : clear = %d, max_pos = %d, max_pos_fil = %d, max_val = %d, sync_pos %d\n",
|
||||
subframe,
|
||||
LOG_D(PHY,
|
||||
"Slot %d: diff = %i, rx_offset (final) = %i : max_pos = %d, max_pos filtered = %ld, max_power = %d\n",
|
||||
slot,
|
||||
diff,
|
||||
ue->rx_offset,
|
||||
clear,
|
||||
sampleShift,
|
||||
max_pos,
|
||||
ue->max_pos_fil,
|
||||
max_val,
|
||||
sync_pos);
|
||||
#endif //DEBUG_PHY
|
||||
ue->max_pos_avg,
|
||||
max_val);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT);
|
||||
return sample_shift;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
/*!\brief Timing drift hysterisis in samples*/
|
||||
#define SYNCH_HYST 2
|
||||
#define NR_SYNCH_HYST 1
|
||||
|
||||
/* A function to perform the channel estimation of DL PRS signal */
|
||||
int nr_prs_channel_estimation(uint8_t gNB_id,
|
||||
@@ -91,15 +91,14 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int rxdataFsize,
|
||||
c16_t rxdataF[][rxdataFsize]);
|
||||
|
||||
void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
module_id_t gNB_id,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates_time [][estimateSz],
|
||||
uint8_t frame,
|
||||
uint8_t subframe,
|
||||
unsigned char clear,
|
||||
short coef);
|
||||
int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
module_id_t gNB_id,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates_time[][estimateSz],
|
||||
uint8_t frame,
|
||||
uint8_t subframe,
|
||||
short coef);
|
||||
|
||||
void nr_ue_measurements(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
@@ -50,7 +50,7 @@ extern openair0_config_t openair0_cfg[];
|
||||
//static nfapi_nr_config_request_t* config =&config_t;
|
||||
int cnt=0;
|
||||
|
||||
#define DEBUG_INITIAL_SYNCH
|
||||
// #define DEBUG_INITIAL_SYNCH
|
||||
#define DUMP_PBCH_CH_ESTIMATES 0
|
||||
|
||||
// create a new node of SSB structure
|
||||
@@ -111,11 +111,6 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_SSB *best_ssb = NULL;
|
||||
NR_UE_SSB *current_ssb;
|
||||
|
||||
#ifdef DEBUG_INITIAL_SYNCH
|
||||
LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id,
|
||||
ue->rx_offset);
|
||||
#endif
|
||||
|
||||
uint8_t N_L = (frame_parms->Lmax == 4)? 4:8;
|
||||
uint8_t N_hf = (frame_parms->Lmax == 4)? 2:1;
|
||||
|
||||
@@ -129,7 +124,7 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
// computing correlation between received DMRS symbols and transmitted sequence for current i_ssb and n_hf
|
||||
for(int i=pbch_initial_symbol; i<pbch_initial_symbol+3;i++)
|
||||
nr_pbch_dmrs_correlation(ue,proc,i,i-pbch_initial_symbol,current_ssb,rxdataF);
|
||||
nr_pbch_dmrs_correlation(ue, proc, i, i - pbch_initial_symbol, current_ssb, rxdataF);
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
|
||||
current_ssb->metric = current_ssb->c_re*current_ssb->c_re + current_ssb->c_im*current_ssb->c_im;
|
||||
@@ -147,7 +142,7 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
|
||||
while (ret!=0 && temp_ptr != NULL) {
|
||||
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
// computing channel estimation for selected best ssb
|
||||
// computing channel estimation for selected best ssb
|
||||
const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
|
||||
@@ -178,242 +173,230 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
free_list(best_ssb);
|
||||
|
||||
|
||||
if (ret==0) {
|
||||
|
||||
frame_parms->nb_antenna_ports_gNB = 1; //pbch_tx_ant;
|
||||
|
||||
// set initial transmission mode to 1 or 2 depending on number of detected TX antennas
|
||||
//frame_parms->mode1_flag = (pbch_tx_ant==1);
|
||||
// openair_daq_vars.dlsch_transmission_mode = (pbch_tx_ant>1) ? 2 : 1;
|
||||
if (ret == 0)
|
||||
frame_parms->nb_antenna_ports_gNB = 1; // pbch_tx_ant;
|
||||
|
||||
// set initial transmission mode to 1 or 2 depending on number of detected TX antennas
|
||||
// frame_parms->mode1_flag = (pbch_tx_ant==1);
|
||||
// openair_daq_vars.dlsch_transmission_mode = (pbch_tx_ant>1) ? 2 : 1;
|
||||
|
||||
#ifdef DEBUG_INITIAL_SYNCH
|
||||
LOG_I(PHY, "[UE%d] Initial sync: pbch decoded sucessfully, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index);
|
||||
#endif
|
||||
return(0);
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
LOG_I(PHY, "[UE%d] Initial sync: pbch decoded sucessfully, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nr_initial_sync(const UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, int sa)
|
||||
nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, int sa)
|
||||
{
|
||||
|
||||
int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2,
|
||||
int32_t metric_tdd_ncp=0;
|
||||
int32_t metric_tdd_ncp = 0;
|
||||
uint8_t phase_tdd_ncp;
|
||||
int frame_id;
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
int ret=-1;
|
||||
int rx_power=0; //aarx,
|
||||
|
||||
nr_initial_sync_t ret = {true, 0};
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_IN);
|
||||
|
||||
|
||||
LOG_D(PHY,"nr_initial sync ue RB_DL %d\n", fp->N_RB_DL);
|
||||
LOG_D(PHY, "nr_initial sync ue RB_DL %d\n", fp->N_RB_DL);
|
||||
|
||||
/* Initial synchronisation
|
||||
*
|
||||
* 1 radio frame = 10 ms
|
||||
* <--------------------------------------------------------------------------->
|
||||
* -----------------------------------------------------------------------------
|
||||
* | Received UE data buffer |
|
||||
* ----------------------------------------------------------------------------
|
||||
* --------------------------
|
||||
* <-------------->| pss | pbch | sss | pbch |
|
||||
* --------------------------
|
||||
* sync_pos SS/PBCH block
|
||||
*/
|
||||
* 1 radio frame = 10 ms
|
||||
* <--------------------------------------------------------------------------->
|
||||
* -----------------------------------------------------------------------------
|
||||
* | Received UE data buffer |
|
||||
* ----------------------------------------------------------------------------
|
||||
* --------------------------
|
||||
* <-------------->| pss | pbch | sss | pbch |
|
||||
* --------------------------
|
||||
* sync_pos SS/PBCH block
|
||||
*/
|
||||
|
||||
const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
|
||||
__attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
|
||||
cnt++;
|
||||
if (1){ // (cnt>100)
|
||||
cnt =0;
|
||||
if (1) { // (cnt>100)
|
||||
cnt = 0;
|
||||
|
||||
// initial sync performed on two successive frames, if pbch passes on first frame, no need to process second frame
|
||||
// only one frame is used for symulation tools
|
||||
for (frame_id = 0; frame_id < n_frames; frame_id++) {
|
||||
/* process pss search on received buffer */
|
||||
sync_pos = pss_synchro_nr(ue, frame_id, NO_RATE_CHANGE);
|
||||
if (sync_pos < fp->nb_prefix_samples)
|
||||
continue;
|
||||
// initial sync performed on two successive frames, if pbch passes on first frame, no need to process second frame
|
||||
// only one frame is used for symulation tools
|
||||
for (frame_id = 0; frame_id < n_frames; frame_id++) {
|
||||
/* process pss search on received buffer */
|
||||
sync_pos = pss_synchro_nr(ue, frame_id, NO_RATE_CHANGE);
|
||||
if (sync_pos < fp->nb_prefix_samples)
|
||||
continue;
|
||||
|
||||
ue->ssb_offset = sync_pos - fp->nb_prefix_samples;
|
||||
ue->ssb_offset = sync_pos - fp->nb_prefix_samples;
|
||||
|
||||
#ifdef DEBUG_INITIAL_SYNCH
|
||||
LOG_I(PHY, "[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n", ue->Mod_id, sync_pos, ue->common_vars.nid2);
|
||||
LOG_I(PHY,"sync_pos %d ssb_offset %d \n",sync_pos,ue->ssb_offset);
|
||||
LOG_I(PHY, "[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n", ue->Mod_id, sync_pos, ue->common_vars.nid2);
|
||||
LOG_I(PHY, "sync_pos %d ssb_offset %d \n", sync_pos, ue->ssb_offset);
|
||||
#endif
|
||||
|
||||
/* check that SSS/PBCH block is continuous inside the received buffer */
|
||||
if (ue->ssb_offset + NR_N_SYMBOLS_SSB * (fp->ofdm_symbol_size + fp->nb_prefix_samples) < fp->samples_per_frame) {
|
||||
/* check that SSS/PBCH block is continuous inside the received buffer */
|
||||
if (ue->ssb_offset + NR_N_SYMBOLS_SSB * (fp->ofdm_symbol_size + fp->nb_prefix_samples) < fp->samples_per_frame) {
|
||||
// digital compensation of FFO for SSB symbols
|
||||
if (ue->UE_fo_compensation) {
|
||||
double s_time = 1 / (1.0e3 * fp->samples_per_subframe); // sampling time
|
||||
double off_angle = -2 * M_PI * s_time * (ue->common_vars.freq_offset); // offset rotation angle compensation per sample
|
||||
|
||||
// digital compensation of FFO for SSB symbols
|
||||
if (ue->UE_fo_compensation){
|
||||
double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time
|
||||
double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample
|
||||
// In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1
|
||||
// and we do not know yet in which slot it goes.
|
||||
|
||||
// In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1
|
||||
// and we do not know yet in which slot it goes.
|
||||
|
||||
for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) {
|
||||
for (int ar=0; ar<fp->nb_antennas_rx; ar++) {
|
||||
const double re = ue->common_vars.rxdata[ar][n].r;
|
||||
const double im = ue->common_vars.rxdata[ar][n].i;
|
||||
ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle)));
|
||||
ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* slot_fep function works for lte and takes into account begining of frame with prefix for subframe 0 */
|
||||
/* for NR this is not the case but slot_fep is still used for computing FFT of samples */
|
||||
/* in order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */
|
||||
/* symbol number are from beginning of SS/PBCH blocks as below: */
|
||||
/* Signal PSS PBCH SSS PBCH */
|
||||
/* symbol number 0 1 2 3 */
|
||||
/* time samples in buffer rxdata are used as input of FFT -> FFT results are stored in the frequency buffer rxdataF */
|
||||
/* rxdataF stores SS/PBCH from beginning of buffers in the same symbol order as in time domain */
|
||||
|
||||
for (int i = 0; i < NR_N_SYMBOLS_SSB; i++)
|
||||
nr_slot_fep_init_sync(ue, proc, i, frame_id * fp->samples_per_frame + ue->ssb_offset, false, rxdataF, link_type_dl);
|
||||
|
||||
#ifdef DEBUG_INITIAL_SYNCH
|
||||
LOG_I(PHY,"Calling sss detection (normal CP)\n");
|
||||
#endif
|
||||
|
||||
int freq_offset_sss = 0;
|
||||
bool ret_sss = rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss, rxdataF);
|
||||
ret = !ret_sss;
|
||||
// digital compensation of FFO for SSB symbols
|
||||
if (ue->UE_fo_compensation){
|
||||
double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time
|
||||
double off_angle = -2*M_PI*s_time*freq_offset_sss; // offset rotation angle compensation per sample
|
||||
|
||||
// In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1
|
||||
// and we do not know yet in which slot it goes.
|
||||
for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) {
|
||||
for (int ar=0; ar<fp->nb_antennas_rx; ar++) {
|
||||
const double re = ue->common_vars.rxdata[ar][n].r;
|
||||
const double im = ue->common_vars.rxdata[ar][n].i;
|
||||
ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle)));
|
||||
ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle)));
|
||||
for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) {
|
||||
for (int ar = 0; ar < fp->nb_antennas_rx; ar++) {
|
||||
const double re = ue->common_vars.rxdata[ar][n].r;
|
||||
const double im = ue->common_vars.rxdata[ar][n].i;
|
||||
ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle)));
|
||||
ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ue->common_vars.freq_offset += freq_offset_sss;
|
||||
}
|
||||
|
||||
if (ret==0) { //we got sss channel
|
||||
nr_gold_pbch(ue);
|
||||
ret = nr_pbch_detection(proc, ue, 1, rxdataF); // start pbch detection at first symbol after pss
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
|
||||
// sync at symbol ue->symbol_offset
|
||||
// computing the offset wrt the beginning of the frame
|
||||
int mu = fp->numerology_index;
|
||||
// number of symbols with different prefix length
|
||||
// every 7*(1<<mu) symbols there is a different prefix length (38.211 5.3.1)
|
||||
int n_symb_prefix0 = (ue->symbol_offset/(7*(1<<mu)))+1;
|
||||
sync_pos_frame = n_symb_prefix0*(fp->ofdm_symbol_size + fp->nb_prefix_samples0)+(ue->symbol_offset-n_symb_prefix0)*(fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
// for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of the n_frames we got sync
|
||||
ue->init_sync_frame = n_frames - 1 - frame_id;
|
||||
|
||||
// compute the scramblingID_pdcch and the gold pdcch
|
||||
ue->scramblingID_pdcch = fp->Nid_cell;
|
||||
nr_gold_pdcch(ue,fp->Nid_cell);
|
||||
|
||||
// compute the scrambling IDs for PDSCH DMRS
|
||||
for (int i=0; i<NR_NB_NSCID; i++) {
|
||||
ue->scramblingID_dlsch[i]=fp->Nid_cell;
|
||||
nr_gold_pdsch(ue, i, ue->scramblingID_dlsch[i]);
|
||||
}
|
||||
|
||||
nr_init_csi_rs(fp, ue->nr_csi_info->nr_gold_csi_rs, fp->Nid_cell);
|
||||
|
||||
// initialize the pusch dmrs
|
||||
for (int i=0; i<NR_NB_NSCID; i++) {
|
||||
ue->scramblingID_ulsch[i]=fp->Nid_cell;
|
||||
nr_init_pusch_dmrs(ue, ue->scramblingID_ulsch[i], i);
|
||||
}
|
||||
|
||||
|
||||
// we also need to take into account the shift by samples_per_frame in case the if is true
|
||||
if (ue->ssb_offset < sync_pos_frame){
|
||||
ue->rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset;
|
||||
ue->init_sync_frame += 1;
|
||||
}
|
||||
else
|
||||
ue->rx_offset = ue->ssb_offset - sync_pos_frame;
|
||||
}
|
||||
|
||||
/*
|
||||
int nb_prefix_samples0 = fp->nb_prefix_samples0;
|
||||
fp->nb_prefix_samples0 = fp->nb_prefix_samples;
|
||||
|
||||
nr_slot_fep(ue, proc, 0, 0, ue->ssb_offset, 0, NR_PDCCH_EST);
|
||||
nr_slot_fep(ue, proc, 1, 0, ue->ssb_offset, 0, NR_PDCCH_EST);
|
||||
fp->nb_prefix_samples0 = nb_prefix_samples0;
|
||||
|
||||
LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n",
|
||||
ue->Mod_id,
|
||||
ue->proc.proc_rxtx[0].frame_rx,
|
||||
ue->rx_offset,
|
||||
ue->common_vars.freq_offset );
|
||||
*/
|
||||
/* slot_fep function works for lte and takes into account begining of frame with prefix for subframe 0 */
|
||||
/* for NR this is not the case but slot_fep is still used for computing FFT of samples */
|
||||
/* in order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */
|
||||
/* symbol number are from beginning of SS/PBCH blocks as below: */
|
||||
/* Signal PSS PBCH SSS PBCH */
|
||||
/* symbol number 0 1 2 3 */
|
||||
/* time samples in buffer rxdata are used as input of FFT -> FFT results are stored in the frequency buffer rxdataF */
|
||||
/* rxdataF stores SS/PBCH from beginning of buffers in the same symbol order as in time domain */
|
||||
|
||||
for (int i = 0; i < NR_N_SYMBOLS_SSB; i++)
|
||||
nr_slot_fep_init_sync(ue, proc, i, frame_id * fp->samples_per_frame + ue->ssb_offset, false, rxdataF, link_type_dl);
|
||||
|
||||
#ifdef DEBUG_INITIAL_SYNCH
|
||||
LOG_I(PHY,"TDD Normal prefix: CellId %d metric %d, phase %d, pbch %d\n",
|
||||
fp->Nid_cell,metric_tdd_ncp,phase_tdd_ncp,ret);
|
||||
LOG_I(PHY, "Calling sss detection (normal CP)\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
else {
|
||||
int freq_offset_sss = 0;
|
||||
bool ret_sss = rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss, rxdataF);
|
||||
ret.cell_notdetected = !ret_sss; // rx_sss_nr returns true if success
|
||||
// digital compensation of FFO for SSB symbols
|
||||
if (ue->UE_fo_compensation) {
|
||||
double s_time = 1 / (1.0e3 * fp->samples_per_subframe); // sampling time
|
||||
double off_angle = -2 * M_PI * s_time * freq_offset_sss; // offset rotation angle compensation per sample
|
||||
|
||||
// In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1
|
||||
// and we do not know yet in which slot it goes.
|
||||
for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) {
|
||||
for (int ar = 0; ar < fp->nb_antennas_rx; ar++) {
|
||||
const double re = ue->common_vars.rxdata[ar][n].r;
|
||||
const double im = ue->common_vars.rxdata[ar][n].i;
|
||||
ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle)));
|
||||
ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle)));
|
||||
}
|
||||
}
|
||||
|
||||
ue->common_vars.freq_offset += freq_offset_sss;
|
||||
}
|
||||
|
||||
if (ret.cell_notdetected == 0) { // we got sss channel
|
||||
nr_gold_pbch(ue);
|
||||
ret.cell_notdetected = nr_pbch_detection(proc, ue, 1, rxdataF); // start pbch detection at first symbol after pss
|
||||
}
|
||||
|
||||
if (ret.cell_notdetected == 0) {
|
||||
// sync at symbol ue->symbol_offset
|
||||
// computing the offset wrt the beginning of the frame
|
||||
int mu = fp->numerology_index;
|
||||
// number of symbols with different prefix length
|
||||
// every 7*(1<<mu) symbols there is a different prefix length (38.211 5.3.1)
|
||||
int n_symb_prefix0 = (ue->symbol_offset / (7 * (1 << mu))) + 1;
|
||||
sync_pos_frame = n_symb_prefix0 * (fp->ofdm_symbol_size + fp->nb_prefix_samples0)
|
||||
+ (ue->symbol_offset - n_symb_prefix0) * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
// for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of
|
||||
// the n_frames we got sync
|
||||
ue->init_sync_frame = n_frames - 1 - frame_id;
|
||||
|
||||
// compute the scramblingID_pdcch and the gold pdcch
|
||||
ue->scramblingID_pdcch = fp->Nid_cell;
|
||||
nr_gold_pdcch(ue, fp->Nid_cell);
|
||||
|
||||
// compute the scrambling IDs for PDSCH DMRS
|
||||
for (int i = 0; i < NR_NB_NSCID; i++) {
|
||||
ue->scramblingID_dlsch[i] = fp->Nid_cell;
|
||||
nr_gold_pdsch(ue, i, ue->scramblingID_dlsch[i]);
|
||||
}
|
||||
|
||||
nr_init_csi_rs(fp, ue->nr_csi_info->nr_gold_csi_rs, fp->Nid_cell);
|
||||
|
||||
// initialize the pusch dmrs
|
||||
for (int i = 0; i < NR_NB_NSCID; i++) {
|
||||
ue->scramblingID_ulsch[i] = fp->Nid_cell;
|
||||
nr_init_pusch_dmrs(ue, ue->scramblingID_ulsch[i], i);
|
||||
}
|
||||
|
||||
// we also need to take into account the shift by samples_per_frame in case the if is true
|
||||
if (ue->ssb_offset < sync_pos_frame) {
|
||||
ret.rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset;
|
||||
ue->init_sync_frame += 1;
|
||||
} else
|
||||
ret.rx_offset = ue->ssb_offset - sync_pos_frame;
|
||||
}
|
||||
|
||||
/*
|
||||
int nb_prefix_samples0 = fp->nb_prefix_samples0;
|
||||
fp->nb_prefix_samples0 = fp->nb_prefix_samples;
|
||||
|
||||
nr_slot_fep(ue, proc, 0, 0, ue->ssb_offset, 0, NR_PDCCH_EST);
|
||||
nr_slot_fep(ue, proc, 1, 0, ue->ssb_offset, 0, NR_PDCCH_EST);
|
||||
fp->nb_prefix_samples0 = nb_prefix_samples0;
|
||||
|
||||
LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n",
|
||||
ue->Mod_id,
|
||||
ue->proc.proc_rxtx[0].frame_rx,
|
||||
ue->rx_offset,
|
||||
ue->common_vars.freq_offset );
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_INITIAL_SYNCH
|
||||
LOG_I(PHY,"TDD Normal prefix: SSS error condition: sync_pos %d\n", sync_pos);
|
||||
LOG_I(PHY,
|
||||
"TDD Normal prefix: CellId %d metric %d, phase %d, pbch detected %d, measured offset %d\n",
|
||||
fp->Nid_cell,
|
||||
metric_tdd_ncp,
|
||||
phase_tdd_ncp,
|
||||
!ret.cell_notdetected,
|
||||
ret.rx_offset);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
#ifdef DEBUG_INITIAL_SYNCH
|
||||
LOG_I(PHY, "TDD Normal prefix: SSS error condition: sync_pos %d\n", sync_pos);
|
||||
#endif
|
||||
}
|
||||
if (ret == 0) break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = -1;
|
||||
if (ret.cell_notdetected == 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret.cell_notdetected = true;
|
||||
}
|
||||
|
||||
/* Consider this is a false detection if the offset is > 1000 Hz
|
||||
/* Consider this is a false detection if the offset is > 1000 Hz
|
||||
Not to be used now that offest estimation is in place
|
||||
if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) )
|
||||
{
|
||||
ret=-1;
|
||||
LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset);
|
||||
}*/
|
||||
if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) )
|
||||
{
|
||||
ret=-1;
|
||||
LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset);
|
||||
}*/
|
||||
|
||||
if (ret==0) { // PBCH found so indicate sync to higher layers and configure frame parameters
|
||||
if (ret.cell_notdetected == 0) { // PBCH found so indicate sync to higher layers and configure frame parameters
|
||||
|
||||
//#ifdef DEBUG_INITIAL_SYNCH
|
||||
|
||||
LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n",ue->Mod_id, ue->rx_offset);
|
||||
LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n", ue->Mod_id, ret.rx_offset);
|
||||
|
||||
//#endif
|
||||
|
||||
if (ue->UE_scan_carrier == 0) {
|
||||
#if UE_AUTOTEST_TRACE
|
||||
LOG_I(PHY,
|
||||
"[UE %d] AUTOTEST Cell Sync : rx_offset %d, freq_offset %d \n",
|
||||
ue->Mod_id,
|
||||
ue->rx_offset,
|
||||
ue->common_vars.freq_offset);
|
||||
#endif
|
||||
|
||||
#if UE_AUTOTEST_TRACE
|
||||
LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : rx_offset %d, freq_offset %d \n",
|
||||
ue->Mod_id,
|
||||
ue->rx_offset,
|
||||
ue->common_vars.freq_offset );
|
||||
#endif
|
||||
|
||||
// send sync status to higher layers later when timing offset converge to target timing
|
||||
|
||||
// send sync status to higher layers later when timing offset converge to target timing
|
||||
}
|
||||
|
||||
LOG_I(PHY,
|
||||
@@ -428,23 +411,22 @@ int nr_initial_sync(const UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_fra
|
||||
LOG_I(PHY,"[UE%d] Initial sync : Estimated Nid_cell %d, Frame_type %d\n",ue->Mod_id,
|
||||
frame_parms->Nid_cell,frame_parms->frame_type);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// gain control
|
||||
if (ret!=0) { //we are not synched, so we cannot use rssi measurement (which is based on channel estimates)
|
||||
rx_power = 0;
|
||||
if (ret.cell_notdetected != 0) { // we are not synched, so we cannot use rssi measurement (which is based on channel estimates)
|
||||
int rx_power = 0;
|
||||
|
||||
// do a measurement on the best guess of the PSS
|
||||
//for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
|
||||
// for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
|
||||
// rx_power += signal_energy(&ue->common_vars.rxdata[aarx][sync_pos2],
|
||||
// frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples);
|
||||
// frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples);
|
||||
|
||||
/*
|
||||
// do a measurement on the full frame
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
|
||||
rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0],
|
||||
frame_parms->samples_per_subframe*10);
|
||||
rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0],
|
||||
frame_parms->samples_per_subframe*10);
|
||||
*/
|
||||
|
||||
// we might add a low-pass filter here later
|
||||
@@ -453,12 +435,10 @@ int nr_initial_sync(const UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_fra
|
||||
ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]);
|
||||
|
||||
#ifdef DEBUG_INITIAL_SYNCH
|
||||
LOG_I(PHY,"[UE%d] Initial sync : Estimated power: %d dB\n",ue->Mod_id,ue->measurements.rx_power_avg_dB[0] );
|
||||
LOG_I(PHY, "[UE%d] Initial sync : Estimated power: %d dB\n", ue->Mod_id, ue->measurements.rx_power_avg_dB[0]);
|
||||
#endif
|
||||
|
||||
}
|
||||
// exit_fun("debug exit");
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -287,6 +287,7 @@ int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uin
|
||||
/*! \brief receiver for the PBCH
|
||||
\returns number of tx antennas or -1 if error
|
||||
*/
|
||||
|
||||
int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const int estimateSz,
|
||||
@@ -297,11 +298,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
fapiPbch_t *result,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int pbch_initial_symbol,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
#ifndef modOrder
|
||||
#define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS
|
||||
#endif
|
||||
@@ -323,7 +319,11 @@ int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
@param n_frames
|
||||
@param sa current running mode
|
||||
*/
|
||||
int nr_initial_sync(const UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, int n_frames, int sa);
|
||||
typedef struct {
|
||||
bool cell_notdetected;
|
||||
int rx_offset;
|
||||
} nr_initial_sync_t;
|
||||
nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, int n_frames, int sa);
|
||||
|
||||
/*!
|
||||
\brief This function gets the carrier frequencies either from FP or command-line-set global variables, depending on the
|
||||
|
||||
@@ -485,12 +485,8 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
uint8_t init_sync_frame;
|
||||
/// temporary offset during cell search prior to MIB decoding
|
||||
int ssb_offset;
|
||||
uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync
|
||||
int rx_offset; /// Timing offset
|
||||
int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP
|
||||
int64_t max_pos_fil; /// Timing offset IIR filter
|
||||
bool apply_timing_offset; /// Do time sync for current frame
|
||||
int time_sync_cell;
|
||||
uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync
|
||||
int64_t max_pos_avg; /// Timing offset IIR filter
|
||||
|
||||
/// Timing Advance updates variables
|
||||
/// Timing advance update computed from the TA command signalled from gNB
|
||||
@@ -644,6 +640,7 @@ typedef struct nr_rxtx_thread_data_s {
|
||||
int writeBlockSize;
|
||||
nr_phy_data_t phy_data;
|
||||
int tx_wait_for_dlsch;
|
||||
int rx_offset;
|
||||
} nr_rxtx_thread_data_t;
|
||||
|
||||
typedef struct LDPCDecode_ue_s {
|
||||
|
||||
@@ -98,7 +98,7 @@ typedef struct {
|
||||
*/
|
||||
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data);
|
||||
|
||||
void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
|
||||
int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
|
||||
|
||||
void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
|
||||
|
||||
|
||||
@@ -826,7 +826,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *
|
||||
return dec;
|
||||
}
|
||||
|
||||
void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
|
||||
int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
|
||||
{
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
@@ -834,6 +834,7 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr
|
||||
fapi_nr_config_request_t *cfg = &ue->nrUE_config;
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
|
||||
int sampleShift = 0;
|
||||
nr_ue_dlsch_init(phy_data->dlsch, NR_MAX_NB_LAYERS>4 ? 2:1, ue->max_ldpc_iterations);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN);
|
||||
@@ -896,17 +897,9 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr
|
||||
|
||||
if (ue->no_timing_correction==0 && pbchSuccess == 0) {
|
||||
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
|
||||
nr_adjust_synch_ue(fp,
|
||||
ue,
|
||||
gNB_id,
|
||||
fp->ofdm_symbol_size,
|
||||
dl_ch_estimates_time,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
0,
|
||||
16384);
|
||||
sampleShift =
|
||||
nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384);
|
||||
}
|
||||
ue->apply_timing_offset = true;
|
||||
}
|
||||
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
|
||||
nr_ue_rrc_measurements(ue, proc, rxdataF);
|
||||
@@ -996,6 +989,7 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr
|
||||
LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt);
|
||||
phy_pdcch_config->nb_search_space = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT);
|
||||
return sampleShift;
|
||||
}
|
||||
|
||||
void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
|
||||
|
||||
@@ -959,7 +959,6 @@ int main(int argc, char **argv)
|
||||
//multipath channel
|
||||
//multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
|
||||
|
||||
UE->rx_offset=0;
|
||||
UE_proc.frame_rx = frame;
|
||||
UE_proc.nr_slot_rx = slot;
|
||||
UE_proc.gNB_id = 0;
|
||||
|
||||
@@ -766,21 +766,22 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if (UE->is_synchronized == 0) {
|
||||
UE_nr_rxtx_proc_t proc={0};
|
||||
ret = nr_initial_sync(&proc, UE, 1, 0);
|
||||
printf("nr_initial_sync1 returns %d\n",ret);
|
||||
if (ret<0) n_errors++;
|
||||
nr_initial_sync_t ret = nr_initial_sync(&proc, UE, 1, 0);
|
||||
printf("nr_initial_sync1 returns %d\n", ret.cell_notdetected);
|
||||
if (ret.cell_notdetected)
|
||||
n_errors++;
|
||||
}
|
||||
else {
|
||||
UE_nr_rxtx_proc_t proc={0};
|
||||
|
||||
UE->rx_offset=0;
|
||||
uint8_t ssb_index = 0;
|
||||
const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
__attribute__((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz];
|
||||
__attribute__((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
|
||||
while (!((SSB_positions >> ssb_index) & 0x01))
|
||||
ssb_index++; // to select the first transmitted ssb
|
||||
UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms, ssb_index);
|
||||
uint8_t ssb_index = 0;
|
||||
const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
__attribute__((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz];
|
||||
__attribute__((
|
||||
aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
|
||||
while (!((SSB_positions >> ssb_index) & 0x01))
|
||||
ssb_index++; // to select the first transmitted ssb
|
||||
UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms, ssb_index);
|
||||
|
||||
int ssb_slot = (UE->symbol_offset/14)+(n_hf*(frame_parms->slots_per_frame>>1));
|
||||
proc.nr_slot_rx = ssb_slot;
|
||||
|
||||
Reference in New Issue
Block a user