Implemented PBCH blind decode

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent a31f3d42ce
commit 5181a9d64c

@ -21,7 +21,7 @@
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 ssb_idx; ///< SSB candidate index, up to 3 LSB are significant
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
@ -46,17 +46,26 @@ typedef struct SRSRAN_API {
*/
SRSRAN_API int srsran_dmrs_pbch_put(const srsran_dmrs_pbch_cfg_t* cfg, cf_t ssb_grid[SRSRAN_SSB_NOF_RE]);
/**
* @brief Measures NR PBCH DMRS
* @param cfg PBCH DMRS configuration
* @param ssb_grid SSB resource grid
* @param[out] meas Measurement
* @return SRSRAN_SUCCESS if the inputs and configuration are valid, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_dmrs_pbch_measure(const srsran_dmrs_pbch_cfg_t* cfg,
const cf_t ssb_grid[SRSRAN_SSB_NOF_RE],
srsran_dmrs_pbch_meas_t* meas);
/**
* @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);
cf_t ce[SRSRAN_SSB_NOF_RE]);
#endif // SRSRAN_DMRS_PBCH_H

@ -39,11 +39,11 @@ typedef struct SRSRAN_API {
* @brief Describes the NR PBCH configuration
*/
typedef struct SRSRAN_API {
uint32_t N_id; ///< Physical cell identifier
srsran_subcarrier_spacing_t ssb_scs; ///< SSB Subcarrier spacing
uint32_t Lmax; ///< Number of SSB opportunities, described in TS 38.213 4.1 ...
float beta; ///< Scaling factor for PBCH symbols, set to zero for default
float beta_dmrs; ///< Scaling factor for PBCH DM-RS, set to zero for default
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, up to 4 LSB significant
uint32_t Lmax; ///< Number of SSB opportunities, described in TS 38.213 4.1 ...
float beta; ///< Scaling factor for PBCH symbols, set to zero for default
} srsran_pbch_nr_cfg_t;
/**
@ -102,15 +102,12 @@ SRSRAN_API int srsran_pbch_nr_encode(srsran_pbch_nr_t* q,
* @brief Decodes an NR PBCH message in the SSB resource grid
* @param q NR PBCH object
* @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, 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);

@ -105,6 +105,16 @@ typedef struct SRSRAN_API {
cf_t* pss_seq[SRSRAN_NOF_NID_2_NR]; ///< Possible frequency domain PSS for find
} srsran_ssb_t;
/**
* @brief Describes an SSB search result
* @note if pbch.crc is true, SSB transmission is found and decoded. Otherwise, no SSB transmission has been decoded
*/
typedef struct {
uint32_t N_id; ///< Most suitable physical cell identifier
uint32_t t_offset; ///< Time offset in the input samples
srsran_pbch_msg_nr_t pbch_msg; ///< Physical broadcast channel message of the most suitable SSB candidate
} srsran_ssb_search_res_t;
/**
* @brief Initialises configures NR SSB with the given arguments
* @param q SSB object
@ -131,18 +141,28 @@ SRSRAN_API int srsran_ssb_set_cfg(srsran_ssb_t* q, const srsran_ssb_cfg_t* cfg);
* @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 ssb_idx SSB candidate index
* @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,
uint32_t n_hf,
uint32_t ssb_idx,
const cf_t* in,
srsran_pbch_msg_nr_t* msg);
/**
* @brief Searches for an SSB transmission and decodes the PBCH message
* @param q SSB object
* @param in Input baseband buffer
* @param nof_samples Number of samples available in the buffer
* @param res SSB Search result
* @return SRSRAN_SUCCESS if the parameters are valid, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_ssb_search(srsran_ssb_t* q, const cf_t* in, uint32_t nof_samples, srsran_ssb_search_res_t* res);
/**
* @brief Decides if the SSB object is configured and a given subframe is configured for SSB transmission
* @param q SSB object
@ -155,16 +175,11 @@ SRSRAN_API bool srsran_ssb_send(srsran_ssb_t* q, uint32_t sf_idx);
* @brief Adds SSB to a given signal in time domain
* @param q SSB object
* @param N_id Physical Cell Identifier
* @param ssb_idx SSB candidate index
* @param msg NR PBCH message to transmit
* @return SRSRAN_SUCCESS if the parameters are valid, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_ssb_add(srsran_ssb_t* q,
uint32_t N_id,
uint32_t ssb_idx,
const srsran_pbch_msg_nr_t* msg,
const cf_t* in,
cf_t* out);
SRSRAN_API int
srsran_ssb_add(srsran_ssb_t* q, uint32_t N_id, const srsran_pbch_msg_nr_t* msg, const cf_t* in, cf_t* out);
/**
* @brief Perform cell search and measurement

@ -137,16 +137,11 @@ int dmrs_pbch_extract_lse(const srsran_dmrs_pbch_cfg_t* cfg,
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)
static int dmrs_pbch_meas_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) {
@ -201,18 +196,47 @@ int srsran_dmrs_pbch_estimate(const srsran_dmrs_pbch_cfg_t* cfg,
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;
if (meas != NULL) {
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);
// Generate estimated grid
if (ce != NULL) {
// 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;
}
int srsran_dmrs_pbch_measure(const srsran_dmrs_pbch_cfg_t* cfg,
const cf_t ssb_grid[SRSRAN_SSB_NOF_RE],
srsran_dmrs_pbch_meas_t* meas)
{
// Validate inputs
if (cfg == NULL || ssb_grid == NULL || meas == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
return dmrs_pbch_meas_estimate(cfg, ssb_grid, NULL, meas);
}
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])
{
// Validate inputs
if (cfg == NULL || ssb_grid == NULL || ce == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
return dmrs_pbch_meas_estimate(cfg, ssb_grid, ce, NULL);
}

@ -245,6 +245,7 @@ pbch_nr_pbch_msg_unpack(const srsran_pbch_nr_cfg_t* cfg, const uint8_t a[PBCH_NR
msg->hrf = (a[G[10]] == 1);
// Put SSB related in a_hat[A_hat + 5] to a_hat[A_hat + 7]
msg->ssb_idx = cfg->ssb_idx; // Load 4 LSB
if (cfg->Lmax == 64) {
msg->ssb_idx = msg->ssb_idx & 0b111;
msg->ssb_idx |= (uint8_t)(a[G[11]] << 5U); // 6th bit of SSB index
@ -427,9 +428,9 @@ static void pbch_nr_scramble_rx(const srsran_pbch_nr_cfg_t* cfg,
uint32_t M_bit = PBCH_NR_E;
// Select value v
uint32_t v = (ssb_idx & 0x7U);
uint32_t v = (ssb_idx & 0b111U);
if (cfg->Lmax == 4) {
v = ssb_idx & 0x3U;
v = ssb_idx & 0b11U;
}
// Advance sequence
@ -594,7 +595,6 @@ int srsran_pbch_nr_encode(srsran_pbch_nr_t* q,
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)
@ -623,7 +623,7 @@ int srsran_pbch_nr_decode(srsran_pbch_nr_t* q,
// TS 38.211 7.3.3 Physical broadcast channel
// 7.3.3.1 Scrambling
pbch_nr_scramble_rx(cfg, ssb_idx, llr, llr);
pbch_nr_scramble_rx(cfg, cfg->ssb_idx, llr, llr);
// 7.1.5 Rate matching
int8_t d[PBCH_NR_N];

@ -510,12 +510,7 @@ bool srsran_ssb_send(srsran_ssb_t* q, uint32_t sf_idx)
return (sf_idx % q->cfg.periodicity_ms == 0);
}
int srsran_ssb_add(srsran_ssb_t* q,
uint32_t N_id,
uint32_t ssb_idx,
const srsran_pbch_msg_nr_t* msg,
const cf_t* in,
cf_t* out)
int srsran_ssb_add(srsran_ssb_t* q, uint32_t N_id, const srsran_pbch_msg_nr_t* msg, const cf_t* in, cf_t* out)
{
// Verify input parameters
if (q == NULL || N_id >= SRSRAN_NOF_NID_NR || msg == NULL || in == NULL || out == NULL) {
@ -558,7 +553,6 @@ int srsran_ssb_add(srsran_ssb_t* q,
// Put PBCH payload
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;
if (srsran_pbch_nr_encode(&q->pbch, &pbch_cfg, msg, ssb_grid) < SRSRAN_SUCCESS) {
ERROR("Error encoding PBCH");
@ -566,7 +560,7 @@ int srsran_ssb_add(srsran_ssb_t* q,
}
// Select start symbol from SSB candidate index
int t_offset = ssb_get_t_offset(q, ssb_idx);
int t_offset = ssb_get_t_offset(q, msg->ssb_idx);
if (t_offset < SRSRAN_SUCCESS) {
ERROR("Invalid SSB candidate index");
return SRSRAN_ERROR;
@ -905,10 +899,100 @@ int srsran_ssb_csi_measure(srsran_ssb_t* q,
return SRSRAN_SUCCESS;
}
int srsran_ssb_decode_pbch(srsran_ssb_t* q,
static int ssb_select_pbch(srsran_ssb_t* q,
uint32_t N_id,
const cf_t ssb_grid[SRSRAN_SSB_NOF_RE],
uint32_t* found_n_hf,
uint32_t* found_ssb_idx_4lsb)
{
// Prepare PBCH DMRS configuration
srsran_dmrs_pbch_cfg_t pbch_dmrs_cfg = {};
pbch_dmrs_cfg.N_id = N_id;
pbch_dmrs_cfg.n_hf = 0; // Parameter to guess
pbch_dmrs_cfg.ssb_idx = 0; // Parameter to guess
pbch_dmrs_cfg.L_max = q->Lmax;
pbch_dmrs_cfg.beta = 0.0f;
pbch_dmrs_cfg.scs = q->cfg.scs;
// Initialise best values
srsran_dmrs_pbch_meas_t best_meas = {};
uint32_t best_n_hf = 0;
uint32_t best_ssb_idx = 0;
// Iterate over all the parameters to guess and select the most suitable
for (uint32_t n_hf = 0; n_hf < 2; n_hf++) {
for (uint32_t ssb_idx = 0; ssb_idx < SRSRAN_MIN(8, q->Lmax); ssb_idx++) {
// Set parameters
pbch_dmrs_cfg.n_hf = n_hf;
pbch_dmrs_cfg.ssb_idx = ssb_idx;
// Measure
srsran_dmrs_pbch_meas_t meas = {};
if (srsran_dmrs_pbch_measure(&pbch_dmrs_cfg, ssb_grid, &meas) < SRSRAN_SUCCESS) {
ERROR("Error measure for n_hf=%d ssb_idx=%d", n_hf, ssb_idx);
return SRSRAN_ERROR;
}
// Select the result with highest correlation (most suitable)
if (meas.corr > best_meas.corr) {
best_meas = meas;
best_n_hf = n_hf;
best_ssb_idx = ssb_idx;
}
}
}
// Save findings
*found_n_hf = best_n_hf;
*found_ssb_idx_4lsb = best_ssb_idx;
return SRSRAN_SUCCESS;
}
static int ssb_decode_pbch(srsran_ssb_t* q,
uint32_t N_id,
uint32_t n_hf,
uint32_t ssb_idx,
const cf_t ssb_grid[SRSRAN_SSB_NOF_RE],
srsran_pbch_msg_nr_t* msg)
{
// 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
cf_t ce[SRSRAN_SSB_NOF_RE] = {};
if (srsran_dmrs_pbch_estimate(&pbch_dmrs_cfg, ssb_grid, ce) < SRSRAN_SUCCESS) {
ERROR("Error estimating channel");
return SRSRAN_ERROR;
}
// Prepare PBCH configuration
srsran_pbch_nr_cfg_t pbch_cfg = {};
pbch_cfg.N_id = N_id;
pbch_cfg.n_hf = n_hf;
pbch_cfg.ssb_idx = ssb_idx;
pbch_cfg.Lmax = q->Lmax;
pbch_cfg.beta = 0.0f;
// Decode
if (srsran_pbch_nr_decode(&q->pbch, &pbch_cfg, ssb_grid, ce, msg) < SRSRAN_SUCCESS) {
ERROR("Error decoding PBCH");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
int srsran_ssb_decode_pbch(srsran_ssb_t* q,
uint32_t N_id,
uint32_t n_hf,
uint32_t ssb_idx,
const cf_t* in,
srsran_pbch_msg_nr_t* msg)
{
@ -935,40 +1019,81 @@ int srsran_ssb_decode_pbch(srsran_ssb_t* q,
return SRSRAN_ERROR;
}
// 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;
// Decode PBCH
if (ssb_decode_pbch(q, N_id, n_hf, ssb_idx, ssb_grid, msg) < SRSRAN_SUCCESS) {
ERROR("Error decoding");
return SRSRAN_ERROR;
}
// 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_SUCCESS;
}
int srsran_ssb_search(srsran_ssb_t* q, const cf_t* in, uint32_t nof_samples, srsran_ssb_search_res_t* res)
{
// Verify inputs
if (q == NULL || in == NULL || res == NULL || !isnormal(q->scs_hz)) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (!q->args.enable_search || !q->args.enable_decode) {
ERROR("SSB is not configured to search (%c) and decode (%c)",
q->args.enable_search ? 'y' : 'n',
q->args.enable_decode ? 'y' : 'n');
return SRSRAN_ERROR;
}
// Compare measurement with threshold
if (meas.corr < q->args.pbch_dmrs_thr) {
msg->crc = false;
return SRSRAN_SUCCESS;
// Search for PSS in time domain
uint32_t N_id_2 = 0;
uint32_t t_offset = 0;
if (ssb_pss_search(q, in, nof_samples, &N_id_2, &t_offset) < SRSRAN_SUCCESS) {
ERROR("Error searching for N_id_2");
return SRSRAN_ERROR;
}
// 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;
// Remove CP offset prior demodulation
if (t_offset >= q->cp_sz) {
t_offset -= q->cp_sz;
} else {
t_offset = 0;
}
// Decode
if (srsran_pbch_nr_decode(&q->pbch, &pbch_cfg, ssb_idx, ssb_grid, ce, msg) < SRSRAN_SUCCESS) {
// Demodulate
cf_t ssb_grid[SRSRAN_SSB_NOF_RE] = {};
if (ssb_demodulate(q, in, t_offset, ssb_grid) < SRSRAN_SUCCESS) {
ERROR("Error demodulating");
return SRSRAN_ERROR;
}
// Find best N_id_1
uint32_t N_id_1 = 0;
float sss_corr = 0.0f;
if (srsran_sss_nr_find(ssb_grid, N_id_2, &sss_corr, &N_id_1) < SRSRAN_SUCCESS) {
ERROR("Error searching for N_id_2");
return SRSRAN_ERROR;
}
// Select N_id
uint32_t N_id = SRSRAN_NID_NR(N_id_1, N_id_2);
// Select the most suitable SSB candidate
uint32_t n_hf = 0;
uint32_t ssb_idx = 0;
if (ssb_select_pbch(q, N_id, ssb_grid, &n_hf, &ssb_idx) < SRSRAN_SUCCESS) {
ERROR("Error selecting PBCH");
return SRSRAN_ERROR;
}
// Compute PBCH channel estimates
srsran_pbch_msg_nr_t pbch_msg = {};
if (ssb_decode_pbch(q, N_id, n_hf, ssb_idx, ssb_grid, &pbch_msg) < SRSRAN_SUCCESS) {
ERROR("Error decoding PBCH");
return SRSRAN_ERROR;
}
// Save result
res->N_id = N_id;
res->t_offset = t_offset;
res->pbch_msg = pbch_msg;
return SRSRAN_SUCCESS;
}

@ -85,6 +85,7 @@ static void gen_pbch_msg(srsran_pbch_msg_nr_t* pbch_msg, uint32_t ssb_idx)
srsran_random_bit_vector(random_gen, pbch_msg->payload, SRSRAN_PBCH_NR_PAYLOAD_SZ);
pbch_msg->ssb_idx = ssb_idx;
pbch_msg->crc = true;
}
static int test_case_1(srsran_ssb_t* ssb)
@ -92,6 +93,7 @@ static int test_case_1(srsran_ssb_t* ssb)
// For benchmarking purposes
uint64_t t_encode_usec = 0;
uint64_t t_decode_usec = 0;
uint64_t t_search_usec = 0;
// SSB configuration
srsran_ssb_cfg_t ssb_cfg = {};
@ -123,7 +125,7 @@ static int test_case_1(srsran_ssb_t* ssb)
// Add the SSB base-band
gettimeofday(&t[1], NULL);
TESTASSERT(srsran_ssb_add(ssb, pci, ssb_idx, &pbch_msg_tx, buffer, buffer) == SRSRAN_SUCCESS);
TESTASSERT(srsran_ssb_add(ssb, pci, &pbch_msg_tx, buffer, buffer) == SRSRAN_SUCCESS);
gettimeofday(&t[2], NULL);
get_time_interval(t);
t_encode_usec += t[0].tv_usec + t[0].tv_sec * 1000000UL;
@ -134,7 +136,8 @@ 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, 0, buffer, &pbch_msg_rx) == SRSRAN_SUCCESS);
TESTASSERT(srsran_ssb_decode_pbch(ssb, pci, pbch_msg_tx.hrf, pbch_msg_tx.ssb_idx, 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;
@ -145,12 +148,30 @@ static int test_case_1(srsran_ssb_t* ssb)
// Assert PBCH message CRC
TESTASSERT(pbch_msg_rx.crc);
TESTASSERT(memcmp(&pbch_msg_rx, &pbch_msg_tx, sizeof(srsran_pbch_msg_nr_t)) == 0);
// Search
srsran_ssb_search_res_t res = {};
gettimeofday(&t[1], NULL);
TESTASSERT(srsran_ssb_search(ssb, buffer, hf_len, &res) == SRSRAN_SUCCESS);
gettimeofday(&t[2], NULL);
get_time_interval(t);
t_search_usec += t[0].tv_usec + t[0].tv_sec * 1000000UL;
// Print decoded PBCH message
srsran_pbch_msg_info(&res.pbch_msg, str, sizeof(str));
INFO("test_case_1 - found pci=%d %s crc=%s", res.N_id, str, res.pbch_msg.crc ? "OK" : "KO");
// Assert PBCH message CRC
TESTASSERT(res.pbch_msg.crc);
TESTASSERT(memcmp(&res.pbch_msg, &pbch_msg_tx, sizeof(srsran_pbch_msg_nr_t)) == 0);
}
}
INFO("test_case_1 - %.1f usec/encode; %.1f usec/decode;",
INFO("test_case_1 - %.1f usec/encode; %.1f usec/decode; %.1f usec/decode;",
(double)t_encode_usec / (double)(count),
(double)t_decode_usec / (double)(count));
(double)t_decode_usec / (double)(count),
(double)t_search_usec / (double)(count));
return SRSRAN_SUCCESS;
}
@ -169,6 +190,7 @@ int main(int argc, char** argv)
srsran_ssb_args_t ssb_args = {};
ssb_args.enable_encode = true;
ssb_args.enable_decode = true;
ssb_args.enable_search = true;
if (buffer == NULL) {
ERROR("Malloc");

@ -116,7 +116,7 @@ static int test_case_1(srsran_ssb_t* ssb)
// Add the SSB base-band
gettimeofday(&t[1], NULL);
TESTASSERT(srsran_ssb_add(ssb, pci, 0, &pbch_msg, buffer, buffer) == SRSRAN_SUCCESS);
TESTASSERT(srsran_ssb_add(ssb, pci, &pbch_msg, buffer, buffer) == SRSRAN_SUCCESS);
gettimeofday(&t[2], NULL);
get_time_interval(t);
t_add_usec += t[0].tv_usec + t[0].tv_sec * 1000000UL;

@ -105,7 +105,7 @@ public:
srsran_pbch_msg_nr_t msg = {};
// Add SSB
if (srsran_ssb_add(&ssb, pci, 0, &msg, buffer.data(), buffer.data()) < SRSRAN_SUCCESS) {
if (srsran_ssb_add(&ssb, pci, &msg, buffer.data(), buffer.data()) < SRSRAN_SUCCESS) {
logger.error("Error adding SSB");
return SRSRAN_ERROR;
}

Loading…
Cancel
Save