moved cell struct of srsue::rrc to separate file

This commit is contained in:
Francisco Paisana 2020-07-01 19:34:24 +01:00
parent f6d3467884
commit 069dc1f751
6 changed files with 298 additions and 255 deletions

View File

@ -22,6 +22,7 @@
#ifndef SRSUE_RRC_H
#define SRSUE_RRC_H
#include "rrc_cell.h"
#include "rrc_common.h"
#include "rrc_metrics.h"
#include "srslte/asn1/rrc_asn1.h"
@ -65,215 +66,6 @@ using srslte::byte_buffer_t;
namespace srsue {
class cell_t
{
public:
bool is_valid() { return phy_cell.earfcn != 0 && srslte_cellid_isvalid(phy_cell.pci); }
bool equals(cell_t* x) { return equals(x->phy_cell.earfcn, x->phy_cell.pci); }
bool equals(uint32_t earfcn, uint32_t pci) { return earfcn == phy_cell.earfcn && pci == phy_cell.pci; }
// NaN means an RSRP value has not yet been obtained. Keep then in the list and clean them if never updated
bool greater(cell_t* x) { return rsrp > x->rsrp || std::isnan(rsrp); }
bool plmn_equals(asn1::rrc::plmn_id_s plmn_id)
{
if (has_valid_sib1) {
for (uint32_t i = 0; i < sib1.cell_access_related_info.plmn_id_list.size(); i++) {
if (plmn_id.mcc == sib1.cell_access_related_info.plmn_id_list[i].plmn_id.mcc &&
plmn_id.mnc == sib1.cell_access_related_info.plmn_id_list[i].plmn_id.mnc) {
return true;
}
}
}
return false;
}
uint32_t nof_plmns()
{
if (has_valid_sib1) {
return sib1.cell_access_related_info.plmn_id_list.size();
} else {
return 0;
}
}
srslte::plmn_id_t get_plmn(uint32_t idx)
{
if (idx < sib1.cell_access_related_info.plmn_id_list.size() && has_valid_sib1) {
return srslte::make_plmn_id_t(sib1.cell_access_related_info.plmn_id_list[idx].plmn_id);
} else {
return {};
}
}
uint16_t get_tac()
{
if (has_valid_sib1) {
return (uint16_t)sib1.cell_access_related_info.tac.to_number();
} else {
return 0;
}
}
cell_t()
{
gettimeofday(&last_update, nullptr);
has_valid_sib1 = false;
has_valid_sib2 = false;
has_valid_sib3 = false;
has_valid_sib13 = false;
phy_cell = {0, 0, 0};
rsrp = NAN;
rsrq = NAN;
sib1 = {};
sib2 = {};
sib3 = {};
sib13 = {};
}
cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell_) : cell_t() { phy_cell = phy_cell_; }
uint32_t get_earfcn() const { return phy_cell.earfcn; }
uint32_t get_pci() const { return phy_cell.pci; }
void set_rsrp(float rsrp_)
{
if (!std::isnan(rsrp_)) {
rsrp = rsrp_;
}
gettimeofday(&last_update, nullptr);
}
void set_rsrq(float rsrq_)
{
if (!std::isnan(rsrq_)) {
rsrq = rsrq_;
}
}
void set_cfo(float cfo_Hz_)
{
if (not std::isnan(cfo_Hz_) && not std::isinf(cfo_Hz_)) {
phy_cell.cfo_hz = cfo_Hz_;
}
}
float get_rsrp() const { return rsrp; }
float get_rsrq() const { return rsrq; }
float get_cfo_hz() const { return phy_cell.cfo_hz; }
void set_sib1(asn1::rrc::sib_type1_s* sib1_);
void set_sib2(asn1::rrc::sib_type2_s* sib2_);
void set_sib3(asn1::rrc::sib_type3_s* sib3_);
void set_sib13(asn1::rrc::sib_type13_r9_s* sib13_);
// TODO: replace with TTI count
uint32_t timeout_secs(struct timeval now)
{
struct timeval t[3];
memcpy(&t[2], &now, sizeof(struct timeval));
memcpy(&t[1], &last_update, sizeof(struct timeval));
get_time_interval(t);
return t[0].tv_sec;
}
asn1::rrc::sib_type1_s* sib1ptr() { return &sib1; }
asn1::rrc::sib_type2_s* sib2ptr() { return &sib2; }
asn1::rrc::sib_type3_s* sib3ptr() { return &sib3; }
asn1::rrc::sib_type13_r9_s* sib13ptr() { return &sib13; }
uint32_t get_cell_id() const { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); }
bool has_sib1() { return has_valid_sib1; }
bool has_sib2() { return has_valid_sib2; }
bool has_sib3() { return has_valid_sib3; }
bool has_sib13() { return has_valid_sib13; }
bool has_sib(uint32_t index)
{
switch (index) {
case 0:
return has_sib1();
case 1:
return has_sib2();
case 2:
return has_sib3();
case 12:
return has_sib13();
}
return false;
}
void reset_sibs()
{
has_valid_sib1 = false;
has_valid_sib2 = false;
has_valid_sib3 = false;
has_valid_sib13 = false;
}
uint16_t get_mcc()
{
uint16_t mcc;
if (has_valid_sib1) {
if (sib1.cell_access_related_info.plmn_id_list.size() > 0) {
if (srslte::bytes_to_mcc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mcc[0], &mcc)) {
return mcc;
}
}
}
return 0;
}
uint16_t get_mnc()
{
uint16_t mnc;
if (has_valid_sib1) {
if (sib1.cell_access_related_info.plmn_id_list.size() > 0) {
if (srslte::bytes_to_mnc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc[0],
&mnc,
sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc.size())) {
return mnc;
}
}
}
return 0;
}
std::string to_string() const
{
char buf[256];
snprintf(buf,
256,
"{cell_id: 0x%x, pci: %d, dl_earfcn: %d, rsrp=%+.1f, cfo=%+.1f}",
get_cell_id(),
get_pci(),
get_earfcn(),
get_rsrp(),
get_cfo_hz());
return std::string{buf};
}
bool is_sib_scheduled(uint32_t sib_index) const;
phy_interface_rrc_lte::phy_cell_t phy_cell = {};
bool has_mcch = false;
asn1::rrc::sib_type1_s sib1;
asn1::rrc::sib_type2_s sib2;
asn1::rrc::sib_type3_s sib3;
asn1::rrc::sib_type13_r9_s sib13;
asn1::rrc::mcch_msg_s mcch;
private:
float rsrp = NAN;
float rsrq = NAN;
struct timeval last_update = {};
bool has_valid_sib1 = false;
bool has_valid_sib2 = false;
bool has_valid_sib3 = false;
bool has_valid_sib13 = false;
std::map<uint32_t, uint32_t> sib_info_map; ///< map of sib_index to index of schedInfoList in SIB1
};
class rrc : public rrc_interface_nas,
public rrc_interface_phy_lte,
public rrc_interface_mac,
@ -299,7 +91,7 @@ public:
void get_metrics(rrc_metrics_t& m);
// Timeout callback interface
void timer_expired(uint32_t timeout_id);
void timer_expired(uint32_t timeout_id) final;
void srslte_rrc_log(const char* str);
typedef enum { Rx = 0, Tx } direction_t;

