Project

General

Profile

Support #4213 » FIX_loops.c

S_erge_y, 09/29/2019 06:20 PM

 
1
/* Loop control for OsmoBTS-TRX */
2

    
3
/* (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
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 Affero General Public License as published by
9
 * the Free Software Foundation; either version 3 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 Affero General Public License
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 */
21

    
22
#include <stdint.h>
23
#include <unistd.h>
24
#include <stdlib.h>
25
#include <errno.h>
26

    
27
#include <osmo-bts/gsm_data.h>
28
#include <osmo-bts/logging.h>
29
#include <osmo-bts/l1sap.h>
30
#include <osmocom/core/bits.h>
31

    
32
#include "trx_if.h"
33
#include "l1_if.h"
34
#include "loops.h"
35

    
36
/*
37
 * MS Power loop
38
 */
39

    
40

    
41

    
42
/*! Input a new RSSI value into the MS power control loop for the given logical channel.
43
 *  \param lchan logical channel
44
 *  \param chan_state L1 channel state of the logical channel.
45
 *  \param rssi Received Signal Strength Indication (in dBm) */
46
static void ms_power_val(struct gsm_lchan *lchan, struct l1sched_chan_state *chan_state, int8_t rssi)
47
{
48
int8_t ms_send;
49
int8_t cur_pow;
50
cur_pow = lchan->ms_power_ctrl.current;
51
LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Current value: %d\n", cur_pow);
52
//if (!(chan_state->meas.clock & 1))
53
//return;
54

    
55
switch(rssi)
56
{
57
            case -2:
58
        ms_send = 25;
59
            break;
60
            case -3:
61
        ms_send = 24;
62
            break;
63
            case -4:
64
        ms_send = 23;
65
            break;
66
            case -5:
67
        ms_send = 22;
68
            break;
69
            case -6:
70
        ms_send = 21;
71
            break;
72
            case -7:
73
        ms_send = 20;
74
            break;
75
            case -8:
76
        ms_send = 19;
77
            break;
78
            case -9:
79
        ms_send = 18;
80
            break;
81
            case -10:
82
        ms_send = 17;
83
            break;
84
            case -11:
85
        ms_send = 16;
86
            break;
87
            case -12:
88
        ms_send = 15;
89
            break;
90
            case -13:
91
        ms_send = 14;
92
            break;
93
            case -14:
94
        ms_send = 14;
95
            break;
96
            case -15:
97
        ms_send = 13;
98
            break;
99
            case -16:
100
        ms_send = 13;
101
            break;
102
            case -17:
103
        ms_send = 12;
104
            break;
105
            case -18:
106
        ms_send = 12;
107
            break;
108
            case -19:
109
        ms_send = 11;
110
            break;
111
            case -20:
112
        ms_send = 11;
113
            break;
114
            case -21:
115
        ms_send = 10;
116
            break;
117
            case -22:
118
        ms_send = 10;
119
            break;
120
            case -23:
121
        ms_send = 9;
122
            break;
123
            case -24:
124
        ms_send = 9;
125
            break;
126
            case -25:
127
        ms_send = 8;
128
            break;
129
            case -26:
130
        ms_send = 8;
131
            break;
132
            case -27:
133
        ms_send = 8;
134
            break;
135
            case -28:
136
        ms_send = 7;
137
            break;
138
            case -29:
139
        ms_send = 7;
140
            break;
141
            case -30:
142
        ms_send = 7;
143
            break;
144
            case -31:
145
        ms_send = 6;
146
            break;
147
            case -32:
148
        ms_send = 6;
149
            break;
150
            case -33:
151
        ms_send = 6;
152
            break;
153
            case -34:
154
        ms_send = 6;
155
            break;
156
            case -35:
157
        ms_send = 5;
158
            default:
159
        ms_send = 5;
160
            break;
161
}
162

    
163
if (rssi > -2)
164
   ms_send = 26;
165

    
166
//ms_send = 30; - min_power
167
lchan->ms_power_ctrl.current = ms_send;
168
LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "RSSI value: %d\n", rssi);
169
LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Set ms_power_ctrl.current value: %d\n", ms_send);
170

    
171
}
172

    
173
/*! Process a single clock tick of the MS power control loop.
174
 *  \param lchan Logical channel to which the clock tick applies */
