From 48dd436d86def6383155f53baea722f2390d1fdf Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 18 Aug 2020 18:25:48 +0100 Subject: [PATCH] integrated observer pattern into rrc phy ctrl fsm --- lib/include/srslte/adt/observer.h | 2 + srsue/hdr/stack/rrc/phy_controller.h | 31 ++++++------- srsue/src/stack/rrc/phy_controller.cc | 65 +++++++++++++-------------- srsue/src/stack/rrc/rrc_procedures.cc | 21 +++++---- srsue/test/upper/rrc_phy_ctrl_test.cc | 11 +++-- 5 files changed, 65 insertions(+), 65 deletions(-) diff --git a/lib/include/srslte/adt/observer.h b/lib/include/srslte/adt/observer.h index 6ccd07407..75b756fbb 100644 --- a/lib/include/srslte/adt/observer.h +++ b/lib/include/srslte/adt/observer.h @@ -81,6 +81,8 @@ public: return count; } + void unsubscribe_all() { observers.clear(); } + //! Signal result to observers void dispatch(Args... args) { diff --git a/srsue/hdr/stack/rrc/phy_controller.h b/srsue/hdr/stack/rrc/phy_controller.h index 1fdb99e79..d3fbfefba 100644 --- a/srsue/hdr/stack/rrc/phy_controller.h +++ b/srsue/hdr/stack/rrc/phy_controller.h @@ -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 callback; - }; - struct cell_search_cmd { - srslte::event_callback 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& on_complete); - bool start_cell_search(const srslte::event_callback& 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_search_observers; + srslte::event_dispatcher cell_selection_observers; + // state getters bool cell_is_camping() { return phy->cell_is_camping(); } bool is_in_sync() const { return is_in_state(); } - // 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 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 > csearch_callbacks; - protected: state_list 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 diff --git a/srsue/src/stack/rrc/phy_controller.cc b/srsue/src/stack/rrc/phy_controller.cc index 08353202d..4bef27a42 100644 --- a/srsue/src/stack/rrc/phy_controller.cc +++ b/srsue/src/stack/rrc/phy_controller.cc @@ -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& 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()) { + 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()) { 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& on_complete) +bool phy_controller::start_cell_search() { - trigger(cell_search_cmd{on_complete}); + if (is_in_state()) { + fsmInfo("Cell search already launched.\n"); + return true; + } + trigger(cell_search_cmd{}); if (not is_in_state()) { fsmWarning("Failed to launch cell search\n"); return false; @@ -115,24 +126,14 @@ bool phy_controller::start_cell_search(const srslte::event_callbackcsearch_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 diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index e85081782..616f7be45 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -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{&rrc_ptr->cell_searcher}); - if (not rrc_ptr->phy_ctrl->is_in_state()) { + 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{&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{&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{&rrc_ptr->cell_selector}); - if (not rrc_ptr->phy_ctrl->is_in_state()) { + 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{&rrc_ptr->ho_handler}); - if (not rrc_ptr->phy_ctrl->is_in_state()) { + 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; diff --git a/srsue/test/upper/rrc_phy_ctrl_test.cc b/srsue/test/upper/rrc_phy_ctrl_test.cc index d4bf5f413..d5894e32e 100644 --- a/srsue/test/upper/rrc_phy_ctrl_test.cc +++ b/srsue/test/upper/rrc_phy_ctrl_test.cc @@ -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{&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{&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{&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");