View File

@ -0,0 +1,136 @@
/*
* Copyright 2013-2020 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 SRSLTE_RRC_CELL_H
#define SRSLTE_RRC_CELL_H
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/asn1/rrc_asn1_utils.h"
#include "srslte/interfaces/ue_interfaces.h"
namespace srsue {
class cell_t
{
public:
cell_t() { gettimeofday(&last_update, nullptr); }
explicit cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell_) : cell_t() { phy_cell = phy_cell_; }
// comparison based on pci and earfcn
bool is_valid() { return phy_cell.earfcn != 0 && srslte_cellid_isvalid(phy_cell.pci); }
bool equals(const cell_t& x) { return equals(x.phy_cell.earfcn, x.phy_cell.pci); }
bool equals(uint32_t earfcn, uint32_t pci) { return earfcn == phy_cell.earfcn && pci == phy_cell.pci; }
// NaN means an RSRP value has not yet been obtained. Keep then in the list and clean them if never updated
bool greater(cell_t* x) { return rsrp > x->rsrp || std::isnan(rsrp); }
bool has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const;
uint32_t nof_plmns() const { return has_sib1() ? sib1.cell_access_related_info.plmn_id_list.size() : 0; }
srslte::plmn_id_t get_plmn(uint32_t idx) const;
uint16_t get_tac() const { return has_sib1() ? (uint16_t)sib1.cell_access_related_info.tac.to_number() : 0; }
uint32_t get_earfcn() const { return phy_cell.earfcn; }
uint32_t get_pci() const { return phy_cell.pci; }
void set_rsrp(float rsrp_)
{
if (!std::isnan(rsrp_)) {
rsrp = rsrp_;
}
gettimeofday(&last_update, nullptr);
}
void set_rsrq(float rsrq_)
{
if (!std::isnan(rsrq_)) {
rsrq = rsrq_;
}
}
void set_cfo(float cfo_Hz_)
{
if (not std::isnan(cfo_Hz_) && not std::isinf(cfo_Hz_)) {
phy_cell.cfo_hz = cfo_Hz_;
}
}
float get_rsrp() const { return rsrp; }
float get_rsrq() const { return rsrq; }
float get_cfo_hz() const { return phy_cell.cfo_hz; }
// TODO: replace with TTI count
uint32_t timeout_secs(struct timeval now) const;
void set_sib1(const asn1::rrc::sib_type1_s& sib1_);
void set_sib2(const asn1::rrc::sib_type2_s& sib2_);
void set_sib3(const asn1::rrc::sib_type3_s& sib3_);
void set_sib13(const asn1::rrc::sib_type13_r9_s& sib13_);
const asn1::rrc::sib_type1_s* sib1ptr() const { return has_sib1() ? &sib1 : nullptr; }
const asn1::rrc::sib_type2_s* sib2ptr() const { return has_sib2() ? &sib2 : nullptr; }
const asn1::rrc::sib_type3_s* sib3ptr() const { return has_sib3() ? &sib3 : nullptr; }
const asn1::rrc::sib_type13_r9_s* sib13ptr() const { return has_sib13() ? &sib13 : nullptr; }
uint32_t get_cell_id() const { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); }
bool has_sib(uint32_t index) const;
bool has_sib1() const { return has_valid_sib1; }
bool has_sib2() const { return has_valid_sib2; }
bool has_sib3() const { return has_valid_sib3; }
bool has_sib13() const { return has_valid_sib13; }
void reset_sibs()
{
has_valid_sib1 = false;
has_valid_sib2 = false;
has_valid_sib3 = false;
has_valid_sib13 = false;
}
uint16_t get_mcc() const;
uint16_t get_mnc() const;
std::string to_string() const;
bool is_sib_scheduled(uint32_t sib_index) const;
phy_interface_rrc_lte::phy_cell_t phy_cell = {0, 0, 0};
bool has_mcch = false;
asn1::rrc::sib_type1_s sib1 = {};
asn1::rrc::sib_type2_s sib2 = {};
asn1::rrc::sib_type3_s sib3 = {};
asn1::rrc::sib_type13_r9_s sib13 = {};
asn1::rrc::mcch_msg_s mcch = {};
private:
float rsrp = NAN;
float rsrq = NAN;
struct timeval last_update = {};
bool has_valid_sib1 = false;
bool has_valid_sib2 = false;
bool has_valid_sib3 = false;
bool has_valid_sib13 = false;
std::map<uint32_t, uint32_t> sib_info_map; ///< map of sib_index to index of schedInfoList in SIB1
};
} // namespace srsue
#endif // SRSLTE_RRC_CELL_H

View File

@ -18,7 +18,7 @@
# and at http://www.gnu.org/licenses/.
#
set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc)
set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc rrc_cell.cc)
add_library(srsue_rrc STATIC ${SOURCES})
if(ENABLE_5GNR)

View File

@ -45,40 +45,6 @@ namespace srsue {
const static uint32_t NOF_REQUIRED_SIBS = 4;
const static uint32_t required_sibs[NOF_REQUIRED_SIBS] = {0, 1, 2, 12}; // SIB1, SIB2, SIB3 and SIB13 (eMBMS)
void cell_t::set_sib1(asn1::rrc::sib_type1_s* sib1_)
{
sib1 = *sib1_;
has_valid_sib1 = true;
sib_info_map.clear();
for (uint32_t i = 0; i < sib1.sched_info_list.size(); ++i) {
for (uint32_t j = 0; j < sib1.sched_info_list[i].sib_map_info.size(); ++j) {
sib_info_map.insert(std::make_pair(sib1.sched_info_list[i].sib_map_info[j].to_number() - 1, i));
}
}
}
void cell_t::set_sib2(asn1::rrc::sib_type2_s* sib2_)
{
sib2 = *sib2_;
has_valid_sib2 = true;
}
void cell_t::set_sib3(asn1::rrc::sib_type3_s* sib3_)
{
sib3 = *sib3_;
has_valid_sib3 = true;
}
void cell_t::set_sib13(asn1::rrc::sib_type13_r9_s* sib13_)
{
sib13 = *sib13_;
has_valid_sib13 = true;
}
bool cell_t::is_sib_scheduled(uint32_t sib_index) const
{
return sib_info_map.find(sib_index) != sib_info_map.end();
}
/*******************************************************************************
Base functions
*******************************************************************************/
@ -1361,7 +1327,7 @@ void rrc::parse_pdu_bcch_dlsch(unique_byte_buffer_t pdu)
if (dlsch_msg.msg.c1().type() == bcch_dl_sch_msg_type_c::c1_c_::types::sib_type1) {
rrc_log->info("Processing SIB1 (1/1)\n");
serving_cell->set_sib1(&dlsch_msg.msg.c1().sib_type1());
serving_cell->set_sib1(dlsch_msg.msg.c1().sib_type1());
si_acquirer.trigger(si_acquire_proc::sib_received_ev{});
handle_sib1();
} else {
@ -1372,21 +1338,21 @@ void rrc::parse_pdu_bcch_dlsch(unique_byte_buffer_t pdu)
switch (sib_list[i].type().value) {
case sib_info_item_c::types::sib2:
if (not serving_cell->has_sib2()) {
serving_cell->set_sib2(&sib_list[i].sib2());
serving_cell->set_sib2(sib_list[i].sib2());
si_acquirer.trigger(si_acquire_proc::sib_received_ev{});
}
handle_sib2();
break;
case sib_info_item_c::types::sib3:
if (not serving_cell->has_sib3()) {
serving_cell->set_sib3(&sib_list[i].sib3());
serving_cell->set_sib3(sib_list[i].sib3());
si_acquirer.trigger(si_acquire_proc::sib_received_ev{});
}
handle_sib3();
break;
case sib_info_item_c::types::sib13_v920:
if (not serving_cell->has_sib13()) {
serving_cell->set_sib13(&sib_list[i].sib13_v920());
serving_cell->set_sib13(sib_list[i].sib13_v920());
si_acquirer.trigger(si_acquire_proc::sib_received_ev{});
}
handle_sib13();
@ -1400,7 +1366,7 @@ void rrc::parse_pdu_bcch_dlsch(unique_byte_buffer_t pdu)
void rrc::handle_sib1()
{
sib_type1_s* sib1 = serving_cell->sib1ptr();
const sib_type1_s* sib1 = serving_cell->sib1ptr();
rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n",
serving_cell->get_cell_id() & 0xfff,
sib1->si_win_len.to_number(),
@ -1428,7 +1394,7 @@ void rrc::handle_sib2()
{
rrc_log->info("SIB2 received\n");
sib_type2_s* sib2 = serving_cell->sib2ptr();
const sib_type2_s* sib2 = serving_cell->sib2ptr();
// Apply RACH and timeAlginmentTimer configuration
set_mac_cfg_t_rach_cfg_common(&current_mac_cfg, sib2->rr_cfg_common.rach_cfg_common);
@ -1496,7 +1462,7 @@ void rrc::handle_sib3()
{
rrc_log->info("SIB3 received\n");
sib_type3_s* sib3 = serving_cell->sib3ptr();
const sib_type3_s* sib3 = serving_cell->sib3ptr();
// cellReselectionInfoCommon
cell_resel_cfg.q_hyst = sib3->cell_resel_info_common.q_hyst.to_number();
@ -1517,7 +1483,7 @@ void rrc::handle_sib13()
{
rrc_log->info("SIB13 received\n");
sib_type13_r9_s* sib13 = serving_cell->sib13ptr();
const sib_type13_r9_s* sib13 = serving_cell->sib13ptr();
phy->set_config_mbsfn_sib13(srslte::make_sib13(*sib13));
add_mrb(0, 0); // Add MRB0

View File

@ -0,0 +1,149 @@
/*
* Copyright 2013-2020 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/stack/rrc/rrc_cell.h"
namespace srsue {
srslte::plmn_id_t cell_t::get_plmn(uint32_t idx) const
{
if (idx < sib1.cell_access_related_info.plmn_id_list.size() && has_valid_sib1) {
return srslte::make_plmn_id_t(sib1.cell_access_related_info.plmn_id_list[idx].plmn_id);
} else {
return {};
}
}
void cell_t::set_sib1(const asn1::rrc::sib_type1_s& sib1_)
{
sib1 = sib1_;
has_valid_sib1 = true;
sib_info_map.clear();
for (uint32_t i = 0; i < sib1.sched_info_list.size(); ++i) {
for (uint32_t j = 0; j < sib1.sched_info_list[i].sib_map_info.size(); ++j) {
sib_info_map.insert(std::make_pair(sib1.sched_info_list[i].sib_map_info[j].to_number() - 1, i));
}
}
}
void cell_t::set_sib2(const asn1::rrc::sib_type2_s& sib2_)
{
sib2 = sib2_;
has_valid_sib2 = true;
}
void cell_t::set_sib3(const asn1::rrc::sib_type3_s& sib3_)
{
sib3 = sib3_;
has_valid_sib3 = true;
}
void cell_t::set_sib13(const asn1::rrc::sib_type13_r9_s& sib13_)
{
sib13 = sib13_;
has_valid_sib13 = true;
}
bool cell_t::is_sib_scheduled(uint32_t sib_index) const
{
return sib_info_map.find(sib_index) != sib_info_map.end();
}
uint32_t cell_t::timeout_secs(struct timeval now) const
{
struct timeval t[3];
memcpy(&t[2], &now, sizeof(struct timeval));
memcpy(&t[1], &last_update, sizeof(struct timeval));
get_time_interval(t);
return t[0].tv_sec;
}
bool cell_t::has_sib(uint32_t index) const
{
switch (index) {
case 0:
return has_sib1();
case 1:
return has_sib2();
case 2:
return has_sib3();
case 12:
return has_sib13();
default:
break;
}
return false;
}
std::string cell_t::to_string() const
{
char buf[256];
snprintf(buf,
256,
"{cell_id: 0x%x, pci: %d, dl_earfcn: %d, rsrp=%+.1f, cfo=%+.1f}",
get_cell_id(),
get_pci(),
get_earfcn(),
get_rsrp(),
get_cfo_hz());
return std::string{buf};
}
bool cell_t::has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const
{
if (has_valid_sib1) {
for (const auto& e : sib1.cell_access_related_info.plmn_id_list) {
if (plmn_id.mcc == e.plmn_id.mcc && plmn_id.mnc == e.plmn_id.mnc) {
return true;
}
}
}
return false;
}
uint16_t cell_t::get_mcc() const
{
uint16_t mcc;
if (has_valid_sib1) {
if (sib1.cell_access_related_info.plmn_id_list.size() > 0) {
if (srslte::bytes_to_mcc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mcc[0], &mcc)) {
return mcc;
}
}
}
return 0;
}
uint16_t cell_t::get_mnc() const
{
uint16_t mnc;
if (has_valid_sib1) {
if (sib1.cell_access_related_info.plmn_id_list.size() > 0) {
if (srslte::bytes_to_mnc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc[0],
&mnc,
sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc.size())) {
return mnc;
}
}
}
return 0;
}
} // namespace srsue

View File

@ -548,7 +548,7 @@ proc_outcome_t rrc::cell_selection_proc::start_serv_cell_selection()
Info("Not camping on serving cell %s. Selecting it...\n", rrc_ptr->serving_cell->to_string().c_str());
state = search_state_t::serv_cell_camp;
if (not rrc_ptr->phy_cell_selector.launch(rrc_ptr->serving_cell->phy_cell)) {
if (not rrc_ptr->phy_cell_selector.launch(*rrc_ptr->serving_cell)) {
Error("Failed to launch PHY Cell Selection\n");
return proc_outcome_t::error;
}
@ -580,7 +580,7 @@ proc_outcome_t rrc::cell_selection_proc::start_cell_selection()
Info("Selected cell: %s\n", rrc_ptr->serving_cell->to_string().c_str());
state = search_state_t::cell_selection;
if (not rrc_ptr->phy_cell_selector.launch(rrc_ptr->serving_cell->phy_cell)) {
if (not rrc_ptr->phy_cell_selector.launch(*rrc_ptr->serving_cell)) {
Error("Failed to launch PHY Cell Selection\n");
return proc_outcome_t::error;
}