Added DCI Format 0_0 unpacking and more NR-PUSCH procedures

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent b150e45129
commit 77f0a53abd

@ -143,6 +143,7 @@ typedef enum SRSLTE_API {
srslte_search_space_type_common_2, ///< configured by pagingSearchSpace in PDCCH-ConfigCommon
srslte_search_space_type_common_3, ///< configured by SearchSpace in PDCCH-Config with searchSpaceType = common
srslte_search_space_type_ue, ///< configured by SearchSpace in PDCCH-Config with searchSpaceType = ue-Specific
srslte_search_space_rar ///< No search space associated, used for grants given by Random Access Response (RAR)
} srslte_search_space_type_t;
/**

@ -62,11 +62,44 @@ typedef struct SRSLTE_API {
} srslte_dci_dl_nr_t;
typedef struct SRSLTE_API {
// Context information
uint16_t rnti;
srslte_rnti_type_t rnti_type;
srslte_dci_format_nr_t format;
srslte_dci_location_t location;
srslte_search_space_type_t search_space;
uint32_t coreset_id;
// Common fields
uint32_t freq_domain_assigment; ///< Frequency domain resource assignment
uint32_t time_domain_assigment; ///< Time domain resource assignment
uint32_t freq_hopping_flag; ///< Frequency hopping flag
uint32_t mcs; ///< Modulation and coding scheme
uint32_t rv; ///< Redundancy version
uint32_t reserved; ///< Reserved bits
// C-RNTI or CS-RNTI or MCS-C-RNTI
uint32_t ndi; ///< New data indicator
uint32_t pid; ///< HARQ process number
uint32_t tpc; ///< TPC command for scheduled PUCCH
uint32_t pucch_resource; ///< PUCCH resource indicator
uint32_t harq_feedback; ///< PDSCH-to-HARQ_feedback timing indicator
// Frequency hopping
uint32_t frequency_offset; ///< frequency offset
} srslte_dci_ul_nr_t;
SRSLTE_API int srslte_dci_nr_pack(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
const srslte_dci_dl_nr_t* dci,
srslte_dci_msg_nr_t* msg);
SRSLTE_API int srslte_dci_nr_format_0_0_sizeof(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
srslte_rnti_type_t rnti_type);
SRSLTE_API SRSLTE_API int srslte_dci_nr_format_1_0_sizeof(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
srslte_rnti_type_t rnti_type);
@ -81,6 +114,6 @@ SRSLTE_API int srslte_dci_nr_format_1_0_unpack(const srslte_carrier_nr_t* carrie
srslte_dci_msg_nr_t* msg,
srslte_dci_dl_nr_t* dci);
SRSLTE_API int srslte_dci_nr_to_str(const srslte_dci_dl_nr_t* dci, char* str, uint32_t str_len);
SRSLTE_API int srslte_dci_dl_nr_to_str(const srslte_dci_dl_nr_t* dci, char* str, uint32_t str_len);
#endif // SRSLTE_DCI_NR_H

@ -82,21 +82,23 @@ typedef struct {
} srslte_dmrs_sch_cfg_t;
/**
* @brief flatten PDSCH time domain allocation parameters
* @brief Common flatten PDSCH and PUSCH time domain allocation parameters
* @remark Described in TS 38.331 V15.10.0 Section PDSCH-TimeDomainResourceAllocationList
* @remark Described in TS 38.331 V15.10.0 Section PUSCH-TimeDomainResourceAllocationList
*/
typedef struct SRSLTE_API {
/// Slot offset between DCI and its scheduled PDSCH
uint32_t k0;
/// For PDSCH Slot offset between DCI and its scheduled PDSCH
/// For PUSCH parameter K2
uint32_t k;
/// PDSCH mapping type
/// SCH mapping type
srslte_sch_mapping_type_t mapping_type;
/// An index giving valid combinations of start symbol and length (jointly encoded) as start and length indicator
/// (SLIV). The network configures the field so that the allocation does not cross the slot boundary
uint32_t sliv;
} srslte_pdsch_time_ra_t;
} srslte_sch_time_ra_t;
/**
* @brief PDSCH grant information provided by the Downlink Control Information (DCI)
@ -144,6 +146,8 @@ typedef struct SRSLTE_API {
* @remark Described in TS 38.331 V15.10.0 Section PUSCH-Config
*/
typedef struct SRSLTE_API {
// Serving cell parameters
uint32_t scs_cfg; // Subcarrier spacing configuration
srslte_dmrs_sch_typeA_pos_t typeA_pos;
bool scrambling_id_present;
@ -157,28 +161,35 @@ typedef struct SRSLTE_API {
uint32_t scrambling_id0;
bool scrambling_id1_present;
uint32_t scrambling_id1;
bool present;
} dmrs_typeA;
bool dmrs_typeA_present;
srslte_dmrs_sch_cfg_t dmrs_typeB;
bool dmrs_typeB_present;
struct {
srslte_dmrs_sch_type_t type;
srslte_dmrs_sch_add_pos_t additional_pos;
srslte_dmrs_sch_len_t length;
bool scrambling_id0_present;
uint32_t scrambling_id0;
bool scrambling_id1_present;
uint32_t scrambling_id1;
bool present;
} dmrs_typeB;
srslte_pdsch_time_ra_t common_pdsch_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION];
uint32_t nof_common_pdsch_time_ra;
srslte_sch_time_ra_t common_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION];
uint32_t nof_common_time_ra;
srslte_pdsch_time_ra_t pdsch_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION];
uint32_t nof_pdsch_time_ra;
srslte_sch_time_ra_t dedicated_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION];
uint32_t nof_dedicated_time_ra;
bool rbg_size_cfg_1; ///< RBG size configuration (1 or 2)
srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters
} srslte_pdsch_cfg_nr_t;
} srslte_sch_hl_cfg_nr_t;
/**
* @brief Common NR-SCH (PDSCH and PUSCH for NR) configuration
*/
typedef struct SRSLTE_API {
bool scrambling_id_present;
uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023)

@ -33,7 +33,7 @@
* @remark Defined by TS 38.214 V15.10.0 section 5.1.2.1.1 Determination of the resource allocation table to be used for
* PDSCH
*
* @param pdsch_cfg Flattened PDSCH configuration provided from higher layers
* @param cfg Flattened PDSCH configuration provided from higher layers
* @param rnti_type Type of the RNTI of the corresponding DCI
* @param ss_type Type of the SS for PDCCH
* @param coreset_id CORESET identifier associated with the PDCCH transmission
@ -41,7 +41,7 @@
* @param[out] Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_dl_nr_time(const srslte_pdsch_cfg_nr_t* cfg,
SRSLTE_API int srslte_ra_dl_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
@ -85,7 +85,7 @@ SRSLTE_API int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const
* @return SRSLTE_SUCCESS if the provided data is valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant);

