Initial NR-PBCH-DMRS integration

This commit is contained in:
Xavier Arteaga 2021-05-26 18:10:40 +02:00 committed by Andre Puschmann
parent 997f7db23a
commit a245039cf3
7 changed files with 367 additions and 18 deletions

View File

@ -0,0 +1,62 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 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.
*
*/
#ifndef SRSRAN_DMRS_PBCH_H
#define SRSRAN_DMRS_PBCH_H
#include "srsran/phy/common/phy_common_nr.h"
/**
* @brief Describes the DeModulation Reference Signals (DMRS) for NR PBCH configuration
*/
typedef struct SRSRAN_API {
uint32_t N_id; ///< Physical cell identifier
uint32_t n_hf; ///< Number of half radio frame, 0 or 1
uint32_t ssb_idx; ///< SSB candidate index
uint32_t L_max; ///< Number of SSB opportunities in half radio frame
float beta; ///< Power allocation specified in TS 38.213
srsran_subcarrier_spacing_t scs; ///< SSB configured subcarrier spacing
} srsran_dmrs_pbch_cfg_t;
/**
* @brief Describes an NR PBCH DMRS based measurement
*/
typedef struct SRSRAN_API {
float corr; ///< Normalised correlation
float epre; ///< Linear energy per resource element
float rsrp; ///< Linear RSRP
float cfo_hz; ///< CFO in Hz
float avg_delay_us; ///< Average delay in us
} srsran_dmrs_pbch_meas_t;
/**
* @brief Put NR PBCH DMRS in the SSB resource grid
* @param cfg PBCH DMRS configuration
* @param[out] ssb_grid SSB resource grid
* @return SRSRAN_SUCCESS if the inputs and configuration are valid, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_dmrs_pbch_put(const srsran_dmrs_pbch_cfg_t* cfg, cf_t ssb_grid[SRSRAN_SSB_NOF_RE]);
/**
* @brief Estimates NR PBCH DMRS
* @param cfg PBCH DMRS configuration
* @param ssb_grid Demodulated SSB resource grid
* @param[out] ce Estimated channel
* @param[out] meas Estimated channel measurements
* @return SRSRAN_SUCCESS if the inputs and configuration are valid, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_dmrs_pbch_estimate(const srsran_dmrs_pbch_cfg_t* cfg,
const cf_t ssb_grid[SRSRAN_SSB_NOF_RE],
cf_t ce[SRSRAN_SSB_NOF_RE],
srsran_dmrs_pbch_meas_t* meas);
#endif // SRSRAN_DMRS_PBCH_H

View File

@ -75,7 +75,7 @@ typedef struct SRSRAN_API {
* @brief Initialises an NR PBCH object with the provided arguments
* @param q NR PBCH object
* @param args Arguments providing the desired configuration
* @return SRSRAN_SUCCESS if initialization is successful, SRSLTE_ERROR code otherwise
* @return SRSRAN_SUCCESS if initialization is successful, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_pbch_nr_init(srsran_pbch_nr_t* q, const srsran_pbch_nr_args_t* args);
@ -91,7 +91,7 @@ SRSRAN_API void srsran_pbch_nr_free(srsran_pbch_nr_t* q);
* @param cfg NR PBCH configuration
* @param msg NR PBCH message to transmit
* @param[out] ssb_grid SSB resource grid
* @return SRSRAN_SUCCESS if encoding is successful, SRSLTE_ERROR code otherwise
* @return SRSRAN_SUCCESS if encoding is successful, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_pbch_nr_encode(srsran_pbch_nr_t* q,
const srsran_pbch_nr_cfg_t* cfg,
@ -104,13 +104,15 @@ SRSRAN_API int srsran_pbch_nr_encode(srsran_pbch_nr_t* q,
* @param cfg NR PBCH configuration
* @param ssb_idx SSB candidate index
* @param[in] ssb_grid SSB resource grid
* @param[in] ce Channel estimates for the SSB resource grid
* @param msg NR PBCH message received
* @return SRSRAN_SUCCESS if decoding is successful, SRSLTE_ERROR code otherwise
* @return SRSRAN_SUCCESS if decoding is successful, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_pbch_nr_decode(srsran_pbch_nr_t* q,
const srsran_pbch_nr_cfg_t* cfg,
uint32_t ssb_idx,
const cf_t ssb_grid[SRSRAN_SSB_NOF_RE],
const cf_t ce[SRSRAN_SSB_NOF_RE],
srsran_pbch_msg_nr_t* msg);
SRSRAN_API uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len);

View File

@ -50,6 +50,7 @@ typedef struct SRSRAN_API {
bool enable_encode; ///< Enables PBCH Encoder
bool enable_decode; ///< Enables PBCH Decoder
bool disable_polar_simd; ///< Disables polar encoder/decoder SIMD acceleration
float pbch_dmrs_thr; ///< NR-PBCH DMRS threshold for blind decoding, set to 0 for default
} srsran_ssb_args_t;
/**
@ -127,13 +128,20 @@ SRSRAN_API void srsran_ssb_free(srsran_ssb_t* q);
SRSRAN_API int srsran_ssb_set_cfg(srsran_ssb_t* q, const srsran_ssb_cfg_t* cfg);
/**
* @brief Decodes PBCH in the given time domain signal
* @note It currently expects an input buffer of half radio frame
* @param q SSB object
* @param N_id Physical Cell Identifier
* @param ssb_idx SSB candidate index
* @param n_hf Number of hald radio frame, 0 or 1
* @param in Input baseband buffer
* @return SRSRAN_SUCCESS if the parameters are valid, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int
srsran_ssb_decode_pbch(srsran_ssb_t* q, uint32_t N_id, uint32_t ssb_idx, const cf_t* in, srsran_pbch_msg_nr_t* msg);
SRSRAN_API int srsran_ssb_decode_pbch(srsran_ssb_t* q,
uint32_t N_id,
uint32_t ssb_idx,
uint32_t n_hf,
const cf_t* in,
srsran_pbch_msg_nr_t* msg);
/**
* @brief Decides if the SSB object is configured and a given subframe is configured for SSB transmission

View File

@ -0,0 +1,218 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 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 "srsran/phy/ch_estimation/dmrs_pbch.h"
#include "srsran/phy/common/sequence.h"
#include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/vector.h"
#include <complex.h>
#include <math.h>
/*
* Number of NR PBCH DMRS resource elements present in an SSB resource grid
*/
#define DMRS_PBCH_NOF_RE 144
static uint32_t dmrs_pbch_cinit(const srsran_dmrs_pbch_cfg_t* cfg)
{
// Default values for L_max == 4
uint64_t i_ssb = (cfg->ssb_idx & 0b11U) + 4UL * cfg->n_hf; // Least 2 significant bits
if (cfg->L_max == 8 || cfg->L_max == 64) {
i_ssb = cfg->ssb_idx & 0b111U; // Least 3 significant bits
}
return SRSRAN_SEQUENCE_MOD(((i_ssb + 1UL) * (SRSRAN_FLOOR(cfg->N_id, 4UL) + 1UL) << 11UL) + ((i_ssb + 1UL) << 6UL) +
(cfg->N_id % 4));
}
int srsran_dmrs_pbch_put(const srsran_dmrs_pbch_cfg_t* cfg, cf_t ssb_grid[SRSRAN_SSB_NOF_RE])
{
// Validate inputs
if (cfg == NULL || ssb_grid == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Calculate index shift
uint32_t v = cfg->N_id % 4;
// Calculate power allocation
float beta = M_SQRT1_2;
if (isnormal(cfg->beta)) {
beta = cfg->beta;
}
// Initialise sequence
uint32_t cinit = dmrs_pbch_cinit(cfg);
srsran_sequence_state_t sequence_state = {};
srsran_sequence_state_init(&sequence_state, cinit);
// Generate sequence
cf_t r[DMRS_PBCH_NOF_RE];
srsran_sequence_state_gen_f(&sequence_state, beta, (float*)r, DMRS_PBCH_NOF_RE * 2);
// r sequence read index
uint32_t r_idx = 0;
// Put sequence in symbol 1
for (uint32_t k = v; k < SRSRAN_SSB_BW_SUBC; k += 4) {
ssb_grid[SRSRAN_SSB_BW_SUBC * 1 + k] = r[r_idx++];
}
// Put sequence in symbol 2, lower section
for (uint32_t k = v; k < 48; k += 4) {
ssb_grid[SRSRAN_SSB_BW_SUBC * 2 + k] = r[r_idx++];
}
// Put sequence in symbol 2, upper section
for (uint32_t k = 192 + v; k < SRSRAN_SSB_BW_SUBC; k += 4) {
ssb_grid[SRSRAN_SSB_BW_SUBC * 2 + k] = r[r_idx++];
}
// Put sequence in symbol 3
for (uint32_t k = v; k < SRSRAN_SSB_BW_SUBC; k += 4) {
ssb_grid[SRSRAN_SSB_BW_SUBC * 3 + k] = r[r_idx++];
}
return SRSRAN_SUCCESS;
}
int dmrs_pbch_extract_lse(const srsran_dmrs_pbch_cfg_t* cfg,
const cf_t ssb_grid[SRSRAN_SSB_NOF_RE],
cf_t lse[DMRS_PBCH_NOF_RE])
{
// Calculate index shift
uint32_t v = cfg->N_id % 4;
// Calculate power allocation
float beta = M_SQRT1_2;
if (isnormal(cfg->beta)) {
beta = cfg->beta;
}
// Initialise sequence
uint32_t cinit = dmrs_pbch_cinit(cfg);
srsran_sequence_state_t sequence_state = {};
srsran_sequence_state_init(&sequence_state, cinit);
// Generate sequence
cf_t r[DMRS_PBCH_NOF_RE];
srsran_sequence_state_gen_f(&sequence_state, beta, (float*)r, DMRS_PBCH_NOF_RE * 2);
// r sequence read index
uint32_t r_idx = 0;
// Put sequence in symbol 1
for (uint32_t k = v; k < SRSRAN_SSB_BW_SUBC; k += 4) {
lse[r_idx++] = ssb_grid[SRSRAN_SSB_BW_SUBC * 1 + k];
}
// Put sequence in symbol 2, lower section
for (uint32_t k = v; k < 48; k += 4) {
lse[r_idx++] = ssb_grid[SRSRAN_SSB_BW_SUBC * 2 + k];
}
// Put sequence in symbol 2, upper section
for (uint32_t k = 192 + v; k < SRSRAN_SSB_BW_SUBC; k += 4) {
lse[r_idx++] = ssb_grid[SRSRAN_SSB_BW_SUBC * 2 + k];
}
// Put sequence in symbol 3
for (uint32_t k = v; k < SRSRAN_SSB_BW_SUBC; k += 4) {
lse[r_idx++] = ssb_grid[SRSRAN_SSB_BW_SUBC * 3 + k];
}
// Calculate actual least square estimates
srsran_vec_prod_conj_ccc(lse, r, lse, DMRS_PBCH_NOF_RE);
return SRSRAN_SUCCESS;
}
int srsran_dmrs_pbch_estimate(const srsran_dmrs_pbch_cfg_t* cfg,
const cf_t ssb_grid[SRSRAN_SSB_NOF_RE],
cf_t ce[SRSRAN_SSB_NOF_RE],
srsran_dmrs_pbch_meas_t* meas)
{
// Validate inputs
if (cfg == NULL || ssb_grid == NULL || ce == NULL || meas == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Extract least square estimates
cf_t lse[DMRS_PBCH_NOF_RE];
if (dmrs_pbch_extract_lse(cfg, ssb_grid, lse) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
float scs_hz = SRSRAN_SUBC_SPACING_NR(cfg->scs);
if (!isnormal(scs_hz)) {
ERROR("Invalid SCS");
return SRSRAN_ERROR;
}
// Compute average delay in microseconds from the symbols 1 and 3 (symbol 2 does not carry PBCH in all the grid)
float avg_delay1_norm = srsran_vec_estimate_frequency(&lse[0], 60) / 4.0f;
float avg_delay3_norm = srsran_vec_estimate_frequency(&lse[84], 60) / 4.0f;
float avg_delay_norm = (avg_delay1_norm + avg_delay3_norm) / 2.0f;
float avg_delay_us = avg_delay_norm / scs_hz;
// Generate a second SSB grid with the corrected average delay
cf_t ssb_grid_corrected[SRSRAN_SSB_NOF_RE];
for (uint32_t l = 0; l < SRSRAN_SSB_DURATION_NSYMB; l++) {
srsran_vec_apply_cfo(&ssb_grid[SRSRAN_SSB_BW_SUBC * l],
avg_delay_norm,
&ssb_grid_corrected[SRSRAN_SSB_BW_SUBC * l],
SRSRAN_SSB_BW_SUBC);
}
// Extract LSE from corrected grid
if (dmrs_pbch_extract_lse(cfg, ssb_grid_corrected, lse) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
// Compute correlation of symbols 1 and 3
cf_t corr1 = srsran_vec_acc_cc(&lse[0], 60) / 60.0f;
cf_t corr3 = srsran_vec_acc_cc(&lse[84], 60) / 60.0f;
// Estimate CFO from correlation
float distance_s = srsran_symbol_distance_s(1, 3, cfg->scs);
float cfo_hz = 0.0f;
if (isnormal(distance_s)) {
cfo_hz = cargf(corr1 * conjf(corr3)) / (2.0f * (float)M_PI * distance_s);
}
// Estimate wideband gain at symbol 0
cf_t wideband_gain = (srsran_vec_acc_cc(lse, DMRS_PBCH_NOF_RE) / DMRS_PBCH_NOF_RE) *
cexpf(I * 2.0f * M_PI * srsran_symbol_offset_s(2, cfg->scs) * cfo_hz);
// Compute RSRP from correlation
float rsrp = SRSRAN_CSQABS((corr1 + corr3) / 2.0f);
// Compute EPRE
float epre = srsran_vec_avg_power_cf(lse, DMRS_PBCH_NOF_RE);
// Write measurements
meas->corr = rsrp / epre;
meas->epre = epre;
meas->rsrp = rsrp;
meas->cfo_hz = cfo_hz;
meas->avg_delay_us = avg_delay_us;
// Compute channel estimates
for (uint32_t l = 0; l < SRSRAN_SSB_DURATION_NSYMB; l++) {
float t_s = srsran_symbol_offset_s(l, cfg->scs);
cf_t symbol_wideband_gain = cexpf(-I * 2.0f * M_PI * cfo_hz * t_s) * wideband_gain;
srsran_vec_gen_sine(symbol_wideband_gain, -avg_delay_norm, &ce[l * SRSRAN_SSB_BW_SUBC], SRSRAN_SSB_BW_SUBC);
}
return SRSRAN_SUCCESS;
}

View File

@ -14,9 +14,11 @@
#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/modem/mod.h"
#include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/simd.h"
#include "srsran/phy/utils/vector.h"
#define PBCH_NR_DEBUG_TX(...) DEBUG("PBCH-NR Tx: " __VA_ARGS__)
@ -594,6 +596,7 @@ int srsran_pbch_nr_decode(srsran_pbch_nr_t* q,
const srsran_pbch_nr_cfg_t* cfg,
uint32_t ssb_idx,
const cf_t ssb_grid[SRSRAN_SSB_NOF_RE],
const cf_t ce_grid[SRSRAN_SSB_NOF_RE],
srsran_pbch_msg_nr_t* msg)
{
if (q == NULL || cfg == NULL || msg == NULL || ssb_grid == NULL) {
@ -602,9 +605,18 @@ int srsran_pbch_nr_decode(srsran_pbch_nr_t* q,
// 7.3.3.3 Mapping to physical resources
// 7.4.3.1.3 Mapping of PBCH and DM-RS within an SS/PBCH block
cf_t symbols[PBCH_NR_M];
srsran_simd_aligned cf_t symbols[PBCH_NR_M];
pbch_nr_demapping(cfg, ssb_grid, symbols);
srsran_simd_aligned cf_t ce[PBCH_NR_M];
pbch_nr_demapping(cfg, ce_grid, ce);
// Channel equalizer
if (srsran_predecoding_single(symbols, ce, symbols, NULL, PBCH_NR_M, 1.0f, 0.0f) < SRSRAN_SUCCESS) {
ERROR("Error in predecoder");
return SRSRAN_ERROR;
}
// 7.3.3.2 Modulation
int8_t llr[PBCH_NR_E];
srsran_demod_soft_demodulate_b(SRSRAN_MOD_QPSK, symbols, llr, PBCH_NR_M);

View File

@ -11,6 +11,7 @@
*/
#include "srsran/phy/sync/ssb.h"
#include "srsran/phy/ch_estimation/dmrs_pbch.h"
#include "srsran/phy/sync/pss_nr.h"
#include "srsran/phy/sync/sss_nr.h"
#include "srsran/phy/utils/debug.h"
@ -33,6 +34,11 @@
*/
#define SSB_CORR_SZ(SYMB_SZ) SRSRAN_MIN(1U << (uint32_t)ceil(log2((double)(SYMB_SZ)) + 3.0), 1U << 13U)
/*
* Default NR-PBCH DMRS normalised correlation (RSRP/EPRE) threshold
*/
#define SSB_PBCH_DMRS_DEFAULT_CORR_THR 0.6f
static int ssb_init_corr(srsran_ssb_t* q)
{
// Initialise correlation only if it is enabled
@ -83,9 +89,8 @@ int srsran_ssb_init(srsran_ssb_t* q, const srsran_ssb_args_t* args)
q->args = *args;
// Check if the maximum sampling rate is in range, force default otherwise
if (!isnormal(q->args.max_srate_hz) || q->args.max_srate_hz < 0.0) {
q->args.max_srate_hz = SRSRAN_SSB_DEFAULT_MAX_SRATE_HZ;
}
q->args.max_srate_hz = (!isnormal(q->args.max_srate_hz)) ? SRSRAN_SSB_DEFAULT_MAX_SRATE_HZ : q->args.max_srate_hz;
q->args.pbch_dmrs_thr = (!isnormal(q->args.pbch_dmrs_thr)) ? SSB_PBCH_DMRS_DEFAULT_CORR_THR : q->args.pbch_dmrs_thr;
q->scs_hz = (float)SRSRAN_SUBC_SPACING_NR(q->args.min_scs);
q->max_symbol_sz = (uint32_t)round(q->args.max_srate_hz / q->scs_hz);
@ -539,7 +544,16 @@ int srsran_ssb_add(srsran_ssb_t* q,
}
// Put PBCH DMRS
// ...
srsran_dmrs_pbch_cfg_t pbch_dmrs_cfg = {};
pbch_dmrs_cfg.N_id = N_id;
pbch_dmrs_cfg.n_hf = msg->hrf ? 0 : 1;
pbch_dmrs_cfg.ssb_idx = msg->ssb_idx;
pbch_dmrs_cfg.L_max = q->Lmax;
pbch_dmrs_cfg.beta = 0.0f;
if (srsran_dmrs_pbch_put(&pbch_dmrs_cfg, ssb_grid) < SRSRAN_SUCCESS) {
ERROR("Error putting PBCH DMRS");
return SRSRAN_ERROR;
}
// Put PBCH payload
srsran_pbch_nr_cfg_t pbch_cfg = {};
@ -630,7 +644,7 @@ ssb_measure(srsran_ssb_t* q, const cf_t ssb_grid[SRSRAN_SSB_NOF_RE], uint32_t N_
uint32_t N_id_1 = SRSRAN_NID_1_NR(N_id);
uint32_t N_id_2 = SRSRAN_NID_2_NR(N_id);
// Extract PSS LSE
// Extract PSS and SSS LSE
cf_t pss_lse[SRSRAN_PSS_NR_LEN];
cf_t sss_lse[SRSRAN_SSS_NR_LEN];
if (srsran_pss_nr_extract_lse(ssb_grid, N_id_2, pss_lse) < SRSRAN_SUCCESS ||
@ -882,7 +896,12 @@ int srsran_ssb_csi_measure(srsran_ssb_t* q,
return SRSRAN_SUCCESS;
}
int srsran_ssb_decode_pbch(srsran_ssb_t* q, uint32_t N_id, uint32_t ssb_idx, const cf_t* in, srsran_pbch_msg_nr_t* msg)
int srsran_ssb_decode_pbch(srsran_ssb_t* q,
uint32_t N_id,
uint32_t ssb_idx,
uint32_t n_hf,
const cf_t* in,
srsran_pbch_msg_nr_t* msg)
{
// Verify inputs
if (q == NULL || N_id >= SRSRAN_NOF_NID_NR || in == NULL || msg == NULL || !isnormal(q->scs_hz)) {
@ -907,14 +926,37 @@ int srsran_ssb_decode_pbch(srsran_ssb_t* q, uint32_t N_id, uint32_t ssb_idx, con
return SRSRAN_ERROR;
}
// Prepare configuration
// Prepare PBCH DMRS configuration
srsran_dmrs_pbch_cfg_t pbch_dmrs_cfg = {};
pbch_dmrs_cfg.N_id = N_id;
pbch_dmrs_cfg.n_hf = n_hf;
pbch_dmrs_cfg.ssb_idx = ssb_idx;
pbch_dmrs_cfg.L_max = q->Lmax;
pbch_dmrs_cfg.beta = 0.0f;
pbch_dmrs_cfg.scs = q->cfg.scs;
// Compute PBCH channel estimates
srsran_dmrs_pbch_meas_t meas = {};
cf_t ce[SRSRAN_SSB_NOF_RE] = {};
if (srsran_dmrs_pbch_estimate(&pbch_dmrs_cfg, ssb_grid, ce, &meas) < SRSRAN_SUCCESS) {
ERROR("Error estimating channel");
return SRSRAN_ERROR;
}
// Compare measurement with threshold
if (meas.corr < q->args.pbch_dmrs_thr) {
msg->crc = false;
return SRSRAN_SUCCESS;
}
// Prepare PBCH configuration
srsran_pbch_nr_cfg_t pbch_cfg = {};
pbch_cfg.N_id = N_id;
pbch_cfg.ssb_scs = q->cfg.scs;
pbch_cfg.Lmax = q->Lmax;
// Decode
if (srsran_pbch_nr_decode(&q->pbch, &pbch_cfg, ssb_idx, ssb_grid, msg) < SRSRAN_SUCCESS) {
if (srsran_pbch_nr_decode(&q->pbch, &pbch_cfg, ssb_idx, ssb_grid, ce, msg) < SRSRAN_SUCCESS) {
ERROR("Error decoding PBCH");
return SRSRAN_ERROR;
}

View File

@ -15,6 +15,7 @@
#include "srsran/phy/sync/ssb.h"
#include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/vector.h"
#include <complex.h>
#include <getopt.h>
#include <srsran/phy/utils/random.h>
#include <stdlib.h>
@ -25,9 +26,10 @@ static srsran_subcarrier_spacing_t carrier_scs = srsran_subcarrier_spacing_1
static srsran_subcarrier_spacing_t ssb_scs = srsran_subcarrier_spacing_30kHz;
// Channel parameters
static int32_t delay_n = 0;
static float cfo_hz = 0.0f;
static float n0_dB = -300.0f;
static cf_t wideband_gain = 1.0f + 0.5 * I;
static int32_t delay_n = 1;
static float cfo_hz = 1000.0f;
static float n0_dB = -10.0f;
// Test context
static srsran_random_t random_gen = NULL;
@ -69,6 +71,9 @@ static void run_channel()
// AWGN
srsran_channel_awgn_run_c(&awgn, buffer, buffer, hf_len);
// Wideband gain
srsran_vec_sc_prod_ccc(buffer, wideband_gain, buffer, hf_len);
}
static void gen_pbch_msg(srsran_pbch_msg_nr_t* pbch_msg, uint32_t ssb_idx)
@ -129,7 +134,7 @@ static int test_case_1(srsran_ssb_t* ssb)
// Decode
gettimeofday(&t[1], NULL);
srsran_pbch_msg_nr_t pbch_msg_rx = {};
TESTASSERT(srsran_ssb_decode_pbch(ssb, pci, ssb_idx, buffer, &pbch_msg_rx) == SRSRAN_SUCCESS);
TESTASSERT(srsran_ssb_decode_pbch(ssb, pci, ssb_idx, 0, buffer, &pbch_msg_rx) == SRSRAN_SUCCESS);
gettimeofday(&t[2], NULL);
get_time_interval(t);
t_decode_usec += t[0].tv_usec + t[0].tv_sec * 1000000UL;