mirror of https://github.com/PentHertz/srsLTE.git
SRSUE: Initial NR-PUCCH HARQ feedback
This commit is contained in:
parent
ff5fbbf0a0
commit
d807ccc3dd
|
@ -108,6 +108,11 @@ extern "C" {
|
|||
*/
|
||||
#define SRSLTE_MAX_NOF_DL_ALLOCATION 16
|
||||
|
||||
/**
|
||||
* @brief Maximum dl-DataToUL-ACK value. This is defined by TS 38.331 v15.10.1 in PUCCH-Config
|
||||
*/
|
||||
#define SRSLTE_MAX_NOF_DL_DATA_TO_UL 8
|
||||
|
||||
typedef enum SRSLTE_API {
|
||||
srslte_coreset_mapping_type_non_interleaved = 0,
|
||||
srslte_coreset_mapping_type_interleaved,
|
||||
|
@ -210,6 +215,15 @@ typedef enum SRSLTE_API {
|
|||
srslte_xoverhead_18
|
||||
} srslte_xoverhead_t;
|
||||
|
||||
/**
|
||||
* @brief PDSCH HARQ ACK codebook configuration
|
||||
* @remark Described in TS 38.331 V15.10.0 PhysicalCellGroupConfig
|
||||
*/
|
||||
typedef enum SRSLTE_API {
|
||||
srslte_pdsch_harq_ack_codebook_none = 0,
|
||||
srslte_pdsch_harq_ack_codebook_semi_static,
|
||||
srslte_pdsch_harq_ack_codebook_dynamic,
|
||||
} srslte_pdsch_harq_ack_codebook_t;
|
||||
/**
|
||||
* @brief NR carrier parameters. It is a combination of fixed cell and bandwidth-part (BWP)
|
||||
*/
|
||||
|
@ -281,6 +295,8 @@ typedef struct SRSLTE_API {
|
|||
uint32_t id;
|
||||
uint32_t coreset_id;
|
||||
uint32_t duration; // in slots
|
||||
uint32_t periodicity;
|
||||
uint32_t offset;
|
||||
srslte_search_space_type_t type;
|
||||
uint32_t nof_candidates[SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR];
|
||||
} srslte_search_space_t;
|
||||
|
|
|
@ -67,6 +67,21 @@
|
|||
*/
|
||||
#define SRSLTE_PUCCH_NR_MAX_CODE_RATE 7
|
||||
|
||||
/**
|
||||
* Maximum number of NR-PUCCH resources per set (TS 38.331 maxNrofPUCCH-ResourcesPerSet)
|
||||
*/
|
||||
#define SRSLTE_PUCCH_NR_MAX_NOF_RESOURCES_PER_SET 32
|
||||
|
||||
/**
|
||||
* Maximum number NR-PUCCH resource sets (TS 38.331 maxNrofPUCCH-ResourceSets)
|
||||
*/
|
||||
#define SRSLTE_PUCCH_NR_MAX_NOF_SETS 4
|
||||
|
||||
/**
|
||||
* Maximum numer of NR-PUCCH CS indexes (TS 38.213 Table 9.2.1-1: PUCCH resource sets...)
|
||||
*/
|
||||
#define SRSLTE_PUCCH_NR_MAX_NOF_CS_INDEXES 4
|
||||
|
||||
typedef enum SRSLTE_API {
|
||||
SRSLTE_PUCCH_NR_FORMAT_0 = 0,
|
||||
SRSLTE_PUCCH_NR_FORMAT_1,
|
||||
|
@ -126,6 +141,18 @@ typedef struct SRSLTE_API {
|
|||
bool additional_dmrs; ///< UE enables 2 DMRS symbols per hop of a PUCCH Format 3 or 4
|
||||
} srslte_pucch_nr_resource_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_pucch_nr_resource_t resources[SRSLTE_PUCCH_NR_MAX_NOF_RESOURCES_PER_SET];
|
||||
uint32_t nof_resources; ///< Set to 0 if it is NOT provided by higher layers
|
||||
uint32_t max_payload_size; ///< Maximum payload size, set to 0 if not present
|
||||
} srslte_pucch_nr_resource_set_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_pucch_nr_common_cfg_t common; ///< NR-PUCCH configuration common for all formats and resources
|
||||
srslte_pucch_nr_resource_set_t sets[SRSLTE_PUCCH_NR_MAX_NOF_SETS]; ///< Resource sets, indexed by pucch-ResourceSetId
|
||||
bool enabled; ///< Set to true if any set is enabled
|
||||
} srslte_pucch_nr_hl_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Validates an NR-PUCCH resource configuration provided by upper layers
|
||||
* @param resource Resource configuration to validate
|
||||
|
|
|
@ -241,4 +241,9 @@ SRSLTE_API int srslte_pucch_nr_format_2_3_4_decode(srslte_pucch_nr_t*
|
|||
cf_t* slot_symbols,
|
||||
srslte_uci_value_nr_t* uci_value);
|
||||
|
||||
SRSLTE_API uint32_t srslte_pucch_nr_tx_info(const srslte_pucch_nr_resource_t* resource,
|
||||
const srslte_uci_data_nr_t* uci_data,
|
||||
char* str,
|
||||
uint32_t str_len);
|
||||
|
||||
#endif // SRSLTE_PUCCH_NR_H
|
||||
|
|
|
@ -99,4 +99,15 @@ SRSLTE_API int srslte_ra_ul_nr_freq(const srslte_carrier_nr_t* carrier,
|
|||
const srslte_dci_ul_nr_t* dci_ul,
|
||||
srslte_sch_grant_nr_t* grant);
|
||||
|
||||
/**
|
||||
* @brief Selects a valid PUCCH resource for transmission
|
||||
* @param pucch_cfg PUCCH configuration from upper layers
|
||||
* @param uci_cfg Uplink Control information configuration (and PDCCH context)
|
||||
* @param[out] resource Selected resource for transmitting PUCCH
|
||||
* @return SRSLTE_SUCCESS if provided configuration is valid, SRSLTE_ERROR code otherwise
|
||||
*/
|
||||
SRSLTE_API int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
|
||||
const srslte_uci_cfg_nr_t* uci_cfg,
|
||||
srslte_pucch_nr_resource_t* resource);
|
||||
|
||||
#endif // SRSLTE_RA_UL_NR_H
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Maximum number of Uplink Control Bits
|
||||
* @remark TS 38.212 section 5.2.1 Polar coding: The value of A is no larger than 1706.
|
||||
*/
|
||||
#define SRSLTE_UCI_NR_MAX_NOF_BITS 1706U
|
||||
|
||||
/**
|
||||
* @brief Maximum number of HARQ ACK feedback bits that can be carried in Uplink Control Information (UCI) message
|
||||
*/
|
||||
|
@ -43,12 +49,15 @@
|
|||
* @brief Uplink Control Information (UCI) message configuration
|
||||
*/
|
||||
typedef struct SRSLTE_API {
|
||||
uint32_t o_ack; ///< Number of HARQ-ACK bits
|
||||
uint32_t o_sr; ///< Number of SR bits
|
||||
uint32_t o_csi1; ///< Number of CSI1 report number of bits
|
||||
uint32_t o_csi2; ///< Number of CSI2 report number of bits
|
||||
srslte_mod_t modulation; ///< Modulation (PUSCH only)
|
||||
uint16_t rnti; ///< RNTI
|
||||
uint32_t o_ack; ///< Number of HARQ-ACK bits
|
||||
uint32_t o_sr; ///< Number of SR bits
|
||||
uint32_t o_csi1; ///< Number of CSI1 report number of bits
|
||||
uint32_t o_csi2; ///< Number of CSI2 report number of bits
|
||||
srslte_mod_t modulation; ///< Modulation (PUSCH only)
|
||||
uint16_t rnti; ///< RNTI
|
||||
uint32_t pucch_resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1
|
||||
uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception
|
||||
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or DCI format 1_1
|
||||
} srslte_uci_cfg_nr_t;
|
||||
|
||||
/**
|
||||
|
@ -62,4 +71,12 @@ typedef struct SRSLTE_API {
|
|||
bool valid; ///< Indicates whether the message has been decoded successfully, ignored in the transmitter
|
||||
} srslte_uci_value_nr_t;
|
||||
|
||||
/**
|
||||
* @brief Uplink Control Information (UCI) data (configuration + values)
|
||||
*/
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_uci_cfg_nr_t cfg;
|
||||
srslte_uci_value_nr_t value;
|
||||
} srslte_uci_data_nr_t;
|
||||
|
||||
#endif // SRSLTE_UCI_CFG_NR_H
|
||||
|
|
|
@ -114,4 +114,15 @@ SRSLTE_API int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
|
|||
int8_t* llr,
|
||||
srslte_uci_value_nr_t* value);
|
||||
|
||||
SRSLTE_API uint32_t srslte_uci_nr_total_bits(const srslte_uci_cfg_nr_t* uci_cfg);
|
||||
|
||||
/**
|
||||
* @brief Converts to string an UCI data structure
|
||||
* @param uci_data UCO data structure
|
||||
* @param str Destination string
|
||||
* @param str_len String length
|
||||
* @return Resultant string length
|
||||
*/
|
||||
SRSLTE_API uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uint32_t str_len);
|
||||
|
||||
#endif // SRSLTE_UCI_NR_H
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "srslte/phy/phch/dci_nr.h"
|
||||
#include "srslte/phy/phch/pdcch_nr.h"
|
||||
#include "srslte/phy/phch/pdsch_nr.h"
|
||||
#include <srslte/phy/phch/uci_cfg_nr.h>
|
||||
|
||||
/**
|
||||
* Maximum number of CORESET
|
||||
|
@ -59,13 +60,16 @@ typedef struct SRSLTE_API {
|
|||
} srslte_ue_dl_nr_pdcch_cfg_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t v_dai_dl;
|
||||
bool dci_format_1_1;
|
||||
uint32_t scell_idx; ///< Serving cell index
|
||||
uint32_t v_dai_dl; ///< Downlink Assigment Index
|
||||
bool dci_format_1_1; ///< Set to true if the PDSCH transmission is triggered by a PDCCH DCI format 1_1 transmission
|
||||
uint32_t k1; ///< HARQ feedback timing
|
||||
uint16_t rnti;
|
||||
uint32_t pucch_resource_id;
|
||||
} srslte_pdsch_ack_resource_nr_t;
|
||||
|
||||
typedef struct {
|
||||
srslte_pdsch_ack_resource_nr_t resource;
|
||||
uint32_t k;
|
||||
uint8_t value[SRSLTE_MAX_CODEWORDS]; // 0/1 or 2 for DTX
|
||||
bool present; // set to true if there is a PDSCH on serving cell c associated with PDCCH in PDCCH monitoring occasion
|
||||
// m, or there is a PDCCH indicating SPS PDSCH release on serving cell c
|
||||
|
@ -89,10 +93,13 @@ typedef struct {
|
|||
} srslte_pdsch_ack_nr_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
bool harq_ack_spatial_bundling_pucch; ///< Param harq-ACK-SpatialBundlingPUCCH, set to true if provided
|
||||
bool harq_ack_spatial_bundling_pusch; ///< Param harq-ACK-SpatialBundlingPUSCH, set to true if provided
|
||||
bool pdsch_harq_ack_codebook_semi_static; ///< set to true for pdsch-HARQ-ACK-Codebook is set to semi-static
|
||||
bool harq_ack_spatial_bundling_pucch; ///< Param harq-ACK-SpatialBundlingPUCCH, set to true if provided
|
||||
bool harq_ack_spatial_bundling_pusch; ///< Param harq-ACK-SpatialBundlingPUSCH, set to true if provided
|
||||
srslte_pdsch_harq_ack_codebook_t pdsch_harq_ack_codebook; ///< pdsch-HARQ-ACK-Codebook configuration
|
||||
bool max_cw_sched_dci_is_2; ///< Param maxNrofCodeWordsScheduledByDCI, set to true if present and equal to 2
|
||||
|
||||
uint32_t dl_data_to_ul_ack[SRSLTE_MAX_NOF_DL_DATA_TO_UL];
|
||||
uint32_t nof_dl_data_to_ul_ack;
|
||||
} srslte_ue_dl_nr_harq_ack_cfg_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
|
@ -153,8 +160,12 @@ SRSLTE_API int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q,
|
|||
char* str,
|
||||
uint32_t str_len);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_nr_pdsch_ack_resource(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
|
||||
const srslte_dci_dl_nr_t* dci_dl,
|
||||
srslte_pdsch_ack_resource_nr_t* pdsch_ack_resource);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_nr_gen_ack(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
|
||||
const srslte_pdsch_ack_nr_t* ack_info,
|
||||
uint8_t* uci_data);
|
||||
srslte_uci_data_nr_t* uci_data);
|
||||
|
||||
#endif // SRSLTE_UE_DL_NR_H
|
||||
|
|
|
@ -27,10 +27,13 @@
|
|||
#include "srslte/phy/common/phy_common_nr.h"
|
||||
#include "srslte/phy/dft/ofdm.h"
|
||||
#include "srslte/phy/phch/phch_cfg_nr.h"
|
||||
#include "srslte/phy/phch/pucch_cfg_nr.h"
|
||||
#include "srslte/phy/phch/pucch_nr.h"
|
||||
#include "srslte/phy/phch/pusch_nr.h"
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_pusch_nr_args_t pusch;
|
||||
srslte_pucch_nr_args_t pucch;
|
||||
uint32_t nof_max_prb;
|
||||
} srslte_ue_ul_nr_args_t;
|
||||
|
||||
|
@ -43,8 +46,8 @@ typedef struct SRSLTE_API {
|
|||
|
||||
cf_t* sf_symbols[SRSLTE_MAX_PORTS];
|
||||
srslte_pusch_nr_t pusch;
|
||||
srslte_pucch_nr_t pucch;
|
||||
srslte_dmrs_sch_t dmrs;
|
||||
|
||||
} srslte_ue_ul_nr_t;
|
||||
|
||||
SRSLTE_API int srslte_ue_ul_nr_init(srslte_ue_ul_nr_t* q, cf_t* output, const srslte_ue_ul_nr_args_t* args);
|
||||
|
@ -56,9 +59,20 @@ SRSLTE_API int srslte_ue_ul_nr_encode_pusch(srslte_ue_ul_nr_t* q,
|
|||
const srslte_sch_cfg_nr_t* pusch_cfg,
|
||||
uint8_t* data_);
|
||||
|
||||
SRSLTE_API int srslte_ue_ul_nr_encode_pucch(srslte_ue_ul_nr_t* q,
|
||||
const srslte_slot_cfg_t* slot_cfg,
|
||||
const srslte_pucch_nr_common_cfg_t* cfg,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
const srslte_uci_data_nr_t* uci_data);
|
||||
|
||||
SRSLTE_API void srslte_ue_ul_nr_free(srslte_ue_ul_nr_t* q);
|
||||
|
||||
SRSLTE_API int
|
||||
srslte_ue_ul_nr_pusch_info(const srslte_ue_ul_nr_t* q, const srslte_sch_cfg_nr_t* cfg, char* str, uint32_t str_len);
|
||||
|
||||
SRSLTE_API int srslte_ue_ul_nr_pucch_info(const srslte_pucch_nr_resource_t* resource,
|
||||
const srslte_uci_data_nr_t* uci_data,
|
||||
char* str,
|
||||
uint32_t str_len);
|
||||
|
||||
#endif // SRSLTE_UE_UL_DATA_H
|
||||
|
|
|
@ -98,9 +98,11 @@ extern "C" {
|
|||
#include "srslte/phy/phch/ra_dl_nr.h"
|
||||
#include "srslte/phy/phch/ra_nr.h"
|
||||
#include "srslte/phy/phch/ra_ul.h"
|
||||
#include "srslte/phy/phch/ra_ul_nr.h"
|
||||
#include "srslte/phy/phch/regs.h"
|
||||
#include "srslte/phy/phch/sch.h"
|
||||
#include "srslte/phy/phch/uci.h"
|
||||
#include "srslte/phy/phch/uci_nr.h"
|
||||
|
||||
#include "srslte/phy/ue/ue_cell_search.h"
|
||||
#include "srslte/phy/ue/ue_dl.h"
|
||||
|
|
|
@ -707,4 +707,58 @@ int srslte_pucch_nr_format_2_3_4_decode(srslte_pucch_nr_t* q,
|
|||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pucch_nr_resource_info(const srslte_pucch_nr_resource_t* r, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
||||
uint32_t nof_prb = 1;
|
||||
if (r->format == SRSLTE_PUCCH_NR_FORMAT_2 || r->format == SRSLTE_PUCCH_NR_FORMAT_3) {
|
||||
nof_prb = r->nof_prb;
|
||||
}
|
||||
|
||||
len = srslte_print_check(str,
|
||||
str_len,
|
||||
len,
|
||||
"f=%d, prb=%d:%d, symb=%d:%d",
|
||||
(int)r->format,
|
||||
r->starting_prb,
|
||||
nof_prb,
|
||||
r->start_symbol_idx,
|
||||
r->nof_symbols);
|
||||
|
||||
if (r->intra_slot_hopping) {
|
||||
len = srslte_print_check(str, str_len, len, ", hop=%d", r->second_hop_prb);
|
||||
}
|
||||
|
||||
if (r->format == SRSLTE_PUCCH_NR_FORMAT_0 || r->format == SRSLTE_PUCCH_NR_FORMAT_1) {
|
||||
len = srslte_print_check(str, str_len, len, ", cs=%d", r->initial_cyclic_shift);
|
||||
}
|
||||
|
||||
if (r->format == SRSLTE_PUCCH_NR_FORMAT_1) {
|
||||
len = srslte_print_check(str, str_len, len, ", occ=%d", r->time_domain_occ);
|
||||
}
|
||||
|
||||
if (r->format == SRSLTE_PUCCH_NR_FORMAT_4) {
|
||||
len = srslte_print_check(str, str_len, len, ", occ=%d:%d", r->occ_index, r->occ_lenth);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint32_t srslte_pucch_nr_tx_info(const srslte_pucch_nr_resource_t* resource,
|
||||
const srslte_uci_data_nr_t* uci_data,
|
||||
char* str,
|
||||
uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
||||
len += pucch_nr_resource_info(resource, &str[len], str_len - len);
|
||||
|
||||
len = srslte_print_check(str, str_len, len, ", ");
|
||||
|
||||
len += srslte_uci_nr_info(uci_data, &str[len], str_len - len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -395,3 +395,69 @@ int srslte_ra_ul_nr_freq(const srslte_carrier_nr_t* carrier,
|
|||
ERROR("Only DCI Format 0_0 is supported");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Implements TS 38.213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration
|
||||
static int ra_ul_nr_pucch_resource_default(uint32_t r_pucch, srslte_pucch_nr_resource_t* resource)
|
||||
{
|
||||
ERROR("Not implemented");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
static int ra_ul_nr_pucch_resource_hl(const srslte_pucch_nr_hl_cfg_t* cfg,
|
||||
uint32_t O_uci,
|
||||
uint32_t pucch_resource_id,
|
||||
srslte_pucch_nr_resource_t* resource)
|
||||
{
|
||||
uint32_t N2 = cfg->sets[1].max_payload_size > 0 ? cfg->sets[1].max_payload_size : SRSLTE_UCI_NR_MAX_NOF_BITS;
|
||||
uint32_t N3 = cfg->sets[2].max_payload_size > 0 ? cfg->sets[2].max_payload_size : SRSLTE_UCI_NR_MAX_NOF_BITS;
|
||||
|
||||
// If the UE transmits O UCI UCI information bits, that include HARQ-ACK information bits, the UE determines a PUCCH
|
||||
// resource set to be...
|
||||
uint32_t resource_set_id = 3;
|
||||
if (O_uci <= 2 && cfg->sets[0].nof_resources > 0) {
|
||||
resource_set_id = 0;
|
||||
} else if (O_uci <= N2 && cfg->sets[1].nof_resources > 0) {
|
||||
resource_set_id = 1;
|
||||
} else if (O_uci <= N3 && cfg->sets[2].nof_resources > 0) {
|
||||
resource_set_id = 2;
|
||||
} else if (cfg->sets[3].nof_resources == 0) {
|
||||
ERROR("Invalid PUCCH resource configuration, N3=%d, O_uci=%d", N3, O_uci);
|
||||
return SRSLTE_ERROR;
|
||||
} else if (O_uci > SRSLTE_UCI_NR_MAX_NOF_BITS) {
|
||||
ERROR("The number of UCI bits (%d), exceeds the maximum (%d)", O_uci, SRSLTE_UCI_NR_MAX_NOF_BITS);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Select resource from the set
|
||||
if (pucch_resource_id >= SRSLTE_PUCCH_NR_MAX_NOF_RESOURCES_PER_SET ||
|
||||
pucch_resource_id >= cfg->sets[resource_set_id].nof_resources) {
|
||||
ERROR("The PUCCH resource identifier (%d) exceeds the number of configured resources (%d) for set identifier %d",
|
||||
pucch_resource_id,
|
||||
cfg->sets[resource_set_id].nof_resources,
|
||||
resource_set_id);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
*resource = cfg->sets[resource_set_id].resources[pucch_resource_id];
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
|
||||
const srslte_uci_cfg_nr_t* uci_cfg,
|
||||
srslte_pucch_nr_resource_t* resource)
|
||||
{
|
||||
if (pucch_cfg == NULL || uci_cfg == NULL) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
uint32_t O_uci = srslte_uci_nr_total_bits(uci_cfg);
|
||||
|
||||
// If a UE does not have dedicated PUCCH resource configuration, provided by PUCCH-ResourceSet in PUCCH-Config,
|
||||
// a PUCCH resource set is provided by pucch-ResourceCommon through an index to a row of Table 9.2.1-1 for size
|
||||
// transmission of HARQ-ACK information on PUCCH in an initial UL BWP of N BWP PRBs.
|
||||
if (!pucch_cfg->enabled) {
|
||||
uint32_t r_pucch = (2 * uci_cfg->n_cce_0) + 2 * uci_cfg->pucch_resource_id;
|
||||
return ra_ul_nr_pucch_resource_default(r_pucch, resource);
|
||||
}
|
||||
return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch_resource_id, resource);
|
||||
}
|
|
@ -706,10 +706,10 @@ int srslte_sch_nr_tb_info(const srslte_sch_tb_t* tb, char* str, uint32_t str_len
|
|||
len += srslte_print_check(str,
|
||||
str_len,
|
||||
len,
|
||||
"tb={mod=%s,Nl=%d,TBS=%d,R=%.3f,rv=%d,Nre=%d,Nbit=%d,cw=%d}",
|
||||
"tb={mod=%s,Nl=%d,tbs=%d,R=%.3f,rv=%d,Nre=%d,Nbit=%d,cw=%d}",
|
||||
srslte_mod_string(tb->mod),
|
||||
tb->N_L,
|
||||
tb->tbs,
|
||||
tb->tbs / 8,
|
||||
tb->R,
|
||||
tb->rv,
|
||||
tb->nof_re,
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#define UCI_NR_INFO_TX(...) INFO("UCI-NR Tx: " __VA_ARGS__)
|
||||
#define UCI_NR_INFO_RX(...) INFO("UCI-NR Rx: " __VA_ARGS__)
|
||||
|
||||
// TS 38.212 section 5.2.1 Polar coding: The value of A is no larger than 1706.
|
||||
#define UCI_NR_MAX_A 1706U
|
||||
#define UCI_NR_MAX_L 11U
|
||||
#define UCI_NR_POLAR_MAX 2048U
|
||||
#define UCI_NR_POLAR_RM_IBIL 0
|
||||
|
@ -84,14 +82,14 @@ int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args)
|
|||
}
|
||||
|
||||
// Allocate bit sequence with space for the CRC
|
||||
q->bit_sequence = srslte_vec_u8_malloc(UCI_NR_MAX_A);
|
||||
q->bit_sequence = srslte_vec_u8_malloc(SRSLTE_UCI_NR_MAX_NOF_BITS);
|
||||
if (q->bit_sequence == NULL) {
|
||||
ERROR("Error malloc");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Allocate c with space for a and the CRC
|
||||
q->c = srslte_vec_u8_malloc(UCI_NR_MAX_A + UCI_NR_MAX_L);
|
||||
q->c = srslte_vec_u8_malloc(SRSLTE_UCI_NR_MAX_NOF_BITS + UCI_NR_MAX_L);
|
||||
if (q->c == NULL) {
|
||||
ERROR("Error malloc");
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -656,7 +654,7 @@ static int uci_nr_encode(srslte_uci_nr_t* q,
|
|||
}
|
||||
|
||||
// Encoding of other sizes up to 1906
|
||||
if (A < UCI_NR_MAX_A) {
|
||||
if (A < SRSLTE_UCI_NR_MAX_NOF_BITS) {
|
||||
return uci_nr_encode_11_1706_bit(q, uci_cfg, A, o, E_uci);
|
||||
}
|
||||
|
||||
|
@ -689,7 +687,7 @@ static int uci_nr_decode(srslte_uci_nr_t* q,
|
|||
if (uci_nr_decode_3_11_bit(q, uci_cfg, A, llr, E_uci, &uci_value->valid) < SRSLTE_SUCCESS) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
} else if (A < UCI_NR_MAX_A) {
|
||||
} else if (A < SRSLTE_UCI_NR_MAX_NOF_BITS) {
|
||||
if (uci_nr_decode_11_1706_bit(q, uci_cfg, A, llr, E_uci, &uci_value->valid) < SRSLTE_SUCCESS) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
@ -785,3 +783,45 @@ int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
|
|||
|
||||
return uci_nr_decode(q, uci_cfg, llr, E_uci, value);
|
||||
}
|
||||
|
||||
uint32_t srslte_uci_nr_total_bits(const srslte_uci_cfg_nr_t* uci_cfg)
|
||||
{
|
||||
if (uci_cfg == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return uci_cfg->o_ack + uci_cfg->o_csi1 + uci_cfg->o_csi2 + uci_cfg->o_sr;
|
||||
}
|
||||
|
||||
uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
||||
len = srslte_print_check(str, str_len, len, "rnti=0x%x", uci_data->cfg.rnti);
|
||||
|
||||
if (uci_data->cfg.o_ack > 0) {
|
||||
char str2[10];
|
||||
srslte_vec_sprint_bin(str2, 10, uci_data->value.ack, uci_data->cfg.o_ack);
|
||||
len = srslte_print_check(str, str_len, len, ", ack=%s", str2);
|
||||
}
|
||||
|
||||
if (uci_data->cfg.o_csi1 > 0) {
|
||||
char str2[10];
|
||||
srslte_vec_sprint_bin(str2, 10, uci_data->value.csi1, uci_data->cfg.o_csi1);
|
||||
len = srslte_print_check(str, str_len, len, ", csi1=%s", str2);
|
||||
}
|
||||
|
||||
if (uci_data->cfg.o_csi2 > 0) {
|
||||
char str2[10];
|
||||
srslte_vec_sprint_bin(str2, 10, uci_data->value.csi2, uci_data->cfg.o_csi2);
|
||||
len = srslte_print_check(str, str_len, len, ", csi2=%s", str2);
|
||||
}
|
||||
|
||||
if (uci_data->cfg.o_sr > 0) {
|
||||
char str2[10];
|
||||
srslte_vec_sprint_bin(str2, 10, uci_data->value.sr, uci_data->cfg.o_sr);
|
||||
len = srslte_print_check(str, str_len, len, ", sr=%s", str2);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
|
@ -517,11 +517,13 @@ static uint32_t ue_dl_nr_V_DL_DAI(uint32_t dai)
|
|||
return dai + 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ue_dl_nr_gen_ack_type2(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg, const srslte_pdsch_ack_nr_t* ack_info, uint8_t* o_ack)
|
||||
static int ue_dl_nr_gen_ack_type2(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
|
||||
const srslte_pdsch_ack_nr_t* ack_info,
|
||||
srslte_uci_data_nr_t* uci_data)
|
||||
{
|
||||
bool harq_ack_spatial_bundling =
|
||||
ack_info->use_pusch ? cfg->harq_ack_spatial_bundling_pusch : cfg->harq_ack_spatial_bundling_pucch;
|
||||
uint8_t* o_ack = uci_data->value.ack;
|
||||
|
||||
uint32_t m = 0; // PDCCH with DCI format 1_0 or DCI format 1_1 monitoring occasion index: lower index corresponds to
|
||||
// earlier PDCCH with DCI format 1_0 or DCI format 1_1 monitoring occasion
|
||||
|
@ -529,11 +531,10 @@ ue_dl_nr_gen_ack_type2(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg, const srslte_p
|
|||
uint32_t V_temp = 0;
|
||||
uint32_t V_temp2 = 0;
|
||||
|
||||
uint32_t N_DL_cells = ack_info->nof_cc; // number of serving cells configured by higher layers for the UE
|
||||
uint32_t M = ack_info->cc[0].M; // Set M to the number of PDCCH monitoring occasion(s)
|
||||
uint32_t N_DL_cells = ack_info->nof_cc; // number of serving cells configured by higher layers for the UE
|
||||
|
||||
// The following code follows the exact pseudo-code provided in TS 38.213 9.1.3.1 Type-2 HARQ-ACK codebook ...
|
||||
while (m < M) {
|
||||
while (m < SRSLTE_UCI_NR_MAX_M) {
|
||||
uint32_t c = 0; // serving cell index: lower indexes correspond to lower RRC indexes of corresponding cell
|
||||
while (c < N_DL_cells) {
|
||||
// Get ACK information of serving cell c for the PDCH monitoring occasion m
|
||||
|
@ -563,6 +564,10 @@ ue_dl_nr_gen_ack_type2(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg, const srslte_p
|
|||
c = c + 1;
|
||||
} else {
|
||||
if (ack->present) {
|
||||
// Load ACK resource data into UCI info
|
||||
uci_data->cfg.pucch_resource_id = ack_info->cc[c].m[m].resource.pucch_resource_id;
|
||||
uci_data->cfg.rnti = ack_info->cc[c].m[m].resource.rnti;
|
||||
|
||||
if (V_DL_CDAI <= V_temp) {
|
||||
j = j + 1;
|
||||
}
|
||||
|
@ -605,20 +610,63 @@ ue_dl_nr_gen_ack_type2(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg, const srslte_p
|
|||
// if harq-ACK-SpatialBundlingPUCCH is not provided to the UE and the UE is configured by
|
||||
// maxNrofCodeWordsScheduledByDCI with reception of two transport blocks for at least one configured DL BWP of a
|
||||
// serving cell,
|
||||
uint32_t O_ack = 4 * j + V_temp2;
|
||||
if (!harq_ack_spatial_bundling && cfg->max_cw_sched_dci_is_2) {
|
||||
O_ack = 2 * (4 * j + V_temp2);
|
||||
uci_data->cfg.o_ack = 2 * (4 * j + V_temp2);
|
||||
} else {
|
||||
uci_data->cfg.o_ack = 4 * j + V_temp2;
|
||||
}
|
||||
|
||||
// Implement here SPS PDSCH reception
|
||||
// ...
|
||||
|
||||
return (int)O_ack;
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int ue_dl_nr_pdsch_k1(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg, const srslte_dci_dl_nr_t* dci_dl)
|
||||
{
|
||||
// For DCI format 1_0, the PDSCH-to-HARQ_feedback timing indicator field values map to {1, 2, 3, 4, 5, 6, 7, 8}
|
||||
if (dci_dl->format == srslte_dci_format_nr_1_0) {
|
||||
return (int)dci_dl->harq_feedback + 1;
|
||||
}
|
||||
|
||||
// For DCI format 1_1, if present, the PDSCH-to-HARQ_feedback timing indicator field values map to values for a set of
|
||||
// number of slots provided by dl-DataToUL-ACK as defined in Table 9.2.3-1.
|
||||
if (dci_dl->harq_feedback >= SRSLTE_MAX_NOF_DL_DATA_TO_UL || dci_dl->harq_feedback >= cfg->nof_dl_data_to_ul_ack) {
|
||||
ERROR("Out-of-range PDSCH-to-HARQ feedback index (%d, max %d)", dci_dl->harq_feedback, cfg->nof_dl_data_to_ul_ack);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
return cfg->dl_data_to_ul_ack[dci_dl->harq_feedback];
|
||||
}
|
||||
|
||||
int srslte_ue_dl_nr_pdsch_ack_resource(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
|
||||
const srslte_dci_dl_nr_t* dci_dl,
|
||||
srslte_pdsch_ack_resource_nr_t* pdsch_ack_resource)
|
||||
{
|
||||
if (cfg == NULL || dci_dl == NULL || pdsch_ack_resource == NULL) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Calculate Data to UL ACK timing k1
|
||||
int k1 = ue_dl_nr_pdsch_k1(cfg, dci_dl);
|
||||
if (k1 < SRSLTE_ERROR) {
|
||||
ERROR("Error calculating K1");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Fill PDSCH resource
|
||||
pdsch_ack_resource->dci_format_1_1 = (dci_dl->format == srslte_dci_format_nr_1_1);
|
||||
pdsch_ack_resource->k1 = k1;
|
||||
pdsch_ack_resource->v_dai_dl = dci_dl->dai;
|
||||
pdsch_ack_resource->rnti = dci_dl->rnti;
|
||||
pdsch_ack_resource->pucch_resource_id = dci_dl->pucch_resource;
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_ue_dl_nr_gen_ack(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
|
||||
const srslte_pdsch_ack_nr_t* ack_info,
|
||||
uint8_t* uci_data)
|
||||
srslte_uci_data_nr_t* uci_data)
|
||||
{
|
||||
// Check inputs
|
||||
if (cfg == NULL || ack_info == NULL || uci_data == NULL) {
|
||||
|
@ -626,7 +674,7 @@ int srslte_ue_dl_nr_gen_ack(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
|
|||
}
|
||||
|
||||
// According TS 38.213 9.1.2 Type-1 HARQ-ACK codebook determination
|
||||
if (cfg->pdsch_harq_ack_codebook_semi_static) {
|
||||
if (cfg->pdsch_harq_ack_codebook == srslte_pdsch_harq_ack_codebook_semi_static) {
|
||||
// This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = semi-static.
|
||||
ERROR("Type-1 HARQ-ACK codebook determination is NOT implemented");
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -634,5 +682,10 @@ int srslte_ue_dl_nr_gen_ack(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
|
|||
|
||||
// According TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination
|
||||
// This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = dynamic.
|
||||
return ue_dl_nr_gen_ack_type2(cfg, ack_info, uci_data);
|
||||
if (cfg->pdsch_harq_ack_codebook == srslte_pdsch_harq_ack_codebook_dynamic) {
|
||||
return ue_dl_nr_gen_ack_type2(cfg, ack_info, uci_data);
|
||||
}
|
||||
|
||||
ERROR("No HARQ-ACK codebook determination is NOT implemented");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,11 @@ int srslte_ue_ul_nr_init(srslte_ue_ul_nr_t* q, cf_t* output, const srslte_ue_ul_
|
|||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_pucch_nr_init(&q->pucch, &args->pucch) < SRSLTE_SUCCESS) {
|
||||
ERROR("Error UCI\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -126,6 +131,58 @@ int srslte_ue_ul_nr_encode_pusch(srslte_ue_ul_nr_t* q,
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
static int ue_ul_nr_encode_pucch_format0(srslte_ue_ul_nr_t* q,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
const srslte_uci_data_nr_t* uci_data)
|
||||
{
|
||||
ERROR("Not implemented");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
static int ue_ul_nr_encode_pucch_format1(srslte_ue_ul_nr_t* q,
|
||||
const srslte_slot_cfg_t* slot,
|
||||
const srslte_pucch_nr_common_cfg_t* cfg,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
const srslte_uci_data_nr_t* uci_data)
|
||||
{
|
||||
uint8_t b[SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS] = {};
|
||||
b[0] = uci_data->value.ack[0];
|
||||
uint32_t nof_bits = 1;
|
||||
|
||||
return srslte_pucch_nr_format1_encode(&q->pucch, &q->carrier, cfg, slot, resource, b, nof_bits, q->sf_symbols[0]);
|
||||
}
|
||||
|
||||
int srslte_ue_ul_nr_encode_pucch(srslte_ue_ul_nr_t* q,
|
||||
const srslte_slot_cfg_t* slot_cfg,
|
||||
const srslte_pucch_nr_common_cfg_t* cfg,
|
||||
const srslte_pucch_nr_resource_t* resource,
|
||||
const srslte_uci_data_nr_t* uci_data)
|
||||
{
|
||||
// Check inputs
|
||||
if (q == NULL || slot_cfg == NULL || resource == NULL || uci_data == NULL) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Actual PUCCH encoding
|
||||
switch (resource->format) {
|
||||
case SRSLTE_PUCCH_NR_FORMAT_0:
|
||||
return ue_ul_nr_encode_pucch_format0(q, resource, uci_data);
|
||||
case SRSLTE_PUCCH_NR_FORMAT_1:
|
||||
return ue_ul_nr_encode_pucch_format1(q, slot_cfg, cfg, resource, uci_data);
|
||||
case SRSLTE_PUCCH_NR_FORMAT_2:
|
||||
case SRSLTE_PUCCH_NR_FORMAT_3:
|
||||
case SRSLTE_PUCCH_NR_FORMAT_4:
|
||||
return srslte_pucch_nr_format_2_3_4_encode(
|
||||
&q->pucch, &q->carrier, cfg, slot_cfg, resource, &uci_data->cfg, &uci_data->value, q->sf_symbols[0]);
|
||||
case SRSLTE_PUCCH_NR_FORMAT_ERROR:
|
||||
default:
|
||||
ERROR("Invalid case");
|
||||
break;
|
||||
}
|
||||
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
void srslte_ue_ul_nr_free(srslte_ue_ul_nr_t* q)
|
||||
{
|
||||
if (q == NULL) {
|
||||
|
@ -137,6 +194,8 @@ void srslte_ue_ul_nr_free(srslte_ue_ul_nr_t* q)
|
|||
}
|
||||
srslte_pusch_nr_free(&q->pusch);
|
||||
srslte_dmrs_sch_free(&q->dmrs);
|
||||
|
||||
SRSLTE_MEM_ZERO(q, srslte_ue_ul_nr_t, 1);
|
||||
}
|
||||
|
||||
int srslte_ue_ul_nr_pusch_info(const srslte_ue_ul_nr_t* q, const srslte_sch_cfg_nr_t* cfg, char* str, uint32_t str_len)
|
||||
|
@ -146,5 +205,18 @@ int srslte_ue_ul_nr_pusch_info(const srslte_ue_ul_nr_t* q, const srslte_sch_cfg_
|
|||
// Append PDSCH info
|
||||
len += srslte_pusch_nr_tx_info(&q->pusch, cfg, &cfg->grant, &str[len], str_len - len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int srslte_ue_ul_nr_pucch_info(const srslte_pucch_nr_resource_t* resource,
|
||||
const srslte_uci_data_nr_t* uci_data,
|
||||
char* str,
|
||||
uint32_t str_len)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
// Append PDSCH info
|
||||
len += srslte_pucch_nr_tx_info(resource, uci_data, &str[len], str_len - len);
|
||||
|
||||
return len;
|
||||
}
|
|
@ -54,6 +54,10 @@ private:
|
|||
srslte_softbuffer_tx_t softbuffer_tx = {};
|
||||
srslte_softbuffer_rx_t softbuffer_rx = {};
|
||||
std::vector<uint8_t> tx_data;
|
||||
|
||||
// Methods for DL...
|
||||
void decode_pdcch_ul();
|
||||
void decode_pdcch_dl();
|
||||
};
|
||||
|
||||
} // namespace nr
|
||||
|
|
|
@ -33,6 +33,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
srslte_sch_hl_cfg_nr_t pdsch;
|
||||
srslte_sch_hl_cfg_nr_t pusch;
|
||||
srslte_pucch_nr_hl_cfg_t pucch;
|
||||
srslte_prach_cfg_t prach;
|
||||
srslte_ue_dl_nr_pdcch_cfg_t pdcch;
|
||||
srslte_ue_dl_nr_harq_ack_cfg_t harq_ack;
|
||||
|
@ -41,13 +42,25 @@ typedef struct {
|
|||
class state
|
||||
{
|
||||
private:
|
||||
struct pending_grant_t {
|
||||
struct pending_ul_grant_t {
|
||||
bool enable;
|
||||
uint32_t pid;
|
||||
srslte_sch_cfg_nr_t sch_cfg;
|
||||
};
|
||||
srslte::circular_array<pending_grant_t, TTIMOD_SZ> pending_ul_grant = {};
|
||||
mutable std::mutex pending_ul_grant_mutex;
|
||||
srslte::circular_array<pending_ul_grant_t, TTIMOD_SZ> pending_ul_grant = {};
|
||||
mutable std::mutex pending_ul_grant_mutex;
|
||||
|
||||
struct pending_dl_grant_t {
|
||||
bool enable;
|
||||
uint32_t pid;
|
||||
srslte_sch_cfg_nr_t sch_cfg;
|
||||
srslte_pdsch_ack_resource_nr_t ack_resource;
|
||||
};
|
||||
srslte::circular_array<pending_dl_grant_t, TTIMOD_SZ> pending_dl_grant = {};
|
||||
mutable std::mutex pending_dl_grant_mutex;
|
||||
|
||||
srslte::circular_array<srslte_pdsch_ack_nr_t, TTIMOD_SZ> pending_ack = {};
|
||||
mutable std::mutex pending_ack_mutex;
|
||||
|
||||
public:
|
||||
mac_interface_phy_nr* stack = nullptr;
|
||||
|
@ -87,7 +100,7 @@ public:
|
|||
|
||||
// physicalCellGroupConfig
|
||||
// pdsch-HARQ-ACK-Codebook: dynamic (1)
|
||||
cfg.harq_ack.pdsch_harq_ack_codebook_semi_static = false;
|
||||
cfg.harq_ack.pdsch_harq_ack_codebook = srslte_pdsch_harq_ack_codebook_dynamic;
|
||||
|
||||
// commonControlResourceSet
|
||||
// controlResourceSetId: 1
|
||||
|
@ -222,6 +235,377 @@ public:
|
|||
// betaOffsetCSI-Part2-Index1: 6
|
||||
// betaOffsetCSI-Part2-Index2: 6
|
||||
// scaling: f1 (3)
|
||||
|
||||
// pucch-Config: setup (1)
|
||||
// setup
|
||||
// resourceSetToAddModList: 2 items
|
||||
cfg.pucch.enabled = true;
|
||||
// Item 0
|
||||
// PUCCH-ResourceSet
|
||||
// pucch-ResourceSetId: 0
|
||||
// resourceList: 8 items
|
||||
// Item 0
|
||||
// PUCCH-ResourceId: 0
|
||||
// Item 1
|
||||
// PUCCH-ResourceId: 1
|
||||
// Item 2
|
||||
// PUCCH-ResourceId: 2
|
||||
// Item 3
|
||||
// PUCCH-ResourceId: 3
|
||||
// Item 4
|
||||
// PUCCH-ResourceId: 4
|
||||
// Item 5
|
||||
// PUCCH-ResourceId: 5
|
||||
// Item 6
|
||||
// PUCCH-ResourceId: 6
|
||||
// Item 7
|
||||
// PUCCH-ResourceId: 7
|
||||
cfg.pucch.sets[0].nof_resources = 8;
|
||||
|
||||
// Item 1
|
||||
// PUCCH-ResourceSet
|
||||
// pucch-ResourceSetId: 1
|
||||
// resourceList: 8 items
|
||||
// Item 0
|
||||
// PUCCH-ResourceId: 8
|
||||
// Item 1
|
||||
// PUCCH-ResourceId: 9
|
||||
// Item 2
|
||||
// PUCCH-ResourceId: 10
|
||||
// Item 3
|
||||
// PUCCH-ResourceId: 11
|
||||
// Item 4
|
||||
// PUCCH-ResourceId: 12
|
||||
// Item 5
|
||||
// PUCCH-ResourceId: 13
|
||||
// Item 6
|
||||
// PUCCH-ResourceId: 14
|
||||
// Item 7
|
||||
// PUCCH-ResourceId: 15
|
||||
cfg.pucch.sets[1].nof_resources = 8;
|
||||
|
||||
// resourceToAddModList: 18 items
|
||||
// Item 0
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 0
|
||||
// startingPRB: 0
|
||||
// format: format1 (1)
|
||||
// format1
|
||||
// initialCyclicShift: 0
|
||||
// nrofSymbols: 14
|
||||
// startingSymbolIndex: 0
|
||||
// timeDomainOCC: 0
|
||||
cfg.pucch.sets[0].resources[0].format = SRSLTE_PUCCH_NR_FORMAT_1;
|
||||
cfg.pucch.sets[0].resources[0].starting_prb = 0;
|
||||
cfg.pucch.sets[0].resources[0].initial_cyclic_shift = 0;
|
||||
cfg.pucch.sets[0].resources[0].nof_symbols = 14;
|
||||
cfg.pucch.sets[0].resources[0].start_symbol_idx = 0;
|
||||
cfg.pucch.sets[0].resources[0].time_domain_occ = 0;
|
||||
|
||||
// Item 1
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 1
|
||||
// startingPRB: 0
|
||||
// format: format1 (1)
|
||||
// format1
|
||||
// initialCyclicShift: 4
|
||||
// nrofSymbols: 14
|
||||
// startingSymbolIndex: 0
|
||||
// timeDomainOCC: 0
|
||||
cfg.pucch.sets[0].resources[1].format = SRSLTE_PUCCH_NR_FORMAT_1;
|
||||
cfg.pucch.sets[0].resources[1].starting_prb = 0;
|
||||
cfg.pucch.sets[0].resources[1].initial_cyclic_shift = 4;
|
||||
cfg.pucch.sets[0].resources[1].nof_symbols = 14;
|
||||
cfg.pucch.sets[0].resources[1].start_symbol_idx = 0;
|
||||
cfg.pucch.sets[0].resources[1].time_domain_occ = 0;
|
||||
|
||||
// Item 2
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 2
|
||||
// startingPRB: 0
|
||||
// format: format1 (1)
|
||||
// format1
|
||||
// initialCyclicShift: 8
|
||||
// nrofSymbols: 14
|
||||
// startingSymbolIndex: 0
|
||||
// timeDomainOCC: 0
|
||||
cfg.pucch.sets[0].resources[2].format = SRSLTE_PUCCH_NR_FORMAT_1;
|
||||
cfg.pucch.sets[0].resources[2].starting_prb = 0;
|
||||
cfg.pucch.sets[0].resources[2].initial_cyclic_shift = 8;
|
||||
cfg.pucch.sets[0].resources[2].nof_symbols = 14;
|
||||
cfg.pucch.sets[0].resources[2].start_symbol_idx = 0;
|
||||
cfg.pucch.sets[0].resources[2].time_domain_occ = 0;
|
||||
|
||||
// Item 3
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 3
|
||||
// startingPRB: 0
|
||||
// format: format1 (1)
|
||||
// format1
|
||||
// initialCyclicShift: 0
|
||||
// nrofSymbols: 14
|
||||
// startingSymbolIndex: 0
|
||||
// timeDomainOCC: 1
|
||||
cfg.pucch.sets[0].resources[3].format = SRSLTE_PUCCH_NR_FORMAT_1;
|
||||
cfg.pucch.sets[0].resources[3].starting_prb = 0;
|
||||
cfg.pucch.sets[0].resources[3].initial_cyclic_shift = 0;
|
||||
cfg.pucch.sets[0].resources[3].nof_symbols = 14;
|
||||
cfg.pucch.sets[0].resources[3].start_symbol_idx = 0;
|
||||
cfg.pucch.sets[0].resources[3].time_domain_occ = 1;
|
||||
|
||||
// Item 4
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 4
|
||||
// startingPRB: 0
|
||||
// format: format1 (1)
|
||||
// format1
|
||||
// initialCyclicShift: 4
|
||||
// nrofSymbols: 14
|
||||
// startingSymbolIndex: 0
|
||||
// timeDomainOCC: 1
|
||||
cfg.pucch.sets[0].resources[4].format = SRSLTE_PUCCH_NR_FORMAT_1;
|
||||
cfg.pucch.sets[0].resources[4].starting_prb = 0;
|
||||
cfg.pucch.sets[0].resources[4].initial_cyclic_shift = 4;
|
||||
cfg.pucch.sets[0].resources[4].nof_symbols = 14;
|
||||
cfg.pucch.sets[0].resources[4].start_symbol_idx = 0;
|
||||
cfg.pucch.sets[0].resources[4].time_domain_occ = 1;
|
||||
|
||||
// Item 5
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 5
|
||||
// startingPRB: 0
|
||||
// format: format1 (1)
|
||||
// format1
|
||||
// initialCyclicShift: 8
|
||||
// nrofSymbols: 14
|
||||
// startingSymbolIndex: 0
|
||||
// timeDomainOCC: 1
|
||||
cfg.pucch.sets[0].resources[5].format = SRSLTE_PUCCH_NR_FORMAT_1;
|
||||
cfg.pucch.sets[0].resources[5].starting_prb = 0;
|
||||
cfg.pucch.sets[0].resources[5].initial_cyclic_shift = 8;
|
||||
cfg.pucch.sets[0].resources[5].nof_symbols = 14;
|
||||
cfg.pucch.sets[0].resources[5].start_symbol_idx = 0;
|
||||
cfg.pucch.sets[0].resources[5].time_domain_occ = 1;
|
||||
|
||||
// Item 6
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 6
|
||||
// startingPRB: 0
|
||||
// format: format1 (1)
|
||||
// format1
|
||||
// initialCyclicShift: 0
|
||||
// nrofSymbols: 14
|
||||
// startingSymbolIndex: 0
|
||||
// timeDomainOCC: 2
|
||||
cfg.pucch.sets[0].resources[6].format = SRSLTE_PUCCH_NR_FORMAT_1;
|
||||
cfg.pucch.sets[0].resources[6].starting_prb = 0;
|
||||
cfg.pucch.sets[0].resources[6].initial_cyclic_shift = 0;
|
||||
cfg.pucch.sets[0].resources[6].nof_symbols = 14;
|
||||
cfg.pucch.sets[0].resources[6].start_symbol_idx = 0;
|
||||
cfg.pucch.sets[0].resources[6].time_domain_occ = 2;
|
||||
|
||||
// Item 7
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 7
|
||||
// startingPRB: 0
|
||||
// format: format1 (1)
|
||||
// format1
|
||||
// initialCyclicShift: 4
|
||||
// nrofSymbols: 14
|
||||
// startingSymbolIndex: 0
|
||||
// timeDomainOCC: 2
|
||||
cfg.pucch.sets[0].resources[7].format = SRSLTE_PUCCH_NR_FORMAT_1;
|
||||
cfg.pucch.sets[0].resources[7].starting_prb = 0;
|
||||
cfg.pucch.sets[0].resources[7].initial_cyclic_shift = 0;
|
||||
cfg.pucch.sets[0].resources[7].nof_symbols = 14;
|
||||
cfg.pucch.sets[0].resources[7].start_symbol_idx = 0;
|
||||
cfg.pucch.sets[0].resources[7].time_domain_occ = 2;
|
||||
|
||||
// Item 8
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 8
|
||||
// startingPRB: 51
|
||||
// format: format2 (2)
|
||||
// format2
|
||||
// nrofPRBs: 1
|
||||
// nrofSymbols: 2
|
||||
// startingSymbolIndex: 0
|
||||
cfg.pucch.sets[1].resources[0].format = SRSLTE_PUCCH_NR_FORMAT_2;
|
||||
cfg.pucch.sets[1].resources[0].starting_prb = 51;
|
||||
cfg.pucch.sets[1].resources[0].nof_prb = 1;
|
||||
cfg.pucch.sets[1].resources[0].nof_symbols = 2;
|
||||
cfg.pucch.sets[1].resources[0].start_symbol_idx = 0;
|
||||
|
||||
// Item 9
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 9
|
||||
// startingPRB: 51
|
||||
// format: format2 (2)
|
||||
// format2
|
||||
// nrofPRBs: 1
|
||||
// nrofSymbols: 2
|
||||
// startingSymbolIndex: 2
|
||||
cfg.pucch.sets[1].resources[1].format = SRSLTE_PUCCH_NR_FORMAT_2;
|
||||
cfg.pucch.sets[1].resources[1].starting_prb = 51;
|
||||
cfg.pucch.sets[1].resources[1].nof_prb = 1;
|
||||
cfg.pucch.sets[1].resources[1].nof_symbols = 2;
|
||||
cfg.pucch.sets[1].resources[1].start_symbol_idx = 2;
|
||||
|
||||
// Item 10
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 10
|
||||
// startingPRB: 51
|
||||
// format: format2 (2)
|
||||
// format2
|
||||
// nrofPRBs: 1
|
||||
// nrofSymbols: 2
|
||||
// startingSymbolIndex: 4
|
||||
cfg.pucch.sets[1].resources[2].format = SRSLTE_PUCCH_NR_FORMAT_2;
|
||||
cfg.pucch.sets[1].resources[2].starting_prb = 51;
|
||||
cfg.pucch.sets[1].resources[2].nof_prb = 1;
|
||||
cfg.pucch.sets[1].resources[2].nof_symbols = 2;
|
||||
cfg.pucch.sets[1].resources[2].start_symbol_idx = 4;
|
||||
|
||||
// Item 11
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 11
|
||||
// startingPRB: 51
|
||||
// format: format2 (2)
|
||||
// format2
|
||||
// nrofPRBs: 1
|
||||
// nrofSymbols: 2
|
||||
// startingSymbolIndex: 6
|
||||
cfg.pucch.sets[1].resources[3].format = SRSLTE_PUCCH_NR_FORMAT_2;
|
||||
cfg.pucch.sets[1].resources[3].starting_prb = 51;
|
||||
cfg.pucch.sets[1].resources[3].nof_prb = 1;
|
||||
cfg.pucch.sets[1].resources[3].nof_symbols = 2;
|
||||
cfg.pucch.sets[1].resources[3].start_symbol_idx = 6;
|
||||
|
||||
// Item 12
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 12
|
||||
// startingPRB: 51
|
||||
// format: format2 (2)
|
||||
// format2
|
||||
// nrofPRBs: 1
|
||||
// nrofSymbols: 2
|
||||
// startingSymbolIndex: 8
|
||||
cfg.pucch.sets[1].resources[4].format = SRSLTE_PUCCH_NR_FORMAT_2;
|
||||
cfg.pucch.sets[1].resources[4].starting_prb = 51;
|
||||
cfg.pucch.sets[1].resources[4].nof_prb = 1;
|
||||
cfg.pucch.sets[1].resources[4].nof_symbols = 2;
|
||||
cfg.pucch.sets[1].resources[4].start_symbol_idx = 8;
|
||||
|
||||
// Item 13
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 13
|
||||
// startingPRB: 51
|
||||
// format: format2 (2)
|
||||
// format2
|
||||
// nrofPRBs: 1
|
||||
// nrofSymbols: 2
|
||||
// startingSymbolIndex: 10
|
||||
cfg.pucch.sets[1].resources[5].format = SRSLTE_PUCCH_NR_FORMAT_2;
|
||||
cfg.pucch.sets[1].resources[5].starting_prb = 51;
|
||||
cfg.pucch.sets[1].resources[5].nof_prb = 1;
|
||||
cfg.pucch.sets[1].resources[5].nof_symbols = 2;
|
||||
cfg.pucch.sets[1].resources[5].start_symbol_idx = 10;
|
||||
|
||||
// Item 14
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 14
|
||||
// startingPRB: 51
|
||||
// format: format2 (2)
|
||||
// format2
|
||||
// nrofPRBs: 1
|
||||
// nrofSymbols: 2
|
||||
// startingSymbolIndex: 12
|
||||
cfg.pucch.sets[1].resources[6].format = SRSLTE_PUCCH_NR_FORMAT_2;
|
||||
cfg.pucch.sets[1].resources[6].starting_prb = 51;
|
||||
cfg.pucch.sets[1].resources[6].nof_prb = 1;
|
||||
cfg.pucch.sets[1].resources[6].nof_symbols = 2;
|
||||
cfg.pucch.sets[1].resources[6].start_symbol_idx = 12;
|
||||
|
||||
// Item 15
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 15
|
||||
// startingPRB: 1
|
||||
// format: format2 (2)
|
||||
// format2
|
||||
// nrofPRBs: 1
|
||||
// nrofSymbols: 2
|
||||
// startingSymbolIndex: 0
|
||||
cfg.pucch.sets[1].resources[7].format = SRSLTE_PUCCH_NR_FORMAT_2;
|
||||
cfg.pucch.sets[1].resources[7].starting_prb = 51;
|
||||
cfg.pucch.sets[1].resources[7].nof_prb = 1;
|
||||
cfg.pucch.sets[1].resources[7].nof_symbols = 2;
|
||||
cfg.pucch.sets[1].resources[7].start_symbol_idx = 2;
|
||||
|
||||
// Item 16
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 16
|
||||
// startingPRB: 0
|
||||
// format: format1 (1)
|
||||
// format1
|
||||
// initialCyclicShift: 8
|
||||
// nrofSymbols: 14
|
||||
// startingSymbolIndex: 0
|
||||
// timeDomainOCC: 2
|
||||
// Item 17
|
||||
// PUCCH-Resource
|
||||
// pucch-ResourceId: 17
|
||||
// startingPRB: 1
|
||||
// format: format2 (2)
|
||||
// format2
|
||||
// nrofPRBs: 1
|
||||
// nrofSymbols: 2
|
||||
// startingSymbolIndex: 2
|
||||
// format1: setup (1)
|
||||
// setup
|
||||
// format2: setup (1)
|
||||
// setup
|
||||
// maxCodeRate: zeroDot25 (2)
|
||||
for (uint32_t i = 0; i < SRSLTE_PUCCH_NR_MAX_NOF_SETS; i++) {
|
||||
srslte_pucch_nr_resource_set_t* set = &cfg.pucch.sets[i];
|
||||
for (uint32_t j = 0; j < set->nof_resources; j++) {
|
||||
if (set->resources[j].format == SRSLTE_PUCCH_NR_FORMAT_2) {
|
||||
set->resources[j].max_code_rate = 2; // 0.25
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// schedulingRequestResourceToAddModList: 1 item
|
||||
// Item 0
|
||||
// SchedulingRequestResourceConfig
|
||||
// schedulingRequestResourceId: 1
|
||||
// schedulingRequestID: 0
|
||||
// periodicityAndOffset: sl40 (10)
|
||||
// sl40: 8
|
||||
// resource: 16
|
||||
|
||||
// dl-DataToUL-ACK: 7 items
|
||||
// Item 0
|
||||
// dl-DataToUL-ACK item: 8
|
||||
// Item 1
|
||||
// dl-DataToUL-ACK item: 7
|
||||
// Item 2
|
||||
// dl-DataToUL-ACK item: 6
|
||||
// Item 3
|
||||
// dl-DataToUL-ACK item: 5
|
||||
// Item 4
|
||||
// dl-DataToUL-ACK item: 4
|
||||
// Item 5
|
||||
// dl-DataToUL-ACK item: 12
|
||||
// Item 6
|
||||
// dl-DataToUL-ACK item: 11
|
||||
cfg.harq_ack.dl_data_to_ul_ack[0] = 8;
|
||||
cfg.harq_ack.dl_data_to_ul_ack[1] = 7;
|
||||
cfg.harq_ack.dl_data_to_ul_ack[2] = 6;
|
||||
cfg.harq_ack.dl_data_to_ul_ack[3] = 5;
|
||||
cfg.harq_ack.dl_data_to_ul_ack[4] = 4;
|
||||
cfg.harq_ack.dl_data_to_ul_ack[5] = 12;
|
||||
cfg.harq_ack.dl_data_to_ul_ack[6] = 11;
|
||||
cfg.harq_ack.nof_dl_data_to_ul_ack = 7;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,10 +629,10 @@ public:
|
|||
std::lock_guard<std::mutex> lock(pending_ul_grant_mutex);
|
||||
|
||||
// Save entry
|
||||
pending_grant_t& pending_grant = pending_ul_grant[tti_tx];
|
||||
pending_grant.sch_cfg = pusch_cfg;
|
||||
pending_grant.pid = dci_ul.pid;
|
||||
pending_grant.enable = true;
|
||||
pending_ul_grant_t& pending_grant = pending_ul_grant[tti_tx];
|
||||
pending_grant.sch_cfg = pusch_cfg;
|
||||
pending_grant.pid = dci_ul.pid;
|
||||
pending_grant.enable = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,7 +648,7 @@ public:
|
|||
std::lock_guard<std::mutex> lock(pending_ul_grant_mutex);
|
||||
|
||||
// Select entry
|
||||
pending_grant_t& pending_grant = pending_ul_grant[tti_tx];
|
||||
pending_ul_grant_t& pending_grant = pending_ul_grant[tti_tx];
|
||||
|
||||
// If the entry is not active, just return
|
||||
if (!pending_grant.enable) {
|
||||
|
@ -279,6 +663,126 @@ public:
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stores a received DL DCI into the pending DL grant list
|
||||
* @param tti_rx The TTI in which the grant was received
|
||||
* @param dci_dl The DL DCI message to store
|
||||
*/
|
||||
void set_dl_pending_grant(uint32_t tti_rx, const srslte_dci_dl_nr_t& dci_dl)
|
||||
{
|
||||
// Convert DL DCI to grant
|
||||
srslte_sch_cfg_nr_t pdsch_cfg = {};
|
||||
if (srslte_ra_dl_dci_to_grant_nr(&carrier, &cfg.pdsch, &dci_dl, &pdsch_cfg, &pdsch_cfg.grant)) {
|
||||
ERROR("Computing UL grant");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate DL DCI to PDSCH ACK resource
|
||||
srslte_pdsch_ack_resource_nr_t ack_resource = {};
|
||||
if (srslte_ue_dl_nr_pdsch_ack_resource(&cfg.harq_ack, &dci_dl, &ack_resource) < SRSLTE_SUCCESS) {
|
||||
ERROR("Computing UL ACK resource");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate Receive TTI
|
||||
tti_rx = TTI_ADD(tti_rx, pdsch_cfg.grant.k);
|
||||
|
||||
// Scope mutex to protect read/write the list
|
||||
std::lock_guard<std::mutex> lock(pending_dl_grant_mutex);
|
||||
|
||||
// Save entry
|
||||
pending_dl_grant_t& pending_grant = pending_dl_grant[tti_rx];
|
||||
pending_grant.sch_cfg = pdsch_cfg;
|
||||
pending_grant.ack_resource = ack_resource;
|
||||
pending_grant.pid = dci_dl.pid;
|
||||
pending_grant.enable = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks the DL pending grant list if there is any grant to receive for the given receive TTI
|
||||
* @param tti_rx Current receive TTI
|
||||
* @param sch_cfg Provides the Shared Channel configuration for the PDSCH transmission
|
||||
* @param ack_resource Provides the UL ACK resource
|
||||
* @param pid Provides the HARQ process identifier
|
||||
* @return true if there is a pending grant for the given TX tti, false otherwise
|
||||
*/
|
||||
bool get_dl_pending_grant(uint32_t tti_rx,
|
||||
srslte_sch_cfg_nr_t& pdsch_cfg,
|
||||
srslte_pdsch_ack_resource_nr_t& ack_resource,
|
||||
uint32_t& pid)
|
||||
{
|
||||
// Scope mutex to protect read/write the list
|
||||
std::lock_guard<std::mutex> lock(pending_dl_grant_mutex);
|
||||
|
||||
// Select entry
|
||||
pending_dl_grant_t& pending_grant = pending_dl_grant[tti_rx];
|
||||
|
||||
// If the entry is not active, just return
|
||||
if (!pending_grant.enable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load shared channel configuration and resource
|
||||
pdsch_cfg = pending_grant.sch_cfg;
|
||||
ack_resource = pending_grant.ack_resource;
|
||||
pid = pending_grant.pid;
|
||||
|
||||
// Reset entry
|
||||
pending_grant.enable = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stores a pending PDSCH ACK into the pending ACK list
|
||||
* @param tti_rx The TTI in which the PDSCH transmission was received
|
||||
* @param dci_dl The DL DCI message to store
|
||||
*/
|
||||
void set_pending_ack(const uint32_t& tti_rx, const srslte_pdsch_ack_resource_nr_t& ack_resource, const bool& crc_ok)
|
||||
{
|
||||
// Calculate Receive TTI
|
||||
uint32_t tti_tx = TTI_ADD(tti_rx, ack_resource.k1);
|
||||
|
||||
// Scope mutex to protect read/write the list
|
||||
std::lock_guard<std::mutex> lock(pending_ack_mutex);
|
||||
|
||||
// Select UL transmission time resource
|
||||
srslte_pdsch_ack_nr_t& ack = pending_ack[tti_tx];
|
||||
ack.nof_cc = 1;
|
||||
|
||||
// Select serving cell
|
||||
srslte_pdsch_ack_cc_nr_t& ack_cc = ack.cc[ack_resource.scell_idx];
|
||||
srslte_pdsch_ack_m_nr_t& ack_m = ack_cc.m[ack_cc.M];
|
||||
ack_cc.M++;
|
||||
|
||||
// Set PDSCH transmission information
|
||||
ack_m.resource = ack_resource;
|
||||
ack_m.value[0] = crc_ok ? 1 : 0;
|
||||
ack_m.present = true;
|
||||
}
|
||||
|
||||
bool get_pending_ack(const uint32_t& tti_tx, srslte_pdsch_ack_nr_t& pdsch_ack)
|
||||
{
|
||||
// Scope mutex to protect read/write the list
|
||||
std::lock_guard<std::mutex> lock(pending_ack_mutex);
|
||||
|
||||
// Select UL transmission time resource
|
||||
srslte_pdsch_ack_nr_t& ack = pending_ack[tti_tx];
|
||||
|
||||
// No pending grant was set
|
||||
if (ack.nof_cc == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy data
|
||||
pdsch_ack = ack;
|
||||
|
||||
// Reset list entry
|
||||
ack = {};
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace nr
|
||||
} // namespace srsue
|
||||
|
|
|
@ -126,30 +126,10 @@ uint32_t cc_worker::get_buffer_len()
|
|||
return buffer_sz;
|
||||
}
|
||||
|
||||
bool cc_worker::work_dl()
|
||||
void cc_worker::decode_pdcch_dl()
|
||||
{
|
||||
// Run FFT
|
||||
srslte_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg);
|
||||
|
||||
// Initialise grants
|
||||
std::array<srslte_dci_dl_nr_t, 5> dci_dl_rx = {};
|
||||
std::array<srslte_dci_ul_nr_t, 5> dci_ul_rx = {};
|
||||
uint32_t nof_found_dci_dl = 0;
|
||||
uint32_t nof_found_dci_ul = 0;
|
||||
|
||||
// Search for RA DCI
|
||||
if (phy->cfg.pdcch.ra_search_space_present) {
|
||||
int n_ra = srslte_ue_dl_nr_find_dl_dci(&ue_dl,
|
||||
&dl_slot_cfg,
|
||||
phy->cfg.pdcch.ra_rnti,
|
||||
&dci_dl_rx[nof_found_dci_dl],
|
||||
(uint32_t)dci_dl_rx.size() - nof_found_dci_dl);
|
||||
if (n_ra < SRSLTE_SUCCESS) {
|
||||
ERROR("Error decoding");
|
||||
return false;
|
||||
}
|
||||
nof_found_dci_dl += n_ra;
|
||||
}
|
||||
std::array<srslte_dci_dl_nr_t, 5> dci_rx = {};
|
||||
uint32_t nof_found_dci = 0;
|
||||
|
||||
// Search for test RNTI
|
||||
if (phy->test_rnti > 0) {
|
||||
|
@ -157,60 +137,90 @@ bool cc_worker::work_dl()
|
|||
int n_dl = srslte_ue_dl_nr_find_dl_dci(&ue_dl,
|
||||
&dl_slot_cfg,
|
||||
(uint16_t)phy->test_rnti,
|
||||
&dci_dl_rx[nof_found_dci_dl],
|
||||
(uint32_t)dci_dl_rx.size() - nof_found_dci_dl);
|
||||
&dci_rx[nof_found_dci],
|
||||
(uint32_t)dci_rx.size() - nof_found_dci);
|
||||
if (n_dl < SRSLTE_SUCCESS) {
|
||||
ERROR("Error decoding");
|
||||
return false;
|
||||
logger.error("Error decoding DL NR-PDCCH for test RNTI");
|
||||
return;
|
||||
}
|
||||
nof_found_dci_dl += n_dl;
|
||||
|
||||
// Search for test UL grants
|
||||
int n_ul = srslte_ue_dl_nr_find_ul_dci(&ue_dl,
|
||||
&dl_slot_cfg,
|
||||
(uint16_t)phy->test_rnti,
|
||||
&dci_ul_rx[nof_found_dci_ul],
|
||||
(uint32_t)dci_ul_rx.size() - nof_found_dci_ul);
|
||||
if (n_ul < SRSLTE_SUCCESS) {
|
||||
ERROR("Error decoding");
|
||||
return false;
|
||||
}
|
||||
nof_found_dci_ul += n_ul;
|
||||
nof_found_dci += n_dl;
|
||||
}
|
||||
|
||||
// Iterate over all UL received grants
|
||||
for (uint32_t i = 0; i < nof_found_dci_ul; i++) {
|
||||
// Search for RA DCI
|
||||
if (phy->cfg.pdcch.ra_search_space_present) {
|
||||
int n_ra = srslte_ue_dl_nr_find_dl_dci(
|
||||
&ue_dl, &dl_slot_cfg, phy->cfg.pdcch.ra_rnti, &dci_rx[nof_found_dci], (uint32_t)dci_rx.size() - nof_found_dci);
|
||||
if (n_ra < SRSLTE_SUCCESS) {
|
||||
logger.error("Error decoding DL NR-PDCCH for RA-RNTI");
|
||||
return;
|
||||
}
|
||||
nof_found_dci += n_ra;
|
||||
}
|
||||
|
||||
// Iterate over all DL received grants
|
||||
for (uint32_t i = 0; i < nof_found_dci; i++) {
|
||||
// Log found DCI
|
||||
if (logger.info.enabled()) {
|
||||
std::array<char, 512> str;
|
||||
srslte_dci_ul_nr_to_str(&dci_ul_rx[i], str.data(), str.size());
|
||||
srslte_dci_dl_nr_to_str(&dci_rx[i], str.data(), str.size());
|
||||
logger.info("PDCCH: cc=%d, %s", cc_idx, str.data());
|
||||
}
|
||||
|
||||
// Enqueue UL grants
|
||||
phy->set_ul_pending_grant(dl_slot_cfg.idx, dci_ul_rx[i]);
|
||||
phy->set_dl_pending_grant(dl_slot_cfg.idx, dci_rx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void cc_worker::decode_pdcch_ul()
|
||||
{
|
||||
std::array<srslte_dci_ul_nr_t, 5> dci_rx = {};
|
||||
uint32_t nof_found_dci = 0;
|
||||
|
||||
// Search for test RNTI
|
||||
if (phy->test_rnti > 0) {
|
||||
// Search for test DL grants
|
||||
int n_dl = srslte_ue_dl_nr_find_ul_dci(&ue_dl,
|
||||
&dl_slot_cfg,
|
||||
(uint16_t)phy->test_rnti,
|
||||
&dci_rx[nof_found_dci],
|
||||
(uint32_t)dci_rx.size() - nof_found_dci);
|
||||
if (n_dl < SRSLTE_SUCCESS) {
|
||||
logger.error("Error decoding DL NR-PDCCH for test RNTI");
|
||||
return;
|
||||
}
|
||||
nof_found_dci += n_dl;
|
||||
}
|
||||
|
||||
// Iterate over all DL received grants
|
||||
for (uint32_t i = 0; i < nof_found_dci_dl; i++) {
|
||||
// Notify MAC about PDCCH found grant
|
||||
// ... At the moment reset softbuffer locally
|
||||
srslte_softbuffer_rx_reset(&softbuffer_rx);
|
||||
|
||||
// Iterate over all UL received grants
|
||||
for (uint32_t i = 0; i < nof_found_dci; i++) {
|
||||
// Log found DCI
|
||||
if (logger.info.enabled()) {
|
||||
std::array<char, 512> str;
|
||||
srslte_dci_dl_nr_to_str(&dci_dl_rx[i], str.data(), str.size());
|
||||
srslte_dci_ul_nr_to_str(&dci_rx[i], str.data(), str.size());
|
||||
logger.info("PDCCH: cc=%d, %s", cc_idx, str.data());
|
||||
}
|
||||
|
||||
// Compute DL grant
|
||||
srslte_sch_cfg_nr_t pdsch_cfg = {};
|
||||
if (srslte_ra_dl_dci_to_grant_nr(&ue_dl.carrier, &phy->cfg.pdsch, &dci_dl_rx[i], &pdsch_cfg, &pdsch_cfg.grant)) {
|
||||
ERROR("Computing DL grant");
|
||||
return false;
|
||||
}
|
||||
// Enqueue UL grants
|
||||
phy->set_ul_pending_grant(dl_slot_cfg.idx, dci_rx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool cc_worker::work_dl()
|
||||
{
|
||||
// Run FFT
|
||||
srslte_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg);
|
||||
|
||||
// Decode PDCCH DL first
|
||||
decode_pdcch_dl();
|
||||
|
||||
// Decode PDCCH UL after
|
||||
decode_pdcch_ul();
|
||||
|
||||
// Get DL grant for this TTI, if available
|
||||
uint32_t pid = 0;
|
||||
srslte_sch_cfg_nr_t pdsch_cfg = {};
|
||||
srslte_pdsch_ack_resource_nr_t ack_resource = {};
|
||||
if (phy->get_dl_pending_grant(dl_slot_cfg.idx, pdsch_cfg, ack_resource, pid)) {
|
||||
// Get data buffer
|
||||
srslte::unique_byte_buffer_t data = srslte::make_byte_buffer();
|
||||
data->N_bytes = pdsch_cfg.grant.tb[0].tbs / 8U;
|
||||
|
@ -233,13 +243,16 @@ bool cc_worker::work_dl()
|
|||
logger.info(pdsch_res[0].payload, pdsch_cfg.grant.tb[0].tbs / 8, "PDSCH: cc=%d, %s", cc_idx, str.data());
|
||||
}
|
||||
|
||||
// Enqueue PDSCH ACK information
|
||||
phy->set_pending_ack(dl_slot_cfg.idx, ack_resource, pdsch_res[0].crc);
|
||||
|
||||
// Notify MAC about PDSCH decoding result
|
||||
if (pdsch_res[0].crc) {
|
||||
// Prepare grant
|
||||
mac_interface_phy_nr::mac_nr_grant_dl_t mac_nr_grant = {};
|
||||
mac_nr_grant.tb[0] = std::move(data);
|
||||
mac_nr_grant.pid = dci_dl_rx[i].pid;
|
||||
mac_nr_grant.rnti = dci_dl_rx[i].rnti;
|
||||
mac_nr_grant.pid = pid;
|
||||
mac_nr_grant.rnti = pdsch_cfg.grant.rnti;
|
||||
mac_nr_grant.tti = dl_slot_cfg.idx;
|
||||
|
||||
// Send data to MAC
|
||||
|
@ -252,36 +265,70 @@ bool cc_worker::work_dl()
|
|||
|
||||
bool cc_worker::work_ul()
|
||||
{
|
||||
srslte_sch_cfg_nr_t pusch_cfg = {};
|
||||
uint32_t pid = 0;
|
||||
srslte_uci_data_nr_t uci_data = {};
|
||||
uint32_t pid = 0;
|
||||
|
||||
// Gather PDSCH ACK information
|
||||
srslte_pdsch_ack_nr_t pdsch_ack = {};
|
||||
bool has_ul_ack = phy->get_pending_ack(ul_slot_cfg.idx, pdsch_ack);
|
||||
|
||||
// Request grant to PHY state for this transmit TTI
|
||||
if (not phy->get_ul_pending_grant(ul_slot_cfg.idx, pusch_cfg, pid)) {
|
||||
// If no grant, return earlier
|
||||
return true;
|
||||
srslte_sch_cfg_nr_t pusch_cfg = {};
|
||||
bool has_pusch_grant = phy->get_ul_pending_grant(ul_slot_cfg.idx, pusch_cfg, pid);
|
||||
|
||||
// If PDSCH UL AKC is available, load into UCI
|
||||
if (has_ul_ack) {
|
||||
pdsch_ack.use_pusch = has_pusch_grant;
|
||||
if (srslte_ue_dl_nr_gen_ack(&phy->cfg.harq_ack, &pdsch_ack, &uci_data) < SRSLTE_SUCCESS) {
|
||||
ERROR("Filling UCI ACK bits");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Notify MAC about PUSCH found grant
|
||||
// ...
|
||||
srslte_softbuffer_tx_reset(&softbuffer_tx);
|
||||
pusch_cfg.grant.tb[0].softbuffer.tx = &softbuffer_tx;
|
||||
if (has_pusch_grant) {
|
||||
// Notify MAC about PUSCH found grant
|
||||
// ...
|
||||
srslte_softbuffer_tx_reset(&softbuffer_tx);
|
||||
pusch_cfg.grant.tb[0].softbuffer.tx = &softbuffer_tx;
|
||||
|
||||
// Encode PUSCH transmission
|
||||
if (srslte_ue_ul_nr_encode_pusch(&ue_ul, &ul_slot_cfg, &pusch_cfg, tx_data.data()) < SRSLTE_SUCCESS) {
|
||||
ERROR("Encoding PUSCH");
|
||||
return false;
|
||||
}
|
||||
// Encode PUSCH transmission
|
||||
if (srslte_ue_ul_nr_encode_pusch(&ue_ul, &ul_slot_cfg, &pusch_cfg, tx_data.data()) < SRSLTE_SUCCESS) {
|
||||
ERROR("Encoding PUSCH");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Logging
|
||||
if (logger.info.enabled()) {
|
||||
std::array<char, 512> str;
|
||||
srslte_ue_ul_nr_pusch_info(&ue_ul, &pusch_cfg, str.data(), str.size());
|
||||
logger.info(tx_data.data(),
|
||||
pusch_cfg.grant.tb[0].tbs / 8,
|
||||
"PUSCH: cc=%d, %s, tti_tx=%d",
|
||||
cc_idx,
|
||||
str.data(),
|
||||
ul_slot_cfg.idx);
|
||||
// PUSCH Logging
|
||||
if (logger.info.enabled()) {
|
||||
std::array<char, 512> str;
|
||||
srslte_ue_ul_nr_pusch_info(&ue_ul, &pusch_cfg, str.data(), str.size());
|
||||
logger.info(tx_data.data(),
|
||||
pusch_cfg.grant.tb[0].tbs / 8,
|
||||
"PUSCH: cc=%d, %s, tti_tx=%d",
|
||||
cc_idx,
|
||||
str.data(),
|
||||
ul_slot_cfg.idx);
|
||||
}
|
||||
} else if (srslte_uci_nr_total_bits(&uci_data.cfg) > 0) {
|
||||
// Get PUCCH resource
|
||||
srslte_pucch_nr_resource_t resource = {};
|
||||
if (srslte_ra_ul_nr_pucch_resource(&phy->cfg.pucch, &uci_data.cfg, &resource) < SRSLTE_SUCCESS) {
|
||||
ERROR("Selecting PUCCH resource");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Encode PUCCH message
|
||||
if (srslte_ue_ul_nr_encode_pucch(&ue_ul, &ul_slot_cfg, &phy->cfg.pucch.common, &resource, &uci_data) <
|
||||
SRSLTE_SUCCESS) {
|
||||
ERROR("Encoding PUCCH");
|
||||
return false;
|
||||
}
|
||||
|
||||
// PUCCH Logging
|
||||
if (logger.info.enabled()) {
|
||||
std::array<char, 512> str;
|
||||
srslte_ue_ul_nr_pucch_info(&resource, &uci_data, str.data(), str.size());
|
||||
logger.info("PUCCH: cc=%d, %s, tti_tx=%d", cc_idx, str.data(), ul_slot_cfg.idx);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue