mirror of https://github.com/PentHertz/srsLTE.git
SRSUE: neighbour cell measurement test defined
This commit is contained in:
parent
385102fa2d
commit
8f6dd184be
|
@ -26,38 +26,154 @@
|
||||||
#include <srslte/phy/utils/vector.h>
|
#include <srslte/phy/utils/vector.h>
|
||||||
#include <srslte/srslte.h>
|
#include <srslte/srslte.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constants
|
||||||
|
* --------------
|
||||||
|
* These constants have been optimized for passing scell_search_test for a number of scenarios.
|
||||||
|
* - 6 PRB. 6 cells distributed uniformly 10ms delay
|
||||||
|
* srsue/test/phy/scell_search_test --duration=5 --cell.nof_prb=6 --active_cell_list=all
|
||||||
|
* --simulation_cell_list=1,2,3,4,5,6 --channel_period_s=30 --channel.hst.fd=750 --channel.delay_max=1000
|
||||||
|
*
|
||||||
|
* - 6 PRB. 6 cells distributed uniformly 10ms delay
|
||||||
|
* srsue/test/phy/scell_search_test --duration=30 --cell.nof_prb=6 --active_cell_list=2,3,4,5,6
|
||||||
|
* --simulation_cell_list=1,2,3,4,5,6 --channel_period_s=30 --channel.hst.fd=750 --channel.delay_max=10000
|
||||||
|
*
|
||||||
|
* - 6 PRB. 6 cell PSS, SSS overlapped:
|
||||||
|
* srsue/test/phy/scell_search_test --duration=30 --cell.nof_prb=6 --active_cell_list=all
|
||||||
|
* --simulation_cell_list=1,2,3,4,5,6 --channel_period_s=30 --channel.hst.fd=750 --channel.delay_max=0
|
||||||
|
*
|
||||||
|
* - 100 PRB, 6 cell, distributed around 1ms
|
||||||
|
* srsue/test/phy/scell_search_test --duration=30 --cell.nof_prb=100 --active_cell_list=2,3,4,5,6
|
||||||
|
* --simulation_cell_list=1,2,3,4,5,6 --channel_period_s=30 --channel.hst.fd=750 --channel.delay_max=1000
|
||||||
|
*/
|
||||||
|
#define REFSIGNAL_DL_SYNC_CORRELATION_THR (4.0f) /* Correlation threashold normalised in Peak / RMS */
|
||||||
|
#define REFSIGNAL_DL_CFO_MIN_MAX_MILD (1000.0f) /* Maximum difference between sub-frame CFO estimation in Hz */
|
||||||
|
#define REFSIGNAL_DL_CFO_MIN_MAX_SEVERE (2000.0f)
|
||||||
|
#define REFSIGNAL_DL_RSRP_MIN_MAX_MILD (6.0f) /* Maximum difference between sub-frame RSRP estimation in dB */
|
||||||
|
#define REFSIGNAL_DL_RSRP_MIN_MAX_SEVERE (10.0f)
|
||||||
|
#define REFSIGNAL_DL_RSRP_FALSE_RATIO_MILD (4.0f) /* Minimum RSRP ratio between real and false in dB */
|
||||||
|
#define REFSIGNAL_DL_RSRP_FALSE_RATIO_SEVERE (3.0f)
|
||||||
|
#define REFSIGNAL_DL_SSS_FALSE_RATIO_MILD (15.0f) /* Minimum SSS strength between real and false (linear) */
|
||||||
|
#define REFSIGNAL_DL_SSS_FALSE_RATIO_SEVERE (1.5f)
|
||||||
|
#define REFSIGNAL_DL_MAX_FAULT_CHECK (1) /* Number of mild faults without declaring false */
|
||||||
|
#define REFSIGNAL_DL_CFO_LOW_WEIGHT (0.5f) /* Weight for low CFO estimation (2 kHz) */
|
||||||
|
#define REFSIGNAL_DL_CFO_MEDIUM_WEIGHT (0.3f) /* Weight for medium CFO estimation (3.5 kHz) */
|
||||||
|
#define REFSIGNAL_DL_CFO_HIGH_WEIGHT (0.2f) /* Weight for high CFO estimation (4.66 kHz) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Helpers
|
||||||
|
*/
|
||||||
|
static inline void refsignal_set_results_not_found(srslte_refsignal_dl_sync_t* q)
|
||||||
|
{
|
||||||
|
q->found = false;
|
||||||
|
q->rsrp_dBfs = NAN;
|
||||||
|
q->rssi_dBfs = NAN;
|
||||||
|
q->rsrq_dB = NAN;
|
||||||
|
q->cfo_Hz = NAN;
|
||||||
|
q->peak_index = UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void refsignal_sf_prepare_correlation(srslte_refsignal_dl_sync_t* q)
|
||||||
|
{
|
||||||
|
uint32_t sf_len = q->ifft.sf_sz;
|
||||||
|
cf_t* ptr_filt = q->conv_fft_cc.filter_fft;
|
||||||
|
memcpy(ptr_filt, q->sequences[0], sizeof(cf_t) * sf_len);
|
||||||
|
bzero(&ptr_filt[sf_len], sizeof(cf_t) * sf_len);
|
||||||
|
srslte_dft_run_c(&q->conv_fft_cc.filter_plan, ptr_filt, ptr_filt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
refsignal_sf_correlate(srslte_refsignal_dl_sync_t* q, cf_t* ptr_in, float* peak_value, uint32_t* peak_idx, float* rms)
|
||||||
|
{
|
||||||
|
// Correlate
|
||||||
|
srslte_corr_fft_cc_run_opt(&q->conv_fft_cc, ptr_in, q->conv_fft_cc.filter_fft, q->correlation);
|
||||||
|
|
||||||
|
// Find maximum, calculate RMS and peak
|
||||||
|
uint32_t imax = srslte_vec_max_abs_ci(q->correlation, q->ifft.sf_sz);
|
||||||
|
|
||||||
|
if (peak_idx) {
|
||||||
|
*peak_idx = imax;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peak_value) {
|
||||||
|
*peak_value = cabsf(q->correlation[imax]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rms) {
|
||||||
|
*rms = sqrtf(srslte_vec_avg_power_cf(q->correlation, q->ifft.sf_sz));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void refsignal_dl_pss_sss_strength(srslte_refsignal_dl_sync_t* q,
|
||||||
|
cf_t* buffer,
|
||||||
|
uint32_t sf_idx,
|
||||||
|
float* pss_strength,
|
||||||
|
float* sss_strength,
|
||||||
|
float* sss_strength_false)
|
||||||
|
{
|
||||||
|
uint32_t symbol_sz = q->ifft.symbol_sz;
|
||||||
|
uint32_t cp_len0 = SRSLTE_CP_LEN_NORM(0, symbol_sz);
|
||||||
|
uint32_t cp_len1 = SRSLTE_CP_LEN_NORM(1, symbol_sz);
|
||||||
|
|
||||||
|
uint32_t pss_n = cp_len0 + cp_len1 * 6 + symbol_sz * 6;
|
||||||
|
uint32_t sss_n = cp_len0 + cp_len1 * 5 + symbol_sz * 5;
|
||||||
|
|
||||||
|
sf_idx %= SRSLTE_NOF_SF_X_FRAME;
|
||||||
|
|
||||||
|
srslte_dl_sf_cfg_t dl_sf_cfg = {};
|
||||||
|
dl_sf_cfg.tti = sf_idx;
|
||||||
|
|
||||||
|
float k = (float)(srslte_refsignal_cs_nof_re(&q->refsignal, &dl_sf_cfg, 0)) / (float)SRSLTE_PSS_LEN;
|
||||||
|
|
||||||
|
if (pss_strength) {
|
||||||
|
cf_t corr = srslte_vec_dot_prod_conj_ccc(&buffer[pss_n], &q->sequences[sf_idx][pss_n], symbol_sz);
|
||||||
|
*pss_strength = k * __real__(corr * conjf(corr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sss_strength) {
|
||||||
|
cf_t corr = srslte_vec_dot_prod_conj_ccc(&buffer[sss_n], &q->sequences[sf_idx][sss_n], symbol_sz);
|
||||||
|
*sss_strength = k * __real__(corr * conjf(corr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sss_strength_false) {
|
||||||
|
uint32_t sf_idx2 = (sf_idx + SRSLTE_NOF_SF_X_FRAME / 2) % SRSLTE_NOF_SF_X_FRAME;
|
||||||
|
cf_t corr = srslte_vec_dot_prod_conj_ccc(&buffer[sss_n], &q->sequences[sf_idx2][sss_n], symbol_sz);
|
||||||
|
*sss_strength_false = k * __real__(corr * conjf(corr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int srslte_refsignal_dl_sync_init(srslte_refsignal_dl_sync_t* q)
|
int srslte_refsignal_dl_sync_init(srslte_refsignal_dl_sync_t* q)
|
||||||
{
|
{
|
||||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
|
|
||||||
if (q) {
|
if (q) {
|
||||||
// Initialise internals
|
// Initialise internals
|
||||||
bzero(q, sizeof(srslte_refsignal_dl_sync_t));
|
memset(q, 0, sizeof(srslte_refsignal_dl_sync_t));
|
||||||
|
|
||||||
// Initialise Reference signals
|
// Initialise Reference signals
|
||||||
ret = srslte_refsignal_cs_init(&q->refsignal, SRSLTE_MAX_PRB);
|
ret = srslte_refsignal_cs_init(&q->refsignal, SRSLTE_MAX_PRB);
|
||||||
|
|
||||||
// Allocate time buffers
|
// Allocate time buffers
|
||||||
for (int i = 0; i < SRSLTE_NOF_SF_X_FRAME; i++) {
|
for (int i = 0; i < SRSLTE_NOF_SF_X_FRAME; i++) {
|
||||||
q->sequences[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX);
|
q->sequences[i] = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX);
|
||||||
if (!q->sequences[i]) {
|
if (!q->sequences[i]) {
|
||||||
perror("Allocating sequence\n");
|
perror("Allocating sequence\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate Temporal OFDM buffer
|
// Allocate Temporal OFDM buffer
|
||||||
q->ifft_buffer_in = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX);
|
q->ifft_buffer_in = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX);
|
||||||
if (!q->ifft_buffer_in) {
|
if (!q->ifft_buffer_in) {
|
||||||
perror("Allocating ifft_buffer_in\n");
|
perror("Allocating ifft_buffer_in\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
q->ifft_buffer_out = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX);
|
q->ifft_buffer_out = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX);
|
||||||
if (!q->ifft_buffer_out) {
|
if (!q->ifft_buffer_out) {
|
||||||
perror("Allocating ifft_buffer_out\n");
|
perror("Allocating ifft_buffer_out\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate correlation
|
// Allocate correlation
|
||||||
q->correlation = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX * 2);
|
q->correlation = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX * 2);
|
||||||
if (!q->correlation) {
|
if (!q->correlation) {
|
||||||
perror("Allocating correlation\n");
|
perror("Allocating correlation\n");
|
||||||
}
|
}
|
||||||
|
@ -76,6 +192,9 @@ int srslte_refsignal_dl_sync_init(srslte_refsignal_dl_sync_t* q)
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ret = srslte_conv_fft_cc_init(&q->conv_fft_cc, q->ifft.sf_sz, q->ifft.sf_sz);
|
ret = srslte_conv_fft_cc_init(&q->conv_fft_cc, q->ifft.sf_sz, q->ifft.sf_sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set default results to not found
|
||||||
|
refsignal_set_results_not_found(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -125,9 +244,6 @@ int srslte_refsignal_dl_sync_set_cell(srslte_refsignal_dl_sync_t* q, srslte_cell
|
||||||
srslte_sss_put_slot(i ? sss_signal5 : sss_signal0, q->ifft_buffer_in, cell.nof_prb, cell.cp);
|
srslte_sss_put_slot(i ? sss_signal5 : sss_signal0, q->ifft_buffer_in, cell.nof_prb, cell.cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase correlation for 2 port eNb
|
|
||||||
cell.nof_ports = 2;
|
|
||||||
|
|
||||||
// Put Reference signals
|
// Put Reference signals
|
||||||
for (int p = 0; p < cell.nof_ports; p++) {
|
for (int p = 0; p < cell.nof_ports; p++) {
|
||||||
ret = srslte_refsignal_cs_put_sf(&q->refsignal, &dl_sf_cfg, p, q->ifft_buffer_in);
|
ret = srslte_refsignal_cs_put_sf(&q->refsignal, &dl_sf_cfg, p, q->ifft_buffer_in);
|
||||||
|
@ -185,33 +301,25 @@ void srslte_refsignal_dl_sync_free(srslte_refsignal_dl_sync_t* q)
|
||||||
int srslte_refsignal_dl_sync_find_peak(srslte_refsignal_dl_sync_t* q, cf_t* buffer, uint32_t nsamples)
|
int srslte_refsignal_dl_sync_find_peak(srslte_refsignal_dl_sync_t* q, cf_t* buffer, uint32_t nsamples)
|
||||||
{
|
{
|
||||||
int ret = SRSLTE_ERROR;
|
int ret = SRSLTE_ERROR;
|
||||||
float thr = 5.5f;
|
|
||||||
float peak_value = 0.0f;
|
float peak_value = 0.0f;
|
||||||
int peak_idx = 0;
|
int peak_idx = 0;
|
||||||
float rms_avg = 0;
|
float rms_avg = 0;
|
||||||
uint32_t sf_len = q->ifft.sf_sz;
|
uint32_t sf_len = q->ifft.sf_sz;
|
||||||
|
|
||||||
// Load correlation sequence and convert to frequency domain
|
// Load correlation sequence and convert to frequency domain
|
||||||
cf_t* ptr_filt = q->conv_fft_cc.filter_fft;
|
refsignal_sf_prepare_correlation(q);
|
||||||
memcpy(ptr_filt, q->sequences[0], sizeof(cf_t) * sf_len);
|
|
||||||
bzero(&ptr_filt[sf_len], sizeof(cf_t) * sf_len);
|
|
||||||
srslte_dft_run_c(&q->conv_fft_cc.filter_plan, ptr_filt, ptr_filt);
|
|
||||||
|
|
||||||
// Limit correlate for a frame or less
|
// Limit correlate for a frame or less
|
||||||
nsamples = SRSLTE_MIN(nsamples - sf_len, SRSLTE_NOF_SF_X_FRAME * sf_len);
|
nsamples = SRSLTE_MIN(nsamples - sf_len, SRSLTE_NOF_SF_X_FRAME * sf_len);
|
||||||
|
|
||||||
// Correlation
|
// Correlation
|
||||||
for (int n = 0; n < nsamples; n += sf_len) {
|
for (int n = 0; n < nsamples; n += sf_len) {
|
||||||
// Set input data, two subframes
|
// Correlate, find maximum, calculate RMS and peak
|
||||||
cf_t* ptr_in = &buffer[n];
|
uint32_t imax = 0;
|
||||||
|
float peak = 0.0f;
|
||||||
|
float rms = 0.0f;
|
||||||
|
refsignal_sf_correlate(q, &buffer[n], &peak, &imax, &rms);
|
||||||
|
|
||||||
// Correlate
|
|
||||||
srslte_corr_fft_cc_run_opt(&q->conv_fft_cc, ptr_in, ptr_filt, q->correlation);
|
|
||||||
|
|
||||||
// Find maximum, calculate RMS and peak
|
|
||||||
uint32_t imax = srslte_vec_max_abs_ci(q->correlation, sf_len);
|
|
||||||
float peak = cabsf(q->correlation[imax]);
|
|
||||||
float rms = sqrtf(srslte_vec_avg_power_cf(q->correlation, sf_len));
|
|
||||||
rms_avg += rms;
|
rms_avg += rms;
|
||||||
|
|
||||||
// Found bigger peak
|
// Found bigger peak
|
||||||
|
@ -223,10 +331,27 @@ int srslte_refsignal_dl_sync_find_peak(srslte_refsignal_dl_sync_t* q, cf_t* buff
|
||||||
|
|
||||||
// Condition of peak detection
|
// Condition of peak detection
|
||||||
rms_avg /= floorf((float)nsamples / sf_len);
|
rms_avg /= floorf((float)nsamples / sf_len);
|
||||||
if (peak_value > rms_avg * thr) {
|
if (peak_value > rms_avg * REFSIGNAL_DL_SYNC_CORRELATION_THR) {
|
||||||
ret = peak_idx;
|
ret = peak_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Double check sub-frame selection failure due to high PSS
|
||||||
|
if (ret > 0) {
|
||||||
|
float sss_strength = 0.0f;
|
||||||
|
float sss_strength_false = 0.0f;
|
||||||
|
refsignal_dl_pss_sss_strength(q, &buffer[peak_idx], 0, NULL, &sss_strength, &sss_strength_false);
|
||||||
|
|
||||||
|
float rsrp_lin = 0.0f;
|
||||||
|
float rsrp_lin_false = 0.0f;
|
||||||
|
srslte_refsignal_dl_sync_measure_sf(q, &buffer[peak_idx], 0, &rsrp_lin, NULL, NULL);
|
||||||
|
srslte_refsignal_dl_sync_measure_sf(q, &buffer[peak_idx], 5, &rsrp_lin_false, NULL, NULL);
|
||||||
|
|
||||||
|
// Change base sub-frame
|
||||||
|
if (sss_strength_false > sss_strength && rsrp_lin_false > rsrp_lin) {
|
||||||
|
ret += (q->ifft.sf_sz * SRSLTE_NOF_SF_X_FRAME) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
INFO("pci=%03d; sf_len=%d; imax=%d; peak=%.3f; rms=%.3f; peak/rms=%.3f\n",
|
INFO("pci=%03d; sf_len=%d; imax=%d; peak=%.3f; rms=%.3f; peak/rms=%.3f\n",
|
||||||
q->refsignal.cell.id,
|
q->refsignal.cell.id,
|
||||||
sf_len,
|
sf_len,
|
||||||
|
@ -242,11 +367,19 @@ int srslte_refsignal_dl_sync_find_peak(srslte_refsignal_dl_sync_t* q, cf_t* buff
|
||||||
void srslte_refsignal_dl_sync_run(srslte_refsignal_dl_sync_t* q, cf_t* buffer, uint32_t nsamples)
|
void srslte_refsignal_dl_sync_run(srslte_refsignal_dl_sync_t* q, cf_t* buffer, uint32_t nsamples)
|
||||||
{
|
{
|
||||||
if (q) {
|
if (q) {
|
||||||
uint32_t sf_len = q->ifft.sf_sz;
|
uint32_t sf_len = q->ifft.sf_sz;
|
||||||
uint32_t sf_count = 0;
|
uint32_t sf_count = 0;
|
||||||
float rsrp_lin = 0.0f;
|
float rsrp_lin = 0.0f;
|
||||||
float rssi_lin = 0.0f;
|
float rsrp_lin_min = +INFINITY;
|
||||||
float cfo_acc = 0.0f;
|
float rsrp_lin_max = -INFINITY;
|
||||||
|
float rssi_lin = 0.0f;
|
||||||
|
float cfo_acc = 0.0f;
|
||||||
|
float cfo_min = +INFINITY;
|
||||||
|
float cfo_max = -INFINITY;
|
||||||
|
float sss_strength_avg = 0.0f;
|
||||||
|
float sss_strength_false_avg = 0.0f;
|
||||||
|
float rsrp_false_avg = 0.0f;
|
||||||
|
bool false_alarm = false;
|
||||||
|
|
||||||
// Stage 1: find peak
|
// Stage 1: find peak
|
||||||
int peak_idx = srslte_refsignal_dl_sync_find_peak(q, buffer, nsamples);
|
int peak_idx = srslte_refsignal_dl_sync_find_peak(q, buffer, nsamples);
|
||||||
|
@ -264,9 +397,33 @@ void srslte_refsignal_dl_sync_run(srslte_refsignal_dl_sync_t* q, cf_t* buffer, u
|
||||||
// Measure subframe rsrp, rssi and accumulate
|
// Measure subframe rsrp, rssi and accumulate
|
||||||
float rsrp = 0.0f, rssi = 0.0f, cfo = 0.0f;
|
float rsrp = 0.0f, rssi = 0.0f, cfo = 0.0f;
|
||||||
srslte_refsignal_dl_sync_measure_sf(q, buf, sf_idx, &rsrp, &rssi, &cfo);
|
srslte_refsignal_dl_sync_measure_sf(q, buf, sf_idx, &rsrp, &rssi, &cfo);
|
||||||
|
|
||||||
|
// Update measurements
|
||||||
rsrp_lin += rsrp;
|
rsrp_lin += rsrp;
|
||||||
|
rsrp_lin_min = SRSLTE_MIN(rsrp_lin_min, rsrp);
|
||||||
|
rsrp_lin_max = SRSLTE_MAX(rsrp_lin_max, rsrp);
|
||||||
|
|
||||||
rssi_lin += rssi;
|
rssi_lin += rssi;
|
||||||
|
|
||||||
cfo_acc += cfo;
|
cfo_acc += cfo;
|
||||||
|
cfo_min = SRSLTE_MIN(cfo_min, cfo);
|
||||||
|
cfo_max = SRSLTE_MAX(cfo_max, cfo);
|
||||||
|
|
||||||
|
// Compute PSS/SSS strength
|
||||||
|
if (sf_idx % (SRSLTE_NOF_SF_X_FRAME / 2) == 0) {
|
||||||
|
float sss_strength = 0.0f;
|
||||||
|
float sss_strength_false = 0.0f;
|
||||||
|
refsignal_dl_pss_sss_strength(q, buf, sf_idx, NULL, &sss_strength, &sss_strength_false);
|
||||||
|
|
||||||
|
float rsrp_false = 0.0f;
|
||||||
|
srslte_refsignal_dl_sync_measure_sf(q, buf, sf_idx + 1, &rsrp_false, NULL, NULL);
|
||||||
|
|
||||||
|
sss_strength_avg += sss_strength;
|
||||||
|
sss_strength_false_avg += sss_strength_false;
|
||||||
|
rsrp_false_avg += rsrp_false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment counter
|
||||||
sf_count++;
|
sf_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,27 +432,82 @@ void srslte_refsignal_dl_sync_run(srslte_refsignal_dl_sync_t* q, cf_t* buffer, u
|
||||||
rsrp_lin /= sf_count;
|
rsrp_lin /= sf_count;
|
||||||
rssi_lin /= sf_count;
|
rssi_lin /= sf_count;
|
||||||
cfo_acc /= sf_count;
|
cfo_acc /= sf_count;
|
||||||
|
sss_strength_avg /= (2.0f * sf_count / SRSLTE_NOF_SF_X_FRAME);
|
||||||
|
sss_strength_false_avg /= (2.0f * sf_count / SRSLTE_NOF_SF_X_FRAME);
|
||||||
|
rsrp_false_avg /= (2.0f * sf_count / SRSLTE_NOF_SF_X_FRAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate in dBm
|
// RSRP conversion to dB
|
||||||
q->rsrp_dBfs = srslte_convert_power_to_dBm(rsrp_lin);
|
float rsrp_dB_min = srslte_convert_power_to_dBm(rsrp_lin_min);
|
||||||
|
float rsrp_dB_max = srslte_convert_power_to_dBm(rsrp_lin_max);
|
||||||
|
float rsrp_dB = srslte_convert_power_to_dBm(rsrp_lin);
|
||||||
|
float rsrp_false_dB = srslte_convert_power_to_dBm(rsrp_false_avg);
|
||||||
|
|
||||||
// Calculate RSSI in dBm
|
// Stage 3: Final false alarm decision
|
||||||
q->rssi_dBfs = srslte_convert_power_to_dBm(rssi_lin);
|
uint32_t false_count = 0;
|
||||||
|
if (sss_strength_avg < sss_strength_false_avg * REFSIGNAL_DL_SSS_FALSE_RATIO_SEVERE) {
|
||||||
|
false_alarm = true;
|
||||||
|
} else if (sss_strength_avg < sss_strength_false_avg * REFSIGNAL_DL_SSS_FALSE_RATIO_MILD) {
|
||||||
|
false_count++;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate RSRQ
|
if (cfo_max - cfo_min > REFSIGNAL_DL_CFO_MIN_MAX_SEVERE) {
|
||||||
q->rsrq_dB = srslte_convert_power_to_dB(q->refsignal.cell.nof_prb) + q->rsrp_dBfs - q->rssi_dBfs;
|
false_alarm = true;
|
||||||
|
} else if (cfo_max - cfo_min > REFSIGNAL_DL_CFO_MIN_MAX_MILD) {
|
||||||
|
false_count++;
|
||||||
|
}
|
||||||
|
|
||||||
q->found = true;
|
if (rsrp_dB_max - rsrp_dB_min > REFSIGNAL_DL_RSRP_MIN_MAX_SEVERE) {
|
||||||
q->cfo_Hz = cfo_acc;
|
false_alarm = true;
|
||||||
q->peak_index = peak_idx;
|
} else if (rsrp_dB_max - rsrp_dB_min > REFSIGNAL_DL_RSRP_MIN_MAX_MILD) {
|
||||||
|
false_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsrp_dB - rsrp_false_dB < REFSIGNAL_DL_RSRP_FALSE_RATIO_SEVERE) {
|
||||||
|
false_alarm = true;
|
||||||
|
} else if (rsrp_dB - rsrp_false_dB < REFSIGNAL_DL_RSRP_FALSE_RATIO_MILD) {
|
||||||
|
false_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow only one check fail
|
||||||
|
if (false_count > REFSIGNAL_DL_MAX_FAULT_CHECK) {
|
||||||
|
false_alarm = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
INFO("-- pci=%03d; rsrp_dB=(%+.1f|%+.1f|%+.1f); rsrp_max-min=%.1f; rsrp_false_ratio=%.1f; "
|
||||||
|
"cfo=(%.1f|%.1f|%.1f); cfo_max-min=%.1f; sss_ratio=%f; false_count=%d;\n",
|
||||||
|
q->refsignal.cell.id,
|
||||||
|
rsrp_dB_min,
|
||||||
|
rsrp_dB,
|
||||||
|
rsrp_dB_max,
|
||||||
|
rsrp_dB_max - rsrp_dB_min,
|
||||||
|
rsrp_dB - rsrp_false_dB,
|
||||||
|
cfo_min,
|
||||||
|
cfo_acc,
|
||||||
|
cfo_max,
|
||||||
|
cfo_max - cfo_min,
|
||||||
|
sss_strength_avg / sss_strength_false_avg,
|
||||||
|
false_count);
|
||||||
|
|
||||||
|
if (!false_alarm) {
|
||||||
|
|
||||||
|
// Calculate in dBm
|
||||||
|
q->rsrp_dBfs = rsrp_dB;
|
||||||
|
|
||||||
|
// Calculate RSSI in dBm
|
||||||
|
q->rssi_dBfs = srslte_convert_power_to_dBm(rssi_lin);
|
||||||
|
|
||||||
|
// Calculate RSRQ
|
||||||
|
q->rsrq_dB = srslte_convert_power_to_dB(q->refsignal.cell.nof_prb) + q->rsrp_dBfs - q->rssi_dBfs;
|
||||||
|
|
||||||
|
q->found = true;
|
||||||
|
q->cfo_Hz = cfo_acc;
|
||||||
|
q->peak_index = peak_idx;
|
||||||
|
} else {
|
||||||
|
refsignal_set_results_not_found(q);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
q->found = false;
|
refsignal_set_results_not_found(q);
|
||||||
q->rsrp_dBfs = NAN;
|
|
||||||
q->rssi_dBfs = NAN;
|
|
||||||
q->rsrq_dB = NAN;
|
|
||||||
q->cfo_Hz = NAN;
|
|
||||||
q->peak_index = UINT32_MAX;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,7 +549,9 @@ void srslte_refsignal_dl_sync_measure_sf(srslte_refsignal_dl_sync_t* q,
|
||||||
rsrp_lin += __real__(corr[l] * conjf(corr[l]));
|
rsrp_lin += __real__(corr[l] * conjf(corr[l]));
|
||||||
|
|
||||||
// Calculate RSSI
|
// Calculate RSSI
|
||||||
rssi_lin += srslte_vec_dot_prod_conj_ccc(&buffer[offset], &buffer[offset], symbol_sz);
|
if (rssi) {
|
||||||
|
rssi_lin += srslte_vec_dot_prod_conj_ccc(&buffer[offset], &buffer[offset], symbol_sz);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return measurements
|
// Return measurements
|
||||||
|
@ -350,10 +564,30 @@ void srslte_refsignal_dl_sync_measure_sf(srslte_refsignal_dl_sync_t* q,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfo) {
|
if (cfo) {
|
||||||
|
|
||||||
|
// Distances between symbols
|
||||||
|
float distance_1 = (cp_len1 + symbol_sz) * 4.0f; // Number of samples between first and second symbol
|
||||||
|
float distance_2 =
|
||||||
|
(cp_len1 + symbol_sz) * 3.0f + (cp_len0 - cp_len1); // Number of samples between second and third symbol
|
||||||
|
|
||||||
|
// Averaging weights, all of them must be 1.0f
|
||||||
|
float low_w = REFSIGNAL_DL_CFO_LOW_WEIGHT / 2.0f; // Two of them
|
||||||
|
float medium_w = REFSIGNAL_DL_CFO_MEDIUM_WEIGHT / 2.0f; // Two of them
|
||||||
|
float high_w = REFSIGNAL_DL_CFO_HIGH_WEIGHT; // One of them
|
||||||
|
|
||||||
|
// Initialise average
|
||||||
*cfo = 0;
|
*cfo = 0;
|
||||||
*cfo += cargf(corr[2] * conjf(corr[0])) / (2.0f * M_PI * 7.5f) * 15000.0f;
|
|
||||||
*cfo += cargf(corr[3] * conjf(corr[1])) / (2.0f * M_PI * 7.5f) * 15000.0f;
|
// Low doppler (2 kHz)
|
||||||
*cfo /= 2;
|
*cfo += cargf(corr[2] * conjf(corr[0])) / (2.0f * M_PI * 7.5f) * 15000.0f * low_w;
|
||||||
|
*cfo += cargf(corr[3] * conjf(corr[1])) / (2.0f * M_PI * 7.5f) * 15000.0f * low_w;
|
||||||
|
|
||||||
|
// Medium Doppler (3.5 kHz)
|
||||||
|
*cfo += cargf(corr[1] * conjf(corr[0])) / (2.0f * M_PI * distance_1) * (15000.0f * symbol_sz) * medium_w;
|
||||||
|
*cfo += cargf(corr[3] * conjf(corr[2])) / (2.0f * M_PI * distance_1) * (15000.0f * symbol_sz) * medium_w;
|
||||||
|
|
||||||
|
// High doppler (4.66 kHz)
|
||||||
|
*cfo += cargf(corr[2] * conjf(corr[1])) / (2.0f * M_PI * distance_2) * (15000.0f * symbol_sz) * high_w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,17 +31,19 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// Common execution parameters
|
// Common execution parameters
|
||||||
static uint32_t duration_execution_s;
|
static uint32_t duration_execution_s;
|
||||||
static srslte_cell_t cell_base = {.nof_prb = 6,
|
static srslte_cell_t cell_base = {.nof_prb = 6,
|
||||||
.nof_ports = 1,
|
.nof_ports = 1,
|
||||||
.id = 0,
|
.id = 0,
|
||||||
.cp = SRSLTE_CP_NORM,
|
.cp = SRSLTE_CP_NORM,
|
||||||
.phich_length = SRSLTE_PHICH_NORM,
|
.phich_length = SRSLTE_PHICH_NORM,
|
||||||
.phich_resources = SRSLTE_PHICH_R_1_6,
|
.phich_resources = SRSLTE_PHICH_R_1_6,
|
||||||
.frame_type = SRSLTE_FDD};
|
.frame_type = SRSLTE_FDD};
|
||||||
static std::string intra_meas_log_level;
|
static std::string intra_meas_log_level;
|
||||||
static std::string cell_list;
|
static std::string active_cell_list;
|
||||||
static int phy_lib_log_level;
|
static std::string simulation_cell_list;
|
||||||
|
static int phy_lib_log_level;
|
||||||
|
static srsue::phy_args_t phy_args;
|
||||||
|
|
||||||
// On the Fly parameters
|
// On the Fly parameters
|
||||||
static int earfcn_dl;
|
static int earfcn_dl;
|
||||||
|
@ -51,9 +53,6 @@ static std::string radio_log_level;
|
||||||
static float rx_gain;
|
static float rx_gain;
|
||||||
|
|
||||||
// Simulation parameters
|
// Simulation parameters
|
||||||
static uint32_t nof_enb;
|
|
||||||
static uint16_t cell_id_start;
|
|
||||||
static uint16_t cell_id_step;
|
|
||||||
static float channel_period_s;
|
static float channel_period_s;
|
||||||
static uint32_t cfi;
|
static uint32_t cfi;
|
||||||
static float ncell_attenuation_dB;
|
static float ncell_attenuation_dB;
|
||||||
|
@ -67,6 +66,10 @@ static uint16_t serving_cell_pdsch_rnti;
|
||||||
static srslte_tm_t serving_cell_pdsch_tm;
|
static srslte_tm_t serving_cell_pdsch_tm;
|
||||||
static uint16_t serving_cell_pdsch_mcs;
|
static uint16_t serving_cell_pdsch_mcs;
|
||||||
|
|
||||||
|
// Parsed PCI lists
|
||||||
|
static std::set<uint32_t> pcis_to_meas = {};
|
||||||
|
static std::set<uint32_t> pcis_to_simulate = {};
|
||||||
|
|
||||||
// PRB allocation helpers
|
// PRB allocation helpers
|
||||||
static uint32_t prbset_num = 1, last_prbset_num = 1;
|
static uint32_t prbset_num = 1, last_prbset_num = 1;
|
||||||
static uint32_t prbset_orig = 0;
|
static uint32_t prbset_orig = 0;
|
||||||
|
@ -197,7 +200,7 @@ public:
|
||||||
float scale = sqrtf(cell_base.nof_prb) / 0.05f / enb_dl.ifft->symbol_sz;
|
float scale = sqrtf(cell_base.nof_prb) / 0.05f / enb_dl.ifft->symbol_sz;
|
||||||
|
|
||||||
// Apply Neighbour cell attenuation
|
// Apply Neighbour cell attenuation
|
||||||
if (enb_dl.cell.id != cell_id_start) {
|
if (enb_dl.cell.id != *pcis_to_simulate.begin()) {
|
||||||
scale *= srslte_convert_dB_to_amplitude(-ncell_attenuation_dB);
|
scale *= srslte_convert_dB_to_amplitude(-ncell_attenuation_dB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,16 +268,22 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_stats()
|
bool print_stats()
|
||||||
{
|
{
|
||||||
printf("\n-- Statistics:\n");
|
printf("\n-- Statistics:\n");
|
||||||
for (auto& e : cells) {
|
uint32_t true_counts = 0;
|
||||||
bool false_alarm = true;
|
uint32_t false_counts = 0;
|
||||||
|
uint32_t tti_count = (1000 * duration_execution_s) / phy_args.intra_freq_meas_period_ms;
|
||||||
|
uint32_t ideal_true_counts = (pcis_to_simulate.size() - 1) * tti_count;
|
||||||
|
uint32_t ideal_false_counts = tti_count * cells.size() - ideal_true_counts;
|
||||||
|
|
||||||
for (uint32_t i = 0; false_alarm && (i < nof_enb); i++) {
|
for (auto& e : cells) {
|
||||||
if (e.first == cell_id_start + cell_id_step * i) {
|
bool false_alarm = pcis_to_simulate.find(e.first) == pcis_to_simulate.end();
|
||||||
false_alarm = false;
|
|
||||||
}
|
if (false_alarm) {
|
||||||
|
false_counts += e.second.count;
|
||||||
|
} else {
|
||||||
|
true_counts += e.second.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" pci=%03d; count=%3d; false=%s; rsrp=%+.1f|%+.1f|%+.1fdBfs; rsrq=%+.1f|%+.1f|%+.1fdB;\n",
|
printf(" pci=%03d; count=%3d; false=%s; rsrp=%+.1f|%+.1f|%+.1fdBfs; rsrq=%+.1f|%+.1f|%+.1fdB;\n",
|
||||||
|
@ -288,13 +297,21 @@ public:
|
||||||
e.second.rsrq_avg,
|
e.second.rsrq_avg,
|
||||||
e.second.rsrq_max);
|
e.second.rsrq_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float prob_detection = (ideal_true_counts) ? (float)true_counts / (float)ideal_true_counts : 0.0f;
|
||||||
|
float prob_false_alarm = (ideal_false_counts) ? (float)false_counts / (float)ideal_false_counts : 0.0f;
|
||||||
|
printf("\n");
|
||||||
|
printf(" Probability of detection: %.6f\n", prob_detection);
|
||||||
|
printf(" Probability of false alarm: %.6f\n", prob_false_alarm);
|
||||||
|
|
||||||
|
return (prob_detection >= 0.9f && prob_false_alarm <= 0.1f);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// shorten boost program options namespace
|
// shorten boost program options namespace
|
||||||
namespace bpo = boost::program_options;
|
namespace bpo = boost::program_options;
|
||||||
|
|
||||||
int parse_args(int argc, char** argv, srsue::phy_args_t* phy_args)
|
int parse_args(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int ret = SRSLTE_SUCCESS;
|
int ret = SRSLTE_SUCCESS;
|
||||||
|
|
||||||
|
@ -308,10 +325,10 @@ int parse_args(int argc, char** argv, srsue::phy_args_t* phy_args)
|
||||||
("duration", bpo::value<uint32_t>(&duration_execution_s)->default_value(60), "Duration of the execution in seconds")
|
("duration", bpo::value<uint32_t>(&duration_execution_s)->default_value(60), "Duration of the execution in seconds")
|
||||||
("cell.nof_prb", bpo::value<uint32_t>(&cell_base.nof_prb)->default_value(100), "Cell Number of PRB")
|
("cell.nof_prb", bpo::value<uint32_t>(&cell_base.nof_prb)->default_value(100), "Cell Number of PRB")
|
||||||
("intra_meas_log_level", bpo::value<std::string>(&intra_meas_log_level)->default_value("none"), "Intra measurement log level (none, warning, info, debug)")
|
("intra_meas_log_level", bpo::value<std::string>(&intra_meas_log_level)->default_value("none"), "Intra measurement log level (none, warning, info, debug)")
|
||||||
("intra_freq_meas_len_ms", bpo::value<uint32_t>(&phy_args->intra_freq_meas_len_ms)->default_value(20), "Intra measurement measurement length")
|
("intra_freq_meas_len_ms", bpo::value<uint32_t>(&phy_args.intra_freq_meas_len_ms)->default_value(20), "Intra measurement measurement length")
|
||||||
("intra_freq_meas_period_ms", bpo::value<uint32_t>(&phy_args->intra_freq_meas_period_ms)->default_value(200), "Intra measurement measurement period")
|
("intra_freq_meas_period_ms", bpo::value<uint32_t>(&phy_args.intra_freq_meas_period_ms)->default_value(200), "Intra measurement measurement period")
|
||||||
("phy_lib_log_level", bpo::value<int>(&phy_lib_log_level)->default_value(SRSLTE_VERBOSE_NONE), "Phy lib log level (0: none, 1: info, 2: debug)")
|
("phy_lib_log_level", bpo::value<int>(&phy_lib_log_level)->default_value(SRSLTE_VERBOSE_NONE), "Phy lib log level (0: none, 1: info, 2: debug)")
|
||||||
("cell_list", bpo::value<std::string>(&cell_list)->default_value("10,17,24,31,38,45,52"), "Comma separated neighbour PCI cell list")
|
("active_cell_list", bpo::value<std::string>(&active_cell_list)->default_value("10,17,24,31,38,45,52"), "Comma separated neighbour PCI cell list")
|
||||||
;
|
;
|
||||||
|
|
||||||
over_the_air.add_options()
|
over_the_air.add_options()
|
||||||
|
@ -324,9 +341,7 @@ int parse_args(int argc, char** argv, srsue::phy_args_t* phy_args)
|
||||||
;
|
;
|
||||||
|
|
||||||
simulation.add_options()
|
simulation.add_options()
|
||||||
("nof_enb", bpo::value<uint32_t >(&nof_enb)->default_value(4), "Number of eNb")
|
("simulation_cell_list", bpo::value<std::string>(&simulation_cell_list)->default_value("10,17,24,31,38,45,52"), "Comma separated neighbour PCI cell list")
|
||||||
("cell_id_start", bpo::value<uint16_t>(&cell_id_start)->default_value(10), "Cell id start")
|
|
||||||
("cell_id_step", bpo::value<uint16_t>(&cell_id_step)->default_value(7), "Cell id step")
|
|
||||||
("cell_cfi", bpo::value<uint32_t >(&cfi)->default_value(1), "Cell CFI")
|
("cell_cfi", bpo::value<uint32_t >(&cfi)->default_value(1), "Cell CFI")
|
||||||
("channel_period_s", bpo::value<float>(&channel_period_s)->default_value(16.8), "Channel period for HST and delay")
|
("channel_period_s", bpo::value<float>(&channel_period_s)->default_value(16.8), "Channel period for HST and delay")
|
||||||
("ncell_attenuation", bpo::value<float>(&ncell_attenuation_dB)->default_value(3.0f), "Neighbour cell attenuation relative to serving cell in dB")
|
("ncell_attenuation", bpo::value<float>(&ncell_attenuation_dB)->default_value(3.0f), "Neighbour cell attenuation relative to serving cell in dB")
|
||||||
|
@ -363,17 +378,42 @@ int parse_args(int argc, char** argv, srsue::phy_args_t* phy_args)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pci_list_parse_helper(std::string& list_str, std::set<uint32_t>& list)
|
||||||
|
{
|
||||||
|
if (list_str == "all") {
|
||||||
|
// Add all possible cells
|
||||||
|
for (int i = 0; i < 504; i++) {
|
||||||
|
list.insert(i);
|
||||||
|
}
|
||||||
|
} else if (list_str == "none") {
|
||||||
|
// Do nothing
|
||||||
|
} else if (!list_str.empty()) {
|
||||||
|
// Remove spaces from neightbour cell list
|
||||||
|
std::size_t p1 = list_str.find(' ');
|
||||||
|
while (p1 != std::string::npos) {
|
||||||
|
list_str.erase(p1);
|
||||||
|
p1 = list_str.find(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add cell to known cells
|
||||||
|
std::stringstream ss(list_str);
|
||||||
|
while (ss.good()) {
|
||||||
|
std::string substr;
|
||||||
|
getline(ss, substr, ',');
|
||||||
|
list.insert((uint32_t)strtoul(substr.c_str(), nullptr, 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int ret = SRSLTE_SUCCESS;
|
int ret;
|
||||||
srsue::phy_args_t phy_args = {};
|
|
||||||
|
|
||||||
// Parse args
|
// Parse args
|
||||||
if (parse_args(argc, argv, &phy_args)) {
|
if (parse_args(argc, argv)) {
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Common for simulation and over-the-air
|
// Common for simulation and over-the-air
|
||||||
auto baseband_buffer = (cf_t*)srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX);
|
auto baseband_buffer = (cf_t*)srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX);
|
||||||
srslte_timestamp_t ts = {};
|
srslte_timestamp_t ts = {};
|
||||||
|
@ -422,18 +462,15 @@ int main(int argc, char** argv)
|
||||||
softbuffer_tx[i] = (srslte_softbuffer_tx_t*)calloc(sizeof(srslte_softbuffer_tx_t), 1);
|
softbuffer_tx[i] = (srslte_softbuffer_tx_t*)calloc(sizeof(srslte_softbuffer_tx_t), 1);
|
||||||
if (!softbuffer_tx[i]) {
|
if (!softbuffer_tx[i]) {
|
||||||
ERROR("Error allocating softbuffer_tx\n");
|
ERROR("Error allocating softbuffer_tx\n");
|
||||||
ret = SRSLTE_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srslte_softbuffer_tx_init(softbuffer_tx[i], cell_base.nof_prb)) {
|
if (srslte_softbuffer_tx_init(softbuffer_tx[i], cell_base.nof_prb)) {
|
||||||
ERROR("Error initiating softbuffer_tx\n");
|
ERROR("Error initiating softbuffer_tx\n");
|
||||||
ret = SRSLTE_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data_tx[i] = (uint8_t*)srslte_vec_malloc(sizeof(uint8_t) * nof_bytes);
|
data_tx[i] = (uint8_t*)srslte_vec_malloc(sizeof(uint8_t) * nof_bytes);
|
||||||
if (!data_tx[i]) {
|
if (!data_tx[i]) {
|
||||||
ERROR("Error allocating data tx\n");
|
ERROR("Error allocating data tx\n");
|
||||||
ret = SRSLTE_ERROR;
|
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t j = 0; j < nof_bytes; j++) {
|
for (uint32_t j = 0; j < nof_bytes; j++) {
|
||||||
data_tx[i][j] = (uint8_t)srslte_random_uniform_int_dist(random_gen, 0, 255);
|
data_tx[i][j] = (uint8_t)srslte_random_uniform_int_dist(random_gen, 0, 255);
|
||||||
|
@ -443,8 +480,11 @@ int main(int argc, char** argv)
|
||||||
srslte_random_free(random_gen);
|
srslte_random_free(random_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pci_list_parse_helper(active_cell_list, pcis_to_meas);
|
||||||
|
pci_list_parse_helper(simulation_cell_list, pcis_to_simulate);
|
||||||
|
|
||||||
// Set cell_base id with the serving cell
|
// Set cell_base id with the serving cell
|
||||||
uint32_t serving_cell_id = (nof_enb == 1) ? (cell_id_start + cell_id_step) : cell_id_start;
|
uint32_t serving_cell_id = *pcis_to_simulate.begin();
|
||||||
cell_base.id = serving_cell_id;
|
cell_base.id = serving_cell_id;
|
||||||
|
|
||||||
logger.set_level(intra_meas_log_level);
|
logger.set_level(intra_meas_log_level);
|
||||||
|
@ -452,8 +492,6 @@ int main(int argc, char** argv)
|
||||||
intra_measure.init(&common, &rrc, &logger);
|
intra_measure.init(&common, &rrc, &logger);
|
||||||
intra_measure.set_primary_cell(serving_cell_id, cell_base);
|
intra_measure.set_primary_cell(serving_cell_id, cell_base);
|
||||||
|
|
||||||
std::set<uint32_t> pcis_to_meas = {};
|
|
||||||
|
|
||||||
if (earfcn_dl >= 0) {
|
if (earfcn_dl >= 0) {
|
||||||
// Create radio log
|
// Create radio log
|
||||||
radio_log = std::unique_ptr<srslte::log_filter>(new srslte::log_filter("Radio"));
|
radio_log = std::unique_ptr<srslte::log_filter>(new srslte::log_filter("Radio"));
|
||||||
|
@ -473,58 +511,40 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Create test eNb's if radio is not available
|
// Create test eNb's if radio is not available
|
||||||
for (uint32_t enb_idx = 0; enb_idx < nof_enb; enb_idx++) {
|
float channel_init_time_s = 0;
|
||||||
|
float channel_delay_us = 0;
|
||||||
|
for (auto& pci : pcis_to_simulate) {
|
||||||
// Initialise cell
|
// Initialise cell
|
||||||
srslte_cell_t cell = cell_base;
|
srslte_cell_t cell = cell_base;
|
||||||
cell.id = (cell_id_start + enb_idx * cell_id_step) % 504;
|
cell.id = pci;
|
||||||
|
|
||||||
// Initialise channel and push back
|
// Initialise channel and push back
|
||||||
srslte::channel::args_t channel_args;
|
srslte::channel::args_t channel_args;
|
||||||
channel_args.enable = true;
|
channel_args.enable = (channel_period_s != 0);
|
||||||
channel_args.hst_enable = (channel_hst_fd_hz != 0.0f);
|
channel_args.hst_enable = (channel_hst_fd_hz != 0.0f);
|
||||||
channel_args.hst_init_time_s = (float)(enb_idx * channel_period_s) / (float)nof_enb;
|
channel_args.hst_init_time_s = channel_init_time_s;
|
||||||
channel_args.hst_period_s = (float)channel_period_s;
|
channel_args.hst_period_s = (float)channel_period_s;
|
||||||
channel_args.hst_fd_hz = channel_hst_fd_hz;
|
channel_args.hst_fd_hz = channel_hst_fd_hz;
|
||||||
channel_args.delay_enable = (channel_delay_max_us != 0.0f);
|
channel_args.delay_enable = (channel_delay_max_us != 0.0f);
|
||||||
channel_args.delay_min_us = 0;
|
channel_args.delay_min_us = channel_delay_us;
|
||||||
channel_args.delay_max_us = channel_delay_max_us;
|
channel_args.delay_max_us = channel_delay_us;
|
||||||
channel_args.delay_period_s = (uint32)channel_period_s;
|
channel_args.delay_period_s = (uint32)channel_period_s;
|
||||||
channel_args.delay_init_time_s = (enb_idx * channel_period_s) / nof_enb;
|
channel_args.delay_init_time_s = channel_init_time_s;
|
||||||
test_enb_v.push_back(std::unique_ptr<test_enb>(new test_enb(cell, channel_args)));
|
test_enb_v.push_back(std::unique_ptr<test_enb>(new test_enb(cell, channel_args)));
|
||||||
|
|
||||||
// Add cell to known cells
|
// Add cell to known cells
|
||||||
if (cell_list.empty()) {
|
if (active_cell_list.empty()) {
|
||||||
pcis_to_meas.insert(cell.id);
|
pcis_to_meas.insert(cell.id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse cell list
|
// Increase init time
|
||||||
if (cell_list == "all") {
|
channel_init_time_s += channel_period_s / (float)pcis_to_simulate.size();
|
||||||
// Add all possible cells
|
channel_delay_us += channel_delay_max_us / (float)pcis_to_simulate.size();
|
||||||
for (int i = 0; i < 504; i++) {
|
|
||||||
pcis_to_meas.insert(i);
|
|
||||||
}
|
|
||||||
} else if (cell_list == "none") {
|
|
||||||
// Do nothing
|
|
||||||
} else if (!cell_list.empty()) {
|
|
||||||
// Remove spaces from neightbour cell list
|
|
||||||
std::size_t p1 = cell_list.find(' ');
|
|
||||||
while (p1 != std::string::npos) {
|
|
||||||
cell_list.erase(p1);
|
|
||||||
p1 = cell_list.find(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add cell to known cells
|
|
||||||
std::stringstream ss(cell_list);
|
|
||||||
while (ss.good()) {
|
|
||||||
std::string substr;
|
|
||||||
getline(ss, substr, ',');
|
|
||||||
pcis_to_meas.insert((uint32_t)strtoul(substr.c_str(), nullptr, 10));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass cells to measure to intra_measure object
|
// pass cells to measure to intra_measure object
|
||||||
|
|
||||||
intra_measure.set_cells_to_meas(pcis_to_meas);
|
intra_measure.set_cells_to_meas(pcis_to_meas);
|
||||||
|
|
||||||
// Run loop
|
// Run loop
|
||||||
|
@ -620,6 +640,12 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
srslte_timestamp_add(&ts, 0, 0.001f);
|
srslte_timestamp_add(&ts, 0, 0.001f);
|
||||||
|
|
||||||
|
if (sf_idx > phy_args.intra_freq_meas_period_ms) {
|
||||||
|
if (sf_idx % phy_args.intra_freq_meas_period_ms == 0) {
|
||||||
|
intra_measure.wait_meas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
intra_measure.write(sf_idx, baseband_buffer, SRSLTE_SF_LEN_PRB(cell_base.nof_prb));
|
intra_measure.write(sf_idx, baseband_buffer, SRSLTE_SF_LEN_PRB(cell_base.nof_prb));
|
||||||
if (sf_idx % 1000 == 0) {
|
if (sf_idx % 1000 == 0) {
|
||||||
printf("Done %.1f%%\n", (double)sf_idx * 100.0 / ((double)duration_execution_s * 1000.0));
|
printf("Done %.1f%%\n", (double)sf_idx * 100.0 / ((double)duration_execution_s * 1000.0));
|
||||||
|
@ -629,7 +655,8 @@ int main(int argc, char** argv)
|
||||||
// Stop
|
// Stop
|
||||||
intra_measure.stop();
|
intra_measure.stop();
|
||||||
|
|
||||||
rrc.print_stats();
|
ret = rrc.print_stats() ? SRSLTE_SUCCESS : SRSLTE_ERROR;
|
||||||
|
|
||||||
if (baseband_buffer) {
|
if (baseband_buffer) {
|
||||||
free(baseband_buffer);
|
free(baseband_buffer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue