From ad96697d10cb8a9adffdcbbfedd99a1f3748d690 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 3 Oct 2024 15:52:27 +0200 Subject: [PATCH 1/8] common function for CSI-RS mapping parameters --- openair1/PHY/NR_TRANSPORT/nr_csi_rs.c | 412 ++---------------- .../PHY/nr_phy_common/inc/nr_phy_common.h | 10 + .../PHY/nr_phy_common/src/nr_phy_common.c | 357 +++++++++++++++ 3 files changed, 393 insertions(+), 386 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c index 3c859a7e67..715d2e4249 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c @@ -21,6 +21,7 @@ #include "PHY/MODULATION/nr_modulation.h" #include "PHY/NR_REFSIG/nr_refsig.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" //#define NR_CSIRS_DEBUG @@ -60,379 +61,13 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, //*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); - } - -#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"); -#endif - + csi_mapping_parms_t phy_csi_parms = get_csi_mapping_parms(csi_params->row, + csi_params->freq_domain, + csi_params->symb_l0, + csi_params->symb_l1); // setting the frequency density from its index double rho = 0; @@ -454,7 +89,7 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, } double alpha = 0; - if (ports == 1) + if (phy_csi_parms.ports == 1) alpha = rho; else alpha = 2 * rho; @@ -482,6 +117,7 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, AssertFatal(false, "Invalid cdm type index for CSI\n"); } + int kprime = phy_csi_parms.kprime; int csi_length; if (rho < 1) { if (csi_params->freq_density == 0) { @@ -498,21 +134,21 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, #endif if (N_cdm_groups) - *N_cdm_groups = size; + *N_cdm_groups = phy_csi_parms.size; if (CDM_group_size) *CDM_group_size = gs; if (k_prime) *k_prime = kprime; if (l_prime) - *l_prime = lprime; + *l_prime = phy_csi_parms.lprime; if (N_ports) - *N_ports = ports; + *N_ports = phy_csi_parms.ports; if (j_cdm) - memcpy(j_cdm, j, 16 * sizeof(uint8_t)); + memcpy(j_cdm, phy_csi_parms.j, 16 * sizeof(uint8_t)); if (k_overline) - memcpy(k_overline, koverline, 16 * sizeof(uint8_t)); + memcpy(k_overline, phy_csi_parms.koverline, 16 * sizeof(uint8_t)); if (l_overline) - memcpy(l_overline, loverline, 16 * sizeof(uint8_t)); + memcpy(l_overline, phy_csi_parms.loverline, 16 * sizeof(uint8_t)); #ifdef NR_CSIRS_DEBUG if (N_ports) @@ -527,7 +163,12 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, 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]); + LOG_I(NR_PHY, + "(CDM group %d) j = %d, koverline = %d, loverline = %d\n", + ji, + phy_csi_parms.j[ji], + phy_csi_parms.koverline[ji], + phy_csi_parms.loverline[ji]); } } #endif @@ -553,7 +194,7 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, AssertFatal(false, "Invalid SS power offset density index for CSI\n"); } - for (int lp = 0; lp <= lprime; lp++) { + for (int lp = 0; lp <= phy_csi_parms.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); @@ -578,23 +219,22 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, } 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 ji = 0; ji < phy_csi_parms.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 + int p = s + phy_csi_parms.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); + int k = (start_sc + (n * NR_NB_SC_PER_RB) + phy_csi_parms.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 kpn = (rho * phy_csi_parms.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]; + for (int lp = 0; lp <= phy_csi_parms.lprime; lp++) { // loop over frequency resource elements within a group + int l = lp + phy_csi_parms.loverline[ji]; // wt according to tables 7.4.5.3-2 to 7.4.5.3-5 int wt; if (s < 2) diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 579102b677..26de45e630 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -24,6 +24,16 @@ #include "PHY/impl_defs_top.h" #include "PHY/TOOLS/tools_defs.h" +typedef struct { + int size; + int ports; + int kprime; + int lprime; + int j[16]; + int koverline[16]; + int loverline[16]; +} csi_mapping_parms_t; +csi_mapping_parms_t get_csi_mapping_parms(int row, int b, int l0, int l1); 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); diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index ef10837d2d..82e5a3dc96 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -354,6 +354,363 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int simde_mm_empty(); } +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; +} + void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal) { const idft_size_idx_t idft_size = get_idft(ofdm_symbol_size); From 7e009781cda878434f55465352df8a5ba090545e Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 3 Oct 2024 19:00:25 +0200 Subject: [PATCH 2/8] moving out CSI mapping parameters from nr_generate_csi_rs --- openair1/PHY/NR_REFSIG/nr_refsig.h | 10 +- openair1/PHY/NR_TRANSPORT/nr_csi_rs.c | 97 ++------- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 196 ++++++++---------- .../PHY/nr_phy_common/inc/nr_phy_common.h | 1 + .../PHY/nr_phy_common/src/nr_phy_common.c | 23 ++ openair1/SCHED_NR/phy_procedures_nr_gNB.c | 13 +- 6 files changed, 126 insertions(+), 214 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index cf93433db7..4cd76d6b8b 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -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, @@ -43,14 +44,7 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, 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); diff --git a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c index 715d2e4249..aab9abbcc6 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c @@ -21,7 +21,6 @@ #include "PHY/MODULATION/nr_modulation.h" #include "PHY/NR_REFSIG/nr_refsig.h" -#include "PHY/nr_phy_common/inc/nr_phy_common.h" //#define NR_CSIRS_DEBUG @@ -31,14 +30,7 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, 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); @@ -64,11 +56,6 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, uint32_t beta = amp; nr_csi_info->csi_rs_generated_signal_bits = log2_approx(amp); - csi_mapping_parms_t phy_csi_parms = get_csi_mapping_parms(csi_params->row, - csi_params->freq_domain, - csi_params->symb_l0, - csi_params->symb_l1); - // setting the frequency density from its index double rho = 0; switch (csi_params->freq_density) { @@ -89,7 +76,7 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, } double alpha = 0; - if (phy_csi_parms.ports == 1) + if (phy_csi_parms->ports == 1) alpha = rho; else alpha = 2 * rho; @@ -99,25 +86,9 @@ 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 kprime = phy_csi_parms.kprime; + int kprime = phy_csi_parms->kprime; int csi_length; if (rho < 1) { if (csi_params->freq_density == 0) { @@ -133,59 +104,19 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, 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 = phy_csi_parms.size; - if (CDM_group_size) - *CDM_group_size = gs; - if (k_prime) - *k_prime = kprime; - if (l_prime) - *l_prime = phy_csi_parms.lprime; - if (N_ports) - *N_ports = phy_csi_parms.ports; - if (j_cdm) - memcpy(j_cdm, phy_csi_parms.j, 16 * sizeof(uint8_t)); - if (k_overline) - memcpy(k_overline, phy_csi_parms.koverline, 16 * sizeof(uint8_t)); - if (l_overline) - memcpy(l_overline, phy_csi_parms.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, - phy_csi_parms.j[ji], - phy_csi_parms.koverline[ji], - phy_csi_parms.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; + beta = (amp * ONE_OVER_SQRT2_Q15) >> 15; break; case 1: beta = amp; break; case 2: - beta = (amp*ONE_OVER_SQRT2_Q15)>>14; + beta = (amp * ONE_OVER_SQRT2_Q15) >> 14; break; case 3: beta = amp << 1; @@ -194,7 +125,7 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, AssertFatal(false, "Invalid SS power offset density index for CSI\n"); } - for (int lp = 0; lp <= phy_csi_parms.lprime; lp++) { + for (int lp = 0; lp <= phy_csi_parms->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); @@ -222,25 +153,25 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, // 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 < phy_csi_parms.size; ji++) { // loop over CDM groups + for (int ji = 0; ji < phy_csi_parms->size; ji++) { // loop over CDM groups for (int s = 0 ; s < gs; s++) { // loop over each CDM group size - int p = s + phy_csi_parms.j[ji] * gs; // port index + int p = s + phy_csi_parms->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) + phy_csi_parms.koverline[ji] + kp) % (frame_parms->ofdm_symbol_size); + int k = (start_sc + (n * NR_NB_SC_PER_RB) + phy_csi_parms->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 * phy_csi_parms.koverline[ji]) / NR_NB_SC_PER_RB; + int kpn = (rho * phy_csi_parms->koverline[ji]) / NR_NB_SC_PER_RB; int mprime = na + kp + kpn; // sequence index - for (int lp = 0; lp <= phy_csi_parms.lprime; lp++) { // loop over frequency resource elements within a group - int l = lp + phy_csi_parms.loverline[ji]; + for (int lp = 0; lp <= phy_csi_parms->lprime; lp++) { // loop over frequency resource elements within a group + int l = lp + phy_csi_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; + wt = -2 * (lp % 2) + 1; else if (s < 6) wt = -2 * (lp / 2) + 1; else { diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index e75f22cab7..7dae8b89b3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -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_txofdm_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; kofdm_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_txofdm_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_txofdm_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_txports; 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_txports; 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_txports; 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; kofdm_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_txports; 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; } @@ -884,14 +871,6 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, 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; @@ -903,40 +882,33 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, 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); + 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_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); + &mapping_parms); - 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]; + 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 + // (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); nr_get_csi_rs_signal(ue, proc, csirs_config_pdu, ue->nr_csi_info, - N_cdm_groups, + &mapping_parms, CDM_group_size, - k_prime, - l_prime, - j_cdm, - k_overline, - l_overline, csi_rs_received_signal, &rsrp, &rsrp_dBm, @@ -945,20 +917,14 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, // 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_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, @@ -971,7 +937,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, nr_csi_rs_ri_estimation(ue, csirs_config_pdu, ue->nr_csi_info, - N_ports, + mapping_parms.ports, mem_offset, csi_rs_estimated_channel_freq, log2_maxh, @@ -983,7 +949,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, nr_csi_rs_pmi_estimation(ue, csirs_config_pdu, ue->nr_csi_info, - N_ports, + 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, diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 26de45e630..2731470618 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -34,6 +34,7 @@ typedef struct { int loverline[16]; } csi_mapping_parms_t; csi_mapping_parms_t get_csi_mapping_parms(int row, int b, int l0, int l1); +int get_cdm_group_size(int cdm_type); 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); diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index 82e5a3dc96..88e941c49f 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -354,6 +354,29 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int simde_mm_empty(); } +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"); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 73f71fad25..bfbb6af01f 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -220,20 +220,17 @@ 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; + 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; } } From ddbbaef302cb7e01debbea7afb510775e8572f18 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 3 Oct 2024 19:34:05 +0200 Subject: [PATCH 3/8] remove nr_csi_info_t from gNB (unused) --- openair1/PHY/INIT/nr_init.c | 6 ------ openair1/PHY/NR_REFSIG/nr_refsig.h | 1 - openair1/PHY/NR_TRANSPORT/nr_csi_rs.c | 2 -- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 18 ++++++++++-------- openair1/PHY/defs_gNB.h | 3 --- openair1/PHY/defs_nr_UE.h | 7 +++++++ openair1/PHY/defs_nr_common.h | 7 ------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 1 - 8 files changed, 17 insertions(+), 28 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 68333c821c..91c9daeef4 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -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; inr_srs_info[id]->srs_generated_signal[i]); diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index 4cd76d6b8b..7996db109a 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -41,7 +41,6 @@ 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, const csi_mapping_parms_t *phy_csi_parms); diff --git a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c index aab9abbcc6..cf5ead64a2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c @@ -27,7 +27,6 @@ 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, const csi_mapping_parms_t *phy_csi_parms) @@ -54,7 +53,6 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, 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))); uint32_t beta = amp; - nr_csi_info->csi_rs_generated_signal_bits = log2_approx(amp); // setting the frequency density from its index double rho = 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 7dae8b89b3..28e2c6b421 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -886,14 +886,16 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, 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_generate_csi_rs(frame_parms, - ue->nr_csi_info->csi_rs_generated_signal, + csi_info->csi_rs_generated_signal, AMP, - ue->nr_csi_info, &csi_params, proc->nr_slot_rx, &mapping_parms); + csi_info->csi_rs_generated_signal_bits = log2_approx(AMP); + 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]; @@ -906,7 +908,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, nr_get_csi_rs_signal(ue, proc, csirs_config_pdu, - ue->nr_csi_info, + csi_info, &mapping_parms, CDM_group_size, csi_rs_received_signal, @@ -920,8 +922,8 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *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, &mapping_parms, CDM_group_size, @@ -936,7 +938,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, if (csirs_config_pdu->measurement_bitmap & 2) { nr_csi_rs_ri_estimation(ue, csirs_config_pdu, - ue->nr_csi_info, + csi_info, mapping_parms.ports, mem_offset, csi_rs_estimated_channel_freq, @@ -948,11 +950,11 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, if (csirs_config_pdu->measurement_bitmap & 8) { nr_csi_rs_pmi_estimation(ue, csirs_config_pdu, - ue->nr_csi_info, + 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, diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 154f752392..fb7bfb887b 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -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; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 0d077dfd42..4def69049e 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -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; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 07eef7a90e..64f3ef303c 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -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); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index bfbb6af01f..e6d2e3bdce 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -227,7 +227,6 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, nr_generate_csi_rs(&gNB->frame_parms, (int32_t **)gNB->common_vars.txdataF, gNB->TX_AMP, - gNB->nr_csi_info, csi_params, slot, &mapping_parms); From 26fd99ff61cc69f454e69adbfbb5a09c64f0db54 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 4 Oct 2024 11:01:51 +0200 Subject: [PATCH 4/8] terminal independent common functions in nr_generate_csi_rs --- openair1/PHY/NR_TRANSPORT/nr_csi_rs.c | 171 ++++-------------- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 5 + .../PHY/nr_phy_common/inc/nr_phy_common.h | 29 +++ .../PHY/nr_phy_common/src/nr_phy_common.c | 160 ++++++++++++++++ openair1/SCHED_NR/phy_procedures_nr_gNB.c | 4 + 5 files changed, 237 insertions(+), 132 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c index cf5ead64a2..50c1b73d01 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c @@ -48,31 +48,32 @@ 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))); - uint32_t beta = amp; - // 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"); - } + 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(" 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); + + uint32_t beta = get_csi_beta_amplitude(amp, csi_params->power_control_offset_ss); double alpha = 0; if (phy_csi_parms->ports == 1) alpha = rho; @@ -86,114 +87,20 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, // CDM group size from CDM type index int gs = get_cdm_group_size(csi_params->cdm_type); - int kprime = phy_csi_parms->kprime; - 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 (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 <= phy_csi_parms->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 < phy_csi_parms->size; ji++) { // loop over CDM groups - for (int s = 0 ; s < gs; s++) { // loop over each CDM group size - int p = s + phy_csi_parms->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) + phy_csi_parms->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 * phy_csi_parms->koverline[ji]) / NR_NB_SC_PER_RB; - int mprime = na + kp + kpn; // sequence index - for (int lp = 0; lp <= phy_csi_parms->lprime; lp++) { // loop over frequency resource elements within a group - int l = lp + phy_csi_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 * 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); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 28e2c6b421..3250cf5f31 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -869,6 +869,11 @@ 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]; int16_t log2_re = 0; diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 2731470618..e0bc2aaa15 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -23,6 +23,8 @@ #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; @@ -33,8 +35,35 @@ typedef struct { 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); diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index 88e941c49f..aaf93444cd 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -354,6 +354,166 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int simde_mm_empty(); } +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 diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index e6d2e3bdce..f713c3b1af 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -220,6 +220,10 @@ 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, From a54a919bd8f14ff6c45f3592d3d7253d0d420ae7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 4 Oct 2024 11:21:25 +0200 Subject: [PATCH 5/8] removing UE dependence on gNB CSI FAPI structure and decoupling UE from gNB procedures --- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 109 ++++++++++++------ openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h | 1 - openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.h | 1 - 3 files changed, 74 insertions(+), 37 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 3250cf5f31..74eb152121 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -815,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, @@ -875,29 +915,17 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, } 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]; - 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); 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_generate_csi_rs(frame_parms, - csi_info->csi_rs_generated_signal, - AMP, - &csi_params, - proc->nr_slot_rx, - &mapping_parms); + nr_ue_generate_csi_rs(csirs_config_pdu, + &mapping_parms, + frame_parms, + AMP, + proc->nr_slot_rx, + csi_info->csi_rs_generated_signal); csi_info->csi_rs_generated_signal_bits = log2_approx(AMP); @@ -910,6 +938,9 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, // 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, @@ -922,6 +953,9 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, 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(frame_parms, @@ -939,6 +973,7 @@ 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, @@ -951,6 +986,10 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, &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, diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index f82555f149..6654fc8bff 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -37,7 +37,6 @@ #include #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" diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.h b/openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.h index 02907f9940..dcc5710724 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.h @@ -22,7 +22,6 @@ #define __NR_CHAN_MODEL_H__ #include "common/platform_types.h" -#include #include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" #define NR_NUM_MCS 29 From 46beda91eea397bff16517cdca864c2ea843c465 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 7 Oct 2024 11:52:37 +0200 Subject: [PATCH 6/8] moving CSI-RS common functions to a new file --- CMakeLists.txt | 6 +- .../PHY/nr_phy_common/src/nr_phy_common.c | 540 ----------------- .../nr_phy_common/src/nr_phy_common_csirs.c | 563 ++++++++++++++++++ 3 files changed, 565 insertions(+), 544 deletions(-) create mode 100644 openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d3834319f..0eb40de493 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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} diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index aaf93444cd..ef10837d2d 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -354,546 +354,6 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int simde_mm_empty(); } -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; -} - void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal) { const idft_size_idx_t idft_size = get_idft(ofdm_symbol_size); diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c new file mode 100644 index 0000000000..bba93b35e6 --- /dev/null +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c @@ -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; +} + From f25ad2b09848f12a6834734d5d8227283d0f5b58 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 8 Oct 2024 09:46:28 +0200 Subject: [PATCH 7/8] remove unnecessary return at the end of nr_ue_csi_rs_procedures --- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 74eb152121..b607ec0a4f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -1041,6 +1041,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; } From aaf9b57abbdd12dc74d9dfde62af561289ea3fe8 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 9 Oct 2024 10:01:46 +0100 Subject: [PATCH 8/8] Call active=0 for CSI-RS early --- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 1 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index b607ec0a4f..eed7da6556 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -884,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; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 33b39fd772..cf1ebf8319 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -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) {