You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.3 KiB
C++

/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__)
#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__)
#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__)
#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__)
#include "srsue/hdr/stack/mac/proc_phr.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srsue/hdr/stack/mac/mac.h"
#include "srsue/hdr/stack/mac/mux.h"
namespace srsue {
phr_proc::phr_proc()
{
initiated = false;
last_pathloss_db = 0;
phr_cfg = {};
}
void phr_proc::init(phy_interface_mac_lte* phy_h_, srslte::log* log_h_, srslte::timer_handler* timers_db_)
{
phy_h = phy_h_;
log_h = log_h_;
timers_db = timers_db_;
initiated = true;
timer_periodic = timers_db->get_unique_timer();
timer_prohibit = timers_db->get_unique_timer();
reset();
}
void phr_proc::reset()
{
timer_periodic.stop();
timer_prohibit.stop();
phr_is_triggered = false;
}
void phr_proc::set_config(srslte::phr_cfg_t& cfg)
{
phr_cfg = cfg;
// First stop timers. If enabled==false or value is Inf, won't be re-started
timer_periodic.stop();
timer_prohibit.stop();
if (cfg.enabled) {
// Setup timers and trigger PHR when configuration changed by higher layers
if (phr_cfg.periodic_timer > 0) {
timer_periodic.set(phr_cfg.periodic_timer, [this](uint32_t tid) { timer_expired(tid); });
timer_periodic.run();
phr_is_triggered = true;
Info("PHR: Configured timer periodic %d ms\n", phr_cfg.periodic_timer);
}
if (phr_cfg.prohibit_timer > 0) {
timer_prohibit.set(phr_cfg.prohibit_timer, [this](uint32_t tid) { timer_expired(tid); });
timer_prohibit.run();
Info("PHR: Configured timer prohibit %d ms\n", phr_cfg.prohibit_timer);
phr_is_triggered = true;
}
}
}
bool phr_proc::pathloss_changed()
{
if (!phr_cfg.enabled) {
return false;
}
int cur_pathloss_db = (int)phy_h->get_pathloss_db();
if (abs(cur_pathloss_db - last_pathloss_db) > phr_cfg.db_pathloss_change && phr_cfg.db_pathloss_change > 0) {
last_pathloss_db = cur_pathloss_db;
return true;
} else {
return false;
}
}
void phr_proc::start_timer()
{
timer_periodic.run();
}
/* Trigger PHR when timers exires */
void phr_proc::timer_expired(uint32_t timer_id)
{
if (!phr_cfg.enabled) {
Warning("PHR: Timer triggered but PHR has been disabled\n");
return;
}
if (timer_id == timer_periodic.id()) {
timer_periodic.run();
Debug("PHR: Triggered by timer periodic (timer expired).\n");
phr_is_triggered = true;
} else if (timer_id == timer_prohibit.id()) {
if (pathloss_changed()) {
Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d (timer expired)\n", last_pathloss_db);
phr_is_triggered = true;
}
} else {
log_h->warning("Received timer callback from unknown timer_id=%d\n", timer_id);
}
}
void phr_proc::step(uint32_t tti)
{
if (phr_cfg.enabled && initiated) {
if (pathloss_changed() && timer_prohibit.is_expired()) {
Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d\n", last_pathloss_db);
phr_is_triggered = true;
}
}
}
bool phr_proc::generate_phr_on_ul_grant(float* phr)
{
if (phr_is_triggered) {
if (phr) {
*phr = phy_h->get_phr();
}
Debug("PHR: Generating PHR=%f\n", phr ? *phr : 0.0);
timer_periodic.run();
timer_prohibit.run();
phr_is_triggered = false;
return true;
} else {
return false;
}
}
bool phr_proc::is_extended()
{
return phr_cfg.extended;
}
} // namespace srsue