Change in osmo-trx[master]: add support for xtrx

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

lynxis lazus gerrit-no-reply at lists.osmocom.org
Mon May 13 16:13:38 UTC 2019


lynxis lazus has uploaded this change for review. ( https://gerrit.osmocom.org/14018


Change subject: add support for xtrx
......................................................................

add support for xtrx

Based on the github.com/xtrx-sdr/osmo-trx

Change-Id: Iad73e0611e7951d5bcfcc918063cc3778cb1dd8f
---
M Transceiver52M/Makefile.am
M Transceiver52M/device/Makefile.am
A Transceiver52M/device/xtrx/Makefile.am
A Transceiver52M/device/xtrx/XTRXDevice.cpp
A Transceiver52M/device/xtrx/XTRXDevice.h
M configure.ac
M contrib/systemd/Makefile.am
A contrib/systemd/osmo-trx-xtrx.service
M debian/control
A debian/osmo-trx-xtrx.install
M doc/examples/Makefile.am
A doc/examples/osmo-trx-xtrx/osmo-trx-xtrx.cfg
12 files changed, 729 insertions(+), 1 deletion(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/18/14018/1

diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am
index 89ab796..b8a9858 100644
--- a/Transceiver52M/Makefile.am
+++ b/Transceiver52M/Makefile.am
@@ -109,3 +109,13 @@
 	$(LMS_LIBS)
 osmo_trx_lms_CPPFLAGS  = $(AM_CPPFLAGS) $(LMS_CFLAGS)
 endif
+
+if DEVICE_XTRX
+bin_PROGRAMS += osmo-trx-xtrx
+osmo_trx_xtrx_SOURCES = osmo-trx.cpp
+osmo_trx_xtrx_LDADD = \
+	$(builddir)/device/xtrx/libdevice.la \
+	$(COMMON_LDADD) \
+	$(XTRX_LIBS)
+osmo_trx_xtrx_CPPFLAGS  = $(AM_CPPFLAGS) $(XTRX_CFLAGS)
+endif
diff --git a/Transceiver52M/device/Makefile.am b/Transceiver52M/device/Makefile.am
index 369e877..8460a96 100644
--- a/Transceiver52M/device/Makefile.am
+++ b/Transceiver52M/device/Makefile.am
@@ -13,3 +13,7 @@
 if DEVICE_LMS
 SUBDIRS += lms
 endif
+
+if DEVICE_XTRX
+SUBDIRS += xtrx
+endif
diff --git a/Transceiver52M/device/xtrx/Makefile.am b/Transceiver52M/device/xtrx/Makefile.am
new file mode 100644
index 0000000..b978d1a
--- /dev/null
+++ b/Transceiver52M/device/xtrx/Makefile.am
@@ -0,0 +1,10 @@
+include $(top_srcdir)/Makefile.common
+
+AM_CPPFLAGS = -Wall $(STD_DEFINES_AND_INCLUDES) -I${srcdir}/..
+AM_CXXFLAGS = -lpthread $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(XTRX_CFLAGS)
+
+noinst_HEADERS = XTRXDevice.h
+
+noinst_LTLIBRARIES = libdevice.la
+
+libdevice_la_SOURCES = XTRXDevice.cpp
diff --git a/Transceiver52M/device/xtrx/XTRXDevice.cpp b/Transceiver52M/device/xtrx/XTRXDevice.cpp
new file mode 100644
index 0000000..5f3cb79
--- /dev/null
+++ b/Transceiver52M/device/xtrx/XTRXDevice.cpp
@@ -0,0 +1,452 @@
+/*
+* Copyright 2018 Sergey Kostanbaev <sergey.kostanbaev at fairwaves.co>
+*
+	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/>.
+*/
+
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "Threads.h"
+#include "XTRXDevice.h"
+
+#include <Logger.h>
+#include <errno.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+using namespace std;
+
+const double defaultRXBandwidth = 0.5e6;
+const double defaultTXBandwidth = 1.5e6;
+
+static int time_tx_corr = 60; //20+20+20+20+20;
+
+XTRXDevice::XTRXDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chans, double lo_offset,
+					   const std::vector<std::string>& tx_paths,
+					   const std::vector<std::string>& rx_paths) :
+	RadioDevice(tx_sps, rx_sps, iface, chans, lo_offset, tx_paths, rx_paths)
+{
+	LOG(INFO) << "creating XTRX device:"
+			  << " RXSPS: " << rx_sps
+			  << " TXSPS: " << tx_sps
+			  << " chans: " << chans
+			  << " lo_off: " << lo_offset
+			  << " rx_path(0): " << (rx_paths.size() ? rx_paths[0] : "<>")
+			  << " tx_path(0): " << (tx_paths.size() ? tx_paths[0] : "<>");
+
+	txsps = tx_sps;
+	rxsps = rx_sps;
+
+	rxGain = 0;
+
+	loopback = false;
+	device = NULL;
+}
+
+static int parse_config(const char* line, const char* argument, int default_value)
+{
+	const char* arg_found = strstr(line, argument);
+	if (!arg_found)
+		return default_value;
+
+	const char* qe_pos = strchr(arg_found, '=');
+	if (!qe_pos)
+		return default_value;
+
+	int res = strtol(qe_pos + 1, NULL, 10);
+	if (res == 0 && errno) {
+		return default_value;
+	}
+
+	return res;
+}
+
+int XTRXDevice::open(const std::string &args, int ref, bool swap_channels)
+{
+	LOG(INFO) << "opening XTRX device '"  << args << "'..";
+
+	int loglevel = parse_config(args.c_str(), "loglevel", 3);
+	int lb_param = parse_config(args.c_str(), "loopback", 0);
+	time_tx_corr = parse_config(args.c_str(), "tcorr", time_tx_corr);
+	int fref     = parse_config(args.c_str(), "refclk", 26000000);
+	int rxdec    = parse_config(args.c_str(), "rxdec", 0);
+
+	char xtrx_name[500];
+	const char* lend = strchr(args.c_str(), ',');
+	int len = (lend) ? (lend - args.c_str()) : sizeof(xtrx_name) - 1;
+	strncpy(xtrx_name, args.c_str(), len);
+	xtrx_name[len] = 0;
+
+	if ((txsps % 2) || (rxsps % 2)) {
+		LOG(ALERT) << "XTRX TxSPS/RxSPS must be even!";
+		return -1;
+	}
+
+	if (lb_param) {
+		LOG(ALERT) << "XTRX LOOPBACK mode is set!";
+		loopback = true;
+	}
+
+	int res = xtrx_open(xtrx_name, loglevel, &device);
+	if (res) {
+		LOG(ALERT) << "XTRX creating failed, device " << xtrx_name << " code " << res;
+		return -1;
+	}
+	double actualMasterClock = 0;
+
+	if (fref > 0) {
+		xtrx_set_ref_clk(device, fref, XTRX_CLKSRC_INT);
+	}
+
+	res = xtrx_set_samplerate(device,
+							  GSMRATE * (double) std::min(txsps, rxsps)  * 32 * 4 * ((rxdec) ? 2 : 1),
+							  GSMRATE * (double) rxsps,
+							  GSMRATE * (double) txsps,
+							  (rxdec) ? XTRX_SAMPLERATE_FORCE_RX_DECIM : 0,
+							  &actualMasterClock,
+							  &actualRXSampleRate,
+							  &actualTXSampleRate);
+	if (res) {
+		LOG(ALERT) << "XTRX failed to set samplerate RX: " << GSMRATE * (double) rxsps
+				   << " TX: " << GSMRATE * (double) txsps
+				   << " res: " << res;
+		return -1;
+	} else {
+		LOG(INFO) << "XTRX set samplerate Master: " << actualMasterClock
+				  << " RX: " << actualRXSampleRate
+				  << " TX: " << actualTXSampleRate;
+	}
+
+	double bw;
+	double actualbw;
+
+	actualbw = 0;
+	bw = defaultRXBandwidth;
+	res = xtrx_tune_rx_bandwidth(device, XTRX_CH_AB, bw, &actualbw);
+	if (res) {
+		LOG(ALERT) << "XTRX failed to set RX bandwidth: " << bw
+				   << " res: " << res;
+	} else {
+		LOG(INFO) << "XTRX set RX bandwidth: " << actualbw;
+	}
+
+	actualbw = 0;
+	bw = defaultTXBandwidth;
+	res = xtrx_tune_tx_bandwidth(device, XTRX_CH_AB, bw, &actualbw);
+	if (res) {
+		LOG(ALERT) << "XTRX failed to set TX bandwidth: " << bw
+				   << " res: " << res;
+	} else {
+		LOG(INFO) << "XTRX set TX bandwidth: " << actualbw;
+	}
+
+	samplesRead = 0;
+	samplesWritten = 0;
+	started = false;
+
+	return NORMAL;
+}
+
+XTRXDevice::~XTRXDevice()
+{
+	if (device) {
+		xtrx_close(device);
+	}
+}
+
+bool XTRXDevice::start()
+{
+	LOG(INFO) << "starting XTRX...";
+	if (started) {
+		return false;
+	}
+
+	dataStart = 0;
+	dataEnd = 0;
+	timeStart = 0;
+	timeEnd = 0;
+	timeRx = initialReadTimestamp();
+	timestampOffset = 0;
+	latestWriteTimestamp = 0;
+	lastPktTimestamp = 0;
+	hi32Timestamp = 0;
+	isAligned = false;
+
+	xtrx_stop(device, XTRX_TX);
+	xtrx_stop(device, XTRX_RX);
+
+	xtrx_set_antenna(device, XTRX_TX_AUTO);
+	xtrx_set_antenna(device, XTRX_RX_AUTO);
+
+	xtrx_run_params_t params;
+	params.dir = XTRX_TRX;
+	params.nflags = (loopback) ? XTRX_RUN_DIGLOOPBACK : 0;
+
+	params.rx.chs = XTRX_CH_AB;
+	params.rx.flags = XTRX_RSP_SISO_MODE;
+	params.rx.hfmt = XTRX_IQ_INT16;
+	params.rx.wfmt = XTRX_WF_16;
+	params.rx.paketsize = 625 * rxsps;
+
+	params.tx.chs = XTRX_CH_AB;
+	params.tx.flags = XTRX_RSP_SISO_MODE;
+	params.tx.hfmt = XTRX_IQ_INT16;
+	params.tx.wfmt = XTRX_WF_16;
+	params.tx.paketsize = 625 * txsps;
+
+	if (loopback) {
+		params.tx.flags |= XTRX_RSP_SWAP_AB | XTRX_RSP_SWAP_IQ;
+	}
+
+	params.tx_repeat_buf = NULL;
+	params.rx_stream_start = initialReadTimestamp();
+
+	int res = xtrx_run_ex(device, &params);
+	if (res) {
+		LOG(ALERT) << "XTRX start failed res: " << res;
+	} else {
+		LOG(INFO) << "XTRX started";
+		started = true;
+	}
+	return started;
+}
+
+bool XTRXDevice::stop()
+{
+	if (started) {
+		int res = xtrx_stop(device, XTRX_TRX);
+		if (res) {
+			LOG(ALERT) << "XTRX stop failed res: " << res;
+		} else {
+			LOG(INFO) << "XTRX stopped";
+			started = false;
+		}
+	}
+	return !started;
+}
+
+TIMESTAMP XTRXDevice::initialWriteTimestamp()
+{
+	if (/*(iface == MULTI_ARFCN) || */(rxsps == txsps))
+		return initialReadTimestamp();
+	else
+		return initialReadTimestamp() * txsps;
+}
+
+double XTRXDevice::maxTxGain()
+{
+	return 30;
+}
+
+double XTRXDevice::minTxGain()
+{
+	return 0;
+}
+
+double XTRXDevice::maxRxGain()
+{
+	return 30;
+}
+
+double XTRXDevice::minRxGain()
+{
+	return 0;
+}
+
+double XTRXDevice::setTxGain(double dB, size_t chan)
+{
+	if (chan) {
+		LOG(ALERT) << "Invalid channel " << chan;
+		return 0.0;
+	}
+	double actual = 0;
+	LOG(NOTICE) << "Setting TX gain to " << dB << " dB.";
+
+	int res = xtrx_set_gain(device, XTRX_CH_AB, XTRX_TX_PAD_GAIN, dB - 30, &actual);
+	if (res) {
+		LOG(ERR) << "Error setting TX gain res: " << res;
+	}
+
+	return actual;
+}
+
+
+double XTRXDevice::setRxGain(double dB, size_t chan)
+{
+	if (chan) {
+		LOG(ALERT) << "Invalid channel " << chan;
+		return 0.0;
+	}
+	double actual = 0;
+	LOG(NOTICE) << "Setting RX gain to " << dB << " dB.";
+
+	int res = xtrx_set_gain(device, XTRX_CH_AB, XTRX_RX_LNA_GAIN, dB, &actual);
+	if (res) {
+		LOG(ERR) << "Error setting RX gain res: " << res;
+	}
+
+	return actual;
+}
+
+// NOTE: Assumes sequential reads
+int XTRXDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
+							TIMESTAMP timestamp, bool *underrun, unsigned *RSSI)
+{
+	if (!started)
+		return -1;
+
+	struct xtrx_recv_ex_info ri;
+	ri.samples = len;
+	ri.buffer_count = bufs.size();
+	ri.buffers = (void* const*)&bufs[0];
+	ri.flags = 0;
+
+	int res = xtrx_recv_sync_ex(device, &ri);
+	if (res) {
+		LOG(ALERT) << "xtrx_recv_sync failed res " << res << " current TS " << timeRx << " req TS" << timestamp;
+		return -1;
+	}
+	timeRx += len;
+
+	// TODO get rid of it!
+	int i;
+	for (i = 0; i < len * 2; i++)
+		bufs[0][i] <<= 4;
+
+	if (underrun) {
+		*underrun = (ri.out_events & RCVEX_EVENT_FILLED_ZERO);
+	}
+	return len;
+
+}
+
+int XTRXDevice::writeSamples(std::vector<short *> &bufs, int len,
+							 bool *underrun, unsigned long long timestamp,
+							 bool isControl)
+{
+	if (!started)
+		return 0;
+
+	xtrx_send_ex_info_t nfo;
+	nfo.buffers = (const void* const*)&bufs[0];
+	nfo.buffer_count = bufs.size();
+	nfo.flags = XTRX_TX_DONT_BUFFER;
+	nfo.samples = len;
+	nfo.ts = timestamp - time_tx_corr;
+
+	int res = xtrx_send_sync_ex(device, &nfo);
+	if (res != 0) {
+		LOG(ALERT) << "xtrx_send_sync_ex returned " << res << " len=" << len << " ts=" << timestamp;
+		return 0;
+	}
+
+	if (*underrun) {
+		*underrun = (nfo.out_flags & XTRX_TX_DISCARDED_TO);
+	}
+
+	return len;
+}
+
+bool XTRXDevice::setRxAntenna(const std::string & ant, size_t chan)
+{
+	LOG(ALERT) << "CH" << chan << ": RX ANTENNA: " << ant.c_str();
+	return true;
+}
+
+std::string XTRXDevice::getRxAntenna(size_t chan)
+{
+	return "";
+}
+
+bool XTRXDevice::setTxAntenna(const std::string & ant, size_t chan)
+{
+	LOG(ALERT) << "CH" << chan << ": TX ANTENNA: " << ant.c_str();
+	return true;
+}
+
+std::string XTRXDevice::getTxAntenna(size_t chan )
+{
+	return "";
+}
+
+
+bool XTRXDevice::requiresRadioAlign()
+{
+	return false;
+}
+
+GSM::Time XTRXDevice::minLatency()
+{
+	return GSM::Time(6,7);
+}
+
+bool XTRXDevice::updateAlignment(TIMESTAMP timestamp)
+{
+	LOG(ALERT) << "Update Aligment " << timestamp;
+	return true;
+}
+
+bool XTRXDevice::setTxFreq(double wFreq, size_t chan)
+{
+	int res;
+	double actual = 0;
+
+	if (chan) {
+		LOG(ALERT) << "Invalid channel " << chan;
+		return false;
+	}
+
+	if ((res = xtrx_tune(device, XTRX_TUNE_TX_FDD, wFreq, &actual)) == 0) {
+		LOG(INFO) << "set RX: " << wFreq << std::endl
+				  << "    actual freq: " << actual << std::endl;
+		return true;
+	}
+	else {
+		LOG(ALERT) << "set RX: " << wFreq << "failed (code: " << res << ")" << std::endl;
+		return false;
+	}
+}
+
+bool XTRXDevice::setRxFreq(double wFreq, size_t chan)
+{
+	int res;
+	double actual = 0;
+
+	if (chan) {
+		LOG(ALERT) << "Invalid channel " << chan;
+		return false;
+	}
+
+	if ((res = xtrx_tune(device, XTRX_TUNE_RX_FDD, wFreq, &actual)) == 0) {
+		LOG(INFO) << "set RX: " << wFreq << std::endl
+				  << "    actual freq: " << actual << std::endl;
+		return true;
+	}
+	else {
+		LOG(ALERT) << "set RX: " << wFreq << "failed (code: " << res << ")" << std::endl;
+		return false;
+	}
+}
+
+RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps,
+							   InterfaceType iface, size_t chans, double lo_offset,
+							   const std::vector < std::string > &tx_paths,
+							   const std::vector < std::string > &rx_paths)
+{
+	return new XTRXDevice(tx_sps, rx_sps, iface, chans, lo_offset, tx_paths, rx_paths);
+}
diff --git a/Transceiver52M/device/xtrx/XTRXDevice.h b/Transceiver52M/device/xtrx/XTRXDevice.h
new file mode 100644
index 0000000..86b2d01
--- /dev/null
+++ b/Transceiver52M/device/xtrx/XTRXDevice.h
@@ -0,0 +1,176 @@
+#ifndef _XTRX_DEVICE_H_
+#define _XTRX_DEVICE_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "radioDevice.h"
+
+#include <stdint.h>
+#include <sys/time.h>
+#include <string>
+#include <iostream>
+
+#include "Threads.h"
+#include <xtrx_api.h>
+
+class XTRXDevice: public RadioDevice {
+private:
+	int txsps;
+	int rxsps;
+	double actualTXSampleRate;	///< the actual XTRX sampling rate
+	double actualRXSampleRate;	///< the actual XTRX sampling rate
+	//unsigned int decimRate;	///< the XTRX decimation rate
+	//unsigned int interRate;	///< the XTRX decimation rate
+
+	unsigned long long samplesRead;	///< number of samples read from XTRX
+	unsigned long long samplesWritten;	///< number of samples sent to XTRX
+
+	bool started;			///< flag indicates XTRX has started
+
+	short *data;
+	unsigned long dataStart;
+	unsigned long dataEnd;
+	TIMESTAMP timeStart;
+	TIMESTAMP timeEnd;
+
+	TIMESTAMP timeRx;
+	bool isAligned;
+
+	Mutex writeLock;
+
+	short *currData;		///< internal data buffer when reading from XTRX
+	TIMESTAMP currTimestamp;	///< timestamp of internal data buffer
+	unsigned currLen;		///< size of internal data buffer
+
+	TIMESTAMP timestampOffset;       ///< timestamp offset b/w Tx and Rx blocks
+	TIMESTAMP latestWriteTimestamp;  ///< timestamp of most recent ping command
+	TIMESTAMP pingTimestamp;	   ///< timestamp of most recent ping response
+
+	unsigned long hi32Timestamp;
+	unsigned long lastPktTimestamp;
+
+	double rxGain;
+	bool loopback;
+
+	xtrx_dev* device;
+public:
+
+	/** Object constructor */
+	XTRXDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chans, double lo_offset,
+			   const std::vector<std::string>& tx_paths,
+			   const std::vector<std::string>& rx_paths);
+
+	~XTRXDevice();
+
+	/** Instantiate the XTRX */
+	int open(const std::string &args, int ref, bool swap_channels);
+
+	/** Start the XTRX */
+	bool start();
+
+	/** Stop the XTRX */
+	bool stop();
+
+	/** Set priority not supported */
+	void setPriority(float prio = 0.5) { }
+
+	enum TxWindowType getWindowType() { return TX_WINDOW_FIXED; }
+
+	/**
+	Read samples from the XTRX.
+	@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 XTRX does not have data to transmit, e.g. data not being sent fast enough
+	@param RSSI The received signal strength of the read result
+	@return The number of samples actually read
+	*/
+	int readSamples(std::vector<short *> &buf, int len, bool *overrun,
+					TIMESTAMP timestamp = 0xffffffff, bool *underrun = NULL,
+					unsigned *RSSI = NULL);
+	/**
+		Write samples to the XTRX.
+		@param buf Contains the data to be written.
+		@param len number of samples to write.
+		@param underrun Set if XTRX 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.
+		@param isControl Set if data is a control packet, e.g. a ping command
+		@return The number of samples actually written
+	*/
+	int writeSamples(std::vector<short *> &bufs, int len, bool *underrun,
+					 TIMESTAMP timestamp = 0xffffffff, bool isControl = false);
+
+	/** Update the alignment between the read and write timestamps */
+	bool updateAlignment(TIMESTAMP timestamp);
+
+	/** Set the transmitter frequency */
+	bool setTxFreq(double wFreq, size_t chan = 0);
+
+	/** Set the receiver frequency */
+	bool setRxFreq(double wFreq, size_t chan = 0);
+
+	/** Returns the starting write Timestamp*/
+	TIMESTAMP initialWriteTimestamp(void);
+
+	/** Returns the starting read Timestamp*/
+	TIMESTAMP initialReadTimestamp(void) { return 20000;}
+
+	/** returns the full-scale transmit amplitude **/
+	double fullScaleInputValue() {return (double) 32767*0.7;}
+
+	/** returns the full-scale receive amplitude **/
+	double fullScaleOutputValue() {return (double) 32767;}
+
+	/** sets the receive chan gain, returns the gain setting **/
+	double setRxGain(double dB, size_t chan = 0);
+
+	/** get the current receive gain */
+	double getRxGain(size_t chan = 0) { return rxGain; }
+
+	/** return maximum Rx Gain **/
+	double maxRxGain(void);
+
+	/** return minimum Rx Gain **/
+	double minRxGain(void);
+
+	/** sets the transmit chan gain, returns the gain setting **/
+	double setTxGain(double dB, size_t chan = 0);
+
+	/** return maximum Tx Gain **/
+	double maxTxGain(void);
+
+	/** return minimum Rx Gain **/
+	double minTxGain(void);
+
+	/** sets the RX path to use, returns true if successful and false otherwise */
+	bool setRxAntenna(const std::string & ant, size_t chan = 0);
+
+	/** return the used RX path */
+	std::string getRxAntenna(size_t chan = 0);
+
+	/** sets the RX path to use, returns true if successful and false otherwise */
+	bool setTxAntenna(const std::string & ant, size_t chan = 0);
+
+	/** return the used RX path */
+	std::string getTxAntenna(size_t chan = 0);
+
+	/** return whether user drives synchronization of Tx/Rx of USRP */
+	bool requiresRadioAlign();
+
+	/** return whether user drives synchronization of Tx/Rx of USRP */
+	virtual GSM::Time minLatency();
+
+	/** Return internal status values */
+	inline double getTxFreq(size_t chan = 0) { return 0; }
+	inline double getRxFreq(size_t chan = 0) { return 0; }
+	inline double getSampleRate() { return actualTXSampleRate; }
+	inline double numberRead() { return samplesRead; }
+	inline double numberWritten() { return samplesWritten; }
+
+};
+
+#endif // _XTRX_DEVICE_H_
+
diff --git a/configure.ac b/configure.ac
index e2a07f8..26a3844 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,6 +125,11 @@
         [enable LimeSuite based transceiver])
 ])
 
