mirror of https://github.com/PentHertz/srsLTE.git
Added more information in NR PHY SA cell search test
This commit is contained in:
parent
5b744bb6c5
commit
4f86c2fac7
|
@ -64,6 +64,8 @@ public:
|
||||||
uint32_t ssb_periodicity_ms;
|
uint32_t ssb_periodicity_ms;
|
||||||
srsran_duplex_mode_t duplex_mode;
|
srsran_duplex_mode_t duplex_mode;
|
||||||
std::set<uint32_t> pci_list;
|
std::set<uint32_t> pci_list;
|
||||||
|
float channel_hst_fd_hz = 0.0f;
|
||||||
|
float channel_hst_period_s = 7.2f;
|
||||||
};
|
};
|
||||||
|
|
||||||
gnb_rf_emulator(const args_t& args)
|
gnb_rf_emulator(const args_t& args)
|
||||||
|
@ -83,6 +85,11 @@ public:
|
||||||
gnb_args.ssb_periodicity_ms = args.ssb_periodicity_ms;
|
gnb_args.ssb_periodicity_ms = args.ssb_periodicity_ms;
|
||||||
gnb_args.duplex_mode = args.duplex_mode;
|
gnb_args.duplex_mode = args.duplex_mode;
|
||||||
|
|
||||||
|
gnb_args.channel.hst_enable = std::isnormal(args.channel_hst_fd_hz) and std::isnormal(args.channel_hst_period_s);
|
||||||
|
gnb_args.channel.hst_fd_hz = args.channel_hst_fd_hz;
|
||||||
|
gnb_args.channel.hst_period_s = args.channel_hst_period_s;
|
||||||
|
gnb_args.channel.enable = gnb_args.channel.hst_enable;
|
||||||
|
|
||||||
gnb_vector.emplace_back(std::make_shared<gnb_emulator>(gnb_args));
|
gnb_vector.emplace_back(std::make_shared<gnb_emulator>(gnb_args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gnb_rf_emulator.h"
|
#include "gnb_rf_emulator.h"
|
||||||
#include "srsran/asn1/rrc_nr.h"
|
|
||||||
#include "srsran/common/band_helper.h"
|
#include "srsran/common/band_helper.h"
|
||||||
#include "srsran/common/crash_handler.h"
|
#include "srsran/common/crash_handler.h"
|
||||||
#include "srsran/common/string_helpers.h"
|
#include "srsran/common/string_helpers.h"
|
||||||
|
@ -46,7 +45,6 @@ public:
|
||||||
pending_tti_cvar.notify_all();
|
pending_tti_cvar.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t count = 0;
|
|
||||||
void tick()
|
void tick()
|
||||||
{
|
{
|
||||||
// Wait for TTI to get processed
|
// Wait for TTI to get processed
|
||||||
|
@ -80,6 +78,8 @@ struct args_t {
|
||||||
|
|
||||||
// Simulation parameters
|
// Simulation parameters
|
||||||
uint32_t sim_ssb_periodicity_ms = 10;
|
uint32_t sim_ssb_periodicity_ms = 10;
|
||||||
|
float sim_channel_hst_fd_hz = 0.0f;
|
||||||
|
float sim_channel_hst_period_s = 7.2f;
|
||||||
std::set<uint32_t> sim_cell_pci;
|
std::set<uint32_t> sim_cell_pci;
|
||||||
|
|
||||||
// RF parameters
|
// RF parameters
|
||||||
|
@ -164,6 +164,8 @@ int parse_args(int argc, char** argv, args_t& args)
|
||||||
("sim.pci_list", bpo::value<std::string>(&simulation_cell_list)->default_value(simulation_cell_list), "Comma separated PCI cell list to simulate")
|
("sim.pci_list", bpo::value<std::string>(&simulation_cell_list)->default_value(simulation_cell_list), "Comma separated PCI cell list to simulate")
|
||||||
("sim.bw", bpo::value<uint32_t>(&args.base_carrier.nof_prb)->default_value(args.base_carrier.nof_prb), "Carrier bandwidth in RB")
|
("sim.bw", bpo::value<uint32_t>(&args.base_carrier.nof_prb)->default_value(args.base_carrier.nof_prb), "Carrier bandwidth in RB")
|
||||||
("sim.ssb_period", bpo::value<uint32_t>(&args.sim_ssb_periodicity_ms)->default_value(args.sim_ssb_periodicity_ms), "SSB period in ms")
|
("sim.ssb_period", bpo::value<uint32_t>(&args.sim_ssb_periodicity_ms)->default_value(args.sim_ssb_periodicity_ms), "SSB period in ms")
|
||||||
|
("sim.channel.hst.fd", bpo::value<float>(&args.sim_channel_hst_fd_hz)->default_value(args.sim_channel_hst_fd_hz), "Channel emulator HST maximum frequency")
|
||||||
|
("sim.channel.hst.period", bpo::value<float>(&args.sim_channel_hst_period_s)->default_value(args.sim_channel_hst_period_s), "Channel emulator HST period")
|
||||||
;
|
;
|
||||||
|
|
||||||
phy.add_options()
|
phy.add_options()
|
||||||
|
@ -223,6 +225,8 @@ public:
|
||||||
phy.wait_initialize();
|
phy.wait_initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cell_search_read_and_clear() { return stack.get_cell_search_finished(); }
|
||||||
|
|
||||||
bool start_cell_search(const srsue::phy_interface_stack_nr::cell_search_args_t& args)
|
bool start_cell_search(const srsue::phy_interface_stack_nr::cell_search_args_t& args)
|
||||||
{
|
{
|
||||||
return phy.start_cell_search(args);
|
return phy.start_cell_search(args);
|
||||||
|
@ -243,6 +247,8 @@ public:
|
||||||
// Stop PHY
|
// Stop PHY
|
||||||
phy.stop();
|
phy.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ue_dummy_stack::metrics_t& get_metrics() const { return stack.get_metrics(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
@ -270,6 +276,8 @@ int main(int argc, char** argv)
|
||||||
gnb_args.ssb_scs = args.ssb_scs;
|
gnb_args.ssb_scs = args.ssb_scs;
|
||||||
gnb_args.duplex_mode = args.duplex_mode;
|
gnb_args.duplex_mode = args.duplex_mode;
|
||||||
gnb_args.pci_list = args.sim_cell_pci;
|
gnb_args.pci_list = args.sim_cell_pci;
|
||||||
|
gnb_args.channel_hst_fd_hz = args.sim_channel_hst_fd_hz;
|
||||||
|
gnb_args.channel_hst_period_s = args.sim_channel_hst_period_s;
|
||||||
|
|
||||||
radio = std::make_shared<gnb_rf_emulator>(gnb_args);
|
radio = std::make_shared<gnb_rf_emulator>(gnb_args);
|
||||||
} else {
|
} else {
|
||||||
|
@ -277,7 +285,7 @@ int main(int argc, char** argv)
|
||||||
srsran::rf_args_t rf_args = {};
|
srsran::rf_args_t rf_args = {};
|
||||||
rf_args.type = "multi";
|
rf_args.type = "multi";
|
||||||
rf_args.log_level = args.rf_log_level;
|
rf_args.log_level = args.rf_log_level;
|
||||||
// rf_args.srate_hz = args.srate_hz;
|
rf_args.srate_hz = args.srate_hz;
|
||||||
rf_args.rx_gain = args.rf_rx_gain_dB;
|
rf_args.rx_gain = args.rf_rx_gain_dB;
|
||||||
rf_args.nof_carriers = 1;
|
rf_args.nof_carriers = 1;
|
||||||
rf_args.nof_antennas = 1;
|
rf_args.nof_antennas = 1;
|
||||||
|
@ -362,7 +370,8 @@ int main(int argc, char** argv)
|
||||||
// Transition PHY to cell search
|
// Transition PHY to cell search
|
||||||
srsran_assert(ue.start_cell_search(cs_args_), "Failed cell search start");
|
srsran_assert(ue.start_cell_search(cs_args_), "Failed cell search start");
|
||||||
|
|
||||||
for (uint32_t i = 0; i < args.duration_ms; i++) {
|
// Run slot until the PHY reported to the stack
|
||||||
|
while (not ue.cell_search_read_and_clear()) {
|
||||||
ue.run_tti();
|
ue.run_tti();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,6 +382,39 @@ int main(int argc, char** argv)
|
||||||
// Stop Radio
|
// Stop Radio
|
||||||
radio->reset();
|
radio->reset();
|
||||||
|
|
||||||
|
const ue_dummy_stack::metrics_t& metrics = ue.get_metrics();
|
||||||
|
printf("| %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s | %10s |\n",
|
||||||
|
"PCI",
|
||||||
|
"SSB",
|
||||||
|
"Count",
|
||||||
|
"RSRP min",
|
||||||
|
"RSRP avg",
|
||||||
|
"RSRP max",
|
||||||
|
"SNR min",
|
||||||
|
"SNR avg",
|
||||||
|
"SNR max",
|
||||||
|
"CFO min",
|
||||||
|
"CFO avg",
|
||||||
|
"CFO max");
|
||||||
|
for (auto& pci : metrics.cell_search) {
|
||||||
|
for (auto& ssb : pci.second) {
|
||||||
|
printf("| %10d | %10d | %10d | %+10.1f | %+10.1f | %+10.1f | %+10.1f | %+10.1f | %+10.1f | %+10.1f | %+10.1f | "
|
||||||
|
"%+10.1f |\n",
|
||||||
|
pci.first,
|
||||||
|
ssb.first,
|
||||||
|
(uint32_t)ssb.second.count,
|
||||||
|
ssb.second.rsrp_db_min,
|
||||||
|
ssb.second.rsrp_db_avg,
|
||||||
|
ssb.second.rsrp_db_max,
|
||||||
|
ssb.second.snr_db_min,
|
||||||
|
ssb.second.snr_db_avg,
|
||||||
|
ssb.second.snr_db_max,
|
||||||
|
ssb.second.cfo_hz_min,
|
||||||
|
ssb.second.cfo_hz_avg,
|
||||||
|
ssb.second.cfo_hz_max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Erase radio
|
// Erase radio
|
||||||
radio = nullptr;
|
radio = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,24 @@ public:
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cell_search_metrics_t {
|
||||||
|
float epre_db_avg = 0.0f;
|
||||||
|
float epre_db_min = +INFINITY;
|
||||||
|
float epre_db_max = -INFINITY;
|
||||||
|
float rsrp_db_avg = 0.0f;
|
||||||
|
float rsrp_db_min = +INFINITY;
|
||||||
|
float rsrp_db_max = -INFINITY;
|
||||||
|
float snr_db_avg = 0.0f;
|
||||||
|
float snr_db_min = +INFINITY;
|
||||||
|
float snr_db_max = -INFINITY;
|
||||||
|
float cfo_hz_avg = 0.0f;
|
||||||
|
float cfo_hz_min = +INFINITY;
|
||||||
|
float cfo_hz_max = -INFINITY;
|
||||||
|
uint32_t count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct metrics_t {
|
struct metrics_t {
|
||||||
|
std::map<uint32_t, std::map<uint32_t, cell_search_metrics_t> > cell_search;
|
||||||
std::map<uint32_t, prach_metrics_t> prach = {}; ///< PRACH metrics indexed with premable index
|
std::map<uint32_t, prach_metrics_t> prach = {}; ///< PRACH metrics indexed with premable index
|
||||||
uint32_t sr_count = 0; ///< Counts number of transmitted SR
|
uint32_t sr_count = 0; ///< Counts number of transmitted SR
|
||||||
};
|
};
|
||||||
|
@ -48,6 +65,8 @@ private:
|
||||||
dummy_tx_harq_entity tx_harq_proc;
|
dummy_tx_harq_entity tx_harq_proc;
|
||||||
dummy_rx_harq_entity rx_harq_proc;
|
dummy_rx_harq_entity rx_harq_proc;
|
||||||
|
|
||||||
|
std::atomic<bool> cell_search_finished = {false};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct args_t {
|
struct args_t {
|
||||||
uint16_t rnti = 0x1234; ///< C-RNTI for PUSCH and PDSCH transmissions
|
uint16_t rnti = 0x1234; ///< C-RNTI for PUSCH and PDSCH transmissions
|
||||||
|
@ -134,21 +153,41 @@ public:
|
||||||
}
|
}
|
||||||
bool is_valid() const { return valid; }
|
bool is_valid() const { return valid; }
|
||||||
|
|
||||||
metrics_t get_metrics() { return metrics; }
|
const metrics_t& get_metrics() const { return metrics; }
|
||||||
|
|
||||||
void set_phy_config_complete(bool status) override {}
|
void set_phy_config_complete(bool status) override {}
|
||||||
|
|
||||||
|
bool get_cell_search_finished()
|
||||||
|
{
|
||||||
|
bool ret = cell_search_finished;
|
||||||
|
|
||||||
|
cell_search_finished = false;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void cell_search_found_cell(const cell_search_result_t& result) override
|
void cell_search_found_cell(const cell_search_result_t& result) override
|
||||||
{
|
{
|
||||||
if (result.cell_found) {
|
// Flag as cell search is done
|
||||||
|
cell_search_finished = true;
|
||||||
|
|
||||||
|
if (not result.cell_found) {
|
||||||
|
logger.info("Cell search finished without detecting any cell");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pack PBCH message bits
|
||||||
|
std::array<uint8_t, SRSRAN_PBCH_MSG_NR_SZ> bit_pack_pbch_msg = {};
|
||||||
|
asn1::cbit_ref cbit(bit_pack_pbch_msg.data(), bit_pack_pbch_msg.size());
|
||||||
|
srsran_bit_pack_vector((uint8_t*)result.pbch_msg.payload, bit_pack_pbch_msg.data(), SRSRAN_PBCH_MSG_NR_SZ);
|
||||||
|
|
||||||
// Unpack MIB with ASN1
|
// Unpack MIB with ASN1
|
||||||
asn1::rrc_nr::mib_s mib_asn1;
|
asn1::rrc_nr::bcch_bch_msg_s bcch;
|
||||||
asn1::cbit_ref cbit(result.pbch_msg.payload, SRSRAN_PBCH_MSG_NR_SZ);
|
bcch.unpack(cbit);
|
||||||
mib_asn1.unpack(cbit);
|
|
||||||
|
|
||||||
// Convert MIB to JSON
|
// Convert MIB to JSON
|
||||||
asn1::json_writer json;
|
asn1::json_writer json;
|
||||||
mib_asn1.to_json(json);
|
bcch.to_json(json);
|
||||||
|
|
||||||
// Unpack MIB with C lib
|
// Unpack MIB with C lib
|
||||||
srsran_mib_nr_t mib_c = {};
|
srsran_mib_nr_t mib_c = {};
|
||||||
|
@ -164,9 +203,21 @@ public:
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"Cell found pci=%d %s %s ASN1: %s", result.pci, mib_info.data(), csi_info.data(), json.to_string().c_str());
|
"Cell found pci=%d %s %s ASN1: %s", result.pci, mib_info.data(), csi_info.data(), json.to_string().c_str());
|
||||||
} else {
|
|
||||||
logger.info("Cell not found\n");
|
cell_search_metrics_t& m = metrics.cell_search[result.pci][result.pbch_msg.ssb_idx];
|
||||||
}
|
m.epre_db_min = SRSRAN_MIN(m.epre_db_min, result.measurements.epre_dB);
|
||||||
|
m.epre_db_max = SRSRAN_MAX(m.epre_db_max, result.measurements.epre_dB);
|
||||||
|
m.epre_db_avg = SRSRAN_VEC_SAFE_CMA(result.measurements.epre_dB, m.epre_db_avg, m.count);
|
||||||
|
m.rsrp_db_min = SRSRAN_MIN(m.rsrp_db_min, result.measurements.rsrp_dB);
|
||||||
|
m.rsrp_db_max = SRSRAN_MAX(m.rsrp_db_max, result.measurements.rsrp_dB);
|
||||||
|
m.rsrp_db_avg = SRSRAN_VEC_SAFE_CMA(result.measurements.rsrp_dB, m.rsrp_db_avg, m.count);
|
||||||
|
m.snr_db_min = SRSRAN_MIN(m.snr_db_min, result.measurements.snr_dB);
|
||||||
|
m.snr_db_max = SRSRAN_MAX(m.snr_db_max, result.measurements.snr_dB);
|
||||||
|
m.snr_db_avg = SRSRAN_VEC_SAFE_CMA(result.measurements.snr_dB, m.snr_db_avg, m.count);
|
||||||
|
m.cfo_hz_min = SRSRAN_MIN(m.cfo_hz_min, result.measurements.cfo_hz);
|
||||||
|
m.cfo_hz_max = SRSRAN_MAX(m.cfo_hz_max, result.measurements.cfo_hz);
|
||||||
|
m.cfo_hz_avg = SRSRAN_VEC_SAFE_CMA(result.measurements.cfo_hz, m.cfo_hz_avg, m.count);
|
||||||
|
m.count++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue