Initial EVM calculation commit and other easthetic changes

This commit is contained in:
Xavier Arteaga 2020-02-19 17:01:54 +01:00 committed by Xavier Arteaga
parent 4739f3084f
commit f261365c91
18 changed files with 386 additions and 98 deletions

View File

@ -250,9 +250,11 @@ typedef enum SRSLTE_API {
SRSLTE_MOD_QPSK,
SRSLTE_MOD_16QAM,
SRSLTE_MOD_64QAM,
SRSLTE_MOD_256QAM,
SRSLTE_MOD_256QAM
} srslte_mod_t;
#define SRSLTE_NOF_MODULATIONS (SRSLTE_MOD_256QAM + 1)
typedef enum {
SRSLTE_DCI_FORMAT0 = 0,
SRSLTE_DCI_FORMAT1,

View File

@ -36,8 +36,6 @@
#include "modem_table.h"
#include "srslte/config.h"
typedef _Complex float cf_t;
typedef struct SRSLTE_API {
srslte_mod_t mod; /* In this implementation, mapping table is hard-coded */
} srslte_demod_hard_t;

View File

@ -0,0 +1,247 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE 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.
*
* srsLTE 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 SRSLTE_EVM_H_
#define SRSLTE_EVM_H_
#include <srslte/config.h>
#include <srslte/phy/phch/ra.h>
#include <srslte/phy/utils/debug.h>
/** @struct srslte_evm_buffer_t
* This structure carries the necessary temporary data required for calculating the EVM.
*
* @var max_bits maximum of bits which can support
* @var hard_bits vector that stores hard bits after decision
* @var symbols vector that stores the modulated symbols from the hard bits
*/
typedef struct {
uint32_t max_bits;
uint8_t* hard_bits;
cf_t* symbols;
} srslte_evm_buffer_t;
/**
* Allocates the EVM calculation buffer
* @param nof_prb that provides the maximum number of bits
* @return EVM buffer pointer
*/
static inline srslte_evm_buffer_t* srslte_evm_buffer_alloc(uint32_t nof_prb)
{
srslte_evm_buffer_t* q = (srslte_evm_buffer_t*)srslte_vec_malloc(sizeof(srslte_evm_buffer_t));
// Check allocation result and number of PRB
if (!q || !nof_prb) {
ERROR("Malloc");
return q;
}
// Zero memory the buffer fields
memset(q, 0, sizeof(srslte_evm_buffer_t));
// Set max number of bits
q->max_bits = srslte_ra_tbs_from_idx(SRSLTE_RA_NOF_TBS_IDX - 1, nof_prb);
// Allocate hard bits
q->hard_bits = srslte_vec_u8_malloc(q->max_bits);
if (!q->hard_bits) {
ERROR("Malloc");
return q;
}
// Allocate symbols assuming BPSK
q->symbols = srslte_vec_cf_malloc(q->max_bits);
if (!q->symbols) {
ERROR("Malloc");
return q;
}
return q;
}
/**
* Allocates the EVM calculation buffer
* @param nof_prb that provides the maximum number of bits
* @return EVM buffer pointer
*/
static inline void srslte_evm_buffer_resize(srslte_evm_buffer_t* q, uint32_t nof_prb)
{
// Assert pointer and number of PRB
if (!q || !nof_prb) {
ERROR("Invalid inputs");
return;
}
// Get new number of max bits
uint32_t new_max_bits = srslte_ra_tbs_from_idx(SRSLTE_RA_NOF_TBS_IDX - 1, nof_prb);
// Return if no resize is required
if (q->max_bits >= new_max_bits) {
return;
}
// Update with greater value
q->max_bits = new_max_bits;
// Free hard bits if it was allocated
if (q->hard_bits) {
free(q->hard_bits);
}
// Allocate hard bits again
q->hard_bits = srslte_vec_u8_malloc(q->max_bits);
if (!q->hard_bits) {
ERROR("Malloc");
return;
}
// Free symbols if it was allocated
if (q->symbols) {
free(q->symbols);
}
// Allocate symbols again
q->symbols = srslte_vec_cf_malloc(q->max_bits);
if (!q->symbols) {
ERROR("Malloc");
return;
}
}
/**
* Template for hard decision taking
*/
#define HARD_DECISION(SOFTBITS, HARDBITS, NOF_SOFTBITS) \
do { \
for (uint32_t i = 0, k = 0; k < NOF_SOFTBITS; i++) { \
uint8_t w = 0; \
for (int j = 0; j < 8 && k < NOF_SOFTBITS; j++, k++) { \
w |= (SOFTBITS[k] > 0) ? ((uint32_t)1 << (uint32_t)(7 - j)) : 0; \
} \
HARDBITS[i] = w; \
} \
} while (false)
/**
* Template RMS EVM calculation for different LLR
*/
#define EVM_RUN_TEMPLATE(LLR_T, SUFFIX) \
static inline float srslte_evm_run_##SUFFIX(srslte_evm_buffer_t* q, \
const srslte_modem_table_t* modem_table, \
const cf_t* symbols, \
const LLR_T* llr, \
uint32_t nof_bits) \
{ \
float evm_rms = NAN; \
\
/* Return NAN if EVM buffers, modem table, LLR, symbols or bits missing*/ \
if (!q || !modem_table || !modem_table->nbits_x_symbol || !llr || !symbols || !nof_bits) { \
ERROR("Invalid inputs %p %p %p %p %d\n", q, modem_table, llr, symbols, nof_bits); \
return evm_rms; \
} \
\
/* Limit number of bits to the one supported by the buffer */ \
nof_bits = SRSLTE_MIN(q->max_bits, nof_bits); \
\
/* Calculate number of symbols */ \
uint32_t nsymbols = nof_bits / modem_table->nbits_x_symbol; \
\
/* Hard decision */ \
HARD_DECISION(llr, q->hard_bits, nof_bits); \
\
/* Modulate */ \
srslte_mod_modulate_bytes(modem_table, q->hard_bits, q->symbols, nof_bits); \
\
/* Compute symbol difference */ \
srslte_vec_sub_ccc(symbols, q->symbols, q->symbols, nsymbols); \
\
/* Average squares */ \
float evm_pow = srslte_vec_avg_power_cf(q->symbols, nsymbols); \
\
/* Convert measure to RMS */ \
evm_rms = sqrtf(evm_pow); \
\
return evm_rms; \
}
/** @function srslte_evm_run_f
* Calculates the Root Mean Squared EVM given a modulation table, complex symbols, floating point LLR (soft bits) and
* the number of bits.
*
* @param q is the EVM buffers, need to be preallocated
* @param modem_table points at the modulator table
* @param symbols vector carrying the modulated complex symbols
* @param llr softbits
* @param nof_bits number of bits
* @return the measured RMS EVM if no error occurs, otherwise it returns NAN
*/
EVM_RUN_TEMPLATE(float, f)
/** @function srslte_evm_run_s
* Calculates the Root Mean Squared EVM given a modulation table, complex symbols, fixed integer 16 bit LLR (soft bits)
* and the number of bits.
*
* @param q is the EVM buffers, need to be preallocated
* @param modem_table points at the modulator table
* @param symbols vector carrying the modulated complex symbols
* @param llr softbits
* @param nof_bits number of bits
* @return the measured RMS EVM if no error occurs, otherwise it returns NAN
*/
EVM_RUN_TEMPLATE(int16_t, s)
/** @function srslte_evm_run_b
* Calculates the Root Mean Squared EVM given a modulation table, complex symbols, fixed integer 8 bit LLR (soft bits)
* and the number of bits.
*
* @param q is the EVM buffers, need to be preallocated
* @param modem_table points at the modulator table
* @param symbols vector carrying the modulated complex symbols
* @param llr softbits
* @param nof_bits number of bits
* @return the measured RMS EVM if no error occurs, otherwise it returns NAN
*/
EVM_RUN_TEMPLATE(int8_t, b)
#undef EVM_RUN_TEMPLATE
#undef HARD_DECISION
static inline void srslte_evm_free(srslte_evm_buffer_t* q)
{
// Check EVM buffer object exist
if (q) {
// Check hard bits were allocated
if (q->hard_bits) {
free(q->hard_bits);
}
// Check symbols were allocated
if (q->symbols) {
free(q->symbols);
}
// Free buffer object
free(q);
}
}
#endif // SRSLTE_EVM_H_

