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

master
Francisco Paisana 5 years ago
parent d48a45976e
commit 58a9610efa

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

@ -40,8 +40,7 @@ phy_controller::phy_controller(srsue::phy_interface_rrc_lte* phy_, srsue::stack_
* PHY Cell Select Procedure * PHY Cell Select Procedure
*************************************/ *************************************/
bool phy_controller::start_cell_select(const phy_cell_t& phy_cell, bool phy_controller::start_cell_select(const phy_cell_t& phy_cell, const srslte::event_callback<bool>& on_complete)
const srslte::event_callback<cell_sel_res>& on_complete)
{ {
trigger(cell_sel_cmd{phy_cell, on_complete}); trigger(cell_sel_cmd{phy_cell, on_complete});
if (not is_in_state<selecting_cell>()) { 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) bool phy_controller::cell_selection_completed(bool outcome)
{ {
return trigger(outcome); return trigger(cell_sel_res{outcome});
} }
void phy_controller::in_sync() void phy_controller::in_sync()
{ {
bool is_selecting_cell = is_in_state<selecting_cell>();
trigger(in_sync_ev{}); 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_) 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) void phy_controller::selecting_cell::enter(phy_controller* f, const cell_sel_cmd& ev)
{ {
target_cell = ev.phy_cell; target_cell = ev.phy_cell;
f->csel_callback = ev.callback; csel_callback = ev.callback;
result = false; csel_res.result = false;
f->log_h->info("Starting \"%s\" for pci=%d, earfcn=%d\n", f->log_h->info("Starting \"%s\" for pci=%d, earfcn=%d\n",
srslte::get_type_name(*this).c_str(), 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(); 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()); log_h->info("Cell %s successfully selected\n", to_string(target_cell).c_str());
} else { } else {
log_h->warning("Failed to select cell %s\n", to_string(target_cell).c_str()); 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) 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->wait_in_sync_timer.set(wait_sync_timeout_ms, [f](uint32_t tid) { f->parent_fsm()->trigger(timeout_ev{}); });
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.run(); 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 //! 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) 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>()) { if (not is_in_state<searching_cell>()) {
log_h->warning("Failed to launch cell search\n"); log_h->warning("Failed to launch cell search\n");
return false; 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) void phy_controller::searching_cell::enter(phy_controller* f, const cell_search_cmd& cmd)
{ {
f->log_h->info("Initiated Cell search\n"); 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(); 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) // TODO: check what errors can happen (currently not handled in our code)
} }
// Forward cell search result to be handled in next state // Signal result back to FSM that called cell search
// trigger(result); 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"); log_h->info("Cell Search already running. Re-utilizing result.\n");
csearch_callbacks.emplace_back(callback); csearch_callbacks.emplace_back(cmd.callback);
} }
} // namespace srsue } // namespace srsue

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

@ -59,7 +59,7 @@ int test_phy_ctrl_fsm()
TESTASSERT(phy_ctrl.start_cell_search(cell_sel_callback)); TESTASSERT(phy_ctrl.start_cell_search(cell_sel_callback));
TESTASSERT(not phy_ctrl.is_in_sync()); 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(); phy_ctrl.in_sync();
TESTASSERT(not phy_ctrl.is_in_sync()); TESTASSERT(not phy_ctrl.is_in_sync());
phy_ctrl.out_sync(); phy_ctrl.out_sync();
@ -72,6 +72,9 @@ int test_phy_ctrl_fsm()
found_cell.earfcn = 2; found_cell.earfcn = 2;
phy_ctrl.cell_search_completed(cs_ret, found_cell); phy_ctrl.cell_search_completed(cs_ret, found_cell);
TESTASSERT(phy_ctrl.current_state_name() != "searching_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_present);
TESTASSERT(csearch_res.cs_ret.found == cs_ret.found); TESTASSERT(csearch_res.cs_ret.found == cs_ret.found);
TESTASSERT(csearch_res.found_cell.pci == found_cell.pci); TESTASSERT(csearch_res.found_cell.pci == found_cell.pci);
@ -105,6 +108,9 @@ int test_phy_ctrl_fsm()
phy_ctrl.in_sync(); phy_ctrl.in_sync();
TESTASSERT(phy_ctrl.is_in_sync()); TESTASSERT(phy_ctrl.is_in_sync());
TESTASSERT(phy_ctrl.current_state_name() != "selecting_cell"); TESTASSERT(phy_ctrl.current_state_name() != "selecting_cell");
// TEST: Propagation of cell selection result to caller
stack.run_tti();
TESTASSERT(cell_select_success == 1); TESTASSERT(cell_select_success == 1);
// TEST: Cell Selection with timeout being reached // TEST: Cell Selection with timeout being reached
@ -120,6 +126,9 @@ int test_phy_ctrl_fsm()
stack.run_tti(); stack.run_tti();
} }
TESTASSERT(phy_ctrl.current_state_name() != "selecting_cell"); TESTASSERT(phy_ctrl.current_state_name() != "selecting_cell");
// TEST: Propagation of cell selection result to caller
stack.run_tti();
TESTASSERT(cell_select_success == 0); TESTASSERT(cell_select_success == 0);
test_log->info("Finished RRC PHY controller test successfully\n"); test_log->info("Finished RRC PHY controller test successfully\n");

Loading…
Cancel
Save