use of stack event loop to propagate cell search and selection results

This commit is contained in:
Francisco Paisana 2020-07-08 11:45:26 +01:00
parent d48a45976e
commit 58a9610efa
4 changed files with 74 additions and 60 deletions

View File

@ -41,19 +41,23 @@ public:
cell_search_ret_t cs_ret;
phy_cell_t found_cell;
};
using cell_sel_res = bool;
struct cell_sel_cmd {
phy_cell_t phy_cell;
srslte::event_callback<cell_sel_res> callback;
struct cell_sel_res {
bool result;
};
struct cell_sel_cmd {
phy_cell_t phy_cell;
srslte::event_callback<bool> callback;
};
struct cell_search_cmd {
srslte::event_callback<cell_srch_res> callback;
};
using cell_search_cmd = srslte::event_callback<cell_srch_res>;
struct in_sync_ev {};
struct out_sync_ev {};
explicit phy_controller(phy_interface_rrc_lte* phy_, stack_interface_rrc* stack_);
// PHY procedures interfaces
bool start_cell_select(const phy_cell_t& phy_cell, const srslte::event_callback<cell_sel_res>& on_complete);
bool start_cell_select(const phy_cell_t& phy_cell, const srslte::event_callback<bool>& on_complete);
bool start_cell_search(const srslte::event_callback<cell_srch_res>& on_complete);
bool cell_search_completed(cell_search_ret_t cs_ret, phy_cell_t found_cell);
bool cell_selection_completed(bool outcome);
@ -71,7 +75,7 @@ public:
struct selecting_cell : public subfsm_t<selecting_cell> {
struct timeout_ev {};
struct wait_result {};
struct wait_csel_res {};
struct wait_in_sync {
void enter(selecting_cell* f, const cell_sel_res& ev);
};
@ -82,24 +86,25 @@ public:
srslte::timer_handler::unique_timer wait_in_sync_timer;
phy_cell_t target_cell = {};
cell_sel_res result = {};
cell_sel_res csel_res = {};
srslte::event_callback<bool> csel_callback;
protected:
// guard functions
bool is_cell_selected(wait_result& s, const cell_sel_res& ev) { return ev; }
bool is_cell_selected(wait_csel_res& s, const cell_sel_res& ev) { return ev.result; }
// event handlers
void set_success(wait_in_sync& s, const in_sync_ev& ev) { result = true; }
void set_success(wait_in_sync& s, const in_sync_ev& ev) { csel_res.result = true; }
state_list<wait_result, wait_in_sync> states{this};
state_list<wait_csel_res, wait_in_sync> states{this};
// clang-format off
using c = selecting_cell;
using transitions = transition_table<
// Start Target Event Action Guard
// +----------------+---------------+--------------+------------------+----------------------+
row< wait_result, wait_in_sync, cell_sel_res, nullptr, &c::is_cell_selected >,
row< wait_result, unknown_st, cell_sel_res >,
row< wait_csel_res, wait_in_sync, cell_sel_res, nullptr, &c::is_cell_selected >,
row< wait_csel_res, unknown_st, cell_sel_res >,
// +----------------+---------------+--------------+------------------+----------------------+
row< wait_in_sync, in_sync_st, in_sync_ev, &c::set_success >,
row< wait_in_sync, unknown_st, timeout_ev >
@ -116,7 +121,6 @@ private:
stack_interface_rrc* stack = nullptr;
std::vector<srslte::event_callback<cell_srch_res> > csearch_callbacks;
srslte::event_callback<cell_sel_res> csel_callback;
protected:
state_list<unknown_st, in_sync_st, out_sync_st, searching_cell, selecting_cell> states{this,
@ -133,24 +137,24 @@ protected:
// clang-format off
using c = phy_controller;
using transitions = transition_table<
// Start Target Event Action Guard
// +----------------+-----------------+------------------+------------------------------+---------------------+
row< unknown_st, selecting_cell, cell_sel_cmd >,
row< unknown_st, searching_cell, cell_search_cmd >,
row< unknown_st, in_sync_st, in_sync_ev >,
row< unknown_st, out_sync_st, out_sync_ev >,
// +----------------+-----------------+------------------+------------------------------+---------------------+
row< in_sync_st, selecting_cell, cell_sel_cmd >,
row< in_sync_st, searching_cell, cell_search_cmd >,
row< in_sync_st, out_sync_st, out_sync_ev >,
// +----------------+-----------------+------------------+------------------------------+---------------------+
row< out_sync_st, selecting_cell, cell_sel_cmd >,
row< out_sync_st, searching_cell, cell_search_cmd >,
row< out_sync_st, in_sync_st, in_sync_ev >,
// +----------------+-----------------+------------------+------------------------------+---------------------+
row< searching_cell, unknown_st, cell_srch_res, &c::handle_cell_search_res >,
upd< searching_cell, cell_search_cmd, &c::share_cell_search_res >
// +----------------+-----------------+------------------+------------------------------+---------------------+
// Start Target Event Action
// +----------------+-----------------+------------------+------------------------------+
row< unknown_st, selecting_cell, cell_sel_cmd >,
row< unknown_st, searching_cell, cell_search_cmd >,
row< unknown_st, in_sync_st, in_sync_ev >,
row< unknown_st, out_sync_st, out_sync_ev >,
// +----------------+-----------------+------------------+------------------------------+
row< in_sync_st, selecting_cell, cell_sel_cmd >,
row< in_sync_st, searching_cell, cell_search_cmd >,
row< in_sync_st, out_sync_st, out_sync_ev >,
// +----------------+-----------------+------------------+------------------------------+
row< out_sync_st, selecting_cell, cell_sel_cmd >,
row< out_sync_st, searching_cell, cell_search_cmd >,
row< out_sync_st, in_sync_st, in_sync_ev >,
// +----------------+-----------------+------------------+------------------------------+
row< searching_cell, unknown_st, cell_srch_res, &c::handle_cell_search_res >,
upd< searching_cell, cell_search_cmd, &c::share_cell_search_res >
// +----------------+-----------------+------------------+------------------------------+
>;
// clang-format on
};

View File

@ -40,8 +40,7 @@ phy_controller::phy_controller(srsue::phy_interface_rrc_lte* phy_, srsue::stack_
* PHY Cell Select Procedure
*************************************/
bool phy_controller::start_cell_select(const phy_cell_t& phy_cell,
const srslte::event_callback<cell_sel_res>& on_complete)
bool phy_controller::start_cell_select(const phy_cell_t& phy_cell, const srslte::event_callback<bool>& on_complete)
{
trigger(cell_sel_cmd{phy_cell, on_complete});
if (not is_in_state<selecting_cell>()) {
@ -53,17 +52,12 @@ bool phy_controller::start_cell_select(const phy_cell_t&
bool phy_controller::cell_selection_completed(bool outcome)
{
return trigger(outcome);
return trigger(cell_sel_res{outcome});
}
void phy_controller::in_sync()
{
bool is_selecting_cell = is_in_state<selecting_cell>();
trigger(in_sync_ev{});
if (is_selecting_cell and not is_in_state<selecting_cell>()) {
// Signal result back to FSM that called cell selection
csel_callback(get_state<selecting_cell>()->result);
}
}
phy_controller::selecting_cell::selecting_cell(phy_controller* parent_) : nested_fsm_t(parent_)
@ -73,9 +67,9 @@ phy_controller::selecting_cell::selecting_cell(phy_controller* parent_) : nested
void phy_controller::selecting_cell::enter(phy_controller* f, const cell_sel_cmd& ev)
{
target_cell = ev.phy_cell;
f->csel_callback = ev.callback;
result = false;
target_cell = ev.phy_cell;
csel_callback = ev.callback;
csel_res.result = false;
f->log_h->info("Starting \"%s\" for pci=%d, earfcn=%d\n",
srslte::get_type_name(*this).c_str(),
@ -88,21 +82,21 @@ void phy_controller::selecting_cell::exit(phy_controller* f)
{
wait_in_sync_timer.stop();
if (result) {
if (csel_res.result) {
log_h->info("Cell %s successfully selected\n", to_string(target_cell).c_str());
} else {
log_h->warning("Failed to select cell %s\n", to_string(target_cell).c_str());
}
// Signal result back to FSM that called cell selection
auto& copied_callback = csel_callback;
bool result = csel_res.result;
f->stack->defer_task([copied_callback, result]() { copied_callback(result); });
}
void phy_controller::selecting_cell::wait_in_sync::enter(selecting_cell* f, const cell_sel_res& ev)
{
f->wait_in_sync_timer.set(wait_sync_timeout_ms, [f](uint32_t tid) {
f->parent_fsm()->trigger(timeout_ev{});
if (not f->parent_fsm()->is_in_state<selecting_cell>()) {
f->parent_fsm()->csel_callback(false);
}
});
f->wait_in_sync_timer.set(wait_sync_timeout_ms, [f](uint32_t tid) { f->parent_fsm()->trigger(timeout_ev{}); });
f->wait_in_sync_timer.run();
}
@ -113,7 +107,7 @@ void phy_controller::selecting_cell::wait_in_sync::enter(selecting_cell* f, cons
//! Searches for a cell in the current frequency and retrieves SIB1 if not retrieved yet
bool phy_controller::start_cell_search(const srslte::event_callback<cell_srch_res>& on_complete)
{
trigger(on_complete);
trigger(cell_search_cmd{on_complete});
if (not is_in_state<searching_cell>()) {
log_h->warning("Failed to launch cell search\n");
return false;
@ -138,7 +132,7 @@ bool phy_controller::cell_search_completed(cell_search_ret_t cs_ret, phy_cell_t
void phy_controller::searching_cell::enter(phy_controller* f, const cell_search_cmd& cmd)
{
f->log_h->info("Initiated Cell search\n");
f->csearch_callbacks.emplace_back(cmd);
f->csearch_callbacks.emplace_back(cmd.callback);
f->stack->start_cell_search();
}
@ -156,14 +150,21 @@ void phy_controller::handle_cell_search_res(searching_cell& s, const cell_srch_r
// TODO: check what errors can happen (currently not handled in our code)
}
// Forward cell search result to be handled in next state
// trigger(result);
// Signal result back to FSM that called cell search
auto& moved_callbacks = csearch_callbacks;
stack->defer_task(std::bind(
[result](std::vector<srslte::event_callback<cell_srch_res> >& callbacks) {
for (auto& f : callbacks) {
f(result);
}
},
std::move(moved_callbacks)));
}
void phy_controller::share_cell_search_res(searching_cell& s, const cell_search_cmd& callback)
void phy_controller::share_cell_search_res(searching_cell& s, const cell_search_cmd& cmd)
{
log_h->info("Cell Search already running. Re-utilizing result.\n");
csearch_callbacks.emplace_back(callback);
csearch_callbacks.emplace_back(cmd.callback);
}
} // namespace srsue

View File

@ -45,9 +45,9 @@ rrc::cell_search_proc::cell_search_proc(rrc* parent_) : rrc_ptr(parent_) {}
proc_outcome_t rrc::cell_search_proc::init()
{
Info("Starting...\n");
state = state_t::phy_cell_search;
rrc_ptr->phy_ctrl->start_cell_search(
[this](const phy_controller::cell_srch_res& res) { rrc_ptr->cell_searcher.trigger(res); });
state = state_t::phy_cell_search;
auto on_complete = [this](const phy_controller::cell_srch_res& res) { rrc_ptr->cell_searcher.trigger(res); };
rrc_ptr->phy_ctrl->start_cell_search(on_complete);
if (not rrc_ptr->phy_ctrl->is_in_state<phy_controller::searching_cell>()) {
Warning("Failed to initiate Cell Search.\n");
return proc_outcome_t::error;

View File

@ -59,7 +59,7 @@ int test_phy_ctrl_fsm()
TESTASSERT(phy_ctrl.start_cell_search(cell_sel_callback));
TESTASSERT(not phy_ctrl.is_in_sync());
// TEST: Cell Search only listens to a cell search result event and calls provided callback on completion
// TEST: Cell Search only listens to a cell search result event
phy_ctrl.in_sync();
TESTASSERT(not phy_ctrl.is_in_sync());
phy_ctrl.out_sync();
@ -72,6 +72,9 @@ int test_phy_ctrl_fsm()
found_cell.earfcn = 2;
phy_ctrl.cell_search_completed(cs_ret, found_cell);
TESTASSERT(phy_ctrl.current_state_name() != "searching_cell");
// TEST: Check propagation of cell search result to caller
stack.run_tti();
TESTASSERT(csearch_res_present);
TESTASSERT(csearch_res.cs_ret.found == cs_ret.found);
TESTASSERT(csearch_res.found_cell.pci == found_cell.pci);
@ -105,6 +108,9 @@ int test_phy_ctrl_fsm()
phy_ctrl.in_sync();
TESTASSERT(phy_ctrl.is_in_sync());
TESTASSERT(phy_ctrl.current_state_name() != "selecting_cell");
// TEST: Propagation of cell selection result to caller
stack.run_tti();
TESTASSERT(cell_select_success == 1);
// TEST: Cell Selection with timeout being reached
@ -120,6 +126,9 @@ int test_phy_ctrl_fsm()
stack.run_tti();
}
TESTASSERT(phy_ctrl.current_state_name() != "selecting_cell");
// TEST: Propagation of cell selection result to caller
stack.run_tti();
TESTASSERT(cell_select_success == 0);
test_log->info("Finished RRC PHY controller test successfully\n");