srsLTE/lib/src/phy/phch/ra_dl_nr.c

276 lines
10 KiB
C
Raw Normal View History

/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/phy/phch/ra_dl_nr.h"
#include "ra_helper.h"
#include "srslte/phy/utils/debug.h"
// Validate S and L combination for TypeA time domain resource allocation
static bool check_time_ra_typeA(uint32_t* S, uint32_t* L)
{
// Check values using Table 5.1.2.1-1
if (*S > 3) {
ERROR("S (%d) is out-of-range {0,1,2,3}\n", *S);
return false;
}
if (*L < 3 || *L > 14) {
ERROR("L (%d) is out-of-range {3,...,14}\n", *L);
return false;
}
uint32_t sum = *S + *L;
if (sum < 3) {
ERROR("The sum of S (%d) and L (%d) is lower than 3\n", *S, *L);
return false;
}
if (sum > 14) {
ERROR("The sum of S (%d) and L (%d) is greater than 14\n", *S, *L);
return false;
}
return true;
}
static bool check_time_ra_typeB(uint32_t* S, uint32_t* L)
{
ERROR("Not implemented\n");
return false;
}
bool srslte_ra_dl_nr_time_validate(srslte_sch_grant_nr_t* grant)
{
if (grant->mapping == srslte_sch_mapping_type_A) {
return check_time_ra_typeA(&grant->S, &grant->L);
} else {
return check_time_ra_typeB(&grant->S, &grant->L);
}
}
int srslte_ra_dl_nr_time_default_A(uint32_t m, srslte_dmrs_sch_typeA_pos_t dmrs_typeA_pos, srslte_sch_grant_nr_t* grant)
{
if (grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (m >= SRSLTE_MAX_NOF_DL_ALLOCATION) {
ERROR("m (%d) is out-of-range\n", m);
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Select k0
grant->k0 = 0;
// Select PDSCH mapping
static srslte_sch_mapping_type_t pdsch_mapping_lut[16] = {srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B};
grant->mapping = pdsch_mapping_lut[m];
static uint32_t S_pos2[SRSLTE_MAX_NOF_DL_ALLOCATION] = {2, 2, 2, 2, 2, 9, 4, 5, 5, 9, 12, 1, 1, 2, 4, 8};
static uint32_t L_pos2[SRSLTE_MAX_NOF_DL_ALLOCATION] = {12, 10, 9, 7, 5, 4, 4, 7, 2, 2, 2, 13, 6, 4, 7, 4};
static uint32_t S_pos3[SRSLTE_MAX_NOF_DL_ALLOCATION] = {3, 3, 3, 3, 3, 10, 6, 5, 5, 9, 12, 1, 1, 2, 4, 8};
static uint32_t L_pos3[SRSLTE_MAX_NOF_DL_ALLOCATION] = {11, 9, 8, 6, 4, 4, 4, 7, 2, 2, 2, 13, 6, 4, 7, 4};
// Select start symbol (S) and length (L)
switch (dmrs_typeA_pos) {
case srslte_dmrs_sch_typeA_pos_2:
grant->S = S_pos2[m];
grant->L = L_pos2[m];
break;
case srslte_dmrs_sch_typeA_pos_3:
grant->S = S_pos3[m];
grant->L = L_pos3[m];
break;
default:
ERROR("Undefined case (%d)\n", dmrs_typeA_pos);
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
static void ra_dl_nr_time_hl(const srslte_sch_time_ra_t* hl_ra_cfg, srslte_sch_grant_nr_t* grant)
{
// Compute S and L from SLIV from higher layers
ra_helper_compute_s_and_l(SRSLTE_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L);
grant->k0 = hl_ra_cfg->k;
grant->mapping = hl_ra_cfg->mapping_type;
}
int srslte_ra_dl_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (m >= SRSLTE_MAX_NOF_DL_ALLOCATION) {
ERROR("m (%d) is out-of-range\n", m);
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Determine which PDSCH Time domain RA configuration to apply (TS 38.214 Table 5.1.2.1.1-1)
if (rnti_type == srslte_rnti_type_si && ss_type == srslte_search_space_type_common_0) {
// Row 1
ERROR("Row not implemented");
} else if (rnti_type == srslte_rnti_type_si && ss_type == srslte_search_space_type_common_0A) {
// Row 2
ERROR("Row not implemented");
} else if ((rnti_type == srslte_rnti_type_ra || rnti_type == srslte_rnti_type_tc) &&
ss_type == srslte_search_space_type_common_1) {
// Row 3
if (cfg->nof_common_time_ra > 0) {
ra_dl_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
// Note: Only Default A is supported, which corresponds SS/PBCH block and coreset mux pattern 1
srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
} else if (rnti_type == srslte_rnti_type_p && ss_type == srslte_search_space_type_common_2) {
// Row 4
ERROR("Row not implemented");
} else if ((rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_mcs_c ||
rnti_type == srslte_rnti_type_cs) &&
SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id == 0) {
// Row 5
if (cfg->nof_common_time_ra > 0) {
ra_dl_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
} else if ((rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_mcs_c ||
rnti_type == srslte_rnti_type_cs) &&
((SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id != 0) || ss_type == srslte_search_space_type_ue)) {
// Row 6
if (cfg->nof_dedicated_time_ra > 0) {
ra_dl_nr_time_hl(&cfg->dedicated_time_ra[m], grant);
} else if (cfg->nof_common_time_ra > 0) {
ra_dl_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
} else {
ERROR("Unhandled case");
}
// Validate S and L parameters
if (!srslte_ra_dl_nr_time_validate(grant)) {
ERROR("Invalid Time RA S=%d; L=%d; m=%d\n", grant->S, grant->L, m);
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_dmrs_sch_cfg_t* cfg,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
/* According to TS 38.214 V15.10.0 5.1.6.1.3 CSI-RS for mobility:
* When receiving PDSCH scheduled by DCI format 1_0, the UE shall assume the number of DM-RS CDM groups without data
* is 1 which corresponds to CDM group 0 for the case of PDSCH with allocation duration of 2 symbols, and the UE
* shall assume that the number of DM-RS CDM groups without data is 2 which corresponds to CDM group {0,1} for all
* other cases.
*/
if (cfg->length == srslte_dmrs_sch_len_2) {
grant->nof_dmrs_cdm_groups_without_data = 1;
} else {
grant->nof_dmrs_cdm_groups_without_data = 2;
}
return SRSLTE_SUCCESS;
}
/* RBG size for type0 scheduling as in table 5.1.2.2.1-1 of 36.214 */
uint32_t srslte_ra_dl_nr_type0_P(uint32_t bwp_size, bool config_is_1)
{
if (bwp_size <= 36) {
return config_is_1 ? 2 : 4;
} else if (bwp_size <= 72) {
return config_is_1 ? 4 : 8;
} else if (bwp_size <= 144) {
return config_is_1 ? 8 : 16;
} else {
return 16;
}
}
static int ra_freq_type0(const srslte_carrier_nr_t* carrier,
const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant)
{
uint32_t P = srslte_ra_dl_nr_type0_P(carrier->nof_prb, cfg->rbg_size_cfg_1);
uint32_t N_rbg = (int)ceilf((float)(carrier->nof_prb + (carrier->start % P)) / P);
uint32_t rbg_offset = 0;
for (uint32_t i = 0; i < N_rbg; i++) {
uint32_t rbg_size = P;
if (i == 0) {
rbg_size -= (carrier->start % P);
} else if ((i == N_rbg - 1) && ((carrier->nof_prb + carrier->start) % P) > 0) {
rbg_size = (carrier->nof_prb + carrier->start) % P;
}
if (dci_dl->freq_domain_assigment & (1 << (N_rbg - i - 1))) {
for (uint32_t j = 0; j < rbg_size; j++) {
if (rbg_offset + j < carrier->nof_prb) {
grant->prb_idx[rbg_offset + j] = true;
grant->nof_prb++;
}
}
}
rbg_offset += rbg_size;
}
return 0;
}
int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL || dci_dl == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// RA scheme
if (dci_dl->format == srslte_dci_format_nr_1_0) {
// when the scheduling grant is received with DCI format 1_0 , then downlink resource allocation type 1 is used.
return ra_helper_freq_type1(carrier->nof_prb, dci_dl->freq_domain_assigment, grant);
}
ra_freq_type0(carrier, cfg, dci_dl, grant);
ERROR("Only DCI Format 1_0 is supported\n");
return SRSLTE_ERROR;
}