View File

@ -23,7 +23,7 @@
* File: mod.h
*
* Description: Modulation.
* Supports BPSK, QPSK, 16QAM and 64QAM.
* Supports BPSK, QPSK, 16QAM, 64QAM and 256QAM.
*
* Reference: 3GPP TS 36.211 version 10.0.0 Release 10 Sec. 7.1
*****************************************************************************/
@ -36,8 +36,9 @@
#include "modem_table.h"
#include "srslte/config.h"
SRSLTE_API int srslte_mod_modulate(srslte_modem_table_t* table, uint8_t* bits, cf_t* symbols, uint32_t nbits);
SRSLTE_API int srslte_mod_modulate(const srslte_modem_table_t* table, uint8_t* bits, cf_t* symbols, uint32_t nbits);
SRSLTE_API int srslte_mod_modulate_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint32_t nbits);
SRSLTE_API int
srslte_mod_modulate_bytes(const srslte_modem_table_t* q, const uint8_t* bits, cf_t* symbols, uint32_t nbits);
#endif // SRSLTE_MOD_H

View File

@ -62,7 +62,6 @@ typedef struct SRSLTE_API {
bpsk_packed_t* symbol_table_bpsk;
qpsk_packed_t* symbol_table_qpsk;
qam16_packed_t* symbol_table_16qam;
qam256_packed_t* symbol_table_256qam;
} srslte_modem_table_t;
SRSLTE_API void srslte_modem_table_init(srslte_modem_table_t* q);