+AC_ARG_WITH(xtrx, [
+    AS_HELP_STRING([--with-xtrx],
+        [enable XTRX based transceiver])
+])
+
 AC_ARG_WITH(singledb, [
     AS_HELP_STRING([--with-singledb],
         [enable single daughterboard use on USRP1])
@@ -164,6 +169,10 @@
     PKG_CHECK_MODULES(LMS, LimeSuite)
 ])
 
+AS_IF([test "x$with_xtrx" = "xyes"], [
+    PKG_CHECK_MODULES(XTRX, libxtrx)
+])
+
 AS_IF([test "x$with_uhd" != "xno"],[
     PKG_CHECK_MODULES(UHD, uhd >= 003.011,
         [AC_DEFINE(USE_UHD_3_11, 1, UHD version 3.11.0 or higher)],
@@ -216,6 +225,7 @@
 AM_CONDITIONAL(DEVICE_UHD, [test "x$with_uhd" != "xno"])
 AM_CONDITIONAL(DEVICE_USRP1, [test "x$with_usrp1" = "xyes"])
 AM_CONDITIONAL(DEVICE_LMS, [test "x$with_lms" = "xyes"])
+AM_CONDITIONAL(DEVICE_XTRX, [test "x$with_xtrx" = "xyes"])
 AM_CONDITIONAL(ARCH_ARM, [test "x$with_neon" = "xyes" || test "x$with_neon_vfpv4" = "xyes"])
 AM_CONDITIONAL(ARCH_ARM_A15, [test "x$with_neon_vfpv4" = "xyes"])
 
@@ -300,6 +310,7 @@
     Transceiver52M/device/uhd/Makefile \
     Transceiver52M/device/usrp1/Makefile \
     Transceiver52M/device/lms/Makefile \
+    Transceiver52M/device/xtrx/Makefile \
     tests/Makefile \
     tests/CommonLibs/Makefile \
     tests/Transceiver52M/Makefile \
diff --git a/contrib/systemd/Makefile.am b/contrib/systemd/Makefile.am
index 800b1e1..7ccd293 100644
--- a/contrib/systemd/Makefile.am
+++ b/contrib/systemd/Makefile.am
@@ -1,7 +1,8 @@
 EXTRA_DIST = \
   osmo-trx-lms.service \
   osmo-trx-uhd.service \
-  osmo-trx-usrp1.service
+  osmo-trx-usrp1.service \
+  osmo-trx-xtrx.service
 
 if HAVE_SYSTEMD
 SYSTEMD_SERVICES =
@@ -18,5 +19,9 @@
 SYSTEMD_SERVICES += osmo-trx-lms.service
 endif
 
+if DEVICE_XTRX
+SYSTEMD_SERVICES += osmo-trx-xtrx.service
+endif
+
 systemdsystemunit_DATA = $(SYSTEMD_SERVICES)
 endif # HAVE_SYSTEMD
diff --git a/contrib/systemd/osmo-trx-xtrx.service b/contrib/systemd/osmo-trx-xtrx.service
new file mode 100644
index 0000000..c131812
--- /dev/null
+++ b/contrib/systemd/osmo-trx-xtrx.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Osmocom SDR BTS L1 Transceiver (XTRX backend)
+
+[Service]
+Type=simple
+Restart=always
+ExecStart=/usr/bin/osmo-trx-xtrx -C /etc/osmocom/osmo-trx-xtrx.cfg
+RestartSec=2
+
+[Install]
+WantedBy=multi-user.target
diff --git a/debian/control b/debian/control
index ffb9ac1..680bead 100644
--- a/debian/control
+++ b/debian/control
@@ -89,3 +89,22 @@
  3GPP is the "3rd Generation Partnership Project" which is the collaboration
  between different telecommunication associations for developing new
  generations of mobile phone networks. (post-2G/GSM)
+
+Package: osmo-trx-xtrx
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: SDR transceiver that implements Layer 1 of a GSM BTS (XTRX)
+ OsmoTRX is a software-defined radio transceiver that implements the Layer 1
+ physical layer of a BTS comprising the following 3GPP specifications:
+ .
+ TS 05.01 "Physical layer on the radio path"
+ TS 05.02 "Multiplexing and Multiple Access on the Radio Path"
+ TS 05.04 "Modulation"
+ TS 05.10 "Radio subsystem synchronization"
+ .
+ In this context, BTS is "Base transceiver station". It's the stations that
+ connect mobile phones to the mobile network.
+ .
+ 3GPP is the "3rd Generation Partnership Project" which is the collaboration
+ between different telecommunication associations for developing new
+ generations of mobile phone networks. (post-2G/GSM)
diff --git a/debian/osmo-trx-xtrx.install b/debian/osmo-trx-xtrx.install
new file mode 100644
index 0000000..8601346
--- /dev/null
+++ b/debian/osmo-trx-xtrx.install
@@ -0,0 +1,4 @@
+etc/osmocom/osmo-trx-xtrx.cfg
+lib/systemd/system/osmo-trx-xtrx.service
+/usr/bin/osmo-trx-xtrx
+/usr/share/doc/osmo-trx/examples/osmo-trx-xtrx/osmo-trx-xtrx.cfg /usr/share/doc/osmo-trx/examples/osmo-trx-xtrx/
diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am
index 88d9142..4b52834 100644
--- a/doc/examples/Makefile.am
+++ b/doc/examples/Makefile.am
@@ -14,6 +14,10 @@
 OSMOCONF_FILES += osmo-trx-lms/osmo-trx-lms.cfg
 endif
 
+if DEVICE_XTRX
+OSMOCONF_FILES += osmo-trx-xtrx/osmo-trx-xtrx.cfg
+endif
+
 osmoconf_DATA = $(OSMOCONF_FILES)
 EXTRA_DIST = $(OSMOCONF_FILES)
 
diff --git a/doc/examples/osmo-trx-xtrx/osmo-trx-xtrx.cfg b/doc/examples/osmo-trx-xtrx/osmo-trx-xtrx.cfg
new file mode 100644
index 0000000..e2c67d6
--- /dev/null
+++ b/doc/examples/osmo-trx-xtrx/osmo-trx-xtrx.cfg
@@ -0,0 +1,22 @@
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category 1
+ logging timestamp 1
+ logging print file basename
+ logging level set-all info
+!
+line vty
+ no login
+!
+trx
+ bind-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ base-port 5700
+ egprs disable
+ tx-sps 4
+ rx-sps 4
+ rt-prio 18
+ chan 0
+  tx-path BAND1
+  rx-path LNAW

-- 
To view, visit https://gerrit.osmocom.org/14018
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-trx
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iad73e0611e7951d5bcfcc918063cc3778cb1dd8f
Gerrit-Change-Number: 14018
Gerrit-PatchSet: 1
Gerrit-Owner: lynxis lazus <lynxis at fe80.eu>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190513/adaf4564/attachment.htm>


More information about the gerrit-log mailing list