mirror of https://github.com/pvnis/srsRAN_4G.git
Merge branch 'next' into agpl_next
# Conflicts: # lib/include/srsran/interfaces/rrc_nr_interface_types.h # lib/include/srsran/phy/enb/enb_dl_nr.h # test/phy/nr_dl_flood.ccmaster
commit
516951c41c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,87 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 SRSRAN_NAS_5G_UTILS_H
|
||||
#define SRSRAN_NAS_5G_UTILS_H
|
||||
|
||||
#include "srsran/asn1/asn1_utils.h"
|
||||
#include "srsran/common/byte_buffer.h"
|
||||
#include "srsran/config.h"
|
||||
|
||||
using namespace asn1;
|
||||
namespace srsran {
|
||||
namespace nas_5g {
|
||||
|
||||
struct ecies_scheme_profile_a_out {
|
||||
uint8_t ecc_ephemeral_key[33];
|
||||
std::vector<uint8_t> ciphertext;
|
||||
uint8_t mac_tag[8];
|
||||
};
|
||||
|
||||
struct ecies_scheme_profile_b_out {
|
||||
uint8_t ecc_ephemeral_key[32];
|
||||
std::vector<uint8_t> ciphertext;
|
||||
uint8_t mac_tag[8];
|
||||
};
|
||||
|
||||
template <typename Enum, int bl>
|
||||
SRSASN_CODE unpack_enum(asn1::cbit_ref& bref, Enum* e)
|
||||
{
|
||||
uint32_t tmp = {};
|
||||
HANDLE_CODE(bref.unpack(tmp, bl));
|
||||
*e = static_cast<Enum>(tmp);
|
||||
return SRSASN_SUCCESS;
|
||||
}
|
||||
|
||||
template <typename Enum, int bl>
|
||||
SRSASN_CODE pack_enum(asn1::bit_ref& bref, Enum e)
|
||||
{
|
||||
uint32_t tmp = static_cast<uint32_t>(e);
|
||||
HANDLE_CODE(bref.pack(tmp, bl));
|
||||
return SRSASN_SUCCESS;
|
||||
}
|
||||
|
||||
template <class EnumType, uint32_t bit_length_>
|
||||
class nas_enumerated : public EnumType
|
||||
{
|
||||
public:
|
||||
static const uint32_t bit_length = bit_length_;
|
||||
|
||||
nas_enumerated() {}
|
||||
nas_enumerated(typename EnumType::options o) { EnumType::value = o; }
|
||||
SRSASN_CODE pack(asn1::bit_ref& bref) const
|
||||
{
|
||||
uint32_t tmp = static_cast<uint32_t>(EnumType::value);
|
||||
HANDLE_CODE(bref.pack(tmp, bit_length));
|
||||
return SRSASN_SUCCESS;
|
||||
}
|
||||
SRSASN_CODE unpack(asn1::cbit_ref& bref)
|
||||
{
|
||||
uint32_t tmp = {};
|
||||
HANDLE_CODE(bref.unpack(tmp, bit_length));
|
||||
*this = static_cast<typename EnumType::options>(tmp);
|
||||
return SRSASN_SUCCESS;
|
||||
}
|
||||
EnumType& operator=(EnumType v)
|
||||
{
|
||||
EnumType::value = v;
|
||||
return *this;
|
||||
}
|
||||
operator typename EnumType::options() const { return EnumType::value; }
|
||||
};
|
||||
|
||||
SRSASN_CODE unpack_mcc_mnc(uint8_t* mcc_bytes, uint8_t* mnc_bytes, asn1::cbit_ref& bref);
|
||||
SRSASN_CODE pack_mcc_mnc(uint8_t* mcc_bytes, uint8_t* mnc_bytes, asn1::bit_ref& bref);
|
||||
|
||||
} // namespace nas_5g
|
||||
} // namespace srsran
|
||||
#endif // MANUAL_H
|
@ -0,0 +1,154 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 SRSRAN_PHY_CFG_NR_H
|
||||
#define SRSRAN_PHY_CFG_NR_H
|
||||
|
||||
#include "srsran/config.h"
|
||||
#include "srsran/srsran.h"
|
||||
#include <array>
|
||||
#include <srsran/adt/bounded_vector.h>
|
||||
#include <string>
|
||||
|
||||
namespace srsran {
|
||||
|
||||
/***************************
|
||||
* PHY Config
|
||||
**************************/
|
||||
|
||||
struct phy_cfg_nr_t {
|
||||
/**
|
||||
* SSB configuration
|
||||
*/
|
||||
struct ssb_cfg_t {
|
||||
uint32_t periodicity_ms = 0;
|
||||
std::array<bool, SRSRAN_SSB_NOF_CANDIDATES> position_in_burst = {};
|
||||
srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz;
|
||||
};
|
||||
|
||||
srsran_tdd_config_nr_t tdd = {};
|
||||
srsran_sch_hl_cfg_nr_t pdsch = {};
|
||||
srsran_sch_hl_cfg_nr_t pusch = {};
|
||||
srsran_pucch_nr_hl_cfg_t pucch = {};
|
||||
srsran_prach_cfg_t prach = {};
|
||||
srsran_pdcch_cfg_nr_t pdcch = {};
|
||||
srsran_harq_ack_cfg_hl_t harq_ack = {};
|
||||
srsran_csi_hl_cfg_t csi = {};
|
||||
srsran_carrier_nr_t carrier = {};
|
||||
ssb_cfg_t ssb;
|
||||
|
||||
phy_cfg_nr_t() {}
|
||||
|
||||
/**
|
||||
* @brief Computes the DCI configuration for the current UE configuration
|
||||
*/
|
||||
srsran_dci_cfg_nr_t get_dci_cfg() const;
|
||||
|
||||
/**
|
||||
* @brief Asserts that the PDCCH configuration is valid for a given Search Space identifier
|
||||
* @param ss_id Identifier
|
||||
* @return true if the configuration is valid, false otherwise
|
||||
*/
|
||||
bool assert_ss_id(uint32_t ss_id) const;
|
||||
|
||||
/**
|
||||
* @brief Calculates the DCI location candidates for a given search space and aggregation level
|
||||
* @param slot_idx Slot index
|
||||
* @param rnti UE temporal identifier
|
||||
* @param ss_id Search Space identifier
|
||||
* @param L Aggregation level
|
||||
* @param[out] locations DCI candidate locations
|
||||
* @return true if the configuration is valid, false otherwise
|
||||
*/
|
||||
bool get_dci_locations(
|
||||
const uint32_t& slot_idx,
|
||||
const uint16_t& rnti,
|
||||
const uint32_t& ss_id,
|
||||
const uint32_t& L,
|
||||
srsran::bounded_vector<srsran_dci_location_t, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR>& locations) const;
|
||||
|
||||
/**
|
||||
* @brief Selects a valid DCI format for scheduling PDSCH and given Search Space identifier
|
||||
* @param ss_id Identifier
|
||||
* @return A valid DCI format if available, SRSRAN_DCI_FORMAT_NR_COUNT otherwise
|
||||
*/
|
||||
srsran_dci_format_nr_t get_dci_format_pdsch(uint32_t ss_id) const;
|
||||
|
||||
/**
|
||||
* @brief Selects a valid DCI format for scheduling PUSCH and given Search Space identifier
|
||||
* @param ss_id Identifier
|
||||
* @return A valid DCI format if available, SRSRAN_DCI_FORMAT_NR_COUNT otherwise
|
||||
*/
|
||||
srsran_dci_format_nr_t get_dci_format_pusch(uint32_t ss_id) const;
|
||||
|
||||
/**
|
||||
* @brief Fills PDSCH DCI context for C-RNTI using a search space identifier, DCI candidate location and RNTI
|
||||
*/
|
||||
bool get_dci_ctx_pdsch_rnti_c(uint32_t ss_id,
|
||||
const srsran_dci_location_t& location,
|
||||
const uint16_t& rnti,
|
||||
srsran_dci_ctx_t& ctx) const;
|
||||
|
||||
/**
|
||||
* @brief Fills PUSCH DCI context for C-RNTI using a search space identifier, DCI candidate location and RNTI
|
||||
*/
|
||||
bool get_dci_ctx_pusch_rnti_c(uint32_t ss_id,
|
||||
const srsran_dci_location_t& location,
|
||||
const uint16_t& rnti,
|
||||
srsran_dci_ctx_t& ctx) const;
|
||||
|
||||
/**
|
||||
* @brief Get PDSCH configuration for a given slot and DCI
|
||||
*/
|
||||
bool
|
||||
get_pdsch_cfg(const srsran_slot_cfg_t& slot_cfg, const srsran_dci_dl_nr_t& dci, srsran_sch_cfg_nr_t& pdsch_cfg) const;
|
||||
|
||||
/**
|
||||
* @brief Get PUSCH configuration for a given slot and DCI
|
||||
*/
|
||||
bool
|
||||
get_pusch_cfg(const srsran_slot_cfg_t& slot_cfg, const srsran_dci_ul_nr_t& dci, srsran_sch_cfg_nr_t& pdsch_cfg) const;
|
||||
|
||||
/**
|
||||
* @brief Get PDSCH ACK resource for a given PDSCH transmission
|
||||
*/
|
||||
bool get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl, srsran_harq_ack_resource_t& ack_resource) const;
|
||||
|
||||
/**
|
||||
* @brief Compute UCI configuration for the given slot from the pending PDSCH ACK resources, periodic CSI,
|
||||
* periodic SR resources and so on.
|
||||
*/
|
||||
bool get_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
|
||||
const srsran_pdsch_ack_nr_t& pdsch_ack,
|
||||
srsran_uci_cfg_nr_t& uci_cfg) const;
|
||||
|
||||
/**
|
||||
* @brief Compute UCI configuration for PUCCH for the given slot from the pending PDSCH ACK resources, periodic CSI,
|
||||
* periodic SR resources and so on.
|
||||
*/
|
||||
bool get_pucch_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
|
||||
const srsran_uci_cfg_nr_t& uci_cfg,
|
||||
srsran_pucch_nr_common_cfg_t& cfg,
|
||||
srsran_pucch_nr_resource_t& resource) const;
|
||||
|
||||
/**
|
||||
* @brief Compute UCI configuration for PUSCH for the given slot from the pending PDSCH ACK resources, periodic CSI,
|
||||
* periodic SR resources and so on.
|
||||
*/
|
||||
bool get_pusch_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
|
||||
const srsran_uci_cfg_nr_t& uci_cfg,
|
||||
srsran_sch_cfg_nr_t& pusch_cfg) const;
|
||||
};
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_PHY_CFG_NR_H
|
@ -0,0 +1,151 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 SRSRAN_PHY_CFG_NR_DEFAULT_H
|
||||
#define SRSRAN_PHY_CFG_NR_DEFAULT_H
|
||||
|
||||
#include "phy_cfg_nr.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
class phy_cfg_nr_default_t : public phy_cfg_nr_t
|
||||
{
|
||||
public:
|
||||
struct reference_cfg_t {
|
||||
enum {
|
||||
/**
|
||||
* @brief Carrier reference configuration for 10MHz serving cell bandwidth
|
||||
* - BW: 10 MHZ (52 PRB)
|
||||
* - PCI: 500
|
||||
* - SCS: 15 kHz
|
||||
* - SSB: 5ms
|
||||
*/
|
||||
R_CARRIER_CUSTOM_10MHZ = 0,
|
||||
} carrier = R_CARRIER_CUSTOM_10MHZ;
|
||||
|
||||
enum {
|
||||
/**
|
||||
* @brief TDD custom reference 5 slot DL and 5 slot UL
|
||||
*/
|
||||
R_TDD_CUSTOM_6_4 = 0,
|
||||
} tdd = R_TDD_CUSTOM_6_4;
|
||||
|
||||
enum {
|
||||
/**
|
||||
* @brief Carrier reference configuration for 10MHz serving cell bandwidth
|
||||
* - CORESET: all channel, 1 symbol
|
||||
* - Single common Search Space
|
||||
* - 2 possible candidate per aggregation level to allow DL and UL grants simultaneously
|
||||
*/
|
||||
R_PDCCH_CUSTOM_COMMON_SS = 0,
|
||||
} pdcch = R_PDCCH_CUSTOM_COMMON_SS;
|
||||
|
||||
enum {
|
||||
/**
|
||||
* @brief Custom fallback baseline configuration, designed for component testing
|
||||
* - Defined single common PDSCH time allocation starting at symbol index 1 and length 13
|
||||
* - No DMRS dedicated configuration
|
||||
*/
|
||||
R_PDSCH_DEFAULT = 0,
|
||||
} pdsch = R_PDSCH_DEFAULT;
|
||||
|
||||
enum {
|
||||
/**
|
||||
* @brief Custom fallback baseline configuration, designed for component testing
|
||||
* - Single Time resource allocation
|
||||
* - transmission starts at symbol index 0 for 14 symbols
|
||||
* - k is 4 slots
|
||||
* - No DMRS dedicated configuration
|
||||
*/
|
||||
R_PUSCH_DEFAULT = 0,
|
||||
} pusch = R_PUSCH_DEFAULT;
|
||||
|
||||
enum {
|
||||
/**
|
||||
* @brief Custom single PUCCH resource per set
|
||||
* - Format 1 for 1 or 2 bits
|
||||
* - Format 2 for more than 2 bits
|
||||
*/
|
||||
R_PUCCH_CUSTOM_ONE = 0,
|
||||
} pucch = R_PUCCH_CUSTOM_ONE;
|
||||
|
||||
enum {
|
||||
/**
|
||||
* @brief Sets the delay between PDSCH and HARQ feedback timing automatically
|
||||
* - Dynamic HARQ ACK codebook
|
||||
* - Guarantees a minimum delay of 4ms
|
||||
* - Assume 15kHz SCS
|
||||
* - Assume TDD pattern2 is not enabled
|
||||
*/
|
||||
R_HARQ_AUTO = 0,
|
||||
} harq = R_HARQ_AUTO;
|
||||
|
||||
enum {
|
||||
/**
|
||||
* @brief Sets the PRACH configuration to an LTE compatible configuration
|
||||
* - Configuration index 0
|
||||
* - Frequency offset 2 PRB
|
||||
* - Root sequence 2
|
||||
*/
|
||||
R_PRACH_DEFAULT_LTE,
|
||||
} prach = R_PRACH_DEFAULT_LTE;
|
||||
};
|
||||
|
||||
phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Carrier make helper methods
|
||||
*/
|
||||
static void make_carrier_custom_10MHz(srsran_carrier_nr_t& carrier);
|
||||
|
||||
/**
|
||||
* TDD make helper methods
|
||||
*/
|
||||
static void make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd);
|
||||
|
||||
/**
|
||||
* PDCCH make helper methods
|
||||
*/
|
||||
static void make_pdcch_custom_common_ss(srsran_pdcch_cfg_nr_t& pdcch, const srsran_carrier_nr_t& carrier);
|
||||
|
||||
/**
|
||||
* PDSCH make helper methods
|
||||
*/
|
||||
static void make_pdsch_default(srsran_sch_hl_cfg_nr_t& pdsch);
|
||||
|
||||
/**
|
||||
* PUSCH make helper methods
|
||||
*/
|
||||
static void make_pusch_default(srsran_sch_hl_cfg_nr_t& pusch);
|
||||
|
||||
/**
|
||||
* PUCCH make helper methods
|
||||
*/
|
||||
static void make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch);
|
||||
|
||||
/**
|
||||
* HARQ make helper methods
|
||||
*/
|
||||
static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
|
||||
const srsran_carrier_nr_t& carrier,
|
||||
const srsran_tdd_config_nr_t& tdd_cfg);
|
||||
|
||||
/**
|
||||
* PRACH make helper methods
|
||||
*/
|
||||
static void make_prach_default_lte(srsran_prach_cfg_t& prach);
|
||||
};
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_PHY_CFG_NR_DEFAULT_H
|
@ -1,147 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_RRC_NR_INTERFACE_TYPES_H
|
||||
#define SRSRAN_RRC_NR_INTERFACE_TYPES_H
|
||||
|
||||
#include "srsran/config.h"
|
||||
#include "srsran/srsran.h"
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace srsran {
|
||||
|
||||
/***************************
|
||||
* PHY Config
|
||||
**************************/
|
||||
|
||||
struct phy_cfg_nr_t {
|
||||
/**
|
||||
* SSB configuration
|
||||
*/
|
||||
struct ssb_cfg_t {
|
||||
uint32_t periodicity_ms = 0;
|
||||
std::array<bool, SRSRAN_SSB_NOF_CANDIDATES> position_in_burst = {};
|
||||
srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz;
|
||||
};
|
||||
|
||||
srsran_tdd_config_nr_t tdd = {};
|
||||
srsran_sch_hl_cfg_nr_t pdsch = {};
|
||||
srsran_sch_hl_cfg_nr_t pusch = {};
|
||||
srsran_pucch_nr_hl_cfg_t pucch = {};
|
||||
srsran_prach_cfg_t prach = {};
|
||||
srsran_pdcch_cfg_nr_t pdcch = {};
|
||||
srsran_ue_dl_nr_harq_ack_cfg_t harq_ack = {};
|
||||
srsran_csi_hl_cfg_t csi = {};
|
||||
srsran_carrier_nr_t carrier = {};
|
||||
ssb_cfg_t ssb;
|
||||
|
||||
phy_cfg_nr_t() {}
|
||||
|
||||
/**
|
||||
* @param carrier
|
||||
*/
|
||||
srsran_dci_cfg_nr_t get_dci_cfg() const
|
||||
{
|
||||
srsran_dci_cfg_nr_t dci_cfg = {};
|
||||
|
||||
// Assume BWP bandwidth equals full channel bandwidth
|
||||
dci_cfg.coreset0_bw = pdcch.coreset_present[0] ? srsran_coreset_get_bw(&pdcch.coreset[0]) : 0;
|
||||
dci_cfg.bwp_dl_initial_bw = carrier.nof_prb;
|
||||
dci_cfg.bwp_dl_active_bw = carrier.nof_prb;
|
||||
dci_cfg.bwp_ul_initial_bw = carrier.nof_prb;
|
||||
dci_cfg.bwp_ul_active_bw = carrier.nof_prb;
|
||||
|
||||
// Iterate over all SS to select monitoring options
|
||||
for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; i++) {
|
||||
// Skip not configured SS
|
||||
if (not pdcch.search_space_present[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Iterate all configured formats
|
||||
for (uint32_t j = 0; j < pdcch.search_space[i].nof_formats; j++) {
|
||||
if (pdcch.search_space[i].type == srsran_search_space_type_common_3 &&
|
||||
pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) {
|
||||
dci_cfg.monitor_common_0_0 = true;
|
||||
} else if (pdcch.search_space[i].type == srsran_search_space_type_ue &&
|
||||
pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) {
|
||||
dci_cfg.monitor_0_0_and_1_0 = true;
|
||||
} else if (pdcch.search_space[i].type == srsran_search_space_type_ue &&
|
||||
pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_1) {
|
||||
dci_cfg.monitor_0_1_and_1_1 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set PUSCH parameters
|
||||
dci_cfg.enable_sul = false;
|
||||
dci_cfg.enable_hopping = false;
|
||||
|
||||
// Set Format 0_1 and 1_1 parameters
|
||||
dci_cfg.carrier_indicator_size = 0;
|
||||
dci_cfg.harq_ack_codebok = harq_ack.harq_ack_codebook;
|
||||
dci_cfg.nof_rb_groups = 0;
|
||||
|
||||
// Format 0_1 specific configuration (for PUSCH only)
|
||||
dci_cfg.nof_ul_bwp = 0;
|
||||
dci_cfg.nof_ul_time_res = (pusch.nof_dedicated_time_ra > 0)
|
||||
? pusch.nof_dedicated_time_ra
|
||||
: (pusch.nof_common_time_ra > 0) ? pusch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA;
|
||||
dci_cfg.nof_srs = 1;
|
||||
dci_cfg.nof_ul_layers = 1;
|
||||
dci_cfg.pusch_nof_cbg = 0;
|
||||
dci_cfg.report_trigger_size = 0;
|
||||
dci_cfg.enable_transform_precoding = false;
|
||||
dci_cfg.dynamic_dual_harq_ack_codebook = false;
|
||||
dci_cfg.pusch_tx_config_non_codebook = false;
|
||||
dci_cfg.pusch_ptrs = false;
|
||||
dci_cfg.pusch_dynamic_betas = false;
|
||||
dci_cfg.pusch_alloc_type = pusch.alloc;
|
||||
dci_cfg.pusch_dmrs_type = pusch.dmrs_type;
|
||||
dci_cfg.pusch_dmrs_max_len = pusch.dmrs_max_length;
|
||||
|
||||
// Format 1_1 specific configuration (for PDSCH only)
|
||||
dci_cfg.nof_dl_bwp = 0;
|
||||
dci_cfg.nof_dl_time_res = (pdsch.nof_dedicated_time_ra > 0)
|
||||
? pdsch.nof_dedicated_time_ra
|
||||
: (pdsch.nof_common_time_ra > 0) ? pdsch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA;
|
||||
dci_cfg.nof_aperiodic_zp = 0;
|
||||
dci_cfg.pdsch_nof_cbg = 0;
|
||||
dci_cfg.nof_dl_to_ul_ack = harq_ack.nof_dl_data_to_ul_ack;
|
||||
dci_cfg.pdsch_inter_prb_to_prb = false;
|
||||
dci_cfg.pdsch_rm_pattern1 = false;
|
||||
dci_cfg.pdsch_rm_pattern2 = false;
|
||||
dci_cfg.pdsch_2cw = false;
|
||||
dci_cfg.multiple_scell = false;
|
||||
dci_cfg.pdsch_tci = false;
|
||||
dci_cfg.pdsch_cbg_flush = false;
|
||||
dci_cfg.pdsch_dynamic_bundling = false;
|
||||
dci_cfg.pdsch_alloc_type = pdsch.alloc;
|
||||
dci_cfg.pdsch_dmrs_type = pdsch.dmrs_type;
|
||||
dci_cfg.pdsch_dmrs_max_len = pdsch.dmrs_max_length;
|
||||
|
||||
return dci_cfg;
|
||||
};
|
||||
};
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_RRC_NR_INTERFACE_TYPES_H
|
@ -1,91 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_ENB_DL_NR_H
|
||||
#define SRSRAN_ENB_DL_NR_H
|
||||
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
#include "srsran/phy/dft/ofdm.h"
|
||||
#include "srsran/phy/phch/pdcch_cfg_nr.h"
|
||||
#include "srsran/phy/phch/pdcch_nr.h"
|
||||
#include "srsran/phy/phch/pdsch_nr.h"
|
||||
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_pdsch_nr_args_t pdsch;
|
||||
srsran_pdcch_nr_args_t pdcch;
|
||||
uint32_t nof_tx_antennas;
|
||||
uint32_t nof_max_prb;
|
||||
} srsran_enb_dl_nr_args_t;
|
||||
|
||||
typedef struct SRSRAN_API {
|
||||
uint32_t max_prb;
|
||||
uint32_t nof_tx_antennas;
|
||||
srsran_carrier_nr_t carrier;
|
||||
srsran_pdcch_cfg_nr_t pdcch_cfg;
|
||||
|
||||
srsran_ofdm_t fft[SRSRAN_MAX_PORTS];
|
||||
|
||||
cf_t* sf_symbols[SRSRAN_MAX_PORTS];
|
||||
srsran_pdsch_nr_t pdsch;
|
||||
srsran_dmrs_sch_t dmrs;
|
||||
|
||||
srsran_dci_nr_t dci; ///< Stores DCI configuration
|
||||
srsran_pdcch_nr_t pdcch;
|
||||
} srsran_enb_dl_nr_t;
|
||||
|
||||
SRSRAN_API int
|
||||
srsran_enb_dl_nr_init(srsran_enb_dl_nr_t* q, cf_t* output[SRSRAN_MAX_PORTS], const srsran_enb_dl_nr_args_t* args);
|
||||
|
||||
SRSRAN_API int srsran_enb_dl_nr_set_carrier(srsran_enb_dl_nr_t* q, const srsran_carrier_nr_t* carrier);
|
||||
|
||||
SRSRAN_API int srsran_enb_dl_nr_set_pdcch_config(srsran_enb_dl_nr_t* q,
|
||||
const srsran_pdcch_cfg_nr_t* cfg,
|
||||
const srsran_dci_cfg_nr_t* dci_cfg);
|
||||
|
||||
SRSRAN_API void srsran_enb_dl_nr_free(srsran_enb_dl_nr_t* q);
|
||||
|
||||
SRSRAN_API int srsran_enb_dl_nr_base_zero(srsran_enb_dl_nr_t* q);
|
||||
|
||||
SRSRAN_API void srsran_enb_dl_nr_gen_signal(srsran_enb_dl_nr_t* q);
|
||||
|
||||
SRSRAN_API int srsran_enb_dl_nr_pdcch_put_dl(srsran_enb_dl_nr_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_dci_dl_nr_t* dci_dl);
|
||||
|
||||
SRSRAN_API int srsran_enb_dl_nr_pdcch_put_ul(srsran_enb_dl_nr_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_dci_ul_nr_t* dci_ul);
|
||||
|
||||
SRSRAN_API int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q,
|
||||
const srsran_slot_cfg_t* slot,
|
||||
const srsran_sch_cfg_nr_t* cfg,
|
||||
uint8_t* data[SRSRAN_MAX_TB]);
|
||||
|
||||
SRSRAN_API int
|
||||
srsran_enb_dl_nr_pdsch_info(const srsran_enb_dl_nr_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len);
|
||||
|
||||
SRSRAN_API int
|
||||
srsran_enb_dl_nr_pdcch_dl_info(const srsran_enb_dl_nr_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len);
|
||||
|
||||
SRSRAN_API int
|
||||
srsran_enb_dl_nr_pdcch_ul_info(const srsran_enb_dl_nr_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len);
|
||||
|
||||
#endif // SRSRAN_ENB_DL_NR_H
|
@ -0,0 +1,79 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 SRSRAN_GNB_DL_H
|
||||
#define SRSRAN_GNB_DL_H
|
||||
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
#include "srsran/phy/dft/ofdm.h"
|
||||
#include "srsran/phy/phch/pdcch_cfg_nr.h"
|
||||
#include "srsran/phy/phch/pdcch_nr.h"
|
||||
#include "srsran/phy/phch/pdsch_nr.h"
|
||||
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_pdsch_nr_args_t pdsch;
|
||||
srsran_pdcch_nr_args_t pdcch;
|
||||
uint32_t nof_tx_antennas;
|
||||
uint32_t nof_max_prb;
|
||||
} srsran_gnb_dl_args_t;
|
||||
|
||||
typedef struct SRSRAN_API {
|
||||
uint32_t max_prb;
|
||||
uint32_t nof_tx_antennas;
|
||||
srsran_carrier_nr_t carrier;
|
||||
srsran_pdcch_cfg_nr_t pdcch_cfg;
|
||||
|
||||
srsran_ofdm_t fft[SRSRAN_MAX_PORTS];
|
||||
|
||||
cf_t* sf_symbols[SRSRAN_MAX_PORTS];
|
||||
srsran_pdsch_nr_t pdsch;
|
||||
srsran_dmrs_sch_t dmrs;
|
||||
|
||||
srsran_dci_nr_t dci; ///< Stores DCI configuration
|
||||
srsran_pdcch_nr_t pdcch;
|
||||
} srsran_gnb_dl_t;
|
||||
|
||||
SRSRAN_API int srsran_gnb_dl_init(srsran_gnb_dl_t* q, cf_t* output[SRSRAN_MAX_PORTS], const srsran_gnb_dl_args_t* args);
|
||||
|
||||
SRSRAN_API int srsran_gnb_dl_set_carrier(srsran_gnb_dl_t* q, const srsran_carrier_nr_t* carrier);
|
||||
|
||||
SRSRAN_API int srsran_gnb_dl_set_pdcch_config(srsran_gnb_dl_t* q,
|
||||
const srsran_pdcch_cfg_nr_t* cfg,
|
||||
const srsran_dci_cfg_nr_t* dci_cfg);
|
||||
|
||||
SRSRAN_API void srsran_gnb_dl_free(srsran_gnb_dl_t* q);
|
||||
|
||||
SRSRAN_API int srsran_gnb_dl_base_zero(srsran_gnb_dl_t* q);
|
||||
|
||||
SRSRAN_API void srsran_gnb_dl_gen_signal(srsran_gnb_dl_t* q);
|
||||
|
||||
SRSRAN_API int
|
||||
srsran_gnb_dl_pdcch_put_dl(srsran_gnb_dl_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_dl_nr_t* dci_dl);
|
||||
|
||||
SRSRAN_API int
|
||||
srsran_gnb_dl_pdcch_put_ul(srsran_gnb_dl_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_ul_nr_t* dci_ul);
|
||||
|
||||
SRSRAN_API int srsran_gnb_dl_pdsch_put(srsran_gnb_dl_t* q,
|
||||
const srsran_slot_cfg_t* slot,
|
||||
const srsran_sch_cfg_nr_t* cfg,
|
||||
uint8_t* data[SRSRAN_MAX_TB]);
|
||||
|
||||
SRSRAN_API int
|
||||
srsran_gnb_dl_pdsch_info(const srsran_gnb_dl_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len);
|
||||
|
||||
SRSRAN_API int
|
||||
srsran_gnb_dl_pdcch_dl_info(const srsran_gnb_dl_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len);
|
||||
|
||||
SRSRAN_API int
|
||||
srsran_gnb_dl_pdcch_ul_info(const srsran_gnb_dl_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len);
|
||||
|
||||
#endif // SRSRAN_GNB_DL_H
|
@ -0,0 +1,74 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 SRSRAN_GNB_UL_H
|
||||
#define SRSRAN_GNB_UL_H
|
||||
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
#include "srsran/phy/dft/ofdm.h"
|
||||
#include "srsran/phy/phch/pucch_nr.h"
|
||||
#include "srsran/phy/phch/pusch_nr.h"
|
||||
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_pusch_nr_args_t pusch;
|
||||
srsran_pucch_nr_args_t pucch;
|
||||
uint32_t nof_max_prb;
|
||||
} srsran_gnb_ul_args_t;
|
||||
|
||||
typedef struct SRSRAN_API {
|
||||
uint32_t max_prb;
|
||||
srsran_carrier_nr_t carrier;
|
||||
|
||||
srsran_ofdm_t fft;
|
||||
|
||||
cf_t* sf_symbols[SRSRAN_MAX_PORTS];
|
||||
srsran_pusch_nr_t pusch;
|
||||
srsran_pucch_nr_t pucch;
|
||||
srsran_dmrs_sch_t dmrs;
|
||||
srsran_chest_dl_res_t chest_pusch;
|
||||
srsran_chest_ul_res_t chest_pucch;
|
||||
} srsran_gnb_ul_t;
|
||||
|
||||
SRSRAN_API int srsran_gnb_ul_init(srsran_gnb_ul_t* q, cf_t* input, const srsran_gnb_ul_args_t* args);
|
||||
|
||||
SRSRAN_API void srsran_gnb_ul_free(srsran_gnb_ul_t* q);
|
||||
|
||||
SRSRAN_API int srsran_gnb_ul_set_carrier(srsran_gnb_ul_t* q, const srsran_carrier_nr_t* carrier);
|
||||
|
||||
SRSRAN_API int srsran_gnb_ul_fft(srsran_gnb_ul_t* q);
|
||||
|
||||
SRSRAN_API int srsran_gnb_ul_get_pusch(srsran_gnb_ul_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_sch_cfg_nr_t* cfg,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
srsran_pusch_res_nr_t* data);
|
||||
|
||||
SRSRAN_API int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_pucch_nr_common_cfg_t* cfg,
|
||||
const srsran_pucch_nr_resource_t* resource,
|
||||
const srsran_uci_cfg_nr_t* uci_cfg,
|
||||
srsran_uci_value_nr_t* uci_value);
|
||||
|
||||
SRSRAN_API uint32_t srsran_gnb_ul_pucch_info(srsran_gnb_ul_t* q,
|
||||
const srsran_pucch_nr_resource_t* resource,
|
||||
const srsran_uci_data_nr_t* uci_data,
|
||||
char* str,
|
||||
uint32_t str_len);
|
||||
|
||||
SRSRAN_API uint32_t srsran_gnb_ul_pusch_info(srsran_gnb_ul_t* q,
|
||||
const srsran_sch_cfg_nr_t* cfg,
|
||||
const srsran_pusch_res_nr_t* res,
|
||||
char* str,
|
||||
uint32_t str_len);
|
||||
|
||||
#endif // SRSRAN_GNB_UL_H
|
@ -0,0 +1,40 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 SRSRAN_HARQ_ACK_H
|
||||
#define SRSRAN_HARQ_ACK_H
|
||||
|
||||
#include "srsran/phy/phch/dci_nr.h"
|
||||
#include "srsran/phy/phch/harq_ack_cfg.h"
|
||||
#include "srsran/phy/phch/uci_cfg_nr.h"
|
||||
|
||||
SRSRAN_API int srsran_harq_ack_resource(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||
const srsran_dci_dl_nr_t* dci_dl,
|
||||
srsran_harq_ack_resource_t* pdsch_ack_resource);
|
||||
|
||||
SRSRAN_API int srsran_harq_ack_gen_uci_cfg(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||
const srsran_pdsch_ack_nr_t* ack_info,
|
||||
srsran_uci_cfg_nr_t* uci_cfg);
|
||||
|
||||
SRSRAN_API int srsran_harq_ack_pack(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||
const srsran_pdsch_ack_nr_t* ack_info,
|
||||
srsran_uci_data_nr_t* uci_data);
|
||||
|
||||
SRSRAN_API int srsran_harq_ack_unpack(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||
const srsran_uci_data_nr_t* uci_data,
|
||||
srsran_pdsch_ack_nr_t* ack_info);
|
||||
|
||||
SRSRAN_API int srsran_harq_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_harq_ack_m_t* m);
|
||||
|
||||
SRSRAN_API uint32_t srsran_harq_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len);
|
||||
|
||||
#endif // SRSRAN_HARQ_ACK_H
|
@ -0,0 +1,107 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 SRSRAN_HARQ_ACK_CFG_H
|
||||
#define SRSRAN_HARQ_ACK_CFG_H
|
||||
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Maximum number of HARQ ACK feedback bits that can be carried in Uplink Control Information (UCI) message
|
||||
*/
|
||||
#define SRSRAN_HARQ_ACK_MAX_NOF_BITS 360
|
||||
|
||||
/**
|
||||
* @brief Describes a HARQ ACK resource configuration
|
||||
*/
|
||||
typedef struct {
|
||||
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
|
||||
uint32_t pid; ///< HARQ process identifier
|
||||
uint16_t rnti;
|
||||
uint32_t pucch_resource_id;
|
||||
} srsran_harq_ack_resource_t;
|
||||
|
||||
/**
|
||||
* @brief Describes a single PDSCH transmission HARQ ACK feedback
|
||||
*/
|
||||
typedef struct {
|
||||
srsran_harq_ack_resource_t resource;
|
||||
uint8_t value[SRSRAN_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
|
||||
bool dl_bwp_changed; // set to true if PDCCH monitoring occasion m is before an active DL BWP change on serving cell c
|
||||
bool ul_bwp_changed; // set to true if an active UL BWP change on the PCell and an active DL BWP change is not
|
||||
// triggered by a DCI format 1_1 in PDCCH monitoring occasion m
|
||||
bool second_tb_present; // set to true if two TB were detected in the PDCCH monitoring occasion m
|
||||
} srsran_harq_ack_m_t;
|
||||
|
||||
#define SRSRAN_UCI_NR_MAX_M 10
|
||||
|
||||
/**
|
||||
* @brief Describes a collection of PDSCH HARQ ACK feedback for a number of PDSCH transmissions within a component
|
||||
* carrier
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t M;
|
||||
srsran_harq_ack_m_t m[SRSRAN_UCI_NR_MAX_M];
|
||||
} srsran_harq_ack_cc_t;
|
||||
|
||||
/**
|
||||
* @brief Describes a collection of PDSCH HARQ ACK feedback for a number of component carriers
|
||||
*/
|
||||
typedef struct {
|
||||
srsran_harq_ack_cc_t cc[SRSRAN_MAX_CARRIERS];
|
||||
uint32_t nof_cc;
|
||||
bool use_pusch; // Set to true, if UCI bits are carried by PUSCH
|
||||
} srsran_pdsch_ack_nr_t;
|
||||
|
||||
/**
|
||||
* @brief Describes higher layer HARQ ACK feedback for PDSCH configuration
|
||||
*/
|
||||
typedef struct SRSRAN_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
|
||||
srsran_harq_ack_codebook_t 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[SRSRAN_MAX_NOF_DL_DATA_TO_UL];
|
||||
uint32_t nof_dl_data_to_ul_ack;
|
||||
} srsran_harq_ack_cfg_hl_t;
|
||||
|
||||
/**
|
||||
* @brief Describes HARQ ACK bit configuration for UCI encoding/decoding
|
||||
* @note if tb0 and tb1 are false, the HARQ ACK bit is not used
|
||||
* @note if tb0 and tb1 are true, the HARQ ACK feedback are bundled, the actual HARQ ACK feedback bit is the result of
|
||||
* the AND operation
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
bool tb0; ///< Set to true if this ACK bit is mapped into TB index 0
|
||||
bool tb1; ///< Set to true if this ACK bit is mapped into TB index 1
|
||||
uint32_t cc_idx; ///< Component carrier index
|
||||
uint32_t m_idx; ///< M resource index for packing/unpacking
|
||||
uint32_t pid; ///< HARQ process identifier
|
||||
} srsran_harq_ack_bit_t;
|
||||
|
||||
/**
|
||||
* @brief Describes HARQ ACK feedback configuration for UCI encoding/decoding
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_harq_ack_bit_t bits[SRSRAN_HARQ_ACK_MAX_NOF_BITS]; ///< HARQ-ACK feedback bits
|
||||
uint32_t count; ///< Number of ACK bits
|
||||
} srsran_harq_ack_cfg_t;
|
||||
|
||||
#endif // SRSRAN_HARQ_ACK_CFG_H
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,56 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 "srsran/asn1/nas_5g_utils.h"
|
||||
|
||||
#include "srsran/asn1/asn1_utils.h"
|
||||
#include "srsran/common/buffer_pool.h"
|
||||
#include "srsran/common/common.h"
|
||||
#include "srsran/config.h"
|
||||
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
namespace srsran {
|
||||
namespace nas_5g {
|
||||
|
||||
SRSASN_CODE unpack_mcc_mnc(uint8_t* mcc_bytes, uint8_t* mnc_bytes, asn1::cbit_ref& bref)
|
||||
{
|
||||
// MCC digit 2 | MCC digit 1 | octet 5
|
||||
// MNC digit 3 | MCC digit 3 | octet 6
|
||||
// MNC digit 2 | MNC digit 1 | octet 7
|
||||
HANDLE_CODE(bref.unpack(mcc_bytes[1], 4));
|
||||
HANDLE_CODE(bref.unpack(mcc_bytes[0], 4));
|
||||
HANDLE_CODE(bref.unpack(mnc_bytes[2], 4));
|
||||
HANDLE_CODE(bref.unpack(mcc_bytes[2], 4));
|
||||
HANDLE_CODE(bref.unpack(mnc_bytes[1], 4));
|
||||
HANDLE_CODE(bref.unpack(mnc_bytes[0], 4));
|
||||
return SRSASN_SUCCESS;
|
||||
}
|
||||
|
||||
SRSASN_CODE pack_mcc_mnc(uint8_t* mcc_bytes, uint8_t* mnc_bytes, asn1::bit_ref& bref)
|
||||
{
|
||||
// MCC digit 2 | MCC digit 1 | octet 5
|
||||
// MNC digit 3 | MCC digit 3 | octet 6
|
||||
// MNC digit 2 | MNC digit 1 | octet 7
|
||||
HANDLE_CODE(bref.pack(mcc_bytes[1], 4));
|
||||
HANDLE_CODE(bref.pack(mcc_bytes[0], 4));
|
||||
HANDLE_CODE(bref.pack(mnc_bytes[2], 4));
|
||||
HANDLE_CODE(bref.pack(mcc_bytes[2], 4));
|
||||
HANDLE_CODE(bref.pack(mnc_bytes[1], 4));
|
||||
HANDLE_CODE(bref.pack(mnc_bytes[0], 4));
|
||||
return SRSASN_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace nas_5g
|
||||
} // namespace srsran
|
@ -0,0 +1,327 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 "srsran/common/phy_cfg_nr.h"
|
||||
#include "srsran/srsran.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
srsran_dci_cfg_nr_t phy_cfg_nr_t::get_dci_cfg() const
|
||||
|
||||
{
|
||||
srsran_dci_cfg_nr_t dci_cfg = {};
|
||||
|
||||
// Assume BWP bandwidth equals full channel bandwidth
|
||||
dci_cfg.coreset0_bw = pdcch.coreset_present[0] ? srsran_coreset_get_bw(&pdcch.coreset[0]) : 0;
|
||||
dci_cfg.bwp_dl_initial_bw = carrier.nof_prb;
|
||||
dci_cfg.bwp_dl_active_bw = carrier.nof_prb;
|
||||
dci_cfg.bwp_ul_initial_bw = carrier.nof_prb;
|
||||
dci_cfg.bwp_ul_active_bw = carrier.nof_prb;
|
||||
|
||||
// Iterate over all SS to select monitoring options
|
||||
for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; i++) {
|
||||
// Skip not configured SS
|
||||
if (not pdcch.search_space_present[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Iterate all configured formats
|
||||
for (uint32_t j = 0; j < pdcch.search_space[i].nof_formats; j++) {
|
||||
if (pdcch.search_space[i].type == srsran_search_space_type_common_3 &&
|
||||
pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) {
|
||||
dci_cfg.monitor_common_0_0 = true;
|
||||
} else if (pdcch.search_space[i].type == srsran_search_space_type_ue &&
|
||||
pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) {
|
||||
dci_cfg.monitor_0_0_and_1_0 = true;
|
||||
} else if (pdcch.search_space[i].type == srsran_search_space_type_ue &&
|
||||
pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_1) {
|
||||
dci_cfg.monitor_0_1_and_1_1 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set PUSCH parameters
|
||||
dci_cfg.enable_sul = false;
|
||||
dci_cfg.enable_hopping = false;
|
||||
|
||||
// Set Format 0_1 and 1_1 parameters
|
||||
dci_cfg.carrier_indicator_size = 0;
|
||||
dci_cfg.harq_ack_codebok = harq_ack.harq_ack_codebook;
|
||||
dci_cfg.nof_rb_groups = 0;
|
||||
|
||||
// Format 0_1 specific configuration (for PUSCH only)
|
||||
dci_cfg.nof_ul_bwp = 0;
|
||||
dci_cfg.nof_ul_time_res = (pusch.nof_dedicated_time_ra > 0)
|
||||
? pusch.nof_dedicated_time_ra
|
||||
: (pusch.nof_common_time_ra > 0) ? pusch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA;
|
||||
dci_cfg.nof_srs = 1;
|
||||
dci_cfg.nof_ul_layers = 1;
|
||||
dci_cfg.pusch_nof_cbg = 0;
|
||||
dci_cfg.report_trigger_size = 0;
|
||||
dci_cfg.enable_transform_precoding = false;
|
||||
dci_cfg.dynamic_dual_harq_ack_codebook = false;
|
||||
dci_cfg.pusch_tx_config_non_codebook = false;
|
||||
dci_cfg.pusch_ptrs = false;
|
||||
dci_cfg.pusch_dynamic_betas = false;
|
||||
dci_cfg.pusch_alloc_type = pusch.alloc;
|
||||
dci_cfg.pusch_dmrs_type = pusch.dmrs_type;
|
||||
dci_cfg.pusch_dmrs_max_len = pusch.dmrs_max_length;
|
||||
|
||||
// Format 1_1 specific configuration (for PDSCH only)
|
||||
dci_cfg.nof_dl_bwp = 0;
|
||||
dci_cfg.nof_dl_time_res = (pdsch.nof_dedicated_time_ra > 0)
|
||||
? pdsch.nof_dedicated_time_ra
|
||||
: (pdsch.nof_common_time_ra > 0) ? pdsch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA;
|
||||
dci_cfg.nof_aperiodic_zp = 0;
|
||||
dci_cfg.pdsch_nof_cbg = 0;
|
||||
dci_cfg.nof_dl_to_ul_ack = harq_ack.nof_dl_data_to_ul_ack;
|
||||
dci_cfg.pdsch_inter_prb_to_prb = false;
|
||||
dci_cfg.pdsch_rm_pattern1 = false;
|
||||
dci_cfg.pdsch_rm_pattern2 = false;
|
||||
dci_cfg.pdsch_2cw = false;
|
||||
dci_cfg.multiple_scell = false;
|
||||
dci_cfg.pdsch_tci = false;
|
||||
dci_cfg.pdsch_cbg_flush = false;
|
||||
dci_cfg.pdsch_dynamic_bundling = false;
|
||||
dci_cfg.pdsch_alloc_type = pdsch.alloc;
|
||||
dci_cfg.pdsch_dmrs_type = pdsch.dmrs_type;
|
||||
dci_cfg.pdsch_dmrs_max_len = pdsch.dmrs_max_length;
|
||||
|
||||
return dci_cfg;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::assert_ss_id(uint32_t ss_id) const
|
||||
{
|
||||
// Make sure SS access if bounded
|
||||
if (ss_id > SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check SS is present
|
||||
if (not pdcch.search_space_present[ss_id]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract CORESET id
|
||||
uint32_t coreset_id = pdcch.search_space[ss_id].coreset_id;
|
||||
|
||||
// Make sure CORESET id is bounded
|
||||
if (coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check CORESET is present
|
||||
if (not pdcch.coreset_present[coreset_id]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::get_dci_locations(
|
||||
const uint32_t& slot_idx,
|
||||
const uint16_t& rnti,
|
||||
const uint32_t& ss_id,
|
||||
const uint32_t& L,
|
||||
srsran::bounded_vector<srsran_dci_location_t, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR>& locations) const
|
||||
{
|
||||
// Assert search space
|
||||
if (not assert_ss_id(ss_id)) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Select SS and CORESET
|
||||
const srsran_search_space_t& ss = pdcch.search_space[ss_id];
|
||||
const srsran_coreset_t& coreset = pdcch.coreset[ss.coreset_id];
|
||||
|
||||
// Compute NCCE
|
||||
std::array<uint32_t, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR> ncce = {};
|
||||
int n = srsran_pdcch_nr_locations_coreset(&coreset, &ss, rnti, L, slot_idx, ncce.data());
|
||||
if (n < SRSRAN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Push locations
|
||||
for (uint32_t i = 0; i < (uint32_t)n; i++) {
|
||||
locations.push_back({L, ncce[i]});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
srsran_dci_format_nr_t phy_cfg_nr_t::get_dci_format_pdsch(uint32_t ss_id) const
|
||||
{
|
||||
// Assert search space
|
||||
if (not assert_ss_id(ss_id)) {
|
||||
return SRSRAN_DCI_FORMAT_NR_COUNT;
|
||||
}
|
||||
|
||||
// Select SS
|
||||
const srsran_search_space_t& ss = pdcch.search_space[ss_id];
|
||||
|
||||
// Extract number of formats
|
||||
uint32_t nof_formats = SRSRAN_MIN(ss.nof_formats, SRSRAN_DCI_FORMAT_NR_COUNT);
|
||||
|
||||
// Select DCI formats
|
||||
for (uint32_t i = 0; i < nof_formats; i++) {
|
||||
// Select DL format
|
||||
if (ss.formats[i] == srsran_dci_format_nr_1_0 or ss.formats[i] == srsran_dci_format_nr_1_1) {
|
||||
return ss.formats[i];
|
||||
}
|
||||
}
|
||||
|
||||
// If reached here, no valid DCI format is available
|
||||
return SRSRAN_DCI_FORMAT_NR_COUNT;
|
||||
}
|
||||
|
||||
srsran_dci_format_nr_t phy_cfg_nr_t::get_dci_format_pusch(uint32_t ss_id) const
|
||||
{
|
||||
// Assert search space
|
||||
if (not assert_ss_id(ss_id)) {
|
||||
return SRSRAN_DCI_FORMAT_NR_COUNT;
|
||||
}
|
||||
|
||||
// Select SS
|
||||
const srsran_search_space_t& ss = pdcch.search_space[ss_id];
|
||||
|
||||
// Extract number of formats
|
||||
uint32_t nof_formats = SRSRAN_MIN(ss.nof_formats, SRSRAN_DCI_FORMAT_NR_COUNT);
|
||||
|
||||
// Select DCI formats
|
||||
for (uint32_t i = 0; i < nof_formats; i++) {
|
||||
// Select DL format
|
||||
if (ss.formats[i] == srsran_dci_format_nr_0_0 or ss.formats[i] == srsran_dci_format_nr_0_1) {
|
||||
return ss.formats[i];
|
||||
}
|
||||
}
|
||||
|
||||
// If reached here, no valid DCI format is available
|
||||
return SRSRAN_DCI_FORMAT_NR_COUNT;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::get_dci_ctx_pdsch_rnti_c(uint32_t ss_id,
|
||||
const srsran_dci_location_t& location,
|
||||
const uint16_t& rnti,
|
||||
srsran_dci_ctx_t& ctx) const
|
||||
{
|
||||
// Get DCI format, includes SS Id assertion
|
||||
srsran_dci_format_nr_t format = get_dci_format_pdsch(ss_id);
|
||||
if (format == SRSRAN_DCI_FORMAT_NR_COUNT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Select search space
|
||||
const srsran_search_space_t& ss = pdcch.search_space[ss_id];
|
||||
|
||||
// Fill context
|
||||
ctx.location = location;
|
||||
ctx.ss_type = ss.type;
|
||||
ctx.coreset_id = ss.coreset_id;
|
||||
ctx.rnti_type = srsran_rnti_type_c;
|
||||
ctx.format = format;
|
||||
ctx.rnti = rnti;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::get_dci_ctx_pusch_rnti_c(uint32_t ss_id,
|
||||
const srsran_dci_location_t& location,
|
||||
const uint16_t& rnti,
|
||||
srsran_dci_ctx_t& ctx) const
|
||||
{
|
||||
// Get DCI format, includes SS Id assertion
|
||||
srsran_dci_format_nr_t format = get_dci_format_pusch(ss_id);
|
||||
if (format == SRSRAN_DCI_FORMAT_NR_COUNT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Select search space
|
||||
const srsran_search_space_t& ss = pdcch.search_space[ss_id];
|
||||
|
||||
// Fill context
|
||||
ctx.location = location;
|
||||
ctx.ss_type = ss.type;
|
||||
ctx.coreset_id = ss.coreset_id;
|
||||
ctx.rnti_type = srsran_rnti_type_c;
|
||||
ctx.format = format;
|
||||
ctx.rnti = rnti;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::get_pdsch_cfg(const srsran_slot_cfg_t& slot_cfg,
|
||||
const srsran_dci_dl_nr_t& dci,
|
||||
srsran_sch_cfg_nr_t& pdsch_cfg) const
|
||||
{
|
||||
return srsran_ra_dl_dci_to_grant_nr(&carrier, &slot_cfg, &pdsch, &dci, &pdsch_cfg, &pdsch_cfg.grant) ==
|
||||
SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::get_pusch_cfg(const srsran_slot_cfg_t& slot_cfg,
|
||||
const srsran_dci_ul_nr_t& dci,
|
||||
srsran_sch_cfg_nr_t& pusch_cfg) const
|
||||
{
|
||||
return srsran_ra_ul_dci_to_grant_nr(&carrier, &slot_cfg, &pusch, &dci, &pusch_cfg, &pusch_cfg.grant) ==
|
||||
SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl,
|
||||
srsran_harq_ack_resource_t& ack_resource) const
|
||||
{
|
||||
return srsran_harq_ack_resource(&harq_ack, &dci_dl, &ack_resource) == SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::get_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
|
||||
const srsran_pdsch_ack_nr_t& pdsch_ack,
|
||||
srsran_uci_cfg_nr_t& uci_cfg) const
|
||||
{
|
||||
// Generate configuration for HARQ feedback
|
||||
if (srsran_harq_ack_gen_uci_cfg(&harq_ack, &pdsch_ack, &uci_cfg) < SRSRAN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate configuration for SR
|
||||
// ...
|
||||
|
||||
// Generate configuration for CSI reports
|
||||
// ...
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::get_pucch_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
|
||||
const srsran_uci_cfg_nr_t& uci_cfg,
|
||||
srsran_pucch_nr_common_cfg_t& cfg,
|
||||
srsran_pucch_nr_resource_t& resource) const
|
||||
{
|
||||
// Select PUCCH resource
|
||||
if (srsran_ra_ul_nr_pucch_resource(&pucch, &uci_cfg, &resource) < SRSRAN_SUCCESS) {
|
||||
ERROR("Selecting PUCCH resource");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool phy_cfg_nr_t::get_pusch_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
|
||||
const srsran_uci_cfg_nr_t& uci_cfg,
|
||||
srsran_sch_cfg_nr_t& pusch_cfg) const
|
||||
{
|
||||
// Generate configuration for PUSCH
|
||||
if (srsran_ra_ul_set_grant_uci_nr(&carrier, &pusch, &uci_cfg, &pusch_cfg) < SRSRAN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace srsran
|
@ -0,0 +1,253 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 "srsran/common/phy_cfg_nr_default.h"
|
||||
#include "srsran/srsran.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
void phy_cfg_nr_default_t::make_carrier_custom_10MHz(srsran_carrier_nr_t& carrier)
|
||||
{
|
||||
carrier.nof_prb = 52;
|
||||
carrier.max_mimo_layers = 1;
|
||||
carrier.pci = 500;
|
||||
carrier.absolute_frequency_point_a = 633928;
|
||||
carrier.absolute_frequency_ssb = 634176;
|
||||
carrier.offset_to_carrier = 0;
|
||||
carrier.scs = srsran_subcarrier_spacing_15kHz;
|
||||
}
|
||||
|
||||
void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd)
|
||||
{
|
||||
tdd.pattern1.period_ms = 10;
|
||||
tdd.pattern1.nof_dl_slots = 6;
|
||||
tdd.pattern1.nof_dl_symbols = 0;
|
||||
tdd.pattern1.nof_ul_slots = 4;
|
||||
tdd.pattern1.nof_ul_symbols = 0;
|
||||
|
||||
// Disable pattern 2
|
||||
tdd.pattern2.period_ms = 0;
|
||||
}
|
||||
|
||||
void phy_cfg_nr_default_t::make_pdcch_custom_common_ss(srsran_pdcch_cfg_nr_t& pdcch, const srsran_carrier_nr_t& carrier)
|
||||
{
|
||||
// Configure CORESET ID 1
|
||||
pdcch.coreset_present[1] = true;
|
||||
pdcch.coreset[1].id = 1;
|
||||
pdcch.coreset[1].duration = 1;
|
||||
pdcch.coreset[1].mapping_type = srsran_coreset_mapping_type_non_interleaved;
|
||||
pdcch.coreset[1].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle;
|
||||
|
||||
// Generate frequency resources for the full BW
|
||||
for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) {
|
||||
pdcch.coreset[1].freq_resources[i] = i < SRSRAN_FLOOR(carrier.nof_prb, 6);
|
||||
}
|
||||
|
||||
// Configure Search Space 1 as common
|
||||
pdcch.search_space_present[1] = true;
|
||||
pdcch.search_space[1].id = 1;
|
||||
pdcch.search_space[1].coreset_id = 1;
|
||||
pdcch.search_space[1].duration = 1;
|
||||
pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; // DCI format for PUSCH
|
||||
pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; // DCI format for PDSCH
|
||||
pdcch.search_space[1].nof_formats = 2;
|
||||
pdcch.search_space[1].type = srsran_search_space_type_common_3;
|
||||
|
||||
// Generate 1 candidate for each aggregation level if possible
|
||||
for (uint32_t L = 0; L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) {
|
||||
pdcch.search_space[1].nof_candidates[L] =
|
||||
SRSRAN_MIN(2, srsran_pdcch_nr_max_candidates_coreset(&pdcch.coreset[1], L));
|
||||
}
|
||||
}
|
||||
|
||||
void phy_cfg_nr_default_t::make_pdsch_default(srsran_sch_hl_cfg_nr_t& pdsch)
|
||||
{
|
||||
// Select PDSCH time resource allocation
|
||||
pdsch.common_time_ra[0].k = 0;
|
||||
pdsch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A;
|
||||
pdsch.common_time_ra[0].sliv = srsran_ra_type2_to_riv(SRSRAN_NSYMB_PER_SLOT_NR - 1, 1, SRSRAN_NSYMB_PER_SLOT_NR);
|
||||
pdsch.nof_common_time_ra = 1;
|
||||
|
||||
// Setup PDSCH DMRS type A position
|
||||
pdsch.typeA_pos = srsran_dmrs_sch_typeA_pos_2;
|
||||
}
|
||||
|
||||
void phy_cfg_nr_default_t::make_pusch_default(srsran_sch_hl_cfg_nr_t& pusch)
|
||||
{
|
||||
// Select PUSCH time resource allocation
|
||||
pusch.common_time_ra[0].k = 4;
|
||||
pusch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A;
|
||||
pusch.common_time_ra[0].sliv = srsran_ra_type2_to_riv(SRSRAN_NSYMB_PER_SLOT_NR, 0, SRSRAN_NSYMB_PER_SLOT_NR);
|
||||
pusch.nof_common_time_ra = 1;
|
||||
|
||||
// Setup PUSCH DMRS type A position
|
||||
pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2;
|
||||
|
||||
pusch.scaling = 1.0f;
|
||||
pusch.beta_offsets.fix_ack = 12.625f;
|
||||
pusch.beta_offsets.fix_csi1 = 2.25f;
|
||||
pusch.beta_offsets.fix_csi2 = 2.25f;
|
||||
}
|
||||
|
||||
void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch)
|
||||
{
|
||||
// PUCCH Resource for format 1
|
||||
srsran_pucch_nr_resource_t resource_small = {};
|
||||
resource_small.starting_prb = 0;
|
||||
resource_small.format = SRSRAN_PUCCH_NR_FORMAT_1;
|
||||
resource_small.initial_cyclic_shift = 0;
|
||||
resource_small.nof_symbols = 14;
|
||||
resource_small.start_symbol_idx = 0;
|
||||
resource_small.time_domain_occ = 0;
|
||||
|
||||
// PUCCH Resource for format 2
|
||||
srsran_pucch_nr_resource_t resource_big = {};
|
||||
resource_big.starting_prb = 51;
|
||||
resource_big.format = SRSRAN_PUCCH_NR_FORMAT_2;
|
||||
resource_big.nof_prb = 1;
|
||||
resource_big.nof_symbols = 2;
|
||||
resource_big.start_symbol_idx = 0;
|
||||
|
||||
// Resource for SR
|
||||
srsran_pucch_nr_resource_t resource_sr = {};
|
||||
resource_sr.starting_prb = 51;
|
||||
resource_sr.format = SRSRAN_PUCCH_NR_FORMAT_1;
|
||||
resource_sr.initial_cyclic_shift = 0;
|
||||
resource_sr.nof_symbols = 14;
|
||||
resource_sr.start_symbol_idx = 0;
|
||||
resource_sr.time_domain_occ = 0;
|
||||
|
||||
pucch.enabled = true;
|
||||
|
||||
// Set format 1 for 1-2 bits
|
||||
pucch.sets[0].resources[0] = resource_small;
|
||||
pucch.sets[0].resources[1] = resource_small;
|
||||
pucch.sets[0].resources[2] = resource_small;
|
||||
pucch.sets[0].resources[3] = resource_small;
|
||||
pucch.sets[0].resources[4] = resource_small;
|
||||
pucch.sets[0].resources[5] = resource_small;
|
||||
pucch.sets[0].resources[6] = resource_small;
|
||||
pucch.sets[0].resources[7] = resource_small;
|
||||
pucch.sets[0].nof_resources = 8;
|
||||
|
||||
// Set format 2 for more bits
|
||||
pucch.sets[1].resources[0] = resource_big;
|
||||
pucch.sets[1].resources[1] = resource_big;
|
||||
pucch.sets[1].resources[2] = resource_big;
|
||||
pucch.sets[1].resources[3] = resource_big;
|
||||
pucch.sets[1].resources[4] = resource_big;
|
||||
pucch.sets[1].resources[5] = resource_big;
|
||||
pucch.sets[1].resources[6] = resource_big;
|
||||
pucch.sets[1].resources[7] = resource_big;
|
||||
pucch.sets[1].nof_resources = 8;
|
||||
|
||||
// Configure scheduling request
|
||||
pucch.sr_resources[1].configured = true;
|
||||
pucch.sr_resources[1].sr_id = 0;
|
||||
pucch.sr_resources[1].period = 40;
|
||||
pucch.sr_resources[1].offset = 8;
|
||||
pucch.sr_resources[1].resource = resource_sr;
|
||||
}
|
||||
|
||||
void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
|
||||
const srsran_carrier_nr_t& carrier,
|
||||
const srsran_tdd_config_nr_t& tdd_cfg)
|
||||
{
|
||||
// Generate as many entries as DL slots
|
||||
harq.nof_dl_data_to_ul_ack = SRSRAN_MAX(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL);
|
||||
|
||||
// Set PDSCH to ACK timing delay to 4 or more
|
||||
for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) {
|
||||
// Set the first slots into the first UL slot
|
||||
if (n < (harq.nof_dl_data_to_ul_ack - 4)) {
|
||||
harq.dl_data_to_ul_ack[n] = harq.nof_dl_data_to_ul_ack - n;
|
||||
continue;
|
||||
}
|
||||
|
||||
// After that try if n+4 is UL slot
|
||||
if (srsran_tdd_nr_is_ul(&tdd_cfg, carrier.scs, n + 4)) {
|
||||
harq.dl_data_to_ul_ack[n] = 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise set delay to the first UL slot of the next TDD period
|
||||
harq.dl_data_to_ul_ack[n] = 2 * harq.nof_dl_data_to_ul_ack - n;
|
||||
}
|
||||
|
||||
// Zero the rest
|
||||
for (uint32_t i = harq.nof_dl_data_to_ul_ack; i < SRSRAN_MAX_NOF_DL_DATA_TO_UL; i++) {
|
||||
harq.dl_data_to_ul_ack[i] = 0;
|
||||
}
|
||||
|
||||
// Select dynamic HARQ-ACK codebook
|
||||
harq.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic;
|
||||
}
|
||||
|
||||
void phy_cfg_nr_default_t::make_prach_default_lte(srsran_prach_cfg_t& prach)
|
||||
{
|
||||
prach.config_idx = 0;
|
||||
prach.freq_offset = 2;
|
||||
prach.root_seq_idx = 0;
|
||||
}
|
||||
|
||||
phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
|
||||
{
|
||||
switch (reference_cfg.carrier) {
|
||||
case reference_cfg_t::R_CARRIER_CUSTOM_10MHZ:
|
||||
make_carrier_custom_10MHz(carrier);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (reference_cfg.tdd) {
|
||||
case reference_cfg_t::R_TDD_CUSTOM_6_4:
|
||||
make_tdd_custom_6_4(tdd);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (reference_cfg.pdcch) {
|
||||
case reference_cfg_t::R_PDCCH_CUSTOM_COMMON_SS:
|
||||
make_pdcch_custom_common_ss(pdcch, carrier);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (reference_cfg.pdsch) {
|
||||
case reference_cfg_t::R_PDSCH_DEFAULT:
|
||||
make_pdsch_default(pdsch);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (reference_cfg.pusch) {
|
||||
case reference_cfg_t::R_PUSCH_DEFAULT:
|
||||
make_pusch_default(pusch);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (reference_cfg.pucch) {
|
||||
case reference_cfg_t::R_PUCCH_CUSTOM_ONE:
|
||||
make_pucch_custom_one(pucch);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (reference_cfg.harq) {
|
||||
case reference_cfg_t::R_HARQ_AUTO:
|
||||
make_harq_auto(harq_ack, carrier, tdd);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (reference_cfg.prach) {
|
||||
case reference_cfg_t::R_PRACH_DEFAULT_LTE:
|
||||
make_prach_default_lte(prach);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace srsran
|
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright 2013-2021 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(GLOB SOURCES "*.c")
|
||||
add_library(srsran_gnb OBJECT ${SOURCES})
|
@ -0,0 +1,310 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 "srsran/phy/gnb/gnb_ul.h"
|
||||
#include "srsran/phy/ch_estimation/dmrs_pucch.h"
|
||||
|
||||
/**
|
||||
* @brief Shifts FFT window a fraction of the cyclic prefix. Set to 0.0f for disabling.
|
||||
* @note Increases protection against inter-symbol interference in case of synchronization error in expense of computing
|
||||
* performance
|
||||
*/
|
||||
#define GNB_UL_NR_FFT_WINDOW_OFFSET 0.5f
|
||||
|
||||
static int gnb_ul_alloc_prb(srsran_gnb_ul_t* q, uint32_t new_nof_prb)
|
||||
{
|
||||
if (q->max_prb < new_nof_prb) {
|
||||
q->max_prb = new_nof_prb;
|
||||
|
||||
srsran_chest_dl_res_free(&q->chest_pusch);
|
||||
if (srsran_chest_dl_res_init(&q->chest_pusch, q->max_prb) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
srsran_chest_ul_res_free(&q->chest_pucch);
|
||||
if (srsran_chest_ul_res_init(&q->chest_pucch, q->max_prb) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (q->sf_symbols[0] != NULL) {
|
||||
free(q->sf_symbols[0]);
|
||||
}
|
||||
|
||||
q->sf_symbols[0] = srsran_vec_cf_malloc(SRSRAN_SLOT_LEN_RE_NR(q->max_prb));
|
||||
if (q->sf_symbols[0] == NULL) {
|
||||
ERROR("Malloc");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_gnb_ul_init(srsran_gnb_ul_t* q, cf_t* input, const srsran_gnb_ul_args_t* args)
|
||||
{
|
||||
if (q == NULL || args == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
if (gnb_ul_alloc_prb(q, args->nof_max_prb) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (srsran_pusch_nr_init_gnb(&q->pusch, &args->pusch) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (srsran_pucch_nr_init(&q->pucch, &args->pucch) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (srsran_dmrs_sch_init(&q->dmrs, true) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
srsran_ofdm_cfg_t ofdm_cfg = {};
|
||||
ofdm_cfg.nof_prb = args->nof_max_prb;
|
||||
ofdm_cfg.in_buffer = input;
|
||||
ofdm_cfg.out_buffer = q->sf_symbols[0];
|
||||
ofdm_cfg.rx_window_offset = GNB_UL_NR_FFT_WINDOW_OFFSET;
|
||||
ofdm_cfg.symbol_sz = srsran_min_symbol_sz_rb(args->nof_max_prb);
|
||||
ofdm_cfg.keep_dc = true;
|
||||
|
||||
if (srsran_ofdm_rx_init_cfg(&q->fft, &ofdm_cfg) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
void srsran_gnb_ul_free(srsran_gnb_ul_t* q)
|
||||
{
|
||||
if (q == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
srsran_ofdm_tx_free(&q->fft);
|
||||
srsran_pusch_nr_free(&q->pusch);
|
||||
srsran_pucch_nr_free(&q->pucch);
|
||||
srsran_dmrs_sch_free(&q->dmrs);
|
||||
srsran_chest_dl_res_free(&q->chest_pusch);
|
||||
srsran_chest_ul_res_free(&q->chest_pucch);
|
||||
|
||||
if (q->sf_symbols[0] != NULL) {
|
||||
free(q->sf_symbols[0]);
|
||||
}
|
||||
|
||||
SRSRAN_MEM_ZERO(q, srsran_gnb_ul_t, 1);
|
||||
}
|
||||
|
||||
int srsran_gnb_ul_set_carrier(srsran_gnb_ul_t* q, const srsran_carrier_nr_t* carrier)
|
||||
{
|
||||
if (q == NULL || carrier == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
q->carrier = *carrier;
|
||||
|
||||
if (gnb_ul_alloc_prb(q, carrier->nof_prb) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (srsran_pusch_nr_set_carrier(&q->pusch, carrier) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (srsran_pucch_nr_set_carrier(&q->pucch, carrier) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (srsran_dmrs_sch_set_carrier(&q->dmrs, carrier) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
srsran_ofdm_cfg_t ofdm_cfg = {};
|
||||
ofdm_cfg.nof_prb = carrier->nof_prb;
|
||||
ofdm_cfg.rx_window_offset = GNB_UL_NR_FFT_WINDOW_OFFSET;
|
||||
ofdm_cfg.symbol_sz = srsran_min_symbol_sz_rb(carrier->nof_prb);
|
||||
ofdm_cfg.keep_dc = true;
|
||||
|
||||
if (srsran_ofdm_rx_init_cfg(&q->fft, &ofdm_cfg) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_gnb_ul_fft(srsran_gnb_ul_t* q)
|
||||
{
|
||||
if (q == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
srsran_ofdm_rx_sf(&q->fft);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_gnb_ul_get_pusch(srsran_gnb_ul_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_sch_cfg_nr_t* cfg,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
srsran_pusch_res_nr_t* data)
|
||||
{
|
||||
if (q == NULL || cfg == NULL || grant == NULL || data == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
if (srsran_dmrs_sch_estimate(&q->dmrs, slot_cfg, cfg, grant, q->sf_symbols[0], &q->chest_pusch) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (srsran_pusch_nr_decode(&q->pusch, cfg, grant, &q->chest_pusch, q->sf_symbols, data) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int gnb_ul_decode_pucch_format1(srsran_gnb_ul_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_pucch_nr_common_cfg_t* cfg,
|
||||
const srsran_pucch_nr_resource_t* resource,
|
||||
const srsran_uci_cfg_nr_t* uci_cfg,
|
||||
srsran_uci_value_nr_t* uci_value)
|
||||
{
|
||||
uint8_t b[SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS] = {};
|
||||
|
||||
// Set ACK bits
|
||||
uint32_t nof_bits = SRSRAN_MIN(SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS, uci_cfg->ack.count);
|
||||
|
||||
// Set SR bits
|
||||
// For a positive SR transmission using PUCCH format 1, the UE transmits the PUCCH as described in [4, TS
|
||||
// 38.211] by setting b ( 0 ) = 0 .
|
||||
if (nof_bits == 0 && uci_cfg->o_sr > 0) {
|
||||
nof_bits = 1;
|
||||
}
|
||||
|
||||
// Channel estimation
|
||||
if (srsran_dmrs_pucch_format1_estimate(&q->pucch, cfg, slot_cfg, resource, q->sf_symbols[0], &q->chest_pucch) <
|
||||
SRSRAN_SUCCESS) {
|
||||
ERROR("Error in PUCCH format 1 estimation");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Actual decode
|
||||
float norm_corr = 0.0f;
|
||||
if (srsran_pucch_nr_format1_decode(
|
||||
&q->pucch, cfg, slot_cfg, resource, &q->chest_pucch, q->sf_symbols[0], b, nof_bits, &norm_corr) <
|
||||
SRSRAN_SUCCESS) {
|
||||
ERROR("Error in PUCCH format 1 decoding");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Take valid decision
|
||||
uci_value->valid = (norm_corr > 0.5f);
|
||||
|
||||
// De-multiplex ACK bits
|
||||
for (uint32_t i = 0; i < nof_bits; i++) {
|
||||
uci_value->ack[i] = b[i];
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int gnb_ul_decode_pucch_format2(srsran_gnb_ul_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_pucch_nr_common_cfg_t* cfg,
|
||||
const srsran_pucch_nr_resource_t* resource,
|
||||
const srsran_uci_cfg_nr_t* uci_cfg,
|
||||
srsran_uci_value_nr_t* uci_value)
|
||||
{
|
||||
if (srsran_dmrs_pucch_format2_estimate(&q->pucch, cfg, slot_cfg, resource, q->sf_symbols[0], &q->chest_pucch) <
|
||||
SRSRAN_SUCCESS) {
|
||||
ERROR("Error in PUCCH format 2 estimation");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (srsran_pucch_nr_format_2_3_4_decode(
|
||||
&q->pucch, cfg, slot_cfg, resource, uci_cfg, &q->chest_pucch, q->sf_symbols[0], uci_value) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error in PUCCH format 2 decoding");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_pucch_nr_common_cfg_t* cfg,
|
||||
const srsran_pucch_nr_resource_t* resource,
|
||||
const srsran_uci_cfg_nr_t* uci_cfg,
|
||||
srsran_uci_value_nr_t* uci_value)
|
||||
{
|
||||
if (q == NULL || slot_cfg == NULL || cfg == NULL || resource == NULL || uci_cfg == NULL || uci_value == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Estimate channel
|
||||
switch (resource->format) {
|
||||
case SRSRAN_PUCCH_NR_FORMAT_1:
|
||||
return gnb_ul_decode_pucch_format1(q, slot_cfg, cfg, resource, uci_cfg, uci_value);
|
||||
case SRSRAN_PUCCH_NR_FORMAT_2:
|
||||
return gnb_ul_decode_pucch_format2(q, slot_cfg, cfg, resource, uci_cfg, uci_value);
|
||||
case SRSRAN_PUCCH_NR_FORMAT_0:
|
||||
case SRSRAN_PUCCH_NR_FORMAT_3:
|
||||
case SRSRAN_PUCCH_NR_FORMAT_4:
|
||||
case SRSRAN_PUCCH_NR_FORMAT_ERROR:
|
||||
ERROR("Invalid or not implemented PUCCH-NR format %d", (int)resource->format);
|
||||
}
|
||||
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t srsran_gnb_ul_pucch_info(srsran_gnb_ul_t* q,
|
||||
const srsran_pucch_nr_resource_t* resource,
|
||||
const srsran_uci_data_nr_t* uci_data,
|
||||
char* str,
|
||||
uint32_t str_len)
|
||||
{
|
||||
if (q == NULL || uci_data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t len = 0;
|
||||
|
||||
len += srsran_pucch_nr_info(resource, uci_data, str, str_len - len);
|
||||
|
||||
len = srsran_print_check(
|
||||
str, str_len, len, "snr=%+.1f valid=%c", q->chest_pucch.snr_db, uci_data->value.valid ? 'y' : 'n');
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint32_t srsran_gnb_ul_pusch_info(srsran_gnb_ul_t* q,
|
||||
const srsran_sch_cfg_nr_t* cfg,
|
||||
const srsran_pusch_res_nr_t* res,
|
||||
char* str,
|
||||
uint32_t str_len)
|
||||
{
|
||||
if (q == NULL || cfg == NULL || res == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t len = 0;
|
||||
|
||||
len += srsran_pusch_nr_rx_info(&q->pusch, cfg, &cfg->grant, res, str, str_len - len);
|
||||
|
||||
len = srsran_print_check(str, str_len, len, "snr=%+.1f", q->chest_pusch.snr_db);
|
||||
|
||||
return len;
|
||||
}
|
@ -0,0 +1,346 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 "srsran/phy/phch/harq_ack.h"
|
||||
#include "srsran/phy/utils/debug.h"
|
||||
#include "srsran/phy/utils/vector.h"
|
||||
|
||||
// Implements TS 38.213 Table 9.1.3-1: Value of counter DAI in DCI format 1_0 and of counter DAI or total DAI DCI format
|
||||
// 1_1
|
||||
static uint32_t ue_dl_nr_V_DL_DAI(uint32_t dai)
|
||||
{
|
||||
return dai + 1;
|
||||
}
|
||||
|
||||
static int harq_ack_gen_ack_type2(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||
const srsran_pdsch_ack_nr_t* ack_info,
|
||||
srsran_uci_cfg_nr_t* uci_cfg)
|
||||
{
|
||||
bool harq_ack_spatial_bundling =
|
||||
ack_info->use_pusch ? cfg->harq_ack_spatial_bundling_pusch : cfg->harq_ack_spatial_bundling_pucch;
|
||||
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
|
||||
uint32_t j = 0;
|
||||
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
|
||||
|
||||
// Initialise ACK bits
|
||||
SRSRAN_MEM_ZERO(uci_cfg->ack.bits, srsran_harq_ack_bit_t, SRSRAN_HARQ_ACK_MAX_NOF_BITS);
|
||||
|
||||
// The following code follows the exact pseudo-code provided in TS 38.213 9.1.3.1 Type-2 HARQ-ACK codebook ...
|
||||
while (m < SRSRAN_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
|
||||
const srsran_harq_ack_m_t* ack = &ack_info->cc[c].m[m];
|
||||
|
||||
// Get DAI counter value
|
||||
uint32_t V_DL_CDAI = ue_dl_nr_V_DL_DAI(ack->resource.v_dai_dl);
|
||||
uint32_t V_DL_TDAI = ack->resource.dci_format_1_1 ? ue_dl_nr_V_DL_DAI(ack->resource.v_dai_dl) : UINT32_MAX;
|
||||
|
||||
// Get ACK values
|
||||
srsran_harq_ack_bit_t ack_tb0 = {};
|
||||
ack_tb0.tb0 = true;
|
||||
ack_tb0.cc_idx = c;
|
||||
ack_tb0.m_idx = m;
|
||||
ack_tb0.pid = ack->resource.pid;
|
||||
srsran_harq_ack_bit_t ack_tb1 = {};
|
||||
ack_tb1.tb1 = true;
|
||||
ack_tb1.cc_idx = c;
|
||||
ack_tb1.m_idx = m;
|
||||
ack_tb1.pid = ack->resource.pid;
|
||||
|
||||
// For a PDCCH monitoring occasion with DCI format 1_0 or DCI format 1_1 in the active DL BWP of a serving cell,
|
||||
// when a UE receives a PDSCH with one transport block and the value of maxNrofCodeWordsScheduledByDCI is 2, the
|
||||
// HARQ-ACK information is associated with the first transport block and the UE generates a NACK for the second
|
||||
// transport block if harq-ACK-SpatialBundlingPUCCH is not provided and generates HARQ-ACK information with
|
||||
// value of ACK for the second transport block if harq-ACK-SpatialBundlingPUCCH is provided.
|
||||
if (cfg->max_cw_sched_dci_is_2 && !ack->second_tb_present) {
|
||||
ack_tb1.tb1 = false;
|
||||
}
|
||||
|
||||
// if PDCCH monitoring occasion m is before an active DL BWP change on serving cell c or an active UL
|
||||
// BWP change on the PCell and an active DL BWP change is not triggered by a DCI format 1_1 in PDCCH
|
||||
// monitoring occasion m
|
||||
if (ack->dl_bwp_changed || ack->ul_bwp_changed) {
|
||||
c = c + 1;
|
||||
} else {
|
||||
if (ack->present) {
|
||||
// Load ACK resource data into UCI info
|
||||
uci_cfg->pucch.resource_id = ack_info->cc[c].m[m].resource.pucch_resource_id;
|
||||
uci_cfg->pucch.rnti = ack_info->cc[c].m[m].resource.rnti;
|
||||
|
||||
if (V_DL_CDAI <= V_temp) {
|
||||
j = j + 1;
|
||||
}
|
||||
|
||||
V_temp = V_DL_CDAI;
|
||||
|
||||
if (V_DL_TDAI == UINT32_MAX) {
|
||||
V_temp2 = V_DL_CDAI;
|
||||
} else {
|
||||
V_temp2 = V_DL_TDAI;
|
||||
}
|
||||
|
||||
// if harq-ACK-SpatialBundlingPUCCH is not provided and m is a monitoring occasion for PDCCH with DCI format
|
||||
// 1_0 or DCI format 1_1 and the UE is configured by maxNrofCodeWordsScheduledByDCI with reception of two
|
||||
// transport blocks for at least one configured DL BWP of at least one serving cell,
|
||||
if (!harq_ack_spatial_bundling && cfg->max_cw_sched_dci_is_2) {
|
||||
uci_cfg->ack.bits[8 * j + 2 * (V_DL_CDAI - 1) + 0] = ack_tb0;
|
||||
uci_cfg->ack.bits[8 * j + 2 * (V_DL_CDAI - 1) + 1] = ack_tb1;
|
||||
}
|
||||
// elseif harq-ACK-SpatialBundlingPUCCH is provided to the UE and m is a monitoring occasion for
|
||||
// PDCCH with DCI format 1_1 and the UE is configured by maxNrofCodeWordsScheduledByDCI with
|
||||
// reception of two transport blocks in at least one configured DL BWP of a serving cell,
|
||||
else if (harq_ack_spatial_bundling && ack->resource.dci_format_1_1 && cfg->max_cw_sched_dci_is_2) {
|
||||
ack_tb0.tb1 = true;
|
||||
uci_cfg->ack.bits[4 * j + (V_DL_CDAI - 1)] = ack_tb0;
|
||||
}
|
||||
// else
|
||||
else {
|
||||
uci_cfg->ack.bits[4 * j + (V_DL_CDAI - 1)] = ack_tb0;
|
||||
}
|
||||
}
|
||||
c = c + 1;
|
||||
}
|
||||
}
|
||||
m = m + 1;
|
||||
}
|
||||
if (V_temp2 < V_temp) {
|
||||
j = j + 1;
|
||||
}
|
||||
|
||||
// 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,
|
||||
if (!harq_ack_spatial_bundling && cfg->max_cw_sched_dci_is_2) {
|
||||
uci_cfg->ack.count = 2 * (4 * j + V_temp2);
|
||||
} else {
|
||||
uci_cfg->ack.count = 4 * j + V_temp2;
|
||||
}
|
||||
|
||||
// Implement here SPS PDSCH reception
|
||||
// ...
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int harq_ack_k1(const srsran_harq_ack_cfg_hl_t* cfg, const srsran_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->ctx.format == srsran_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 >= SRSRAN_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 SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return (int)cfg->dl_data_to_ul_ack[dci_dl->harq_feedback];
|
||||
}
|
||||
|
||||
int srsran_harq_ack_resource(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||
const srsran_dci_dl_nr_t* dci_dl,
|
||||
srsran_harq_ack_resource_t* pdsch_ack_resource)
|
||||
{
|
||||
if (cfg == NULL || dci_dl == NULL || pdsch_ack_resource == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Calculate Data to UL ACK timing k1
|
||||
int k1 = harq_ack_k1(cfg, dci_dl);
|
||||
if (k1 < SRSRAN_ERROR) {
|
||||
ERROR("Error calculating K1");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Fill PDSCH resource
|
||||
pdsch_ack_resource->dci_format_1_1 = (dci_dl->ctx.format == srsran_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->ctx.rnti;
|
||||
pdsch_ack_resource->pucch_resource_id = dci_dl->pucch_resource;
|
||||
pdsch_ack_resource->pid = dci_dl->pid;
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_harq_ack_gen_uci_cfg(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||
const srsran_pdsch_ack_nr_t* ack_info,
|
||||
srsran_uci_cfg_nr_t* uci_cfg)
|
||||
{
|
||||
// Check inputs
|
||||
if (cfg == NULL || ack_info == NULL || uci_cfg == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// According TS 38.213 9.1.2 Type-1 HARQ-ACK codebook determination
|
||||
if (cfg->harq_ack_codebook == srsran_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 SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// According TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination
|
||||
if (cfg->harq_ack_codebook == srsran_pdsch_harq_ack_codebook_dynamic) {
|
||||
// This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = dynamic.
|
||||
return harq_ack_gen_ack_type2(cfg, ack_info, uci_cfg);
|
||||
}
|
||||
|
||||
ERROR("No HARQ-ACK codebook determination is NOT implemented");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
int srsran_harq_ack_pack(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||
const srsran_pdsch_ack_nr_t* ack_info,
|
||||
srsran_uci_data_nr_t* uci_data)
|
||||
{
|
||||
// Check inputs
|
||||
if (cfg == NULL || ack_info == NULL || uci_data == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Generate configuration
|
||||
if (srsran_harq_ack_gen_uci_cfg(cfg, ack_info, &uci_data->cfg) < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Actual packing
|
||||
for (uint32_t i = 0; i < uci_data->cfg.ack.count; i++) {
|
||||
srsran_harq_ack_bit_t* ack_bit = &uci_data->cfg.ack.bits[i];
|
||||
|
||||
// Skip bit if no TB is used
|
||||
if (!ack_bit->tb0 && !ack_bit->tb1) {
|
||||
uci_data->value.ack[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only TB0
|
||||
if (ack_bit->tb0 && !ack_bit->tb1) {
|
||||
uci_data->value.ack[i] = ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[0];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only TB1
|
||||
if (!ack_bit->tb0 && ack_bit->tb1) {
|
||||
uci_data->value.ack[i] = ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Both TB with bundling
|
||||
uci_data->value.ack[i] = ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[0];
|
||||
uci_data->value.ack[i] &= ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[1];
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_harq_ack_unpack(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||
const srsran_uci_data_nr_t* uci_data,
|
||||
srsran_pdsch_ack_nr_t* ack_info)
|
||||
{
|
||||
// Check inputs
|
||||
if (cfg == NULL || ack_info == NULL || uci_data == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Actual packing
|
||||
for (uint32_t i = 0; i < uci_data->cfg.ack.count; i++) {
|
||||
const srsran_harq_ack_bit_t* ack_bit = &uci_data->cfg.ack.bits[i];
|
||||
|
||||
// Extract TB0
|
||||
if (ack_bit->tb0) {
|
||||
ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[0] = uci_data->value.ack[i];
|
||||
}
|
||||
|
||||
// Extract TB1
|
||||
if (ack_bit->tb1) {
|
||||
ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[1] = uci_data->value.ack[i];
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_harq_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_harq_ack_m_t* m)
|
||||
{
|
||||
// Check inputs
|
||||
if (ack_info == NULL || m == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Protect SCell index and extract information
|
||||
if (m->resource.scell_idx >= SRSRAN_MAX_CARRIERS) {
|
||||
ERROR("Serving cell index (%d) exceeds maximum", m->resource.scell_idx);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
srsran_harq_ack_cc_t* cc = &ack_info->cc[m->resource.scell_idx];
|
||||
|
||||
// Find insertion index
|
||||
uint32_t idx = cc->M; // Append at the end by default
|
||||
for (uint32_t i = 0; i < cc->M; i++) {
|
||||
if (cc->m[i].resource.k1 < m->resource.k1) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment count
|
||||
cc->M += 1;
|
||||
|
||||
// Make space for insertion
|
||||
for (uint32_t i = cc->M - 1; i > idx; i--) {
|
||||
cc->m[i] = cc->m[i - 1];
|
||||
}
|
||||
|
||||
// Actual insertion
|
||||
cc->m[idx] = *m;
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t srsran_harq_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
||||
if (ack_info == NULL || str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Print base info
|
||||
len = srsran_print_check(
|
||||
str, str_len, len, "use_pusch=%c nof_cc=%d\n", ack_info->use_pusch ? 'y' : 'n', ack_info->nof_cc);
|
||||
|
||||
// Iterate all carriers
|
||||
for (uint32_t cc = 0; cc < ack_info->nof_cc; cc++) {
|
||||
len = srsran_print_check(str, str_len, len, " CC %d: M=%d\n", cc, ack_info->cc[cc].M);
|
||||
for (uint32_t m = 0; m < ack_info->cc[cc].M; m++) {
|
||||
if (ack_info->cc[cc].m[m].present) {
|
||||
len = srsran_print_check(str,
|
||||
str_len,
|
||||
len,
|
||||
" m %d: k1=%d dai=%d ack=%d\n",
|
||||
m,
|
||||
ack_info->cc[cc].m[m].resource.k1,
|
||||
ack_info->cc[cc].m[m].resource.v_dai_dl,
|
||||
ack_info->cc[cc].m[m].value[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,113 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 SRSENB_RRC_ENDC_H
|
||||
#define SRSENB_RRC_ENDC_H
|
||||
|
||||
#include "rrc.h"
|
||||
#include "rrc_ue.h"
|
||||
#include "srsran/adt/fsm.h"
|
||||
#include <map>
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
/**
|
||||
* @brief This procedure handles the secondary node (SgNB) addition for
|
||||
* EUTRA-NR Dual connectivity (ENDC)
|
||||
*
|
||||
*/
|
||||
|
||||
class rrc::ue::rrc_endc : public srsran::fsm_t<rrc::ue::rrc_endc>
|
||||
{
|
||||
public:
|
||||
// public events
|
||||
struct user_crnti_upd_ev {
|
||||
uint16_t crnti;
|
||||
uint16_t temp_crnti;
|
||||
};
|
||||
struct ho_cancel_ev {
|
||||
asn1::s1ap::cause_c cause;
|
||||
|
||||
ho_cancel_ev(const asn1::s1ap::cause_c& cause_) : cause(cause_) {}
|
||||
};
|
||||
|
||||
rrc_endc(srsenb::rrc::ue* outer_ue);
|
||||
|
||||
bool fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg);
|
||||
void handle_ue_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps);
|
||||
void handle_ue_meas_report(const asn1::rrc::meas_report_s& msg);
|
||||
void handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15,
|
||||
const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15);
|
||||
void handle_sgnb_addition_reject();
|
||||
|
||||
private:
|
||||
// Send SgNB addition request to gNB
|
||||
bool start_sgnb_addition();
|
||||
|
||||
bool is_endc_activation_running() const { return not is_in_state<idle_st>(); }
|
||||
|
||||
rrc::ue* rrc_ue = nullptr;
|
||||
rrc* rrc_enb = nullptr;
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
// vars
|
||||
bool endc_supported = false;
|
||||
asn1::rrc::rrc_conn_recfg_complete_s pending_recfg_complete;
|
||||
|
||||
// events
|
||||
struct sgnb_add_req_sent_ev {};
|
||||
struct sgnb_add_req_ack_ev {};
|
||||
struct sgnb_add_req_reject_ev {};
|
||||
struct prach_nr_received_ev {};
|
||||
|
||||
using recfg_complete_ev = asn1::rrc::rrc_conn_recfg_complete_s;
|
||||
using status_transfer_ev = asn1::s1ap::bearers_subject_to_status_transfer_list_l;
|
||||
|
||||
// states
|
||||
struct idle_st {};
|
||||
struct wait_sgnb_add_req_resp {};
|
||||
struct wait_recfg_comp {};
|
||||
struct wait_prach_nr {};
|
||||
|
||||
// FSM guards
|
||||
|
||||
// FSM transition handlers
|
||||
void handle_recfg_complete(wait_recfg_comp& s, const recfg_complete_ev& ev);
|
||||
void handle_sgnb_addition_request_sent(const sgnb_add_req_sent_ev& ev);
|
||||
|
||||
protected:
|
||||
// states
|
||||
state_list<idle_st, wait_sgnb_add_req_resp, wait_recfg_comp, wait_prach_nr> states{this,
|
||||
idle_st{},
|
||||
wait_sgnb_add_req_resp{},
|
||||
wait_recfg_comp{},
|
||||
wait_prach_nr{}};
|
||||
|
||||
// transitions
|
||||
using fsm = rrc_endc;
|
||||
// clang-format off
|
||||
using transitions = transition_table<
|
||||
// Start Target Event Action Guard
|
||||
// +-----------------------+-----------------------+------------------------+----------------------------+-------------------------+
|
||||
row< idle_st, wait_sgnb_add_req_resp, sgnb_add_req_sent_ev, nullptr >,
|
||||
// +-----------------------+-----------------------+------------------------+----------------------------+-------------------------+
|
||||
row< wait_sgnb_add_req_resp, wait_recfg_comp, sgnb_add_req_ack_ev >,
|
||||
row< wait_sgnb_add_req_resp, idle_st, sgnb_add_req_reject_ev >,
|
||||
row< wait_recfg_comp, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete >
|
||||
// +-----------------------+-----------------------+------------------------+----------------------------+-------------------------+
|
||||
>;
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSENB_RRC_ENDC_H
|
@ -0,0 +1,252 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 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 "srsenb/hdr/stack/rrc/rrc_endc.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
#define Info(fmt, ...) logger.info("ENDC: " fmt, ##__VA_ARGS__)
|
||||
#define Error(fmt, ...) logger.error("ENDC: " fmt, ##__VA_ARGS__)
|
||||
#define Warning(fmt, ...) logger.warning("ENDC: " fmt, ##__VA_ARGS__)
|
||||
#define Debug(fmt, ...) logger.debug("ENDC: " fmt, ##__VA_ARGS__)
|
||||
|
||||
#define procInfo(fmt, ...) parent->logger.info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
|
||||
#define procWarning(fmt, ...) parent->logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
|
||||
#define procError(fmt, ...) parent->logger.error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
|
||||
|
||||
using namespace asn1::rrc;
|
||||
|
||||
/*************************************************************************************************
|
||||
* rrc_endc class
|
||||
************************************************************************************************/
|
||||
|
||||
rrc::ue::rrc_endc::rrc_endc(rrc::ue* outer_ue) :
|
||||
base_t(outer_ue->parent->logger), rrc_ue(outer_ue), rrc_enb(outer_ue->parent), logger(outer_ue->parent->logger)
|
||||
{}
|
||||
|
||||
//! Method to add NR fields to a RRC Connection Reconfiguration Message
|
||||
bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg)
|
||||
{
|
||||
if (not endc_supported) {
|
||||
// skipping ENDC-related field
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not is_endc_activation_running()) {
|
||||
// add hard-coded measConfig
|
||||
conn_recfg->meas_cfg_present = true;
|
||||
meas_cfg_s& meas_cfg = conn_recfg->meas_cfg;
|
||||
|
||||
meas_cfg.meas_obj_to_add_mod_list_present = true;
|
||||
meas_cfg.meas_obj_to_add_mod_list.resize(2);
|
||||
|
||||
auto& meas_obj = meas_cfg.meas_obj_to_add_mod_list[0];
|
||||
meas_obj.meas_obj_id = 1;
|
||||
meas_obj.meas_obj.set_meas_obj_eutra();
|
||||
meas_obj.meas_obj.meas_obj_eutra().carrier_freq = 300;
|
||||
meas_obj.meas_obj.meas_obj_eutra().allowed_meas_bw = allowed_meas_bw_opts::mbw50;
|
||||
meas_obj.meas_obj.meas_obj_eutra().presence_ant_port1 = false;
|
||||
meas_obj.meas_obj.meas_obj_eutra().neigh_cell_cfg.from_number(0b01);
|
||||
|
||||
auto& meas_obj2 = meas_cfg.meas_obj_to_add_mod_list[1];
|
||||
meas_obj2.meas_obj_id = 2;
|
||||
meas_obj2.meas_obj.set_meas_obj_nr_r15();
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().carrier_freq_r15 = 634176;
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.periodicity_and_offset_r15.set_sf20_r15();
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.ssb_dur_r15 =
|
||||
asn1::rrc::mtc_ssb_nr_r15_s::ssb_dur_r15_opts::sf1;
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.subcarrier_spacing_ssb_r15 =
|
||||
asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_opts::khz30;
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().ext = true;
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.set_present(true);
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.get()->set_setup() = 78;
|
||||
|
||||
// report config
|
||||
meas_cfg.report_cfg_to_add_mod_list_present = true;
|
||||
meas_cfg.report_cfg_to_add_mod_list.resize(1);
|
||||
auto& report_cfg = meas_cfg.report_cfg_to_add_mod_list[0];
|
||||
|
||||
report_cfg.report_cfg_id = 1;
|
||||
report_cfg.report_cfg.set_report_cfg_inter_rat();
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.set_event();
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().event_id.set_event_b1_nr_r15();
|
||||
report_cfg.report_cfg.report_cfg_inter_rat()
|
||||
.trigger_type.event()
|
||||
.event_id.event_b1_nr_r15()
|
||||
.b1_thres_nr_r15.set_nr_rsrp_r15();
|
||||
report_cfg.report_cfg.report_cfg_inter_rat()
|
||||
.trigger_type.event()
|
||||
.event_id.event_b1_nr_r15()
|
||||
.b1_thres_nr_r15.nr_rsrp_r15() = 56;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().event_id.event_b1_nr_r15().report_on_leave_r15 =
|
||||
false;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().hysteresis = 0;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().time_to_trigger = time_to_trigger_opts::ms100;
|
||||
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().max_report_cells = 1;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().report_interv = report_interv_opts::ms120;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().report_amount = report_cfg_inter_rat_s::report_amount_opts::r1;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.set_present(true);
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().ext = true;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrp = true;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrq = true;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_sinr = true;
|
||||
|
||||
// measIdToAddModList
|
||||
meas_cfg.meas_id_to_add_mod_list_present = true;
|
||||
meas_cfg.meas_id_to_add_mod_list.resize(1);
|
||||
auto& meas_id = meas_cfg.meas_id_to_add_mod_list[0];
|
||||
meas_id.meas_id = 1;
|
||||
meas_id.meas_obj_id = 2;
|
||||
meas_id.report_cfg_id = 1;
|
||||
|
||||
// quantityConfig
|
||||
meas_cfg.quant_cfg_present = true;
|
||||
meas_cfg.quant_cfg.quant_cfg_eutra_present = true;
|
||||
meas_cfg.quant_cfg.quant_cfg_nr_list_r15.set_present(true);
|
||||
meas_cfg.quant_cfg.quant_cfg_nr_list_r15.get()->resize(1);
|
||||
meas_cfg.quant_cfg.ext = true;
|
||||
auto& meas_quant = meas_cfg.quant_cfg.quant_cfg_nr_list_r15.get()[0];
|
||||
meas_quant[0].meas_quant_cell_nr_r15.filt_coeff_rsrp_r15_present = true;
|
||||
meas_quant[0].meas_quant_cell_nr_r15.filt_coeff_rsrp_r15 = filt_coef_opts::fc3;
|
||||
|
||||
// measGapConfig
|
||||
meas_cfg.meas_gap_cfg_present = true;
|
||||
meas_cfg.meas_gap_cfg.set_setup();
|
||||
meas_cfg.meas_gap_cfg.setup().gap_offset.set_gp0() = 16;
|
||||
} else {
|
||||
// only add reconfigure EN-DC extension/release 15.10 field if ENDC activation is active
|
||||
conn_recfg->non_crit_ext_present = true;
|
||||
conn_recfg->non_crit_ext.non_crit_ext_present = true;
|
||||
conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext_present = true;
|
||||
conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present = true;
|
||||
conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present = true;
|
||||
conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present = true;
|
||||
conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present =
|
||||
true;
|
||||
conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext
|
||||
.non_crit_ext_present = true;
|
||||
rrc_conn_recfg_v1510_ies_s& reconf_v1510 = conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext
|
||||
.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext;
|
||||
reconf_v1510.nr_cfg_r15_present = true;
|
||||
reconf_v1510.sk_counter_r15_present = true;
|
||||
reconf_v1510.sk_counter_r15 = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Called when UE capabilities are received
|
||||
void rrc::ue::rrc_endc::handle_ue_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps)
|
||||
{
|
||||
// Only enabled ENDC support if UE caps have been exchanged and UE signals support
|
||||
if (eutra_caps.non_crit_ext_present) {
|
||||
if (eutra_caps.non_crit_ext.non_crit_ext_present) {
|
||||
if (eutra_caps.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present) {
|
||||
if (eutra_caps.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present) {
|
||||
auto& ue_cap_v1170 =
|
||||
eutra_caps.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext;
|
||||
if (ue_cap_v1170.non_crit_ext_present) {
|
||||
if (ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext_present) {
|
||||
if (ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present) {
|
||||
if (ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext
|
||||
.non_crit_ext_present) {
|
||||
if (ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext
|
||||
.non_crit_ext.non_crit_ext_present) {
|
||||
auto& ue_cap_v1330 = ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext
|
||||
.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext;
|
||||
if (ue_cap_v1330.non_crit_ext_present) {
|
||||
if (ue_cap_v1330.non_crit_ext.non_crit_ext.non_crit_ext_present) {
|
||||
if (ue_cap_v1330.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present) {
|
||||
if (ue_cap_v1330.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext
|
||||
.non_crit_ext_present) {
|
||||
auto& ue_cap_v1510 = ue_cap_v1330.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext
|
||||
.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext;
|
||||
if (ue_cap_v1510.irat_params_nr_r15_present) {
|
||||
if (ue_cap_v1510.irat_params_nr_r15.en_dc_r15_present) {
|
||||
logger.info("Enabling ENDC support for rnti=%d", rrc_ue->rnti);
|
||||
endc_supported = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Method called whenever the eNB receives a MeasReport from the UE
|
||||
void rrc::ue::rrc_endc::handle_ue_meas_report(const meas_report_s& msg)
|
||||
{
|
||||
// Ignore event if ENDC isn't supported
|
||||
if (not endc_supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (not is_in_state<idle_st>()) {
|
||||
Info("Received a MeasReport while already enabling ENDC support. Ignoring...");
|
||||
return;
|
||||
}
|
||||
// Check if meas_id is valid
|
||||
const meas_results_s& meas_res = msg.crit_exts.c1().meas_report_r8().meas_results;
|
||||
if (not meas_res.meas_result_neigh_cells_present) {
|
||||
Info("Received a MeasReport, but the UE did not detect any cell.");
|
||||
return;
|
||||
}
|
||||
|
||||
// only handle NR cells here, EUTRA is handled in mobility class
|
||||
if (meas_res.meas_result_neigh_cells.type().value !=
|
||||
meas_results_s::meas_result_neigh_cells_c_::types::meas_result_neigh_cell_list_nr_r15) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start EN-DC activation
|
||||
logger.info("Triggering SgNB addition");
|
||||
rrc_enb->rrc_nr->sgnb_addition_request(rrc_ue->rnti);
|
||||
|
||||
sgnb_add_req_sent_ev sgnb_add_req{};
|
||||
trigger(sgnb_add_req);
|
||||
}
|
||||
|
||||
void rrc::ue::rrc_endc::handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15,
|
||||
const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15)
|
||||
{
|
||||
logger.info("Received SgNB addition acknowledgement for rnti=%d", rrc_ue->rnti);
|
||||
|
||||
// prepare reconfiguration message with NR fields
|
||||
srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer();
|
||||
if (pdu == nullptr) {
|
||||
logger.error("Couldn't allocate PDU in %s().", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
// rrc_enb->send_connection_reconf(std::move(pdu));
|
||||
}
|
||||
|
||||
void rrc::ue::rrc_endc::handle_sgnb_addition_reject()
|
||||
{
|
||||
logger.error("Received SgNB addition reject for rnti=%d", rrc_ue->rnti);
|
||||
}
|
||||
|
||||
void rrc::ue::rrc_endc::handle_recfg_complete(wait_recfg_comp& s, const recfg_complete_ev& ev)
|
||||
{
|
||||
logger.info("User rnti=0x%x successfully enabled EN-DC", rrc_ue->rnti);
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue