2020-11-26 01:25:22 -08:00
|
|
|
/**
|
2020-10-16 00:52:55 -07:00
|
|
|
*
|
2020-11-26 01:25:22 -08:00
|
|
|
* \section COPYRIGHT
|
2020-10-16 00:52:55 -07:00
|
|
|
*
|
2021-03-19 03:45:56 -07:00
|
|
|
* Copyright 2013-2021 Software Radio Systems Limited
|
2020-10-16 00:52:55 -07:00
|
|
|
*
|
2020-11-26 01:25:22 -08:00
|
|
|
* 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.
|
2020-10-16 00:52:55 -07:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
#include "srsran/phy/phch/pdcch_nr.h"
|
|
|
|
#include "srsran/phy/common/sequence.h"
|
|
|
|
#include "srsran/phy/fec/polar/polar_chanalloc.h"
|
|
|
|
#include "srsran/phy/fec/polar/polar_interleaver.h"
|
|
|
|
#include "srsran/phy/mimo/precoding.h"
|
|
|
|
#include "srsran/phy/modem/demod_soft.h"
|
|
|
|
#include "srsran/phy/utils/bit.h"
|
|
|
|
#include "srsran/phy/utils/debug.h"
|
|
|
|
#include "srsran/phy/utils/vector.h"
|
2020-10-16 00:52:55 -07:00
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
#define PDCCH_NR_POLAR_RM_IBIL 0
|
|
|
|
|
2020-11-30 09:00:24 -08:00
|
|
|
#define PDCCH_INFO_TX(...) INFO("PDCCH Tx: " __VA_ARGS__)
|
|
|
|
#define PDCCH_INFO_RX(...) INFO("PDCCH Rx: " __VA_ARGS__)
|
|
|
|
|
2020-10-16 00:52:55 -07:00
|
|
|
/**
|
|
|
|
* @brief Recursive Y_p_n function
|
|
|
|
*/
|
2021-03-19 03:45:56 -07:00
|
|
|
static uint32_t srsran_pdcch_calculate_Y_p_n(uint32_t coreset_id, uint16_t rnti, uint32_t n)
|
2020-10-16 00:52:55 -07:00
|
|
|
{
|
|
|
|
static const uint32_t A_p[3] = {39827, 39829, 39839};
|
|
|
|
const uint32_t D = 65537;
|
|
|
|
|
2021-03-11 00:52:08 -08:00
|
|
|
uint32_t Y_p_n = (uint32_t)rnti;
|
|
|
|
for (uint32_t i = 0; i <= n; i++) {
|
|
|
|
Y_p_n = (A_p[coreset_id % 3] * Y_p_n) % D;
|
2020-10-16 00:52:55 -07:00
|
|
|
}
|
|
|
|
|
2021-03-11 00:52:08 -08:00
|
|
|
return Y_p_n;
|
2020-10-16 00:52:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculates the Control Channnel Element As described in 3GPP 38.213 R15 10.1 UE procedure for determining physical
|
|
|
|
* downlink control channel assignment
|
|
|
|
*
|
|
|
|
*/
|
2021-03-19 03:45:56 -07:00
|
|
|
static int srsran_pdcch_nr_get_ncce(const srsran_coreset_t* coreset,
|
|
|
|
const srsran_search_space_t* search_space,
|
2020-10-16 00:52:55 -07:00
|
|
|
uint16_t rnti,
|
|
|
|
uint32_t aggregation_level,
|
|
|
|
uint32_t slot_idx,
|
|
|
|
uint32_t candidate)
|
|
|
|
{
|
2021-03-19 03:45:56 -07:00
|
|
|
if (aggregation_level >= SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR) {
|
2021-02-10 04:46:25 -08:00
|
|
|
ERROR("Invalid aggregation level %d;", aggregation_level);
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-10-16 00:52:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t L = 1U << aggregation_level; // Aggregation level
|
|
|
|
uint32_t n_ci = 0; // Carrier indicator field
|
|
|
|
uint32_t m = candidate; // Selected PDDCH candidate
|
|
|
|
uint32_t M = search_space->nof_candidates[aggregation_level]; // Number of aggregation levels
|
|
|
|
|
|
|
|
if (M == 0) {
|
2021-02-10 04:46:25 -08:00
|
|
|
ERROR("Invalid number of candidates %d for aggregation level %d", M, aggregation_level);
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-10-16 00:52:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Every REG is 1PRB wide and a CCE is 6 REG. So, the number of N_CCE is a sixth of the bandwidth times the number of
|
|
|
|
// symbols
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t N_cce = srsran_coreset_get_bw(coreset) * coreset->duration / 6;
|
2020-10-16 00:52:55 -07:00
|
|
|
|
|
|
|
if (N_cce < L) {
|
2021-02-10 04:46:25 -08:00
|
|
|
ERROR("Error number of CCE %d is lower than the aggregation level %d", N_cce, L);
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-10-16 00:52:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate Y_p_n for UE search space only
|
|
|
|
uint32_t Y_p_n = 0;
|
2021-03-19 03:45:56 -07:00
|
|
|
if (search_space->type == srsran_search_space_type_ue) {
|
|
|
|
Y_p_n = srsran_pdcch_calculate_Y_p_n(coreset->id, rnti, slot_idx);
|
2020-10-16 00:52:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return (int)(L * ((Y_p_n + (m * N_cce) / (L * M) + n_ci) % (N_cce / L)));
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
int srsran_pdcch_nr_locations_coreset(const srsran_coreset_t* coreset,
|
|
|
|
const srsran_search_space_t* search_space,
|
2020-10-22 00:53:59 -07:00
|
|
|
uint16_t rnti,
|
|
|
|
uint32_t aggregation_level,
|
|
|
|
uint32_t slot_idx,
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t locations[SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR])
|
2020-10-16 00:52:55 -07:00
|
|
|
{
|
|
|
|
if (coreset == NULL || search_space == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR_INVALID_INPUTS;
|
2020-10-16 00:52:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t nof_candidates = search_space->nof_candidates[aggregation_level];
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
nof_candidates = SRSRAN_MIN(nof_candidates, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR);
|
2020-10-16 00:52:55 -07:00
|
|
|
|
|
|
|
for (uint32_t candidate = 0; candidate < nof_candidates; candidate++) {
|
2021-03-19 03:45:56 -07:00
|
|
|
int ret = srsran_pdcch_nr_get_ncce(coreset, search_space, rnti, aggregation_level, slot_idx, candidate);
|
|
|
|
if (ret < SRSRAN_SUCCESS) {
|
2020-10-16 00:52:55 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
locations[candidate] = ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nof_candidates;
|
|
|
|
}
|
2020-11-27 01:23:26 -08:00
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
int srsran_pdcch_nr_max_candidates_coreset(const srsran_coreset_t* coreset, uint32_t aggregation_level)
|
2020-11-27 10:06:12 -08:00
|
|
|
{
|
|
|
|
if (coreset == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 10:06:12 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t coreset_bw = srsran_coreset_get_bw(coreset);
|
2020-11-27 10:06:12 -08:00
|
|
|
uint32_t nof_cce = (coreset_bw * coreset->duration) / 6;
|
|
|
|
|
|
|
|
uint32_t L = 1U << aggregation_level;
|
|
|
|
uint32_t nof_candidates = nof_cce / L;
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_MIN(nof_candidates, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR);
|
2020-11-27 10:06:12 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
static int pdcch_nr_init_common(srsran_pdcch_nr_t* q, const srsran_pdcch_nr_args_t* args)
|
2020-11-27 01:23:26 -08:00
|
|
|
{
|
|
|
|
if (q == NULL || args == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR_INVALID_INPUTS;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
q->meas_time_en = args->measure_time;
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
q->c = srsran_vec_u8_malloc(SRSRAN_PDCCH_MAX_RE * 2);
|
2020-11-27 01:23:26 -08:00
|
|
|
if (q->c == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
q->d = srsran_vec_u8_malloc(SRSRAN_PDCCH_MAX_RE * 2);
|
2020-11-27 01:23:26 -08:00
|
|
|
if (q->d == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
q->f = srsran_vec_u8_malloc(SRSRAN_PDCCH_MAX_RE * 2);
|
2020-11-27 01:23:26 -08:00
|
|
|
if (q->f == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
q->symbols = srsran_vec_cf_malloc(SRSRAN_PDCCH_MAX_RE);
|
2020-11-27 01:23:26 -08:00
|
|
|
if (q->symbols == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
q->allocated = srsran_vec_u8_malloc(NMAX);
|
2020-11-27 06:35:51 -08:00
|
|
|
if (q->allocated == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_crc_init(&q->crc24c, SRSRAN_LTE_CRC24C, 24) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_code_init(&q->code) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_modem_table_lte(&q->modem_table, SRSRAN_MOD_QPSK);
|
2020-11-27 06:35:51 -08:00
|
|
|
if (args->measure_evm) {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_modem_table_bytes(&q->modem_table);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
2020-11-27 01:23:26 -08:00
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_SUCCESS;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
int srsran_pdcch_nr_init_tx(srsran_pdcch_nr_t* q, const srsran_pdcch_nr_args_t* args)
|
2020-11-27 01:23:26 -08:00
|
|
|
{
|
2021-03-19 03:45:56 -07:00
|
|
|
if (pdcch_nr_init_common(q, args) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
q->is_tx = true;
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_polar_encoder_type_t encoder_type =
|
|
|
|
(args->disable_simd) ? SRSRAN_POLAR_ENCODER_PIPELINED : SRSRAN_POLAR_ENCODER_AVX2;
|
2020-11-27 01:23:26 -08:00
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_encoder_init(&q->encoder, encoder_type, NMAX_LOG) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_rm_tx_init(&q->rm) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_SUCCESS;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
int srsran_pdcch_nr_init_rx(srsran_pdcch_nr_t* q, const srsran_pdcch_nr_args_t* args)
|
2020-11-27 01:23:26 -08:00
|
|
|
{
|
2021-03-19 03:45:56 -07:00
|
|
|
if (pdcch_nr_init_common(q, args) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_polar_decoder_type_t decoder_type =
|
|
|
|
(args->disable_simd) ? SRSRAN_POLAR_DECODER_SSC_C : SRSRAN_POLAR_DECODER_SSC_C_AVX2;
|
2020-11-27 01:23:26 -08:00
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_decoder_init(&q->decoder, decoder_type, NMAX_LOG) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_rm_rx_init_c(&q->rm) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (args->measure_evm) {
|
2021-03-19 03:45:56 -07:00
|
|
|
q->evm_buffer = srsran_evm_buffer_alloc(SRSRAN_PDCCH_MAX_RE * 2);
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_SUCCESS;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
void srsran_pdcch_nr_free(srsran_pdcch_nr_t* q)
|
2020-11-27 01:23:26 -08:00
|
|
|
{
|
|
|
|
if (q == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_polar_code_free(&q->code);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
if (q->is_tx) {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_polar_encoder_free(&q->encoder);
|
|
|
|
srsran_polar_rm_tx_free(&q->rm);
|
2020-11-27 01:23:26 -08:00
|
|
|
} else {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_polar_decoder_free(&q->decoder);
|
|
|
|
srsran_polar_rm_rx_free_c(&q->rm);
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (q->c) {
|
|
|
|
free(q->c);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (q->d) {
|
|
|
|
free(q->d);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (q->f) {
|
|
|
|
free(q->f);
|
|
|
|
}
|
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
if (q->allocated) {
|
|
|
|
free(q->allocated);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (q->symbols) {
|
|
|
|
free(q->symbols);
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_modem_table_free(&q->modem_table);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
if (q->evm_buffer) {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_evm_free(q->evm_buffer);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
SRSRAN_MEM_ZERO(q, srsran_pdcch_nr_t, 1);
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
int srsran_pdcch_nr_set_carrier(srsran_pdcch_nr_t* q,
|
|
|
|
const srsran_carrier_nr_t* carrier,
|
|
|
|
const srsran_coreset_t* coreset)
|
2020-11-27 01:23:26 -08:00
|
|
|
{
|
|
|
|
if (q == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR_INVALID_INPUTS;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (carrier != NULL) {
|
|
|
|
q->carrier = *carrier;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coreset != NULL) {
|
|
|
|
q->coreset = *coreset;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_SUCCESS;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
static uint32_t pdcch_nr_cp(const srsran_pdcch_nr_t* q,
|
|
|
|
const srsran_dci_location_t* dci_location,
|
2020-11-27 01:23:26 -08:00
|
|
|
cf_t* slot_grid,
|
|
|
|
cf_t* symbols,
|
|
|
|
bool put)
|
|
|
|
{
|
|
|
|
uint32_t L = 1U << dci_location->L;
|
|
|
|
|
|
|
|
// Calculate begin and end sub-carrier index for the selected candidate
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t k_begin = (dci_location->ncce * SRSRAN_NRE * 6) / q->coreset.duration;
|
|
|
|
uint32_t k_end = k_begin + (L * 6 * SRSRAN_NRE) / q->coreset.duration;
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
uint32_t count = 0;
|
|
|
|
|
|
|
|
// Iterate over symbols
|
|
|
|
for (uint32_t l = 0; l < q->coreset.duration; l++) {
|
|
|
|
// Iterate over frequency resource groups
|
|
|
|
uint32_t k = 0;
|
2021-03-19 03:45:56 -07:00
|
|
|
for (uint32_t r = 0; r < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; r++) {
|
2020-11-27 01:23:26 -08:00
|
|
|
if (q->coreset.freq_resources[r]) {
|
2021-03-19 03:45:56 -07:00
|
|
|
for (uint32_t i = r * 6 * SRSRAN_NRE; i < (r + 1) * 6 * SRSRAN_NRE; i++, k++) {
|
2020-11-27 01:23:26 -08:00
|
|
|
if (k >= k_begin && k < k_end && k % 4 != 1) {
|
|
|
|
if (put) {
|
2021-03-19 03:45:56 -07:00
|
|
|
slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + i] = symbols[count++];
|
2020-11-27 01:23:26 -08:00
|
|
|
} else {
|
2021-03-19 03:45:56 -07:00
|
|
|
symbols[count++] = slot_grid[q->carrier.nof_prb * SRSRAN_NRE * l + i];
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
static uint32_t pdcch_nr_c_init(const srsran_pdcch_nr_t* q, const srsran_dci_msg_nr_t* dci_msg)
|
2020-11-27 01:23:26 -08:00
|
|
|
{
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t n_id = (dci_msg->search_space == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present)
|
2020-11-27 01:23:26 -08:00
|
|
|
? q->coreset.dmrs_scrambling_id
|
|
|
|
: q->carrier.id;
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t n_rnti = (dci_msg->search_space == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present)
|
2020-11-27 01:23:26 -08:00
|
|
|
? dci_msg->rnti
|
|
|
|
: 0U;
|
|
|
|
return ((n_rnti << 16U) + n_id) & 0x7fffffffU;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
int srsran_pdcch_nr_encode(srsran_pdcch_nr_t* q, const srsran_dci_msg_nr_t* dci_msg, cf_t* slot_symbols)
|
2020-11-27 01:23:26 -08:00
|
|
|
{
|
|
|
|
if (q == NULL || dci_msg == NULL || slot_symbols == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
struct timeval t[3];
|
|
|
|
if (q->meas_time_en) {
|
|
|
|
gettimeofday(&t[1], NULL);
|
|
|
|
}
|
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Calculate...
|
2020-12-11 09:05:02 -08:00
|
|
|
q->K = dci_msg->nof_bits + 24U; // Payload size including CRC
|
2021-03-19 03:45:56 -07:00
|
|
|
q->M = (1U << dci_msg->location.L) * (SRSRAN_NRE - 3U) * 6U; // Number of RE
|
2020-12-11 09:05:02 -08:00
|
|
|
q->E = q->M * 2; // Number of Rate-Matched bits
|
|
|
|
uint32_t cinit = pdcch_nr_c_init(q, dci_msg); // Pseudo-random sequence initiation
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Get polar code
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_code_get(&q->code, q->K, q->E, 9U) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
2021-02-10 04:46:25 -08:00
|
|
|
PDCCH_INFO_TX("K=%d; E=%d; M=%d; n=%d; cinit=%08x;", q->K, q->E, q->M, q->code.n, cinit);
|
2020-12-11 09:05:02 -08:00
|
|
|
|
|
|
|
// Set first L bits to ones, c will have an offset of 24 bits
|
|
|
|
uint8_t* c = q->c;
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_bit_unpack(UINT32_MAX, &c, 24U);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Copy DCI message
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_u8_copy(c, dci_msg->payload, dci_msg->nof_bits);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Append CRC
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_crc_attach(&q->crc24c, q->c, q->K);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
PDCCH_INFO_TX("Append CRC %06x", (uint32_t)srsran_crc_checksum_get(&q->crc24c));
|
2020-11-27 06:35:51 -08:00
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Unpack RNTI
|
|
|
|
uint8_t unpacked_rnti[16] = {};
|
|
|
|
uint8_t* ptr = unpacked_rnti;
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_bit_unpack(dci_msg->rnti, &ptr, 16);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Scramble CRC with RNTI
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_xor_bbb(unpacked_rnti, &c[q->K - 16], &c[q->K - 16], 16);
|
2020-11-27 06:35:51 -08:00
|
|
|
|
2020-12-11 09:05:02 -08:00
|
|
|
// Interleave
|
2021-03-19 03:45:56 -07:00
|
|
|
uint8_t c_prime[SRSRAN_POLAR_INTERLEAVER_K_MAX_IL];
|
|
|
|
srsran_polar_interleaver_run_u8(c, c_prime, q->K, true);
|
2020-12-11 09:05:02 -08:00
|
|
|
|
|
|
|
// Print c and c_prime (after interleaving)
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
2020-11-30 09:00:24 -08:00
|
|
|
PDCCH_INFO_TX("c=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_hex(stdout, c, q->K);
|
2020-12-11 09:05:02 -08:00
|
|
|
PDCCH_INFO_TX("c_prime=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_hex(stdout, c_prime, q->K);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate channel
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_polar_chanalloc_tx(c_prime, q->allocated, q->code.N, q->code.K, q->code.nPC, q->code.K_set, q->code.PC_set);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Encode bits
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_encoder_encode(&q->encoder, q->allocated, q->d, q->code.n) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
// Print d
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
2020-11-30 09:00:24 -08:00
|
|
|
PDCCH_INFO_TX("d=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_byte(stdout, q->d, q->code.N);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Rate matching
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_polar_rm_tx(&q->rm, q->d, q->f, q->code.n, q->E, q->K, PDCCH_NR_POLAR_RM_IBIL);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Scrambling
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_sequence_apply_bit(q->f, q->f, q->E, cinit);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Modulation
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_mod_modulate(&q->modem_table, q->f, q->symbols, q->E);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Put symbols in grid
|
|
|
|
uint32_t m = pdcch_nr_cp(q, &dci_msg->location, slot_symbols, q->symbols, true);
|
2020-11-27 06:35:51 -08:00
|
|
|
if (q->M != m) {
|
2021-02-10 04:46:25 -08:00
|
|
|
ERROR("Unmatch number of RE (%d != %d)", m, q->M);
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
if (q->meas_time_en) {
|
|
|
|
gettimeofday(&t[2], NULL);
|
|
|
|
get_time_interval(t);
|
|
|
|
q->meas_time_us = (uint32_t)t[0].tv_usec;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
2020-11-27 06:35:51 -08:00
|
|
|
char str[128] = {};
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_pdcch_nr_info(q, NULL, str, sizeof(str));
|
2021-02-10 04:46:25 -08:00
|
|
|
PDCCH_INFO_TX("%s", str);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_SUCCESS;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
int srsran_pdcch_nr_decode(srsran_pdcch_nr_t* q,
|
2020-11-27 01:23:26 -08:00
|
|
|
cf_t* slot_symbols,
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_dmrs_pdcch_ce_t* ce,
|
|
|
|
srsran_dci_msg_nr_t* dci_msg,
|
|
|
|
srsran_pdcch_nr_res_t* res)
|
2020-11-27 01:23:26 -08:00
|
|
|
{
|
|
|
|
if (q == NULL || dci_msg == NULL || ce == NULL || slot_symbols == NULL || res == NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
struct timeval t[3];
|
|
|
|
if (q->meas_time_en) {
|
|
|
|
gettimeofday(&t[1], NULL);
|
|
|
|
}
|
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Calculate...
|
2020-11-27 06:35:51 -08:00
|
|
|
q->K = dci_msg->nof_bits + 24U; // Payload size including CRC
|
2021-03-19 03:45:56 -07:00
|
|
|
q->M = (1U << dci_msg->location.L) * (SRSRAN_NRE - 3U) * 6U; // Number of RE
|
2020-11-27 06:35:51 -08:00
|
|
|
q->E = q->M * 2; // Number of Rate-Matched bits
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Check number of estimates is correct
|
2020-11-27 06:35:51 -08:00
|
|
|
if (ce->nof_re != q->M) {
|
2021-02-10 04:46:25 -08:00
|
|
|
ERROR("Invalid number of channel estimates (%d != %d)", q->M, ce->nof_re);
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get polar code
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_code_get(&q->code, q->K, q->E, 9U) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
2021-02-10 04:46:25 -08:00
|
|
|
PDCCH_INFO_RX("K=%d; E=%d; M=%d; n=%d;", q->K, q->E, q->M, q->code.n);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Get symbols from grid
|
|
|
|
uint32_t m = pdcch_nr_cp(q, &dci_msg->location, slot_symbols, q->symbols, false);
|
2020-11-27 06:35:51 -08:00
|
|
|
if (q->M != m) {
|
2021-02-10 04:46:25 -08:00
|
|
|
ERROR("Unmatch number of RE (%d != %d)", m, q->M);
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2020-11-30 09:00:24 -08:00
|
|
|
// Print channel estimates if enabled
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
2020-11-30 09:00:24 -08:00
|
|
|
PDCCH_INFO_RX("ce=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_c(stdout, ce->ce, q->M);
|
2020-11-30 09:00:24 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Equalise
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_predecoding_single(q->symbols, ce->ce, q->symbols, NULL, q->M, 1.0f, ce->noise_var);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
2020-11-30 09:00:24 -08:00
|
|
|
// Print symbols if enabled
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
2020-11-30 09:00:24 -08:00
|
|
|
PDCCH_INFO_RX("symbols=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_c(stdout, q->symbols, q->M);
|
2020-11-30 09:00:24 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Demodulation
|
|
|
|
int8_t* llr = (int8_t*)q->f;
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_demod_soft_demodulate_b(SRSRAN_MOD_QPSK, q->symbols, llr, q->M);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Measure EVM if configured
|
|
|
|
if (q->evm_buffer != NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
res->evm = srsran_evm_run_b(q->evm_buffer, &q->modem_table, q->symbols, llr, q->E);
|
2020-11-27 01:23:26 -08:00
|
|
|
} else {
|
|
|
|
res->evm = NAN;
|
|
|
|
}
|
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
// Negate all LLR
|
|
|
|
for (uint32_t i = 0; i < q->E; i++) {
|
|
|
|
llr[i] *= -1;
|
|
|
|
}
|
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Descrambling
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_sequence_apply_c(llr, llr, q->E, pdcch_nr_c_init(q, dci_msg));
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Un-rate matching
|
|
|
|
int8_t* d = (int8_t*)q->d;
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_rm_rx_c(&q->rm, llr, d, q->E, q->code.n, q->K, PDCCH_NR_POLAR_RM_IBIL) < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
// Print d
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
2020-11-30 09:00:24 -08:00
|
|
|
PDCCH_INFO_RX("d=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_bs(stdout, d, q->K);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Decode
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_polar_decoder_decode_c(&q->decoder, d, q->allocated, q->code.n, q->code.F_set, q->code.F_set_size) <
|
|
|
|
SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
// De-allocate channel
|
2021-03-19 03:45:56 -07:00
|
|
|
uint8_t c_prime[SRSRAN_POLAR_INTERLEAVER_K_MAX_IL];
|
|
|
|
srsran_polar_chanalloc_rx(q->allocated, c_prime, q->code.K, q->code.nPC, q->code.K_set, q->code.PC_set);
|
2020-12-11 09:05:02 -08:00
|
|
|
|
|
|
|
// Set first L bits to ones, c will have an offset of 24 bits
|
|
|
|
uint8_t* c = q->c;
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_bit_unpack(UINT32_MAX, &c, 24U);
|
2020-12-11 09:05:02 -08:00
|
|
|
|
|
|
|
// De-interleave
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_polar_interleaver_run_u8(c_prime, c, q->K, false);
|
2020-11-27 06:35:51 -08:00
|
|
|
|
|
|
|
// Print c
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
2020-12-11 09:05:02 -08:00
|
|
|
PDCCH_INFO_RX("c_prime=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_hex(stdout, c_prime, q->K);
|
2020-11-30 09:00:24 -08:00
|
|
|
PDCCH_INFO_RX("c=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_hex(stdout, c, q->K);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Unpack RNTI
|
|
|
|
uint8_t unpacked_rnti[16] = {};
|
|
|
|
uint8_t* ptr = unpacked_rnti;
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_bit_unpack(dci_msg->rnti, &ptr, 16);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// De-Scramble CRC with RNTI
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_xor_bbb(unpacked_rnti, &c[q->K - 16], &c[q->K - 16], 16);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
|
|
|
// Check CRC
|
2020-12-11 09:05:02 -08:00
|
|
|
ptr = &c[q->K - 24];
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t checksum1 = srsran_crc_checksum(&q->crc24c, q->c, q->K);
|
|
|
|
uint32_t checksum2 = srsran_bit_pack(&ptr, 24);
|
2020-11-27 01:23:26 -08:00
|
|
|
res->crc = checksum1 == checksum2;
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
2020-11-30 09:00:24 -08:00
|
|
|
PDCCH_INFO_RX("CRC={%06x, %06x}; msg=", checksum1, checksum2);
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_hex(stdout, c, dci_msg->nof_bits);
|
2020-11-30 09:00:24 -08:00
|
|
|
}
|
2020-11-27 06:35:51 -08:00
|
|
|
|
2020-11-27 01:23:26 -08:00
|
|
|
// Copy DCI message
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_u8_copy(dci_msg->payload, c, dci_msg->nof_bits);
|
2020-11-27 01:23:26 -08:00
|
|
|
|
2020-11-27 06:35:51 -08:00
|
|
|
if (q->meas_time_en) {
|
|
|
|
gettimeofday(&t[2], NULL);
|
|
|
|
get_time_interval(t);
|
|
|
|
q->meas_time_us = (uint32_t)t[0].tv_usec;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
2020-11-27 06:35:51 -08:00
|
|
|
char str[128] = {};
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_pdcch_nr_info(q, res, str, sizeof(str));
|
2021-02-10 04:46:25 -08:00
|
|
|
PDCCH_INFO_RX("%s", str);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_SUCCESS;
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t srsran_pdcch_nr_info(const srsran_pdcch_nr_t* q, const srsran_pdcch_nr_res_t* res, char* str, uint32_t str_len)
|
2020-11-27 06:35:51 -08:00
|
|
|
{
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
if (q == NULL) {
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, "K=%d,E=%d", q->K, q->E);
|
2020-11-27 06:35:51 -08:00
|
|
|
|
|
|
|
if (res != NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ",crc=%s", res->crc ? "OK" : "KO");
|
2020-11-27 06:35:51 -08:00
|
|
|
|
|
|
|
if (q->evm_buffer && res) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ",evm=%.2f", res->evm);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (q->meas_time_en) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ",t=%d us", q->meas_time_us);
|
2020-11-27 06:35:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
2020-11-27 01:23:26 -08:00
|
|
|
}
|