blob: 8b5bff1b808bf63fd8a72f962813ba6b147ebd59 [file] [log] [blame]
Harald Welte38fe2a62009-12-21 09:26:17 +01001/* Measurement Report Processing */
2
3/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <sys/types.h>
24
25#include <openbsc/gsm_data.h>
26#include <openbsc/meas_rep.h>
27
28static int get_field(const struct gsm_meas_rep *rep,
29 enum meas_rep_field field)
30{
31 switch (field) {
32 case MEAS_REP_DL_RXLEV_FULL:
33 return rep->dl.full.rx_lev;
34 case MEAS_REP_DL_RXLEV_SUB:
35 return rep->dl.sub.rx_lev;
36 case MEAS_REP_DL_RXQUAL_FULL:
37 return rep->dl.full.rx_qual;
38 case MEAS_REP_DL_RXQUAL_SUB:
39 return rep->dl.sub.rx_qual;
40 case MEAS_REP_UL_RXLEV_FULL:
41 return rep->ul.full.rx_lev;
42 case MEAS_REP_UL_RXLEV_SUB:
43 return rep->ul.sub.rx_lev;
44 case MEAS_REP_UL_RXQUAL_FULL:
45 return rep->ul.full.rx_qual;
46 case MEAS_REP_UL_RXQUAL_SUB:
47 return rep->ul.sub.rx_qual;
48 }
49
50 return 0;
51}
52
53
54unsigned int calc_initial_idx(unsigned int array_size,
55 unsigned int meas_rep_idx,
56 unsigned int num_values)
57{
58 int offs, idx;
59
60 /* from which element do we need to start if we're interested
61 * in an average of 'num' elements */
62 offs = meas_rep_idx - num_values;
63
64 if (offs < 0)
65 idx = array_size + offs;
66 else
67 idx = offs;
68
69 return idx;
70}
71
72/* obtain an average over the last 'num' fields in the meas reps */
73int get_meas_rep_avg(const struct gsm_lchan *lchan,
74 enum meas_rep_field field, unsigned int num)
75{
76 unsigned int i, idx;
77 int avg = 0;
78
Holger Hans Peter Freyther6e95c5f2010-07-23 19:46:04 +080079 if (num < 1)
80 return 0;
81
Harald Welte38fe2a62009-12-21 09:26:17 +010082 idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
83 lchan->meas_rep_idx, num);
84
85 for (i = 0; i < num; i++) {
86 int j = (idx+i) % ARRAY_SIZE(lchan->meas_rep);
87
88 avg += get_field(&lchan->meas_rep[j], field);
89 }
90
91 return avg / num;
92}
93
94/* Check if N out of M last values for FIELD are >= bd */
95int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
96 enum meas_rep_field field,
97 unsigned int n, unsigned int m, int be)
98{
99 unsigned int i, idx;
100 int count = 0;
101
102 idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
103 lchan->meas_rep_idx, m);
104
105 for (i = 0; i < m; i++) {
106 int j = (idx + i) % ARRAY_SIZE(lchan->meas_rep);
107 int val = get_field(&lchan->meas_rep[j], field);
108
109 if (val >= be)
110 count++;
111
112 if (count >= n)
113 return 1;
114 }
115
116 return 0;
117}