View File

@ -36,6 +36,7 @@
#include "srslte/phy/mimo/layermap.h"
#include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/modem/evm.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/phch/pdsch_cfg.h"
@ -72,7 +73,10 @@ typedef struct SRSLTE_API {
float* csi[SRSLTE_MAX_CODEWORDS]; /* Channel Strengh Indicator */
/* tx & rx objects */
srslte_modem_table_t mod[5];
srslte_modem_table_t mod[SRSLTE_NOF_MODULATIONS];
// EVM buffers, one for each codeword (avoid concurrency issue with coworker)
srslte_evm_buffer_t* evm_buffer[SRSLTE_MAX_CODEWORDS];
// This is to generate the scrambling seq for multiple CRNTIs
srslte_pdsch_user_t** users;
@ -89,6 +93,7 @@ typedef struct {
uint8_t* payload;
bool crc;
float avg_iterations_block;
float evm;
} srslte_pdsch_res_t;
SRSLTE_API int srslte_pdsch_init_ue(srslte_pdsch_t* q, uint32_t max_prb, uint32_t nof_rx_antennas);

View File

@ -67,9 +67,9 @@ typedef struct SRSLTE_API {
srslte_softbuffer_rx_t* rx[SRSLTE_MAX_CODEWORDS];
} softbuffers;
bool meas_evm_en;
bool meas_time_en;
uint32_t meas_time_value;
} srslte_pdsch_cfg_t;
#endif // SRSLTE_PDSCH_CFG_H

View File

@ -75,6 +75,8 @@ typedef struct SRSLTE_API {
enum { SRSLTE_RA_TYPE2_LOC = 0, SRSLTE_RA_TYPE2_DIST = 1 } mode;
} srslte_ra_type2_t;
#define SRSLTE_RA_NOF_TBS_IDX 34
SRSLTE_API uint32_t srslte_ra_type0_P(uint32_t nof_prb);
SRSLTE_API uint32_t srslte_ra_type2_n_vrb_dl(uint32_t nof_prb, bool ngap_is_1);

View File

