Project

General

Profile

Support #4213 » loops.c

S_erge_y, 09/28/2019 07:24 AM

 
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
switch(rssi)
50
{
51
            case -2:
52
        ms_send = 13;
53
            break;
54
            case -3:
55
        ms_send = 13;
56
            break;
57
            case -4:
58
        ms_send = 13;
59
            break;
60
            case -5:
61
        ms_send = 13;
62
            break;
63
            case -6:
64
        ms_send = 14;
65
            break;
66
            case -7:
67
        ms_send = 14;
68
            break;
69
            case -8:
70
        ms_send = 14;
71
            break;
72
            case -9:
73
        ms_send = 15;
74
            break;
75
            case -10:
76
        ms_send = 15;
77
            break;
78
            case -11:
79
        ms_send = 15;
80
            break;
81
            case -12:
82
        ms_send = 15;
83
            break;
84
            case -13:
85
        ms_send = 16;
86
            break;
87
            case -14:
88
        ms_send = 16;
89
            break;
90
            case -15:
91
        ms_send = 16;
92
            break;
93
            case -16:
94
        ms_send = 17;
95
            break;
96
            case -17:
97
        ms_send = 17;
98
            break;
99
            case -18:
100
        ms_send = 18;
101
            break;
102
            case -19:
103
        ms_send = 18;
104
            break;
105
            case -20:
106
        ms_send = 19;
107
            break;
108
            case -21:
109
        ms_send = 19;
110
            break;
111
            case -22:
112
        ms_send = 20;
113
            break;
114
            case -23:
115
        ms_send = 20;
116
            break;
117
            case -24:
118
        ms_send = 21;
119
            break;
120
            case -25:
121
        ms_send = 21;
122
            break;
123
            case -26:
124
        ms_send = 22;
125
            break;
126
            case -27:
127
        ms_send = 22;
128
            break;
129
            case -28:
130
        ms_send = 23;
131
            break;
132
            case -29:
133
        ms_send = 23;
134
            break;
135
            case -30:
136
        ms_send = 23;
137
            break;
138
            case -31:
139
        ms_send = 24;
140
            break;
141
            case -32:
142
        ms_send = 24;
143
            break;
144
            case -33:
145
        ms_send = 24;
146
            break;
147
            case -34:
148
        ms_send = 25;
149
            break;
150
            case -35:
151
        ms_send = 25;
152
            break;
153
            case -36:
154
        ms_send = 25;
155
            break;
156
            case -37:
157
        ms_send = 26;
158
            break;
159
            case -38:
160
        ms_send = 26;
161
            break;
162
            case -39:
163
        ms_send = 26;
164
            break;
165
            case -40:
166
        ms_send = 27;
167
            break;
168
            case -41:
169
        ms_send = 27;
170
            break;
171
            case -42:
172
        ms_send = 27;
173
            break;
174
            case -43:
175
        ms_send = 28;
176
            break;
177
            case -44:
178
        ms_send = 28;
179
            break;
180
            case -45:
181
        ms_send = 28;
182
            break;
183
            case -46:
184
        ms_send = 29;
185
            break;
186
            case -47:
187
        ms_send = 29;
188
            break;
189
            case -48:
190
        ms_send = 29;
191
            break;
192
            case -49:
193
        ms_send = 30;
194
            break;
195
            case -50:
196
        ms_send = 30;
197
            break;
198
            case -51:
199
        ms_send = 30;
200
            break;
201
            case -52:
202
        ms_send = 31;
203
            break;
204
            case -53:
205
        ms_send = 31;
206
            break;
207
            case -54:
208
        ms_send = 31;
209
            break;
210
            case -55:
211
        ms_send = 32;
212
            break;
213
            case -56:
214
        ms_send = 32;
215
            break;
216
            case -57:
217
        ms_send = 32;
218
            break;
219
            default:
220
        ms_send = 33;
221
            break;
222
}
223
if (rssi > -2)
224
   ms_send = 13;
225

    
226
lchan->ms_power_ctrl.current = ms_send;
227
LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "RSSI value: %d\n", rssi);
228
LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Set ms_power_ctrl.current value: %d\n", ms_send);
229

    
230
}
231

    
232
/*! Process a single clock tick of the MS power control loop.
233
 *  \param lchan Logical channel to which the clock tick applies */
