mirror of https://github.com/pvnis/srsRAN_4G.git
Initial EVM calculation commit and other easthetic changes
parent
4739f3084f
commit
f261365c91
@ -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_
|
Loading…
Reference in New Issue