Packed NR TDD config in duplex configuration and created test case for FDD

This commit is contained in:
Xavier Arteaga 2021-09-21 15:11:05 +02:00 committed by Andre Puschmann
parent 53bf29a540
commit 0324806d6c
17 changed files with 214 additions and 127 deletions

View File

@ -73,7 +73,7 @@ void to_asn1(asn1::rrc_nr::plmn_id_s* asn1_type, const plmn_id_t& cfg);
bool make_phy_rach_cfg(const asn1::rrc_nr::rach_cfg_common_s& asn1_type, srsran_prach_cfg_t* prach_cfg);
bool make_phy_tdd_cfg(const asn1::rrc_nr::tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
srsran_tdd_config_nr_t* srsran_tdd_config_nr);
srsran_duplex_config_nr_t* srsran_duplex_config_nr);
bool make_phy_harq_ack_cfg(const asn1::rrc_nr::phys_cell_group_cfg_s& phys_cell_group_cfg,
srsran_harq_ack_cfg_hl_t* srsran_ue_dl_nr_harq_ack_cfg);
bool make_phy_coreset_cfg(const asn1::rrc_nr::ctrl_res_set_s& ctrl_res_set, srsran_coreset_t* srsran_coreset);

View File

@ -35,16 +35,16 @@ struct phy_cfg_nr_t {
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;
srsran_duplex_config_nr_t duplex = {};
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() {}

View File

@ -43,18 +43,23 @@ public:
const std::array<std::string, R_CARRIER_COUNT> R_CARRIER_STRING = {{"10MHz", "20MHz"}};
enum {
/**
* @brief FDD, all slots for DL and UL
*/
R_DUPLEX_FDD = 0,
/**
* @brief TDD custom reference 5 slot DL and 5 slot UL
*/
R_TDD_CUSTOM_6_4 = 0,
R_DUPLEX_TDD_CUSTOM_6_4,
/**
* @brief TDD pattern FR1.15-1 defined in TS38.101-4 Table A.1.2-1
*/
R_TDD_FR1_15_1,
R_TDD_COUNT,
} tdd = R_TDD_CUSTOM_6_4;
const std::array<std::string, R_TDD_COUNT> R_TDD_STRING = {{"6D+4U", "FR1.15-1"}};
R_DUPLEX_TDD_FR1_15_1,
R_DUPLEX_COUNT,
} duplex = R_DUPLEX_TDD_CUSTOM_6_4;
const std::array<std::string, R_DUPLEX_COUNT> R_DUPLEX_STRING = {{"FDD", "6D+4U", "FR1.15-1"}};
enum {
/**
@ -144,8 +149,8 @@ private:
/**
* TDD make helper methods
*/
static void make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd);
static void make_tdd_fr1_15_1(srsran_tdd_config_nr_t& tdd);
static void make_tdd_custom_6_4(srsran_duplex_config_nr_t& duplex);
static void make_tdd_fr1_15_1(srsran_duplex_config_nr_t& duplex);
/**
* PDCCH make helper methods
@ -171,9 +176,9 @@ private:
/**
* 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);
static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
const srsran_carrier_nr_t& carrier,
const srsran_duplex_config_nr_t& duplex_cfg);
/**
* PRACH make helper methods

View File

@ -458,6 +458,17 @@ typedef struct SRSRAN_API {
srsran_tdd_pattern_t pattern2;
} srsran_tdd_config_nr_t;
/**
* @brief Describes duplex configuration
*/
typedef struct SRSRAN_API {
srsran_duplex_mode_t mode;
union {
srsran_tdd_config_nr_t tdd; ///< TDD configuration
// ... add here other mode parameters
};
} srsran_duplex_config_nr_t;
/**
* @brief Describes a measurement based on NZP-CSI-RS or SSB-CSI
* @note Used for tracking RSRP, SNR, CFO, SFO, and so on
@ -593,21 +604,21 @@ SRSRAN_API float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subca
/**
* @brief Decides whether a given slot is configured as Downlink
* @param cfg Provides TDD configuration
* @param cfg Provides the carrier duplex configuration
* @param numerology Provides BWP numerology
* @param slot_idx Slot index in the frame for the given numerology
* @return true if the provided slot index is configured for Downlink
*/
SRSRAN_API bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx);
SRSRAN_API bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx);
/**
* @brief Decides whether a given slot is configured as Uplink
* @param cfg Provides TDD configuration
* @param cfg Provides the carrier duplex configuration
* @param numerology Provides BWP numerology
* @param slot_idx Slot index in the frame for the given numerology
* @return true if the provided slot index is configured for Uplink
*/
SRSRAN_API bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx);
SRSRAN_API bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx);
SRSRAN_API int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell);