175
//static void ms_power_clock(struct gsm_lchan *lchan, struct l1sched_chan_state *chan_state)
176
//{
177
//	struct gsm_bts_trx *trx = lchan->ts->trx;
178
//	struct phy_instance *pinst = trx_phy_instance(trx);
179
//	int rssi;
180
//	int i;
181

    
182
	/* skip every second clock, to prevent oscillating due to roundtrip
183
	 * delay */
184
//	if (!(chan_state->meas.clock & 1))
185
//		return;
186

    
187
//	LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Got SACCH master clock at RSSI count %d\n",
188
//		chan_state->meas.rssi_count);
189

    
190
	/* wait for initial burst */
191
/* Отключить 
192
	if (!chan_state->meas.rssi_got_burst)
193
                ms_power_diff(lchan, MS_RAISE_MAX);
194
		return; */
195

    
196
	/* if no burst was received from MS at clock */
197
/* Отключить
198
	if (chan_state->meas.rssi_count == 0) {
199
		LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE, "LOST SACCH frame, so we raise MS power\n");
200
		ms_power_diff(lchan, MS_RAISE_MAX);
201
		return;
202
	}*/
203

    
204
	/* reset total counter */
205
//	chan_state->meas.rssi_count = 0;
206

    
207
	/* check the minimum level received after MS acknowledged the ordered
208
	 * power level */
209
//	if (chan_state->meas.rssi_valid_count == 0)
210
//		return;
211
//	for (rssi = 999, i = 0; i < chan_state->meas.rssi_valid_count; i++) {
212
//		if (rssi > chan_state->meas.rssi[i])
213
//			rssi = chan_state->meas.rssi[i];
214
//	}
215

    
216
	/* reset valid counter */
217
//	chan_state->meas.rssi_valid_count = 0;
218

    
219
	/* change RSSI 
220
	LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Lowest RSSI: %d Target RSSI: %d Current "
221
		"MS power: %d (%d dBm)\n", rssi,
222
		pinst->phy_link->u.osmotrx.trx_target_rssi, lchan->ms_power_ctrl.current,
223
		ms_pwr_dbm(trx->bts->band, lchan->ms_power_ctrl.current));
224
	ms_power_diff(lchan, pinst->phy_link->u.osmotrx.trx_target_rssi - rssi); */
225
//}
226

    
227

    
228
/* 90% of one bit duration in 1/256 symbols: 256*0.9 */
229
#define TOA256_9OPERCENT	230
230

    
231
/*
232
 * Timing Advance loop
233
 */
234

    
235
void ta_val(struct gsm_lchan *lchan, struct l1sched_chan_state *chan_state, int16_t toa256)
236
{
237
	/* check if the current L1 header acks to the current ordered TA */
238
	if (lchan->meas.l1_info[1] != lchan->rqd_ta)
239
		return;
240

    
241
	/* sum measurement */
242
	chan_state->meas.toa256_sum += toa256;
243
	if (++(chan_state->meas.toa_num) < 16)
244
		return;
245

    
246
	/* complete set */
247
	toa256 = chan_state->meas.toa256_sum / chan_state->meas.toa_num;
248

    
249
	/* check for change of TOA */
250
	if (toa256 < -TOA256_9OPERCENT && lchan->rqd_ta > 0) {
251
		LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "TOA is too early (%d), now lowering TA from %d to %d\n",
252
			toa256, lchan->rqd_ta, lchan->rqd_ta - 1);
253
		lchan->rqd_ta--;
254
	} else if (toa256 > TOA256_9OPERCENT && lchan->rqd_ta < 63) {
255
		LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "TOA is too late (%d), now raising TA from %d to %d\n",
256
			toa256, lchan->rqd_ta, lchan->rqd_ta + 1);
257
		lchan->rqd_ta++;
258
	} else
259
		LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "TOA is correct (%d), keeping current TA of %d\n",
260
			toa256, lchan->rqd_ta);
261

    
262
	chan_state->meas.toa_num = 0;
263
	chan_state->meas.toa256_sum = 0;
264
}
265

    
266
/*! Process a SACCH event as input to the MS power control and TA loop.  Function
267
 *  is called once every uplink SACCH block is received.
268
 * \param l1t L1 TRX instance on which we operate
269
 * \param chan_nr RSL channel number on which we operate
270
 * \param chan_state L1 scheduler channel state of the channel on which we operate
271
 * \param[in] rssi Receive Signal Strength Indication
272
 * \param[in] toa256 Time of Arrival in 1/256 symbol periods */
273
void trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr,
274
	struct l1sched_chan_state *chan_state, int8_t rssi, int16_t toa256)
