SRSUE: Added initial SR procedure for NR

master
Xavier Arteaga 4 years ago committed by David Rupprecht
parent 822abc763e
commit 126fc09b7d

@ -498,6 +498,13 @@ struct phy_cfg_nr_t {
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 2
pucch.sr_resources[1].resource.format = SRSLTE_PUCCH_NR_FORMAT_1;
pucch.sr_resources[1].resource.starting_prb = 0;
pucch.sr_resources[1].resource.initial_cyclic_shift = 8;
pucch.sr_resources[1].resource.nof_symbols = 14;
pucch.sr_resources[1].resource.start_symbol_idx = 0;
pucch.sr_resources[1].resource.time_domain_occ = 2;
// Item 17
// PUCCH-Resource
// pucch-ResourceId: 17
@ -529,6 +536,10 @@ struct phy_cfg_nr_t {
// periodicityAndOffset: sl40 (10)
// sl40: 8
// resource: 16
pucch.sr_resources[1].sr_id = 0;
pucch.sr_resources[1].period = 40;
pucch.sr_resources[1].offset = 8;
pucch.sr_resources[1].configured = true;
// dl-DataToUL-ACK: 7 items
// Item 0

@ -17,6 +17,7 @@
#include "srslte/interfaces/mac_interface_types.h"
#include "srslte/interfaces/rrc_nr_interface_types.h"
#include <array>
#include <set>
#include <string>
namespace srsue {
@ -120,6 +121,7 @@ struct phy_args_nr_t {
srslte::phy_log_args_t log;
srslte_ue_dl_nr_args_t dl;
srslte_ue_ul_nr_args_t ul;
std::set<uint32_t> fixed_sr;
phy_args_nr_t()
{
@ -131,6 +133,8 @@ struct phy_args_nr_t {
ul.nof_max_prb = 100;
ul.pusch.measure_time = true;
ul.pusch.sch.disable_simd = false;
// fixed_sr.insert(0); // Enable SR_id = 0 by default for testing purposes
}
};
@ -156,6 +160,9 @@ public:
const int preamble_index,
const float preamble_received_target_power,
const float ta_base_sec = 0.0f) = 0;
/// Instruct PHY to transmit SR for a given identifier
virtual void sr_send(uint32_t sr_id) = 0;
};
class phy_interface_rrc_nr

@ -77,6 +77,11 @@
*/
#define SRSLTE_PUCCH_NR_MAX_NOF_SETS 4
/**
* Maximum number of SR resources (TS 38.331 maxNrofSR-Resources)
*/
#define SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES 8
typedef enum SRSLTE_API {
SRSLTE_PUCCH_NR_FORMAT_0 = 0,
SRSLTE_PUCCH_NR_FORMAT_1,
@ -142,10 +147,24 @@ typedef struct SRSLTE_API {
uint32_t max_payload_size; ///< Maximum payload size, set to 0 if not present
} srslte_pucch_nr_resource_set_t;
/**
* @brief Scheduling Request resource described in TS 38.331 SchedulingRequestResourceConfig
* @note Every SR configuration corresponds to one or more logical channels (resources)
*/
typedef struct SRSLTE_API {
uint32_t sr_id; ///< Scheduling Request identifier
uint32_t period; ///< Period in slots
uint32_t offset; ///< Offset from beginning of the period in slots
srslte_pucch_nr_resource_t resource; ///< PUCCH resource
bool configured; ///< Set to true if higher layers added this value, otherwise set to false
} srslte_pucch_nr_sr_resource_t;
typedef struct SRSLTE_API {
srslte_pucch_nr_common_cfg_t common; ///< NR-PUCCH configuration common for all formats and resources
srslte_pucch_nr_resource_set_t sets[SRSLTE_PUCCH_NR_MAX_NOF_SETS]; ///< Resource sets, indexed by pucch-ResourceSetId
bool enabled; ///< Set to true if any set is enabled
srslte_pucch_nr_sr_resource_t
sr_resources[SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES]; ///< SR resources, indexed by identifier
} srslte_pucch_nr_hl_cfg_t;
/**

@ -62,7 +62,8 @@ typedef struct SRSLTE_API {
uint16_t rnti; ///< RNTI
uint32_t pucch_resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1
uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or DCI format 1_1
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or 1_1
uint32_t sr_resource_id; ///< Scheduling request resource identifier, only valid if o_sr > 0
} srslte_uci_cfg_nr_t;
/**

@ -75,4 +75,23 @@ SRSLTE_API int srslte_ue_ul_nr_pucch_info(const srslte_pucch_nr_resource_t* reso
char* str,
uint32_t str_len);
/**
* @brief Decides whether the provided slot index within the radio frame is a SR transmission opportunity
*
* @remark Implemented according to TS 38.213 9.2.4 UE procedure for reporting SR
*
* @param sr_resources Provides the SR configuration from the upper layers
* @param slot_idx Slot index in the radio frame
* @param sr_id Scheduling Request logic channel identifier
* @param[out] sr_resource_id Optional SR resource index (or identifier)
*
* @return 1 if the provided slot index is a SR transmission opportunity, SRSLTE_SUCCESS if it is not an SR transmission
* opportunity, SRSLTE_ERROR code if provided parameters are invalid
*/
SRSLTE_API int
srslte_ue_ul_nr_sr_send_slot(const srslte_pucch_nr_sr_resource_t sr_resources[SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES],
uint32_t slot_idx,
uint32_t sr_id,
uint32_t* sr_resource_id);
#endif // SRSLTE_UE_UL_DATA_H

@ -450,12 +450,32 @@ int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
const srslte_uci_cfg_nr_t* uci_cfg,
srslte_pucch_nr_resource_t* resource)
{
if (pucch_cfg == NULL || uci_cfg == NULL) {
if (pucch_cfg == NULL || uci_cfg == NULL || resource == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
uint32_t O_uci = srslte_uci_nr_total_bits(uci_cfg);
// Scheduling request has preference see 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR in a PUCCH
if (uci_cfg->o_sr > 0) {
uint32_t sr_resource_id = uci_cfg->sr_resource_id;
if (sr_resource_id >= SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES) {
ERROR("SR resource ID (%d) exceeds the maximum ID (%d)", sr_resource_id, SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES);
return SRSLTE_ERROR;
}
if (!pucch_cfg->sr_resources[sr_resource_id].configured) {
ERROR("SR resource ID (%d) is not configured", sr_resource_id);
return SRSLTE_ERROR;
}
// Set PUCCH resource
*resource = pucch_cfg->sr_resources[sr_resource_id].resource;
// No more logic is required in this case
return SRSLTE_SUCCESS;
}
// If a UE does not have dedicated PUCCH resource configuration, provided by PUCCH-ResourceSet in PUCCH-Config,
// a PUCCH resource set is provided by pucch-ResourceCommon through an index to a row of Table 9.2.1-1 for size
// transmission of HARQ-ACK information on PUCCH in an initial UL BWP of N BWP PRBs.

@ -139,8 +139,20 @@ static int ue_ul_nr_encode_pucch_format1(srslte_ue_ul_nr_t* q,
const srslte_uci_data_nr_t* uci_data)
{
uint8_t b[SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS] = {};
b[0] = uci_data->value.ack[0];
uint32_t nof_bits = 1;
// Set ACK bits
uint32_t nof_bits = SRSLTE_MIN(SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS, uci_data->cfg.o_ack);
for (uint32_t i = 0; i < nof_bits; i++) {
b[i] = uci_data->value.ack[i];
}
// 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_data->cfg.o_sr > 0 && uci_data->value.sr[0] != 0) {
b[0] = 0;
nof_bits = 1;
}
if (srslte_dmrs_pucch_format1_put(&q->pucch, &q->carrier, cfg, slot, resource, q->sf_symbols[0])) {
return SRSLTE_ERROR;
@ -238,3 +250,40 @@ int srslte_ue_ul_nr_pucch_info(const srslte_pucch_nr_resource_t* resource,
return len;
}
int srslte_ue_ul_nr_sr_send_slot(const srslte_pucch_nr_sr_resource_t sr_resources[SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES],
uint32_t slot_idx,
uint32_t sr_id,
uint32_t* sr_resource_id)
{
// Check inputs
if (sr_resources == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Iterate over all SR resources
for (uint32_t i = 0; i < SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES; i++) {
const srslte_pucch_nr_sr_resource_t* res = &sr_resources[i];
// Skip if resource is not provided
if (!res->configured) {
continue;
}
// Skip if SR identifier does not match
if (sr_id != res->sr_id) {
continue;
}
// Check periodicity and offset condition
if ((slot_idx + res->period - res->offset) % res->period == 0) {
if (sr_resource_id != NULL) {
*sr_resource_id = i;
}
return 1;
}
}
// If the program reached this point is because there is no SR transmission opportunity
return SRSLTE_SUCCESS;
}

@ -47,6 +47,9 @@ private:
srslte::circular_array<srslte_pdsch_ack_nr_t, TTIMOD_SZ> pending_ack = {};
mutable std::mutex pending_ack_mutex;
/// Pending scheduling request identifiers
std::set<uint32_t> pending_sr_id;
public:
mac_interface_phy_nr* stack = nullptr;
srslte_carrier_nr_t carrier = {};
@ -240,6 +243,35 @@ public:
return true;
}
void reset() { pending_sr_id.clear(); }
void set_pending_sr(uint32_t value) { pending_sr_id.insert(value); }
void get_pending_sr(const uint32_t& tti, srslte_uci_data_nr_t& uci_data)
{
// Append fixed SR
pending_sr_id.insert(args.fixed_sr.begin(), args.fixed_sr.end());
// Iterate all SR IDs
for (const uint32_t& sr_id : pending_sr_id) {
uint32_t sr_resource_id = 0;
// Check if there is an SR transmission opportunity for the given SR identifier in any SR logic channel
if (srslte_ue_ul_nr_sr_send_slot(cfg.pucch.sr_resources, tti, sr_id, &sr_resource_id) > SRSLTE_SUCCESS) {
// Set UCI data
uci_data.cfg.o_sr = 1;
uci_data.cfg.sr_resource_id = sr_resource_id;
uci_data.value.sr[0] = 1;
// Remove pending SR
pending_sr_id.erase(sr_id);
// Only one SR is supported
return;
}
}
}
};
} // namespace nr
} // namespace srsue

@ -41,6 +41,7 @@ public:
void send_prach(uint32_t prach_occasion, uint32_t preamble_index, int preamble_received_target_power);
int set_ul_grant(std::array<uint8_t, SRSLTE_RAR_UL_GRANT_NBITS> array, uint16_t rnti, srslte_rnti_type_t rnti_type);
bool set_config(const srslte::phy_cfg_nr_t& cfg);
void sr_send(uint32_t sr_id);
};
} // namespace nr

@ -66,9 +66,7 @@ private:
srslte::block_queue<std::function<void(void)> > cmd_queue;
};
class phy final : public ue_lte_phy_base,
public ue_nr_phy_base,
public srslte::thread
class phy final : public ue_lte_phy_base, public ue_nr_phy_base, public srslte::thread
{
public:
explicit phy(srslog::sink& log_sink) :
@ -184,6 +182,7 @@ public:
const float ta_base_sec = 0.0f) final;
int tx_request(const tx_request_t& request) final;
void set_earfcn(std::vector<uint32_t> earfcns) final;
void sr_send(uint32_t sr_id) final;
private:
void run_thread() final;