View File

@ -271,21 +271,21 @@ bool make_phy_rach_cfg(const rach_cfg_common_s& asn1_type, srsran_prach_cfg_t* p
};
bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
srsran_tdd_config_nr_t* in_srsran_tdd_config_nr)
srsran_duplex_config_nr_t* in_srsran_duplex_config_nr)
{
srsran_tdd_config_nr_t srsran_tdd_config_nr = {};
srsran_duplex_config_nr_t srsran_duplex_config_nr = {};
switch (tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity) {
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1:
srsran_tdd_config_nr.pattern1.period_ms = 1;
srsran_duplex_config_nr.tdd.pattern1.period_ms = 1;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2:
srsran_tdd_config_nr.pattern1.period_ms = 2;
srsran_duplex_config_nr.tdd.pattern1.period_ms = 2;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5:
srsran_tdd_config_nr.pattern1.period_ms = 5;
srsran_duplex_config_nr.tdd.pattern1.period_ms = 5;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10:
srsran_tdd_config_nr.pattern1.period_ms = 10;
srsran_duplex_config_nr.tdd.pattern1.period_ms = 10;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25:
@ -297,12 +297,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity.to_string());
return false;
}
srsran_tdd_config_nr.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots;
srsran_tdd_config_nr.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols;
srsran_tdd_config_nr.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots;
srsran_tdd_config_nr.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols;
srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots;
srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols;
srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots;
srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols;
// Copy and return struct
*in_srsran_tdd_config_nr = srsran_tdd_config_nr;
*in_srsran_duplex_config_nr = srsran_duplex_config_nr;
if (not tdd_ul_dl_cfg_common.pattern2_present) {
return true;
@ -310,16 +310,16 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
switch (tdd_ul_dl_cfg_common.pattern2.dl_ul_tx_periodicity) {
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1:
srsran_tdd_config_nr.pattern2.period_ms = 1;
srsran_duplex_config_nr.tdd.pattern2.period_ms = 1;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2:
srsran_tdd_config_nr.pattern2.period_ms = 2;
srsran_duplex_config_nr.tdd.pattern2.period_ms = 2;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5:
srsran_tdd_config_nr.pattern2.period_ms = 5;
srsran_duplex_config_nr.tdd.pattern2.period_ms = 5;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10:
srsran_tdd_config_nr.pattern2.period_ms = 10;
srsran_duplex_config_nr.tdd.pattern2.period_ms = 10;
break;
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25:
@ -332,12 +332,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
return false;
}
srsran_tdd_config_nr.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots;
srsran_tdd_config_nr.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols;
srsran_tdd_config_nr.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots;
srsran_tdd_config_nr.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols;
srsran_duplex_config_nr.tdd.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots;
srsran_duplex_config_nr.tdd.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols;
srsran_duplex_config_nr.tdd.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots;
srsran_duplex_config_nr.tdd.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols;
// Copy and return struct
*in_srsran_tdd_config_nr = srsran_tdd_config_nr;
*in_srsran_duplex_config_nr = srsran_duplex_config_nr;
return true;
}

View File