@ -95,13 +95,13 @@ SRSLTE_API void srslte_vec_cf_zero(cf_t* ptr, uint32_t nsamples);
SRSLTE_API void srslte_vec_f_zero(float* ptr, uint32_t nsamples);
/* print vectors */
SRSLTE_API void srslte_vec_fprint_c(FILE* stream, cf_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_f(FILE* stream, float* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_b(FILE* stream, uint8_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_bs(FILE* stream, int8_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_byte(FILE* stream, uint8_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_i(FILE* stream, int* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_s(FILE* stream, short* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_c(FILE* stream, const cf_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_f(FILE* stream, const float* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_b(FILE* stream, const uint8_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_bs(FILE* stream, const int8_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_byte(FILE* stream, const uint8_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_i(FILE* stream, const int* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_s(FILE* stream, const int16_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_hex(FILE* stream, uint8_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_sprint_hex(char* str, const uint32_t max_str_len, uint8_t* x, const uint32_t len);

View File

@ -45,7 +45,7 @@ int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t* q, uint32_t nof_prb)
if (q != NULL) {
bzero(q, sizeof(srslte_softbuffer_rx_t));
ret = srslte_ra_tbs_from_idx(33, nof_prb);
ret = srslte_ra_tbs_from_idx(SRSLTE_RA_NOF_TBS_IDX - 1, nof_prb);
if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t)ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;
ret = SRSLTE_ERROR;
@ -163,7 +163,7 @@ int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t* q, uint32_t nof_prb)
bzero(q, sizeof(srslte_softbuffer_tx_t));
ret = srslte_ra_tbs_from_idx(33, nof_prb);
ret = srslte_ra_tbs_from_idx(SRSLTE_RA_NOF_TBS_IDX - 1, nof_prb);
if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t)ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;

View File

@ -19,7 +19,7 @@
*
*/
typedef _Complex float cf_t;
#include <srslte/config.h>
#define BPSK_LEVEL M_SQRT1_2

View File

@ -30,7 +30,7 @@
/** Low-level API */
int srslte_mod_modulate(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint32_t nbits)
int srslte_mod_modulate(const srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint32_t nbits)
{
uint32_t i, j, idx;
uint8_t* b_ptr = (uint8_t*)bits;
@ -47,7 +47,7 @@ int srslte_mod_modulate(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, u
return j;
}
void mod_bpsk_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint32_t nbits)
static void mod_bpsk_bytes(const srslte_modem_table_t* q, const uint8_t* bits, cf_t* symbols, uint32_t nbits)
{
uint8_t mask_bpsk[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
uint8_t shift_bpsk[8] = {7, 6, 5, 4, 3, 2, 1, 0};
@ -60,7 +60,7 @@ void mod_bpsk_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint3
}
}
void mod_qpsk_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint32_t nbits)
static void mod_qpsk_bytes(const srslte_modem_table_t* q, const uint8_t* bits, cf_t* symbols, uint32_t nbits)
{
uint8_t mask_qpsk[4] = {0xc0, 0x30, 0x0c, 0x03};
uint8_t shift_qpsk[4] = {6, 4, 2, 0};
@ -73,7 +73,7 @@ void mod_qpsk_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint3
}
}
void mod_16qam_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint32_t nbits)
static void mod_16qam_bytes(const srslte_modem_table_t* q, const uint8_t* bits, cf_t* symbols, uint32_t nbits)
{
for (int i = 0; i < nbits / 8; i++) {
memcpy(&symbols[2 * i], &q->symbol_table_16qam[bits[i]], sizeof(qam16_packed_t));
@ -84,7 +84,7 @@ void mod_16qam_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint
}
}
void mod_64qam_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint32_t nbits)
static void mod_64qam_bytes(const srslte_modem_table_t* q, const uint8_t* bits, cf_t* symbols, uint32_t nbits)
{
uint8_t in0, in1, in2, in3;
uint32_t in80, in81, in82;
@ -124,7 +124,7 @@ void mod_64qam_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint
}
}
void mod_256qam_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint32_t nbits)
static void mod_256qam_bytes(const srslte_modem_table_t* q, const uint8_t* bits, cf_t* symbols, uint32_t nbits)
{
for (int i = 0; i < nbits / 8; i++) {
symbols[i] = q->symbol_table[bits[i]];
@ -132,12 +132,12 @@ void mod_256qam_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uin
}
/* Assumes packet bits as input */
int srslte_mod_modulate_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symbols, uint32_t nbits)
int srslte_mod_modulate_bytes(const srslte_modem_table_t* q, const uint8_t* bits, cf_t* symbols, uint32_t nbits)
{
if (!q->byte_tables_init) {
ERROR("Error need to initiated modem tables for packeted bits before calling srslte_mod_modulate_bytes()\n");
return -1;
return SRSLTE_ERROR;
}
if (nbits % q->nbits_x_symbol) {
ERROR("Error modulator expects number of bits (%d) to be multiple of %d\n", nbits, q->nbits_x_symbol);
@ -161,7 +161,7 @@ int srslte_mod_modulate_bytes(srslte_modem_table_t* q, uint8_t* bits, cf_t* symb
break;
default:
ERROR("srslte_mod_modulate_bytes() accepts QPSK/16QAM/64QAM modulations only\n");
return -1;
return SRSLTE_ERROR;
}
return nbits / q->nbits_x_symbol;
}

View File

@ -56,9 +56,6 @@ void srslte_modem_table_free(srslte_modem_table_t* q)
if (q->symbol_table_16qam) {
free(q->symbol_table_16qam);
}
if (q->symbol_table_256qam) {
free(q->symbol_table_256qam);
}
bzero(q, sizeof(srslte_modem_table_t));
}
void srslte_modem_table_reset(srslte_modem_table_t* q)

View File

@ -64,7 +64,7 @@ typedef struct {
srslte_sch_t dl_sch;
/* Encoder/Decoder data pointers: they must be set before posting start semaphore */
uint8_t* data;
srslte_pdsch_res_t* data;
/* Execution status */
int ret_status;
@ -254,7 +254,7 @@ static int pdsch_init(srslte_pdsch_t* q, uint32_t max_prb, bool is_ue, uint32_t
INFO("Init PDSCH: %d PRBs, max_symbols: %d\n", max_prb, q->max_re);
for (int i = 0; i < 5; i++) {
for (int i = 0; i < SRSLTE_NOF_MODULATIONS; i++) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
goto clean;
}
@ -268,29 +268,38 @@ static int pdsch_init(srslte_pdsch_t* q, uint32_t max_prb, bool is_ue, uint32_t
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
// Allocate int16_t for reception (LLRs)
q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_256QAM));
q->e[i] = srslte_vec_i16_malloc(q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_256QAM));
if (!q->e[i]) {
goto clean;
}
q->d[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
q->d[i] = srslte_vec_cf_malloc(q->max_re);
if (!q->d[i]) {
goto clean;
}
// If it is the UE, allocate EVM buffer, for only minimum PRB
if (is_ue) {
q->evm_buffer[i] = srslte_evm_buffer_alloc(6);
if (!q->evm_buffer[i]) {
ERROR("Allocating EVM buffer\n");
goto clean;
}
}
}
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
q->x[i] = srslte_vec_cf_malloc(q->max_re);
if (!q->x[i]) {
goto clean;
}
q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
q->symbols[i] = srslte_vec_cf_malloc(q->max_re);
if (!q->symbols[i]) {
goto clean;
}
if (q->is_ue) {
for (int j = 0; j < SRSLTE_MAX_PORTS; j++) {
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
q->ce[i][j] = srslte_vec_cf_malloc(q->max_re);
if (!q->ce[i][j]) {
goto clean;
}
@ -310,7 +319,7 @@ static int pdsch_init(srslte_pdsch_t* q, uint32_t max_prb, bool is_ue, uint32_t
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (!q->csi[i]) {
q->csi[i] = srslte_vec_malloc(sizeof(float) * q->max_re * 2);
q->csi[i] = srslte_vec_f_malloc(q->max_re * 2);
if (!q->csi[i]) {
return SRSLTE_ERROR;
}
@ -413,6 +422,10 @@ void srslte_pdsch_free(srslte_pdsch_t* q)
if (q->csi[i]) {
free(q->csi[i]);
}
if (q->evm_buffer[i]) {
srslte_evm_free(q->evm_buffer[i]);
}
}
/* Free sch objects */
@ -448,7 +461,7 @@ void srslte_pdsch_free(srslte_pdsch_t* q)
srslte_sequence_free(&q->tmp_seq);
for (int i = 0; i < 5; i++) {
for (int i = 0; i < SRSLTE_NOF_MODULATIONS; i++) {
srslte_modem_table_free(&q->mod[i]);
}
@ -463,6 +476,13 @@ int srslte_pdsch_set_cell(srslte_pdsch_t* q, srslte_cell_t cell)
q->cell = cell;
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
// Resize EVM buffer, only for UE
if (q->is_ue) {
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
srslte_evm_buffer_resize(q->evm_buffer[i], cell.nof_prb);
}
}
INFO("PDSCH: Cell config PCI=%d, %d ports, %d PRBs, max_symbols: %d\n",
q->cell.id,
q->cell.nof_ports,
@ -740,7 +760,7 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_pdsch_cfg_t* cfg,
srslte_sch_t* dl_sch,
uint8_t* data,
srslte_pdsch_res_t* data,
uint32_t tb_idx,
bool* ack)
{
@ -772,6 +792,23 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t* q,
} else {
srslte_demod_soft_demodulate_s(mcs->mod, q->d[codeword_idx], q->e[codeword_idx], cfg->grant.nof_re);
}
if (cfg->meas_evm_en && q->evm_buffer[codeword_idx]) {
if (q->llr_is_8bit) {
data[tb_idx].evm = srslte_evm_run_b(q->evm_buffer[codeword_idx],
&q->mod[mcs->mod],
q->d[codeword_idx],
q->e[codeword_idx],
cfg->grant.tb[tb_idx].nof_bits);
} else {
data[tb_idx].evm = srslte_evm_run_s(q->evm_buffer[codeword_idx],
&q->mod[mcs->mod],
q->d[codeword_idx],
q->e[codeword_idx],
cfg->grant.tb[tb_idx].nof_bits);
}
} else {
data[tb_idx].evm = NAN;
}
/* Select scrambling sequence */
srslte_sequence_t* seq =
@ -793,7 +830,7 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t* q,
}
/* Return */
ret = srslte_dlsch_decode2(dl_sch, cfg, q->e[codeword_idx], data, tb_idx, nof_layers);
ret = srslte_dlsch_decode2(dl_sch, cfg, q->e[codeword_idx], data[tb_idx].payload, tb_idx, nof_layers);
if (ret == SRSLTE_SUCCESS) {
*ack = true;
@ -957,7 +994,7 @@ int srslte_pdsch_decode(srslte_pdsch_t* q,
h->pdsch_ptr = q;
h->cfg = cfg;
h->sf = sf;
h->data = data[tb_idx].payload;
h->data = &data[tb_idx];
h->tb_idx = tb_idx;
h->ack = &data[tb_idx].crc;
h->dl_sch.max_iterations = q->dl_sch.max_iterations;
@ -965,7 +1002,7 @@ int srslte_pdsch_decode(srslte_pdsch_t* q,
sem_post(&h->start);
} else {
ret = srslte_pdsch_codeword_decode(q, sf, cfg, &q->dl_sch, data[tb_idx].payload, tb_idx, &data[tb_idx].crc);
ret = srslte_pdsch_codeword_decode(q, sf, cfg, &q->dl_sch, data, tb_idx, &data[tb_idx].crc);
data[tb_idx].avg_iterations_block = srslte_sch_last_noi(&q->dl_sch);
}
@ -1100,7 +1137,7 @@ int srslte_pdsch_encode(srslte_pdsch_t* q,
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (cfg->grant.nof_re > q->max_re || cfg->grant.nof_re > q->max_re) {
if (cfg->grant.nof_re > q->max_re) {
ERROR("Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n",
cfg->grant.nof_re,
q->max_re,
@ -1255,6 +1292,21 @@ srslte_pdsch_rx_info(srslte_pdsch_cfg_t* cfg, srslte_pdsch_res_t res[SRSLTE_MAX_
uint32_t len = srslte_print_check(str, str_len, 0, "rnti=0x%x", cfg->rnti);
len += srslte_pdsch_grant_rx_info(&cfg->grant, res, &str[len], str_len - len);
if (cfg->meas_evm_en) {
len = srslte_print_check(str, str_len, len, ", evm={", 0);
for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (cfg->grant.tb[i].enabled && !isnan(res[i].evm)) {
len = srslte_print_check(str, str_len, len, "%.2f", res[i].evm);
if (i < SRSLTE_MAX_CODEWORDS - 1) {
if (cfg->grant.tb[i + 1].enabled) {
len = srslte_print_check(str, str_len, len, "/", 0);
}
}
}
}
len = srslte_print_check(str, str_len, len, "}", 0);
}
if (cfg->meas_time_en) {
len = srslte_print_check(str, str_len, len, ", t=%d us\n", cfg->meas_time_value);
}

View File

@ -33,8 +33,6 @@
#include "tbs_tables.h"
#define min(a, b) (a < b ? a : b)
/* Convert Type2 scheduling L_crb and RB_start to RIV value */
uint32_t srslte_ra_type2_to_riv(uint32_t L_crb, uint32_t RB_start, uint32_t nof_prb)
{
@ -201,7 +199,7 @@ int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx, bool is_ul)
/* Table 7.1.7.2.1-1: Transport block size table on 36.213 */
int srslte_ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb)
{
if (tbs_idx < 34 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) {
if (tbs_idx < SRSLTE_RA_NOF_TBS_IDX && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) {
return tbs_table[tbs_idx][n_prb - 1];
} else {
return SRSLTE_ERROR;

View File

@ -32,7 +32,7 @@ static const int ul_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26};
/* Transport Block Size from 3GPP TS 36.213 v12.13.0 table 7.1.7.2.1-1 */
static const int tbs_table[34][110] = {
static const int tbs_table[SRSLTE_RA_NOF_TBS_IDX][110] = {
/* The matrix below is automatically generated from ETSI TS 136 213 V12.13.0 (2019-03) */
{16, 32, 56, 88, 120, 152, 176, 208, 224, 256, 288, 328, 344, 376, 392, 424, 456, 488, 504,
536, 568, 600, 616, 648, 680, 712, 744, 776, 776, 808, 840, 872, 904, 936, 968, 1000, 1032, 1032,

View File

@ -200,7 +200,7 @@ void* srslte_vec_realloc(void* ptr, uint32_t old_size, uint32_t new_size)
#endif
}
void srslte_vec_fprint_c(FILE* stream, cf_t* x, const uint32_t len)
void srslte_vec_fprint_c(FILE* stream, const cf_t* x, const uint32_t len)
{
int i;
fprintf(stream, "[");
@ -210,7 +210,7 @@ void srslte_vec_fprint_c(FILE* stream, cf_t* x, const uint32_t len)
fprintf(stream, "];\n");
}
void srslte_vec_fprint_f(FILE* stream, float* x, const uint32_t len)
void srslte_vec_fprint_f(FILE* stream, const float* x, const uint32_t len)
{
int i;
fprintf(stream, "[");
@ -220,7 +220,7 @@ void srslte_vec_fprint_f(FILE* stream, float* x, const uint32_t len)
fprintf(stream, "];\n");
}
void srslte_vec_fprint_b(FILE* stream, uint8_t* x, const uint32_t len)
void srslte_vec_fprint_b(FILE* stream, const uint8_t* x, const uint32_t len)
{
int i;
fprintf(stream, "[");
@ -230,7 +230,7 @@ void srslte_vec_fprint_b(FILE* stream, uint8_t* x, const uint32_t len)
fprintf(stream, "];\n");
}
void srslte_vec_fprint_bs(FILE* stream, int8_t* x, const uint32_t len)
void srslte_vec_fprint_bs(FILE* stream, const int8_t* x, const uint32_t len)
{
int i;
fprintf(stream, "[");
@ -240,7 +240,7 @@ void srslte_vec_fprint_bs(FILE* stream, int8_t* x, const uint32_t len)
fprintf(stream, "];\n");
}
void srslte_vec_fprint_byte(FILE* stream, uint8_t* x, const uint32_t len)
void srslte_vec_fprint_byte(FILE* stream, const uint8_t* x, const uint32_t len)
{
int i;
fprintf(stream, "[");
@ -250,7 +250,7 @@ void srslte_vec_fprint_byte(FILE* stream, uint8_t* x, const uint32_t len)
fprintf(stream, "];\n");
}
void srslte_vec_fprint_i(FILE* stream, int* x, const uint32_t len)
void srslte_vec_fprint_i(FILE* stream, const int* x, const uint32_t len)
{
int i;
fprintf(stream, "[");
@ -260,7 +260,7 @@ void srslte_vec_fprint_i(FILE* stream, int* x, const uint32_t len)
fprintf(stream, "];\n");
}
void srslte_vec_fprint_s(FILE* stream, short* x, const uint32_t len)
void srslte_vec_fprint_s(FILE* stream, const int16_t* x, const uint32_t len)
{
int i;
fprintf(stream, "[");

View File

@ -140,9 +140,6 @@ void parse_args(int argc, char** argv)
}
}
int prbset_num = 1, last_prbset_num = 1;
int prbset_orig = 0;
int work_enb(srslte_enb_dl_t* enb_dl,
srslte_dl_sf_cfg_t* dl_sf,
srslte_dci_cfg_t* dci_cfg,
@ -203,16 +200,16 @@ int work_ue(srslte_ue_dl_t* ue_dl,
{
if (srslte_ue_dl_decode_fft_estimate(ue_dl, sf_cfg_dl, ue_dl_cfg) < 0) {
ERROR("Getting PDCCH FFT estimate sf_idx=%d\n", sf_idx);
return -1;
return SRSLTE_ERROR;
}
int nof_grants = srslte_ue_dl_find_dl_dci(ue_dl, sf_cfg_dl, ue_dl_cfg, rnti, dci_dl);
if (nof_grants < 0) {
ERROR("Looking for DL grants sf_idx=%d\n", sf_idx);
return -1;
return SRSLTE_ERROR;
} else if (nof_grants == 0) {
ERROR("Failed to find DCI in sf_idx=%d\n", sf_idx);
return -1;
return SRSLTE_ERROR;
}
// Enable power allocation
@ -221,15 +218,18 @@ int work_ue(srslte_ue_dl_t* ue_dl,
ue_dl_cfg->cfg.pdsch.p_b = (transmission_mode > SRSLTE_TM1) ? 1 : 0; // 0 dB
ue_dl_cfg->cfg.pdsch.rnti = dci_dl->rnti;
ue_dl_cfg->cfg.pdsch.csi_enable = false;
ue_dl_cfg->cfg.pdsch.meas_evm_en = true;
char str[512];
srslte_dci_dl_info(&dci_dl[0], str, 512);
INFO("UE PDCCH: rnti=0x%x, %s\n", rnti, str);
if (srslte_verbose >= SRSLTE_VERBOSE_INFO) {
char str[512];
srslte_dci_dl_info(&dci_dl[0], str, 512);
INFO("UE PDCCH: rnti=0x%x, %s\n", rnti, str);
}
if (srslte_ra_dl_dci_to_grant(
&cell, sf_cfg_dl, transmission_mode, enable_256qam, &dci_dl[0], &ue_dl_cfg->cfg.pdsch.grant)) {
ERROR("Computing DL grant sf_idx=%d\n", sf_idx);
return -1;
return SRSLTE_ERROR;
}
// Reset softbuffer
@ -241,34 +241,16 @@ int work_ue(srslte_ue_dl_t* ue_dl,
if (srslte_ue_dl_decode_pdsch(ue_dl, sf_cfg_dl, &ue_dl_cfg->cfg.pdsch, pdsch_res)) {
ERROR("ERROR: Decoding PDSCH sf_idx=%d\n", sf_idx);
return -1;
return SRSLTE_ERROR;
}
srslte_pdsch_tx_info(&ue_dl_cfg->cfg.pdsch, str, 512);
INFO("UE PDSCH: rnti=0x%x, %s\n", rnti, str);
return 0;
}
unsigned int reverse(register unsigned int x)
{
x = (((x & (uint32_t)0xaaaaaaaa) >> (uint32_t)1) | ((x & (uint32_t)0x55555555) << (uint32_t)1));
x = (((x & (uint32_t)0xcccccccc) >> (uint32_t)2) | ((x & (uint32_t)0x33333333) << (uint32_t)2));
x = (((x & (uint32_t)0xf0f0f0f0) >> (uint32_t)4) | ((x & (uint32_t)0x0f0f0f0f) << (uint32_t)4));
x = (((x & (uint32_t)0xff00ff00) >> (uint32_t)8) | ((x & (uint32_t)0x00ff00ff) << (uint32_t)8));
return ((x >> (uint32_t)16) | (x << (uint32_t)16));
}
uint32_t prbset_to_bitmask()
{
uint32_t mask = 0;
uint32_t nb = (uint32_t)ceilf((float)cell.nof_prb / srslte_ra_type0_P(cell.nof_prb));
for (uint32_t i = 0; i < nb; i++) {
if (i >= prbset_orig && i < prbset_orig + prbset_num) {
mask = mask | ((uint32_t)0x1 << i);
}
if (srslte_verbose >= SRSLTE_VERBOSE_INFO) {
char str[512];
srslte_pdsch_rx_info(&ue_dl_cfg->cfg.pdsch, pdsch_res, str, 512);
INFO("eNb PDSCH: rnti=0x%x, %s\n", rnti, str);
}
return reverse(mask) >> (uint32_t)(32 - nb);
return SRSLTE_SUCCESS;
}
static int
@ -448,8 +430,8 @@ int main(int argc, char** argv)
/*
* DCI Configuration
*/
srslte_dci_dl_t dci;
srslte_dci_cfg_t dci_cfg;
srslte_dci_dl_t dci = {};
srslte_dci_cfg_t dci_cfg = {};
dci_cfg.srs_request_enabled = false;
dci_cfg.ra_format_enabled = false;
dci_cfg.multiple_csi_request_enabled = false;
@ -480,14 +462,19 @@ int main(int argc, char** argv)
}
// Set PRB Allocation type
#if 0
dci.alloc_type = SRSLTE_RA_ALLOC_TYPE2;
uint32_t n_prb = 1; ///< Number of PRB
uint32_t s_prb = 0; ///< Start
dci.type2_alloc.riv = srslte_ra_type2_to_riv(n_prb, s_prb, cell.nof_prb);
#else
dci.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
prbset_num = (int)ceilf((float)cell.nof_prb / srslte_ra_type0_P(cell.nof_prb));
last_prbset_num = prbset_num;
dci.type0_alloc.rbg_bitmask = prbset_to_bitmask();
dci.type0_alloc.rbg_bitmask = 0xffffffff; // All PRB
#endif
// Set TB
if (transmission_mode < SRSLTE_TM3) {
dci.format = SRSLTE_DCI_FORMAT1;
dci.format = (dci.alloc_type == SRSLTE_RA_ALLOC_TYPE2) ? SRSLTE_DCI_FORMAT1A : SRSLTE_DCI_FORMAT1;
dci.tb[0].mcs_idx = mcs;
dci.tb[0].rv = 0;
dci.tb[0].ndi = 0;
@ -530,7 +517,7 @@ int main(int argc, char** argv)
/*
* Run eNodeB
*/
srslte_dl_sf_cfg_t sf_cfg_dl;
srslte_dl_sf_cfg_t sf_cfg_dl = {};
sf_cfg_dl.tti = sf_idx % 10;
sf_cfg_dl.cfi = cfi;
sf_cfg_dl.sf_type = SRSLTE_SF_NORM;