|
|
|
/**
|
|
|
|
*
|
|
|
|
* \section COPYRIGHT
|
|
|
|
*
|
|
|
|
* Copyright 2013-2015 Software Radio Systems Limited
|
|
|
|
*
|
|
|
|
* \section LICENSE
|
|
|
|
*
|
|
|
|
* This file is part of the srsUE library.
|
|
|
|
*
|
|
|
|
* srsUE 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.
|
|
|
|
*
|
|
|
|
* srsUE 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_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
|
|
|
#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
|
|
|
#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
|
|
|
#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#include "mac/proc_phr.h"
|
|
|
|
#include "mac/mac.h"
|
|
|
|
#include "mac/mux.h"
|
|
|
|
#include "srslte/interfaces/ue_interfaces.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace srsue {
|
|
|
|
|
|
|
|
phr_proc::phr_proc()
|
|
|
|
{
|
|
|
|
initiated = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void phr_proc::init(phy_interface_mac* phy_h_, srslte::log* log_h_, mac_interface_rrc::mac_cfg_t *mac_cfg_, srslte::timers *timers_db_)
|
|
|
|
{
|
|
|
|
phy_h = phy_h_;
|
|
|
|
log_h = log_h_;
|
|
|
|
mac_cfg = mac_cfg_;
|
|
|
|
timers_db = timers_db_;
|
|
|
|
initiated = true;
|
|
|
|
|
|
|
|
timer_periodic_id = timers_db->get_unique_id();
|
|
|
|
timer_prohibit_id = timers_db->get_unique_id();
|
|
|
|
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void phr_proc::reset()
|
|
|
|
{
|
|
|
|
phr_is_triggered = false;
|
|
|
|
timer_periodic_value = -2;
|
|
|
|
timer_prohibit_value = -2;
|
|
|
|
dl_pathloss_change = -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool phr_proc::pathloss_changed() {
|
|
|
|
|
|
|
|
int min_change = liblte_rrc_dl_pathloss_change_num[mac_cfg->main.phr_cnfg.dl_pathloss_change];
|
|
|
|
int cur_pathloss_db = (int) phy_h->get_pathloss_db();
|
|
|
|
|
|
|
|
if (abs(cur_pathloss_db - last_pathloss_db) > min_change && min_change > 0) {
|
|
|
|
last_pathloss_db = cur_pathloss_db;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void phr_proc::start_timer() {
|
|
|
|
timers_db->get(timer_periodic_id)->run();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Trigger PHR when timers exire */
|
|
|
|
void phr_proc::timer_expired(uint32_t timer_id) {
|
|
|
|
if(timer_id == timer_periodic_id) {
|
|
|
|
timers_db->get(timer_periodic_id)->reset();
|
|
|
|
timers_db->get(timer_periodic_id)->run();
|
|
|
|
Debug("PHR: Triggered by timer periodic (timer expired).\n");
|
|
|
|
phr_is_triggered = true;
|
|
|
|
} else if (timer_id == timer_prohibit_id) {
|
|
|
|
int pathloss_db = liblte_rrc_dl_pathloss_change_num[mac_cfg->main.phr_cnfg.dl_pathloss_change];
|
|
|
|
if (pathloss_changed()) {
|
|
|
|
Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%f (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 (!initiated) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mac_cfg->main.phr_cnfg.setup_present) {
|
|
|
|
int cfg_timer_periodic = liblte_rrc_periodic_phr_timer_num[mac_cfg->main.phr_cnfg.periodic_phr_timer];
|
|
|
|
|
|
|
|
// Setup timers and trigger PHR when configuration changed by higher layers
|
|
|
|
if (timer_periodic_value != cfg_timer_periodic && cfg_timer_periodic > 0)
|
|
|
|
{
|
|
|
|
timer_periodic_value = cfg_timer_periodic;
|
|
|
|
timers_db->get(timer_periodic_id)->set(this, timer_periodic_value);
|
|
|
|
timers_db->get(timer_periodic_id)->run();
|
|
|
|
phr_is_triggered = true;
|
|
|
|
Info("PHR: Configured timer periodic %d ms\n", timer_periodic_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int cfg_timer_prohibit = liblte_rrc_prohibit_phr_timer_num[mac_cfg->main.phr_cnfg.prohibit_phr_timer];
|
|
|
|
|
|
|
|
if (timer_prohibit_value != cfg_timer_prohibit && cfg_timer_prohibit > 0)
|
|
|
|
{
|
|
|
|
timer_prohibit_value = cfg_timer_prohibit;
|
|
|
|
timers_db->get(timer_prohibit_id)->set(this, timer_prohibit_value);
|
|
|
|
timers_db->get(timer_prohibit_id)->run();
|
|
|
|
Info("PHR: Configured timer prohibit %d ms\n", timer_prohibit_value);
|
|
|
|
phr_is_triggered = true;
|
|
|
|
}
|
|
|
|
if (pathloss_changed() && timers_db->get(timer_prohibit_id)->is_expired())
|
|
|
|
{
|
|
|
|
Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%f\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);
|
|
|
|
|
|
|
|
timers_db->get(timer_periodic_id)->reset();
|
|
|
|
timers_db->get(timer_prohibit_id)->reset();
|
|
|
|
timers_db->get(timer_periodic_id)->run();
|
|
|
|
timers_db->get(timer_prohibit_id)->run();
|
|
|
|
|
|
|
|
phr_is_triggered = false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|