aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/device/ipc/IPCDevice.h
blob: a7618f905e55df85777dd58309542b425ef19e44 (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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
* Copyright 2020 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Pau Espin Pedrol <pespin@sysmocom.de>
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
* See the COPYING file in the main directory for details.
*/

#ifndef _IPC_DEVICE_H_
#define _IPC_DEVICE_H_

#include <cstdint>
#include <cstddef>
#include <climits>
#include <string>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

extern "C" {
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include "shm.h"
}

#include "radioDevice.h"

class smpl_buf;

#define IPC_MAX_NUM_TRX 8

struct ipc_per_trx_sock_state {
	struct osmo_fd conn_bfd; /* fd for connection to the BTS */
	struct osmo_timer_list timer; /* socket connect retry timer */
	struct llist_head upqueue; /* queue for sending messages */
	uint32_t messages_processed_mask; // (=| IPC_IF_MSG_xxx-IPC_IF_CHAN_MSG_OFFSET) bitmask
	ipc_per_trx_sock_state() : conn_bfd(), timer(), upqueue(), messages_processed_mask()
	{
		conn_bfd.fd = -1;
	}
};

class IPCDevice : public RadioDevice {
    protected:
	struct ipc_per_trx_sock_state master_sk_state;

	std::vector<struct ipc_per_trx_sock_state> sk_chan_state;

	uint32_t tx_attenuation[IPC_MAX_NUM_TRX];
	uint8_t tmp_state;
	char shm_name[SHM_NAME_MAX];
	int ipc_shm_connect(const char *shm_name);
	void *shm;
	struct ipc_shm_region *shm_dec;

	std::vector<smpl_buf *> rx_buffers;
	double actualSampleRate;

	bool started;

	TIMESTAMP ts_initial, ts_offset;

	std::vector<double> tx_gains, rx_gains;

	struct ipc_sk_if_info_req current_info_req;
	struct ipc_sk_if_info_cnf current_info_cnf;
	struct ipc_sk_if_open_cnf current_open_cnf;

	std::vector<struct ipc_shm_io *> shm_io_rx_streams;
	std::vector<struct ipc_shm_io *> shm_io_tx_streams;

	bool flush_recv(size_t num_pkts);
	void update_stream_stats_rx(size_t chan, bool *overrun);
	void update_stream_stats_tx(size_t chan, bool *underrun);
	void manually_poll_sock_fds();

	void ipc_sock_close(ipc_per_trx_sock_state *state);

	int ipc_rx(uint8_t msg_type, struct ipc_sk_if *ipc_prim);
	int ipc_rx_greeting_cnf(const struct ipc_sk_if_greeting *greeting_cnf);
	int ipc_rx_info_cnf(const struct ipc_sk_if_info_cnf *info_cnf);
	int ipc_rx_open_cnf(const struct ipc_sk_if_open_cnf *open_cnf);
	int ipc_tx_open_req(struct ipc_per_trx_sock_state *state, uint32_t num_chans, uint32_t ref);

	int ipc_chan_rx(uint8_t msg_type, ipc_sk_chan_if *ipc_prim, uint8_t chan_nr);
	int ipc_rx_chan_start_cnf(ipc_sk_chan_if_op_rc *ret, uint8_t chan_nr);
	int ipc_rx_chan_stop_cnf(ipc_sk_chan_if_op_rc *ret, uint8_t chan_nr);
	int ipc_rx_chan_setgain_cnf(ipc_sk_chan_if_gain *ret, uint8_t chan_nr);
	int ipc_rx_chan_setfreq_cnf(ipc_sk_chan_if_freq_cnf *ret, uint8_t chan_nr);
	int ipc_rx_chan_notify_underflow(ipc_sk_chan_if_notfiy *ret, uint8_t chan_nr);
	int ipc_rx_chan_notify_overflow(ipc_sk_chan_if_notfiy *ret, uint8_t chan_nr);
	int ipc_rx_chan_settxattn_cnf(ipc_sk_chan_if_tx_attenuation *ret, uint8_t chan_nr);

	bool send_chan_wait_rsp(uint32_t chan, struct msgb *msg_to_send, uint32_t expected_rsp_msg_id);
	bool send_all_chan_wait_rsp(uint32_t msgid_to_send, uint32_t msgid_to_expect);

    public:
	int ipc_sock_read(struct osmo_fd *bfd);
	int ipc_sock_write(struct osmo_fd *bfd);
	int ipc_chan_sock_read(osmo_fd *bfd);
	int ipc_chan_sock_write(osmo_fd *bfd);

	/** Object constructor */
	IPCDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chan_num, double lo_offset,
		  const std::vector<std::string> &tx_paths, const std::vector<std::string> &rx_paths);
	virtual ~IPCDevice() override;

	/** Instantiate the IPC */
	virtual int open(const std::string &args, int ref, bool swap_channels) override;

	/** Start the IPC */
	virtual bool start() override;

	/** Stop the IPC */
	virtual bool stop() override;

	/* FIXME: any != USRP1 will do for now... */
	enum TxWindowType getWindowType() override
	{
		return TX_WINDOW_LMS1;
	}

	/**
	Read samples from the IPC.
	@param buf preallocated buf to contain read result
	@param len number of samples desired
	@param overrun Set if read buffer has been overrun, e.g. data not being read fast enough
	@param timestamp The timestamp of the first samples to be read
	@param underrun Set if IPC does not have data to transmit, e.g. data not being sent fast enough
	@return The number of samples actually read
	*/
	virtual int readSamples(std::vector<short *> &buf, int len, bool *overrun, TIMESTAMP timestamp = 0xffffffff,
				bool *underrun = NULL) override;
	/**
	Write samples to the IPC.
	@param buf Contains the data to be written.
	@param len number of samples to write.
	@param underrun Set if IPC does not have data to transmit, e.g. data not being sent fast enough
	@param timestamp The timestamp of the first sample of the data buffer.
	@return The number of samples actually written
	*/
	virtual int writeSamples(std::vector<short *> &bufs, int len, bool *underrun,
				 TIMESTAMP timestamp = 0xffffffff) override;

	/** Update the alignment between the read and write timestamps */
	virtual bool updateAlignment(TIMESTAMP timestamp) override;

	/** Set the transmitter frequency */
	virtual bool setTxFreq(double wFreq, size_t chan = 0) override;

	/** Set the receiver frequency */
	virtual bool setRxFreq(double wFreq, size_t chan = 0) override;

	/** Returns the starting write Timestamp*/
	virtual TIMESTAMP initialWriteTimestamp(void) override;

	/** Returns the starting read Timestamp*/
	virtual TIMESTAMP initialReadTimestamp(void) override;

	/** returns the full-scale transmit amplitude **/
	virtual double fullScaleInputValue() override
	{
		return (double)SHRT_MAX * current_info_cnf.iq_scaling_val_rx;
	}

	/** returns the full-scale receive amplitude **/
	virtual double fullScaleOutputValue() override
	{
		return (double)SHRT_MAX * current_info_cnf.iq_scaling_val_tx;
	}

	/** sets the receive chan gain, returns the gain setting **/
	virtual double setRxGain(double dB, size_t chan = 0) override;

	/** get the current receive gain */
	virtual double getRxGain(size_t chan = 0) override
	{
		return rx_gains[chan];
	}

	/** return maximum Rx Gain **/
	virtual double maxRxGain(void) override;

	/** return minimum Rx Gain **/
	virtual double minRxGain(void) override;

	double setPowerAttenuation(int atten, size_t chan) override;
	double getPowerAttenuation(size_t chan = 0) override;

	virtual int getNominalTxPower(size_t chan = 0) override;

	/** sets the RX path to use, returns true if successful and false otherwise */
	virtual bool setRxAntenna(const std::string &ant, size_t chan = 0) override;

	/* return the used RX path */
	virtual std::string getRxAntenna(size_t chan = 0) override;

	/** sets the RX path to use, returns true if successful and false otherwise */
	virtual bool setTxAntenna(const std::string &ant, size_t chan = 0) override;

	/* return the used RX path */
	virtual std::string getTxAntenna(size_t chan = 0) override;

	/** return whether user drives synchronization of Tx/Rx of USRP */
	virtual bool requiresRadioAlign() override;

	/** return whether user drives synchronization of Tx/Rx of USRP */
	virtual GSM::Time minLatency() override;

	/** Return internal status values */
	virtual inline double getTxFreq(size_t chan = 0) override
	{
		return 0;
	}
	virtual inline double getRxFreq(size_t chan = 0) override
	{
		return 0;
	}
	virtual inline double getSampleRate() override
	{
		return actualSampleRate;
	}
};

#endif // _IPC_DEVICE_H_