From 1ee4d84f80b45a3bc5c059e26cdb73649b200736 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 20 Jan 2021 10:04:53 +0100 Subject: [PATCH] Added NR-PUCCH encode/decode format2 skeleton --- lib/include/srslte/phy/phch/pucch_cfg_nr.h | 7 ++ lib/include/srslte/phy/phch/pucch_nr.h | 69 +++++++++++++---- lib/include/srslte/phy/phch/uci_nr.h | 18 +++++ lib/src/phy/phch/pucch_cfg_nr.c | 29 ++++++++ lib/src/phy/phch/pucch_nr.c | 86 +++++++++++++++++++++- lib/src/phy/phch/uci_nr.c | 2 - 6 files changed, 192 insertions(+), 19 deletions(-) diff --git a/lib/include/srslte/phy/phch/pucch_cfg_nr.h b/lib/include/srslte/phy/phch/pucch_cfg_nr.h index 6a7864973..71b21055b 100644 --- a/lib/include/srslte/phy/phch/pucch_cfg_nr.h +++ b/lib/include/srslte/phy/phch/pucch_cfg_nr.h @@ -83,4 +83,11 @@ SRSLTE_API int srslte_pucch_nr_format0_resource_valid(const srslte_pucch_nr_reso */ SRSLTE_API int srslte_pucch_nr_format1_resource_valid(const srslte_pucch_nr_resource_t* resource); +/** + * @brief Validates a PUCCH format 2 resource configuration provided by upper layers + * @param resource Resource configuration to validate + * @return SRSLTE_SUCCESS if valid, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_pucch_nr_format2_resource_valid(const srslte_pucch_nr_resource_t* resource); + #endif // SRSLTE_PUCCH_CFG_NR_H diff --git a/lib/include/srslte/phy/phch/pucch_nr.h b/lib/include/srslte/phy/phch/pucch_nr.h index 9a1a6397d..94d165488 100644 --- a/lib/include/srslte/phy/phch/pucch_nr.h +++ b/lib/include/srslte/phy/phch/pucch_nr.h @@ -13,14 +13,11 @@ #ifndef SRSLTE_PUCCH_NR_H #define SRSLTE_PUCCH_NR_H -#include "srslte/config.h" +#include "srslte/phy/ch_estimation/chest_ul.h" #include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/common/zc_sequence.h" #include "srslte/phy/modem/modem_table.h" #include "srslte/phy/phch/uci_nr.h" -#include -#include -#include /** * @brief Maximum number of symbols (without DMRS) that NR-PUCCH format 1 can transmit @@ -109,8 +106,8 @@ SRSLTE_API int srslte_pucch_nr_alpha_idx(const srslte_carrier_nr_t* car /** * @brief Encode and writes NR-PUCCH format 0 in the resource grid * @remark Described in TS 38.211 clause 6.3.2.3 PUCCH format 0 - * @param[in] q NR-PUCCH encoder/decoder object - * @param[in] carrier Carrier configuration + * @param[in,out] q NR-PUCCH encoder/decoder object + * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 0 resource @@ -128,8 +125,8 @@ SRSLTE_API int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* /** * @brief Measures PUCCH format 0 in the resource grid - * @param[in] q NR-PUCCH encoder/decoder object - * @param[in] carrier Carrier configuration + * @param[in,out] q NR-PUCCH encoder/decoder object + * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 0 resource @@ -150,7 +147,7 @@ SRSLTE_API int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* /** * @brief Get NR-PUCCH orthogonal sequence w * @remark Defined by TS 38.211 Table 6.3.2.4.1-2: Orthogonal sequences ... for PUCCH format 1 - * @param[in] q NR-PUCCH encoder/decoder object + * @param[in,out] q NR-PUCCH encoder/decoder object * @param[in] n_pucch Number of PUCCH symbols * @param[in] i sequence index * @param m OFDM symbol index @@ -161,8 +158,8 @@ SRSLTE_API cf_t srslte_pucch_nr_format1_w(const srslte_pucch_nr_t* q, uint32_t n /** * @brief Encodes and puts NR-PUCCH format 1 in the resource grid * @remark Described in TS 38.211 clause 6.3.2.4 PUCCH format 1 - * @param[in] q NR-PUCCH encoder/decoder object - * @param[in] carrier Carrier configuration + * @param[in,out] q NR-PUCCH encoder/decoder object + * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 1 resource @@ -182,11 +179,11 @@ SRSLTE_API int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* /** * @brief Decodes NR-PUCCH format 1 - * @param[in] q NR-PUCCH encoder/decoder object - * @param[in] carrier Carrier configuration + * @param[in,out] q NR-PUCCH encoder/decoder object + * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration - * @param[in] resource PUCCH format 1 resource + * @param[in] resource PUCCH format 2-4 resource * @param[in] chest_res Channel estimator result * @param[in] slot_symbols Resource grid of the given slot * @param[out] b Bits to decode @@ -203,4 +200,48 @@ SRSLTE_API int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* uint8_t b[SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS], uint32_t nof_bits); +/** + * @brief Encoder NR-PUCCH formats 2, 3 and 4. The NR-PUCCH format is selected by resource->format. + * @param[in,out] q NR-PUCCH encoder/decoder object + * @param[in] carrier Serving cell and Uplink BWP configuration + * @param[in] cfg PUCCH common configuration + * @param[in] slot slot configuration + * @param[in] resource PUCCH format 1 resource + * @param[in] uci_cfg Uplink Control Information configuration + * @param[in] uci_value Uplink Control Information data + * @param[out] slot_symbols Resource grid of the given slot + * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q, + const srslte_carrier_nr_t* carrier, + const srslte_pucch_nr_common_cfg_t* cfg, + const srslte_dl_slot_cfg_t* slot, + const srslte_pucch_nr_resource_t* resource, + const srslte_uci_cfg_nr_t* uci_cfg, + const srslte_uci_value_nr_t* uci_value, + cf_t* slot_symbols); + +/** + * @brief Decode NR-PUCCH format 2, 3, and 4. The NR-PUCCH format is selected by resource->format. + * @param q[in,out] q NR-PUCCH encoder/decoder + * @param[in] carrier Serving cell and Uplink BWP configuration + * @param[in] cfg PUCCH common configuration + * @param[in] slot slot configuration + * @param[in] resource PUCCH format 2-4 resource + * @param[in] uci_cfg Uplink Control Information configuration + * @param[in] chest_res Channel estimator result + * @param[in] slot_symbols Resource grid of the given slot + * @param[out] uci_value Uplink Control Information data + * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_pucch_nr_format_2_3_4_decode(srslte_pucch_nr_t* q, + const srslte_carrier_nr_t* carrier, + const srslte_pucch_nr_common_cfg_t* cfg, + const srslte_dl_slot_cfg_t* slot, + const srslte_pucch_nr_resource_t* resource, + const srslte_uci_cfg_nr_t* uci_cfg, + srslte_chest_ul_res_t* chest_res, + cf_t* slot_symbols, + srslte_uci_value_nr_t* uci_value); + #endif // SRSLTE_PUCCH_NR_H diff --git a/lib/include/srslte/phy/phch/uci_nr.h b/lib/include/srslte/phy/phch/uci_nr.h index 8d31c3124..898eb8744 100644 --- a/lib/include/srslte/phy/phch/uci_nr.h +++ b/lib/include/srslte/phy/phch/uci_nr.h @@ -75,4 +75,22 @@ SRSLTE_API int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q, const srslte_uci_value_nr_t* value, uint8_t* o); +/** + * @brief Decoder UCI bits + * + * @attention Compatible only with PUCCH formats 2, 3 and 4 + * + * @param[in,out] q NR-UCI object + * @param[in] pucch_resource_cfg + * @param[in] uci_cfg + * @param[in] llr + * @param[out] value + * @return SRSLTE_SUCCESSFUL if it is successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q, + const srslte_pucch_nr_resource_t* pucch_resource_cfg, + const srslte_uci_cfg_nr_t* uci_cfg, + const int8_t* llr, + srslte_uci_value_nr_t* value); + #endif // SRSLTE_UCI_NR_H diff --git a/lib/src/phy/phch/pucch_cfg_nr.c b/lib/src/phy/phch/pucch_cfg_nr.c index 174d11e48..bb58760a9 100644 --- a/lib/src/phy/phch/pucch_cfg_nr.c +++ b/lib/src/phy/phch/pucch_cfg_nr.c @@ -78,5 +78,34 @@ int srslte_pucch_nr_format1_resource_valid(const srslte_pucch_nr_resource_t* res return SRSLTE_ERROR; } + return SRSLTE_SUCCESS; +} + +int srslte_pucch_nr_format2_resource_valid(const srslte_pucch_nr_resource_t* resource) +{ + if (resource == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + if (resource->format != SRSLTE_PUCCH_NR_FORMAT_2) { + ERROR("Invalid format (%d)\n", resource->format); + return SRSLTE_ERROR; + } + + if (resource->nof_symbols < 1 || resource->nof_symbols > 2) { + ERROR("Invalid number of symbols (%d)\n", resource->nof_symbols); + return SRSLTE_ERROR; + } + + if (resource->nof_prb < 1 || resource->nof_prb > 16) { + ERROR("Invalid number of prb (%d)\n", resource->nof_prb); + return SRSLTE_ERROR; + } + + if (resource->start_symbol_idx > 13) { + ERROR("Invalid initial start symbol idx (%d)\n", resource->start_symbol_idx); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; } \ No newline at end of file diff --git a/lib/src/phy/phch/pucch_nr.c b/lib/src/phy/phch/pucch_nr.c index a77837d0e..2c0b8c189 100644 --- a/lib/src/phy/phch/pucch_nr.c +++ b/lib/src/phy/phch/pucch_nr.c @@ -14,11 +14,12 @@ #include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/common/sequence.h" #include "srslte/phy/common/zc_sequence.h" +#include "srslte/phy/mimo/precoding.h" +#include "srslte/phy/modem/demod_soft.h" #include "srslte/phy/modem/mod.h" #include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/vector.h" #include -#include int srslte_pucch_nr_group_sequence(const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, @@ -500,6 +501,25 @@ int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q, return SRSLTE_SUCCESS; } +static int pucch_nr_format2_encode(srslte_pucch_nr_t* q, + const srslte_carrier_nr_t* carrier, + const srslte_pucch_nr_common_cfg_t* cfg, + const srslte_dl_slot_cfg_t* slot, + const srslte_pucch_nr_resource_t* resource, + const srslte_uci_cfg_nr_t* uci_cfg, + cf_t* slot_symbols) +{ + // Validate configuration + if (srslte_pucch_nr_format2_resource_valid(resource) < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; + } + + // Implement encode here + // ... + + return SRSLTE_SUCCESS; +} + int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q, const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, @@ -509,20 +529,22 @@ int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q, const srslte_uci_value_nr_t* uci_value, cf_t* slot_symbols) { + // Validate input pointers if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || uci_cfg == NULL || uci_value == NULL || slot_symbols == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } + // Encode PUCCH message if (srslte_uci_nr_encode_pucch(&q->uci, resource, uci_cfg, uci_value, q->b) < SRSLTE_SUCCESS) { ERROR("Error encoding UCI\n"); return SRSLTE_ERROR; } - // Encode PUCCH + // Modulate PUCCH switch (resource->format) { case SRSLTE_PUCCH_NR_FORMAT_2: - break; + return pucch_nr_format2_encode(q, carrier, cfg, slot, resource, uci_cfg, slot_symbols); case SRSLTE_PUCCH_NR_FORMAT_3: case SRSLTE_PUCCH_NR_FORMAT_4: ERROR("Not implemented\n"); @@ -530,7 +552,65 @@ int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q, default: case SRSLTE_PUCCH_NR_FORMAT_ERROR: ERROR("Invalid format\n"); + } + + return SRSLTE_ERROR; +} + +static int pucch_nr_format2_decode(srslte_pucch_nr_t* q, + const srslte_carrier_nr_t* carrier, + const srslte_pucch_nr_common_cfg_t* cfg, + const srslte_dl_slot_cfg_t* slot, + const srslte_pucch_nr_resource_t* resource, + srslte_chest_ul_res_t* chest_res, + cf_t* slot_symbols, + int8_t* llr) +{ + // Validate configuration + if (srslte_pucch_nr_format2_resource_valid(resource) < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; + } + + // Implement decode here + // ... + + return SRSLTE_SUCCESS; +} + +int srslte_pucch_nr_format_2_3_4_decode(srslte_pucch_nr_t* q, + const srslte_carrier_nr_t* carrier, + const srslte_pucch_nr_common_cfg_t* cfg, + const srslte_dl_slot_cfg_t* slot, + const srslte_pucch_nr_resource_t* resource, + const srslte_uci_cfg_nr_t* uci_cfg, + srslte_chest_ul_res_t* chest_res, + cf_t* slot_symbols, + srslte_uci_value_nr_t* uci_value) +{ + // Validate input pointers + if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || uci_cfg == NULL || + chest_res == NULL || uci_value == NULL || slot_symbols == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + // Demodulate PUCCH message + int8_t* llr = (int8_t*)q->b; + switch (resource->format) { + case SRSLTE_PUCCH_NR_FORMAT_2: + return pucch_nr_format2_decode(q, carrier, cfg, slot, resource, chest_res, slot_symbols, llr); + case SRSLTE_PUCCH_NR_FORMAT_3: + case SRSLTE_PUCCH_NR_FORMAT_4: + ERROR("Not implemented\n"); return SRSLTE_ERROR; + default: + case SRSLTE_PUCCH_NR_FORMAT_ERROR: + ERROR("Invalid format\n"); + } + + // Decode PUCCH message + if (srslte_uci_nr_decode_pucch(&q->uci, resource, uci_cfg, llr, uci_value) < SRSLTE_SUCCESS) { + ERROR("Error encoding UCI\n"); + return SRSLTE_ERROR; } return SRSLTE_SUCCESS; diff --git a/lib/src/phy/phch/uci_nr.c b/lib/src/phy/phch/uci_nr.c index 84b56d136..c8838cd78 100644 --- a/lib/src/phy/phch/uci_nr.c +++ b/lib/src/phy/phch/uci_nr.c @@ -682,7 +682,6 @@ int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q, const srslte_uci_value_nr_t* value, uint8_t* o) { - int E_tot = uci_nr_pucch_E_tot(pucch_resource_cfg, uci_cfg); if (E_tot < SRSLTE_SUCCESS) { return SRSLTE_ERROR; @@ -702,7 +701,6 @@ int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q, const int8_t* llr, srslte_uci_value_nr_t* value) { - int E_tot = uci_nr_pucch_E_tot(pucch_resource_cfg, uci_cfg); if (E_tot < SRSLTE_SUCCESS) { return SRSLTE_ERROR;