@ -96,7 +96,7 @@ SRSLTE_API int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg,
* @return 0 on success, -1 on error
*/
SRSLTE_API int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_sch_hl_cfg_nr_t* pdsch_cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* pdsch_grant);

@ -13,10 +13,59 @@
#ifndef SRSLTE_RA_UL_NR_H
#define SRSLTE_RA_UL_NR_H
#include "dci_nr.h"
#include "srslte/config.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#include "srslte/phy/phch/pucch_cfg_nr.h"
#include "uci_cfg_nr.h"
/**
* @brief Calculates the PUSCH time resource allocation and stores it in the provided PUSCH NR grant.
*
* @remark Defined by TS 38.214 V15.10.0 section 6.1.2.1.1 Determination of the resource allocation table to be used for
* PUSCH
*
* @param cfg Flattened PUSCH configuration provided from higher layers
* @param rnti_type Type of the RNTI of the corresponding DCI
* @param ss_type Type of the SS for PDCCH
* @param coreset_id CORESET identifier associated with the PDCCH transmission
* @param m Time domain resource assignment field value m provided in DCI
* @param[out] Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m,
srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the PUSCH time resource default A and stores it in the provided PUSCH NR grant.
*
* @remark Defined by TS 38.214 V15.10.0 Table 6.1.2.1.1-2: Default PUSCH time domain resource allocation A for normal
* CP
*
* @param scs_cfg Sub-carrier spacing configuration for PUSCH (μ)
* @param m Time domain resource assignment field value m of the DCI
* @param[out] grant PUSCH grant
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int
srslte_ra_ul_nr_pdsch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the number of PUSCH-DMRS CDM groups without data for DCI format 0_0
*
* @remark Defined by TS 38.214 V15.10.0 6.2.2 UE DM-RS transmission procedure
*
* @param cfg PUSCH NR configuration by upper layers
* @param[out] grant Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided data is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the minimum number of PRB required for transmitting NR-PUCCH Format 2, 3 or 4
* @remark Based in TS 38.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR in a PUCCH
@ -25,4 +74,19 @@
SRSLTE_API int srslte_ra_ul_nr_pucch_format_2_3_min_prb(const srslte_pucch_nr_resource_t* resource,
const srslte_uci_cfg_nr_t* uci_cfg);
/**
* @brief Calculates the PUSCH frequency resource allocation and stores it in the provided PUSCH NR grant.
*
* @remark Defined by TS 38.214 V15.10.0 section 5.1.2.2
* @param carrier Carrier information
* @param cfg PDSCH NR configuration by upper layers
* @param dci_dl Unpacked DCI used to schedule the PDSCH grant
* @param[out] grant Provides grant pointer to fill
* @return SRSLTE_SUCCESS if the provided data is valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_ra_ul_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_dci_ul_nr_t* dci_ul,
srslte_sch_grant_nr_t* grant);
#endif // SRSLTE_RA_UL_NR_H

@ -0,0 +1,29 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
/******************************************************************************
* @file ue_dl_nr.h
*
* Description: NR UE uplink physical layer procedures for data
*
* This module is a frontend to all the uplink data channel processing modules.
*
* Reference:
*****************************************************************************/
#ifndef SRSLTE_UE_UL_DATA_H
#define SRSLTE_UE_UL_DATA_H
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#endif // SRSLTE_UE_UL_DATA_H