@ -59,6 +59,7 @@ public:
const int prach_occasion,
const float target_power_dbm,
const float ta_base_sec = 0.0f) override{};
void sr_send(uint32_t sr_id) override;
private:
std::unique_ptr<srslte::srslte_basic_vnf> vnf;

@ -259,7 +259,7 @@ bool cc_worker::work_ul()
srslte_sch_cfg_nr_t pusch_cfg = {};
bool has_pusch_grant = phy->get_ul_pending_grant(ul_slot_cfg.idx, pusch_cfg, pid);
// If PDSCH UL AKC is available, load into UCI
// If PDSCH UL ACK is available, load into UCI
if (has_ul_ack) {
pdsch_ack.use_pusch = has_pusch_grant;
if (srslte_ue_dl_nr_gen_ack(&phy->cfg.harq_ack, &pdsch_ack, &uci_data) < SRSLTE_SUCCESS) {
@ -268,6 +268,9 @@ bool cc_worker::work_ul()
}
}
// Add SR to UCI data if available
phy->get_pending_sr(ul_slot_cfg.idx, uci_data);
if (has_pusch_grant) {
// Notify MAC about PUSCH found grant
mac_interface_phy_nr::tb_action_ul_t ul_action = {};

@ -1,17 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsue/hdr/phy/nr/state.h"
namespace srsue {
namespace nr {}
} // namespace srsue

@ -134,5 +134,10 @@ bool worker_pool::set_config(const srslte::phy_cfg_nr_t& cfg)
phy_state.cfg = cfg;
return true;
}
void worker_pool::sr_send(uint32_t sr_id)
{
phy_state.set_pending_sr(sr_id);
}
} // namespace nr
} // namespace srsue

