|
|
@ -23,7 +23,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
namespace srsue {
|
|
|
|
namespace srsue {
|
|
|
|
|
|
|
|
|
|
|
|
#define MIN_IN_SYNC_POWER (-100)
|
|
|
|
#define MIN_IN_SYNC_POWER (-120.0)
|
|
|
|
#define DEFAULT_RSRQ (-3.0)
|
|
|
|
#define DEFAULT_RSRQ (-3.0)
|
|
|
|
|
|
|
|
|
|
|
|
lte_ttcn3_phy::lte_ttcn3_phy(srslte::logger* logger_) : logger(logger_) {}
|
|
|
|
lte_ttcn3_phy::lte_ttcn3_phy(srslte::logger* logger_) : logger(logger_) {}
|
|
|
@ -72,19 +72,6 @@ void lte_ttcn3_phy::set_cell_map(const cell_list_t& cells_)
|
|
|
|
cells = cells_;
|
|
|
|
cells = cells_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// The interface for RRC
|
|
|
|
|
|
|
|
void lte_ttcn3_phy::get_current_cell(srslte_cell_t* cell_, uint32_t* earfcn_)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cell_) {
|
|
|
|
|
|
|
|
memcpy(cell_, &pcell.info, sizeof(srslte_cell_t));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (earfcn_) {
|
|
|
|
|
|
|
|
*earfcn_ = pcell.earfcn;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t lte_ttcn3_phy::get_current_earfcn()
|
|
|
|
uint32_t lte_ttcn3_phy::get_current_earfcn()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return pcell.earfcn;
|
|
|
|
return pcell.earfcn;
|
|
|
@ -130,43 +117,39 @@ int lte_ttcn3_phy::meas_stop(uint32_t earfcn, int pci)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void lte_ttcn3_phy::select_pcell()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// select strongest cell as PCell
|
|
|
|
|
|
|
|
float max_power = -145;
|
|
|
|
|
|
|
|
int max_index = 0;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < cells.size(); ++i) {
|
|
|
|
|
|
|
|
if (cells[i].power > max_power) {
|
|
|
|
|
|
|
|
max_power = cells[i].power;
|
|
|
|
|
|
|
|
max_index = i;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
pcell = cells[max_index];
|
|
|
|
|
|
|
|
log.info("Setting PCell to EARFCN=%d CellId=%d with RS power=%.2f\n", pcell.earfcn, pcell.info.id, pcell.power);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Cell search and selection procedures */
|
|
|
|
/* Cell search and selection procedures */
|
|
|
|
phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* found_cell)
|
|
|
|
phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* found_cell)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
|
|
|
|
|
|
|
select_pcell();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log.info("Running cell search in PHY\n");
|
|
|
|
log.info("Running cell search in PHY\n");
|
|
|
|
|
|
|
|
|
|
|
|
cell_search_ret_t ret = {};
|
|
|
|
cell_search_ret_t ret = {};
|
|
|
|
|
|
|
|
ret.found = cell_search_ret_t::CELL_NOT_FOUND;
|
|
|
|
|
|
|
|
|
|
|
|
// Consider cell found if Pcell power >= -100dBm
|
|
|
|
if (not cells.empty() && cell_idx < cells.size()) {
|
|
|
|
if (pcell.power >= MIN_IN_SYNC_POWER) {
|
|
|
|
log.info("Found Cell: EARFCN=%d CellId=%d\n", cells[cell_idx].earfcn, cells[cell_idx].info.id);
|
|
|
|
if (found_cell) {
|
|
|
|
if (found_cell) {
|
|
|
|
found_cell->earfcn = pcell.earfcn;
|
|
|
|
found_cell->earfcn = cells[cell_idx].earfcn;
|
|
|
|
found_cell->pci = pcell.info.id;
|
|
|
|
found_cell->pci = cells[cell_idx].info.id;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ret.found = cell_search_ret_t::CELL_FOUND;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// advance index
|
|
|
|
|
|
|
|
cell_idx++;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cell_idx < cells.size()) {
|
|
|
|
|
|
|
|
// more cells will be reported
|
|
|
|
|
|
|
|
ret.last_freq = cell_search_ret_t::MORE_FREQS;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// all available cells have been reported, reset cell index
|
|
|
|
|
|
|
|
ret.last_freq = cell_search_ret_t::NO_MORE_FREQS;
|
|
|
|
|
|
|
|
cell_idx = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret.found = cell_search_ret_t::CELL_FOUND;
|
|
|
|
|
|
|
|
ret.last_freq = cell_search_ret_t::NO_MORE_FREQS;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// no suitable cell found
|
|
|
|
log.warning("No cells configured yet.\n");
|
|
|
|
ret.found = cell_search_ret_t::CELL_NOT_FOUND;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -175,17 +158,31 @@ bool lte_ttcn3_phy::cell_select(phy_cell_t* rrc_cell)
|
|
|
|
// try to find RRC cell in current cell map
|
|
|
|
// try to find RRC cell in current cell map
|
|
|
|
for (auto& cell : cells) {
|
|
|
|
for (auto& cell : cells) {
|
|
|
|
if (cell.info.id == rrc_cell->pci) {
|
|
|
|
if (cell.info.id == rrc_cell->pci) {
|
|
|
|
pcell = cell;
|
|
|
|
if (cell.power >= MIN_IN_SYNC_POWER) {
|
|
|
|
return true;
|
|
|
|
pcell = cell;
|
|
|
|
|
|
|
|
pcell_set = true;
|
|
|
|
|
|
|
|
syssim->select_cell(pcell.info);
|
|
|
|
|
|
|
|
log.info("Select PCell with %.2f on PCI=%d on EARFCN=%d.\n", cell.power, rrc_cell->pci, rrc_cell->earfcn);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
pcell_set = false;
|
|
|
|
|
|
|
|
log.error("Power of selected cell too low (%.2f < %.2f)\n", cell.power, MIN_IN_SYNC_POWER);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return pcell_set;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log.error("Couldn't fine RRC cell with PCI=%d on EARFCN=%d in cell map.\n", rrc_cell->pci, rrc_cell->earfcn);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
bool lte_ttcn3_phy::cell_is_camping()
|
|
|
|
bool lte_ttcn3_phy::cell_is_camping()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return (pcell.power >= MIN_IN_SYNC_POWER);
|
|
|
|
if (pcell_set) {
|
|
|
|
|
|
|
|
log.info("pcell.power=%2.f\n", pcell.power);
|
|
|
|
|
|
|
|
return (pcell.power >= MIN_IN_SYNC_POWER);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void lte_ttcn3_phy::reset()
|
|
|
|
void lte_ttcn3_phy::reset()
|
|
|
@ -369,21 +366,33 @@ void lte_ttcn3_phy::run_tti()
|
|
|
|
m.earfcn = cell.earfcn;
|
|
|
|
m.earfcn = cell.earfcn;
|
|
|
|
m.rsrp = cell.power;
|
|
|
|
m.rsrp = cell.power;
|
|
|
|
m.rsrq = DEFAULT_RSRQ;
|
|
|
|
m.rsrq = DEFAULT_RSRQ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Measurement for PCell needs to have EARFCN set to 0
|
|
|
|
|
|
|
|
if (pcell_set && m.earfcn == pcell.earfcn) {
|
|
|
|
|
|
|
|
m.earfcn = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log.debug("Create cell measurement for PCI=%d, EARFCN=%d with RSRP=%.2f\n", m.pci, m.earfcn, m.rsrp);
|
|
|
|
phy_meas.push_back(m);
|
|
|
|
phy_meas.push_back(m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
stack->new_cell_meas(phy_meas);
|
|
|
|
|
|
|
|
|
|
|
|
if (not phy_meas.empty()) {
|
|
|
|
|
|
|
|
stack->new_cell_meas(phy_meas);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// check if Pcell is in sync
|
|
|
|
// check if Pcell is in sync
|
|
|
|
for (auto& cell : cells) {
|
|
|
|
if (pcell_set) {
|
|
|
|
if (cell.info.id == pcell.info.id) {
|
|
|
|
for (auto& cell : cells) {
|
|
|
|
if (cell.power >= MIN_IN_SYNC_POWER) {
|
|
|
|
if (cell.info.id == pcell.info.id) {
|
|
|
|
log.debug("PCell id=%d power=%.2f -> sync\n", pcell.info.id, cell.power);
|
|
|
|
if (cell.power >= MIN_IN_SYNC_POWER) {
|
|
|
|
stack->in_sync();
|
|
|
|
log.debug("PCell id=%d power=%.2f -> sync\n", pcell.info.id, cell.power);
|
|
|
|
} else {
|
|
|
|
stack->in_sync();
|
|
|
|
log.debug("PCell id=%d power=%.2f -> out of sync\n", pcell.info.id, cell.power);
|
|
|
|
} else {
|
|
|
|
stack->out_of_sync();
|
|
|
|
log.debug("PCell id=%d power=%.2f -> out of sync\n", pcell.info.id, cell.power);
|
|
|
|
|
|
|
|
stack->out_of_sync();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break; // make sure to call stack only once
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break; // make sure to call stack only once
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|