mirror of https://github.com/pvnis/srsRAN_4G.git
SRSUE: moved sync SCell classes in new namespace
parent
22139afe09
commit
ceac7a02c8
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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 SRSUE_INTRA_MEASURE_H
|
||||||
|
#define SRSUE_INTRA_MEASURE_H
|
||||||
|
|
||||||
|
#include <srslte/common/log.h>
|
||||||
|
#include <srslte/common/threads.h>
|
||||||
|
#include <srslte/srslte.h>
|
||||||
|
|
||||||
|
#include <srsue/hdr/phy/scell/scell_recv.h>
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
namespace scell {
|
||||||
|
|
||||||
|
// Class to perform intra-frequency measurements
|
||||||
|
class intra_measure : public thread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
intra_measure();
|
||||||
|
~intra_measure();
|
||||||
|
void init(phy_common* common, rrc_interface_phy_lte* rrc, srslte::log* log_h);
|
||||||
|
void stop();
|
||||||
|
void add_cell(int pci);
|
||||||
|
void rem_cell(int pci);
|
||||||
|
void set_primay_cell(uint32_t earfcn, srslte_cell_t cell);
|
||||||
|
void clear_cells();
|
||||||
|
int get_offset(uint32_t pci);
|
||||||
|
void write(uint32_t tti, cf_t* data, uint32_t nsamples);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void run_thread();
|
||||||
|
const static int INTRA_FREQ_MEAS_PRIO = DEFAULT_PRIORITY + 5;
|
||||||
|
|
||||||
|
scell_recv scell;
|
||||||
|
rrc_interface_phy_lte* rrc;
|
||||||
|
srslte::log* log_h;
|
||||||
|
phy_common* common;
|
||||||
|
uint32_t current_earfcn;
|
||||||
|
uint32_t current_sflen;
|
||||||
|
srslte_cell_t primary_cell;
|
||||||
|
std::vector<int> active_pci;
|
||||||
|
|
||||||
|
srslte::tti_sync_cv tti_sync;
|
||||||
|
|
||||||
|
cf_t* search_buffer;
|
||||||
|
|
||||||
|
scell_recv::cell_info_t info[scell_recv::MAX_CELLS];
|
||||||
|
|
||||||
|
bool running;
|
||||||
|
bool receive_enabled;
|
||||||
|
bool receiving;
|
||||||
|
uint32_t measure_tti;
|
||||||
|
uint32_t receive_cnt;
|
||||||
|
srslte_ringbuffer_t ring_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace scell
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSUE_INTRA_MEASURE_H
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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 SRSUE_MEASURE_RECV_H
|
||||||
|
#define SRSUE_MEASURE_RECV_H
|
||||||
|
|
||||||
|
#include <srslte/srslte.h>
|
||||||
|
|
||||||
|
#include "srsue/hdr/phy/phy_common.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
namespace scell {
|
||||||
|
// Class to perform cell measurements
|
||||||
|
class measure
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: This class could early stop once the variance between the last N measurements is below 3GPP requirements
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef enum { IDLE, MEASURE_OK, ERROR } ret_code;
|
||||||
|
|
||||||
|
~measure();
|
||||||
|
void init(cf_t* buffer[SRSLTE_MAX_PORTS],
|
||||||
|
srslte::log* log_h,
|
||||||
|
uint32_t nof_rx_antennas,
|
||||||
|
phy_common* worker_com,
|
||||||
|
uint32_t nof_subframes = RSRP_MEASURE_NOF_FRAMES);
|
||||||
|
void reset();
|
||||||
|
void set_cell(srslte_cell_t cell);
|
||||||
|
ret_code run_subframe(uint32_t sf_idx);
|
||||||
|
ret_code run_multiple_subframes(cf_t* buffer, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf);
|
||||||
|
float rssi();
|
||||||
|
float rsrp();
|
||||||
|
float rsrq();
|
||||||
|
float snr();
|
||||||
|
uint32_t frame_st_idx();
|
||||||
|
void set_rx_gain_offset(float rx_gain_offset);
|
||||||
|
|
||||||
|
private:
|
||||||
|
srslte::log* log_h;
|
||||||
|
srslte_ue_dl_t ue_dl;
|
||||||
|
srslte_ue_dl_cfg_t ue_dl_cfg;
|
||||||
|
cf_t* buffer[SRSLTE_MAX_PORTS];
|
||||||
|
uint32_t cnt;
|
||||||
|
uint32_t nof_subframes;
|
||||||
|
uint32_t current_prb;
|
||||||
|
float rx_gain_offset;
|
||||||
|
float mean_rsrp, mean_rsrq, mean_snr, mean_rssi;
|
||||||
|
uint32_t final_offset;
|
||||||
|
const static int RSRP_MEASURE_NOF_FRAMES = 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace scell
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSUE_MEASURE_RECV_H
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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 SRSUE_SCELL_RECV_H
|
||||||
|
#define SRSUE_SCELL_RECV_H
|
||||||
|
|
||||||
|
#include <srslte/common/tti_sync_cv.h>
|
||||||
|
#include <srslte/srslte.h>
|
||||||
|
|
||||||
|
#include <srsue/hdr/phy/scell/measure.h>
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
namespace scell {
|
||||||
|
|
||||||
|
// Class to receive secondary cell
|
||||||
|
class scell_recv
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static int MAX_CELLS = 8;
|
||||||
|
typedef struct {
|
||||||
|
uint32_t pci;
|
||||||
|
float rsrp;
|
||||||
|
float rsrq;
|
||||||
|
uint32_t offset;
|
||||||
|
} cell_info_t;
|
||||||
|
void init(srslte::log* log_h, bool sic_pss_enabled, uint32_t max_sf_window, phy_common* worker_com);
|
||||||
|
void deinit();
|
||||||
|
void reset();
|
||||||
|
int find_cells(cf_t* input_buffer,
|
||||||
|
float rx_gain_offset,
|
||||||
|
srslte_cell_t current_cell,
|
||||||
|
uint32_t nof_sf,
|
||||||
|
cell_info_t found_cells[MAX_CELLS]);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 36.133 9.1.2.1 for band 7
|
||||||
|
constexpr static float ABSOLUTE_RSRP_THRESHOLD_DBM = -125;
|
||||||
|
|
||||||
|
cf_t* sf_buffer[SRSLTE_MAX_PORTS];
|
||||||
|
srslte::log* log_h;
|
||||||
|
srslte_sync_t sync_find;
|
||||||
|
|
||||||
|
bool sic_pss_enabled;
|
||||||
|
uint32_t current_fft_sz;
|
||||||
|
measure measure_p;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace scell
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSUE_SCELL_RECV_H
|
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* 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/intra_measure.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 {
|
||||||
|
|
||||||
|
intra_measure::intra_measure() : scell(), thread("SYNC_INTRA_MEASURE")
|
||||||
|
{
|
||||||
|
|
||||||
|
rrc = nullptr;
|
||||||
|
common = nullptr;
|
||||||
|
search_buffer = nullptr;
|
||||||
|
log_h = nullptr;
|
||||||
|
|
||||||
|
current_earfcn = 0;
|
||||||
|
current_sflen = 0;
|
||||||
|
measure_tti = 0;
|
||||||
|
receive_cnt = 0;
|
||||||
|
|
||||||
|
running = false;
|
||||||
|
receive_enabled = false;
|
||||||
|
receiving = false;
|
||||||
|
|
||||||
|
ZERO_OBJECT(info);
|
||||||
|
ZERO_OBJECT(ring_buffer);
|
||||||
|
ZERO_OBJECT(primary_cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
intra_measure::~intra_measure()
|
||||||
|
{
|
||||||
|
srslte_ringbuffer_free(&ring_buffer);
|
||||||
|
scell.deinit();
|
||||||
|
free(search_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void intra_measure::init(phy_common* common, rrc_interface_phy_lte* rrc, srslte::log* log_h)
|
||||||
|
{
|
||||||
|
this->rrc = rrc;
|
||||||
|
this->log_h = log_h;
|
||||||
|
this->common = common;
|
||||||
|
receive_enabled = false;
|
||||||
|
|
||||||
|
// Start scell
|
||||||
|
scell.init(log_h, common->args->sic_pss_enabled, common->args->intra_freq_meas_len_ms, common);
|
||||||
|
|
||||||
|
search_buffer =
|
||||||
|
(cf_t*)srslte_vec_malloc(common->args->intra_freq_meas_len_ms * SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB) * sizeof(cf_t));
|
||||||
|
|
||||||
|
if (srslte_ringbuffer_init(
|
||||||
|
&ring_buffer, sizeof(cf_t) * common->args->intra_freq_meas_len_ms * 2 * SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
start(INTRA_FREQ_MEAS_PRIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void intra_measure::stop()
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
srslte_ringbuffer_stop(&ring_buffer);
|
||||||
|
tti_sync.increase();
|
||||||
|
wait_thread_finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void intra_measure::set_primay_cell(uint32_t earfcn, srslte_cell_t cell)
|
||||||
|
{
|
||||||
|
this->current_earfcn = earfcn;
|
||||||
|
current_sflen = (uint32_t)SRSLTE_SF_LEN_PRB(cell.nof_prb);
|
||||||
|
this->primary_cell = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
void intra_measure::clear_cells()
|
||||||
|
{
|
||||||
|
active_pci.clear();
|
||||||
|
receive_enabled = false;
|
||||||
|
receiving = false;
|
||||||
|
receive_cnt = 0;
|
||||||
|
srslte_ringbuffer_reset(&ring_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void intra_measure::add_cell(int pci)
|
||||||
|
{
|
||||||
|
if (std::find(active_pci.begin(), active_pci.end(), pci) == active_pci.end()) {
|
||||||
|
active_pci.push_back(pci);
|
||||||
|
receive_enabled = true;
|
||||||
|
Info("INTRA: Starting intra-frequency measurement for pci=%d\n", pci);
|
||||||
|
} else {
|
||||||
|
Debug("INTRA: Requested to start already existing intra-frequency measurement for PCI=%d\n", pci);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int intra_measure::get_offset(uint32_t pci)
|
||||||
|
{
|
||||||
|
for (auto& i : info) {
|
||||||
|
if (i.pci == pci) {
|
||||||
|
return i.offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void intra_measure::rem_cell(int pci)
|
||||||
|
{
|
||||||
|
auto newEnd = std::remove(active_pci.begin(), active_pci.end(), pci);
|
||||||
|
|
||||||
|
if (newEnd != active_pci.end()) {
|
||||||
|
active_pci.erase(newEnd, active_pci.end());
|
||||||
|
if (active_pci.empty()) {
|
||||||
|
receive_enabled = false;
|
||||||
|
}
|
||||||
|
Info("INTRA: Stopping intra-frequency measurement for pci=%d. Number of cells: %zu\n", pci, active_pci.size());
|
||||||
|
} else {
|
||||||
|
Warning("INTRA: Requested to stop non-existing intra-frequency measurement for PCI=%d\n", pci);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void intra_measure::write(uint32_t tti, cf_t* data, uint32_t nsamples)
|
||||||
|
{
|
||||||
|
if (receive_enabled) {
|
||||||
|
if ((tti % common->args->intra_freq_meas_period_ms) == 0) {
|
||||||
|
receiving = true;
|
||||||
|
receive_cnt = 0;
|
||||||
|
measure_tti = tti;
|
||||||
|
srslte_ringbuffer_reset(&ring_buffer);
|
||||||
|
}
|
||||||
|
if (receiving) {
|
||||||
|
if (srslte_ringbuffer_write(&ring_buffer, data, nsamples * sizeof(cf_t)) < (int)(nsamples * sizeof(cf_t))) {
|
||||||
|
Warning("Error writting to ringbuffer\n");
|
||||||
|
receiving = false;
|
||||||
|
} else {
|
||||||
|
receive_cnt++;
|
||||||
|
if (receive_cnt == common->args->intra_freq_meas_len_ms) {
|
||||||
|
tti_sync.increase();
|
||||||
|
receiving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void intra_measure::run_thread()
|
||||||
|
{
|
||||||
|
while (running) {
|
||||||
|
if (running) {
|
||||||
|
tti_sync.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (running) {
|
||||||
|
|
||||||
|
// Read data from buffer and find cells in it
|
||||||
|
srslte_ringbuffer_read(
|
||||||
|
&ring_buffer, search_buffer, common->args->intra_freq_meas_len_ms * current_sflen * sizeof(cf_t));
|
||||||
|
int found_cells = scell.find_cells(
|
||||||
|
search_buffer, common->rx_gain_offset, primary_cell, common->args->intra_freq_meas_len_ms, info);
|
||||||
|
receiving = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < found_cells; i++) {
|
||||||
|
rrc->new_phy_meas(info[i].rsrp, info[i].rsrq, measure_tti, current_earfcn, info[i].pci);
|
||||||
|
}
|
||||||
|
// Look for other cells not found automatically
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace scell
|
||||||
|
} // namespace srsue
|
@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* 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/measure.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 {
|
||||||
|
void measure::init(cf_t* buffer[SRSLTE_MAX_PORTS],
|
||||||
|
srslte::log* log_h,
|
||||||
|
uint32_t nof_rx_antennas,
|
||||||
|
phy_common* worker_com,
|
||||||
|
uint32_t nof_subframes)
|
||||||
|
|
||||||
|
{
|
||||||
|
this->log_h = log_h;
|
||||||
|
this->nof_subframes = nof_subframes;
|
||||||
|
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||||
|
this->buffer[i] = buffer[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srslte_ue_dl_init(&ue_dl, this->buffer, SRSLTE_MAX_PRB, nof_rx_antennas)) {
|
||||||
|
Error("SYNC: Initiating ue_dl_measure\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
worker_com->set_ue_dl_cfg(&ue_dl_cfg);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
measure::~measure()
|
||||||
|
{
|
||||||
|
srslte_ue_dl_free(&ue_dl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void measure::reset()
|
||||||
|
{
|
||||||
|
cnt = 0;
|
||||||
|
mean_rsrp = 0;
|
||||||
|
mean_rsrq = 0;
|
||||||
|
mean_snr = 0;
|
||||||
|
mean_rssi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void measure::set_cell(srslte_cell_t cell)
|
||||||
|
{
|
||||||
|
current_prb = cell.nof_prb;
|
||||||
|
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
|
||||||
|
Error("SYNC: Setting cell: initiating ue_dl_measure\n");
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
float measure::rssi()
|
||||||
|
{
|
||||||
|
return 10 * log10(mean_rssi);
|
||||||
|
}
|
||||||
|
|
||||||
|
float measure::rsrp()
|
||||||
|
{
|
||||||
|
return 10 * log10(mean_rsrp) + 30 - rx_gain_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
float measure::rsrq()
|
||||||
|
{
|
||||||
|
return 10 * log10(mean_rsrq);
|
||||||
|
}
|
||||||
|
|
||||||
|
float measure::snr()
|
||||||
|
{
|
||||||
|
return mean_snr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t measure::frame_st_idx()
|
||||||
|
{
|
||||||
|
return final_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void measure::set_rx_gain_offset(float rx_gain_offset)
|
||||||
|
{
|
||||||
|
this->rx_gain_offset = rx_gain_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
measure::ret_code measure::run_multiple_subframes(cf_t* input_buffer, uint32_t offset, uint32_t sf_idx, uint32_t max_sf)
|
||||||
|
{
|
||||||
|
uint32_t sf_len = (uint32_t)SRSLTE_SF_LEN_PRB(current_prb);
|
||||||
|
|
||||||
|
ret_code ret = IDLE;
|
||||||
|
|
||||||
|
int sf_start = offset - sf_len / 2;
|
||||||
|
while (sf_start < 0 && sf_idx < max_sf) {
|
||||||
|
Info("INTRA: sf_start=%d, sf_idx=%d\n", sf_start, sf_idx);
|
||||||
|
sf_start += sf_len;
|
||||||
|
sf_idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FINE_TUNE_OFFSET_WITH_RS
|
||||||
|
float max_rsrp = -200;
|
||||||
|
int best_test_sf_start = 0;
|
||||||
|
int test_sf_start = 0;
|
||||||
|
bool found_best = false;
|
||||||
|
|
||||||
|
// Fine-tune sf_start using RS
|
||||||
|
for (uint32_t n = 0; n < 5; n++) {
|
||||||
|
|
||||||
|
test_sf_start = sf_start - 2 + n;
|
||||||
|
if (test_sf_start >= 0) {
|
||||||
|
|
||||||
|
cf_t* buf_m[SRSLTE_MAX_PORTS];
|
||||||
|
buf_m[0] = &input_buffer[test_sf_start];
|
||||||
|
|
||||||
|
uint32_t cfi;
|
||||||
|
if (srslte_ue_dl_decode_fft_estimate_noguru(&ue_dl, buf_m, sf_idx, &cfi)) {
|
||||||
|
Error("MEAS: Measuring RSRP: Estimating channel\n");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest);
|
||||||
|
if (rsrp > max_rsrp) {
|
||||||
|
max_rsrp = rsrp;
|
||||||
|
best_test_sf_start = test_sf_start;
|
||||||
|
found_best = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug("INTRA: fine-tuning sf_start: %d, found_best=%d, rem_sf=%d\n", sf_start, found_best, nof_sf);
|
||||||
|
|
||||||
|
sf_start = found_best ? best_test_sf_start : sf_start;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sf_start >= 0 && sf_start < (int)(sf_len * max_sf)) {
|
||||||
|
|
||||||
|
uint32_t nof_sf = (sf_len * max_sf - sf_start) / sf_len;
|
||||||
|
|
||||||
|
final_offset = (uint32_t)sf_start;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < nof_sf; i++) {
|
||||||
|
memcpy(buffer[0], &input_buffer[sf_start + i * sf_len], sizeof(cf_t) * sf_len);
|
||||||
|
ret = run_subframe((sf_idx + i) % 10);
|
||||||
|
if (ret != IDLE) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret != ERROR) {
|
||||||
|
return MEASURE_OK;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Error("INTRA: not running because sf_start=%d, offset=%d, sf_len*max_sf=%d*%d\n", sf_start, offset, sf_len, max_sf);
|
||||||
|
ret = ERROR;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
measure::ret_code measure::run_subframe(uint32_t sf_idx)
|
||||||
|
{
|
||||||
|
srslte_dl_sf_cfg_t sf_cfg;
|
||||||
|
ZERO_OBJECT(sf_cfg);
|
||||||
|
sf_cfg.tti = sf_idx;
|
||||||
|
|
||||||
|
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, &sf_cfg, &ue_dl_cfg)) {
|
||||||
|
log_h->error("SYNC: Measuring RSRP: Estimating channel\n");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rsrp = ue_dl.chest_res.rsrp;
|
||||||
|
float rsrq = ue_dl.chest_res.rsrq;
|
||||||
|
float snr = ue_dl.chest_res.snr_db;
|
||||||
|
float rssi = srslte_vec_avg_power_cf(buffer[0], (uint32_t)SRSLTE_SF_LEN_PRB(current_prb));
|
||||||
|
|
||||||
|
if (cnt == 0) {
|
||||||
|
mean_rsrp = rsrp;
|
||||||
|
mean_rsrq = rsrq;
|
||||||
|
mean_snr = snr;
|
||||||
|
mean_rssi = rssi;
|
||||||
|
} else {
|
||||||
|
mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt);
|
||||||
|
mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt);
|
||||||
|
mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt);
|
||||||
|
mean_rssi = SRSLTE_VEC_CMA(rssi, mean_rssi, cnt);
|
||||||
|
}
|
||||||
|
cnt++;
|
||||||
|
|
||||||
|
log_h->debug(
|
||||||
|
"SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", cnt, nof_subframes, sf_idx, rsrp, snr);
|
||||||
|
|
||||||
|
if (cnt >= nof_subframes) {
|
||||||
|
return MEASURE_OK;
|
||||||
|
} else {
|
||||||
|
return IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace scell
|
||||||
|
} // namespace srsue
|
@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
Loading…
Reference in New Issue