@ -1,54 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
/******************************************************************************
* @file ue_dl_nr.h
*
* Description: NR UE uplink physical layer procedures for data
*
* This module is a frontend to all the uplink data channel processing modules.
*
* Reference:
*****************************************************************************/
#ifndef SRSLTE_UE_UL_DATA_H
#define SRSLTE_UE_UL_DATA_H
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
/**
* @brief Calculates the PUSCH time resource default A and stores it in the provided PUSCH NR grant.
*
* @remark Defined by TS 38.214 V15.10.0 Table 6.1.2.1.1-2: Default PUSCH time domain resource allocation A for normal
* CP
*
* @param m Time domain resource assignment field value m of the DCI
* @param[out] grant PUSCH grant
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ue_ul_nr_pdsch_time_resource_default_A(uint32_t m, srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the number of PUSCH-DMRS CDM groups without data for DCI format 0_0
*
* @remark Defined by TS 38.214 V15.10.0 6.2.2 UE DM-RS transmission procedure
*
* @param cfg PUSCH NR configuration by upper layers
* @param[out] grant Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided data is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ue_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* grant);
#endif // SRSLTE_UE_UL_DATA_H

@ -14,6 +14,15 @@
#include "srslte/phy/utils/bit.h"
#include "srslte/phy/utils/debug.h"
static int dci_nr_format_0_0_freq_resource_size(const srslte_carrier_nr_t* carrier)
{
if (carrier == NULL) {
return SRSLTE_ERROR;
}
return (int)ceil(log2(carrier->nof_prb * (carrier->nof_prb + 1) / 2.0));
}
static int dci_nr_format_1_0_freq_resource_size(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset0,
srslte_rnti_type_t rnti_type)
@ -64,6 +73,222 @@ int srslte_dci_nr_pack(const srslte_carrier_nr_t* carrier,
return SRSLTE_SUCCESS;
}
int srslte_dci_nr_format_0_0_pack(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset0,
const srslte_dci_ul_nr_t* dci,
srslte_dci_msg_nr_t* msg)
{
uint32_t trim = 0; // hard-coded bit trimming
bool enable_hopping = false; // hard-coded PUSCH hopping
uint32_t padding = 0; // Hard-coded padding
bool supplementary_uplink = false; // Hard-coded supplementary Uplink
uint8_t* y = msg->payload;
srslte_rnti_type_t rnti_type = msg->rnti_type;
if (carrier == NULL) {
return SRSLTE_ERROR;
}
// Check RNTI type
if (rnti_type != srslte_rnti_type_c && rnti_type != srslte_rnti_type_cs && rnti_type != srslte_rnti_type_mcs_c) {
return SRSLTE_ERROR;
}
// Identifier for DCI formats 1 bits
*y = 0;
y++;
// For PUSCH hopping with resource allocation type 1 N UL_hop MSB bits are used to indicate the frequency offset
int N_UL_hop = (enable_hopping) ? ((carrier->nof_prb < 50) ? 1 : 2) : 0;
srslte_bit_unpack(dci->frequency_offset, &y, N_UL_hop);
// Frequency domain resource assignment
int N = dci_nr_format_0_0_freq_resource_size(carrier);
if (N < SRSLTE_SUCCESS || N - N_UL_hop <= 0) {
return SRSLTE_ERROR;
}
srslte_bit_unpack(dci->freq_domain_assigment, &y, N - N_UL_hop - trim);
// Time domain resource assignment 4 bits
srslte_bit_unpack(dci->time_domain_assigment, &y, 4);
// Frequency hopping flag 1 bit
srslte_bit_unpack(dci->freq_hopping_flag, &y, 1);
// Modulation and coding scheme 5 bits
srslte_bit_unpack(dci->mcs, &y, 5);
// New data indicator 1 bit
srslte_bit_unpack(dci->ndi, &y, 1);
// Redundancy version 2 bits
srslte_bit_unpack(dci->rv, &y, 2);
// HARQ process number 4 bits
srslte_bit_unpack(dci->pid, &y, 4);
// TPC command for scheduled PUSCH 2 bits
srslte_bit_unpack(dci->tpc, &y, 2);
// Padding goes here
for (uint32_t i = 0; i < padding; i++) {
*(y++) = 0;
}
// UL/SUL indicator 1 bit for UEs configured with supplementaryUplink in ServingCellConfig, othwerwise 0
if (supplementary_uplink) {
*(y++) = 0;
}
msg->nof_bits = srslte_dci_nr_format_0_0_sizeof(carrier, coreset0, rnti_type);
if (msg->nof_bits != y - msg->payload) {
ERROR("Unpacked bits readed (%d) do NOT match payload size (%d)\n", msg->nof_bits, (int)(y - msg->payload));
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_dci_nr_format_0_0_unpack(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
srslte_dci_msg_nr_t* msg,
srslte_dci_ul_nr_t* dci)
{
uint32_t trim = 0; // hard-coded bit trimming
bool enable_hopping = false; // hard-coded PUSCH hopping
uint32_t padding = 0; // Hard-coded padding
bool supplementary_uplink = false; // Hard-coded supplementary Uplink
uint8_t* y = msg->payload;
srslte_rnti_type_t rnti_type = msg->rnti_type;
if (carrier == NULL) {
return SRSLTE_ERROR;
}
// Check RNTI type
if (rnti_type != srslte_rnti_type_c && rnti_type != srslte_rnti_type_cs && rnti_type != srslte_rnti_type_mcs_c) {
return SRSLTE_ERROR;
}
if (msg->nof_bits != srslte_dci_nr_format_0_0_sizeof(carrier, coreset, rnti_type)) {
ERROR("Invalid number of bits %d, expected %d\n",
msg->nof_bits,
srslte_dci_nr_format_0_0_sizeof(carrier, coreset, rnti_type));
return SRSLTE_ERROR;
}
// Identifier for DCI formats 1 bits
if (*(y++) != 0) {
ERROR("Wrond DCI format\n");
return SRSLTE_ERROR;
}
// For PUSCH hopping with resource allocation type 1 N UL_hop MSB bits are used to indicate the frequency offset
int N_UL_hop = (enable_hopping) ? ((carrier->nof_prb < 50) ? 1 : 2) : 0;
dci->frequency_offset = srslte_bit_pack(&y, N_UL_hop);
// Frequency domain resource assignment
int N = dci_nr_format_0_0_freq_resource_size(carrier);
if (N < SRSLTE_SUCCESS || N - N_UL_hop <= 0) {
return SRSLTE_ERROR;
}
dci->freq_domain_assigment = srslte_bit_pack(&y, N - N_UL_hop - trim);
// Time domain resource assignment 4 bits
dci->time_domain_assigment = srslte_bit_pack(&y, 4);
// Frequency hopping flag 1 bit
dci->freq_hopping_flag = srslte_bit_pack(&y, 1);
// Modulation and coding scheme 5 bits
dci->mcs = srslte_bit_pack(&y, 5);
// New data indicator 1 bit
dci->ndi = srslte_bit_pack(&y, 1);
// Redundancy version 2 bits
dci->rv = srslte_bit_pack(&y, 2);
// HARQ process number 4 bits
dci->pid = srslte_bit_pack(&y, 4);
// TPC command for scheduled PUSCH 2 bits
dci->tpc = srslte_bit_pack(&y, 2);
// Padding goes here
for (uint32_t i = 0; i < padding; i++) {
y++;
}
// UL/SUL indicator 1 bit for UEs configured with supplementaryUplink in ServingCellConfig, othwerwise 0
if (supplementary_uplink) {
y++;
}
return SRSLTE_SUCCESS;
}
int srslte_dci_nr_format_0_0_sizeof(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
srslte_rnti_type_t rnti_type)
{
uint32_t trim = 0; // hard-coded bit trimming
bool enable_hopping = false; // hard-coded PUSCH hopping
uint32_t padding = 0; // Hard-coded padding
bool supplementary_uplink = false; // Hard-coded supplementary Uplink
int count = 0;
// Identifier for DCI formats 1 bits
count++;
// For PUSCH hopping with resource allocation type 1 N UL_hop MSB bits are used to indicate the frequency offset
int N_UL_hop = (enable_hopping) ? ((carrier->nof_prb < 50) ? 1 : 2) : 0;
count += N_UL_hop;
// Frequency domain resource assignment
int N = dci_nr_format_0_0_freq_resource_size(carrier);
if (N < SRSLTE_SUCCESS || N - N_UL_hop <= 0) {
return SRSLTE_ERROR;
}
count += N - N_UL_hop - trim;
// Time domain resource assignment 4 bits
count += 4;
// Frequency hopping flag 1 bit
count += 1;
// Modulation and coding scheme 5 bits
count += 5;
// New data indicator 1 bit
count += 1;
// Redundancy version 2 bits
count += 2;
// HARQ process number 4 bits
count += 4;
// TPC command for scheduled PUSCH 2 bits
count += 2;
// Padding goes here
count += padding;
// UL/SUL indicator 1 bit for UEs configured with supplementaryUplink in ServingCellConfig, othwerwise 0
if (supplementary_uplink) {
count++;
}
return count;
}
static int dci_nr_format_0_0_to_str(const srslte_dci_ul_nr_t* dci, char* str, uint32_t str_len)
{
return SRSLTE_ERROR;
}
int srslte_dci_nr_format_1_0_pack(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
const srslte_dci_dl_nr_t* dci,
@ -198,11 +423,10 @@ int srslte_dci_nr_format_1_0_unpack(const srslte_carrier_nr_t* carrier,
// Identifier for DCI formats 1 bits
if (rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_tc) {
// The value of this bit field is always set to 1, indicating a DL DCI format
if (*y != 1) {
if (*(y++) != 1) {
ERROR("Wrond DCI format\n");
return SRSLTE_ERROR;
}
y++;
}
if (rnti_type == srslte_rnti_type_p) {
@ -298,7 +522,7 @@ int srslte_dci_nr_format_1_0_sizeof(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
srslte_rnti_type_t rnti_type)
{
uint32_t count = 0;
int count = 0;
// Identifier for DCI formats 1 bits
if (rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_tc) {
@ -467,7 +691,19 @@ static int dci_nr_format_1_0_to_str(const srslte_dci_dl_nr_t* dci, char* str, ui
return len;
}
int srslte_dci_nr_to_str(const srslte_dci_dl_nr_t* dci, char* str, uint32_t str_len)
int srslte_dci_ul_nr_to_str(const srslte_dci_ul_nr_t* dci, char* str, uint32_t str_len)
{
// Pack DCI
switch (dci->format) {
case srslte_dci_format_nr_0_0:
return dci_nr_format_0_0_to_str(dci, str, str_len);
default:; // Do nothing
}
return srslte_print_check(str, str_len, 0, "unknown");
}
int srslte_dci_dl_nr_to_str(const srslte_dci_dl_nr_t* dci, char* str, uint32_t str_len)
{
// Pack DCI
switch (dci->format) {

@ -10,21 +10,9 @@
*
*/
#include "srslte/phy/phch/ra_dl_nr.h"
#include "ra_helper.h"
#include "srslte/phy/utils/debug.h"
static void compute_s_and_l(uint32_t N, uint32_t v, uint32_t* S, uint32_t* L)
{
uint32_t low = v % N;
uint32_t high = v / N;
if (high + 1 + low <= N) {
*S = low;
*L = high + 1;
} else {
*S = N - 1 - low;
*L = N - high + 1;
}
}
// Validate S and L combination for TypeA time domain resource allocation
static bool check_time_ra_typeA(uint32_t* S, uint32_t* L)
{
@ -108,7 +96,6 @@ int srslte_ra_dl_nr_time_default_A(uint32_t m, srslte_dmrs_sch_typeA_pos_t dmrs_
// Select start symbol (S) and length (L)
switch (dmrs_typeA_pos) {
case srslte_dmrs_sch_typeA_pos_2:
grant->S = S_pos2[m];
grant->L = L_pos2[m];
@ -125,23 +112,22 @@ int srslte_ra_dl_nr_time_default_A(uint32_t m, srslte_dmrs_sch_typeA_pos_t dmrs_
return SRSLTE_SUCCESS;
}
void srslte_ra_dl_nr_time_hl(const srslte_pdsch_time_ra_t* hl_ra_cfg, srslte_sch_grant_nr_t* grant)
static void ra_dl_nr_time_hl(const srslte_sch_time_ra_t* hl_ra_cfg, srslte_sch_grant_nr_t* grant)
{
// Compute S and L from SLIV from higher layers
compute_s_and_l(SRSLTE_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L);
ra_helper_compute_s_and_l(SRSLTE_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L);
grant->k0 = hl_ra_cfg->k0;
grant->k0 = hl_ra_cfg->k;
grant->mapping = hl_ra_cfg->mapping_type;
}
int srslte_ra_dl_nr_time(const srslte_pdsch_cfg_nr_t* cfg,
int srslte_ra_dl_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
@ -161,8 +147,8 @@ int srslte_ra_dl_nr_time(const srslte_pdsch_cfg_nr_t* cfg,
} else if ((rnti_type == srslte_rnti_type_ra || rnti_type == srslte_rnti_type_tc) &&
ss_type == srslte_search_space_type_common_1) {
// Row 3
if (cfg->nof_common_pdsch_time_ra > 0) {
srslte_ra_dl_nr_time_hl(&cfg->common_pdsch_time_ra[m], grant);
if (cfg->nof_common_time_ra > 0) {
ra_dl_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
// Note: Only Default A is supported, which corresponds SS/PBCH block and coreset mux pattern 1
srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
@ -174,8 +160,8 @@ int srslte_ra_dl_nr_time(const srslte_pdsch_cfg_nr_t* cfg,
rnti_type == srslte_rnti_type_cs) &&
SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id == 0) {
// Row 5
if (cfg->nof_common_pdsch_time_ra > 0) {
srslte_ra_dl_nr_time_hl(&cfg->common_pdsch_time_ra[m], grant);
if (cfg->nof_common_time_ra > 0) {
ra_dl_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
@ -183,10 +169,10 @@ int srslte_ra_dl_nr_time(const srslte_pdsch_cfg_nr_t* cfg,
rnti_type == srslte_rnti_type_cs) &&
((SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id != 0) || ss_type == srslte_search_space_type_ue)) {
// Row 6
if (cfg->nof_pdsch_time_ra > 0) {
srslte_ra_dl_nr_time_hl(&cfg->pdsch_time_ra[m], grant);
} else if (cfg->nof_common_pdsch_time_ra > 0) {
srslte_ra_dl_nr_time_hl(&cfg->common_pdsch_time_ra[m], grant);
if (cfg->nof_dedicated_time_ra > 0) {
ra_dl_nr_time_hl(&cfg->dedicated_time_ra[m], grant);
} else if (cfg->nof_common_time_ra > 0) {
ra_dl_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
@ -240,7 +226,7 @@ uint32_t srslte_ra_dl_nr_type0_P(uint32_t bwp_size, bool config_is_1)
}
static int ra_freq_type0(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant)
{
@ -268,44 +254,11 @@ static int ra_freq_type0(const srslte_carrier_nr_t* carrier,
return 0;
}
static int
ra_freq_type1(const srslte_carrier_nr_t* carrier, const srslte_dci_dl_nr_t* dci_dl, srslte_sch_grant_nr_t* grant)
{
uint32_t riv = dci_dl->freq_domain_assigment;
uint32_t N_bwp_size = carrier->nof_prb;
uint32_t start = 0;
uint32_t len = 0;
compute_s_and_l(N_bwp_size, riv, &start, &len);
if (start + len > N_bwp_size) {
ERROR("RIV 0x%x for BWP size %d resulted in freq=%d:%d\n", riv, N_bwp_size, start, len);
return SRSLTE_ERROR;
}
for (uint32_t i = 0; i < start; i++) {
grant->prb_idx[i] = false;
}
for (uint32_t i = start; i < start + len; i++) {
grant->prb_idx[i] = true;
}
for (uint32_t i = start + len; i < SRSLTE_MAX_PRB_NR; i++) {
grant->prb_idx[i] = false;
}
grant->nof_prb = len;
return SRSLTE_SUCCESS;
}
int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL || dci_dl == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
@ -313,7 +266,7 @@ int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
// RA scheme
if (dci_dl->format == srslte_dci_format_nr_1_0) {
// when the scheduling grant is received with DCI format 1_0 , then downlink resource allocation type 1 is used.
return ra_freq_type1(carrier, dci_dl, grant);
return ra_helper_freq_type1(carrier->nof_prb, dci_dl->freq_domain_assigment, grant);
}
ra_freq_type0(carrier, cfg, dci_dl, grant);

@ -0,0 +1,59 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_RA_HELPER_H
#define SRSLTE_RA_HELPER_H
#include "srslte/phy/utils/debug.h"
#include <stdint.h>
static inline void ra_helper_compute_s_and_l(uint32_t N, uint32_t v, uint32_t* S, uint32_t* L)
{
uint32_t low = v % N;
uint32_t high = v / N;
if (high + 1 + low <= N) {
*S = low;
*L = high + 1;
} else {
*S = N - 1 - low;
*L = N - high + 1;
}
}
static int ra_helper_freq_type1(uint32_t N_bwp_size, uint32_t riv, srslte_sch_grant_nr_t* grant)
{
uint32_t start = 0;
uint32_t len = 0;
ra_helper_compute_s_and_l(N_bwp_size, riv, &start, &len);
if (start + len > N_bwp_size) {
ERROR("RIV 0x%x for BWP size %d resulted in freq=%d:%d\n", riv, N_bwp_size, start, len);
return SRSLTE_ERROR;
}
for (uint32_t i = 0; i < start; i++) {
grant->prb_idx[i] = false;
}
for (uint32_t i = start; i < start + len; i++) {
grant->prb_idx[i] = true;
}
for (uint32_t i = start + len; i < SRSLTE_MAX_PRB_NR; i++) {
grant->prb_idx[i] = false;
}
grant->nof_prb = len;
return SRSLTE_SUCCESS;
}
#endif // SRSLTE_RA_HELPER_H

@ -13,6 +13,7 @@
#include "srslte/phy/phch/ra_nr.h"
#include "srslte/phy/phch/pdsch_nr.h"
#include "srslte/phy/phch/ra_dl_nr.h"
#include "srslte/phy/phch/ra_ul_nr.h"
#include "srslte/phy/utils/debug.h"
typedef struct {
@ -215,7 +216,6 @@ static ra_nr_table_t ra_nr_select_table(srslte_mcs_table_t mcs_table,
srslte_search_space_type_t search_space_type,
srslte_rnti_type_t rnti_type)
{
// Check if it is a PUSCH transmission
if (dci_format == srslte_dci_format_nr_0_0 || dci_format == srslte_dci_format_nr_0_1 ||
dci_format == srslte_dci_format_nr_rar || dci_format == srslte_dci_format_nr_cg) {
@ -455,16 +455,15 @@ int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg,
return SRSLTE_SUCCESS;
}
static int ra_dl_dmrs(const srslte_pdsch_cfg_nr_t* pdsch_hl_cfg,
static int ra_dl_dmrs(const srslte_sch_hl_cfg_nr_t* pdsch_hl_cfg,
srslte_sch_grant_nr_t* pdsch_grant,
srslte_dmrs_sch_cfg_t* dmrs_cfg)
{
const bool dedicated_dmrs_present = (pdsch_grant->mapping == srslte_sch_mapping_type_A)
? pdsch_hl_cfg->dmrs_typeA_present
: pdsch_hl_cfg->dmrs_typeB_present;
? pdsch_hl_cfg->dmrs_typeA.present
: pdsch_hl_cfg->dmrs_typeB.present;
if (pdsch_grant->dci_format == srslte_dci_format_nr_1_0 || !dedicated_dmrs_present) {
if (pdsch_grant->mapping == srslte_sch_mapping_type_A) {
// Absent default values are defined is TS 38.331 - DMRS-DownlinkConfig
dmrs_cfg->additional_pos = srslte_dmrs_sch_add_pos_2;
@ -491,7 +490,7 @@ static int ra_dl_dmrs(const srslte_pdsch_cfg_nr_t* pdsch_hl_cfg,
}
int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* pdsch_hl_cfg,
const srslte_sch_hl_cfg_nr_t* pdsch_hl_cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_cfg_nr_t* pdsch_cfg,
srslte_sch_grant_nr_t* pdsch_grant)
@ -535,3 +534,49 @@ int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
return SRSLTE_SUCCESS;
}
int srslte_ra_ul_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_sch_hl_cfg_nr_t* pusch_hl_cfg,
const srslte_dci_ul_nr_t* dci_ul,
srslte_sch_cfg_nr_t* pusch_cfg,
srslte_sch_grant_nr_t* pusch_grant)
{
// 5.2.1.1 Resource allocation in time domain
if (srslte_ra_dl_nr_time(pusch_hl_cfg,
dci_ul->rnti_type,
dci_ul->search_space,
dci_ul->coreset_id,
dci_ul->time_domain_assigment,
pusch_grant) < SRSLTE_SUCCESS) {
ERROR("Error computing time domain resource allocation\n");
return SRSLTE_ERROR;
}
// 5.1.2.2 Resource allocation in frequency domain
if (srslte_ra_ul_nr_freq(carrier, pusch_hl_cfg, dci_ul, pusch_grant) < SRSLTE_SUCCESS) {
ERROR("Error computing frequency domain resource allocation\n");
return SRSLTE_ERROR;
}
// 5.1.2.3 Physical resource block (PRB) bundling
// ...
pusch_grant->nof_layers = 1;
pusch_grant->dci_format = dci_ul->format;
pusch_grant->rnti = dci_ul->rnti;
pusch_grant->rnti_type = dci_ul->rnti_type;
// 5.1.6.2 DM-RS reception procedure
if (ra_dl_dmrs(pusch_hl_cfg, pusch_grant, &pusch_cfg->dmrs) < SRSLTE_SUCCESS) {
ERROR("Error selecting DMRS configuration");
return SRSLTE_ERROR;
}
// 5.1.3 Modulation order, target code rate, redundancy version and transport block size determination
if (srslte_ra_nr_fill_tb(pusch_cfg, pusch_grant, dci_ul->mcs, &pusch_grant->tb[0]) < SRSLTE_SUCCESS) {
ERROR("Error filing tb\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}

@ -11,10 +11,211 @@
*/
#include "srslte/phy/phch/ra_ul_nr.h"
#include "ra_helper.h"
#include "srslte/phy/ch_estimation/dmrs_pucch.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/utils/debug.h"
typedef struct {
srslte_sch_mapping_type_t mapping;
uint32_t K2;
uint32_t S;
uint32_t L;
} ue_ra_time_resource_t;
static const ue_ra_time_resource_t ue_ul_default_A_lut[16] = {{srslte_sch_mapping_type_A, 0, 0, 14},
{srslte_sch_mapping_type_A, 0, 0, 12},
{srslte_sch_mapping_type_A, 0, 0, 10},
{srslte_sch_mapping_type_B, 0, 2, 10},
{srslte_sch_mapping_type_B, 0, 4, 10},
{srslte_sch_mapping_type_B, 0, 4, 8},
{srslte_sch_mapping_type_B, 0, 4, 6},
{srslte_sch_mapping_type_A, 1, 0, 14},
{srslte_sch_mapping_type_A, 1, 0, 12},
{srslte_sch_mapping_type_A, 1, 0, 10},
{srslte_sch_mapping_type_A, 2, 0, 14},
{srslte_sch_mapping_type_A, 2, 0, 12},
{srslte_sch_mapping_type_A, 2, 0, 10},
{srslte_sch_mapping_type_B, 0, 8, 6},
{srslte_sch_mapping_type_A, 3, 0, 14},
{srslte_sch_mapping_type_A, 3, 0, 10}};
int srslte_ra_ul_nr_pdsch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant)
{
uint32_t j[4] = {1, 1, 2, 3};
if (grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (scs_cfg > 4) {
ERROR("Invalid numerology (%d)", scs_cfg);
return SRSLTE_ERROR;
}
if (m >= 16) {
ERROR("m (%d) is out-of-range", m);
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Select mapping
grant->mapping = ue_ul_default_A_lut[m].mapping;
grant->k2 = ue_ul_default_A_lut[m].K2 + j[scs_cfg];
grant->S = ue_ul_default_A_lut[m].S;
grant->L = ue_ul_default_A_lut[m].L;
return SRSLTE_SUCCESS;
}
static void ra_ul_nr_time_hl(const srslte_sch_time_ra_t* hl_ra_cfg, srslte_sch_grant_nr_t* grant)
{
// Compute S and L from SLIV from higher layers
ra_helper_compute_s_and_l(SRSLTE_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L);
grant->k2 = hl_ra_cfg->k;
grant->mapping = hl_ra_cfg->mapping_type;
}
// Validate S and L combination for TypeA time domain resource allocation
static bool check_time_ra_typeA(uint32_t* S, uint32_t* L)
{
// Check values using Table 5.1.2.1-1
if (*S != 0) {
ERROR("S (%d) is out-of-range {0}", *S);
return false;
}
if (*L < 4 || *L > 14) {
ERROR("L (%d) is out-of-range {4,...,14}", *L);
return false;
}
uint32_t sum = *S + *L;
if (sum < 4) {
ERROR("The sum of S (%d) and L (%d) is lower than 4", *S, *L);
return false;
}
if (sum > 14) {
ERROR("The sum of S (%d) and L (%d) is greater than 14", *S, *L);
return false;
}
return true;
}
static bool check_time_ra_typeB(uint32_t* S, uint32_t* L)
{
ERROR("Not implemented");
return false;
}
bool srslte_ra_ul_nr_time_validate(srslte_sch_grant_nr_t* grant)
{
if (grant->mapping == srslte_sch_mapping_type_A) {
return check_time_ra_typeA(&grant->S, &grant->L);
}
return check_time_ra_typeB(&grant->S, &grant->L);
}
int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (m >= SRSLTE_MAX_NOF_DL_ALLOCATION) {
ERROR("m (%d) is out-of-range", m);
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Determine which PUSCH Time domain RA configuration to apply (TS 38.214 Table 6.1.2.1.1-1:)
if (ss_type == srslte_search_space_rar) {
// Row 1
if (cfg->nof_common_time_ra == 0) {
srslte_ra_ul_nr_pdsch_time_resource_default_A(cfg->scs_cfg, m, grant);
} else if (m < SRSLTE_MAX_NOF_DL_ALLOCATION) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
}
} else if ((rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_mcs_c ||
rnti_type == srslte_rnti_type_tc || rnti_type == srslte_rnti_type_cs) &&
SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id == 0) {
// Row 2
if (cfg->nof_common_time_ra == 0) {
srslte_ra_ul_nr_pdsch_time_resource_default_A(cfg->scs_cfg, m, grant);
} else if (m < SRSLTE_MAX_NOF_DL_ALLOCATION) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
}
} else if ((rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_mcs_c ||
rnti_type == srslte_rnti_type_tc || rnti_type == srslte_rnti_type_cs ||
rnti_type == srslte_rnti_type_sp_csi) &&
((SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id != 0) || ss_type == srslte_search_space_type_ue)) {
// Row 3
if (cfg->nof_dedicated_time_ra > 0) {
ra_ul_nr_time_hl(&cfg->dedicated_time_ra[m], grant);
} else if (cfg->nof_common_time_ra > 0) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
srslte_ra_ul_nr_pdsch_time_resource_default_A(cfg->scs_cfg, m, grant);
}
} else {
ERROR("Unhandled case");
}
// Table 6.1.2.1.1-5 defines the additional subcarrier spacing specific slot delay value for the first transmission of
// PUSCH scheduled by the RAR. When the UE transmits a PUSCH scheduled by RAR, the Δ value specific to the PUSCH
// subcarrier spacing μ PUSCH is applied in addition to the K 2 value.
if (ss_type == srslte_search_space_rar) {
uint32_t delta[4] = {2, 3, 4, 6};
if (cfg->scs_cfg <= 4) {
ERROR("Invalid numerology");
return SRSLTE_ERROR;
}
grant->k2 += delta[cfg->scs_cfg];
}
// Validate S and L parameters
if (!srslte_ra_ul_nr_time_validate(grant)) {
ERROR("Invalid Time RA S=%d; L=%d; m=%d", grant->S, grant->L, m);
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
/* According to TS 38.214 V15.10.0 6.2.2 UE DM-RS transmission procedure:
* For PUSCH scheduled by DCI format 0_0 or by activation DCI format 0_0 with CRC scrambled by CS-RNTI, the UE
* shall assume the number of DM-RS CDM groups without data is 1 which corresponds to CDM group 0 for the case of
* PUSCH with allocation duration of 2 or less OFDM symbols with transform precoding disabled, the UE shall assume
* that the number of DM-RS CDM groups without data is 3 which corresponds to CDM group {0,1,2} for the case of PUSCH
* scheduled by activation DCI format 0_0 and the dmrs-Type in cg-DMRS-Configuration equal to 'type2' and the PUSCH
* allocation duration being more than 2 OFDM symbols, and the UE shall assume that the number of DM-RS CDM groups
* without data is 2 which corresponds to CDM group {0,1} for all other cases.
*/
if (grant->L <= 2 && !cfg->enable_transform_precoder) {
grant->nof_dmrs_cdm_groups_without_data = 1;
// } else if (grant->L > 2 && cfg->dmrs_cg.type == srslte_dmrs_sch_type_2){
// grant->nof_dmrs_cdm_groups_without_data = 3;
} else {
grant->nof_dmrs_cdm_groups_without_data = 2;
}
return SRSLTE_SUCCESS;
}
#define RA_UL_PUCCH_CODE_RATE_N 8
#define RA_UL_PUCCH_CODE_RATE_RESERVED NAN
@ -25,7 +226,7 @@ static const double ra_ul_pucch_code_rate_table[RA_UL_PUCCH_CODE_RATE_N] =
static double ra_ul_nr_pucch_code_rate_r(const srslte_pucch_nr_resource_t* resource)
{
if (resource->max_code_rate >= RA_UL_PUCCH_CODE_RATE_RESERVED) {
ERROR("Invalid code rate\n");
ERROR("Invalid code rate");
return RA_UL_PUCCH_CODE_RATE_RESERVED;
}
@ -42,7 +243,7 @@ static double ra_ul_nr_pucch_code_rate_r(const srslte_pucch_nr_resource_t* resou
// case SRSLTE_PUCCH_NR_FORMAT_4:
// return SRSLTE_PUCCH_NR_FORMAT4_NPRB;
// default:
// ERROR("Invalid case\n");
// ERROR("Invalid case");
// break;
// }
// return SRSLTE_ERROR;
@ -59,7 +260,7 @@ static int ra_ul_nr_pucch_nre(const srslte_pucch_nr_resource_t* resource)
case SRSLTE_PUCCH_NR_FORMAT_4:
return SRSLTE_NRE / resource->occ_lenth;
default:
ERROR("Invalid case\n");
ERROR("Invalid case");
break;
}
return SRSLTE_ERROR;
@ -84,7 +285,7 @@ static int ra_ul_nr_pucch_nsymb(const srslte_pucch_nr_resource_t* resource)
return (int)resource->nof_symbols - nsymb_dmrs;
}
default:
ERROR("Invalid case\n");
ERROR("Invalid case");
break;
}
return SRSLTE_ERROR;
@ -100,7 +301,7 @@ static int ra_ul_nr_pucch_qm(const srslte_pucch_nr_resource_t* resource)
case SRSLTE_PUCCH_NR_FORMAT_4:
return resource->enable_pi_bpsk ? 1 : 2;
default:
ERROR("Invalid case\n");
ERROR("Invalid case");
break;
}
return SRSLTE_ERROR;
@ -116,28 +317,28 @@ int srslte_ra_ul_nr_pucch_format_2_3_min_prb(const srslte_pucch_nr_resource_t* r
// Get maximum allowed code rate
double r = ra_ul_nr_pucch_code_rate_r(resource);
if (!isnormal(r)) {
ERROR("Invalid coderate %f\n", r);
ERROR("Invalid coderate %f", r);
return SRSLTE_ERROR;
}
// Get number of RE/PRB
int nre = ra_ul_nr_pucch_nre(resource);
if (nre < SRSLTE_SUCCESS) {
ERROR("Getting nre\n");
ERROR("Getting nre");
return SRSLTE_ERROR;
}
// Get number of symbols
int nsymb = ra_ul_nr_pucch_nsymb(resource);
if (nsymb < SRSLTE_SUCCESS) {
ERROR("Getting nsymb\n");
ERROR("Getting nsymb");
return SRSLTE_ERROR;
}
// Get modulation order
int qm = ra_ul_nr_pucch_qm(resource);
if (qm < SRSLTE_SUCCESS) {
ERROR("Getting qm\n");
ERROR("Getting qm");
return SRSLTE_ERROR;
}
@ -156,3 +357,22 @@ int srslte_ra_ul_nr_pucch_format_2_3_min_prb(const srslte_pucch_nr_resource_t* r
// Return the minimum
return (int)ceil(O_total / nof_bits_rb);
}
int srslte_ra_ul_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_dci_ul_nr_t* dci_ul,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL || dci_ul == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// RA scheme
if (dci_ul->format == srslte_dci_format_nr_0_0) {
// when the scheduling grant is received with DCI format 1_0 , then downlink resource allocation type 1 is used.
return ra_helper_freq_type1(carrier->nof_prb, dci_ul->freq_domain_assigment, grant);
}
ERROR("Only DCI Format 0_0 is supported");
return SRSLTE_ERROR;
}

@ -12,7 +12,7 @@
#include "srslte/phy/phch/pusch_nr.h"
#include "srslte/phy/phch/ra_nr.h"
#include "srslte/phy/ue/ue_ul_nr_data.h"
#include "srslte/phy/phch/ra_ul_nr.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/random.h"
#include "srslte/phy/utils/vector.h"
@ -152,13 +152,13 @@ int main(int argc, char** argv)
}
// Use grant default A time resources with m=0
if (srslte_ue_ul_nr_pdsch_time_resource_default_A(0, &pusch_grant) < SRSLTE_SUCCESS) {
if (srslte_ra_ul_nr_pdsch_time_resource_default_A(carrier.numerology, 0, &pusch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
goto clean_exit;
}
// Load number of DMRS CDM groups without data
if (srslte_ue_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(&pusch_cfg, &pusch_grant) < SRSLTE_SUCCESS) {
if (srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(&pusch_cfg, &pusch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading number of DMRS CDM groups without data\n");
goto clean_exit;
}
@ -188,7 +188,6 @@ int main(int argc, char** argv)
for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) {
for (mcs = mcs_start; mcs < mcs_end; mcs++) {
for (uint32_t n = 0; n < SRSLTE_MAX_PRB_NR; n++) {
pusch_grant.prb_idx[n] = (n < n_prb);
}

@ -0,0 +1,13 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/phy/ue/ue_ul_nr.h"
#include "srslte/phy/utils/debug.h"

@ -1,84 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/phy/ue/ue_ul_nr_data.h"
#include "srslte/phy/utils/debug.h"
typedef struct {
srslte_sch_mapping_type_t mapping;
uint32_t K2;
uint32_t S;
uint32_t L;
} ue_ul_time_resource_t;
static const ue_ul_time_resource_t ue_ul_default_A_lut[16] = {{srslte_sch_mapping_type_A, 0, 0, 14},
{srslte_sch_mapping_type_A, 0, 0, 12},
{srslte_sch_mapping_type_A, 0, 0, 10},
{srslte_sch_mapping_type_B, 0, 2, 10},
{srslte_sch_mapping_type_B, 0, 4, 10},
{srslte_sch_mapping_type_B, 0, 4, 8},
{srslte_sch_mapping_type_B, 0, 4, 6},
{srslte_sch_mapping_type_A, 1, 0, 14},
{srslte_sch_mapping_type_A, 1, 0, 12},
{srslte_sch_mapping_type_A, 1, 0, 10},
{srslte_sch_mapping_type_A, 2, 0, 14},
{srslte_sch_mapping_type_A, 2, 0, 12},
{srslte_sch_mapping_type_A, 2, 0, 10},
{srslte_sch_mapping_type_B, 0, 8, 6},
{srslte_sch_mapping_type_A, 3, 0, 14},
{srslte_sch_mapping_type_A, 3, 0, 10}};
int srslte_ue_ul_nr_pdsch_time_resource_default_A(uint32_t m, srslte_sch_grant_nr_t* grant)
{
if (grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (m >= 16) {
ERROR("m (%d) is out-of-range\n", m);
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Select mapping
grant->mapping = ue_ul_default_A_lut[m].mapping;
grant->k2 = ue_ul_default_A_lut[m].K2;
grant->S = ue_ul_default_A_lut[m].S;
grant->L = ue_ul_default_A_lut[m].L;
return SRSLTE_SUCCESS;
}
int srslte_ue_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
/* According to TS 38.214 V15.10.0 6.2.2 UE DM-RS transmission procedure:
* For PUSCH scheduled by DCI format 0_0 or by activation DCI format 0_0 with CRC scrambled by CS-RNTI, the UE
* shall assume the number of DM-RS CDM groups without data is 1 which corresponds to CDM group 0 for the case of
* PUSCH with allocation duration of 2 or less OFDM symbols with transform precoding disabled, the UE shall assume
* that the number of DM-RS CDM groups without data is 3 which corresponds to CDM group {0,1,2} for the case of PUSCH
* scheduled by activation DCI format 0_0 and the dmrs-Type in cg-DMRS-Configuration equal to 'type2' and the PUSCH
* allocation duration being more than 2 OFDM symbols, and the UE shall assume that the number of DM-RS CDM groups
* without data is 2 which corresponds to CDM group {0,1} for all other cases.
*/
if (grant->L <= 2 && !cfg->enable_transform_precoder) {
grant->nof_dmrs_cdm_groups_without_data = 1;
// } else if (grant->L > 2 && cfg->dmrs_cg.type == srslte_dmrs_sch_type_2){
// grant->nof_dmrs_cdm_groups_without_data = 3;
} else {
grant->nof_dmrs_cdm_groups_without_data = 2;
}
return SRSLTE_SUCCESS;
}

@ -29,7 +29,7 @@ typedef struct {
} phy_nr_args_t;
typedef struct {
srslte_pdsch_cfg_nr_t pdsch;
srslte_sch_hl_cfg_nr_t pdsch;
} phy_nr_cfg_t;
class phy_nr_state

@ -121,7 +121,7 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui
for (uint32_t i = 0; i < nof_grants; i++) {
// Get PHY config for UE
// ...
srslte_pdsch_cfg_nr_t pdsch_hl_cfg = {};
srslte_sch_hl_cfg_nr_t pdsch_hl_cfg = {};
srslte_sch_cfg_nr_t pdsch_cfg = {};
// Compute DL grant

@ -29,7 +29,7 @@ typedef struct {
} phy_nr_args_t;
typedef struct {
srslte_pdsch_cfg_nr_t pdsch;
srslte_sch_hl_cfg_nr_t pdsch;
srslte_prach_cfg_t prach;
srslte_ue_dl_nr_cfg_t pdcch;
} phy_nr_cfg_t;
@ -128,11 +128,11 @@ public:
// PDSCH-TimeDomainResourceAllocation
// mappingType: typeA (0)
// startSymbolAndLength: 57
cfg.pdsch.common_pdsch_time_ra[0].mapping_type = srslte_sch_mapping_type_A;
cfg.pdsch.common_pdsch_time_ra[0].sliv = 40;
cfg.pdsch.common_pdsch_time_ra[1].mapping_type = srslte_sch_mapping_type_A;
cfg.pdsch.common_pdsch_time_ra[1].sliv = 57;
cfg.pdsch.nof_common_pdsch_time_ra = 2;
cfg.pdsch.common_time_ra[0].mapping_type = srslte_sch_mapping_type_A;
cfg.pdsch.common_time_ra[0].sliv = 40;
cfg.pdsch.common_time_ra[1].mapping_type = srslte_sch_mapping_type_A;
cfg.pdsch.common_time_ra[1].sliv = 57;
cfg.pdsch.nof_common_time_ra = 2;
}
};
} // namespace nr

@ -96,7 +96,7 @@ uint32_t cc_worker::get_buffer_len()
bool cc_worker::work_dl()
{
srslte_pdsch_cfg_nr_t pdsch_hl_cfg = phy->cfg.pdsch;
srslte_sch_hl_cfg_nr_t pdsch_hl_cfg = phy->cfg.pdsch;
// Run FFT
srslte_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg);
@ -144,7 +144,7 @@ bool cc_worker::work_dl()
// Log found DCI
if (logger.info.enabled()) {
std::array<char, 512> str;
srslte_dci_nr_to_str(dci_dl, str.data(), str.size());
srslte_dci_dl_nr_to_str(dci_dl, str.data(), str.size());
logger.info("PDCCH: cc=%d, %s", cc_idx, str.data());
}

Loading…
Cancel
Save