@ -44,13 +44,13 @@ phy_cfg_nr_default_t::reference_cfg_t::reference_cfg_t(const std::string& args)
}
}
srsran_assert(carrier != R_CARRIER_COUNT, "Invalid carrier reference configuration '%s'", param.back().c_str());
} else if (param.front() == "tdd") {
for (tdd = R_TDD_CUSTOM_6_4; tdd < R_TDD_COUNT; tdd = inc(tdd)) {
if (R_TDD_STRING[tdd] == param.back()) {
} else if (param.front() == "duplex") {
for (duplex = R_DUPLEX_FDD; duplex < R_DUPLEX_COUNT; duplex = inc(duplex)) {
if (R_DUPLEX_STRING[duplex] == param.back()) {
break;
}
}
srsran_assert(tdd != R_TDD_COUNT, "Invalid TDD reference configuration '%s'", param.back().c_str());
srsran_assert(duplex != R_DUPLEX_COUNT, "Invalid duplex reference configuration '%s'", param.back().c_str());
} else if (param.front() == "pdsch") {
for (pdsch = R_PDSCH_DEFAULT; pdsch < R_PDSCH_COUNT; pdsch = inc(pdsch)) {
if (R_PDSCH_STRING[pdsch] == param.back()) {
@ -86,8 +86,18 @@ void phy_cfg_nr_default_t::make_carrier_custom_20MHz(srsran_carrier_nr_t& carrie
carrier.scs = srsran_subcarrier_spacing_15kHz;
}
void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd)
void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_duplex_config_nr_t& conf)
{
// Set the duplex mode to TDD
conf.mode = SRSRAN_DUPLEX_MODE_TDD;
// Select TDD config
srsran_tdd_config_nr_t& tdd = conf.tdd;
// Initialise pattern
tdd = {};
// Enable pattern 1
tdd.pattern1.period_ms = 10;
tdd.pattern1.nof_dl_slots = 6;
tdd.pattern1.nof_dl_symbols = 0;
@ -98,8 +108,17 @@ void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd)
tdd.pattern2.period_ms = 0;
}
void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_tdd_config_nr_t& tdd)
{
void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_duplex_config_nr_t& conf)
{ // Set the duplex mode to TDD
conf.mode = SRSRAN_DUPLEX_MODE_TDD;
// Select TDD config
srsran_tdd_config_nr_t& tdd = conf.tdd;
// Initialise pattern
tdd = {};
// Enable pattern 1
tdd.pattern1.period_ms = 5;
tdd.pattern1.nof_dl_slots = 3;
tdd.pattern1.nof_dl_symbols = 10;
@ -319,32 +338,39 @@ void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch
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)
void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
const srsran_carrier_nr_t& carrier,
const srsran_duplex_config_nr_t& duplex_cfg)
{
// Generate as many entries as DL slots
harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL);
if (tdd_cfg.pattern1.nof_dl_symbols > 0) {
harq.nof_dl_data_to_ul_ack++;
}
if (duplex_cfg.mode == SRSRAN_DUPLEX_MODE_TDD) {
const srsran_tdd_config_nr_t& tdd_cfg = duplex_cfg.tdd;
// 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 (harq.nof_dl_data_to_ul_ack >= 4 and 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;
// Generate as many entries as DL slots
harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL);
if (tdd_cfg.pattern1.nof_dl_symbols > 0) {
harq.nof_dl_data_to_ul_ack++;
}
// 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;
}
// 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 (harq.nof_dl_data_to_ul_ack >= 4 and 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;
}
// Otherwise set delay to the first UL slot of the next TDD period
harq.dl_data_to_ul_ack[n] = (tdd_cfg.pattern1.period_ms + tdd_cfg.pattern1.nof_dl_slots) - n;
// After that try if n+4 is UL slot
if (srsran_duplex_nr_is_ul(&duplex_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] = (tdd_cfg.pattern1.period_ms + tdd_cfg.pattern1.nof_dl_slots) - n;
}
} else {
harq.dl_data_to_ul_ack[0] = 4;
harq.nof_dl_data_to_ul_ack = 1;
}
// Zero the rest
@ -377,14 +403,17 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
srsran_assertion_failure("Invalid carrier reference");
}
switch (reference_cfg.tdd) {
case reference_cfg_t::R_TDD_CUSTOM_6_4:
make_tdd_custom_6_4(tdd);
switch (reference_cfg.duplex) {
case reference_cfg_t::R_DUPLEX_FDD:
duplex.mode = SRSRAN_DUPLEX_MODE_FDD;
break;
case reference_cfg_t::R_TDD_FR1_15_1:
make_tdd_fr1_15_1(tdd);
case reference_cfg_t::R_DUPLEX_TDD_CUSTOM_6_4:
make_tdd_custom_6_4(duplex);
break;
case reference_cfg_t::R_TDD_COUNT:
case reference_cfg_t::R_DUPLEX_TDD_FR1_15_1:
make_tdd_fr1_15_1(duplex);
break;
case reference_cfg_t::R_DUPLEX_COUNT:
srsran_assertion_failure("Invalid TDD reference");
}
@ -419,7 +448,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
switch (reference_cfg.harq) {
case reference_cfg_t::R_HARQ_AUTO:
make_harq_auto(harq_ack, carrier, tdd);
make_harq_auto(harq_ack, carrier, duplex);
break;
}

View File

@ -283,13 +283,8 @@ float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subcarrier_spaci
return srsran_symbol_offset_s(l1, scs) - srsran_symbol_offset_s(l0, scs);
}
bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
static bool tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
{
// Protect NULL pointer access
if (cfg == NULL) {
return false;
}
// Prevent zero division
if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) {
return false;
@ -312,13 +307,24 @@ bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology,
(slot_idx_period == pattern->nof_dl_slots && pattern->nof_dl_symbols != 0));
}
bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
{
// Protect NULL pointer access
if (cfg == NULL) {
return false;
}
// In case of TDD
if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) {
return tdd_nr_is_dl(&cfg->tdd, numerology, slot_idx);
}
return true;
}
static bool tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
{
// Prevent zero division
if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) {
return false;
@ -343,6 +349,21 @@ bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology,
return (slot_idx_period > start_ul || (slot_idx_period == start_ul && pattern->nof_ul_symbols != 0));
}
bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx)
{
// Protect NULL pointer access
if (cfg == NULL) {
return false;
}
// In case of TDD
if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) {
return tdd_nr_is_ul(&cfg->tdd, numerology, slot_idx);
}
return true;
}
int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell)
{
// Protect memory access

View File

@ -88,15 +88,15 @@ int make_phy_tdd_cfg_test()
tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots = 2;
tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols = 4;
srsran_tdd_config_nr_t srsran_tdd_config_nr;
TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_tdd_config_nr) == true);
srsran_duplex_config_nr_t srsran_duplex_config_nr;
TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_duplex_config_nr) == true);
TESTASSERT(srsran_tdd_config_nr.pattern1.period_ms == 10);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_slots == 7);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_symbols == 6);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_slots == 2);
TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_symbols == 4);
TESTASSERT(srsran_tdd_config_nr.pattern2.period_ms == 0);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.period_ms == 10);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots == 7);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols == 6);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots == 2);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols == 4);
TESTASSERT(srsran_duplex_config_nr.tdd.pattern2.period_ms == 0);
return SRSRAN_SUCCESS;
}

