aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-trx/l1_if.h
blob: 50369d9d8cdea752a51d05385e5d6d7abe8c6fa8 (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
137
138
139
140
141
142
#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,
	BTSTRX_CTR_SCHED_DL_FH_NO_CARRIER,
	BTSTRX_CTR_SCHED_UL_FH_NO_CARRIER,
};

/*! 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_pdu_ver_req; /* requested TRXD PDU version */
	uint8_t			trxd_pdu_ver_use; /* actual TRXD PDU version in use */
	bool			setformat_sent;
	bool			setformat_acked;

	bool			enabled;


	bool			arfcn_valid;
	uint16_t		arfcn;
	bool			rxtune_sent;
	bool			rxtune_acked;
	bool			txtune_sent;
	bool			txtune_acked;

	bool			tsc_valid;
	uint8_t			tsc;
	bool			tsc_sent;
	bool			tsc_acked;

	bool			bsic_valid;
	uint8_t			bsic;
	bool			bsic_sent;
	bool			bsic_acked;

	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			nomtxpower_sent;
	bool			nomtxpower_acked;

	bool			maxdly_valid;
	int			maxdly;
	bool			maxdly_sent;

	bool			maxdlynb_valid;
	int			maxdlynb;
	bool			maxdlynb_sent;

	uint8_t			slotmask;

	bool			setslot_valid[TRX_NR_TS];
	struct {
		uint8_t slottype;
		uint8_t tsc_set;
		uint8_t tsc_val;
		bool tsc_valid;
	}			setslot[TRX_NR_TS];
	bool			setslot_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 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);

#endif /* L1_IF_H_TRX */