diff options
author | Eric Wild <ewild@sysmocom.de> | 2020-03-24 17:19:27 +0100 |
---|---|---|
committer | Eric <ewild@sysmocom.de> | 2020-08-25 01:00:03 +0200 |
commit | 1e17c4fb0a77dcee49a7cd566dca7e8f48f6d8e7 (patch) | |
tree | 9e680f91408ff7741fe62d7689ad420c1f48648a /Transceiver52M/device/ipc/IPCDevice.h | |
parent | f9a2f4427277f36b9459cd349512f6ca3230fe9c (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.h | 239 |
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_ |