View File

@ -60,7 +60,7 @@ public:
struct cell_cfg_t {
srsran_carrier_nr_t carrier = {};
srsran_tdd_config_nr_t tdd = {};
srsran_duplex_config_nr_t duplex = {};
srsran::phy_cfg_nr_t::ssb_cfg_t ssb = {};
srsran::bounded_vector<bwp_cfg_t, SCHED_NR_MAX_BWP_PER_CELL> bwps{1}; // idx0 for BWP-common
};

View File

@ -37,8 +37,8 @@ bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, ui
uint32_t nof_slots = SRSRAN_NSLOTS_PER_FRAME_NR(cfg.numerology_idx);
for (size_t sl = 0; sl < nof_slots; ++sl) {
slot_cfg sl_cfg{};
sl_cfg.is_dl = srsran_tdd_nr_is_dl(&cell_cfg.tdd, cfg.numerology_idx, sl);
sl_cfg.is_ul = srsran_tdd_nr_is_ul(&cell_cfg.tdd, cfg.numerology_idx, sl);
sl_cfg.is_dl = srsran_duplex_nr_is_dl(&cell_cfg.duplex, cfg.numerology_idx, sl);
sl_cfg.is_ul = srsran_duplex_nr_is_ul(&cell_cfg.duplex, cfg.numerology_idx, sl);
slots.push_back(sl_cfg);
}

View File

