aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-trx/l1_if.h
blob: f35936e1430169f34db0795c0d0c24d930c4e59d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#ifndef L1_IF_H_TRX
#define L1_IF_H_TRX

#include <osmocom/core/rate_ctr.h>

#include <osmo-bts/scheduler.h>
#include <osmo-bts/phy_link.h>
#include "trx_if.h"

/*
 * TRX frame clock handling
 *
 * In a "normal" synchronous PHY layer, we would be polled every time
 * the PHY needs data for a given frame number.  However, the
 * OpenBTS-inherited TRX protocol works differently:  We (L1) must
 * autonomously send burst data based on our own clock, and every so
 * often (currently every ~ 216 frames), we get a clock indication from
 * the TRX.
 *
 * We're using a MONOTONIC timerfd interval timer for the 4.615ms frame
 * intervals, and then compute + send the 8 bursts for that frame.
 *
 * Upon receiving a clock indication from the TRX, we compensate
 * accordingly: If we were transmitting too fast, we're delaying the
 * next interval timer accordingly.  If we were too slow, we immediately
 * send burst data for the missing frame numbers.
 */

/* bts-trx specific rate counters */
enum {
	BTSTRX_CTR_SCHED_DL_MISS_FN,
};

/*! clock state of a given TRX */
struct osmo_trx_clock_state {
	/*! number of FN periods without TRX clock indication */
	uint32_t fn_without_clock_ind;
	struct {
		/*! last FN we processed based on FN period timer */
		uint32_t fn;
		/*! time at which we last processed FN */
		struct timespec tv;
	} last_fn_timer;
	struct {
		/*! last FN we received a clock indication for */
		uint32_t fn;
		/*! time at which we received the last clock indication */
		struct timespec tv;
	} last_clk_ind;
	/*! Osmocom FD wrapper for timerfd */
	struct osmo_fd fn_timer_ofd;
};

/* gsm_bts->model_priv, specific to osmo-bts-trx */
struct bts_trx_priv {
	struct osmo_trx_clock_state clk_s;
	struct rate_ctr_group *ctrs;		/* bts-trx specific rate counters */
};

struct trx_config {
	uint8_t			trxd_hdr_ver_req; /* requested TRXD header version */
	uint8_t			trxd_hdr_ver_use; /* actual TRXD header version in use */
	bool			setformat_sent;

	bool			enabled;


	bool			arfcn_valid;
	uint16_t		arfcn;
	bool			arfcn_sent;

	bool			tsc_valid;
	uint8_t			tsc;
	bool			tsc_sent;

	bool			bsic_valid;
	uint8_t			bsic;
	bool			bsic_sent;

	bool			rxgain_valid;
	uint8_t			rxgain;
	bool			rxgain_sent;

	int			forced_max_power_red; /* -1 if not forced by VTY config (default) */

	bool			nominal_power_set_by_vty; /* whether nominal trx power was enforced/retreived from VTY config "nominal-tx-power" */

	bool			maxdly_valid;
	int			maxdly;
	bool			maxdly_sent;

	bool			maxdlynb_valid;
	int			maxdlynb;
	bool			maxdlynb_sent;

	uint8_t			slotmask;

	bool			slottype_valid[TRX_NR_TS];
	uint8_t			slottype[TRX_NR_TS];
	bool			slottype_sent[TRX_NR_TS];
};

struct trx_l1h {
	struct llist_head	trx_ctrl_list;
	/* Latest RSPed cmd, used to catch duplicate RSPs from sent retransmissions */
	struct trx_ctrl_msg 	*last_acked;

	//struct gsm_bts_trx	*trx;
	struct phy_instance	*phy_inst;

	struct osmo_fd		trx_ofd_ctrl;
	struct osmo_timer_list	trx_ctrl_timer;
	struct osmo_fd		trx_ofd_data;

	/* transceiver config */
	struct trx_config	config;
	struct osmo_fsm_inst	*provision_fi;

	struct l1sched_trx	l1s;
};

struct trx_l1h *trx_l1h_alloc(void *tall_ctx, struct phy_instance *pinst);
int l1if_provision_transceiver_trx(struct trx_l1h *l1h);
int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn);
void l1if_trx_set_nominal_power(struct gsm_bts_trx *trx, int nominal_power);
int l1if_trx_start_power_ramp(struct gsm_bts_trx *trx, ramp_compl_cb_t ramp_compl_cb);
enum gsm_phys_chan_config transceiver_chan_type_2_pchan(uint8_t type);

static inline struct l1sched_trx *trx_l1sched_hdl(struct gsm_bts_trx *trx)
{
	struct phy_instance *pinst = trx->role_bts.l1h;
	struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
	return &l1h->l1s;
}

#endif /* L1_IF_H_TRX */