Merge remote-tracking branch 'origin/NR_CSI_improvements' into integration_2024_w41
This commit is contained in:
+2
-4
@@ -1001,7 +1001,7 @@ set(PHY_SRC_UE
|
||||
|
||||
set(PHY_NR_SRC_COMMON
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_csi_rs.c
|
||||
${OPENAIR1_DIR}/PHY/nr_phy_common/src/nr_phy_common_csirs.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/refsig.c
|
||||
@@ -1033,12 +1033,12 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_csi_rs.c
|
||||
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_freq_equalization.c
|
||||
${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_measurements_gNB.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
|
||||
#${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c
|
||||
@@ -1093,7 +1093,6 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_gain.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
|
||||
# ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c
|
||||
@@ -1104,7 +1103,6 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/lut.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c
|
||||
${OPENAIR1_DIR}/PHY/INIT/nr_init_ue.c
|
||||
# ${OPENAIR1_DIR}/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c
|
||||
${PHY_POLARSRC}
|
||||
${PHY_SMALLBLOCKSRC}
|
||||
${PHY_NR_CODINGIF}
|
||||
|
||||
@@ -150,10 +150,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
nr_generate_modulation_table();
|
||||
nr_init_pbch_interleaver(gNB->nr_pbch_interleaver);
|
||||
|
||||
// CSI RS init
|
||||
// ceil((NB_RB*8(max allocation per RB)*2(QPSK))/32)
|
||||
gNB->nr_csi_info = (nr_csi_info_t *)malloc16_clear(sizeof(nr_csi_info_t));
|
||||
|
||||
generate_ul_reference_signal_sequences(SHRT_MAX);
|
||||
|
||||
/* Generate low PAPR type 1 sequences for PUSCH DMRS, these are used if transform precoding is enabled. */
|
||||
@@ -241,8 +237,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
free_and_zero(meas->n0_subband_power);
|
||||
free_and_zero(meas->n0_subband_power_dB);
|
||||
|
||||
free_and_zero(gNB->nr_csi_info);
|
||||
|
||||
for (int id = 0; id < gNB->max_nb_srs; id++) {
|
||||
for(int i=0; i<MAX_NUM_NR_SRS_AP; i++) {
|
||||
free_and_zero(gNB->nr_srs_info[id]->srs_generated_signal[i]);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "openair1/PHY/NR_REFSIG/nr_refsig_common.h"
|
||||
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
|
||||
|
||||
int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
|
||||
unsigned int Ns,
|
||||
@@ -40,17 +41,9 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
|
||||
void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
int32_t **dataF,
|
||||
const int16_t amp,
|
||||
nr_csi_info_t *nr_csi_info,
|
||||
const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params,
|
||||
const int slot,
|
||||
uint8_t *N_cdm_groups,
|
||||
uint8_t *CDM_group_size,
|
||||
uint8_t *k_prime,
|
||||
uint8_t *l_prime,
|
||||
uint8_t *N_ports,
|
||||
uint8_t *j_cdm,
|
||||
uint8_t *k_overline,
|
||||
uint8_t *l_overline);
|
||||
const csi_mapping_parms_t *phy_csi_parms);
|
||||
|
||||
void init_scrambling_luts(void);
|
||||
void nr_generate_modulation_table(void);
|
||||
|
||||
@@ -27,17 +27,9 @@
|
||||
void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
int32_t **dataF,
|
||||
const int16_t amp,
|
||||
nr_csi_info_t *nr_csi_info,
|
||||
const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params,
|
||||
const int slot,
|
||||
uint8_t *N_cdm_groups,
|
||||
uint8_t *CDM_group_size,
|
||||
uint8_t *k_prime,
|
||||
uint8_t *l_prime,
|
||||
uint8_t *N_ports,
|
||||
uint8_t *j_cdm,
|
||||
uint8_t *k_overline,
|
||||
uint8_t *l_overline)
|
||||
const csi_mapping_parms_t *phy_csi_parms)
|
||||
{
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
LOG_I(NR_PHY, "csi_params->subcarrier_spacing = %i\n", csi_params->subcarrier_spacing);
|
||||
@@ -56,405 +48,34 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
LOG_I(NR_PHY, "csi_params->power_control_offset_ss = %i\n", csi_params->power_control_offset_ss);
|
||||
#endif
|
||||
|
||||
int dataF_offset = slot * frame_parms->samples_per_slot_wCP;
|
||||
//*8(max allocation per RB)*2(QPSK))
|
||||
int csi_rs_length = frame_parms->N_RB_DL << 4;
|
||||
int16_t mod_csi[frame_parms->symbols_per_slot][csi_rs_length>>1] __attribute__((aligned(16)));
|
||||
uint16_t b = csi_params->freq_domain;
|
||||
uint32_t beta = amp;
|
||||
nr_csi_info->csi_rs_generated_signal_bits = log2_approx(amp);
|
||||
|
||||
AssertFatal(b != 0, "Invalid CSI frequency domain mapping: no bit selected in bitmap\n");
|
||||
int size, ports, kprime, lprime;
|
||||
int j[16], k_n[6], koverline[16], loverline[16];
|
||||
int found = 0;
|
||||
int fi = 0;
|
||||
// implementation of table 7.4.1.5.3-1 of 38.211
|
||||
// lprime and kprime are the max value of l' and k'
|
||||
switch (csi_params->row) {
|
||||
case 1:
|
||||
ports = 1;
|
||||
kprime = 0;
|
||||
lprime = 0;
|
||||
size = 3;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = 0;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[0] + (i<<2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
ports = 1;
|
||||
kprime = 0;
|
||||
lprime = 0;
|
||||
size = 1;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = 0;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[0];
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
ports = 2;
|
||||
kprime = 1;
|
||||
lprime = 0;
|
||||
size = 1;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = 0;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[0];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
ports = 4;
|
||||
kprime = 1;
|
||||
lprime = 0;
|
||||
size = 2;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 2;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[0] + (i << 1);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
ports = 4;
|
||||
kprime = 1;
|
||||
lprime = 0;
|
||||
size = 2;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0 + i;
|
||||
koverline[i] = k_n[0];
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
ports = 8;
|
||||
kprime = 1;
|
||||
lprime = 0;
|
||||
size = 4;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
ports = 8;
|
||||
kprime = 1;
|
||||
lprime = 0;
|
||||
size = 4;
|
||||
while (found < 2) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0 + (i >> 1);
|
||||
koverline[i] = k_n[i % 2];
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
ports = 8;
|
||||
kprime = 1;
|
||||
lprime = 1;
|
||||
size = 2;
|
||||
while (found < 2) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
ports = 12;
|
||||
kprime = 1;
|
||||
lprime = 0;
|
||||
size = 6;
|
||||
while (found < 6) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
ports = 12;
|
||||
kprime = 1;
|
||||
lprime = 1;
|
||||
size = 3;
|
||||
while (found < 3) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
ports = 16;
|
||||
kprime = 1;
|
||||
lprime = 0;
|
||||
size = 8;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0 + (i >> 2);
|
||||
koverline[i] = k_n[i % 4];
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
ports = 16;
|
||||
kprime = 1;
|
||||
lprime = 1;
|
||||
size = 4;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
ports = 24;
|
||||
kprime = 1;
|
||||
lprime = 0;
|
||||
size = 12;
|
||||
while (found < 3) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
if (i < 6)
|
||||
loverline[i] = csi_params->symb_l0 + i / 3;
|
||||
else
|
||||
loverline[i] = csi_params->symb_l1 + i / 9;
|
||||
koverline[i] = k_n[i % 3];
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
ports = 24;
|
||||
kprime = 1;
|
||||
lprime = 1;
|
||||
size = 6;
|
||||
while (found < 3) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
if (i < 3)
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
else
|
||||
loverline[i] = csi_params->symb_l1;
|
||||
koverline[i] = k_n[i%3];
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
ports = 24;
|
||||
kprime = 1;
|
||||
lprime = 3;
|
||||
size = 3;
|
||||
while (found < 3) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
ports = 32;
|
||||
kprime = 1;
|
||||
lprime = 0;
|
||||
size = 16;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
if (i < 8)
|
||||
loverline[i] = csi_params->symb_l0 + (i>>2);
|
||||
else
|
||||
loverline[i] = csi_params->symb_l1 + (i/12);
|
||||
koverline[i] = k_n[i % 4];
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
ports = 32;
|
||||
kprime = 1;
|
||||
lprime = 1;
|
||||
size = 8;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
if (i < 4)
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
else
|
||||
loverline[i] = csi_params->symb_l1;
|
||||
koverline[i] = k_n[i % 4];
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
ports = 32;
|
||||
kprime = 1;
|
||||
lprime = 3;
|
||||
size = 4;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
j[i] = i;
|
||||
loverline[i] = csi_params->symb_l0;
|
||||
koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Row %d is not valid for CSI Table 7.4.1.5.3-1\n", csi_params->row);
|
||||
}
|
||||
// setting the frequency density from its index
|
||||
double rho = get_csi_rho(csi_params->freq_density);
|
||||
int csi_length = get_csi_modulation_length(rho,
|
||||
csi_params->freq_density,
|
||||
phy_csi_parms->kprime,
|
||||
csi_params->start_rb,
|
||||
csi_params->nr_of_rbs);
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
printf(" row %d, n. of ports %d\n k' ",csi_params->row,ports);
|
||||
for (int kp = 0; kp <= kprime; kp++)
|
||||
printf("%d, ",kp);
|
||||
printf("l' ");
|
||||
for (int lp = 0; lp <= lprime; lp++)
|
||||
printf("%d, ", lp);
|
||||
printf("\n k overline ");
|
||||
for (int i = 0; i < size; i++)
|
||||
printf("%d, ",koverline[i]);
|
||||
printf("\n l overline ");
|
||||
for (int i = 0; i < size; i++)
|
||||
printf("%d, ",loverline[i]);
|
||||
printf("\n");
|
||||
printf(" start rb %d, nr of rbs %d, csi length %d\n", csi_params->start_rb, csi_params->nr_of_rbs, csi_length);
|
||||
#endif
|
||||
|
||||
//*8(max allocation per RB)*2(QPSK))
|
||||
int16_t mod_csi[frame_parms->symbols_per_slot][(frame_parms->N_RB_DL << 4) >> 1] __attribute__((aligned(16)));
|
||||
get_modulated_csi_symbols(frame_parms->symbols_per_slot,
|
||||
slot,
|
||||
frame_parms->N_RB_DL,
|
||||
csi_length,
|
||||
mod_csi,
|
||||
phy_csi_parms->lprime,
|
||||
csi_params->symb_l0,
|
||||
csi_params->symb_l1,
|
||||
csi_params->row,
|
||||
csi_params->scramb_id);
|
||||
|
||||
// setting the frequency density from its index
|
||||
double rho = 0;
|
||||
switch (csi_params->freq_density) {
|
||||
case 0:
|
||||
rho = 0.5;
|
||||
break;
|
||||
case 1:
|
||||
rho = 0.5;
|
||||
break;
|
||||
case 2:
|
||||
rho = 1;
|
||||
break;
|
||||
case 3:
|
||||
rho = 3;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Invalid frequency density index for CSI\n");
|
||||
}
|
||||
|
||||
uint32_t beta = get_csi_beta_amplitude(amp, csi_params->power_control_offset_ss);
|
||||
double alpha = 0;
|
||||
if (ports == 1)
|
||||
if (phy_csi_parms->ports == 1)
|
||||
alpha = rho;
|
||||
else
|
||||
alpha = 2 * rho;
|
||||
@@ -464,167 +85,22 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
#endif
|
||||
|
||||
// CDM group size from CDM type index
|
||||
int gs = 0;
|
||||
switch (csi_params->cdm_type) {
|
||||
case 0:
|
||||
gs = 1;
|
||||
break;
|
||||
case 1:
|
||||
gs = 2;
|
||||
break;
|
||||
case 2:
|
||||
gs = 4;
|
||||
break;
|
||||
case 3:
|
||||
gs = 8;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Invalid cdm type index for CSI\n");
|
||||
}
|
||||
int gs = get_cdm_group_size(csi_params->cdm_type);
|
||||
|
||||
int csi_length;
|
||||
if (rho < 1) {
|
||||
if (csi_params->freq_density == 0) {
|
||||
csi_length = (((csi_params->start_rb + csi_params->nr_of_rbs) >> 1) << kprime) << 1;
|
||||
} else {
|
||||
csi_length = ((((csi_params->start_rb + csi_params->nr_of_rbs) >> 1) << kprime) + 1) << 1;
|
||||
}
|
||||
} else {
|
||||
csi_length = (((uint16_t) rho * (csi_params->start_rb + csi_params->nr_of_rbs)) << kprime) << 1;
|
||||
}
|
||||
int dataF_offset = slot * frame_parms->samples_per_slot_wCP;
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
printf(" start rb %d, nr of rbs %d, csi length %d\n", csi_params->start_rb, csi_params->nr_of_rbs, csi_length);
|
||||
#endif
|
||||
|
||||
if (N_cdm_groups)
|
||||
*N_cdm_groups = size;
|
||||
if (CDM_group_size)
|
||||
*CDM_group_size = gs;
|
||||
if (k_prime)
|
||||
*k_prime = kprime;
|
||||
if (l_prime)
|
||||
*l_prime = lprime;
|
||||
if (N_ports)
|
||||
*N_ports = ports;
|
||||
if (j_cdm)
|
||||
memcpy(j_cdm, j, 16 * sizeof(uint8_t));
|
||||
if (k_overline)
|
||||
memcpy(k_overline, koverline, 16 * sizeof(uint8_t));
|
||||
if (l_overline)
|
||||
memcpy(l_overline, loverline, 16 * sizeof(uint8_t));
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
if (N_ports)
|
||||
LOG_I(NR_PHY, "nr_csi_info->N_ports = %d\n", *N_ports);
|
||||
if (N_cdm_groups)
|
||||
LOG_I(NR_PHY, "nr_csi_info->N_cdm_groups = %d\n", *N_cdm_groups);
|
||||
if (CDM_group_size)
|
||||
LOG_I(NR_PHY, "nr_csi_info->CDM_group_size = %d\n", *CDM_group_size);
|
||||
if (k_prime)
|
||||
LOG_I(NR_PHY, "nr_csi_info->kprime = %d\n", *k_prime);
|
||||
if (l_prime)
|
||||
LOG_I(NR_PHY, "nr_csi_info->lprime = %d\n", *l_prime);
|
||||
if (N_cdm_groups) {
|
||||
for(int ji = 0; ji < *N_cdm_groups; ji++) {
|
||||
LOG_I(NR_PHY, "(CDM group %d) j = %d, koverline = %d, loverline = %d\n", ji, j[ji], koverline[ji], loverline[ji]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (csi_params->csi_type == 2) // ZP-CSI
|
||||
return;
|
||||
|
||||
// assuming amp is the amplitude of SSB channels
|
||||
switch (csi_params->power_control_offset_ss) {
|
||||
case 0:
|
||||
beta = (amp*ONE_OVER_SQRT2_Q15)>>15;
|
||||
break;
|
||||
case 1:
|
||||
beta = amp;
|
||||
break;
|
||||
case 2:
|
||||
beta = (amp*ONE_OVER_SQRT2_Q15)>>14;
|
||||
break;
|
||||
case 3:
|
||||
beta = amp << 1;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Invalid SS power offset density index for CSI\n");
|
||||
}
|
||||
|
||||
for (int lp = 0; lp <= lprime; lp++) {
|
||||
int symb = csi_params->symb_l0;
|
||||
const uint32_t *gold =
|
||||
nr_gold_csi_rs(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, slot, symb + lp, csi_params->scramb_id);
|
||||
nr_modulation(gold, csi_length, DMRS_MOD_ORDER, mod_csi[symb + lp]);
|
||||
uint8_t row = csi_params->row;
|
||||
if ((row == 5) || (row == 7) || (row == 11) || (row == 13) || (row == 16)) {
|
||||
const uint32_t *gold =
|
||||
nr_gold_csi_rs(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, slot, symb + 1, csi_params->scramb_id);
|
||||
nr_modulation(gold, csi_length, DMRS_MOD_ORDER, mod_csi[symb + 1]);
|
||||
}
|
||||
if ((row == 14) || (row == 13) || (row == 16) || (row == 17)) {
|
||||
symb = csi_params->symb_l1;
|
||||
const uint32_t *gold =
|
||||
nr_gold_csi_rs(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, slot, symb + lp, csi_params->scramb_id);
|
||||
nr_modulation(gold, csi_length, DMRS_MOD_ORDER, mod_csi[symb + lp]);
|
||||
if ((row == 13) || (row == 16)) {
|
||||
const uint32_t *gold =
|
||||
nr_gold_csi_rs(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, slot, symb + 1, csi_params->scramb_id);
|
||||
nr_modulation(gold, csi_length, DMRS_MOD_ORDER, mod_csi[symb + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t start_sc = frame_parms->first_carrier_offset;
|
||||
|
||||
// resource mapping according to 38.211 7.4.1.5.3
|
||||
for (int n = csi_params->start_rb; n < (csi_params->start_rb + csi_params->nr_of_rbs); n++) {
|
||||
if ((csi_params->freq_density > 1) || (csi_params->freq_density == (n % 2))) { // for freq density 0.5 checks if even or odd RB
|
||||
for (int ji = 0; ji < size; ji++) { // loop over CDM groups
|
||||
for (int s = 0 ; s < gs; s++) { // loop over each CDM group size
|
||||
int p = s + j[ji] * gs; // port index
|
||||
for (int kp = 0; kp <= kprime; kp++) { // loop over frequency resource elements within a group
|
||||
// frequency index of current resource element
|
||||
int k = (start_sc + (n * NR_NB_SC_PER_RB) + koverline[ji] + kp) % (frame_parms->ofdm_symbol_size);
|
||||
// wf according to tables 7.4.5.3-2 to 7.4.5.3-5
|
||||
int wf = kp == 0 ? 1 : (-2 * (s % 2) + 1);
|
||||
int na = n * alpha;
|
||||
int kpn = (rho * koverline[ji]) / NR_NB_SC_PER_RB;
|
||||
int mprime = na + kp + kpn; // sequence index
|
||||
for (int lp = 0; lp <= lprime; lp++) { // loop over frequency resource elements within a group
|
||||
int l = lp + loverline[ji];
|
||||
// wt according to tables 7.4.5.3-2 to 7.4.5.3-5
|
||||
int wt;
|
||||
if (s < 2)
|
||||
wt = 1;
|
||||
else if (s < 4)
|
||||
wt = -2*(lp % 2) + 1;
|
||||
else if (s < 6)
|
||||
wt = -2 * (lp / 2) + 1;
|
||||
else {
|
||||
if ((lp == 0) || (lp == 3))
|
||||
wt = 1;
|
||||
else
|
||||
wt = -1;
|
||||
}
|
||||
int index = ((l * frame_parms->ofdm_symbol_size + k) << 1) + (2 * dataF_offset);
|
||||
((int16_t*)dataF[p])[index] = (beta * wt * wf * mod_csi[l][mprime << 1]) >> 15;
|
||||
((int16_t*)dataF[p])[index + 1] = (beta * wt * wf * mod_csi[l][(mprime << 1) + 1]) >> 15;
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
printf("l,k (%d,%d) seq. index %d \t port %d \t (%d,%d)\n",
|
||||
l,
|
||||
k,
|
||||
mprime,
|
||||
p + 3000,
|
||||
((int16_t*)dataF[p])[index],
|
||||
((int16_t*)dataF[p])[index + 1]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
csi_rs_resource_mapping(dataF,
|
||||
frame_parms->N_RB_DL << 4,
|
||||
mod_csi,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
dataF_offset,
|
||||
frame_parms->first_carrier_offset,
|
||||
phy_csi_parms,
|
||||
csi_params->start_rb,
|
||||
csi_params->nr_of_rbs,
|
||||
alpha,
|
||||
beta,
|
||||
rho,
|
||||
gs,
|
||||
csi_params->freq_density);
|
||||
}
|
||||
|
||||
@@ -177,21 +177,16 @@ bool is_csi_rs_in_symbol(const fapi_nr_dl_config_csirs_pdu_rel15_t csirs_config_
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
const uint8_t N_cdm_groups,
|
||||
const uint8_t CDM_group_size,
|
||||
const uint8_t k_prime,
|
||||
const uint8_t l_prime,
|
||||
const uint8_t *j_cdm,
|
||||
const uint8_t *k_overline,
|
||||
const uint8_t *l_overline,
|
||||
int32_t csi_rs_received_signal[][ue->frame_parms.samples_per_slot_wCP],
|
||||
uint32_t *rsrp,
|
||||
int *rsrp_dBm,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
static int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
const csi_mapping_parms_t *csi_mapping,
|
||||
const int CDM_group_size,
|
||||
int32_t csi_rs_received_signal[][ue->frame_parms.samples_per_slot_wCP],
|
||||
uint32_t *rsrp,
|
||||
int *rsrp_dBm,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
{
|
||||
const NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
uint16_t meas_count = 0;
|
||||
@@ -206,17 +201,17 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int cdm_id = 0; cdm_id < N_cdm_groups; cdm_id++) {
|
||||
for (int cdm_id = 0; cdm_id < csi_mapping->size; cdm_id++) {
|
||||
for (int s = 0; s < CDM_group_size; s++) {
|
||||
|
||||
// loop over frequency resource elements within a group
|
||||
for (int kp = 0; kp <= k_prime; kp++) {
|
||||
for (int kp = 0; kp <= csi_mapping->kprime; kp++) {
|
||||
|
||||
uint16_t k = (fp->first_carrier_offset + (rb * NR_NB_SC_PER_RB) + k_overline[cdm_id] + kp) % fp->ofdm_symbol_size;
|
||||
uint16_t k = (fp->first_carrier_offset + (rb * NR_NB_SC_PER_RB) + csi_mapping->koverline[cdm_id] + kp) % fp->ofdm_symbol_size;
|
||||
|
||||
// loop over time resource elements within a group
|
||||
for (int lp = 0; lp <= l_prime; lp++) {
|
||||
uint16_t symb = lp + l_overline[cdm_id];
|
||||
for (int lp = 0; lp <= csi_mapping->lprime; lp++) {
|
||||
uint16_t symb = lp + csi_mapping->loverline[cdm_id];
|
||||
uint64_t symbol_offset = symb * fp->ofdm_symbol_size;
|
||||
c16_t *rx_signal = &rxdataF[ant_rx][symbol_offset];
|
||||
c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset];
|
||||
@@ -230,7 +225,7 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
int dataF_offset = proc->nr_slot_rx * fp->samples_per_slot_wCP;
|
||||
uint16_t port_tx = s+j_cdm[cdm_id]*CDM_group_size;
|
||||
uint16_t port_tx = s + csi_mapping->j[cdm_id] * CDM_group_size;
|
||||
c16_t *tx_csi_rs_signal = (c16_t*)&nr_csi_info->csi_rs_generated_signal[port_tx][symbol_offset + dataF_offset];
|
||||
LOG_I(NR_PHY,
|
||||
"l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n",
|
||||
@@ -278,39 +273,32 @@ uint32_t calc_power_csirs(const uint16_t *x, const fapi_nr_dl_config_csirs_pdu_r
|
||||
return sum_x2 / size - (sum_x / size) * (sum_x / size);
|
||||
}
|
||||
|
||||
int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
const int32_t **csi_rs_generated_signal,
|
||||
const int32_t csi_rs_received_signal[][ue->frame_parms.samples_per_slot_wCP],
|
||||
const uint8_t N_cdm_groups,
|
||||
const uint8_t CDM_group_size,
|
||||
const uint8_t k_prime,
|
||||
const uint8_t l_prime,
|
||||
const uint8_t N_ports,
|
||||
const uint8_t *j_cdm,
|
||||
const uint8_t *k_overline,
|
||||
const uint8_t *l_overline,
|
||||
uint8_t mem_offset,
|
||||
int32_t csi_rs_ls_estimated_channel[][N_ports][ue->frame_parms.ofdm_symbol_size],
|
||||
int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
|
||||
int16_t *log2_re,
|
||||
int16_t *log2_maxh,
|
||||
uint32_t *noise_power) {
|
||||
|
||||
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
const int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP;
|
||||
static int nr_csi_rs_channel_estimation(const NR_DL_FRAME_PARMS *fp,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
const int32_t **csi_rs_generated_signal,
|
||||
const int32_t csi_rs_received_signal[][fp->samples_per_slot_wCP],
|
||||
const csi_mapping_parms_t *csi_mapping,
|
||||
const int CDM_group_size,
|
||||
uint8_t mem_offset,
|
||||
int32_t csi_rs_ls_estimated_channel[][csi_mapping->ports][fp->ofdm_symbol_size],
|
||||
int32_t csi_rs_estimated_channel_freq[][csi_mapping->ports][fp->ofdm_symbol_size + FILTER_MARGIN],
|
||||
int16_t *log2_re,
|
||||
int16_t *log2_maxh,
|
||||
uint32_t *noise_power)
|
||||
{
|
||||
const int dataF_offset = proc->nr_slot_rx * fp->samples_per_slot_wCP;
|
||||
*noise_power = 0;
|
||||
int maxh = 0;
|
||||
int count = 0;
|
||||
|
||||
for (int ant_rx = 0; ant_rx < frame_parms->nb_antennas_rx; ant_rx++) {
|
||||
for (int ant_rx = 0; ant_rx < fp->nb_antennas_rx; ant_rx++) {
|
||||
|
||||
/// LS channel estimation
|
||||
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
memset(csi_rs_ls_estimated_channel[ant_rx][port_tx], 0, frame_parms->ofdm_symbol_size*sizeof(int32_t));
|
||||
for(uint16_t port_tx = 0; port_tx < csi_mapping->ports; port_tx++) {
|
||||
memset(csi_rs_ls_estimated_channel[ant_rx][port_tx], 0, fp->ofdm_symbol_size*sizeof(int32_t));
|
||||
}
|
||||
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
@@ -320,21 +308,21 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int cdm_id = 0; cdm_id < N_cdm_groups; cdm_id++) {
|
||||
for (int cdm_id = 0; cdm_id < csi_mapping->size; cdm_id++) {
|
||||
for (int s = 0; s < CDM_group_size; s++) {
|
||||
|
||||
uint16_t port_tx = s+j_cdm[cdm_id]*CDM_group_size;
|
||||
uint16_t port_tx = s + csi_mapping->j[cdm_id] * CDM_group_size;
|
||||
|
||||
// loop over frequency resource elements within a group
|
||||
for (int kp = 0; kp <= k_prime; kp++) {
|
||||
for (int kp = 0; kp <= csi_mapping->kprime; kp++) {
|
||||
|
||||
uint16_t kinit = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
uint16_t k = kinit + k_overline[cdm_id] + kp;
|
||||
uint16_t kinit = (fp->first_carrier_offset + rb*NR_NB_SC_PER_RB) % fp->ofdm_symbol_size;
|
||||
uint16_t k = kinit + csi_mapping->koverline[cdm_id] + kp;
|
||||
|
||||
// loop over time resource elements within a group
|
||||
for (int lp = 0; lp <= l_prime; lp++) {
|
||||
uint16_t symb = lp + l_overline[cdm_id];
|
||||
uint64_t symbol_offset = symb*frame_parms->ofdm_symbol_size;
|
||||
for (int lp = 0; lp <= csi_mapping->lprime; lp++) {
|
||||
uint16_t symb = lp + csi_mapping->loverline[cdm_id];
|
||||
uint64_t symbol_offset = symb * fp->ofdm_symbol_size;
|
||||
c16_t *tx_csi_rs_signal = (c16_t*)&csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset];
|
||||
c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset];
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
|
||||
@@ -357,10 +345,10 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
if(!is_csi_rs_in_symbol(*csirs_config_pdu,symb)) {
|
||||
continue;
|
||||
}
|
||||
for(int k = 0; k<frame_parms->ofdm_symbol_size; k++) {
|
||||
for(int k = 0; k < fp->ofdm_symbol_size; k++) {
|
||||
LOG_I(NR_PHY, "l,k (%2d,%4d) | ", symb, k);
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
uint64_t symbol_offset = symb*frame_parms->ofdm_symbol_size;
|
||||
for(uint16_t port_tx = 0; port_tx < csi_mapping->ports; port_tx++) {
|
||||
uint64_t symbol_offset = symb * fp->ofdm_symbol_size;
|
||||
c16_t *tx_csi_rs_signal = (c16_t*)&csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset];
|
||||
c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset];
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
|
||||
@@ -377,8 +365,8 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
|
||||
/// Channel interpolation
|
||||
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
memset(csi_rs_estimated_channel_freq[ant_rx][port_tx], 0, (frame_parms->ofdm_symbol_size + FILTER_MARGIN) * sizeof(int32_t));
|
||||
for(uint16_t port_tx = 0; port_tx < csi_mapping->ports; port_tx++) {
|
||||
memset(csi_rs_estimated_channel_freq[ant_rx][port_tx], 0, (fp->ofdm_symbol_size + FILTER_MARGIN) * sizeof(int32_t));
|
||||
}
|
||||
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
@@ -390,15 +378,15 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
|
||||
count++;
|
||||
|
||||
uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
uint16_t k = (fp->first_carrier_offset + rb * NR_NB_SC_PER_RB) % fp->ofdm_symbol_size;
|
||||
uint16_t k_offset = k + mem_offset;
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
for(uint16_t port_tx = 0; port_tx < csi_mapping->ports; port_tx++) {
|
||||
int16_t *csi_rs_ls_estimated_channel16 = (int16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][k];
|
||||
int16_t *csi_rs_estimated_channel16 = (int16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][k_offset];
|
||||
if( (k == 0) || (k == frame_parms->first_carrier_offset) ) { // Start of OFDM symbol case or first occupied subcarrier case
|
||||
if( (k == 0) || (k == fp->first_carrier_offset) ) { // Start of OFDM symbol case or first occupied subcarrier case
|
||||
multadd_real_vector_complex_scalar(filt24_start, csi_rs_ls_estimated_channel16, csi_rs_estimated_channel16, 24);
|
||||
} else if( ( (k + NR_NB_SC_PER_RB) >= frame_parms->ofdm_symbol_size) ||
|
||||
(rb == (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs-1)) ) { // End of OFDM symbol case or Last occupied subcarrier case
|
||||
} else if(((k + NR_NB_SC_PER_RB) >= fp->ofdm_symbol_size) ||
|
||||
(rb == (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs-1))) { // End of OFDM symbol case or Last occupied subcarrier case
|
||||
multadd_real_vector_complex_scalar(filt24_end, csi_rs_ls_estimated_channel16, csi_rs_estimated_channel16 - 3*sizeof(uint64_t), 24);
|
||||
} else { // Middle case
|
||||
multadd_real_vector_complex_scalar(filt24_middle, csi_rs_ls_estimated_channel16, csi_rs_estimated_channel16 - 3*sizeof(uint64_t), 24);
|
||||
@@ -408,15 +396,15 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
|
||||
/// 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[frame_parms->nb_antennas_rx][N_ports][csirs_config_pdu->nr_of_rbs];
|
||||
uint16_t noise_imag[frame_parms->nb_antennas_rx][N_ports][csirs_config_pdu->nr_of_rbs];
|
||||
uint16_t noise_real[fp->nb_antennas_rx][csi_mapping->ports][csirs_config_pdu->nr_of_rbs];
|
||||
uint16_t noise_imag[fp->nb_antennas_rx][csi_mapping->ports][csirs_config_pdu->nr_of_rbs];
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) {
|
||||
continue;
|
||||
}
|
||||
uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
uint16_t k = (fp->first_carrier_offset + rb*NR_NB_SC_PER_RB) % fp->ofdm_symbol_size;
|
||||
uint16_t k_offset = k + mem_offset;
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
for(uint16_t port_tx = 0; port_tx < csi_mapping->ports; port_tx++) {
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][k];
|
||||
c16_t *csi_rs_estimated_channel16 = (c16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][k_offset];
|
||||
noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb] = abs(csi_rs_ls_estimated_channel16->r-csi_rs_estimated_channel16->r);
|
||||
@@ -424,17 +412,17 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
maxh = cmax3(maxh, abs(csi_rs_estimated_channel16->r), abs(csi_rs_estimated_channel16->i));
|
||||
}
|
||||
}
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
for(uint16_t port_tx = 0; port_tx < csi_mapping->ports; port_tx++) {
|
||||
*noise_power += (calc_power_csirs(noise_real[ant_rx][port_tx], csirs_config_pdu) + calc_power_csirs(noise_imag[ant_rx][port_tx],csirs_config_pdu));
|
||||
}
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
for(int k = 0; k<frame_parms->ofdm_symbol_size; k++) {
|
||||
int rb = k >= frame_parms->first_carrier_offset ?
|
||||
(k - frame_parms->first_carrier_offset)/NR_NB_SC_PER_RB :
|
||||
(k + frame_parms->ofdm_symbol_size - frame_parms->first_carrier_offset)/NR_NB_SC_PER_RB;
|
||||
for(int k = 0; k < fp->ofdm_symbol_size; k++) {
|
||||
int rb = k >= fp->first_carrier_offset ?
|
||||
(k - fp->first_carrier_offset)/NR_NB_SC_PER_RB :
|
||||
(k + fp->ofdm_symbol_size - fp->first_carrier_offset)/NR_NB_SC_PER_RB;
|
||||
LOG_I(NR_PHY, "(k = %4d) |\t", k);
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
for(uint16_t port_tx = 0; port_tx < csi_mapping->ports; port_tx++) {
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
|
||||
c16_t *csi_rs_estimated_channel16 = (c16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][mem_offset];
|
||||
printf("Channel port_tx %d --> ant_rx %d : ls (%4d,%4d), int (%4d,%4d), noise (%4d,%4d) | ",
|
||||
@@ -450,14 +438,13 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
|
||||
}
|
||||
|
||||
*noise_power /= (frame_parms->nb_antennas_rx*N_ports);
|
||||
*log2_maxh = log2_approx(maxh-1);
|
||||
*log2_re = log2_approx(count-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);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -828,24 +815,64 @@ void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
|
||||
ue->nr_csi_info->csi_im_meas_computed = true;
|
||||
}
|
||||
|
||||
static nfapi_nr_dl_tti_csi_rs_pdu_rel15_t convert_csirs_pdu(const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu)
|
||||
static void nr_ue_generate_csi_rs(const fapi_nr_dl_config_csirs_pdu_rel15_t *csi_params,
|
||||
const csi_mapping_parms_t *mapping_parms,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int16_t amp,
|
||||
const int slot,
|
||||
int32_t **dataF)
|
||||
{
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t dl_tti_csi_rs_pdu;
|
||||
dl_tti_csi_rs_pdu.subcarrier_spacing = csirs_config_pdu->subcarrier_spacing;
|
||||
dl_tti_csi_rs_pdu.cyclic_prefix = csirs_config_pdu->cyclic_prefix;
|
||||
dl_tti_csi_rs_pdu.start_rb = csirs_config_pdu->start_rb;
|
||||
dl_tti_csi_rs_pdu.nr_of_rbs = csirs_config_pdu->nr_of_rbs;
|
||||
dl_tti_csi_rs_pdu.csi_type = csirs_config_pdu->csi_type;
|
||||
dl_tti_csi_rs_pdu.row = csirs_config_pdu->row;
|
||||
dl_tti_csi_rs_pdu.freq_domain = csirs_config_pdu->freq_domain;
|
||||
dl_tti_csi_rs_pdu.symb_l0 = csirs_config_pdu->symb_l0;
|
||||
dl_tti_csi_rs_pdu.symb_l1 = csirs_config_pdu->symb_l1;
|
||||
dl_tti_csi_rs_pdu.cdm_type = csirs_config_pdu->cdm_type;
|
||||
dl_tti_csi_rs_pdu.freq_density = csirs_config_pdu->freq_density;
|
||||
dl_tti_csi_rs_pdu.scramb_id = csirs_config_pdu->scramb_id;
|
||||
dl_tti_csi_rs_pdu.power_control_offset = csirs_config_pdu->power_control_offset;
|
||||
dl_tti_csi_rs_pdu.power_control_offset_ss = csirs_config_pdu->power_control_offset_ss;
|
||||
return dl_tti_csi_rs_pdu;
|
||||
// setting the frequency density from its index
|
||||
double rho = get_csi_rho(csi_params->freq_density);
|
||||
int csi_length = get_csi_modulation_length(rho,
|
||||
csi_params->freq_density,
|
||||
mapping_parms->kprime,
|
||||
csi_params->start_rb,
|
||||
csi_params->nr_of_rbs);
|
||||
|
||||
//*8(max allocation per RB)*2(QPSK))
|
||||
int16_t mod_csi[frame_parms->symbols_per_slot][(frame_parms->N_RB_DL << 4) >> 1] __attribute__((aligned(16)));
|
||||
get_modulated_csi_symbols(frame_parms->symbols_per_slot,
|
||||
slot,
|
||||
frame_parms->N_RB_DL,
|
||||
csi_length,
|
||||
mod_csi,
|
||||
mapping_parms->lprime,
|
||||
csi_params->symb_l0,
|
||||
csi_params->symb_l1,
|
||||
csi_params->row,
|
||||
csi_params->scramb_id);
|
||||
|
||||
uint32_t beta = get_csi_beta_amplitude(amp, csi_params->power_control_offset_ss);
|
||||
double alpha = 0;
|
||||
if (mapping_parms->ports == 1)
|
||||
alpha = rho;
|
||||
else
|
||||
alpha = 2 * rho;
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
printf(" rho %f, alpha %f\n", rho, alpha);
|
||||
#endif
|
||||
|
||||
// CDM group size from CDM type index
|
||||
int gs = get_cdm_group_size(csi_params->cdm_type);
|
||||
|
||||
int dataF_offset = slot * frame_parms->samples_per_slot_wCP;
|
||||
|
||||
csi_rs_resource_mapping(dataF,
|
||||
frame_parms->N_RB_DL << 4,
|
||||
mod_csi,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
dataF_offset,
|
||||
frame_parms->first_carrier_offset,
|
||||
mapping_parms,
|
||||
csi_params->start_rb,
|
||||
csi_params->nr_of_rbs,
|
||||
alpha,
|
||||
beta,
|
||||
rho,
|
||||
gs,
|
||||
csi_params->freq_density);
|
||||
}
|
||||
|
||||
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
@@ -857,6 +884,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
if(!ue->csirs_vars[gNB_id]->active) {
|
||||
return;
|
||||
}
|
||||
ue->csirs_vars[gNB_id]->active = 0;
|
||||
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = &ue->csirs_vars[gNB_id]->csirs_config_pdu;
|
||||
|
||||
@@ -882,83 +910,63 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
return;
|
||||
}
|
||||
|
||||
if(csirs_config_pdu->csi_type == 2) {
|
||||
LOG_E(NR_PHY, "Handling of ZP CSI-RS not handled yet at PHY\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
int32_t csi_rs_received_signal[frame_parms->nb_antennas_rx][frame_parms->samples_per_slot_wCP];
|
||||
uint8_t N_cdm_groups = 0;
|
||||
uint8_t CDM_group_size = 0;
|
||||
uint8_t k_prime = 0;
|
||||
uint8_t l_prime = 0;
|
||||
uint8_t N_ports = 0;
|
||||
uint8_t j_cdm[16];
|
||||
uint8_t k_overline[16];
|
||||
uint8_t l_overline[16];
|
||||
int16_t log2_re = 0;
|
||||
int16_t log2_maxh = 0;
|
||||
uint32_t rsrp = 0;
|
||||
int rsrp_dBm = 0;
|
||||
uint32_t noise_power = 0;
|
||||
uint8_t rank_indicator = 0;
|
||||
uint32_t precoded_sinr_dB = 0;
|
||||
uint8_t cqi = 0;
|
||||
uint8_t i1[3] = {0};
|
||||
uint8_t i2[1] = {0};
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t csi_params = convert_csirs_pdu(csirs_config_pdu);
|
||||
nr_generate_csi_rs(frame_parms,
|
||||
ue->nr_csi_info->csi_rs_generated_signal,
|
||||
AMP,
|
||||
ue->nr_csi_info,
|
||||
&csi_params,
|
||||
proc->nr_slot_rx,
|
||||
&N_cdm_groups,
|
||||
&CDM_group_size,
|
||||
&k_prime,
|
||||
&l_prime,
|
||||
&N_ports,
|
||||
j_cdm,
|
||||
k_overline,
|
||||
l_overline);
|
||||
csi_mapping_parms_t mapping_parms = get_csi_mapping_parms(csirs_config_pdu->row,
|
||||
csirs_config_pdu->freq_domain,
|
||||
csirs_config_pdu->symb_l0,
|
||||
csirs_config_pdu->symb_l1);
|
||||
nr_csi_info_t *csi_info = ue->nr_csi_info;
|
||||
nr_ue_generate_csi_rs(csirs_config_pdu,
|
||||
&mapping_parms,
|
||||
frame_parms,
|
||||
AMP,
|
||||
proc->nr_slot_rx,
|
||||
csi_info->csi_rs_generated_signal);
|
||||
|
||||
int32_t csi_rs_ls_estimated_channel[frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size];
|
||||
int32_t csi_rs_estimated_channel_freq[frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN];
|
||||
csi_info->csi_rs_generated_signal_bits = log2_approx(AMP);
|
||||
|
||||
// (long)&csi_rs_estimated_channel_freq[0][0][frame_parms->first_carrier_offset] & 0x1F gives us the remainder of the integer division by 32 of the memory address
|
||||
int32_t csi_rs_ls_estimated_channel[frame_parms->nb_antennas_rx][mapping_parms.ports][frame_parms->ofdm_symbol_size];
|
||||
int32_t csi_rs_estimated_channel_freq[frame_parms->nb_antennas_rx][mapping_parms.ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN];
|
||||
|
||||
// (long)&csi_rs_estimated_channel_freq[0][0][frame_parms->first_carrier_offset] & 0x1F
|
||||
// gives us the remainder of the integer division by 32 of the memory address
|
||||
// By subtracting the previous value of 32, we know how much is left to have a multiple of 32.
|
||||
// Doing >> 2 <=> /sizeof(int32_t), we know what is the index offset of the array.
|
||||
uint8_t mem_offset = (((32 - ((long)&csi_rs_estimated_channel_freq[0][0][frame_parms->first_carrier_offset])) & 0x1F) >> 2);
|
||||
|
||||
int CDM_group_size = get_cdm_group_size(csirs_config_pdu->cdm_type);
|
||||
int32_t csi_rs_received_signal[frame_parms->nb_antennas_rx][frame_parms->samples_per_slot_wCP];
|
||||
uint32_t rsrp = 0;
|
||||
int rsrp_dBm = 0;
|
||||
nr_get_csi_rs_signal(ue,
|
||||
proc,
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
N_cdm_groups,
|
||||
csi_info,
|
||||
&mapping_parms,
|
||||
CDM_group_size,
|
||||
k_prime,
|
||||
l_prime,
|
||||
j_cdm,
|
||||
k_overline,
|
||||
l_overline,
|
||||
csi_rs_received_signal,
|
||||
&rsrp,
|
||||
&rsrp_dBm,
|
||||
rxdataF);
|
||||
|
||||
|
||||
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)
|
||||
nr_csi_rs_channel_estimation(ue,
|
||||
nr_csi_rs_channel_estimation(frame_parms,
|
||||
proc,
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
(const int32_t **) ue->nr_csi_info->csi_rs_generated_signal,
|
||||
csi_info,
|
||||
(const int32_t **) csi_info->csi_rs_generated_signal,
|
||||
csi_rs_received_signal,
|
||||
N_cdm_groups,
|
||||
&mapping_parms,
|
||||
CDM_group_size,
|
||||
k_prime,
|
||||
l_prime,
|
||||
N_ports,
|
||||
j_cdm,
|
||||
k_overline,
|
||||
l_overline,
|
||||
mem_offset,
|
||||
csi_rs_ls_estimated_channel,
|
||||
csi_rs_estimated_channel_freq,
|
||||
@@ -966,27 +974,32 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
&log2_maxh,
|
||||
&noise_power);
|
||||
|
||||
uint8_t rank_indicator = 0;
|
||||
// bit 1 in bitmap to indicate RI measurment
|
||||
if (csirs_config_pdu->measurement_bitmap & 2) {
|
||||
nr_csi_rs_ri_estimation(ue,
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
N_ports,
|
||||
csi_info,
|
||||
mapping_parms.ports,
|
||||
mem_offset,
|
||||
csi_rs_estimated_channel_freq,
|
||||
log2_maxh,
|
||||
&rank_indicator);
|
||||
}
|
||||
|
||||
uint8_t i1[3] = {0};
|
||||
uint8_t i2[1] = {0};
|
||||
uint8_t cqi = 0;
|
||||
uint32_t precoded_sinr_dB = 0;
|
||||
// bit 3 in bitmap to indicate RI measurment
|
||||
if (csirs_config_pdu->measurement_bitmap & 8) {
|
||||
nr_csi_rs_pmi_estimation(ue,
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
N_ports,
|
||||
csi_info,
|
||||
mapping_parms.ports,
|
||||
mem_offset,
|
||||
csi_rs_estimated_channel_freq,
|
||||
ue->nr_csi_info->csi_im_meas_computed ? ue->nr_csi_info->interference_plus_noise_power : noise_power,
|
||||
csi_info->csi_im_meas_computed ? csi_info->interference_plus_noise_power : noise_power,
|
||||
rank_indicator,
|
||||
log2_re,
|
||||
i1,
|
||||
@@ -1029,6 +1042,4 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_CSIRS_IND, ue, NULL, NULL, 1, proc, (void *)&csirs_measurements, NULL);
|
||||
if (ue->if_inst && ue->if_inst->dl_indication)
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -464,9 +464,6 @@ typedef struct PHY_VARS_gNB_s {
|
||||
/// SRS variables
|
||||
nr_srs_info_t **nr_srs_info;
|
||||
|
||||
/// CSI variables
|
||||
nr_csi_info_t *nr_csi_info;
|
||||
|
||||
// reference amplitude for TX
|
||||
int16_t TX_AMP;
|
||||
|
||||
|
||||
@@ -310,6 +310,13 @@ typedef struct {
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t csirs_config_pdu;
|
||||
} NR_UE_CSI_RS;
|
||||
|
||||
typedef struct {
|
||||
uint8_t csi_rs_generated_signal_bits;
|
||||
int32_t **csi_rs_generated_signal;
|
||||
bool csi_im_meas_computed;
|
||||
uint32_t interference_plus_noise_power;
|
||||
} nr_csi_info_t;
|
||||
|
||||
typedef struct {
|
||||
bool active;
|
||||
fapi_nr_ul_config_srs_pdu srs_config_pdu;
|
||||
|
||||
@@ -119,13 +119,6 @@ typedef struct {
|
||||
nfapi_nr_srs_pdu_t srs_pdu;
|
||||
} nr_srs_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t csi_rs_generated_signal_bits;
|
||||
int32_t **csi_rs_generated_signal;
|
||||
bool csi_im_meas_computed;
|
||||
uint32_t interference_plus_noise_power;
|
||||
} nr_csi_info_t;
|
||||
|
||||
typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS;
|
||||
|
||||
typedef uint32_t (*get_samples_per_slot_t)(int slot, const NR_DL_FRAME_PARMS *fp);
|
||||
|
||||
@@ -23,7 +23,47 @@
|
||||
#define __NR_PHY_COMMON__H__
|
||||
#include "PHY/impl_defs_top.h"
|
||||
#include "PHY/TOOLS/tools_defs.h"
|
||||
#include "PHY/NR_REFSIG/nr_refsig_common.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
int ports;
|
||||
int kprime;
|
||||
int lprime;
|
||||
int j[16];
|
||||
int koverline[16];
|
||||
int loverline[16];
|
||||
} csi_mapping_parms_t;
|
||||
void get_modulated_csi_symbols(int symbols_per_slot,
|
||||
int slot,
|
||||
int N_RB_DL,
|
||||
int mod_length,
|
||||
int16_t mod_csi[][(N_RB_DL << 4) >> 1],
|
||||
int lprime,
|
||||
int l0,
|
||||
int l1,
|
||||
int row,
|
||||
int scramb_id);
|
||||
void csi_rs_resource_mapping(int32_t **dataF,
|
||||
int csi_rs_length,
|
||||
int16_t mod_csi[][csi_rs_length >> 1],
|
||||
int ofdm_symbol_size,
|
||||
int dataF_offset,
|
||||
int start_sc,
|
||||
const csi_mapping_parms_t *mapping_parms,
|
||||
int start_rb,
|
||||
int nb_rbs,
|
||||
double alpha,
|
||||
int beta,
|
||||
double rho,
|
||||
int gs,
|
||||
int freq_density);
|
||||
csi_mapping_parms_t get_csi_mapping_parms(int row, int b, int l0, int l1);
|
||||
int get_cdm_group_size(int cdm_type);
|
||||
double get_csi_rho(int freq_density);
|
||||
uint32_t get_csi_beta_amplitude(const int16_t amp, int power_control_offset_ss);
|
||||
int get_csi_modulation_length(double rho, int freq_density, int kprime, int start_rb, int nb_rbs);
|
||||
void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re);
|
||||
void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint32_t nb_re);
|
||||
void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int16_t *llr, uint32_t nb_re);
|
||||
|
||||
@@ -0,0 +1,563 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
|
||||
|
||||
void csi_rs_resource_mapping(int32_t **dataF,
|
||||
int csi_rs_length,
|
||||
int16_t mod_csi[][csi_rs_length >> 1],
|
||||
int ofdm_symbol_size,
|
||||
int dataF_offset,
|
||||
int start_sc,
|
||||
const csi_mapping_parms_t *mapping_parms,
|
||||
int start_rb,
|
||||
int nb_rbs,
|
||||
double alpha,
|
||||
int beta,
|
||||
double rho,
|
||||
int gs,
|
||||
int freq_density)
|
||||
{
|
||||
// resource mapping according to 38.211 7.4.1.5.3
|
||||
for (int n = start_rb; n < (start_rb + nb_rbs); n++) {
|
||||
if ((freq_density > 1) || (freq_density == (n % 2))) { // for freq density 0.5 checks if even or odd RB
|
||||
for (int ji = 0; ji < mapping_parms->size; ji++) { // loop over CDM groups
|
||||
for (int s = 0 ; s < gs; s++) { // loop over each CDM group size
|
||||
int p = s + mapping_parms->j[ji] * gs; // port index
|
||||
for (int kp = 0; kp <= mapping_parms->kprime; kp++) { // loop over frequency resource elements within a group
|
||||
// frequency index of current resource element
|
||||
int k = (start_sc + (n * NR_NB_SC_PER_RB) + mapping_parms->koverline[ji] + kp) % (ofdm_symbol_size);
|
||||
// wf according to tables 7.4.5.3-2 to 7.4.5.3-5
|
||||
int wf = kp == 0 ? 1 : (-2 * (s % 2) + 1);
|
||||
int na = n * alpha;
|
||||
int kpn = (rho * mapping_parms->koverline[ji]) / NR_NB_SC_PER_RB;
|
||||
int mprime = na + kp + kpn; // sequence index
|
||||
for (int lp = 0; lp <= mapping_parms->lprime; lp++) { // loop over frequency resource elements within a group
|
||||
int l = lp + mapping_parms->loverline[ji];
|
||||
// wt according to tables 7.4.5.3-2 to 7.4.5.3-5
|
||||
int wt;
|
||||
if (s < 2)
|
||||
wt = 1;
|
||||
else if (s < 4)
|
||||
wt = -2 * (lp % 2) + 1;
|
||||
else if (s < 6)
|
||||
wt = -2 * (lp / 2) + 1;
|
||||
else {
|
||||
if ((lp == 0) || (lp == 3))
|
||||
wt = 1;
|
||||
else
|
||||
wt = -1;
|
||||
}
|
||||
int index = ((l * ofdm_symbol_size + k) << 1) + (2 * dataF_offset);
|
||||
((int16_t*)dataF[p])[index] = (beta * wt * wf * mod_csi[l][mprime << 1]) >> 15;
|
||||
((int16_t*)dataF[p])[index + 1] = (beta * wt * wf * mod_csi[l][(mprime << 1) + 1]) >> 15;
|
||||
LOG_D(PHY,
|
||||
"l,k (%d,%d) seq. index %d \t port %d \t (%d,%d)\n",
|
||||
l,
|
||||
k,
|
||||
mprime,
|
||||
p + 3000,
|
||||
((int16_t*)dataF[p])[index],
|
||||
((int16_t*)dataF[p])[index + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void get_modulated_csi_symbols(int symbols_per_slot,
|
||||
int slot,
|
||||
int N_RB_DL,
|
||||
int mod_length,
|
||||
int16_t mod_csi[][(N_RB_DL << 4) >> 1],
|
||||
int lprime,
|
||||
int l0,
|
||||
int l1,
|
||||
int row,
|
||||
int scramb_id)
|
||||
{
|
||||
for (int lp = 0; lp <= lprime; lp++) {
|
||||
int symb = l0;
|
||||
const uint32_t *gold =
|
||||
nr_gold_csi_rs(N_RB_DL, symbols_per_slot, slot, symb + lp, scramb_id);
|
||||
nr_modulation(gold, mod_length, DMRS_MOD_ORDER, mod_csi[symb + lp]);
|
||||
if ((row == 5) || (row == 7) || (row == 11) || (row == 13) || (row == 16)) {
|
||||
const uint32_t *gold =
|
||||
nr_gold_csi_rs(N_RB_DL, symbols_per_slot, slot, symb + 1, scramb_id);
|
||||
nr_modulation(gold, mod_length, DMRS_MOD_ORDER, mod_csi[symb + 1]);
|
||||
}
|
||||
if ((row == 14) || (row == 13) || (row == 16) || (row == 17)) {
|
||||
symb = l1;
|
||||
const uint32_t *gold =
|
||||
nr_gold_csi_rs(N_RB_DL, symbols_per_slot, slot, symb + lp, scramb_id);
|
||||
nr_modulation(gold, mod_length, DMRS_MOD_ORDER, mod_csi[symb + lp]);
|
||||
if ((row == 13) || (row == 16)) {
|
||||
const uint32_t *gold =
|
||||
nr_gold_csi_rs(N_RB_DL, symbols_per_slot, slot, symb + 1, scramb_id);
|
||||
nr_modulation(gold, mod_length, DMRS_MOD_ORDER, mod_csi[symb + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t get_csi_beta_amplitude(const int16_t amp, int power_control_offset_ss)
|
||||
{
|
||||
uint32_t beta = amp;
|
||||
// assuming amp is the amplitude of SSB channels
|
||||
switch (power_control_offset_ss) {
|
||||
case 0:
|
||||
beta = (amp * ONE_OVER_SQRT2_Q15) >> 15;
|
||||
break;
|
||||
case 1:
|
||||
beta = amp;
|
||||
break;
|
||||
case 2:
|
||||
beta = (amp * ONE_OVER_SQRT2_Q15) >> 14;
|
||||
break;
|
||||
case 3:
|
||||
beta = amp << 1;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Invalid SS power offset density index for CSI\n");
|
||||
}
|
||||
return beta;
|
||||
}
|
||||
|
||||
int get_csi_modulation_length(double rho, int freq_density, int kprime, int start_rb, int nr_rbs)
|
||||
{
|
||||
int csi_length = 0;
|
||||
if (rho < 1) {
|
||||
if (freq_density == 0) {
|
||||
csi_length = (((start_rb + nr_rbs) >> 1) << kprime) << 1;
|
||||
} else {
|
||||
csi_length = ((((start_rb + nr_rbs) >> 1) << kprime) + 1) << 1;
|
||||
}
|
||||
} else {
|
||||
csi_length = (((uint16_t) rho * (start_rb + nr_rbs)) << kprime) << 1;
|
||||
}
|
||||
return csi_length;
|
||||
}
|
||||
|
||||
double get_csi_rho(int freq_density)
|
||||
{
|
||||
// setting the frequency density from its index
|
||||
double rho = 0;
|
||||
switch (freq_density) {
|
||||
case 0:
|
||||
rho = 0.5;
|
||||
break;
|
||||
case 1:
|
||||
rho = 0.5;
|
||||
break;
|
||||
case 2:
|
||||
rho = 1;
|
||||
break;
|
||||
case 3:
|
||||
rho = 3;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Invalid frequency density index for CSI\n");
|
||||
}
|
||||
return rho;
|
||||
}
|
||||
|
||||
int get_cdm_group_size(int cdm_type)
|
||||
{
|
||||
// CDM group size from CDM type index
|
||||
int gs = 0;
|
||||
switch (cdm_type) {
|
||||
case 0:
|
||||
gs = 1;
|
||||
break;
|
||||
case 1:
|
||||
gs = 2;
|
||||
break;
|
||||
case 2:
|
||||
gs = 4;
|
||||
break;
|
||||
case 3:
|
||||
gs = 8;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Invalid cdm type index for CSI\n");
|
||||
}
|
||||
return gs;
|
||||
}
|
||||
|
||||
csi_mapping_parms_t get_csi_mapping_parms(int row, int b, int l0, int l1)
|
||||
{
|
||||
AssertFatal(b != 0, "Invalid CSI frequency domain mapping: no bit selected in bitmap\n");
|
||||
csi_mapping_parms_t csi_parms = {0};
|
||||
int found = 0;
|
||||
int fi = 0;
|
||||
int k_n[6];
|
||||
// implementation of table 7.4.1.5.3-1 of 38.211
|
||||
// lprime and kprime are the max value of l' and k'
|
||||
switch (row) {
|
||||
case 1:
|
||||
csi_parms.ports = 1;
|
||||
csi_parms.kprime = 0;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 3;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = 0;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[0] + (i << 2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
csi_parms.ports = 1;
|
||||
csi_parms.kprime = 0;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 1;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = 0;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[0];
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
csi_parms.ports = 2;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 1;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = 0;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[0];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
csi_parms.ports = 4;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 2;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 2;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[0] + (i << 1);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
csi_parms.ports = 4;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 2;
|
||||
while (found < 1) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
else
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0 + i;
|
||||
csi_parms.koverline[i] = k_n[0];
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
csi_parms.ports = 8;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 4;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
csi_parms.ports = 8;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 4;
|
||||
while (found < 2) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0 + (i >> 1);
|
||||
csi_parms.koverline[i] = k_n[i % 2];
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
csi_parms.ports = 8;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 1;
|
||||
csi_parms.size = 2;
|
||||
while (found < 2) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
csi_parms.ports = 12;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 6;
|
||||
while (found < 6) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
csi_parms.ports = 12;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 1;
|
||||
csi_parms.size = 3;
|
||||
while (found < 3) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
csi_parms.ports = 16;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 8;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0 + (i >> 2);
|
||||
csi_parms.koverline[i] = k_n[i % 4];
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
csi_parms.ports = 16;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 1;
|
||||
csi_parms.size = 4;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
csi_parms.ports = 24;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 12;
|
||||
while (found < 3) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
if (i < 6)
|
||||
csi_parms.loverline[i] = l0 + i / 3;
|
||||
else
|
||||
csi_parms.loverline[i] = l1 + i / 9;
|
||||
csi_parms.koverline[i] = k_n[i % 3];
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
csi_parms.ports = 24;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 1;
|
||||
csi_parms.size = 6;
|
||||
while (found < 3) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
if (i < 3)
|
||||
csi_parms.loverline[i] = l0;
|
||||
else
|
||||
csi_parms.loverline[i] = l1;
|
||||
csi_parms.koverline[i] = k_n[i % 3];
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
csi_parms.ports = 24;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 3;
|
||||
csi_parms.size = 3;
|
||||
while (found < 3) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
csi_parms.ports = 32;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 0;
|
||||
csi_parms.size = 16;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
if (i < 8)
|
||||
csi_parms.loverline[i] = l0 + (i >> 2);
|
||||
else
|
||||
csi_parms.loverline[i] = l1 + (i / 12);
|
||||
csi_parms.koverline[i] = k_n[i % 4];
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
csi_parms.ports = 32;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 1;
|
||||
csi_parms.size = 8;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
if (i < 4)
|
||||
csi_parms.loverline[i] = l0;
|
||||
else
|
||||
csi_parms.loverline[i] = l1;
|
||||
csi_parms.koverline[i] = k_n[i % 4];
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
csi_parms.ports = 32;
|
||||
csi_parms.kprime = 1;
|
||||
csi_parms.lprime = 3;
|
||||
csi_parms.size = 4;
|
||||
while (found < 4) {
|
||||
if ((b >> fi) & 0x01) {
|
||||
k_n[found] = fi << 1;
|
||||
found++;
|
||||
}
|
||||
fi++;
|
||||
}
|
||||
for (int i = 0; i < csi_parms.size; i++) {
|
||||
csi_parms.j[i] = i;
|
||||
csi_parms.loverline[i] = l0;
|
||||
csi_parms.koverline[i] = k_n[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Row %d is not valid for CSI Table 7.4.1.5.3-1\n", row);
|
||||
}
|
||||
return csi_parms;
|
||||
}
|
||||
|
||||
@@ -220,20 +220,20 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
if (csirs->active == 1) {
|
||||
LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot);
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csirs->csirs_pdu.csi_rs_pdu_rel15;
|
||||
if (csi_params->csi_type == 2) { // ZP-CSI
|
||||
csirs->active = 0;
|
||||
return;
|
||||
}
|
||||
csi_mapping_parms_t mapping_parms = get_csi_mapping_parms(csi_params->row,
|
||||
csi_params->freq_domain,
|
||||
csi_params->symb_l0,
|
||||
csi_params->symb_l1);
|
||||
nr_generate_csi_rs(&gNB->frame_parms,
|
||||
(int32_t **)gNB->common_vars.txdataF,
|
||||
gNB->TX_AMP,
|
||||
gNB->nr_csi_info,
|
||||
csi_params,
|
||||
slot,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
&mapping_parms);
|
||||
csirs->active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1081,7 +1081,6 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
|
||||
}
|
||||
}
|
||||
nr_ue_csi_rs_procedures(ue, proc, rxdataF);
|
||||
ue->csirs_vars[gNB_id]->active = 0;
|
||||
}
|
||||
|
||||
if (dlsch[0].active) {
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include <semaphore.h>
|
||||
#include "fapi_nr_ue_interface.h"
|
||||
#include "openair2/PHY_INTERFACE/queue_t.h"
|
||||
#include "nfapi_nr_interface_scf.h"
|
||||
#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h"
|
||||
#include "NR_Packet_Drop.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/sidelink_nr_ue_interface.h"
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#define __NR_CHAN_MODEL_H__
|
||||
|
||||
#include "common/platform_types.h"
|
||||
#include <nfapi_nr_interface_scf.h>
|
||||
#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h"
|
||||
|
||||
#define NR_NUM_MCS 29
|
||||
|
||||
Reference in New Issue
Block a user