@ -61,15 +61,15 @@ slot_ue ue_carrier::try_reserve(slot_point pdcch_slot,
sfu.dl_pending_bytes = dl_pending_bytes;
sfu.ul_pending_bytes = ul_pending_bytes;
const srsran_tdd_config_nr_t& tdd_cfg = cell_params.cell_cfg.tdd;
if (srsran_tdd_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) {
const srsran_duplex_config_nr_t& tdd_cfg = cell_params.cell_cfg.duplex;
if (srsran_duplex_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) {
// If DL enabled
sfu.h_dl = harq_ent.find_pending_dl_retx();
if (sfu.h_dl == nullptr and sfu.dl_pending_bytes > 0) {
sfu.h_dl = harq_ent.find_empty_dl_harq();
}
}
if (srsran_tdd_nr_is_ul(&tdd_cfg, 0, sfu.pusch_slot.slot_idx())) {
if (srsran_duplex_nr_is_ul(&tdd_cfg, 0, sfu.pusch_slot.slot_idx())) {
// If UL enabled
sfu.h_ul = harq_ent.find_pending_ul_retx();
if (sfu.h_ul == nullptr and sfu.ul_pending_bytes > 0) {

View File

@ -36,7 +36,7 @@ inline sched_nr_interface::cell_cfg_t get_default_cell_cfg(
sched_nr_interface::cell_cfg_t cell_cfg{};
cell_cfg.carrier = phy_cfg.carrier;
cell_cfg.tdd = phy_cfg.tdd;
cell_cfg.duplex = phy_cfg.duplex;
cell_cfg.bwps.resize(1);
cell_cfg.bwps[0].pdcch = phy_cfg.pdcch;

View File

@ -82,7 +82,7 @@ void sched_nr_cfg_serialized_test()
uint32_t max_nof_ttis = 1000, nof_sectors = 4;
task_job_manager tasks;
sched_nr_interface::sched_cfg_t cfg;
sched_nr_interface::sched_cfg_t cfg;
cfg.auto_refill_buffer = true;
std::vector<sched_nr_interface::cell_cfg_t> cells_cfg = get_default_cells_cfg(nof_sectors);
@ -111,7 +111,7 @@ void sched_nr_cfg_serialized_test()
sched_nr_cc_output_res_t out{slot_tx, cc, &dl_res, &ul_res};
sched_tester.update(out);
tasks.finish_cc(slot_rx, dl_res, ul_res);
TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (slot_tx).slot_idx()) or
TESTASSERT(not srsran_duplex_nr_is_dl(&cells_cfg[cc].duplex, 0, (slot_tx).slot_idx()) or
dl_res.dl_sched.pdcch_dl.size() == 1);
}
}

View File

@ -475,7 +475,7 @@ bool cc_worker::work_dl()
}
// Check if it is a DL slot, if not skip
if (!srsran_tdd_nr_is_dl(&phy.cfg.tdd, 0, dl_slot_cfg.idx)) {
if (!srsran_duplex_nr_is_dl(&phy.cfg.duplex, 0, dl_slot_cfg.idx)) {
return true;
}
@ -523,7 +523,7 @@ bool cc_worker::work_ul()
bool has_ul_ack = phy.get_pending_ack(ul_slot_cfg.idx, pdsch_ack);
// Check if it is a UL slot, if not skip
if (!srsran_tdd_nr_is_ul(&phy.cfg.tdd, 0, ul_slot_cfg.idx)) {
if (!srsran_duplex_nr_is_ul(&phy.cfg.duplex, 0, ul_slot_cfg.idx)) {
// No NR signal shall be transmitted
srsran_vec_cf_zero(tx_buffer[0], ue_ul.ifft.sf_sz);

View File

@ -1193,11 +1193,11 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg)
}
if (recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present) {
srsran_tdd_config_nr_t tdd;
if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &tdd) == true) {
phy_cfg.tdd = tdd;
srsran_duplex_config_nr_t duplex;
if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &duplex) == true) {
phy_cfg.duplex = duplex;
} else {
logger.warning("Warning while building tdd structure");
logger.warning("Warning while building duplex structure");
return false;
}
} else {

View File

@ -25,15 +25,18 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
${Boost_LIBRARIES}
${ATOMIC_LIBS})
# For each supported bandwidth
foreach (NR_PHY_TEST_BW "10MHz" "20MHz")
foreach (NR_PHY_TEST_TDD "6D+4U" "FR1.15-1")
# For each supported frame structure
foreach (NR_PHY_TEST_DUPLEX "FDD" "6D+4U" "FR1.15-1")
set(NR_PHY_TEST_DURATION_MS 20)
# DL flooding only
foreach (NR_PHY_TEST_PDSCH "default" "ts38101/5.2-1")
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD},pdsch=${NR_PHY_TEST_PDSCH}
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX},pdsch=${NR_PHY_TEST_PDSCH}
--duration=${NR_PHY_TEST_DURATION_MS}
--gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots
--gnb.stack.pdsch.slots=all
--gnb.stack.pdsch.start=0 # Start at RB 0
--gnb.stack.pdsch.length=52 # Full 10 MHz BW
--gnb.stack.pdsch.mcs=27 # Maximum MCS
@ -43,11 +46,12 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
)
endforeach ()
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_ul_only nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD}
# UL flooding
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_ul_only nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX}
--duration=${NR_PHY_TEST_DURATION_MS}
--gnb.stack.pdsch.slots=6 # No PDSCH
--gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots
--gnb.stack.pdsch.slots=none
--gnb.stack.pusch.slots=all
--gnb.stack.pusch.start=0 # Start at RB 0
--gnb.stack.pusch.length=52 # Full 10 MHz BW
--gnb.stack.pusch.mcs=28 # Maximum MCS
@ -55,14 +59,15 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
--ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS}
)
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_bidir nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD}
# DL and UL flooding
add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_bidir nr_phy_test
--reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX}
--duration=${NR_PHY_TEST_DURATION_MS}
--gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots
--gnb.stack.pdsch.slots=all
--gnb.stack.pdsch.start=0 # Start at RB 0
--gnb.stack.pdsch.length=52 # Full 10 MHz BW
--gnb.stack.pdsch.mcs=28 # Maximum MCS
--gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots
--gnb.stack.pusch.slots=all
--gnb.stack.pusch.start=0 # Start at RB 0
--gnb.stack.pusch.length=52 # Full 10 MHz BW
--gnb.stack.pusch.mcs=28 # Maximum MCS

