From e7562e5b3ff6e09c4edddd67266df0d5e3867792 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 18 Jan 2021 10:53:48 +0100 Subject: [PATCH] Added ZC sequence LUT object --- lib/include/srslte/phy/common/zc_sequence.h | 54 ++++++++++++- lib/src/phy/common/zc_sequence.c | 85 ++++++++++++++++++++- 2 files changed, 136 insertions(+), 3 deletions(-) diff --git a/lib/include/srslte/phy/common/zc_sequence.h b/lib/include/srslte/phy/common/zc_sequence.h index ac77b9371..66c71ef89 100644 --- a/lib/include/srslte/phy/common/zc_sequence.h +++ b/lib/include/srslte/phy/common/zc_sequence.h @@ -17,6 +17,16 @@ #include #include +/** + * @brief Defines the maximum number of ZC sequence groups (u) + */ +#define SRSLTE_ZC_SEQUENCE_NOF_GROUPS 30 + +/** + * @brief Defines the maximum number of base sequences (v) + */ +#define SRSLTE_ZC_SEQUENCE_NOF_BASE 2 + /** * @brief Generates ZC sequences given the required parameters used in the TS 36 series (LTE) * @@ -35,7 +45,7 @@ SRSLTE_API int srslte_zc_sequence_generate_lte(uint32_t u, uint32_t v, float alp * @brief Generates ZC sequences given the required parameters used in the TS 38 series (NR) * * @remark Implemented as defined in TS 38.211 section 5.2.2 Low-PAPR sequence generation - + * * @param u Group number {0,1,...29} * @param v base sequence * @param alpha Phase shift @@ -47,4 +57,46 @@ SRSLTE_API int srslte_zc_sequence_generate_lte(uint32_t u, uint32_t v, float alp SRSLTE_API int srslte_zc_sequence_generate_nr(uint32_t u, uint32_t v, float alpha, uint32_t m, uint32_t delta, cf_t* sequence); +/** + * @brief Low-PAPR ZC sequence look-up-table + */ +typedef struct SRSLTE_API { + uint32_t M_zc; + uint32_t nof_alphas; + cf_t* sequence[SRSLTE_ZC_SEQUENCE_NOF_GROUPS][SRSLTE_ZC_SEQUENCE_NOF_BASE]; +} srslte_zc_sequence_lut_t; + +/** + * @brief Initialises a Low-PAPR sequence look-up-table object using NR tables + * + * @param q Object pointer + * @param m Number of PRB + * @param delta Delta parameter described in specification + * @param alphas Vector with the alpha shift parameters + * @param nof_alphas Number alpha shifts to generate + * @return SRSLTE_SUCCESS if the initialization is successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_zc_sequence_lut_init_nr(srslte_zc_sequence_lut_t* q, + uint32_t m, + uint32_t delta, + float* alphas, + uint32_t nof_alphas); + +/** + * @brief Deallocates a Low-PAPR sequence look-up-table object + * @param q Object pointer + */ +SRSLTE_API void srslte_zc_sequence_lut_free(srslte_zc_sequence_lut_t* q); + +/** + * @brief Get a Low-PAPR sequence from the LUT + * @param q Object pointer + * @param u Group number {0,1,...29} + * @param v base sequence + * @param alpha_idx Phase shift index + * @return SRSLTE_SUCCESS if the generation is successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API const cf_t* + srslte_zc_sequence_lut_get(const srslte_zc_sequence_lut_t* q, uint32_t u, uint32_t v, uint32_t alpha_idx); + #endif // SRSLTE_ZC_SEQUENCE_H diff --git a/lib/src/phy/common/zc_sequence.c b/lib/src/phy/common/zc_sequence.c index 161833d90..18652c089 100644 --- a/lib/src/phy/common/zc_sequence.c +++ b/lib/src/phy/common/zc_sequence.c @@ -267,11 +267,17 @@ static void zc_sequence_generate(uint32_t M_zc, float alpha, const cf_t* tmp_arg int srslte_zc_sequence_generate_lte(uint32_t u, uint32_t v, float alpha, uint32_t nof_prb, cf_t* sequence) { - + // Check inputs if (sequence == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } + // Check U and V + if (u >= SRSLTE_ZC_SEQUENCE_NOF_GROUPS || v >= SRSLTE_ZC_SEQUENCE_NOF_BASE) { + ERROR("Invalid u (%d) or v (%d)\n", u, v); + return SRSLTE_ERROR_OUT_OF_BOUNDS; + } + // Calculate number of samples uint32_t M_zc = nof_prb * SRSLTE_NRE; @@ -293,6 +299,12 @@ int srslte_zc_sequence_generate_nr(uint32_t u, uint32_t v, float alpha, uint32_t return SRSLTE_ERROR_INVALID_INPUTS; } + // Check U and V + if (u >= SRSLTE_ZC_SEQUENCE_NOF_GROUPS || v >= SRSLTE_ZC_SEQUENCE_NOF_BASE) { + ERROR("Invalid u (%d) or v (%d)\n", u, v); + return SRSLTE_ERROR_OUT_OF_BOUNDS; + } + // Calculate number of samples uint32_t M_zc = (m * SRSLTE_NRE) >> delta; @@ -305,4 +317,73 @@ int srslte_zc_sequence_generate_nr(uint32_t u, uint32_t v, float alpha, uint32_t zc_sequence_generate(M_zc, alpha, sequence, sequence); return SRSLTE_SUCCESS; -} \ No newline at end of file +} + +int srslte_zc_sequence_lut_init_nr(srslte_zc_sequence_lut_t* q, + uint32_t m, + uint32_t delta, + float* alphas, + uint32_t nof_alphas) +{ + if (q == NULL || alphas == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + // Set all structure to zero + SRSLTE_MEM_ZERO(q, srslte_zc_sequence_lut_t, 1); + + // Calculate number of samples + q->M_zc = (m * SRSLTE_NRE) >> delta; + q->nof_alphas = nof_alphas; + + for (uint32_t u = 0; u < SRSLTE_ZC_SEQUENCE_NOF_GROUPS; u++) { + for (uint32_t v = 0; v < SRSLTE_ZC_SEQUENCE_NOF_BASE; v++) { + // Allocate sequence + q->sequence[u][v] = srslte_vec_cf_malloc(nof_alphas * q->M_zc); + if (q->sequence[u][v] == NULL) { + ERROR("Malloc\n"); + return SRSLTE_ERROR; + } + + // Generate a sequence for each alpha + for (uint32_t alpha_idx = 0; alpha_idx < nof_alphas; alpha_idx++) { + if (srslte_zc_sequence_generate_nr(u, v, alphas[alpha_idx], m, delta, &q->sequence[u][v][alpha_idx * q->M_zc]) < + SRSLTE_SUCCESS) { + ERROR("Generating sequence\n"); + return SRSLTE_ERROR; + } + } + } + } + + return SRSLTE_SUCCESS; +} + +void srslte_zc_sequence_lut_free(srslte_zc_sequence_lut_t* q) +{ + for (uint32_t u = 0; u < SRSLTE_ZC_SEQUENCE_NOF_GROUPS; u++) { + for (uint32_t v = 0; v < SRSLTE_ZC_SEQUENCE_NOF_BASE; v++) { + if (q->sequence[u][v] != NULL) { + free(q->sequence[u][v]); + } + } + } + SRSLTE_MEM_ZERO(q, srslte_zc_sequence_lut_t, 1); +} + +const cf_t* srslte_zc_sequence_lut_get(const srslte_zc_sequence_lut_t* q, uint32_t u, uint32_t v, uint32_t alpha_idx) +{ + if (q == NULL) { + return NULL; + } + + if (u >= SRSLTE_ZC_SEQUENCE_NOF_GROUPS) { + return NULL; + } + + if (v >= SRSLTE_ZC_SEQUENCE_NOF_BASE) { + return NULL; + } + + return &q->sequence[u][v][alpha_idx * q->M_zc]; +}