aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/device/ipc/IPCDevice.h
diff options
context:
space:
mode:
authorEric Wild <ewild@sysmocom.de>2020-03-24 17:19:27 +0100
committerEric <ewild@sysmocom.de>2020-08-25 01:00:03 +0200
commit1e17c4fb0a77dcee49a7cd566dca7e8f48f6d8e7 (patch)
tree9e680f91408ff7741fe62d7689ad420c1f48648a /Transceiver52M/device/ipc/IPCDevice.h
parentf9a2f4427277f36b9459cd349512f6ca3230fe9c (diff)
osmo-trx-ipc
This adds a IPC backend that uses shared memory interface to communicate with (proprietary) devices. Requires config file option dev-args ipc_msock=/path/to/socket to specify the master socket the ipc backend should connect to. If UHD is avaialble the ipc-driver-test tool can be used to test the backend with a uhd device, this was so far only tested with a b2xx. Change-Id: Ice63d3499026293ade8aad675ff7a883bcdd5756
Diffstat (limited to 'Transceiver52M/device/ipc/IPCDevice.h')
-rw-r--r--Transceiver52M/device/ipc/IPCDevice.h239
1 files changed, 239 insertions, 0 deletions
diff --git a/Transceiver52M/device/ipc/IPCDevice.h b/Transceiver52M/device/ipc/IPCDevice.h
new file mode 100644
index 0000000..a7618f9
--- /dev/null
+++ b/Transceiver52M/device/ipc/IPCDevice.h
@@ -0,0 +1,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_