View File

@ -360,10 +360,22 @@ public:
ul.mcs = args.pusch.mcs;
if (args.pdsch.slots != "none" and not args.pdsch.slots.empty()) {
srsran::string_parse_list(args.pdsch.slots, ',', dl.slots);
if (args.pdsch.slots == "all") {
for (uint32_t n = 0; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) {
dl.slots.insert(n);
}
} else {
srsran::string_parse_list(args.pdsch.slots, ',', dl.slots);
}
}
if (args.pusch.slots != "none" and not args.pusch.slots.empty()) {
srsran::string_parse_list(args.pusch.slots, ',', ul.slots);
if (args.pusch.slots == "all") {
for (uint32_t n = 0; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) {
ul.slots.insert(n);
}
} else {
srsran::string_parse_list(args.pusch.slots, ',', ul.slots);
}
}
// Select DCI locations
@ -405,7 +417,11 @@ public:
// Setup DL Data to ACK timing
for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) {
dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.tdd.pattern1.period_ms];
if (args.phy_cfg.duplex.mode == SRSRAN_DUPLEX_MODE_TDD) {
dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.duplex.tdd.pattern1.period_ms];
} else {
dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.harq_ack.nof_dl_data_to_ul_ack];
}
}
// If reached this point the configuration is valid
@ -441,7 +457,7 @@ public:
}
// Check if it is TDD DL slot and PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip
if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) {
if (not srsran_duplex_nr_is_dl(&phy_cfg.duplex, phy_cfg.carrier.scs, slot_cfg.idx)) {
return SRSRAN_SUCCESS;
}
@ -451,7 +467,7 @@ public:
}
// Check if the UL slot is valid, if not skip UL scheduling
if (not srsran_tdd_nr_is_ul(&phy_cfg.tdd, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) {
if (not srsran_duplex_nr_is_ul(&phy_cfg.duplex, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) {
return SRSRAN_SUCCESS;
}