234
//static void ms_power_clock(struct gsm_lchan *lchan, struct l1sched_chan_state *chan_state)
235
//{
236
//	struct gsm_bts_trx *trx = lchan->ts->trx;
237
//	struct phy_instance *pinst = trx_phy_instance(trx);
238
//	int rssi;
239
//	int i;
240

    
241
	/* skip every second clock, to prevent oscillating due to roundtrip
242
	 * delay */
243
//	if (!(chan_state->meas.clock & 1))
244
//		return;
245

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

    
249
	/* wait for initial burst */
250
/* Отключить 
251
	if (!chan_state->meas.rssi_got_burst)
252
                ms_power_diff(lchan, MS_RAISE_MAX);
253
		return; */
254

    
255
	/* if no burst was received from MS at clock */
256
/* Отключить
257
	if (chan_state->meas.rssi_count == 0) {
258
		LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE, "LOST SACCH frame, so we raise MS power\n");
259
		ms_power_diff(lchan, MS_RAISE_MAX);
260
		return;
261
	}*/
262

    
263
	/* reset total counter */
264
//	chan_state->meas.rssi_count = 0;
265

    
266
	/* check the minimum level received after MS acknowledged the ordered
267
	 * power level */
268
//	if (chan_state->meas.rssi_valid_count == 0)
269
//		return;
270
//	for (rssi = 999, i = 0; i < chan_state->meas.rssi_valid_count; i++) {
271
//		if (rssi > chan_state->meas.rssi[i])
272
//			rssi = chan_state->meas.rssi[i];
273
//	}
274

    
275
	/* reset valid counter */
276
//	chan_state->meas.rssi_valid_count = 0;
277

    
278
	/* change RSSI 
279
	LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Lowest RSSI: %d Target RSSI: %d Current "
280
		"MS power: %d (%d dBm)\n", rssi,
281
		pinst->phy_link->u.osmotrx.trx_target_rssi, lchan->ms_power_ctrl.current,
282
		ms_pwr_dbm(trx->bts->band, lchan->ms_power_ctrl.current));
283
	ms_power_diff(lchan, pinst->phy_link->u.osmotrx.trx_target_rssi - rssi); */
284
//}
285

    
286

    
287
/* 90% of one bit duration in 1/256 symbols: 256*0.9 */
288
#define TOA256_9OPERCENT	230
289

    
290
/*
291
 * Timing Advance loop
292
 */
293

    
294
void ta_val(struct gsm_lchan *lchan, struct l1sched_chan_state *chan_state, int16_t toa256)
295
{
296
	/* check if the current L1 header acks to the current ordered TA */
297
	if (lchan->meas.l1_info[1] != lchan->rqd_ta)
298
		return;
299

    
300
	/* sum measurement */
301
	chan_state->meas.toa256_sum += toa256;
302
	if (++(chan_state->meas.toa_num) < 16)
303
		return;
304

    
305
	/* complete set */
306
	toa256 = chan_state->meas.toa256_sum / chan_state->meas.toa_num;
307

    
308
	/* check for change of TOA */
309
	if (toa256 < -TOA256_9OPERCENT && lchan->rqd_ta > 0) {
310
		LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "TOA is too early (%d), now lowering TA from %d to %d\n",
311
			toa256, lchan->rqd_ta, lchan->rqd_ta - 1);
312
		lchan->rqd_ta--;
313
	} else if (toa256 > TOA256_9OPERCENT && lchan->rqd_ta < 63) {
314
		LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "TOA is too late (%d), now raising TA from %d to %d\n",
315
			toa256, lchan->rqd_ta, lchan->rqd_ta + 1);
316
		lchan->rqd_ta++;
317
	} else
318
		LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "TOA is correct (%d), keeping current TA of %d\n",
319
			toa256, lchan->rqd_ta);
320

    
321
	chan_state->meas.toa_num = 0;
322
	chan_state->meas.toa256_sum = 0;
323
}
324

    
325
/*! Process a SACCH event as input to the MS power control and TA loop.  Function
326
 *  is called once every uplink SACCH block is received.
327
 * \param l1t L1 TRX instance on which we operate
328
 * \param chan_nr RSL channel number on which we operate
329
 * \param chan_state L1 scheduler channel state of the channel on which we operate
330
 * \param[in] rssi Receive Signal Strength Indication
331
 * \param[in] toa256 Time of Arrival in 1/256 symbol periods */
