You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
9.1 KiB
C++

/*
* 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/.
*
*/
#include "srsue/hdr/phy/scell/scell_recv.h"
#define Error(fmt, ...) \
if (SRSLTE_DEBUG_ENABLED) \
log_h->error(fmt, ##__VA_ARGS__)
#define Warning(fmt, ...) \
if (SRSLTE_DEBUG_ENABLED) \
log_h->warning(fmt, ##__VA_ARGS__)
#define Info(fmt, ...) \
if (SRSLTE_DEBUG_ENABLED) \
log_h->info(fmt, ##__VA_ARGS__)
#define Debug(fmt, ...) \
if (SRSLTE_DEBUG_ENABLED) \
log_h->debug(fmt, ##__VA_ARGS__)
namespace srsue {
namespace scell {
/**********
* Secondary cell receiver
*/
void scell_recv::init(srslte::log* _log_h, bool _sic_pss_enabled, uint32_t max_sf_window, phy_common* worker_com)
{
log_h = _log_h;
sic_pss_enabled = _sic_pss_enabled;
// and a separate ue_sync instance
uint32_t max_fft_sz = srslte_symbol_sz(100);
uint32_t max_sf_size = SRSLTE_SF_LEN(max_fft_sz);
sf_buffer[0] = (cf_t*)srslte_vec_malloc(sizeof(cf_t) * max_sf_size);
if (!sf_buffer[0]) {
ERROR("Error allocating %d samples for scell\n", max_sf_size);
return;
}
measure_p.init(sf_buffer, log_h, 1, worker_com, max_sf_window);
// do this different we don't need all this search window.
if (srslte_sync_init(&sync_find, max_sf_window * max_sf_size, 5 * max_sf_size, max_fft_sz)) {
ERROR("Error initiating sync_find\n");
return;
}
srslte_sync_set_sss_algorithm(&sync_find, SSS_FULL);
srslte_sync_cp_en(&sync_find, false);
srslte_sync_set_cfo_pss_enable(&sync_find, true);
srslte_sync_set_threshold(&sync_find, 1.7);
srslte_sync_set_em_alpha(&sync_find, 0.3);
// Configure FIND object behaviour (this configuration is always the same)
srslte_sync_set_cfo_ema_alpha(&sync_find, 1.0);
srslte_sync_set_cfo_i_enable(&sync_find, false);
srslte_sync_set_cfo_pss_enable(&sync_find, true);
srslte_sync_set_pss_filt_enable(&sync_find, true);
srslte_sync_set_sss_eq_enable(&sync_find, true);
sync_find.pss.chest_on_filter = true;
sync_find.sss_channel_equalize = false;
reset();
}
void scell_recv::deinit()
{
srslte_sync_free(&sync_find);
free(sf_buffer[0]);
}
void scell_recv::reset()
{
current_fft_sz = 0;
measure_p.reset();
}
int scell_recv::find_cells(
cf_t* input_buffer, float rx_gain_offset, srslte_cell_t cell, uint32_t nof_sf, cell_info_t cells[MAX_CELLS])
{
uint32_t fft_sz = srslte_symbol_sz(cell.nof_prb);
uint32_t sf_len = SRSLTE_SF_LEN(fft_sz);
if (fft_sz != current_fft_sz) {
if (srslte_sync_resize(&sync_find, nof_sf * sf_len, 5 * sf_len, fft_sz)) {
ERROR("Error resizing sync nof_sf=%d, sf_len=%d, fft_sz=%d\n", nof_sf, sf_len, fft_sz);
return SRSLTE_ERROR;
}
current_fft_sz = fft_sz;
}
int nof_cells = 0;
uint32_t peak_idx = 0;
uint32_t sf_idx = 0;
int cell_id = 0;
srslte_cell_t found_cell;
found_cell = cell;
measure_p.set_rx_gain_offset(rx_gain_offset);
for (uint32_t n_id_2 = 0; n_id_2 < 3; n_id_2++) {
found_cell.id = 10000;
if (n_id_2 != (cell.id % 3) || sic_pss_enabled) {
srslte_sync_set_N_id_2(&sync_find, n_id_2);
srslte_sync_find_ret_t sync_res;
do {
srslte_sync_reset(&sync_find);
srslte_sync_cfo_reset(&sync_find);
sync_res = SRSLTE_SYNC_NOFOUND;
cell_id = 0;
float max_peak = -1;
uint32_t max_sf5 = 0;
uint32_t max_sf_idx = 0;
for (uint32_t sf5_cnt = 0; sf5_cnt < nof_sf / 5; sf5_cnt++) {
sync_res = srslte_sync_find(&sync_find, input_buffer, sf5_cnt * 5 * sf_len, &peak_idx);
Debug("INTRA: n_id_2=%d, cnt=%d/%d, sync_res=%d, sf_idx=%d, peak_idx=%d, peak_value=%f\n",
n_id_2,
sf5_cnt,
nof_sf / 5,
sync_res,
srslte_sync_get_sf_idx(&sync_find),
peak_idx,
sync_find.peak_value);
if (sync_find.peak_value > max_peak && sync_res == SRSLTE_SYNC_FOUND) {
max_sf5 = sf5_cnt;
max_sf_idx = srslte_sync_get_sf_idx(&sync_find);
cell_id = srslte_sync_get_cell_id(&sync_find);
}
}
switch (sync_res) {
case SRSLTE_SYNC_ERROR:
return SRSLTE_ERROR;
ERROR("Error finding correlation peak\n");
return SRSLTE_ERROR;
case SRSLTE_SYNC_FOUND:
sf_idx = (10 - max_sf_idx - 5 * (max_sf5 % 2)) % 10;
if (cell_id >= 0) {
// We found the same cell as before, look another N_id_2
if ((uint32_t)cell_id == found_cell.id || (uint32_t)cell_id == cell.id) {
Debug("INTRA: n_id_2=%d, PCI=%d, found_cell.id=%d, cell.id=%d\n",
n_id_2,
cell_id,
found_cell.id,
cell.id);
sync_res = SRSLTE_SYNC_NOFOUND;
} else {
// We found a new cell ID
found_cell.id = (uint32_t)cell_id;
found_cell.nof_ports = 1; // Use port 0 only for measurement
measure_p.set_cell(found_cell);
// Correct CFO
/*
srslte_cfo_correct(&sync_find.cfo_corr_frame,
input_buffer,
input_cfo_corrected,
-srslte_sync_get_cfo(&sync_find)/sync_find.fft_size);
*/
switch (measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) {
default:
// Consider a cell to be detectable 8.1.2.2.1.1 from 36.133. Currently only using first condition
if (measure_p.rsrp() > ABSOLUTE_RSRP_THRESHOLD_DBM) {
cells[nof_cells].pci = found_cell.id;
cells[nof_cells].rsrp = measure_p.rsrp();
cells[nof_cells].rsrq = measure_p.rsrq();
cells[nof_cells].offset = measure_p.frame_st_idx();
Info("INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, "
"sf=%d, max_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n",
nof_cells,
cell_id,
measure_p.rsrp(),
measure_p.frame_st_idx(),
sync_find.peak_value,
sf_idx,
max_sf5,
n_id_2,
15000 * srslte_sync_get_cfo(&sync_find));
nof_cells++;
/*
if (sic_pss_enabled) {
srslte_pss_sic(&sync_find.pss, &input_buffer[sf5_cnt * 5 * sf_len + sf_len / 2 - fft_sz]);
}*/
} else {
Info("INTRA: Found neighbour cell but RSRP=%.1f dBm is below threshold (%.1f dBm)\n",
measure_p.rsrp(),
ABSOLUTE_RSRP_THRESHOLD_DBM);
}
break;
case measure::ERROR:
Error("INTRA: Measuring neighbour cell\n");
return SRSLTE_ERROR;
}
}
} else {
sync_res = SRSLTE_SYNC_NOFOUND;
}
break;
case SRSLTE_SYNC_FOUND_NOSPACE:
/* If a peak was found but there is not enough space for SSS/CP detection, discard a few samples */
break;
default:
break;
}
} while (sync_res == SRSLTE_SYNC_FOUND && sic_pss_enabled && nof_cells < MAX_CELLS);
}
}
return nof_cells;
}
} // namespace scell
} // namespace srsue