mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Merge remote-tracking branch 'sakthivelvelumani/ue-trs-support' into integration_2026_w28
UE: implement TRS processing in PHY (#199) This PR implements PHY layer processing for CSI-RS tracking signal that estimates the CFO and sends a frequency correction command to the radio when CFO goes above a threshold of 500Hz. A CI test is added with a GNU radio script between OCUDU gNB and the UE that simulates a continuous frequency offset. The test passes if the UE sends a frequency correction command. Reviewed-by: Robert Schmidt <robert.schmidt@openairinterface.org> Reviewed-by: Bartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org> Reviewed-by: Francesco Mani <email@francescomani.it>
This commit is contained in:
@@ -215,9 +215,8 @@ static void UE_synch(void *arg) {
|
||||
((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);
|
||||
|
||||
if (get_nrUE_params()->cont_fo_comp) {
|
||||
UE->freq_offset = freq_offset - UE->dl_Doppler_shift;
|
||||
} else {
|
||||
UE->freq_offset = freq_offset - UE->dl_Doppler_shift;
|
||||
if (!get_nrUE_params()->cont_fo_comp) {
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
nrue_ru_set_freq(UE, ul_carrier, dl_carrier, freq_offset);
|
||||
}
|
||||
@@ -711,6 +710,18 @@ static inline int get_readBlockSize(uint16_t slot, const NR_DL_FRAME_PARMS *fp)
|
||||
return rem_samples + next_slot_first_symbol;
|
||||
}
|
||||
|
||||
void trs_freq_correction(PHY_VARS_NR_UE *ue, int cfo)
|
||||
{
|
||||
if (abs(cfo) > TRS_CFO_THRESH) {
|
||||
LOG_A(PHY, "CFO estimated (%d) from TRS exceeded threshold (%d). Adjusting radio CF\n", cfo, TRS_CFO_THRESH);
|
||||
ue->freq_offset += cfo;
|
||||
uint64_t dl_carrier;
|
||||
uint64_t ul_carrier;
|
||||
nr_get_carrier_frequencies(ue, &dl_carrier, &ul_carrier);
|
||||
nrue_ru_set_freq(ue, ul_carrier, dl_carrier, ue->freq_offset);
|
||||
}
|
||||
}
|
||||
|
||||
void *UE_thread(void *arg)
|
||||
{
|
||||
//this thread should be over the processing thread to keep in real time
|
||||
|
||||
@@ -463,6 +463,7 @@ typedef struct {
|
||||
uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS
|
||||
uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS
|
||||
uint8_t measurement_bitmap; // bit 0 RSRP, bit 1 RI, bit 2 LI, bit 3 PMI, bit 4 CQI, bit 5 i1
|
||||
uint8_t last_trs_slot; // indicates to PHY if the slot is end of TRS burst
|
||||
} fapi_nr_dl_config_csirs_pdu_rel15_t;
|
||||
|
||||
typedef enum{vrb_to_prb_mapping_non_interleaved = 0, vrb_to_prb_mapping_interleaved = 1} vrb_to_prb_mapping_t;
|
||||
|
||||
@@ -262,6 +262,8 @@ static int nr_csi_rs_channel_estimation(
|
||||
int16_t *log2_maxh,
|
||||
uint32_t *noise_power)
|
||||
{
|
||||
const int meas_bitmap = csirs_config_pdu->measurement_bitmap;
|
||||
AssertFatal(meas_bitmap != 1, "No need to do CSI-RS channel estimation for only RSRP measurment\n");
|
||||
*noise_power = 0;
|
||||
int maxh = 0;
|
||||
int count = 0;
|
||||
@@ -301,10 +303,16 @@ static int nr_csi_rs_channel_estimation(
|
||||
const c16_t *rx_csi_rs_signal = &csi_rs_received_signal[ant_rx][symbol_offset];
|
||||
c16_t tmp =
|
||||
c16MulConjShift(tx_csi_rs_signal[k_tx], rx_csi_rs_signal[k_rx], nr_csi_info->csi_rs_generated_signal_bits);
|
||||
// This is not just the LS estimation for each (k,l), but also the sum of the different contributions
|
||||
// for the sake of optimizing the memory used.
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][kinit_tx].r += tmp.r;
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][kinit_tx].i += tmp.i;
|
||||
if (csirs_config_pdu->csi_type != 0) {
|
||||
// This is not just the LS estimation for each (k,l), but also the sum of the different contributions
|
||||
// for the sake of optimizing the memory used.
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][kinit_tx].r += tmp.r;
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][kinit_tx].i += tmp.i;
|
||||
} else {
|
||||
// for tracking we want estimates of all sub carriers having CSI-RS
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][k_tx].r = tmp.r;
|
||||
csi_rs_ls_estimated_channel[ant_rx][port_tx][k_tx].i = tmp.i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,6 +370,10 @@ static int nr_csi_rs_channel_estimation(
|
||||
}
|
||||
}
|
||||
|
||||
// we need only ls estimates for tracking CSI. So stop here.
|
||||
if (meas_bitmap == 0)
|
||||
continue;
|
||||
|
||||
/// Power noise estimation
|
||||
AssertFatal(csirs_config_pdu->nr_of_rbs > 0, " nr_of_rbs needs to be greater than 0\n");
|
||||
uint16_t noise_real[fp->nb_antennas_rx][csi_mapping->ports][csirs_config_pdu->nr_of_rbs];
|
||||
@@ -406,9 +418,11 @@ static int nr_csi_rs_channel_estimation(
|
||||
|
||||
}
|
||||
|
||||
*noise_power /= (fp->nb_antennas_rx * csi_mapping->ports);
|
||||
*log2_maxh = log2_approx(maxh - 1);
|
||||
*log2_re = log2_approx(count - 1);
|
||||
if (meas_bitmap > 1) {
|
||||
*noise_power /= (fp->nb_antennas_rx * csi_mapping->ports);
|
||||
*log2_maxh = log2_approx(maxh - 1);
|
||||
*log2_re = log2_approx(count - 1);
|
||||
}
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
LOG_I(NR_PHY, "Noise power estimation based on CSI-RS: %i\n", *noise_power);
|
||||
@@ -774,6 +788,61 @@ static void nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue,
|
||||
#endif
|
||||
}
|
||||
|
||||
static double get_cfo(const double phase_diff, const int sym0, const int sym1, const NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
const double one_fs = 1.0 / (fp->samples_per_frame * 100);
|
||||
int sample_count = 0;
|
||||
for (int s = sym0 + 1; s <= sym1; s++) {
|
||||
const int prefix = (s % (7 * (1 << fp->numerology_index))) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
|
||||
sample_count += (fp->ofdm_symbol_size + prefix);
|
||||
}
|
||||
const double delta_time = sample_count * one_fs;
|
||||
const double cfo = phase_diff / (2 * M_PI * delta_time);
|
||||
return cfo;
|
||||
}
|
||||
|
||||
static void nr_ue_trs_processing(PHY_VARS_NR_UE *ue,
|
||||
const c16_t res0_est[][1][ue->frame_parms.ofdm_symbol_size],
|
||||
const c16_t res1_est[][1][ue->frame_parms.ofdm_symbol_size],
|
||||
const c16_t freq_interp_est[][1][ue->frame_parms.ofdm_symbol_size],
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const csi_mapping_parms_t *csi_mapping,
|
||||
const int sym0,
|
||||
const int sym1,
|
||||
int *cfo,
|
||||
int *time_offset)
|
||||
{
|
||||
AssertFatal((sym0 > -1) && (sym1 > -1) && (sym1 > sym0), "Invalid symbol index for TRS estimation\n");
|
||||
const NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
// CFO estimation
|
||||
const int ant_rx = 0; // Estimate only on first antenna port
|
||||
cd_t phase_diff = {0.0};
|
||||
AssertFatal(csirs_config_pdu->freq_density == 3,
|
||||
"CSI-RS for tracking must have freq density of 3 but has %d\n",
|
||||
csirs_config_pdu->freq_density);
|
||||
AssertFatal(csi_mapping->kprime == 0 && csi_mapping->lprime == 0, "Invalid kprime, lprime for CSI-RS for tracking (row 1)\n");
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb + csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
for (int cdm_id = 0; cdm_id < csi_mapping->size; cdm_id++) {
|
||||
uint16_t kinit = rb * NR_NB_SC_PER_RB;
|
||||
uint16_t k = kinit + csi_mapping->koverline[cdm_id];
|
||||
|
||||
const c16_t *res0 = res0_est[ant_rx][0];
|
||||
const c16_t *res1 = res1_est[ant_rx][0];
|
||||
phase_diff.r += res1[k].r * res0[k].r + res1[k].i * res0[k].i;
|
||||
phase_diff.i += res1[k].i * res0[k].r - res1[k].r * res0[k].i;
|
||||
}
|
||||
}
|
||||
*cfo = (int)get_cfo(atan2(phase_diff.i, phase_diff.r), sym0, sym1, fp);
|
||||
|
||||
if (time_offset) {
|
||||
// Time offset estimation
|
||||
__attribute__((aligned(32))) c16_t time_est[fp->ofdm_symbol_size];
|
||||
delay_t delay = {0};
|
||||
nr_est_delay(fp->ofdm_symbol_size, freq_interp_est[ant_rx][0], time_est, &delay);
|
||||
*time_offset = delay.delay_max_pos;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
|
||||
const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
const fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu)
|
||||
@@ -796,7 +865,10 @@ void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
|
||||
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu)
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
c16_t trs_estimates[][1][ue->frame_parms.ofdm_symbol_size],
|
||||
const int res_idx,
|
||||
const int trs_sym0)
|
||||
{
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
@@ -816,11 +888,6 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
LOG_I(NR_PHY, "csirs_config_pdu->power_control_offset_ss = %i\n", csirs_config_pdu->power_control_offset_ss);
|
||||
#endif
|
||||
|
||||
if(csirs_config_pdu->csi_type == 0) {
|
||||
LOG_E(NR_PHY, "Handling of CSI-RS for tracking not handled yet at PHY\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(csirs_config_pdu->csi_type == 2) {
|
||||
LOG_E(NR_PHY, "Handling of ZP CSI-RS not handled yet at PHY\n");
|
||||
return;
|
||||
@@ -870,29 +937,25 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
&rsrp_dBm,
|
||||
rxdataF);
|
||||
|
||||
|
||||
if (csirs_config_pdu->measurement_bitmap == 0) {
|
||||
LOG_D(NR_PHY, "No CSI-RS measurements configured\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t noise_power = 0;
|
||||
int16_t log2_re = 0;
|
||||
int16_t log2_maxh = 0;
|
||||
// if we need to measure only RSRP no need to do channel estimation
|
||||
if (csirs_config_pdu->measurement_bitmap > 1)
|
||||
if (csirs_config_pdu->measurement_bitmap != 1) {
|
||||
const bool use_trs_buff = (csirs_config_pdu->csi_type == 0 && res_idx == 0);
|
||||
nr_csi_rs_channel_estimation(frame_parms,
|
||||
csirs_config_pdu,
|
||||
csi_info,
|
||||
(const c16_t **)csi_info->csi_rs_generated_signal,
|
||||
csi_rs_received_signal,
|
||||
&mapping_parms,
|
||||
CDM_group_size,
|
||||
csi_rs_ls_estimated_channel,
|
||||
csi_rs_estimated_channel_freq,
|
||||
&log2_re,
|
||||
&log2_maxh,
|
||||
&noise_power);
|
||||
csirs_config_pdu,
|
||||
csi_info,
|
||||
(const c16_t **)csi_info->csi_rs_generated_signal,
|
||||
csi_rs_received_signal,
|
||||
&mapping_parms,
|
||||
CDM_group_size,
|
||||
(use_trs_buff) ? trs_estimates : csi_rs_ls_estimated_channel,
|
||||
csi_rs_estimated_channel_freq,
|
||||
&log2_re,
|
||||
&log2_maxh,
|
||||
&noise_power);
|
||||
}
|
||||
|
||||
uint8_t rank_indicator = 0;
|
||||
// bit 1 in bitmap to indicate RI measurment
|
||||
@@ -926,9 +989,34 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
nr_csi_rs_cqi_estimation(precoded_sinr_dB, &cqi);
|
||||
}
|
||||
|
||||
int trs_cfo = 0;
|
||||
const bool do_trs_est = (csirs_config_pdu->csi_type == 0) && (res_idx == 1);
|
||||
if (do_trs_est) {
|
||||
start_meas_nr_ue_phy(ue, TRS_PROCESSING);
|
||||
nr_ue_trs_processing(ue,
|
||||
trs_estimates,
|
||||
csi_rs_ls_estimated_channel,
|
||||
csi_rs_estimated_channel_freq,
|
||||
csirs_config_pdu,
|
||||
&mapping_parms,
|
||||
trs_sym0,
|
||||
csirs_config_pdu->symb_l0,
|
||||
&trs_cfo,
|
||||
NULL); // Time offset not estimated because it is corrected using PBCH DMRS
|
||||
stop_meas_nr_ue_phy(ue, TRS_PROCESSING);
|
||||
}
|
||||
|
||||
switch (csirs_config_pdu->measurement_bitmap) {
|
||||
case 1 :
|
||||
LOG_I(NR_PHY, "[UE %d] RSRP = %i dBm\n", ue->Mod_id, rsrp_dBm);
|
||||
case 0:
|
||||
if (do_trs_est)
|
||||
LOG_I(NR_PHY,
|
||||
"%d.%d TRS estimated CFO: %d Hz\n",
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
trs_cfo);
|
||||
break;
|
||||
case 1:
|
||||
LOG_I(NR_PHY, "%d.%d [UE %d] RSRP = %i dBm\n", proc->frame_rx, proc->nr_slot_rx, ue->Mod_id, rsrp_dBm);
|
||||
break;
|
||||
case 26 :
|
||||
LOG_I(NR_PHY, "RI = %i i1 = %i.%i.%i, i2 = %i, SINR = %i dB, CQI = %i\n",
|
||||
@@ -942,6 +1030,10 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
AssertFatal(false, "Not supported measurement configuration\n");
|
||||
}
|
||||
|
||||
if (!ue->cont_fo_comp && do_trs_est && csirs_config_pdu->last_trs_slot) {
|
||||
trs_freq_correction(ue, trs_cfo);
|
||||
}
|
||||
|
||||
// Send CSI measurements to MAC
|
||||
if (!ue->if_inst || !ue->if_inst->dl_indication)
|
||||
return;
|
||||
|
||||
@@ -56,6 +56,11 @@
|
||||
// (0 + 0 * 20) % 512 = 0
|
||||
#define NUM_PROCESS_SLOT_TX_BARRIERS 512
|
||||
|
||||
// CSI for tracking can have up to 2 resources per slot
|
||||
#define MAX_CSI_RES_SLOT 2
|
||||
// Threshold to change radio frequency
|
||||
#define TRS_CFO_THRESH 500
|
||||
|
||||
#include "impl_defs_nr.h"
|
||||
#include "time_meas.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
@@ -553,7 +558,8 @@ typedef struct nr_phy_data_s {
|
||||
int n_dlsch_codewords;
|
||||
// Sidelink Rx action decided by MAC
|
||||
sl_nr_rx_config_type_enum_t sl_rx_action;
|
||||
NR_UE_CSI_RS csirs_vars;
|
||||
int num_csirs;
|
||||
NR_UE_CSI_RS csirs_vars[MAX_CSI_RES_SLOT];
|
||||
NR_UE_CSI_IM csiim_vars;
|
||||
} nr_phy_data_t;
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
FN(ULSCH_INTERLEAVING_STATS),\
|
||||
FN(ULSCH_ENCODING_STATS),\
|
||||
FN(OFDM_MOD_STATS),\
|
||||
FN(PRACH_GEN_STATS)
|
||||
FN(PRACH_GEN_STATS),\
|
||||
FN(TRS_PROCESSING)
|
||||
|
||||
typedef enum {
|
||||
FOREACH_NR_PHY_CPU_MEAS(NOOP),
|
||||
|
||||
@@ -134,7 +134,12 @@ void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
|
||||
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu);
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
c16_t trs_estimates[][1][ue->frame_parms.ofdm_symbol_size],
|
||||
const int res_idx,
|
||||
const int trs_sym0);
|
||||
|
||||
void trs_freq_correction(PHY_VARS_NR_UE *ue, int cfo);
|
||||
|
||||
int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
|
||||
void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp);
|
||||
|
||||
@@ -150,8 +150,14 @@ static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac,
|
||||
phy_data->csiim_vars.active = true;
|
||||
break;
|
||||
case FAPI_NR_DL_CONFIG_TYPE_CSI_RS:
|
||||
phy_data->csirs_vars.csirs_config_pdu = pdu->csirs_config_pdu.csirs_config_rel15;
|
||||
phy_data->csirs_vars.active = true;
|
||||
AssertFatal(phy_data->num_csirs < MAX_CSI_RES_SLOT, "CSI resources per slot exceeded limit\n");
|
||||
const int c = phy_data->num_csirs;
|
||||
if (phy_data->csirs_vars[c].active) {
|
||||
AssertFatal(false, "Resource should not be active before its configured\n");
|
||||
}
|
||||
phy_data->csirs_vars[c].csirs_config_pdu = pdu->csirs_config_pdu.csirs_config_rel15;
|
||||
phy_data->csirs_vars[c].active = true;
|
||||
phy_data->num_csirs++;
|
||||
break;
|
||||
case FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH:
|
||||
case FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH:
|
||||
|
||||
@@ -1184,16 +1184,35 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
|
||||
}
|
||||
|
||||
// do procedures for CSI-RS
|
||||
if (phy_data->csirs_vars.active == 1) {
|
||||
for(int symb = 0; symb < ue->frame_parms.symbols_per_slot; symb++) {
|
||||
if(is_csi_rs_in_symbol(phy_data->csirs_vars.csirs_config_pdu, symb)) {
|
||||
if (!slot_fep_map[symb]) {
|
||||
nr_slot_fep(ue, &ue->frame_parms, proc->nr_slot_rx, symb, rxdataF, link_type_dl, 0, ue->common_vars.rxdata);
|
||||
slot_fep_map[symb] = true;
|
||||
{
|
||||
/*
|
||||
CSI-RS for tracking use only one port.
|
||||
Number of CSI-RS resources for tracking is always 2 per slot.
|
||||
Computed estimates from first resource is saved and used while estimating second resource.
|
||||
*/
|
||||
c16_t trs_estimates[ue->frame_parms.nb_antennas_rx][1][ue->frame_parms.ofdm_symbol_size];
|
||||
for (int res = 0; res < MAX_CSI_RES_SLOT; res++) {
|
||||
if (phy_data->csirs_vars[res].active == 1) {
|
||||
for (int symb = 0; symb < ue->frame_parms.symbols_per_slot; symb++) {
|
||||
if (is_csi_rs_in_symbol(phy_data->csirs_vars[res].csirs_config_pdu, symb)) {
|
||||
if (!slot_fep_map[symb]) {
|
||||
nr_slot_fep(ue, &ue->frame_parms, proc->nr_slot_rx, symb, rxdataF, link_type_dl, 0, ue->common_vars.rxdata);
|
||||
slot_fep_map[symb] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res > 0 && phy_data->csirs_vars[res].csirs_config_pdu.csi_type == 0) // tracking CSI
|
||||
AssertFatal(phy_data->csirs_vars[res - 1].active && (phy_data->csirs_vars[res - 1].csirs_config_pdu.csi_type == 0),
|
||||
"CSI-RS for tracking must have two consecutive active resources\n");
|
||||
nr_ue_csi_rs_procedures(ue,
|
||||
proc,
|
||||
rxdataF,
|
||||
&phy_data->csirs_vars[res].csirs_config_pdu,
|
||||
trs_estimates,
|
||||
res,
|
||||
(res == 1) ? phy_data->csirs_vars[0].csirs_config_pdu.symb_l0 : -1);
|
||||
}
|
||||
}
|
||||
nr_ue_csi_rs_procedures(ue, proc, rxdataF, &phy_data->csirs_vars.csirs_config_pdu);
|
||||
}
|
||||
|
||||
int16_t *llr[2];
|
||||
|
||||
@@ -68,3 +68,7 @@ void configure_nr_nfapi_vnf(eth_params_t params)
|
||||
{
|
||||
UNUSED(params);
|
||||
}
|
||||
|
||||
void trs_freq_correction(PHY_VARS_NR_UE *ue, int cfo)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1114,7 +1114,8 @@ static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MA
|
||||
|
||||
static NR_CSI_ResourceConfigId_t find_CSI_resourceconfig(NR_CSI_MeasConfig_t *csi_measconfig,
|
||||
NR_BWP_Id_t dl_bwp_id,
|
||||
NR_NZP_CSI_RS_ResourceId_t csi_id)
|
||||
NR_NZP_CSI_RS_ResourceId_t csi_id,
|
||||
bool *is_last_res)
|
||||
{
|
||||
bool found = false;
|
||||
for (int csi_list = 0; csi_list < csi_measconfig->csi_ResourceConfigToAddModList->list.count; csi_list++) {
|
||||
@@ -1139,14 +1140,14 @@ static NR_CSI_ResourceConfigId_t find_CSI_resourceconfig(NR_CSI_MeasConfig_t *cs
|
||||
AssertFatal(csi_res->nzp_CSI_RS_Resources.list.array[k], "NZP_CSI_RS_ResourceId shoulan't be NULL\n");
|
||||
if (csi_id == *csi_res->nzp_CSI_RS_Resources.list.array[k]) {
|
||||
found = true;
|
||||
*is_last_res = (k == (csi_res->nzp_CSI_RS_Resources.list.count - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found && csi_res->trs_Info)
|
||||
// CRI-RS for Tracking (not implemented yet)
|
||||
// in this case we there is no associated CSI report
|
||||
// therefore to signal this we return a value higher than
|
||||
// maxNrofCSI-ResourceConfigurations
|
||||
/* CRI-RS for Tracking. In this case there is no associated CSI report
|
||||
* therefore to signal this we return a value higher than
|
||||
* maxNrofCSI-ResourceConfigurations. */
|
||||
return NR_maxNrofCSI_ResourceConfigurations + 1;
|
||||
else if (found)
|
||||
return csires->csi_ResourceConfigId;
|
||||
@@ -1216,7 +1217,8 @@ static void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int sl
|
||||
csi_period_offset(NULL, nzpcsi->periodicityAndOffset, &period, &offset);
|
||||
if((frame * mac->frame_structure.numb_slots_frame + slot-offset) % period != 0)
|
||||
continue;
|
||||
NR_CSI_ResourceConfigId_t csi_res_id = find_CSI_resourceconfig(csi_measconfig, dl_bwp_id, nzpcsi->nzp_CSI_RS_ResourceId);
|
||||
bool is_last_res = false;
|
||||
NR_CSI_ResourceConfigId_t csi_res_id = find_CSI_resourceconfig(csi_measconfig, dl_bwp_id, nzpcsi->nzp_CSI_RS_ResourceId, &is_last_res);
|
||||
// do not schedule reseption of this CSI-RS if not associated with current BWP
|
||||
if(csi_res_id < 0)
|
||||
continue;
|
||||
@@ -1226,9 +1228,12 @@ static void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int sl
|
||||
csirs_config_pdu->subcarrier_spacing = mu;
|
||||
csirs_config_pdu->cyclic_prefix = current_DL_BWP->cyclicprefix ? *current_DL_BWP->cyclicprefix : 0;
|
||||
|
||||
if (csi_res_id > NR_maxNrofCSI_ResourceConfigurations)
|
||||
if (csi_res_id > NR_maxNrofCSI_ResourceConfigurations) {
|
||||
/* According to 38.214 5.1.6.1.1, the number of resources indicate if one
|
||||
* or two consequtive slots for TRS is used. We indicate to phy the last slot. */
|
||||
csirs_config_pdu->last_trs_slot = is_last_res;
|
||||
csirs_config_pdu->csi_type = 0; // TRS
|
||||
else
|
||||
} else
|
||||
csirs_config_pdu->csi_type = 1; // NZP-CSI-RS
|
||||
|
||||
csirs_config_pdu->scramb_id = nzpcsi->scramblingID;
|
||||
|
||||
Reference in New Issue
Block a user