mirror of https://github.com/PentHertz/srsLTE.git
integrated observer pattern into rrc phy ctrl fsm
This commit is contained in:
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…
Reference in New Issue