diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am index ade4e30b..2f636f40 100644 --- a/Transceiver52M/Makefile.am +++ b/Transceiver52M/Makefile.am @@ -104,3 +104,13 @@ osmo_trx_lms_LDADD = \ $(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 369e877a..8460a966 100644 --- a/Transceiver52M/device/Makefile.am +++ b/Transceiver52M/device/Makefile.am @@ -13,3 +13,7 @@ endif 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 00000000..2b99b397 --- /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}/../common +AM_CXXFLAGS = -lpthread $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_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 00000000..a3327f6c --- /dev/null +++ b/Transceiver52M/device/xtrx/XTRXDevice.cpp @@ -0,0 +1,456 @@ +/* +* Copyright 2018 Sergey Kostanbaev +* Copyright 2019 Alexander Chemeris +* + 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 . +*/ + + +#include +#include +#include +#include "Threads.h" +#include "XTRXDevice.h" + +#include +#include + +#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; + +XTRXDevice::XTRXDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chans, double lo_offset, + const std::vector& tx_paths, + const std::vector& 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; + txGain = 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, ¶ms); + 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; + } + LOG(NOTICE) << "Setting TX gain to " << dB << " dB."; + + int res = xtrx_set_gain(device, XTRX_CH_AB, XTRX_TX_PAD_GAIN, dB - 30, &txGain); + if (res) { + LOG(ERR) << "Error setting TX gain res: " << res; + } else { + LOG(NOTICE) << "Actual TX gain: " << txGain << " dB."; + } + + return txGain; +} + + +double XTRXDevice::setRxGain(double dB, size_t chan) +{ + if (chan) { + LOG(ALERT) << "Invalid channel " << chan; + return 0.0; + } + LOG(NOTICE) << "Setting RX gain to " << dB << " dB."; + + int res = xtrx_set_gain(device, XTRX_CH_AB, XTRX_RX_LNA_GAIN, dB, &rxGain); + if (res) { + LOG(ERR) << "Error setting RX gain res: " << res; + } else { + LOG(NOTICE) << "Actual RX gain: " << rxGain << " dB."; + } + + return rxGain; +} + +// NOTE: Assumes sequential reads +int XTRXDevice::readSamples(std::vector &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 &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() << " (SETTING RX ANTENNA IS NOT IMPLEMENTED)"; + 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() << " (SETTING TX ANTENNA IS NOT IMPLEMENTED)"; + 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 00000000..d4810e46 --- /dev/null +++ b/Transceiver52M/device/xtrx/XTRXDevice.h @@ -0,0 +1,180 @@ +#ifndef _XTRX_DEVICE_H_ +#define _XTRX_DEVICE_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "radioDevice.h" + +#include +#include +#include +#include + +#include "Threads.h" +#include + +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; + double txGain; + 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& tx_paths, + const std::vector& 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 &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 &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); + + /** gets the current transmit gain **/ + double getTxGain(size_t chan = 0) { return txGain; } + + /** 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 350c77c2..c0e49b6d 100644 --- a/configure.ac +++ b/configure.ac @@ -125,6 +125,11 @@ AC_ARG_WITH(lms, [ [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 @@ AS_IF([test "x$with_lms" = "xyes"], [ 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)], @@ -226,6 +235,7 @@ AS_IF([test "x$osmo_cv_cc_has___sync_fetch_and_and" = "xyes" && test "x$osmo_cv_ 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"]) @@ -310,6 +320,7 @@ AC_CONFIG_FILES([\ 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 800b1e1c..f418685a 100644 --- a/contrib/systemd/Makefile.am +++ b/contrib/systemd/Makefile.am @@ -18,5 +18,9 @@ if DEVICE_LMS 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 00000000..c1318127 --- /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 750f7b97..109704a3 100644 --- a/debian/control +++ b/debian/control @@ -91,6 +91,25 @@ Description: SDR transceiver that implements Layer 1 of a GSM BTS (LimeSuite) 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) + Package: osmo-trx-doc Architecture: all Section: doc diff --git a/debian/osmo-trx-xtrx.install b/debian/osmo-trx-xtrx.install new file mode 100644 index 00000000..86013467 --- /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 88d91421..4b528346 100644 --- a/doc/examples/Makefile.am +++ b/doc/examples/Makefile.am @@ -14,6 +14,10 @@ if DEVICE_LMS 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 00000000..173166d9 --- /dev/null +++ b/doc/examples/osmo-trx-xtrx/osmo-trx-xtrx.cfg @@ -0,0 +1,20 @@ +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