2020-11-26 01:25:22 -08:00
|
|
|
/**
|
2019-04-23 01:53:11 -07:00
|
|
|
*
|
2020-11-26 01:25:22 -08:00
|
|
|
* \section COPYRIGHT
|
2019-04-23 01:53:11 -07:00
|
|
|
*
|
2021-03-19 03:45:56 -07:00
|
|
|
* Copyright 2013-2021 Software Radio Systems Limited
|
2019-04-23 01:53:11 -07:00
|
|
|
*
|
2020-11-26 01:25:22 -08:00
|
|
|
* By using this file, you agree to the terms and conditions set
|
|
|
|
* forth in the LICENSE file which can be found at the top level of
|
|
|
|
* the distribution.
|
2019-04-23 01:53:11 -07:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
#include "srsran/srsran.h"
|
2019-12-16 07:04:22 -08:00
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
#include "srsran/common/standard_streams.h"
|
2020-11-17 06:18:28 -08:00
|
|
|
#include "srsue/hdr/phy/lte/sf_worker.h"
|
2019-04-23 01:53:11 -07:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#define Error(fmt, ...) \
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED) \
|
2021-01-28 08:17:43 -08:00
|
|
|
logger.error(fmt, ##__VA_ARGS__)
|
2019-04-23 01:53:11 -07:00
|
|
|
#define Warning(fmt, ...) \
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED) \
|
2021-01-28 08:17:43 -08:00
|
|
|
logger.warning(fmt, ##__VA_ARGS__)
|
2019-04-23 01:53:11 -07:00
|
|
|
#define Info(fmt, ...) \
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED) \
|
2021-01-28 08:17:43 -08:00
|
|
|
logger.info(fmt, ##__VA_ARGS__)
|
2019-04-23 01:53:11 -07:00
|
|
|
#define Debug(fmt, ...) \
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED) \
|
2021-01-28 08:17:43 -08:00
|
|
|
logger.debug(fmt, ##__VA_ARGS__)
|
2019-04-23 01:53:11 -07:00
|
|
|
|
|
|
|
/* This is to visualize the channel response */
|
|
|
|
#ifdef ENABLE_GUI
|
|
|
|
#include "srsgui/srsgui.h"
|
|
|
|
#include <semaphore.h>
|
|
|
|
|
2021-01-19 08:58:02 -08:00
|
|
|
static void init_plots(srsue::lte::sf_worker* worker);
|
|
|
|
static pthread_t plot_thread;
|
|
|
|
static sem_t plot_sem;
|
|
|
|
static int plot_worker_id = -1;
|
2021-01-20 01:16:10 -08:00
|
|
|
static bool plot_nr_enable = false;
|
2019-04-23 01:53:11 -07:00
|
|
|
#else
|
2019-07-23 02:09:23 -07:00
|
|
|
#pragma message "Compiling without srsGUI support"
|
2019-04-23 01:53:11 -07:00
|
|
|
#endif
|
|
|
|
/*********************************************/
|
|
|
|
|
|
|
|
namespace srsue {
|
2020-11-17 06:18:28 -08:00
|
|
|
namespace lte {
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2021-01-28 08:17:43 -08:00
|
|
|
sf_worker::sf_worker(uint32_t max_prb, phy_common* phy_, srslog::basic_logger& logger) : logger(logger)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
2021-01-28 08:17:43 -08:00
|
|
|
phy = phy_;
|
2019-04-23 01:53:11 -07:00
|
|
|
|
|
|
|
// ue_sync in phy.cc requires a buffer for 3 subframes
|
2020-11-20 03:12:29 -08:00
|
|
|
for (uint32_t r = 0; r < phy->args->nof_lte_carriers; r++) {
|
2021-01-28 08:17:43 -08:00
|
|
|
cc_workers.push_back(new cc_worker(r, max_prb, phy, logger));
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sf_worker::~sf_worker()
|
|
|
|
{
|
2020-11-20 03:12:29 -08:00
|
|
|
for (uint32_t r = 0; r < phy->args->nof_lte_carriers; r++) {
|
2019-04-23 01:53:11 -07:00
|
|
|
delete cc_workers[r];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-22 12:47:16 -07:00
|
|
|
void sf_worker::reset_cell_unlocked(uint32_t cc_idx)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
2020-09-22 12:47:16 -07:00
|
|
|
cc_workers[cc_idx]->reset_cell_unlocked();
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
bool sf_worker::set_cell_unlocked(uint32_t cc_idx, srsran_cell_t cell_)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
|
|
|
if (cc_idx < cc_workers.size()) {
|
2020-09-22 12:47:16 -07:00
|
|
|
if (!cc_workers[cc_idx]->set_cell_unlocked(cell_)) {
|
2021-01-28 08:17:43 -08:00
|
|
|
Error("Setting cell for cc=%d", cc_idx);
|
2019-12-13 07:49:58 -08:00
|
|
|
return false;
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
} else {
|
2021-01-28 08:17:43 -08:00
|
|
|
Error("Setting cell for cc=%d; Not enough CC workers (%zd);", cc_idx, cc_workers.size());
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cc_idx == 0) {
|
2020-09-22 12:47:16 -07:00
|
|
|
std::lock_guard<std::mutex> lock(cell_mutex);
|
2019-09-24 06:41:28 -07:00
|
|
|
cell = cell_;
|
2019-04-23 01:53:11 -07:00
|
|
|
cell_initiated = true;
|
2019-12-13 07:49:58 -08:00
|
|
|
cell_init_cond.notify_one();
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
2019-12-13 07:49:58 -08:00
|
|
|
return true;
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
cf_t* sf_worker::get_buffer(uint32_t carrier_idx, uint32_t antenna_idx)
|
|
|
|
{
|
|
|
|
return cc_workers[carrier_idx]->get_rx_buffer(antenna_idx);
|
|
|
|
}
|
|
|
|
|
2020-02-04 07:19:03 -08:00
|
|
|
uint32_t sf_worker::get_buffer_len()
|
|
|
|
{
|
|
|
|
if (cc_workers.empty()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return cc_workers.at(0)->get_buffer_len();
|
|
|
|
}
|
|
|
|
|
2019-12-17 06:49:56 -08:00
|
|
|
void sf_worker::set_tti(uint32_t tti_)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
2019-09-24 06:41:28 -07:00
|
|
|
tti = tti_;
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2019-09-24 06:41:28 -07:00
|
|
|
for (auto& cc_worker : cc_workers) {
|
|
|
|
cc_worker->set_tti(tti);
|
|
|
|
}
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2021-01-28 08:17:43 -08:00
|
|
|
logger.set_context(tti);
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
void sf_worker::set_tx_time(const srsran::rf_timestamp_t& tx_time_)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
2020-05-07 06:37:24 -07:00
|
|
|
tx_time.copy(tx_time_);
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
2019-09-24 06:41:28 -07:00
|
|
|
void sf_worker::set_prach(cf_t* prach_ptr_, float prach_power_)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
2019-09-24 06:41:28 -07:00
|
|
|
prach_ptr = prach_ptr_;
|
|
|
|
prach_power = prach_power_;
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
2020-09-22 12:47:16 -07:00
|
|
|
void sf_worker::set_cfo_unlocked(const uint32_t& cc_idx, float cfo)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
2020-09-22 12:47:16 -07:00
|
|
|
cc_workers[cc_idx]->set_cfo_unlocked(cfo);
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
void sf_worker::set_tdd_config_unlocked(srsran_tdd_config_t config)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
2019-09-24 06:41:28 -07:00
|
|
|
for (auto& cc_worker : cc_workers) {
|
2020-09-22 12:47:16 -07:00
|
|
|
cc_worker->set_tdd_config_unlocked(config);
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
tdd_config = config;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
void sf_worker::set_config_unlocked(uint32_t cc_idx, srsran::phy_cfg_t phy_cfg)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
|
|
|
if (cc_idx < cc_workers.size()) {
|
2020-09-22 12:47:16 -07:00
|
|
|
cc_workers[cc_idx]->set_config_unlocked(phy_cfg);
|
2020-02-16 14:16:51 -08:00
|
|
|
if (cc_idx > 0) {
|
|
|
|
// Update DCI config for PCell
|
2020-09-22 12:47:16 -07:00
|
|
|
cc_workers[0]->upd_config_dci_unlocked(phy_cfg.dl_cfg.dci);
|
2020-02-16 14:16:51 -08:00
|
|
|
}
|
2019-04-23 01:53:11 -07:00
|
|
|
} else {
|
2021-01-28 08:17:43 -08:00
|
|
|
Error("Setting config for cc=%d; Invalid cc_idx", cc_idx);
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sf_worker::work_imp()
|
|
|
|
{
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran::rf_buffer_t tx_signal_ptr = {};
|
2019-04-23 01:53:11 -07:00
|
|
|
if (!cell_initiated) {
|
2021-01-26 09:30:51 -08:00
|
|
|
phy->worker_end(this, false, tx_signal_ptr, tx_time, false);
|
2020-07-16 06:52:32 -07:00
|
|
|
return;
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
2020-03-25 08:56:32 -07:00
|
|
|
bool rx_signal_ok = false;
|
|
|
|
bool tx_signal_ready = false;
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t nof_samples = SRSRAN_SF_LEN_PRB(cell.nof_prb);
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2020-07-30 23:50:32 -07:00
|
|
|
/***** Downlink Processing *******/
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2020-07-30 23:50:32 -07:00
|
|
|
// Loop through all carriers. carrier_idx=0 is PCell
|
|
|
|
for (uint32_t carrier_idx = 0; carrier_idx < cc_workers.size(); carrier_idx++) {
|
|
|
|
// Process all DL and special subframes
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_sfidx_tdd_type(tdd_config, tti % 10) != SRSRAN_TDD_SF_U || cell.frame_type == SRSRAN_FDD) {
|
|
|
|
srsran_mbsfn_cfg_t mbsfn_cfg;
|
2020-07-30 23:50:32 -07:00
|
|
|
ZERO_OBJECT(mbsfn_cfg);
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2020-07-30 23:50:32 -07:00
|
|
|
if (carrier_idx == 0 && phy->is_mbsfn_sf(&mbsfn_cfg, tti)) {
|
2021-02-11 02:49:33 -08:00
|
|
|
rx_signal_ok =
|
|
|
|
cc_workers[0]->work_dl_mbsfn(mbsfn_cfg); // Don't do chest_ok in mbsfn since it trigger measurements
|
2020-07-30 23:50:32 -07:00
|
|
|
} else {
|
2020-11-13 03:31:23 -08:00
|
|
|
if (phy->cell_state.is_configured(carrier_idx)) {
|
2020-07-30 23:50:32 -07:00
|
|
|
rx_signal_ok = cc_workers[carrier_idx]->work_dl_regular();
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-07-30 23:50:32 -07:00
|
|
|
}
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2020-07-30 23:50:32 -07:00
|
|
|
/***** Uplink Generation + Transmission *******/
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2020-07-30 23:50:32 -07:00
|
|
|
/* If TTI+4 is an uplink subframe (TODO: Support short PRACH and SRS in UpPts special subframes) */
|
2021-03-19 03:45:56 -07:00
|
|
|
if ((srsran_sfidx_tdd_type(tdd_config, TTI_TX(tti) % 10) == SRSRAN_TDD_SF_U) || cell.frame_type == SRSRAN_FDD) {
|
2020-07-30 23:50:32 -07:00
|
|
|
// Generate Uplink signal if no PRACH pending
|
|
|
|
if (!prach_ptr) {
|
|
|
|
// Common UCI data object for all carriers
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_uci_data_t uci_data;
|
2020-07-30 23:50:32 -07:00
|
|
|
reset_uci(&uci_data);
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2020-07-30 23:50:32 -07:00
|
|
|
uint32_t uci_cc_idx = phy->get_ul_uci_cc(TTI_TX(tti));
|
2020-07-06 09:27:03 -07:00
|
|
|
|
2020-07-30 23:50:32 -07:00
|
|
|
// Fill periodic CQI data; In case of periodic CSI report collision, lower carrier index have preference, so
|
|
|
|
// stop as soon as either CQI data is enabled or RI is carried
|
2020-11-20 03:12:29 -08:00
|
|
|
for (uint32_t carrier_idx = 0; carrier_idx < phy->args->nof_lte_carriers and not uci_data.cfg.cqi.data_enable and
|
|
|
|
uci_data.cfg.cqi.ri_len == 0;
|
2020-07-30 23:50:32 -07:00
|
|
|
carrier_idx++) {
|
2020-11-11 05:38:08 -08:00
|
|
|
if (phy->cell_state.is_active(carrier_idx, TTI_TX(tti))) {
|
2020-07-30 23:50:32 -07:00
|
|
|
cc_workers[carrier_idx]->set_uci_periodic_cqi(&uci_data);
|
2020-07-06 09:27:03 -07:00
|
|
|
}
|
2020-07-30 23:50:32 -07:00
|
|
|
}
|
2020-07-06 09:27:03 -07:00
|
|
|
|
2020-07-30 23:50:32 -07:00
|
|
|
// Loop through all carriers
|
2020-11-20 03:12:29 -08:00
|
|
|
for (uint32_t carrier_idx = 0; carrier_idx < phy->args->nof_lte_carriers; carrier_idx++) {
|
2020-11-11 05:38:08 -08:00
|
|
|
if (phy->cell_state.is_active(carrier_idx, tti)) {
|
2020-09-22 12:47:16 -07:00
|
|
|
tx_signal_ready |= cc_workers[carrier_idx]->work_ul(uci_cc_idx == carrier_idx ? &uci_data : nullptr);
|
2019-04-23 01:53:11 -07:00
|
|
|
|
2020-09-22 12:47:16 -07:00
|
|
|
// Set signal pointer based on offset
|
|
|
|
tx_signal_ptr.set(carrier_idx, 0, phy->args->nof_rx_ant, cc_workers[carrier_idx]->get_tx_buffer(0));
|
|
|
|
}
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-19 01:19:36 -07:00
|
|
|
tx_signal_ptr.set_nof_samples(nof_samples);
|
2019-04-23 01:53:11 -07:00
|
|
|
|
|
|
|
// Set PRACH buffer signal pointer
|
|
|
|
if (prach_ptr) {
|
2020-03-06 06:26:48 -08:00
|
|
|
tx_signal_ready = true;
|
|
|
|
tx_signal_ptr.set(0, prach_ptr);
|
|
|
|
prach_ptr = nullptr;
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Call worker_end to transmit the signal
|
2021-01-26 09:30:51 -08:00
|
|
|
phy->worker_end(this, tx_signal_ready, tx_signal_ptr, tx_time, false);
|
2019-04-23 01:53:11 -07:00
|
|
|
|
|
|
|
if (rx_signal_ok) {
|
|
|
|
update_measurements();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Tell the plotting thread to draw the plots */
|
|
|
|
#ifdef ENABLE_GUI
|
|
|
|
if ((int)get_id() == plot_worker_id) {
|
|
|
|
sem_post(&plot_sem);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************* Uplink common control functions ****************************/
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
void sf_worker::reset_uci(srsran_uci_data_t* uci_data)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_uci_data_reset(uci_data);
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**************************** Measurements **************************/
|
|
|
|
|
|
|
|
void sf_worker::update_measurements()
|
|
|
|
{
|
2020-12-02 03:45:20 -08:00
|
|
|
std::vector<phy_meas_t> serving_cells = {};
|
2020-09-22 12:47:16 -07:00
|
|
|
for (uint32_t cc_idx = 0; cc_idx < cc_workers.size(); cc_idx++) {
|
|
|
|
cf_t* rssi_power_buffer = nullptr;
|
|
|
|
// Setting rssi_power_buffer to nullptr disables RSSI update. Do it only by worker 0
|
|
|
|
if (cc_idx == 0 && get_id() == 0) {
|
|
|
|
rssi_power_buffer = cc_workers[0]->get_rx_buffer(0);
|
2019-07-18 01:53:12 -07:00
|
|
|
}
|
2020-09-22 12:47:16 -07:00
|
|
|
cc_workers[cc_idx]->update_measurements(serving_cells, rssi_power_buffer);
|
|
|
|
}
|
|
|
|
// Send report to stack
|
|
|
|
if (not serving_cells.empty()) {
|
|
|
|
phy->stack->new_cell_meas(serving_cells);
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************
|
|
|
|
*
|
|
|
|
* Interface for Plot visualization
|
|
|
|
*
|
|
|
|
***********************************************************/
|
|
|
|
|
|
|
|
void sf_worker::start_plot()
|
|
|
|
{
|
|
|
|
#ifdef ENABLE_GUI
|
|
|
|
if (plot_worker_id == -1) {
|
|
|
|
plot_worker_id = get_id();
|
2021-01-20 01:16:10 -08:00
|
|
|
plot_nr_enable = phy->args->nof_nr_carriers > 0;
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran::console("Starting plot for worker_id=%d\n", plot_worker_id);
|
2019-04-23 01:53:11 -07:00
|
|
|
init_plots(this);
|
|
|
|
} else {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran::console("Trying to start a plot but already started by worker_id=%d\n", plot_worker_id);
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
#else
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran::console("Trying to start a plot but plots are disabled (ENABLE_GUI constant in sf_worker.cc)\n");
|
2019-04-23 01:53:11 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int sf_worker::read_ce_abs(float* ce_abs, uint32_t tx_antenna, uint32_t rx_antenna)
|
|
|
|
{
|
|
|
|
return cc_workers[0]->read_ce_abs(ce_abs, tx_antenna, rx_antenna);
|
|
|
|
}
|
|
|
|
|
|
|
|
int sf_worker::read_pdsch_d(cf_t* pdsch_d)
|
|
|
|
{
|
|
|
|
return cc_workers[0]->read_pdsch_d(pdsch_d);
|
|
|
|
}
|
|
|
|
|
2019-04-12 08:35:49 -07:00
|
|
|
float sf_worker::get_cfo()
|
|
|
|
{
|
2021-04-12 13:48:25 -07:00
|
|
|
sync_metrics_t::array_t sync_metrics = {};
|
2019-04-12 08:35:49 -07:00
|
|
|
phy->get_sync_metrics(sync_metrics);
|
2019-05-17 04:03:29 -07:00
|
|
|
return sync_metrics[0].cfo;
|
2019-04-12 08:35:49 -07:00
|
|
|
}
|
2020-11-17 06:18:28 -08:00
|
|
|
} // namespace lte
|
2019-04-23 01:53:11 -07:00
|
|
|
} // namespace srsue
|
|
|
|
|
|
|
|
/***********************************************************
|
|
|
|
*
|
|
|
|
* PLOT TO VISUALIZE THE CHANNEL RESPONSEE
|
|
|
|
*
|
|
|
|
***********************************************************/
|
|
|
|
|
|
|
|
#ifdef ENABLE_GUI
|
2021-03-19 03:45:56 -07:00
|
|
|
plot_real_t pce[SRSRAN_MAX_PORTS][SRSRAN_MAX_PORTS];
|
2019-04-23 01:53:11 -07:00
|
|
|
plot_scatter_t pconst;
|
2021-01-19 08:58:02 -08:00
|
|
|
plot_scatter_t pconst_nr;
|
|
|
|
bool pconst_nr_ready = false;
|
2021-03-19 03:45:56 -07:00
|
|
|
#define SCATTER_PDSCH_BUFFER_LEN (20 * 6 * SRSRAN_SF_LEN_RE(SRSRAN_MAX_PRB, SRSRAN_CP_NORM))
|
2019-04-23 01:53:11 -07:00
|
|
|
#define SCATTER_PDSCH_PLOT_LEN 4000
|
|
|
|
float tmp_plot[SCATTER_PDSCH_BUFFER_LEN];
|
2021-03-19 03:45:56 -07:00
|
|
|
cf_t tmp_plot2[SRSRAN_SF_LEN_RE(SRSRAN_MAX_PRB, SRSRAN_CP_NORM)];
|
2019-09-24 06:41:28 -07:00
|
|
|
bool plot_quit = false;
|
2019-04-23 01:53:11 -07:00
|
|
|
|
|
|
|
#define CFO_PLOT_LEN 0 /* Set to non zero for enabling CFO plot */
|
|
|
|
#if CFO_PLOT_LEN > 0
|
|
|
|
static plot_real_t pcfo;
|
|
|
|
static uint32_t icfo = 0;
|
|
|
|
static float cfo_buffer[CFO_PLOT_LEN];
|
|
|
|
#endif /* CFO_PLOT_LEN > 0 */
|
|
|
|
|
2019-04-12 08:35:49 -07:00
|
|
|
#define SYNC_PLOT_LEN 0 /* Set to non zero for enabling Sync error plot */
|
|
|
|
#if SYNC_PLOT_LEN > 0
|
|
|
|
static plot_real_t psync;
|
|
|
|
static uint32_t isync = 0;
|
|
|
|
static float sync_buffer[SYNC_PLOT_LEN];
|
|
|
|
#endif /* SYNC_PLOT_LEN > 0 */
|
|
|
|
|
2021-01-19 08:58:02 -08:00
|
|
|
static void* plot_thread_run(void* arg)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
2020-12-02 01:55:56 -08:00
|
|
|
auto worker = (srsue::lte::sf_worker*)arg;
|
2019-12-16 07:04:22 -08:00
|
|
|
uint32_t row_count = 0;
|
2019-04-23 01:53:11 -07:00
|
|
|
|
|
|
|
sdrgui_init();
|
|
|
|
for (uint32_t tx = 0; tx < worker->get_cell_nof_ports(); tx++) {
|
|
|
|
for (uint32_t rx = 0; rx < worker->get_rx_nof_antennas(); rx++) {
|
|
|
|
char str_buf[64];
|
|
|
|
snprintf(str_buf, 64, "|H%d%d|", rx, tx);
|
|
|
|
plot_real_init(&pce[tx][rx]);
|
|
|
|
plot_real_setTitle(&pce[tx][rx], str_buf);
|
|
|
|
plot_real_setLabels(&pce[tx][rx], (char*)"Index", (char*)"dB");
|
|
|
|
plot_real_setYAxisScale(&pce[tx][rx], -40, 40);
|
|
|
|
|
|
|
|
plot_real_addToWindowGrid(&pce[tx][rx], (char*)"srsue", tx, rx);
|
|
|
|
}
|
|
|
|
}
|
2019-04-12 08:35:49 -07:00
|
|
|
row_count = worker->get_rx_nof_antennas();
|
2019-04-23 01:53:11 -07:00
|
|
|
|
|
|
|
plot_scatter_init(&pconst);
|
2021-01-19 08:58:02 -08:00
|
|
|
plot_scatter_setTitle(&pconst, (char*)"LTE - PDSCH - Equalized Symbols");
|
2019-04-23 01:53:11 -07:00
|
|
|
plot_scatter_setXAxisScale(&pconst, -4, 4);
|
|
|
|
plot_scatter_setYAxisScale(&pconst, -4, 4);
|
2021-01-19 08:58:02 -08:00
|
|
|
plot_scatter_addToWindowGrid(&pconst, (char*)"srsue", 0, row_count++);
|
|
|
|
|
2021-01-20 01:16:10 -08:00
|
|
|
if (plot_nr_enable) {
|
2021-01-31 12:01:39 -08:00
|
|
|
plot_scatter_init(&pconst_nr);
|
|
|
|
plot_scatter_setTitle(&pconst_nr, (char*)"NR - PDSCH - Equalized Symbols");
|
|
|
|
plot_scatter_setXAxisScale(&pconst_nr, -4, 4);
|
|
|
|
plot_scatter_setYAxisScale(&pconst_nr, -4, 4);
|
2021-01-20 01:16:10 -08:00
|
|
|
plot_scatter_addToWindowGrid(&pconst_nr, (char*)"srsue", 0, row_count++);
|
|
|
|
pconst_nr_ready = true;
|
|
|
|
}
|
2019-04-23 01:53:11 -07:00
|
|
|
|
|
|
|
#if CFO_PLOT_LEN > 0
|
|
|
|
plot_real_init(&pcfo);
|
|
|
|
plot_real_setTitle(&pcfo, (char*)"CFO (Hz)");
|
|
|
|
plot_real_setLabels(&pcfo, (char*)"Time", (char*)"Hz");
|
|
|
|
plot_real_setYAxisScale(&pcfo, -4000, 4000);
|
|
|
|
|
2019-04-12 08:35:49 -07:00
|
|
|
plot_scatter_addToWindowGrid(&pcfo, (char*)"srsue", 1, row_count++);
|
2019-04-23 01:53:11 -07:00
|
|
|
#endif /* CFO_PLOT_LEN > 0 */
|
|
|
|
|
2019-04-12 08:35:49 -07:00
|
|
|
#if SYNC_PLOT_LEN > 0
|
|
|
|
plot_real_init(&psync);
|
|
|
|
plot_real_setTitle(&psync, (char*)"Sync error (in samples)");
|
|
|
|
plot_real_setLabels(&psync, (char*)"Time", (char*)"Error");
|
|
|
|
plot_real_setYAxisScale(&psync, -2, +2);
|
|
|
|
|
|
|
|
plot_scatter_addToWindowGrid(&psync, (char*)"srsue", 1, row_count++);
|
|
|
|
#endif /* SYNC_PLOT_LEN > 0 */
|
|
|
|
|
2019-12-13 07:49:58 -08:00
|
|
|
uint32_t num_tx = worker->get_cell_nof_ports();
|
|
|
|
uint32_t num_rx = worker->get_rx_nof_antennas();
|
|
|
|
|
2019-04-23 01:53:11 -07:00
|
|
|
int n;
|
|
|
|
int readed_pdsch_re = 0;
|
2019-09-24 06:41:28 -07:00
|
|
|
while (!plot_quit) {
|
2019-04-23 01:53:11 -07:00
|
|
|
sem_wait(&plot_sem);
|
|
|
|
|
|
|
|
if (readed_pdsch_re < SCATTER_PDSCH_PLOT_LEN) {
|
|
|
|
n = worker->read_pdsch_d(&tmp_plot2[readed_pdsch_re]);
|
|
|
|
readed_pdsch_re += n;
|
|
|
|
} else {
|
2019-12-13 07:49:58 -08:00
|
|
|
for (uint32_t tx = 0; tx < num_tx; tx++) {
|
|
|
|
for (uint32_t rx = 0; rx < num_rx; rx++) {
|
2019-04-23 01:53:11 -07:00
|
|
|
n = worker->read_ce_abs(tmp_plot, tx, rx);
|
|
|
|
if (n > 0) {
|
|
|
|
plot_real_setNewData(&pce[tx][rx], tmp_plot, n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (readed_pdsch_re > 0) {
|
|
|
|
plot_scatter_setNewData(&pconst, tmp_plot2, readed_pdsch_re);
|
|
|
|
}
|
|
|
|
readed_pdsch_re = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if CFO_PLOT_LEN > 0
|
|
|
|
cfo_buffer[icfo] = worker->get_cfo() * 15000.0f;
|
|
|
|
icfo = (icfo + 1) % CFO_PLOT_LEN;
|
|
|
|
plot_real_setNewData(&pcfo, cfo_buffer, CFO_PLOT_LEN);
|
|
|
|
#endif /* CFO_PLOT_LEN > 0 */
|
|
|
|
}
|
2019-09-24 06:41:28 -07:00
|
|
|
return nullptr;
|
2019-04-23 01:53:11 -07:00
|
|
|
}
|
|
|
|
|
2020-12-02 01:55:56 -08:00
|
|
|
void init_plots(srsue::lte::sf_worker* worker)
|
2019-04-23 01:53:11 -07:00
|
|
|
{
|
|
|
|
if (sem_init(&plot_sem, 0, 0)) {
|
|
|
|
perror("sem_init");
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_attr_t attr;
|
2019-09-24 06:41:28 -07:00
|
|
|
struct sched_param param = {};
|
2019-12-16 07:04:22 -08:00
|
|
|
param.sched_priority = 0;
|
2019-04-23 01:53:11 -07:00
|
|
|
pthread_attr_init(&attr);
|
|
|
|
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
|
|
|
pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
|
|
|
|
pthread_attr_setschedparam(&attr, ¶m);
|
|
|
|
if (pthread_create(&plot_thread, &attr, plot_thread_run, worker)) {
|
|
|
|
perror("pthread_create");
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|