@ -644,4 +644,8 @@ bool phy::set_config(const srslte::phy_cfg_nr_t& cfg)
return nr_workers.set_config(cfg);
}
void phy::sr_send(uint32_t sr_id)
{
nr_workers.sr_send(sr_id);
}
} // namespace srsue

@ -73,5 +73,6 @@ bool vnf_phy_nr::set_config(const srslte::phy_cfg_nr_t& cfg)
{
return false;
}
void vnf_phy_nr::sr_send(uint32_t sr_id) {}
} // namespace srsue

@ -23,14 +23,14 @@ public:
void send_prach(const uint32_t prach_occasion_,
const int preamble_index_,
const float preamble_received_target_power_,
const float ta_base_sec_ = 0.0f)
const float ta_base_sec_ = 0.0f) override
{
prach_occasion = prach_occasion_;
preamble_index = preamble_index_;
preamble_received_target_power = preamble_received_target_power_;
}
int tx_request(const tx_request_t& request) { return 0; }
int set_ul_grant(std::array<uint8_t, SRSLTE_RAR_UL_GRANT_NBITS>, uint16_t rnti, srslte_rnti_type_t rnti_type)
int tx_request(const tx_request_t& request) override { return 0; }
int set_ul_grant(std::array<uint8_t, SRSLTE_RAR_UL_GRANT_NBITS>, uint16_t rnti, srslte_rnti_type_t rnti_type) override
{
return 0;
}
@ -41,6 +41,7 @@ public:
*preamble_index_ = preamble_index;
*preamble_received_target_power_ = preamble_received_target_power;
}
void sr_send(uint32_t sr_id) override {}
private:
uint32_t prach_occasion;

Loading…
Cancel
Save