osmo-bsc/src/libbsc/meas_rep.c

116 lines
2.8 KiB
C

/* Measurement Report Processing */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* This program 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.
*
* This program 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <openbsc/gsm_data.h>
#include <openbsc/meas_rep.h>
static int get_field(const struct gsm_meas_rep *rep,
enum meas_rep_field field)
{
switch (field) {
case MEAS_REP_DL_RXLEV_FULL:
return rep->dl.full.rx_lev;
case MEAS_REP_DL_RXLEV_SUB:
return rep->dl.sub.rx_lev;
case MEAS_REP_DL_RXQUAL_FULL:
return rep->dl.full.rx_qual;
case MEAS_REP_DL_RXQUAL_SUB:
return rep->dl.sub.rx_qual;
case MEAS_REP_UL_RXLEV_FULL:
return rep->ul.full.rx_lev;
case MEAS_REP_UL_RXLEV_SUB:
return rep->ul.sub.rx_lev;
case MEAS_REP_UL_RXQUAL_FULL:
return rep->ul.full.rx_qual;
case MEAS_REP_UL_RXQUAL_SUB:
return rep->ul.sub.rx_qual;
}
return 0;
}
unsigned int calc_initial_idx(unsigned int array_size,
unsigned int meas_rep_idx,
unsigned int num_values)
{
int offs, idx;
/* from which element do we need to start if we're interested
* in an average of 'num' elements */
offs = meas_rep_idx - num_values;
if (offs < 0)
idx = array_size + offs;
else
idx = offs;
return idx;
}
/* obtain an average over the last 'num' fields in the meas reps */
int get_meas_rep_avg(const struct gsm_lchan *lchan,
enum meas_rep_field field, unsigned int num)
{
unsigned int i, idx;
int avg = 0;
if (num < 1)
return 0;
idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
lchan->meas_rep_idx, num);
for (i = 0; i < num; i++) {
int j = (idx+i) % ARRAY_SIZE(lchan->meas_rep);
avg += get_field(&lchan->meas_rep[j], field);
}
return avg / num;
}
/* Check if N out of M last values for FIELD are >= bd */
int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
enum meas_rep_field field,
unsigned int n, unsigned int m, int be)
{
unsigned int i, idx;
int count = 0;
idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
lchan->meas_rep_idx, m);
for (i = 0; i < m; i++) {
int j = (idx + i) % ARRAY_SIZE(lchan->meas_rep);
int val = get_field(&lchan->meas_rep[j], field);
if (val >= be)
count++;
if (count >= n)
return 1;
}
return 0;
}