blob: 4b9cc1a0ce3893ba9f9b215cb29c812cff1e21c6 [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
79 idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
80 lchan->meas_rep_idx, num);
81
82 for (i = 0; i < num; i++) {
83 int j = (idx+i) % ARRAY_SIZE(lchan->meas_rep);
84
85 avg += get_field(&lchan->meas_rep[j], field);
86 }
87
88 return avg / num;
89}
90
91/* Check if N out of M last values for FIELD are >= bd */
92int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
93 enum meas_rep_field field,
94 unsigned int n, unsigned int m, int be)
95{
96 unsigned int i, idx;
97 int count = 0;
98
99 idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
100 lchan->meas_rep_idx, m);
101
102 for (i = 0; i < m; i++) {
103 int j = (idx + i) % ARRAY_SIZE(lchan->meas_rep);
104 int val = get_field(&lchan->meas_rep[j], field);
105
106 if (val >= be)
107 count++;
108
109 if (count >= n)
110 return 1;
111 }
112
113 return 0;
114}