From 423475173d48db579f1b6021a3cb39b1fadc59b4 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 18 Oct 2019 17:25:23 +0200 Subject: [PATCH] Refactored magnitude and argument extraction from sf_worker --- lib/include/srslte/phy/utils/vector.h | 51 +++++++++++++++++++++++++++ lib/src/phy/utils/vector.c | 32 +++++++++++++++++ srsenb/src/phy/cc_worker.cc | 16 ++------- srsue/src/phy/cc_worker.cc | 8 +---- 4 files changed, 86 insertions(+), 21 deletions(-) diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index 7d8beee18..205a7ee33 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -156,6 +156,57 @@ SRSLTE_API void srslte_vec_quant_sus(const int16_t *in, uint16_t *out, const flo SRSLTE_API void srslte_vec_abs_cf(const cf_t *x, float *abs, const uint32_t len); SRSLTE_API void srslte_vec_abs_square_cf(const cf_t *x, float *abs_square, const uint32_t len); +/** + * @brief Extracts module in decibels of a complex vector + * + * This function extracts the module in decibels of a complex array input. Abnormal absolute value inputs (zero, + * infinity and not-a-number) are set to default_value outputs. + * + * Equivalent code: + * for (int i = 0; i < len; i++) { + * float mag = x[i]; + * + * // Check boundaries + * if (isnormal(mag)) { + * // Avoid infinites and zeros + * abs[i] = 20.0f * log10f(mag); + * } else { + * // Set to default value instead + * abs[i] = default_value; + * } + * } + * + * @param x is the input complex vector + * @param default_value is the value to use in case of having an abnormal absolute value. + * @param abs is the destination vector + * @param len is the input and output number of samples + * + */ +SRSLTE_API void srslte_vec_abs_dB_cf(const cf_t* x, float default_value, float* abs, const uint32_t len); + +/** + * @brief Extracts argument in degrees from a complex vector + * + * This function extracts the argument from a complex vector. Infinity and not-a-number results are set to + * default_value. + * + * Equivalent code: + * for(int i = 0; i < len; i++) { + * arg[i] = cargf(x[i]) * (180.0f / M_PI); + * + * if (arg[i]!=0.0f && !isnormal(arg[i])) { + * arg[i] = default_value; + * } + * } + * + * @param x is the input complex vector + * @param default_value is the value to use in case of having an abnormal result. + * @param arg is the destination vector + * @param len is the input and output number of samples + * + */ +SRSLTE_API void srslte_vec_arg_deg_cf(const cf_t* x, float default_value, float* arg, const uint32_t len); + /* Copy 256 bit aligned vector */ SRSLTE_API void srs_vec_cf_cpy(const cf_t *src, cf_t *dst, const int len); diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 026bd2658..473f63396 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -380,6 +380,38 @@ void srslte_vec_abs_cf(const cf_t *x, float *abs, const uint32_t len) { srslte_vec_abs_cf_simd(x, abs, len); } +void srslte_vec_abs_dB_cf(const cf_t* x, float default_value, float* abs, const uint32_t len) +{ + // Convert complex input to absplute value + srslte_vec_abs_cf(x, abs, len); + + // Convert absolute value to dB + for (int i = 0; i < len; i++) { + // Check boundaries + if (isnormal(abs[i])) { + // Avoid infinites and zeros + abs[i] = 20.0f * log10f(abs[i]); + } else { + // Set to default value instead + abs[i] = default_value; + } + } +} + +void srslte_vec_arg_deg_cf(const cf_t* x, float default_value, float* arg, const uint32_t len) +{ + for (int i = 0; i < len; i++) { + // Convert complex value to argument in degrees + arg[i] = cargf(x[i]) * (180.0f / M_PI); + + // Check boundaries + if (arg[i] != 0.0f && !isnormal(arg[i])) { + // different than zero and not normal + arg[i] = default_value; + } + } +} + // PRACH void srslte_vec_abs_square_cf(const cf_t *x, float *abs_square, const uint32_t len) { srslte_vec_abs_square_cf_simd(x,abs_square,len); diff --git a/srsenb/src/phy/cc_worker.cc b/srsenb/src/phy/cc_worker.cc index b1b4b12d6..c40272d5b 100644 --- a/srsenb/src/phy/cc_worker.cc +++ b/srsenb/src/phy/cc_worker.cc @@ -759,31 +759,19 @@ void cc_worker::ue::metrics_ul(uint32_t mcs, float rssi, float sinr, float turbo int cc_worker::read_ce_abs(float* ce_abs) { - uint32_t i = 0; int sz = srslte_symbol_sz(phy->cell.nof_prb); bzero(ce_abs, sizeof(float) * sz); int g = (sz - 12 * phy->cell.nof_prb) / 2; - for (i = 0; i < 12 * phy->cell.nof_prb; i++) { - ce_abs[g + i] = 20 * log10(std::abs(std::complex(enb_ul.chest_res.ce[i]))); - if (isinf(ce_abs[g + i])) { - ce_abs[g + i] = -80; - } - } + srslte_vec_abs_dB_cf(enb_ul.chest_res.ce, -80.0f, &ce_abs[g], SRSLTE_NRE * phy->cell.nof_prb); return sz; } int cc_worker::read_ce_arg(float* ce_arg) { - uint32_t i = 0; int sz = srslte_symbol_sz(phy->cell.nof_prb); bzero(ce_arg, sizeof(float) * sz); int g = (sz - 12 * phy->cell.nof_prb) / 2; - for (i = 0; i < 12 * phy->cell.nof_prb; i++) { - ce_arg[g + i] = std::arg(std::complex(enb_ul.chest_res.ce[i])) * 180.0f / (float)M_PI; - if (isinf(ce_arg[g + i])) { - ce_arg[g + i] = -80; - } - } + srslte_vec_arg_deg_cf(enb_ul.chest_res.ce, -80.0f, &ce_arg[g], SRSLTE_NRE * phy->cell.nof_prb); return sz; } diff --git a/srsue/src/phy/cc_worker.cc b/srsue/src/phy/cc_worker.cc index 2687e72d2..923979bfa 100644 --- a/srsue/src/phy/cc_worker.cc +++ b/srsue/src/phy/cc_worker.cc @@ -904,16 +904,10 @@ void cc_worker::set_config(srslte::phy_cfg_t& phy_cfg) int cc_worker::read_ce_abs(float* ce_abs, uint32_t tx_antenna, uint32_t rx_antenna) { - uint32_t i = 0; int sz = srslte_symbol_sz(cell.nof_prb); bzero(ce_abs, sizeof(float) * sz); int g = (sz - 12 * cell.nof_prb) / 2; - for (i = 0; i < 12 * cell.nof_prb; i++) { - ce_abs[g + i] = 20 * log10f(std::abs(std::complex(ue_dl.chest_res.ce[tx_antenna][rx_antenna][i]))); - if (std::isinf(ce_abs[g + i])) { - ce_abs[g + i] = -80; - } - } + srslte_vec_abs_dB_cf(ue_dl.chest_res.ce[tx_antenna][rx_antenna], -80, &ce_abs[g], SRSLTE_NRE * cell.nof_prb); return sz; }