275
{
276
	struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)]
277
					.lchan[l1sap_chan2ss(chan_nr)];
278
	struct phy_instance *pinst = trx_phy_instance(l1t->trx);
279

    
280
	/* if MS power control loop is enabled, handle it */
281
	if (pinst->phy_link->u.osmotrx.trx_ms_power_loop)
282
		ms_power_val(lchan, chan_state, rssi);
283

    
284
	/* if TA loop is enabled, handle it */
285
	if (pinst->phy_link->u.osmotrx.trx_ta_loop)
286
		ta_val(lchan, chan_state, toa256);
287
}
288

    
289
/*! Called once every downlink SACCH block needs to be sent. */
290
void trx_loop_sacch_clock(struct l1sched_trx *l1t, uint8_t chan_nr,
291
	struct l1sched_chan_state *chan_state)
292
{
293
	struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)]
294
					.lchan[l1sap_chan2ss(chan_nr)];
295
	struct phy_instance *pinst = trx_phy_instance(l1t->trx);
296

    
297
	if (lchan->ms_power_ctrl.fixed)
298
	        return;
299

    
300
//	if (pinst->phy_link->u.osmotrx.trx_ms_power_loop)
301
//		ms_power_clock(lchan, chan_state);
302

    
303
	/* count the number of SACCH clocks */
304
	chan_state->meas.clock++;
305
}
306

    
307
void trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr,
308
	struct l1sched_chan_state *chan_state, float ber)
309
{
310
	struct gsm_bts_trx *trx = l1t->trx;
311
	struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)]
312
					.lchan[l1sap_chan2ss(chan_nr)];
313

    
314
	/* check if loop is enabled */
315
	if (!chan_state->amr_loop)
316
		return;
317

    
318
	/* wait for MS to use the requested codec */
319
	if (chan_state->ul_ft != chan_state->dl_cmr)
320
		return;
321

    
322
	/* count bit errors */
323
	if (L1SAP_IS_CHAN_TCHH(chan_nr)) {
324
		chan_state->ber_num += 2;
325
		chan_state->ber_sum += (ber + ber);
326
	} else {
327
		chan_state->ber_num++;
328
		chan_state->ber_sum += ber;
329
	}
330

    
331
	/* count frames */
332
	if (chan_state->ber_num < 48)
333
		return;
334

    
335
	/* calculate average (reuse ber variable) */
336
	ber = chan_state->ber_sum / chan_state->ber_num;
337

    
338
	/* reset bit errors */
339
	chan_state->ber_num = 0;
340
	chan_state->ber_sum = 0;
341

    
342
	LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Current bit error rate (BER) %.6f "
343
		"codec id %d\n", ber, chan_state->ul_ft);
344

    
345
	/* degrade */
346
	if (chan_state->dl_cmr > 0) {
347
		/* degrade, if ber is above threshold FIXME: C/I */
348
		if (ber >
349
		   lchan->tch.amr_mr.bts_mode[chan_state->dl_cmr-1].threshold) {
350
			LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Degrading due to BER %.6f "
351
				"from codec id %d to %d\n", ber, chan_state->dl_cmr,
352
				chan_state->dl_cmr - 1);
353
			chan_state->dl_cmr--;
354
		}
355
	} else if (chan_state->dl_cmr < chan_state->codecs - 1) {
356
		/* degrade, if ber is above threshold  FIXME: C/I*/
357
		if (ber <
358
		    lchan->tch.amr_mr.bts_mode[chan_state->dl_cmr].threshold
359
		  - lchan->tch.amr_mr.bts_mode[chan_state->dl_cmr].hysteresis) {
360
			LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Upgrading due to BER %.6f "
361
				"from codec id %d to %d\n", ber, chan_state->dl_cmr,
362
				chan_state->dl_cmr + 1);
363
			chan_state->dl_cmr++;
364
		}
365
	}
366
}
367

    
368
void trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop)
369
{
370
	if (chan_state->amr_loop && !loop) {
371
		chan_state->amr_loop = 0;
372
		return;
373
	}
374

    
375
	if (!chan_state->amr_loop && loop) {
376
		chan_state->amr_loop = 1;
377

    
378
		/* reset bit errors */
379
		chan_state->ber_num = 0;
380
		chan_state->ber_sum = 0;
381

    
382
		return;
383
	}
384
}
(3-3/6)
Add picture from clipboard (Maximum size: 48.8 MB)