332
void trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr,
333
	struct l1sched_chan_state *chan_state, int8_t rssi, int16_t toa256)
334
{
335
	struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)]
336
					.lchan[l1sap_chan2ss(chan_nr)];
337
	struct phy_instance *pinst = trx_phy_instance(l1t->trx);
338

    
339
	/* if MS power control loop is enabled, handle it */
340
	if (pinst->phy_link->u.osmotrx.trx_ms_power_loop)
341
		ms_power_val(lchan, chan_state, rssi);
342

    
343
	/* if TA loop is enabled, handle it */
344
	if (pinst->phy_link->u.osmotrx.trx_ta_loop)
345
		ta_val(lchan, chan_state, toa256);
346
}
347

    
348
/*! Called once every downlink SACCH block needs to be sent. */
349
void trx_loop_sacch_clock(struct l1sched_trx *l1t, uint8_t chan_nr,
350
	struct l1sched_chan_state *chan_state)
351
{
352
	struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)]
353
					.lchan[l1sap_chan2ss(chan_nr)];
354
	struct phy_instance *pinst = trx_phy_instance(l1t->trx);
355

    
356
	if (lchan->ms_power_ctrl.fixed)
357
	        return;
358

    
359
//	if (pinst->phy_link->u.osmotrx.trx_ms_power_loop)
360
//		ms_power_clock(lchan, chan_state);
361

    
362
	/* count the number of SACCH clocks */
363
	chan_state->meas.clock++;
364
}
365

    
366
void trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr,
367
	struct l1sched_chan_state *chan_state, float ber)
368
{
369
	struct gsm_bts_trx *trx = l1t->trx;
370
	struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)]
371
					.lchan[l1sap_chan2ss(chan_nr)];
372

    
373
	/* check if loop is enabled */
374
	if (!chan_state->amr_loop)
375
		return;
376

    
377
	/* wait for MS to use the requested codec */
378
	if (chan_state->ul_ft != chan_state->dl_cmr)
379
		return;
380

    
381
	/* count bit errors */
382
	if (L1SAP_IS_CHAN_TCHH(chan_nr)) {
383
		chan_state->ber_num += 2;
384
		chan_state->ber_sum += (ber + ber);
385
	} else {
386
		chan_state->ber_num++;
387
		chan_state->ber_sum += ber;
388
	}
389

    
390
	/* count frames */
391
	if (chan_state->ber_num < 48)
392
		return;
393

    
394
	/* calculate average (reuse ber variable) */
395
	ber = chan_state->ber_sum / chan_state->ber_num;
396

    
397
	/* reset bit errors */
398
	chan_state->ber_num = 0;
399
	chan_state->ber_sum = 0;
400

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

    
404
	/* degrade */
405
	if (chan_state->dl_cmr > 0) {
406
		/* degrade, if ber is above threshold FIXME: C/I */
407
		if (ber >
408
		   lchan->tch.amr_mr.bts_mode[chan_state->dl_cmr-1].threshold) {
409
			LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Degrading due to BER %.6f "
410
				"from codec id %d to %d\n", ber, chan_state->dl_cmr,
411
				chan_state->dl_cmr - 1);
412
			chan_state->dl_cmr--;
413
		}
414
	} else if (chan_state->dl_cmr < chan_state->codecs - 1) {
415
		/* degrade, if ber is above threshold  FIXME: C/I*/
416
		if (ber <
417
		    lchan->tch.amr_mr.bts_mode[chan_state->dl_cmr].threshold
418
		  - lchan->tch.amr_mr.bts_mode[chan_state->dl_cmr].hysteresis) {
419
			LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Upgrading due to BER %.6f "
420
				"from codec id %d to %d\n", ber, chan_state->dl_cmr,
421
				chan_state->dl_cmr + 1);
422
			chan_state->dl_cmr++;
423
		}
424
	}
425
}
426

    
427
void trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop)
428
{
429
	if (chan_state->amr_loop && !loop) {
430
		chan_state->amr_loop = 0;
431
		return;
432
	}
433

    
434
	if (!chan_state->amr_loop && loop) {
435
		chan_state->amr_loop = 1;
436

    
437
		/* reset bit errors */
438
		chan_state->ber_num = 0;
439
		chan_state->ber_sum = 0;
440

    
441
		return;
442
	}
443
}
(2-2/6)
Add picture from clipboard (Maximum size: 48.8 MB)