integrated observer pattern into rrc phy ctrl fsm

master
Francisco Paisana 4 years ago
parent b2313e3631
commit 48dd436d86

@ -81,6 +81,8 @@ public:
return count;
}
void unsubscribe_all() { observers.clear(); }
//! Signal result to observers
void dispatch(Args... args)
{

@ -22,6 +22,7 @@
#ifndef SRSLTE_PHY_CONTROLLER_H
#define SRSLTE_PHY_CONTROLLER_H
#include "srslte/adt/observer.h"
#include "srslte/common/fsm.h"
#include "srslte/common/logmap.h"
#include "srslte/interfaces/ue_interfaces.h"
@ -45,30 +46,31 @@ public:
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;
phy_cell_t phy_cell;
};
struct cell_search_cmd {};
struct in_sync_ev {};
struct out_sync_ev {};
explicit phy_controller(phy_interface_rrc_lte* phy_, srslte::task_sched_handle task_sched_);
// PHY procedures interfaces
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);
bool start_cell_select(const phy_cell_t& phy_cell);
bool start_cell_search();
void cell_search_completed(cell_search_ret_t cs_ret, phy_cell_t found_cell);
void cell_selection_completed(bool outcome);
void in_sync();
void out_sync() { trigger(out_sync_ev{}); }
// Event Observers
srslte::event_dispatcher<cell_srch_res> cell_search_observers;
srslte::event_dispatcher<bool> cell_selection_observers;
// state getters
bool cell_is_camping() { return phy->cell_is_camping(); }
bool is_in_sync() const { return is_in_state<in_sync_st>(); }
// states
// FSM states
struct unknown_st {};
struct in_sync_st {};
struct out_sync_st {};
@ -87,7 +89,6 @@ public:
srslte::timer_handler::unique_timer wait_in_sync_timer;
phy_cell_t target_cell = {};
cell_sel_res csel_res = {};
srslte::event_callback<bool> csel_callback;
protected:
// guard functions
@ -113,15 +114,13 @@ public:
// clang-format on
};
struct searching_cell {
void enter(phy_controller* f, const cell_search_cmd& cmd);
void enter(phy_controller* f);
};
private:
phy_interface_rrc_lte* phy = nullptr;
srslte::task_sched_handle task_sched;
std::vector<srslte::event_callback<cell_srch_res> > csearch_callbacks;
protected:
state_list<unknown_st, in_sync_st, out_sync_st, searching_cell, selecting_cell> states{this,
unknown_st{},
@ -132,7 +131,6 @@ protected:
// event handlers
void handle_cell_search_res(searching_cell& s, const cell_srch_res& result);
void share_cell_search_res(searching_cell& s, const cell_search_cmd& cmd);
// clang-format off
using c = phy_controller;
@ -152,8 +150,7 @@ protected:
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 >
row< searching_cell, unknown_st, cell_srch_res, &c::handle_cell_search_res >
// +----------------+-----------------+------------------+------------------------------+
>;
// clang-format on

@ -36,13 +36,22 @@ phy_controller::phy_controller(srsue::phy_interface_rrc_lte* phy_, srslte::task_
task_sched(task_sched_)
{}
void phy_controller::in_sync()
{
trigger(in_sync_ev{});
}
/**************************************
* PHY Cell Select Procedure
*************************************/
bool phy_controller::start_cell_select(const phy_cell_t& phy_cell, const srslte::event_callback<bool>& on_complete)
bool phy_controller::start_cell_select(const phy_cell_t& phy_cell)
{
trigger(cell_sel_cmd{phy_cell, on_complete});
if (is_in_state<selecting_cell>()) {
log_h->warning("Failed to launch cell selection as it is already running\n");
return false;
}
trigger(cell_sel_cmd{phy_cell});
if (not is_in_state<selecting_cell>()) {
log_h->warning("Failed to launch cell selection. Current state: %s\n", current_state_name().c_str());
return false;
@ -50,14 +59,9 @@ bool phy_controller::start_cell_select(const phy_cell_t& phy_cell, const srslte:
return true;
}
bool phy_controller::cell_selection_completed(bool outcome)
void phy_controller::cell_selection_completed(bool outcome)
{
return trigger(cell_sel_res{outcome});
}
void phy_controller::in_sync()
{
trigger(in_sync_ev{});
trigger(cell_sel_res{outcome});
}
phy_controller::selecting_cell::selecting_cell(phy_controller* parent_) : composite_fsm_t(parent_)
@ -68,7 +72,6 @@ phy_controller::selecting_cell::selecting_cell(phy_controller* parent_) : compos
void phy_controller::selecting_cell::enter(phy_controller* f, const cell_sel_cmd& ev)
{
target_cell = ev.phy_cell;
csel_callback = ev.callback;
csel_res.result = false;
fsmInfo("Starting for pci=%d, earfcn=%d\n", target_cell.pci, target_cell.earfcn);
@ -91,7 +94,11 @@ void phy_controller::selecting_cell::exit(phy_controller* f)
}
// Signal result back to FSM that called cell selection
f->task_sched.defer_task(srslte::make_move_task(csel_callback, csel_res.result));
bool result = csel_res.result;
f->task_sched.defer_task([f, result]() {
f->cell_selection_observers.dispatch(result);
f->cell_selection_observers.unsubscribe_all();
});
}
void phy_controller::selecting_cell::wait_in_sync::enter(selecting_cell* f, const cell_sel_res& ev)
@ -105,9 +112,13 @@ 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)
bool phy_controller::start_cell_search()
{
trigger(cell_search_cmd{on_complete});
if (is_in_state<searching_cell>()) {
fsmInfo("Cell search already launched.\n");
return true;
}
trigger(cell_search_cmd{});
if (not is_in_state<searching_cell>()) {
fsmWarning("Failed to launch cell search\n");
return false;
@ -115,24 +126,14 @@ bool phy_controller::start_cell_search(const srslte::event_callback<cell_srch_re
return true;
}
bool phy_controller::cell_search_completed(cell_search_ret_t cs_ret, phy_cell_t found_cell)
void phy_controller::cell_search_completed(cell_search_ret_t cs_ret, phy_cell_t found_cell)
{
cell_srch_res res{cs_ret, found_cell};
if (trigger(res)) {
// Signal callers the result of cell search
for (auto& f : csearch_callbacks) {
f(res);
}
csearch_callbacks.clear();
return true;
}
return false;
trigger(cell_srch_res{cs_ret, found_cell});
}
void phy_controller::searching_cell::enter(phy_controller* f, const cell_search_cmd& cmd)
void phy_controller::searching_cell::enter(phy_controller* f)
{
otherfsmInfo(f, "Initiating Cell search\n");
f->csearch_callbacks.emplace_back(cmd.callback);
f->task_sched.enqueue_background_task([f](uint32_t worker_id) {
phy_interface_rrc_lte::phy_cell_t found_cell;
phy_interface_rrc_lte::cell_search_ret_t ret = f->phy->cell_search(&found_cell);
@ -156,13 +157,11 @@ void phy_controller::handle_cell_search_res(searching_cell& s, const cell_srch_r
}
// Signal result back to FSM that called cell search
task_sched.defer_task(srslte::make_move_task(std::move(csearch_callbacks), result));
}
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(cmd.callback);
auto copy = result;
task_sched.defer_task([this, copy]() {
cell_search_observers.dispatch(copy);
cell_search_observers.unsubscribe_all();
});
}
} // namespace srsue

@ -46,11 +46,11 @@ proc_outcome_t rrc::cell_search_proc::init()
{
Info("Starting...\n");
state = state_t::phy_cell_search;
rrc_ptr->phy_ctrl->start_cell_search(srslte::event_callback<phy_controller::cell_srch_res>{&rrc_ptr->cell_searcher});
if (not rrc_ptr->phy_ctrl->is_in_state<phy_controller::searching_cell>()) {
if (not rrc_ptr->phy_ctrl->start_cell_search()) {
Warning("Failed to initiate Cell Search.\n");
return proc_outcome_t::error;
}
rrc_ptr->phy_ctrl->cell_search_observers.subscribe(rrc_ptr->cell_searcher);
return proc_outcome_t::yield;
}
@ -98,11 +98,11 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_
// set new serving cell in PHY
state = state_t::phy_cell_select;
if (not rrc_ptr->phy_ctrl->start_cell_select(rrc_ptr->meas_cells.serving_cell().phy_cell,
srslte::event_callback<bool>{&rrc_ptr->cell_searcher})) {
if (not rrc_ptr->phy_ctrl->start_cell_select(rrc_ptr->meas_cells.serving_cell().phy_cell)) {
Error("Couldn't start phy cell selection\n");
return proc_outcome_t::error;
}
rrc_ptr->phy_ctrl->cell_selection_observers.subscribe(rrc_ptr->cell_searcher);
return proc_outcome_t::yield;
}
@ -511,11 +511,11 @@ proc_outcome_t rrc::cell_selection_proc::start_serv_cell_selection()
Info("Not camping on serving cell %s. Selecting it...\n", rrc_ptr->meas_cells.serving_cell().to_string().c_str());
state = search_state_t::serv_cell_camp;
if (not rrc_ptr->phy_ctrl->start_cell_select(rrc_ptr->meas_cells.serving_cell().phy_cell,
srslte::event_callback<bool>{&rrc_ptr->cell_selector})) {
if (not rrc_ptr->phy_ctrl->start_cell_select(rrc_ptr->meas_cells.serving_cell().phy_cell)) {
Error("Failed to launch PHY Cell Selection\n");
return proc_outcome_t::error;
}
rrc_ptr->phy_ctrl->cell_selection_observers.subscribe(rrc_ptr->cell_selector);
serv_cell_select_attempted = true;
return proc_outcome_t::yield;
}
@ -553,12 +553,11 @@ proc_outcome_t rrc::cell_selection_proc::start_cell_selection()
Info("Selected cell: %s\n", rrc_ptr->meas_cells.serving_cell().to_string().c_str());
state = search_state_t::cell_selection;
rrc_ptr->phy_ctrl->start_cell_select(rrc_ptr->meas_cells.serving_cell().phy_cell,
srslte::event_callback<bool>{&rrc_ptr->cell_selector});
if (not rrc_ptr->phy_ctrl->is_in_state<phy_controller::selecting_cell>()) {
if (not rrc_ptr->phy_ctrl->start_cell_select(rrc_ptr->meas_cells.serving_cell().phy_cell)) {
Error("Failed to launch PHY Cell Selection\n");
return proc_outcome_t::error;
}
rrc_ptr->phy_ctrl->cell_selection_observers.subscribe(rrc_ptr->cell_selector);
return proc_outcome_t::yield;
}
}
@ -1493,11 +1492,11 @@ srslte::proc_outcome_t rrc::ho_proc::step()
Info("Starting cell selection of target cell %s\n", target_cell->to_string().c_str());
rrc_ptr->phy_ctrl->start_cell_select(target_cell->phy_cell, srslte::event_callback<bool>{&rrc_ptr->ho_handler});
if (not rrc_ptr->phy_ctrl->is_in_state<phy_controller::selecting_cell>()) {
if (not rrc_ptr->phy_ctrl->start_cell_select(target_cell->phy_cell)) {
Error("Failed to launch the selection of target cell %s\n", target_cell->to_string().c_str());
return proc_outcome_t::error;
}
rrc_ptr->phy_ctrl->cell_selection_observers.subscribe(rrc_ptr->ho_handler);
state = wait_phy_cell_select_complete;
}
return proc_outcome_t::yield;

@ -83,7 +83,8 @@ int test_phy_ctrl_fsm()
TESTASSERT(phy_ctrl.is_in_sync());
// TEST: Correct initiation of Cell Search state
TESTASSERT(phy_ctrl.start_cell_search(srslte::event_callback<phy_controller::cell_srch_res>{&csearch_tester}));
TESTASSERT(phy_ctrl.start_cell_search());
phy_ctrl.cell_search_observers.subscribe(csearch_tester);
TESTASSERT(not phy_ctrl.is_in_sync());
// TEST: Cell Search only listens to a cell search result event
@ -111,14 +112,15 @@ int test_phy_ctrl_fsm()
phy_ctrl.out_sync();
// TEST: Correct initiation of Cell Select state
phy_ctrl.start_cell_select(found_cell, srslte::event_callback<bool>{&csel_tester});
phy_ctrl.start_cell_select(found_cell);
phy_ctrl.cell_selection_observers.subscribe(csel_tester);
TESTASSERT(not phy_ctrl.is_in_sync());
TESTASSERT(phy_ctrl.current_state_name() == "selecting_cell");
// TEST: Cell Selection state ignores events other than the cell selection result, and callback is called
phy_ctrl.in_sync();
TESTASSERT(not phy_ctrl.is_in_sync());
TESTASSERT(phy_ctrl.cell_selection_completed(true));
phy_ctrl.cell_selection_completed(true);
// Note: Still in cell selection, but now waiting for the first in_sync
TESTASSERT(phy_ctrl.current_state_name() == "selecting_cell");
TESTASSERT(not phy_ctrl.is_in_sync());
@ -133,7 +135,8 @@ int test_phy_ctrl_fsm()
// TEST: Cell Selection with timeout being reached
csel_tester.result = -1;
TESTASSERT(phy_ctrl.start_cell_select(found_cell, srslte::event_callback<bool>{&csel_tester}));
TESTASSERT(phy_ctrl.start_cell_select(found_cell));
phy_ctrl.cell_selection_observers.subscribe(csel_tester);
TESTASSERT(not phy_ctrl.is_in_sync());
phy_ctrl.cell_selection_completed(true);
TESTASSERT(phy_ctrl.current_state_name() == "selecting_cell");

Loading…
Cancel
Save