mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
				synced 2025-11-03 05:33:16 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			master
			...
			Hoernchen/
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					ea6cec5014 | ||
| 
						 | 
					98a50b7597 | ||
| 
						 | 
					238891f161 | 
							
								
								
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
			
		||||
open_collective: osmocom
 | 
			
		||||
@@ -28,7 +28,7 @@ std::vector<std::string> comma_delimited_to_vector(const char* opt)
 | 
			
		||||
	{
 | 
			
		||||
	    std::string substr;
 | 
			
		||||
	    getline(ss, substr, ',');
 | 
			
		||||
	    result.push_back(std::move(substr));
 | 
			
		||||
	    result.push_back(substr);
 | 
			
		||||
	}
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -781,6 +781,17 @@ DEFUN(show_trx, show_trx_cmd,
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int trx_vty_is_config_node(struct vty *vty, int node)
 | 
			
		||||
{
 | 
			
		||||
	switch (node) {
 | 
			
		||||
	case TRX_NODE:
 | 
			
		||||
	case CHAN_NODE:
 | 
			
		||||
		return 1;
 | 
			
		||||
	default:
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int trx_vty_go_parent(struct vty *vty)
 | 
			
		||||
{
 | 
			
		||||
	switch (vty->node) {
 | 
			
		||||
@@ -818,6 +829,7 @@ struct vty_app_info g_vty_info = {
 | 
			
		||||
	.version	= PACKAGE_VERSION,
 | 
			
		||||
	.copyright	= trx_copyright,
 | 
			
		||||
	.go_parent_cb	= trx_vty_go_parent,
 | 
			
		||||
	.is_config_node	= trx_vty_is_config_node,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct trx_ctx *vty_trx_ctx_alloc(void *talloc_ctx)
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,7 @@ EXTRA_DIST = \
 | 
			
		||||
	LEGAL \
 | 
			
		||||
	COPYING \
 | 
			
		||||
	README.md \
 | 
			
		||||
	contrib/osmo-trx.spec.in \
 | 
			
		||||
	debian \
 | 
			
		||||
	git-version-gen \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								README.md
									
									
									
									
									
								
							@@ -4,17 +4,17 @@ About OsmoTRX
 | 
			
		||||
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*
 | 
			
		||||
* 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"
 | 
			
		||||
 | 
			
		||||
OsmoTRX is originally based on the transceiver code from the
 | 
			
		||||
[OpenBTS](https://osmocom.org/projects/osmobts/wiki/OpenBTS) project, but setup
 | 
			
		||||
to operate independently with the purpose of using with non-OpenBTS software and
 | 
			
		||||
projects, specifically within the Osmocom stack.  Used together with
 | 
			
		||||
[OsmoBTS](https://osmocom.org/projects/osmobts/wiki) you can get a pretty
 | 
			
		||||
standard GSM/GPRS/EGPRS BTS with Abis interface as per the relevant 3GPP specifications.
 | 
			
		||||
standard GSM BTS with Abis interface as per the relevant 3GPP specifications.
 | 
			
		||||
 | 
			
		||||
Homepage
 | 
			
		||||
--------
 | 
			
		||||
@@ -27,7 +27,7 @@ GIT Repository
 | 
			
		||||
 | 
			
		||||
You can clone from the official osmo-trx.git repository using
 | 
			
		||||
 | 
			
		||||
        git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-trx
 | 
			
		||||
        git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-trx`
 | 
			
		||||
 | 
			
		||||
There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-trx>
 | 
			
		||||
 | 
			
		||||
@@ -39,13 +39,6 @@ also available online for each of the sub-libraries at User Manual for OsmoTRX
 | 
			
		||||
can be generated during the build process, and is also available online at
 | 
			
		||||
<https://ftp.osmocom.org/docs/latest/osmotrx-usermanual.pdf>.
 | 
			
		||||
 | 
			
		||||
Forum
 | 
			
		||||
-----
 | 
			
		||||
 | 
			
		||||
We welcome any osmo-trx related discussions in the
 | 
			
		||||
[Cellular Network Infrastructure -> 2 RAN (GERAN)](https://discourse.osmocom.org/c/cni/geran)
 | 
			
		||||
section of the osmocom discourse (web based Forum).
 | 
			
		||||
 | 
			
		||||
Mailing List
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
@@ -57,20 +50,13 @@ Please observe the [Osmocom Mailing List
 | 
			
		||||
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
 | 
			
		||||
when posting.
 | 
			
		||||
 | 
			
		||||
Issue Tracker
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
We use the [issue tracker of the osmo-trx project on osmocom.org](https://osmocom.org/projects/osmotrx/issues) for
 | 
			
		||||
tracking the state of bug reports and feature requests.  Feel free to submit any issues you may find, or help
 | 
			
		||||
us out by resolving existing issues.
 | 
			
		||||
 | 
			
		||||
Contributing
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
Our coding standards are described at
 | 
			
		||||
<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
 | 
			
		||||
 | 
			
		||||
We use a Gerrit based patch submission/review process for managing contributions.
 | 
			
		||||
We us a gerrit based patch submission/review process for managing contributions.
 | 
			
		||||
Please see <https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit>
 | 
			
		||||
for more details
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
 | 
			
		||||
# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
 | 
			
		||||
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
 | 
			
		||||
# LIBVERSION=c:r:a
 | 
			
		||||
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
 | 
			
		||||
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a.
 | 
			
		||||
# If any interfaces have been added since the last public release: c:r:a + 1.
 | 
			
		||||
# If any interfaces have been removed or changed since the last public release: c:r:0.
 | 
			
		||||
#library	what			description / commit summary line
 | 
			
		||||
 
 | 
			
		||||
@@ -97,6 +97,7 @@ MS_UPPER_SRC = \
 | 
			
		||||
	ms/ms_upper.cpp \
 | 
			
		||||
	ms/l1ctl_server.c \
 | 
			
		||||
	ms/logging.c \
 | 
			
		||||
	ms/mssdr_vty.c \
 | 
			
		||||
	ms/l1ctl_server_cb.cpp \
 | 
			
		||||
	ms/ms_trxcon_if.cpp
 | 
			
		||||
 | 
			
		||||
@@ -110,6 +111,7 @@ noinst_HEADERS += \
 | 
			
		||||
	ms/itrq.h \
 | 
			
		||||
	ms/sch.h \
 | 
			
		||||
	ms/threadpool.h \
 | 
			
		||||
	ms/mssdr_vty.h \
 | 
			
		||||
	grgsm_vitac/viterbi_detector.h \
 | 
			
		||||
	grgsm_vitac/constants.h \
 | 
			
		||||
	grgsm_vitac/grgsm_vitac.h
 | 
			
		||||
 
 | 
			
		||||
@@ -150,7 +150,7 @@ static void lms_log_callback(int lvl, const char *msg)
 | 
			
		||||
{
 | 
			
		||||
	/* map lime specific log levels */
 | 
			
		||||
	static const int lvl_map[5] = {
 | 
			
		||||
		[LMS_LOG_CRITICAL] = LOGL_FATAL,
 | 
			
		||||
		[0] = LOGL_FATAL,
 | 
			
		||||
		[LMS_LOG_ERROR] = LOGL_ERROR,
 | 
			
		||||
		[LMS_LOG_WARNING] = LOGL_NOTICE,
 | 
			
		||||
		[LMS_LOG_INFO] = LOGL_INFO,
 | 
			
		||||
 
 | 
			
		||||
@@ -75,19 +75,18 @@ USRPDevice::USRPDevice(InterfaceType iface, const struct trx_cfg *cfg) : RadioDe
 | 
			
		||||
   * split sample rate Tx/Rx - 4/1 sps we need to need to
 | 
			
		||||
   * compensate for advance rather than delay.
 | 
			
		||||
   */
 | 
			
		||||
  pingOffset = 272;
 | 
			
		||||
 | 
			
		||||
  /* Split SPS (4/1) unsupported on USRP1
 | 
			
		||||
   * if(tx_sps == 4 && rx_sps == 1)
 | 
			
		||||
   *   pingOffset = 269 - 7500;
 | 
			
		||||
   */
 | 
			
		||||
  if (tx_sps == 1)
 | 
			
		||||
    pingOffset = 272;
 | 
			
		||||
  else if (tx_sps == 4)
 | 
			
		||||
    pingOffset = 269 - 7500;
 | 
			
		||||
  else
 | 
			
		||||
    pingOffset = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef SWLOOPBACK
 | 
			
		||||
  samplePeriod = 1.0e6/actualSampleRate;
 | 
			
		||||
  loopbackBufferSize = 0;
 | 
			
		||||
  gettimeofday(&lastReadTime,NULL);
 | 
			
		||||
  firstRead = false;
 | 
			
		||||
  pingOffset = 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -102,7 +101,7 @@ int USRPDevice::open()
 | 
			
		||||
  m_uRx.reset();
 | 
			
		||||
  try {
 | 
			
		||||
    m_uRx = usrp_standard_rx_sptr(usrp_standard_rx::make(
 | 
			
		||||
                                        0, decimRate, 1, -1,
 | 
			
		||||
                                        0, decimRate * tx_sps, 1, -1,
 | 
			
		||||
                                        usrp_standard_rx::FPGA_MODE_NORMAL,
 | 
			
		||||
                                        1024, 16 * 8, rbf));
 | 
			
		||||
    m_uRx->set_fpga_master_clock_freq(masterClockRate);
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,9 @@
 | 
			
		||||
#include <libbladeRF.h>
 | 
			
		||||
#include <Timeval.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
extern "C" {
 | 
			
		||||
#include "mssdr_vty.h"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const size_t BLADE_BUFFER_SIZE = 1024 * 1;
 | 
			
		||||
const size_t BLADE_NUM_BUFFERS = 32 * 1;
 | 
			
		||||
@@ -183,7 +186,6 @@ struct blade_otw_buffer_helper {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using dev_buf_t = typeof(blade_otw_buffer_helper<BLADE_BUFFER_SIZE, blade_speed_buffer_type::SS>::x);
 | 
			
		||||
// using buf_in_use = blade_otw_buffer<2, blade_speed_buffer_type::SS>;
 | 
			
		||||
using bh_fn_t = std::function<int(dev_buf_t *)>;
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
@@ -191,12 +193,11 @@ struct blade_hw {
 | 
			
		||||
	struct bladerf *dev;
 | 
			
		||||
	struct bladerf_stream *rx_stream;
 | 
			
		||||
	struct bladerf_stream *tx_stream;
 | 
			
		||||
	// using pkt2buf = blade_otw_buffer<2, blade_speed_buffer_type::SS>;
 | 
			
		||||
	using tx_buf_q_type = spsc_cond_timeout<BLADE_NUM_BUFFERS, dev_buf_t *, true, false>;
 | 
			
		||||
	const unsigned int rxFullScale, txFullScale;
 | 
			
		||||
	const int rxtxdelay;
 | 
			
		||||
	bool use_agc;
 | 
			
		||||
 | 
			
		||||
	float rxgain, txgain;
 | 
			
		||||
	static std::atomic<bool> stop_lower_threads_flag;
 | 
			
		||||
	double rxfreq_cache, txfreq_cache;
 | 
			
		||||
 | 
			
		||||
@@ -205,9 +206,13 @@ struct blade_hw {
 | 
			
		||||
		int rx_freq;
 | 
			
		||||
		int sample_rate;
 | 
			
		||||
		int bandwidth;
 | 
			
		||||
		float rxgain;
 | 
			
		||||
		float txgain;
 | 
			
		||||
 | 
			
		||||
	    public:
 | 
			
		||||
		ms_trx_config() : tx_freq(881e6), rx_freq(926e6), sample_rate(((1625e3 / 6) * 4)), bandwidth(1e6)
 | 
			
		||||
		ms_trx_config()
 | 
			
		||||
			: tx_freq(881e6), rx_freq(926e6), sample_rate(((1625e3 / 6) * 4)), bandwidth(1e6), rxgain(30),
 | 
			
		||||
			  txgain(30)
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
	} cfg;
 | 
			
		||||
@@ -223,10 +228,14 @@ struct blade_hw {
 | 
			
		||||
	{
 | 
			
		||||
		close_device();
 | 
			
		||||
	}
 | 
			
		||||
	blade_hw()
 | 
			
		||||
		: rxFullScale(2047), txFullScale(2047), rxtxdelay(-60), rxgain(30), txgain(30), rxfreq_cache(0),
 | 
			
		||||
	blade_hw(struct mssdr_cfg *cfgdata)
 | 
			
		||||
		: rxFullScale(2047), txFullScale(2047), rxtxdelay(-60), use_agc(cfgdata->use_agc), rxfreq_cache(0),
 | 
			
		||||
		  txfreq_cache(0)
 | 
			
		||||
	{
 | 
			
		||||
		cfg.tx_freq = cfgdata->overrides.ul_freq;
 | 
			
		||||
		cfg.rx_freq = cfgdata->overrides.dl_freq;
 | 
			
		||||
		cfg.rxgain = cfgdata->overrides.dl_gain;
 | 
			
		||||
		cfg.txgain = cfgdata->overrides.ul_gain;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void close_device()
 | 
			
		||||
@@ -251,6 +260,7 @@ struct blade_hw {
 | 
			
		||||
	int init_device(bh_fn_t rxh, bh_fn_t txh)
 | 
			
		||||
	{
 | 
			
		||||
		struct bladerf_rational_rate rate = { 0, static_cast<uint64_t>((1625e3 * 4)) * 64, 6 * 64 }, actual;
 | 
			
		||||
		std::cerr << "cfg: ul " << cfg.tx_freq << " dl " << cfg.rx_freq << std::endl;
 | 
			
		||||
 | 
			
		||||
		bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_DEBUG);
 | 
			
		||||
		bladerf_set_usb_reset_on_open(true);
 | 
			
		||||
@@ -294,9 +304,10 @@ struct blade_hw {
 | 
			
		||||
		blade_check(bladerf_set_bandwidth, dev, BLADERF_CHANNEL_TX(0), (bladerf_bandwidth)cfg.bandwidth,
 | 
			
		||||
			    (bladerf_bandwidth *)NULL);
 | 
			
		||||
 | 
			
		||||
		blade_check(bladerf_set_gain_mode, dev, BLADERF_CHANNEL_RX(0), BLADERF_GAIN_MGC);
 | 
			
		||||
		setRxGain(rxgain, 0);
 | 
			
		||||
		setTxGain(txgain, 0);
 | 
			
		||||
		blade_check(bladerf_set_gain_mode, dev, BLADERF_CHANNEL_RX(0),
 | 
			
		||||
			    use_agc ? BLADERF_GAIN_AUTOMATIC : BLADERF_GAIN_MGC);
 | 
			
		||||
		setRxGain(cfg.rxgain, 0);
 | 
			
		||||
		setTxGain(cfg.txgain, 0);
 | 
			
		||||
		usleep(1000);
 | 
			
		||||
 | 
			
		||||
		bladerf_set_stream_timeout(dev, BLADERF_TX, 10);
 | 
			
		||||
@@ -350,7 +361,7 @@ struct blade_hw {
 | 
			
		||||
 | 
			
		||||
	double setRxGain(double dB, size_t chan = 0)
 | 
			
		||||
	{
 | 
			
		||||
		rxgain = dB;
 | 
			
		||||
		cfg.rxgain = dB;
 | 
			
		||||
		msleep(15);
 | 
			
		||||
		blade_check(bladerf_set_gain, dev, BLADERF_CHANNEL_RX(0), (bladerf_gain)dB);
 | 
			
		||||
		msleep(15);
 | 
			
		||||
@@ -358,7 +369,7 @@ struct blade_hw {
 | 
			
		||||
	};
 | 
			
		||||
	double setTxGain(double dB, size_t chan = 0)
 | 
			
		||||
	{
 | 
			
		||||
		txgain = dB;
 | 
			
		||||
		cfg.txgain = dB;
 | 
			
		||||
		msleep(15);
 | 
			
		||||
		blade_check(bladerf_set_gain, dev, BLADERF_CHANNEL_TX(0), (bladerf_gain)dB);
 | 
			
		||||
		msleep(15);
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ class spsc_cond_timeout_detail {
 | 
			
		||||
	std::condition_variable cond_r, cond_w;
 | 
			
		||||
	std::mutex lr, lw;
 | 
			
		||||
	std::atomic_int r_flag, w_flag;
 | 
			
		||||
	const int timeout_ms = 200;
 | 
			
		||||
	const int timeout_ms = 600;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
	explicit spsc_cond_timeout_detail() : r_flag(0), w_flag(0)
 | 
			
		||||
 
 | 
			
		||||
@@ -22,19 +22,13 @@
 | 
			
		||||
#include "GSMCommon.h"
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <complex>
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
 | 
			
		||||
#include "ms.h"
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
#include "sch.h"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "threadsched.h"
 | 
			
		||||
 | 
			
		||||
dummylog ms_trx::dummy_log;
 | 
			
		||||
 
 | 
			
		||||
@@ -181,7 +181,6 @@ class time_keeper {
 | 
			
		||||
		std::lock_guard<std::mutex> g(m);
 | 
			
		||||
		global_time_keeper.incTN(1);
 | 
			
		||||
		global_ts_keeper = new_ts;
 | 
			
		||||
		// std::cerr << "u " << new_ts << std::endl;
 | 
			
		||||
	}
 | 
			
		||||
	void inc_and_update_safe(int64_t new_ts)
 | 
			
		||||
	{
 | 
			
		||||
@@ -191,7 +190,6 @@ class time_keeper {
 | 
			
		||||
		assert(diff > 0.5 * ONE_TS_BURST_LEN);
 | 
			
		||||
		global_time_keeper.incTN(1);
 | 
			
		||||
		global_ts_keeper = new_ts;
 | 
			
		||||
		// std::cerr << "s " << new_ts << std::endl;
 | 
			
		||||
	}
 | 
			
		||||
	void dec_by_one()
 | 
			
		||||
	{
 | 
			
		||||
@@ -217,8 +215,6 @@ class time_keeper {
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using ts_hitter_q_t = spsc_cond<64, GSM::Time, true, false>;
 | 
			
		||||
 | 
			
		||||
// used to globally initialize the sched/hw information
 | 
			
		||||
struct sched_hw_info {
 | 
			
		||||
	int hw_cpus;
 | 
			
		||||
@@ -239,7 +235,7 @@ struct ms_trx : public BASET, public sched_hw_info {
 | 
			
		||||
	unsigned int mTSC;
 | 
			
		||||
	unsigned int mBSIC;
 | 
			
		||||
	int timing_advance;
 | 
			
		||||
	bool do_auto_gain;
 | 
			
		||||
	bool use_va;
 | 
			
		||||
 | 
			
		||||
	pthread_t lower_rx_task;
 | 
			
		||||
	pthread_t lower_tx_task;
 | 
			
		||||
@@ -276,8 +272,8 @@ struct ms_trx : public BASET, public sched_hw_info {
 | 
			
		||||
	void *tx_cb();
 | 
			
		||||
	void maybe_update_gain(one_burst &brst);
 | 
			
		||||
 | 
			
		||||
	ms_trx()
 | 
			
		||||
		: mTSC(0), mBSIC(0), timing_advance(0), do_auto_gain(false), rxqueue(),
 | 
			
		||||
	ms_trx(struct mssdr_cfg *cfgdata)
 | 
			
		||||
		: BASET(cfgdata), mTSC(0), mBSIC(0), timing_advance(0), use_va(cfgdata->use_va), rxqueue(),
 | 
			
		||||
		  first_sch_buf(new blade_sample_type[SCH_LEN_SPS]),
 | 
			
		||||
		  burst_copy_buffer(new blade_sample_type[ONE_TS_BURST_LEN]), first_sch_buf_rcv_ts(0),
 | 
			
		||||
		  rcv_done{ false }, sch_thread_done{ false }, upper_is_ready(false)
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,8 @@ extern "C" {
 | 
			
		||||
 | 
			
		||||
#define PRINT_Q_OVERFLOW
 | 
			
		||||
 | 
			
		||||
extern std::atomic<bool> g_exit_flag;
 | 
			
		||||
 | 
			
		||||
bool ms_trx::decode_sch(char *bits, bool update_global_clock)
 | 
			
		||||
{
 | 
			
		||||
	int fn;
 | 
			
		||||
@@ -87,8 +89,6 @@ bool ms_trx::decode_sch(char *bits, bool update_global_clock)
 | 
			
		||||
			mBSIC = sch.bsic;
 | 
			
		||||
			mTSC = sch.bsic & 0x7;
 | 
			
		||||
			timekeeper.set(fn, 0);
 | 
			
		||||
			// global_time_keeper.FN(fn);
 | 
			
		||||
			// global_time_keeper.TN(0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
@@ -108,12 +108,12 @@ void ms_trx::maybe_update_gain(one_burst &brst)
 | 
			
		||||
	runmean = gain_check ? (runmean * (gain_check + 2) - 1 + sum) / (gain_check + 2) : sum;
 | 
			
		||||
 | 
			
		||||
	if (gain_check == avgburst_num - 1) {
 | 
			
		||||
		DBGLG2() << "\x1B[32m #RXG \033[0m" << rxgain << " " << runmean << " " << sum << std::endl;
 | 
			
		||||
		DBGLG2() << "\x1B[32m #RXG \033[0m" << cfg.rxgain << " " << runmean << " " << sum << std::endl;
 | 
			
		||||
		auto gainoffset = runmean < (rxFullScale / 4 ? 4 : 2);
 | 
			
		||||
		gainoffset = runmean < (rxFullScale / 2 ? 2 : 1);
 | 
			
		||||
		float newgain = runmean < rx_max_cutoff ? rxgain + gainoffset : rxgain - gainoffset;
 | 
			
		||||
		float newgain = runmean < rx_max_cutoff ? cfg.rxgain + gainoffset : cfg.rxgain - gainoffset;
 | 
			
		||||
		// FIXME: gian cutoff
 | 
			
		||||
		if (newgain != rxgain && newgain <= 60) {
 | 
			
		||||
		if (newgain != cfg.rxgain && newgain <= 60) {
 | 
			
		||||
			auto gain_fun = [this, newgain] { setRxGain(newgain); };
 | 
			
		||||
			worker_thread.add_task(gain_fun);
 | 
			
		||||
		}
 | 
			
		||||
@@ -141,10 +141,10 @@ bool ms_trx::handle_sch_or_nb()
 | 
			
		||||
		memcpy(brst.sch_bits, sch_demod_bits, sizeof(sch_demod_bits));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (upper_is_ready && !rxqueue.spsc_push(&brst))
 | 
			
		||||
	while (!g_exit_flag && upper_is_ready && !rxqueue.spsc_push(&brst))
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
	if (do_auto_gain)
 | 
			
		||||
	if (!use_agc)
 | 
			
		||||
		maybe_update_gain(brst);
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
@@ -158,24 +158,24 @@ bool ms_trx::handle_sch(bool is_first_sch_acq)
 | 
			
		||||
	const auto buf_len = is_first_sch_acq ? SCH_LEN_SPS : ONE_TS_BURST_LEN;
 | 
			
		||||
	const auto which_in_buffer = is_first_sch_acq ? first_sch_buf : burst_copy_buffer;
 | 
			
		||||
	memset((void *)&sch_acq_buffer[0], 0, sizeof(sch_acq_buffer));
 | 
			
		||||
#if 1
 | 
			
		||||
	const auto which_out_buffer = is_first_sch_acq ? sch_acq_buffer : &sch_acq_buffer[40 * 2];
 | 
			
		||||
	const auto ss = reinterpret_cast<std::complex<float> *>(which_out_buffer);
 | 
			
		||||
	std::complex<float> channel_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
 | 
			
		||||
	int start;
 | 
			
		||||
	convert_and_scale(which_out_buffer, which_in_buffer, buf_len * 2, 1.f / float(rxFullScale));
 | 
			
		||||
	if (is_first_sch_acq) {
 | 
			
		||||
		float max_corr = 0;
 | 
			
		||||
		start = get_sch_buffer_chan_imp_resp(ss, &channel_imp_resp[0], buf_len, &max_corr);
 | 
			
		||||
	} else {
 | 
			
		||||
		start = get_sch_chan_imp_resp(ss, &channel_imp_resp[0]);
 | 
			
		||||
		start = start < 39 ? start : 39;
 | 
			
		||||
		start = start > -39 ? start : -39;
 | 
			
		||||
	}
 | 
			
		||||
	detect_burst_nb(&ss[start], &channel_imp_resp[0], 0, sch_demod_bits);
 | 
			
		||||
	if (use_va) {
 | 
			
		||||
		const auto which_out_buffer = is_first_sch_acq ? sch_acq_buffer : &sch_acq_buffer[40 * 2];
 | 
			
		||||
		const auto ss = reinterpret_cast<std::complex<float> *>(which_out_buffer);
 | 
			
		||||
		std::complex<float> channel_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
 | 
			
		||||
		int start;
 | 
			
		||||
		convert_and_scale(which_out_buffer, which_in_buffer, buf_len * 2, 1.f / float(rxFullScale));
 | 
			
		||||
		if (is_first_sch_acq) {
 | 
			
		||||
			float max_corr = 0;
 | 
			
		||||
			start = get_sch_buffer_chan_imp_resp(ss, &channel_imp_resp[0], buf_len, &max_corr);
 | 
			
		||||
		} else {
 | 
			
		||||
			start = get_sch_chan_imp_resp(ss, &channel_imp_resp[0]);
 | 
			
		||||
			start = start < 39 ? start : 39;
 | 
			
		||||
			start = start > -39 ? start : -39;
 | 
			
		||||
		}
 | 
			
		||||
		detect_burst_nb(&ss[start], &channel_imp_resp[0], 0, sch_demod_bits);
 | 
			
		||||
 | 
			
		||||
	auto sch_decode_success = decode_sch(sch_demod_bits, is_first_sch_acq);
 | 
			
		||||
#if 0
 | 
			
		||||
		auto sch_decode_success = decode_sch(sch_demod_bits, is_first_sch_acq);
 | 
			
		||||
#if 0 // useful to debug offset shifts
 | 
			
		||||
	auto burst = new signalVector(buf_len, 50);
 | 
			
		||||
	const auto corr_type = is_first_sch_acq ? sch_detect_type::SCH_DETECT_BUFFER : sch_detect_type::SCH_DETECT_FULL;
 | 
			
		||||
	struct estim_burst_params ebp;
 | 
			
		||||
@@ -189,113 +189,113 @@ bool ms_trx::handle_sch(bool is_first_sch_acq)
 | 
			
		||||
	std::cerr << "ooffs: " << howmuchdelay << " " << std::endl;
 | 
			
		||||
	std::cerr << "voffs: " << start << " " << sch_decode_success << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
	if (sch_decode_success) {
 | 
			
		||||
		const auto ts_offset_symb = 4;
 | 
			
		||||
		if (is_first_sch_acq) {
 | 
			
		||||
			// update ts to first sample in sch buffer, to allow delay calc for current ts
 | 
			
		||||
			first_sch_ts_start = first_sch_buf_rcv_ts + start - (ts_offset_symb * 4) - 1;
 | 
			
		||||
		} else if (abs(start) > 1) {
 | 
			
		||||
			// continuous sch tracking, only update if off too much
 | 
			
		||||
			temp_ts_corr_offset += -start;
 | 
			
		||||
			std::cerr << "offs: " << start << " " << temp_ts_corr_offset << std::endl;
 | 
			
		||||
		if (sch_decode_success) {
 | 
			
		||||
			const auto ts_offset_symb = 4;
 | 
			
		||||
			if (is_first_sch_acq) {
 | 
			
		||||
				// update ts to first sample in sch buffer, to allow delay calc for current ts
 | 
			
		||||
				first_sch_ts_start = first_sch_buf_rcv_ts + start - (ts_offset_symb * 4) - 1;
 | 
			
		||||
			} else if (abs(start) > 1) {
 | 
			
		||||
				// continuous sch tracking, only update if off too much
 | 
			
		||||
				temp_ts_corr_offset += -start;
 | 
			
		||||
				std::cerr << "offs: " << start << " " << temp_ts_corr_offset << std::endl;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return true;
 | 
			
		||||
		} else {
 | 
			
		||||
			DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << start << " "
 | 
			
		||||
				 << current_gsm_time.FN() << ":" << current_gsm_time.TN() << std::endl;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	} else {
 | 
			
		||||
		DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << start << " " << current_gsm_time.FN()
 | 
			
		||||
			 << ":" << current_gsm_time.TN() << std::endl;
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	const auto ts_offset_symb = 4;
 | 
			
		||||
	auto burst = new signalVector(buf_len, 50);
 | 
			
		||||
	const auto corr_type = is_first_sch_acq ? sch_detect_type::SCH_DETECT_BUFFER : sch_detect_type::SCH_DETECT_FULL;
 | 
			
		||||
	struct estim_burst_params ebp;
 | 
			
		||||
		const auto ts_offset_symb = 4;
 | 
			
		||||
		auto burst = new signalVector(buf_len, 50);
 | 
			
		||||
		const auto corr_type =
 | 
			
		||||
			is_first_sch_acq ? sch_detect_type::SCH_DETECT_BUFFER : sch_detect_type::SCH_DETECT_FULL;
 | 
			
		||||
		struct estim_burst_params ebp;
 | 
			
		||||
 | 
			
		||||
	// scale like uhd, +-2k -> +-32k
 | 
			
		||||
	convert_and_scale(burst->begin(), which_in_buffer, buf_len * 2, SAMPLE_SCALE_FACTOR);
 | 
			
		||||
		// scale like uhd, +-2k -> +-32k
 | 
			
		||||
		convert_and_scale(burst->begin(), which_in_buffer, buf_len * 2, SAMPLE_SCALE_FACTOR);
 | 
			
		||||
 | 
			
		||||
	auto rv = detectSCHBurst(*burst, 4, 4, corr_type, &ebp);
 | 
			
		||||
		auto rv = detectSCHBurst(*burst, 4, 4, corr_type, &ebp);
 | 
			
		||||
 | 
			
		||||
	int howmuchdelay = ebp.toa * 4;
 | 
			
		||||
		int howmuchdelay = ebp.toa * 4;
 | 
			
		||||
 | 
			
		||||
	if (!rv) {
 | 
			
		||||
		delete burst;
 | 
			
		||||
		DBGLG() << "SCH : \x1B[31m detect fail \033[0m NOOOOOOOOOOOOOOOOOO toa:" << ebp.toa << " "
 | 
			
		||||
			<< current_gsm_time.FN() << ":" << current_gsm_time.TN() << std::endl;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SoftVector *bits;
 | 
			
		||||
	if (is_first_sch_acq) {
 | 
			
		||||
		// can't be legit with a buf size spanning _at least_ one SCH but delay that implies partial sch burst
 | 
			
		||||
		if (howmuchdelay < 0 || (buf_len - howmuchdelay) < ONE_TS_BURST_LEN) {
 | 
			
		||||
		if (!rv) {
 | 
			
		||||
			delete burst;
 | 
			
		||||
			DBGLG() << "SCH : \x1B[31m detect fail \033[0m NOOOOOOOOOOOOOOOOOO toa:" << ebp.toa << " "
 | 
			
		||||
				<< current_gsm_time.FN() << ":" << current_gsm_time.TN() << std::endl;
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		struct estim_burst_params ebp2;
 | 
			
		||||
		// auto sch_chunk = new signalVector(ONE_TS_BURST_LEN, 50);
 | 
			
		||||
		// auto sch_chunk_start = sch_chunk->begin();
 | 
			
		||||
		// memcpy(sch_chunk_start, sch_buf_f.data() + howmuchdelay, sizeof(std::complex<float>) * ONE_TS_BURST_LEN);
 | 
			
		||||
 | 
			
		||||
		auto delay = delayVector(burst, NULL, -howmuchdelay);
 | 
			
		||||
 | 
			
		||||
		scaleVector(*delay, (complex)1.0 / ebp.amp);
 | 
			
		||||
 | 
			
		||||
		auto rv2 = detectSCHBurst(*delay, 4, 4, sch_detect_type::SCH_DETECT_FULL, &ebp2);
 | 
			
		||||
		DBGLG() << "FIRST SCH : " << (rv2 ? "yes " : "   ") << "Timing offset     " << ebp2.toa << " symbols"
 | 
			
		||||
			<< std::endl;
 | 
			
		||||
 | 
			
		||||
		bits = demodAnyBurst(*delay, SCH, 4, &ebp2);
 | 
			
		||||
		delete delay;
 | 
			
		||||
	} else {
 | 
			
		||||
		bits = demodAnyBurst(*burst, SCH, 4, &ebp);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	delete burst;
 | 
			
		||||
 | 
			
		||||
	// clamp to +-1.5 because +-127 softbits scaled by 64 after -0.5 can be at most +-1.5
 | 
			
		||||
	clamp_array(bits->begin(), 148, 1.5f);
 | 
			
		||||
 | 
			
		||||
	float_to_sbit(&bits->begin()[0], (signed char *)&sch_demod_bits[0], 62, 148);
 | 
			
		||||
	// float_to_sbit(&bits->begin()[106], &data[39], 62, 39);
 | 
			
		||||
 | 
			
		||||
	if (decode_sch((char *)sch_demod_bits, is_first_sch_acq)) {
 | 
			
		||||
		auto current_gsm_time_updated = timekeeper.gsmtime();
 | 
			
		||||
		SoftVector *bits;
 | 
			
		||||
		if (is_first_sch_acq) {
 | 
			
		||||
			// update ts to first sample in sch buffer, to allow delay calc for current ts
 | 
			
		||||
			first_sch_ts_start = first_sch_buf_rcv_ts + howmuchdelay - (ts_offset_symb * 4);
 | 
			
		||||
		} else {
 | 
			
		||||
			// continuous sch tracking, only update if off too much
 | 
			
		||||
			auto diff = [](float x, float y) { return x > y ? x - y : y - x; };
 | 
			
		||||
 | 
			
		||||
			auto d = diff(ebp.toa, ts_offset_symb);
 | 
			
		||||
			if (abs(d) > 0.3) {
 | 
			
		||||
				if (ebp.toa < ts_offset_symb)
 | 
			
		||||
					ebp.toa = d;
 | 
			
		||||
				else
 | 
			
		||||
					ebp.toa = -d;
 | 
			
		||||
				temp_ts_corr_offset += ebp.toa * 4;
 | 
			
		||||
 | 
			
		||||
				DBGLG() << "offs: " << ebp.toa << " " << temp_ts_corr_offset << std::endl;
 | 
			
		||||
			// can't be legit with a buf size spanning _at least_ one SCH but delay that implies partial sch burst
 | 
			
		||||
			if (howmuchdelay < 0 || (buf_len - howmuchdelay) < ONE_TS_BURST_LEN) {
 | 
			
		||||
				delete burst;
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			struct estim_burst_params ebp2;
 | 
			
		||||
			// auto sch_chunk = new signalVector(ONE_TS_BURST_LEN, 50);
 | 
			
		||||
			// auto sch_chunk_start = sch_chunk->begin();
 | 
			
		||||
			// memcpy(sch_chunk_start, sch_buf_f.data() + howmuchdelay, sizeof(std::complex<float>) * ONE_TS_BURST_LEN);
 | 
			
		||||
 | 
			
		||||
			auto delay = delayVector(burst, NULL, -howmuchdelay);
 | 
			
		||||
 | 
			
		||||
			scaleVector(*delay, (complex)1.0 / ebp.amp);
 | 
			
		||||
 | 
			
		||||
			auto rv2 = detectSCHBurst(*delay, 4, 4, sch_detect_type::SCH_DETECT_FULL, &ebp2);
 | 
			
		||||
			DBGLG() << "FIRST SCH : " << (rv2 ? "yes " : "   ") << "Timing offset     " << ebp2.toa
 | 
			
		||||
				<< " symbols" << std::endl;
 | 
			
		||||
 | 
			
		||||
			bits = demodAnyBurst(*delay, SCH, 4, &ebp2);
 | 
			
		||||
			delete delay;
 | 
			
		||||
		} else {
 | 
			
		||||
			bits = demodAnyBurst(*burst, SCH, 4, &ebp);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		auto a = gsm_sch_check_fn(current_gsm_time_updated.FN() - 1);
 | 
			
		||||
		auto b = gsm_sch_check_fn(current_gsm_time_updated.FN());
 | 
			
		||||
		auto c = gsm_sch_check_fn(current_gsm_time_updated.FN() + 1);
 | 
			
		||||
		DBGLG() << "L SCH : Timing offset     " << rv << " " << ebp.toa << " " << a << b << c << "fn "
 | 
			
		||||
			<< current_gsm_time_updated.FN() << ":" << current_gsm_time_updated.TN() << std::endl;
 | 
			
		||||
		delete burst;
 | 
			
		||||
 | 
			
		||||
		// clamp to +-1.5 because +-127 softbits scaled by 64 after -0.5 can be at most +-1.5
 | 
			
		||||
		clamp_array(bits->begin(), 148, 1.5f);
 | 
			
		||||
 | 
			
		||||
		float_to_sbit(&bits->begin()[0], (signed char *)&sch_demod_bits[0], 62, 148);
 | 
			
		||||
 | 
			
		||||
		if (decode_sch((char *)sch_demod_bits, is_first_sch_acq)) {
 | 
			
		||||
			auto current_gsm_time_updated = timekeeper.gsmtime();
 | 
			
		||||
			if (is_first_sch_acq) {
 | 
			
		||||
				// update ts to first sample in sch buffer, to allow delay calc for current ts
 | 
			
		||||
				first_sch_ts_start = first_sch_buf_rcv_ts + howmuchdelay - (ts_offset_symb * 4);
 | 
			
		||||
			} else {
 | 
			
		||||
				// continuous sch tracking, only update if off too much
 | 
			
		||||
				auto diff = [](float x, float y) { return x > y ? x - y : y - x; };
 | 
			
		||||
 | 
			
		||||
				auto d = diff(ebp.toa, ts_offset_symb);
 | 
			
		||||
				if (abs(d) > 0.3) {
 | 
			
		||||
					if (ebp.toa < ts_offset_symb)
 | 
			
		||||
						ebp.toa = d;
 | 
			
		||||
					else
 | 
			
		||||
						ebp.toa = -d;
 | 
			
		||||
					temp_ts_corr_offset += ebp.toa * 4;
 | 
			
		||||
 | 
			
		||||
					DBGLG() << "offs: " << ebp.toa << " " << temp_ts_corr_offset << std::endl;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			auto a = gsm_sch_check_fn(current_gsm_time_updated.FN() - 1);
 | 
			
		||||
			auto b = gsm_sch_check_fn(current_gsm_time_updated.FN());
 | 
			
		||||
			auto c = gsm_sch_check_fn(current_gsm_time_updated.FN() + 1);
 | 
			
		||||
			DBGLG() << "L SCH : Timing offset     " << rv << " " << ebp.toa << " " << a << b << c << "fn "
 | 
			
		||||
				<< current_gsm_time_updated.FN() << ":" << current_gsm_time_updated.TN() << std::endl;
 | 
			
		||||
 | 
			
		||||
			delete bits;
 | 
			
		||||
			return true;
 | 
			
		||||
		} else {
 | 
			
		||||
			DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << ebp.toa << " "
 | 
			
		||||
				 << current_gsm_time.FN() << ":" << current_gsm_time.TN() << std::endl;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		delete bits;
 | 
			
		||||
		return true;
 | 
			
		||||
	} else {
 | 
			
		||||
		DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << ebp.toa << " " << current_gsm_time.FN()
 | 
			
		||||
			 << ":" << current_gsm_time.TN() << std::endl;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	delete bits;
 | 
			
		||||
#endif
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -333,12 +333,12 @@ SCH_STATE ms_trx::search_for_sch(dev_buf_t *rcd)
 | 
			
		||||
			float sum = normed_abs_sum(first_sch_buf, SCH_LEN_SPS);
 | 
			
		||||
 | 
			
		||||
			//FIXME: arbitrary value, gain cutoff
 | 
			
		||||
			if (sum > target_val || rxgain >= 60) // enough ?
 | 
			
		||||
			if (sum > target_val || cfg.rxgain >= 60) // enough ?
 | 
			
		||||
				sch_thread_done = this->handle_sch(true);
 | 
			
		||||
			else {
 | 
			
		||||
				std::cerr << "\x1B[32m #RXG \033[0m gain " << rxgain << " -> " << rxgain + 4
 | 
			
		||||
				std::cerr << "\x1B[32m #RXG \033[0m gain " << cfg.rxgain << " -> " << cfg.rxgain + 4
 | 
			
		||||
					  << " sample avg:" << sum << " target: >=" << target_val << std::endl;
 | 
			
		||||
				setRxGain(rxgain + 4);
 | 
			
		||||
				setRxGain(cfg.rxgain + 4);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!sch_thread_done)
 | 
			
		||||
@@ -368,7 +368,6 @@ void ms_trx::grab_bursts(dev_buf_t *rcd)
 | 
			
		||||
 | 
			
		||||
		if (fracts)
 | 
			
		||||
			timekeeper.inc_both();
 | 
			
		||||
		// timekeeper.inc_and_update(first_sch_ts_start + 1 * ONE_TS_BURST_LEN);
 | 
			
		||||
 | 
			
		||||
		timekeeper.dec_by_one(); // oops, off by one?
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,6 @@ struct internal_q_tx_buf {
 | 
			
		||||
		memcpy(buf, (void *)br->burst, br->burst_len);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
using tx_queue_t = spsc_cond<8 * 1, internal_q_tx_buf, true, false>;
 | 
			
		||||
using tx_queue_t = spsc_cond_timeout<8 * 1, internal_q_tx_buf, true, false>;
 | 
			
		||||
using cmd_queue_t = spsc_cond_timeout<8 * 1, trxcon_phyif_cmd, true, false>;
 | 
			
		||||
using cmdr_queue_t = spsc_cond<8 * 1, trxcon_phyif_rsp, false, false>;
 | 
			
		||||
using cmdr_queue_t = spsc_cond_timeout<8 * 1, trxcon_phyif_rsp, false, false>;
 | 
			
		||||
 
 | 
			
		||||
@@ -160,10 +160,11 @@ static void *static_alloc(size_t newSize)
 | 
			
		||||
 | 
			
		||||
bool upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset)
 | 
			
		||||
{
 | 
			
		||||
	float pow, avg = 1.0;
 | 
			
		||||
	// float pow, avg = 1.0;
 | 
			
		||||
	const auto zero_pad_len = 40; // give the VA some runway for misaligned bursts
 | 
			
		||||
	const auto workbuf_size = zero_pad_len + ONE_TS_BURST_LEN + zero_pad_len;
 | 
			
		||||
	static complex workbuf[workbuf_size];
 | 
			
		||||
	static int32_t meas_p, meas_rssi;
 | 
			
		||||
 | 
			
		||||
	static signalVector sv(workbuf, zero_pad_len, ONE_TS_BURST_LEN, static_alloc, static_free);
 | 
			
		||||
	one_burst e;
 | 
			
		||||
@@ -171,9 +172,11 @@ bool upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset)
 | 
			
		||||
	std::fill(workbuf, workbuf + workbuf_size, 0);
 | 
			
		||||
	// assert(sv.begin() == &workbuf[40]);
 | 
			
		||||
 | 
			
		||||
	while (!rxqueue.spsc_pop(&e)) {
 | 
			
		||||
	while (!rxqueue.spsc_pop(&e) && !g_exit_flag) {
 | 
			
		||||
		rxqueue.spsc_prep_pop();
 | 
			
		||||
	}
 | 
			
		||||
	if (g_exit_flag)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	wTime = e.gsmts;
 | 
			
		||||
 | 
			
		||||
@@ -183,8 +186,11 @@ bool upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset)
 | 
			
		||||
	trxcon_phyif_rtr_ind i = { static_cast<uint32_t>(wTime.FN()), static_cast<uint8_t>(wTime.TN()) };
 | 
			
		||||
	trxcon_phyif_rtr_rsp r = {};
 | 
			
		||||
	trxcon_phyif_handle_rtr_ind(g_trxcon, &i, &r);
 | 
			
		||||
	if (!(r.flags & TRXCON_PHYIF_RTR_F_ACTIVE))
 | 
			
		||||
	if (!(r.flags & TRXCON_PHYIF_RTR_F_ACTIVE)) {
 | 
			
		||||
		bladerf_get_rfic_rssi(dev, 0, &meas_p, &meas_rssi);
 | 
			
		||||
		// std::cerr << "G : \x1B[31m rx fail \033[0m @:" << meas_rssi << std::endl;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (is_fcch) {
 | 
			
		||||
		// return trash
 | 
			
		||||
@@ -199,77 +205,75 @@ bool upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset)
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
	convert_and_scale(ss, e.burst, ONE_TS_BURST_LEN * 2, 1.f / float(rxFullScale));
 | 
			
		||||
	if (use_va) {
 | 
			
		||||
		convert_and_scale(ss, e.burst, ONE_TS_BURST_LEN * 2, 1.f / float(rxFullScale));
 | 
			
		||||
 | 
			
		||||
	pow = energyDetect(sv, 20 * 4 /*sps*/);
 | 
			
		||||
	if (pow < -1) {
 | 
			
		||||
		LOG(ALERT) << "Received empty burst";
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
		// pow = energyDetect(sv, 20 * 4 /*sps*/);
 | 
			
		||||
		// if (pow < -1) {
 | 
			
		||||
		// 	LOG(ALERT) << "Received empty burst";
 | 
			
		||||
		// 	return false;
 | 
			
		||||
		// }
 | 
			
		||||
 | 
			
		||||
	avg = sqrt(pow);
 | 
			
		||||
	{
 | 
			
		||||
		float ncmax;
 | 
			
		||||
		std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
 | 
			
		||||
		auto normal_burst_start = get_norm_chan_imp_resp(ss, &chan_imp_resp[0], &ncmax, mTSC);
 | 
			
		||||
		// avg = sqrt(pow);
 | 
			
		||||
		{
 | 
			
		||||
			float ncmax;
 | 
			
		||||
			std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
 | 
			
		||||
			auto normal_burst_start = get_norm_chan_imp_resp(ss, &chan_imp_resp[0], &ncmax, mTSC);
 | 
			
		||||
#ifdef DBGXX
 | 
			
		||||
		float dcmax;
 | 
			
		||||
		std::complex<float> chan_imp_resp2[CHAN_IMP_RESP_LENGTH * d_OSR];
 | 
			
		||||
		auto dummy_burst_start = get_norm_chan_imp_resp(ss, &chan_imp_resp2[0], &dcmax, TS_DUMMY);
 | 
			
		||||
		auto is_nb = ncmax > dcmax;
 | 
			
		||||
		// DBGLG() << " U " << (is_nb ? "NB" : "DB") << "@ o nb: " << normal_burst_start
 | 
			
		||||
		// 	  << " o db: " << dummy_burst_start << std::endl;
 | 
			
		||||
			float dcmax;
 | 
			
		||||
			std::complex<float> chan_imp_resp2[CHAN_IMP_RESP_LENGTH * d_OSR];
 | 
			
		||||
			auto dummy_burst_start = get_norm_chan_imp_resp(ss, &chan_imp_resp2[0], &dcmax, TS_DUMMY);
 | 
			
		||||
			auto is_nb = ncmax > dcmax;
 | 
			
		||||
			// DBGLG() << " U " << (is_nb ? "NB" : "DB") << "@ o nb: " << normal_burst_start
 | 
			
		||||
			// 	  << " o db: " << dummy_burst_start << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
		normal_burst_start = normal_burst_start < 39 ? normal_burst_start : 39;
 | 
			
		||||
		normal_burst_start = normal_burst_start > -39 ? normal_burst_start : -39;
 | 
			
		||||
			normal_burst_start = normal_burst_start < 39 ? normal_burst_start : 39;
 | 
			
		||||
			normal_burst_start = normal_burst_start > -39 ? normal_burst_start : -39;
 | 
			
		||||
#ifdef DBGXX
 | 
			
		||||
		// fprintf(stderr, "%s %d\n", (is_nb ? "N":"D"), burst_time.FN());
 | 
			
		||||
		// if (is_nb)
 | 
			
		||||
			// fprintf(stderr, "%s %d\n", (is_nb ? "N":"D"), burst_time.FN());
 | 
			
		||||
			// if (is_nb)
 | 
			
		||||
#endif
 | 
			
		||||
		detect_burst_nb(ss, &chan_imp_resp[0], normal_burst_start, demodded_softbits);
 | 
			
		||||
			detect_burst_nb(ss, &chan_imp_resp[0], normal_burst_start, demodded_softbits);
 | 
			
		||||
#ifdef DBGXX
 | 
			
		||||
		// else
 | 
			
		||||
		// 	detect_burst(ss, &chan_imp_resp2[0], dummy_burst_start, outbin);
 | 
			
		||||
			// else
 | 
			
		||||
			// 	detect_burst(ss, &chan_imp_resp2[0], dummy_burst_start, outbin);
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// lower layer sch detection offset, easy to verify by just printing the detected value using both the va+sigproc code.
 | 
			
		||||
		convert_and_scale(ss + 16, e.burst, ONE_TS_BURST_LEN * 2, 15);
 | 
			
		||||
 | 
			
		||||
		// pow = energyDetect(sv, 20 * 4 /*sps*/);
 | 
			
		||||
		// if (pow < -1) {
 | 
			
		||||
		// 	LOG(ALERT) << "Received empty burst";
 | 
			
		||||
		// 	return false;
 | 
			
		||||
		// }
 | 
			
		||||
 | 
			
		||||
		// avg = sqrt(pow);
 | 
			
		||||
 | 
			
		||||
		/* Detect normal or RACH bursts */
 | 
			
		||||
		CorrType type = CorrType::TSC;
 | 
			
		||||
		struct estim_burst_params ebp;
 | 
			
		||||
		auto rc = detectAnyBurst(sv, mTSC, 3, 4, type, 48, &ebp);
 | 
			
		||||
		if (rc > 0) {
 | 
			
		||||
			type = (CorrType)rc;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (rc < 0) {
 | 
			
		||||
			std::cerr << "UR : \x1B[31m rx fail \033[0m @ toa:" << ebp.toa << " " << e.gsmts.FN() << ":"
 | 
			
		||||
				  << e.gsmts.TN() << std::endl;
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		SoftVector *bits = demodAnyBurst(sv, type, 4, &ebp);
 | 
			
		||||
 | 
			
		||||
		SoftVector::const_iterator burstItr = bits->begin();
 | 
			
		||||
		// invert and fix to +-127 sbits
 | 
			
		||||
		for (int ii = 0; ii < 148; ii++) {
 | 
			
		||||
			demodded_softbits[ii] = *burstItr++ > 0.0f ? -127 : 127;
 | 
			
		||||
		}
 | 
			
		||||
		delete bits;
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
	// lower layer sch detection offset, easy to verify by just printing the detected value using both the va+sigproc code.
 | 
			
		||||
	convert_and_scale(ss + 16, e.burst, ONE_TS_BURST_LEN * 2, 15);
 | 
			
		||||
 | 
			
		||||
	pow = energyDetect(sv, 20 * 4 /*sps*/);
 | 
			
		||||
	if (pow < -1) {
 | 
			
		||||
		LOG(ALERT) << "Received empty burst";
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	avg = sqrt(pow);
 | 
			
		||||
 | 
			
		||||
	/* Detect normal or RACH bursts */
 | 
			
		||||
	CorrType type = CorrType::TSC;
 | 
			
		||||
	struct estim_burst_params ebp;
 | 
			
		||||
	auto rc = detectAnyBurst(sv, mTSC, 3, 4, type, 48, &ebp);
 | 
			
		||||
	if (rc > 0) {
 | 
			
		||||
		type = (CorrType)rc;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		std::cerr << "UR : \x1B[31m rx fail \033[0m @ toa:" << ebp.toa << " " << e.gsmts.FN() << ":"
 | 
			
		||||
			  << e.gsmts.TN() << std::endl;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	SoftVector *bits = demodAnyBurst(sv, type, 4, &ebp);
 | 
			
		||||
 | 
			
		||||
	SoftVector::const_iterator burstItr = bits->begin();
 | 
			
		||||
	// invert and fix to +-127 sbits
 | 
			
		||||
	for (int ii = 0; ii < 148; ii++) {
 | 
			
		||||
		demodded_softbits[ii] = *burstItr++ > 0.0f ? -127 : 127;
 | 
			
		||||
	}
 | 
			
		||||
	delete bits;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
	RSSI = (int)floor(20.0 * log10(rxFullScale / avg));
 | 
			
		||||
	RSSI = meas_rssi; // (int)floor(20.0 * log10(rxFullScale / avg));
 | 
			
		||||
	// FIXME: properly handle offset, sch/nb alignment diff? handled by lower anyway...
 | 
			
		||||
	timingOffset = (int)round(0);
 | 
			
		||||
 | 
			
		||||
@@ -419,13 +423,13 @@ bool upper_trx::driveControl()
 | 
			
		||||
		r.param.measure.band_arfcn = cmd.param.measure.band_arfcn;
 | 
			
		||||
		// FIXME: do we want to measure anything, considering the transceiver just syncs by.. syncing?
 | 
			
		||||
		r.param.measure.dbm = -80;
 | 
			
		||||
		tuneRx(gsm_arfcn2freq10(cmd.param.measure.band_arfcn, 0) * 1000 * 100);
 | 
			
		||||
		tuneTx(gsm_arfcn2freq10(cmd.param.measure.band_arfcn, 1) * 1000 * 100);
 | 
			
		||||
		// tuneRx(gsm_arfcn2freq10(cmd.param.measure.band_arfcn, 0) * 1000 * 100);
 | 
			
		||||
		// tuneTx(gsm_arfcn2freq10(cmd.param.measure.band_arfcn, 1) * 1000 * 100);
 | 
			
		||||
		cmdq_from_phy.spsc_push(&r);
 | 
			
		||||
		break;
 | 
			
		||||
	case TRXCON_PHYIF_CMDT_SETFREQ_H0:
 | 
			
		||||
		tuneRx(gsm_arfcn2freq10(cmd.param.setfreq_h0.band_arfcn, 0) * 1000 * 100);
 | 
			
		||||
		tuneTx(gsm_arfcn2freq10(cmd.param.setfreq_h0.band_arfcn, 1) * 1000 * 100);
 | 
			
		||||
		// tuneRx(gsm_arfcn2freq10(cmd.param.setfreq_h0.band_arfcn, 0) * 1000 * 100);
 | 
			
		||||
		// tuneTx(gsm_arfcn2freq10(cmd.param.setfreq_h0.band_arfcn, 1) * 1000 * 100);
 | 
			
		||||
		break;
 | 
			
		||||
	case TRXCON_PHYIF_CMDT_SETFREQ_H1:
 | 
			
		||||
		break;
 | 
			
		||||
@@ -456,6 +460,12 @@ void sighandler(int sigset)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
#include <osmocom/vty/command.h>
 | 
			
		||||
#include <osmocom/vty/logging.h>
 | 
			
		||||
#include "mssdr_vty.h"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	auto tall_trxcon_ctx = talloc_init("trxcon context");
 | 
			
		||||
@@ -476,6 +486,22 @@ int main(int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
	osmo_fsm_log_timeouts(true);
 | 
			
		||||
 | 
			
		||||
	auto g_mssdr_ctx = vty_mssdr_ctx_alloc(tall_trxcon_ctx);
 | 
			
		||||
	vty_init(&g_mssdr_vty_info);
 | 
			
		||||
	logging_vty_add_cmds();
 | 
			
		||||
	mssdr_vty_init(g_mssdr_ctx);
 | 
			
		||||
 | 
			
		||||
	const char *home_dir = getenv("HOME");
 | 
			
		||||
	if (!home_dir)
 | 
			
		||||
		home_dir = "~";
 | 
			
		||||
	auto config_file = talloc_asprintf(tall_trxcon_ctx, "%s/%s", home_dir, ".osmocom/bb/mssdr.cfg");
 | 
			
		||||
 | 
			
		||||
	int rc = vty_read_config_file(config_file, NULL);
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		fprintf(stderr, "Failed to parse config file: '%s'\n", config_file);
 | 
			
		||||
		exit(2);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_trxcon = trxcon_inst_alloc(tall_trxcon_ctx, 0);
 | 
			
		||||
	g_trxcon->gsmtap = nullptr;
 | 
			
		||||
	g_trxcon->phyif = nullptr;
 | 
			
		||||
@@ -487,8 +513,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
	initvita();
 | 
			
		||||
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	auto trx = new upper_trx();
 | 
			
		||||
	trx->do_auto_gain = true;
 | 
			
		||||
	auto trx = new upper_trx(&g_mssdr_ctx->cfg);
 | 
			
		||||
 | 
			
		||||
	status = trx->init_dev_and_streams();
 | 
			
		||||
	if (status < 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -44,5 +44,6 @@ class upper_trx : public ms_trx {
 | 
			
		||||
	void driveReceiveFIFO();
 | 
			
		||||
	void driveTx();
 | 
			
		||||
 | 
			
		||||
	upper_trx() : mOn(false){};
 | 
			
		||||
	upper_trx() = delete;
 | 
			
		||||
	explicit upper_trx(struct mssdr_cfg *cfgdata) : ms_trx(cfgdata), mOn(false){};
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										264
									
								
								Transceiver52M/ms/mssdr_vty.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								Transceiver52M/ms/mssdr_vty.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,264 @@
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2024 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Eric Wild <ewild@sysmocom.de>
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <osmocom/vty/command.h>
 | 
			
		||||
#include <osmocom/vty/logging.h>
 | 
			
		||||
#include "../config.h"
 | 
			
		||||
#include "mssdr_vty.h"
 | 
			
		||||
 | 
			
		||||
static struct mssdr_ctx *g_mssdr_ctx;
 | 
			
		||||
 | 
			
		||||
enum mssdr_vty_node {
 | 
			
		||||
	MSSDR_NODE = _LAST_OSMOVTY_NODE + 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char mssdr_copyright[] =
 | 
			
		||||
	"Copyright (C) 2007-2014 Free Software Foundation, Inc.\r\n"
 | 
			
		||||
	"Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>\r\n"
 | 
			
		||||
	"Copyright (C) 2013-2019 Fairwaves, Inc.\r\n"
 | 
			
		||||
	"Copyright (C) 2015 Ettus Research LLC\r\n"
 | 
			
		||||
	"Copyright (C) 2017-2024 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>\r\n"
 | 
			
		||||
	"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
 | 
			
		||||
	"This is free software: you are free to change and redistribute it.\r\n"
 | 
			
		||||
	"There is NO WARRANTY, to the extent permitted by law.\r\n";
 | 
			
		||||
 | 
			
		||||
static int mssdr_vty_go_parent(struct vty *vty)
 | 
			
		||||
{
 | 
			
		||||
	switch (vty->node) {
 | 
			
		||||
	case MSSDR_NODE:
 | 
			
		||||
		vty->node = CONFIG_NODE;
 | 
			
		||||
		vty->index = NULL;
 | 
			
		||||
		vty->index_sub = NULL;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		vty->node = CONFIG_NODE;
 | 
			
		||||
		vty->index = NULL;
 | 
			
		||||
		vty->index_sub = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vty->node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct mssdr_ctx *mssdr_from_vty(struct vty *v)
 | 
			
		||||
{
 | 
			
		||||
	OSMO_ASSERT(g_mssdr_ctx);
 | 
			
		||||
	return g_mssdr_ctx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct vty_app_info g_mssdr_vty_info = {
 | 
			
		||||
	.name = "OsmoMSSDR",
 | 
			
		||||
	.version = PACKAGE_VERSION,
 | 
			
		||||
	.copyright = mssdr_copyright,
 | 
			
		||||
	.go_parent_cb = mssdr_vty_go_parent,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mssdr_ctx *vty_mssdr_ctx_alloc(void *talloc_ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = talloc_zero(talloc_ctx, struct mssdr_ctx);
 | 
			
		||||
	trx->cfg.use_va = true;
 | 
			
		||||
	trx->cfg.use_agc = true;
 | 
			
		||||
	return trx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mssdr_dump_vty(struct vty *vty, struct mssdr_ctx *trx)
 | 
			
		||||
{
 | 
			
		||||
	// vty_out(vty, "TRX Config:%s", VTY_NEWLINE);
 | 
			
		||||
	// vty_out(vty, " Local IP: %s%s", trx->cfg.bind_addr, VTY_NEWLINE);
 | 
			
		||||
	// vty_out(vty, " Remote IP: %s%s", trx->cfg.remote_addr, VTY_NEWLINE);
 | 
			
		||||
	// vty_out(vty, " TRX Base Port: %u%s", trx->cfg.base_port, VTY_NEWLINE);
 | 
			
		||||
	// vty_out(vty, " Device args: %s%s", trx->cfg.dev_args, VTY_NEWLINE);
 | 
			
		||||
	// vty_out(vty, " Tx Samples-per-Symbol: %u%s", trx->cfg.tx_sps, VTY_NEWLINE);
 | 
			
		||||
	// vty_out(vty, " Rx Samples-per-Symbol: %u%s", trx->cfg.rx_sps, VTY_NEWLINE);
 | 
			
		||||
	// vty_out(vty, " Filler Burst Type: %s%s", get_value_string(filler_names, trx->cfg.filler), VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, "trx%s", VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.overrides.dl_freq_override)
 | 
			
		||||
		vty_out(vty, " dl-freq-override %f%s", trx->cfg.overrides.dl_freq, VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.overrides.ul_freq_override)
 | 
			
		||||
		vty_out(vty, " ul-freq-override %f%s", trx->cfg.overrides.ul_freq, VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.overrides.dl_gain_override)
 | 
			
		||||
		vty_out(vty, " dl-gain-override %f%s", trx->cfg.overrides.dl_gain, VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.overrides.ul_gain_override)
 | 
			
		||||
		vty_out(vty, " ul-gain-override %f%s", trx->cfg.overrides.ul_gain, VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.use_va)
 | 
			
		||||
		vty_out(vty, " viterbi-eq %s%s", trx->cfg.use_va ? "enable" : "disable", VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.use_agc)
 | 
			
		||||
		vty_out(vty, " rx-agc %s%s", trx->cfg.use_agc ? "enable" : "disable", VTY_NEWLINE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int config_write_mssdr(struct vty *vty)
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = mssdr_from_vty(vty);
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "trx%s", VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.overrides.dl_freq_override)
 | 
			
		||||
		vty_out(vty, " dl-freq-override %f%s", trx->cfg.overrides.dl_freq, VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.overrides.ul_freq_override)
 | 
			
		||||
		vty_out(vty, " ul-freq-override %f%s", trx->cfg.overrides.ul_freq, VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.overrides.dl_gain_override)
 | 
			
		||||
		vty_out(vty, " dl-gain-override %f%s", trx->cfg.overrides.dl_gain, VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.overrides.ul_gain_override)
 | 
			
		||||
		vty_out(vty, " ul-gain-override %f%s", trx->cfg.overrides.ul_gain, VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.use_va)
 | 
			
		||||
		vty_out(vty, " viterbi-eq %s%s", trx->cfg.use_va ? "enable" : "disable", VTY_NEWLINE);
 | 
			
		||||
	if (trx->cfg.use_agc)
 | 
			
		||||
		vty_out(vty, " rx-agc %s%s", trx->cfg.use_agc ? "enable" : "disable", VTY_NEWLINE);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN(show_mssdr, show_mssdr_cmd,
 | 
			
		||||
	"show mssdr",
 | 
			
		||||
	SHOW_STR "Display information on the TRX\n")
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = mssdr_from_vty(vty);
 | 
			
		||||
 | 
			
		||||
	mssdr_dump_vty(vty, trx);
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN(cfg_mssdr, cfg_mssdr_cmd,
 | 
			
		||||
	"mssdr",
 | 
			
		||||
	"Configure the mssdr\n")
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = mssdr_from_vty(vty);
 | 
			
		||||
 | 
			
		||||
	if (!trx)
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
 | 
			
		||||
	vty->node = MSSDR_NODE;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN_ATTR(cfg_ul_freq_override, cfg_ul_freq_override_cmd,
 | 
			
		||||
	   "ul-freq-override FLOAT",
 | 
			
		||||
	   "Overrides Tx carrier frequency\n"
 | 
			
		||||
	   "Frequency in Hz (e.g. 145300000)\n",
 | 
			
		||||
	   CMD_ATTR_HIDDEN)
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = mssdr_from_vty(vty);
 | 
			
		||||
 | 
			
		||||
	trx->cfg.overrides.ul_freq_override = true;
 | 
			
		||||
	trx->cfg.overrides.ul_freq = atof(argv[0]);
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
DEFUN_ATTR(cfg_dl_freq_override, cfg_dl_freq_override_cmd,
 | 
			
		||||
	   "dl-freq-override FLOAT",
 | 
			
		||||
	   "Overrides Rx carrier frequency\n"
 | 
			
		||||
	   "Frequency in Hz (e.g. 145300000)\n",
 | 
			
		||||
	   CMD_ATTR_HIDDEN)
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = mssdr_from_vty(vty);
 | 
			
		||||
 | 
			
		||||
	trx->cfg.overrides.dl_freq_override = true;
 | 
			
		||||
	trx->cfg.overrides.dl_freq = atof(argv[0]);
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN_ATTR(cfg_ul_gain_override, cfg_ul_gain_override_cmd,
 | 
			
		||||
	   "ul-gain-override FLOAT",
 | 
			
		||||
	   "Overrides Tx gain\n"
 | 
			
		||||
	   "gain in dB\n",
 | 
			
		||||
	   CMD_ATTR_HIDDEN)
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = mssdr_from_vty(vty);
 | 
			
		||||
 | 
			
		||||
	trx->cfg.overrides.ul_gain_override = true;
 | 
			
		||||
	trx->cfg.overrides.ul_gain = atof(argv[0]);
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
DEFUN_ATTR(cfg_dl_gain_override, cfg_dl_gain_override_cmd,
 | 
			
		||||
	   "dl-gain-override FLOAT",
 | 
			
		||||
	   "Overrides Rx gain\n"
 | 
			
		||||
	   "gain in dB\n",
 | 
			
		||||
	   CMD_ATTR_HIDDEN)
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = mssdr_from_vty(vty);
 | 
			
		||||
 | 
			
		||||
	trx->cfg.overrides.dl_gain_override = true;
 | 
			
		||||
	trx->cfg.overrides.dl_gain = atof(argv[0]);
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN_ATTR(cfg_use_viterbi, cfg_use_viterbi_cmd,
 | 
			
		||||
	"viterbi-eq (disable|enable)",
 | 
			
		||||
	"Use viterbi equalizer for gmsk (default=enable)\n"
 | 
			
		||||
	"Disable VA\n"
 | 
			
		||||
	"Enable VA\n",
 | 
			
		||||
	CMD_ATTR_HIDDEN)
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = mssdr_from_vty(vty);
 | 
			
		||||
 | 
			
		||||
	if (strcmp("disable", argv[0]) == 0)
 | 
			
		||||
		trx->cfg.use_va = false;
 | 
			
		||||
	else if (strcmp("enable", argv[0]) == 0)
 | 
			
		||||
		trx->cfg.use_va = true;
 | 
			
		||||
	else
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN_ATTR(cfg_use_agc, cfg_use_agc_cmd,
 | 
			
		||||
	"rx-agc (disable|enable)",
 | 
			
		||||
	"Use the transceiver rx agc (default=enable)\n"
 | 
			
		||||
	"Disable agc\n"
 | 
			
		||||
	"Enable agc\n",
 | 
			
		||||
	CMD_ATTR_HIDDEN)
 | 
			
		||||
{
 | 
			
		||||
	struct mssdr_ctx *trx = mssdr_from_vty(vty);
 | 
			
		||||
 | 
			
		||||
	if (strcmp("disable", argv[0]) == 0)
 | 
			
		||||
		trx->cfg.use_agc = false;
 | 
			
		||||
	else if (strcmp("enable", argv[0]) == 0)
 | 
			
		||||
		trx->cfg.use_agc = true;
 | 
			
		||||
	else
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct cmd_node mssdr_node = {
 | 
			
		||||
	MSSDR_NODE,
 | 
			
		||||
	"%s(config-mssdr)# ",
 | 
			
		||||
	1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int mssdr_vty_init(struct mssdr_ctx *trx)
 | 
			
		||||
{
 | 
			
		||||
	g_mssdr_ctx = trx;
 | 
			
		||||
	install_element_ve(&show_mssdr_cmd);
 | 
			
		||||
	install_element(CONFIG_NODE, &cfg_mssdr_cmd);
 | 
			
		||||
 | 
			
		||||
	install_node(&mssdr_node, config_write_mssdr);
 | 
			
		||||
	install_element(MSSDR_NODE, &cfg_ul_freq_override_cmd);
 | 
			
		||||
	install_element(MSSDR_NODE, &cfg_dl_freq_override_cmd);
 | 
			
		||||
	install_element(MSSDR_NODE, &cfg_ul_gain_override_cmd);
 | 
			
		||||
	install_element(MSSDR_NODE, &cfg_dl_gain_override_cmd);
 | 
			
		||||
	install_element(MSSDR_NODE, &cfg_use_viterbi_cmd);
 | 
			
		||||
	install_element(MSSDR_NODE, &cfg_use_agc_cmd);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								Transceiver52M/ms/mssdr_vty.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								Transceiver52M/ms/mssdr_vty.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2024 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Eric Wild <ewild@sysmocom.de>
 | 
			
		||||
 *
 | 
			
		||||
 * 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/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct mssdr_cfg {
 | 
			
		||||
	struct {
 | 
			
		||||
		bool ul_freq_override;
 | 
			
		||||
		bool dl_freq_override;
 | 
			
		||||
		bool ul_gain_override;
 | 
			
		||||
		bool dl_gain_override;
 | 
			
		||||
		double ul_freq;
 | 
			
		||||
		double dl_freq;
 | 
			
		||||
		double ul_gain;
 | 
			
		||||
		double dl_gain;
 | 
			
		||||
	} overrides;
 | 
			
		||||
	bool use_va;
 | 
			
		||||
	bool use_agc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mssdr_ctx {
 | 
			
		||||
	struct mssdr_cfg cfg;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mssdr_ctx *vty_mssdr_ctx_alloc(void *talloc_ctx);
 | 
			
		||||
int mssdr_vty_init(struct mssdr_ctx *trx);
 | 
			
		||||
extern struct vty_app_info g_mssdr_vty_info;
 | 
			
		||||
@@ -21,7 +21,6 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <future>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <queue>
 | 
			
		||||
 
 | 
			
		||||
@@ -645,7 +645,6 @@ int main(int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
	osmo_init_logging2(tall_trx_ctx, &log_info);
 | 
			
		||||
	log_enable_multithread();
 | 
			
		||||
	log_cache_enable();
 | 
			
		||||
	osmo_stats_init(tall_trx_ctx);
 | 
			
		||||
	vty_init(&g_vty_info);
 | 
			
		||||
	logging_vty_add_cmds();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								configure.ac
									
									
									
									
									
								
							@@ -82,10 +82,10 @@ AC_TYPE_SIZE_T
 | 
			
		||||
AC_HEADER_TIME
 | 
			
		||||
AC_C_BIGENDIAN
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 1.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.9.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.9.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 1.9.0)
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(sanitize,
 | 
			
		||||
	[AS_HELP_STRING(
 | 
			
		||||
@@ -240,6 +240,7 @@ AS_IF([test "x$with_sse" != "xno"], [
 | 
			
		||||
    AM_CONDITIONAL(HAVE_SSE4_1, false)
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
dnl Check if the compiler supports specified GCC's built-in function
 | 
			
		||||
AC_DEFUN([CHECK_BUILTIN_SUPPORT], [
 | 
			
		||||
  AC_CACHE_CHECK(
 | 
			
		||||
    [whether ${CC} has $1 built-in],
 | 
			
		||||
@@ -379,5 +380,6 @@ AC_CONFIG_FILES([\
 | 
			
		||||
    contrib/Makefile \
 | 
			
		||||
    contrib/systemd/Makefile \
 | 
			
		||||
    doc/manuals/Makefile \
 | 
			
		||||
    contrib/osmo-trx.spec \
 | 
			
		||||
])
 | 
			
		||||
AC_OUTPUT
 | 
			
		||||
 
 | 
			
		||||
@@ -9,19 +9,60 @@
 | 
			
		||||
#
 | 
			
		||||
set -ex
 | 
			
		||||
 | 
			
		||||
case "$INSTR" in
 | 
			
		||||
	"--with-neon"*)
 | 
			
		||||
		case "$(arch)" in
 | 
			
		||||
			arm*)
 | 
			
		||||
				;;
 | 
			
		||||
			*)
 | 
			
		||||
				set +x
 | 
			
		||||
				echo "ERROR: trying to build with INSTR=$INSTR but not running on a 32-bit arm machine! (arch=$(arch))"
 | 
			
		||||
				exit 1
 | 
			
		||||
				;;
 | 
			
		||||
		esac
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
substr() { [ -z "${2##*$1*}" ]; }
 | 
			
		||||
 | 
			
		||||
#apt-get install qemu qemu-user-static qemu-system-arm debootstrap fakeroot proot
 | 
			
		||||
mychroot_nocwd() {
 | 
			
		||||
        # LC_ALL + LANGUAGE set to avoid lots of print errors due to locale not being set inside container
 | 
			
		||||
        # PATH is needed to be able to reach binaries like ldconfig without logging in to root, which adds the paths to PATH.
 | 
			
		||||
        # PROOT_NO_SECCOMP is required due to proot bug #106
 | 
			
		||||
        LC_ALL=C LANGUAGE=C PATH="$PATH:/usr/sbin:/sbin" PROOT_NO_SECCOMP=1 proot -r "$ROOTFS" -w / -b /proc --root-id -q qemu-arm-static "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mychroot() {
 | 
			
		||||
        mychroot_nocwd -w / "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if [ -z "${INSIDE_CHROOT}" ]; then
 | 
			
		||||
 | 
			
		||||
        # Only use ARM chroot if host is not ARM and the target is ARM:
 | 
			
		||||
        if ! $(substr "arm" "$(uname -m)") && [ "x${INSTR}" = "x--with-neon" -o "x${INSTR}" = "x--with-neon-vfpv4" ]; then
 | 
			
		||||
 | 
			
		||||
                OSMOTRX_DIR="$PWD" # we assume we are called as contrib/jenkins.sh
 | 
			
		||||
                ROOTFS_PREFIX="${ROOTFS_PREFIX:-$HOME}"
 | 
			
		||||
                ROOTFS="${ROOTFS_PREFIX}/qemu-img"
 | 
			
		||||
                mkdir -p "${ROOTFS_PREFIX}"
 | 
			
		||||
 | 
			
		||||
                # Prepare chroot:
 | 
			
		||||
                if [ ! -d "$ROOTFS" ]; then
 | 
			
		||||
                        mkdir -p "$ROOTFS"
 | 
			
		||||
                        if [ "x${USE_DEBOOTSTRAP}" = "x1" ]; then
 | 
			
		||||
                                fakeroot qemu-debootstrap --foreign --include="linux-image-armmp-lpae" --arch=armhf stretch "$ROOTFS" http://ftp.de.debian.org/debian/
 | 
			
		||||
                                # Hack to avoid debootstrap trying to mount /proc, as it will fail with "no permissions" and anyway proot takes care of it:
 | 
			
		||||
                                sed -i "s/setup_proc//g" "$ROOTFS/debootstrap/suite-script"
 | 
			
		||||
                                mychroot /debootstrap/debootstrap --second-stage --verbose http://ftp.de.debian.org/debian/
 | 
			
		||||
                        else
 | 
			
		||||
                                YESTERDAY=$(python -c 'import datetime ; print((datetime.datetime.now() - datetime.timedelta(days=1)).strftime("%Y%m%d"))')
 | 
			
		||||
                                wget -nc -q "https://uk.images.linuxcontainers.org/images/debian/stretch/armhf/default/${YESTERDAY}_22:42/rootfs.tar.xz"
 | 
			
		||||
                                tar -xf rootfs.tar.xz -C "$ROOTFS/" || true
 | 
			
		||||
                                echo "nameserver 8.8.8.8" > "$ROOTFS/etc/resolv.conf"
 | 
			
		||||
                        fi
 | 
			
		||||
                        mychroot -b /dev apt-get update
 | 
			
		||||
                        mychroot apt-get -y install build-essential dh-autoreconf pkg-config libuhd-dev libusb-1.0-0-dev libusb-dev git libtalloc-dev libgnutls28-dev stow
 | 
			
		||||
                fi
 | 
			
		||||
                # Run jenkins.sh inside the chroot:
 | 
			
		||||
                INSIDE_CHROOT=1 mychroot_nocwd \
 | 
			
		||||
                 -w /osmo-trx \
 | 
			
		||||
                 -b "$OSMOTRX_DIR:/osmo-trx" \
 | 
			
		||||
                 -b "$(which osmo-clean-workspace.sh):/usr/bin/osmo-clean-workspace.sh" \
 | 
			
		||||
                 -b "$(which osmo-build-dep.sh):/usr/bin/osmo-build-dep.sh" \
 | 
			
		||||
                 -b "$(which osmo-deps.sh):/usr/bin/osmo-deps.sh" \
 | 
			
		||||
                  ./contrib/jenkins.sh
 | 
			
		||||
                exit 0
 | 
			
		||||
        fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
set -ex
 | 
			
		||||
 | 
			
		||||
if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
 | 
			
		||||
	echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										254
									
								
								contrib/osmo-trx.spec.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								contrib/osmo-trx.spec.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
#
 | 
			
		||||
# spec file for package osmo-trx
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c) 2017, Martin Hauke <mardnh@gmx.de>
 | 
			
		||||
#
 | 
			
		||||
# All modifications and additions to the file contributed by third parties
 | 
			
		||||
# remain the property of their copyright owners, unless otherwise agreed
 | 
			
		||||
# upon. The license for this file, and modifications and additions to the
 | 
			
		||||
# file, is the same license as for the pristine package itself (unless the
 | 
			
		||||
# license for the pristine package is not an Open Source License, in which
 | 
			
		||||
# case the license is the MIT License). An "Open Source License" is a
 | 
			
		||||
# license that conforms to the Open Source Definition (Version 1.9)
 | 
			
		||||
# published by the Open Source Initiative.
 | 
			
		||||
 | 
			
		||||
Name:           osmo-trx
 | 
			
		||||
Version:        @VERSION@
 | 
			
		||||
Release:        0
 | 
			
		||||
Summary:        SDR transceiver that implements Layer 1 of a GSM BTS
 | 
			
		||||
License:        AGPL-3.0-or-later
 | 
			
		||||
Group:          Productivity/Telephony/Servers
 | 
			
		||||
URL:            https://osmocom.org/projects/osmotrx
 | 
			
		||||
Source:         %{name}-%{version}.tar.xz
 | 
			
		||||
BuildRequires:  autoconf
 | 
			
		||||
BuildRequires:  automake
 | 
			
		||||
BuildRequires:  fdupes
 | 
			
		||||
BuildRequires:  gcc-c++
 | 
			
		||||
BuildRequires:  libtool
 | 
			
		||||
BuildRequires:  pkgconfig >= 0.20
 | 
			
		||||
%if 0%{?suse_version}
 | 
			
		||||
BuildRequires:  systemd-rpm-macros
 | 
			
		||||
%endif
 | 
			
		||||
%if ! 0%{?centos_ver}
 | 
			
		||||
BuildRequires:  pkgconfig(LimeSuite)
 | 
			
		||||
BuildRequires:  pkgconfig(usrp) >= 3.3
 | 
			
		||||
%endif
 | 
			
		||||
BuildRequires:  pkgconfig(fftw3f)
 | 
			
		||||
BuildRequires:  pkgconfig(libosmocoding) >= 1.9.0
 | 
			
		||||
BuildRequires:  pkgconfig(libosmocore) >= 1.9.0
 | 
			
		||||
BuildRequires:  pkgconfig(libosmoctrl) >= 1.9.0
 | 
			
		||||
BuildRequires:  pkgconfig(libosmovty) >= 1.9.0
 | 
			
		||||
BuildRequires:  pkgconfig(libusb-1.0)
 | 
			
		||||
BuildRequires:  pkgconfig(uhd)
 | 
			
		||||
%{?systemd_requires}
 | 
			
		||||
%if 0%{?suse_version} > 1325
 | 
			
		||||
BuildRequires:  libboost_program_options-devel
 | 
			
		||||
BuildRequires:  libboost_system-devel
 | 
			
		||||
BuildRequires:  libboost_test-devel
 | 
			
		||||
BuildRequires:  libboost_thread-devel
 | 
			
		||||
%else
 | 
			
		||||
BuildRequires:  boost-devel
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%description
 | 
			
		||||
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 uhd
 | 
			
		||||
Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (UHD)
 | 
			
		||||
Group:          Productivity/Telephony/Servers
 | 
			
		||||
Requires:       uhd-firmware
 | 
			
		||||
 | 
			
		||||
%description uhd
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
%if ! 0%{?centos_ver}
 | 
			
		||||
%package usrp1
 | 
			
		||||
Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (USRP1)
 | 
			
		||||
Group:          Productivity/Telephony/Servers
 | 
			
		||||
 | 
			
		||||
%description usrp1
 | 
			
		||||
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 lms
 | 
			
		||||
Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (LimeSuite)
 | 
			
		||||
Group:          Productivity/Telephony/Servers
 | 
			
		||||
 | 
			
		||||
%description lms
 | 
			
		||||
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)
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%package ipc
 | 
			
		||||
Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (IPC)
 | 
			
		||||
Group:          Productivity/Telephony/Servers
 | 
			
		||||
 | 
			
		||||
%description ipc
 | 
			
		||||
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 ipc-test
 | 
			
		||||
Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (IPC) driver test utility
 | 
			
		||||
Group:          Productivity/Telephony/Servers
 | 
			
		||||
 | 
			
		||||
%description ipc-test
 | 
			
		||||
OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
			
		||||
physical layer of a BTS comprising the following 3GPP specifications:
 | 
			
		||||
 | 
			
		||||
This package include the test tools for osmo-trx-ipc
 | 
			
		||||
 | 
			
		||||
%prep
 | 
			
		||||
%setup -q
 | 
			
		||||
 | 
			
		||||
%build
 | 
			
		||||
echo "%{version}" >.tarball-version
 | 
			
		||||
autoreconf -fi
 | 
			
		||||
 | 
			
		||||
%if 0%{?centos_ver}
 | 
			
		||||
%configure \
 | 
			
		||||
  --docdir=%{_docdir}/%{name} \
 | 
			
		||||
  --with-systemdsystemunitdir=%{_unitdir} \
 | 
			
		||||
  --without-lms \
 | 
			
		||||
  --with-uhd \
 | 
			
		||||
  --without-usrp1 \
 | 
			
		||||
  --with-ipc
 | 
			
		||||
%else
 | 
			
		||||
%configure \
 | 
			
		||||
  --docdir=%{_docdir}/%{name} \
 | 
			
		||||
  --with-systemdsystemunitdir=%{_unitdir} \
 | 
			
		||||
  --with-lms \
 | 
			
		||||
  --with-uhd \
 | 
			
		||||
  --with-usrp1 \
 | 
			
		||||
  --with-ipc
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
make %{?_smp_mflags} V=1
 | 
			
		||||
 | 
			
		||||
%check
 | 
			
		||||
make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
 | 
			
		||||
 | 
			
		||||
%install
 | 
			
		||||
%make_install
 | 
			
		||||
%fdupes -s %{buildroot}/%{_datadir}
 | 
			
		||||
 | 
			
		||||
%if 0%{?suse_version}
 | 
			
		||||
%pre    lms %service_add_pre    osmo-trx-lms.service
 | 
			
		||||
%post   lms %service_add_post   osmo-trx-lms.service
 | 
			
		||||
%preun  lms %service_del_preun  osmo-trx-lms.service
 | 
			
		||||
%postun lms %service_del_postun osmo-trx-lms.service
 | 
			
		||||
%pre    uhd %service_add_pre    osmo-trx-uhd.service
 | 
			
		||||
%post   uhd %service_add_post   osmo-trx-uhd.service
 | 
			
		||||
%preun  uhd %service_del_preun  osmo-trx-uhd.service
 | 
			
		||||
%postun uhd %service_del_postun osmo-trx-uhd.service
 | 
			
		||||
%pre    usrp1 %service_add_pre    osmo-trx-usrp1.service
 | 
			
		||||
%post   usrp1 %service_add_post   osmo-trx-usrp1.service
 | 
			
		||||
%preun  usrp1 %service_del_preun  osmo-trx-usrp1.service
 | 
			
		||||
%postun usrp1 %service_del_postun osmo-trx-usrp1.service
 | 
			
		||||
%pre    ipc %service_add_pre    osmo-trx-ipc.service
 | 
			
		||||
%post   ipc %service_add_post   osmo-trx-ipc.service
 | 
			
		||||
%preun  ipc %service_del_preun  osmo-trx-ipc.service
 | 
			
		||||
%postun ipc %service_del_postun osmo-trx-ipc.service
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%files
 | 
			
		||||
%license COPYING
 | 
			
		||||
%doc README.md
 | 
			
		||||
%doc %{_docdir}/%{name}/examples
 | 
			
		||||
 | 
			
		||||
%if ! 0%{?centos_ver}
 | 
			
		||||
%files lms
 | 
			
		||||
%{_bindir}/osmo-trx-lms
 | 
			
		||||
%dir %{_sysconfdir}/osmocom
 | 
			
		||||
%config(noreplace) %{_sysconfdir}/osmocom/osmo-trx-lms.cfg
 | 
			
		||||
%{_unitdir}/osmo-trx-lms.service
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%files uhd
 | 
			
		||||
%{_bindir}/osmo-trx-uhd
 | 
			
		||||
%dir %{_sysconfdir}/osmocom
 | 
			
		||||
%config(noreplace) %{_sysconfdir}/osmocom/osmo-trx-uhd.cfg
 | 
			
		||||
%{_unitdir}/osmo-trx-uhd.service
 | 
			
		||||
 | 
			
		||||
%if ! 0%{?centos_ver}
 | 
			
		||||
%files usrp1
 | 
			
		||||
%{_bindir}/osmo-trx-usrp1
 | 
			
		||||
%dir %{_datadir}/usrp
 | 
			
		||||
%dir %{_datadir}/usrp/rev2
 | 
			
		||||
%dir %{_datadir}/usrp/rev4
 | 
			
		||||
%{_datadir}/usrp/rev2/std_inband.rbf
 | 
			
		||||
%{_datadir}/usrp/rev4/std_inband.rbf
 | 
			
		||||
%{_unitdir}/osmo-trx-usrp1.service
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%files ipc
 | 
			
		||||
%{_bindir}/osmo-trx-ipc
 | 
			
		||||
%dir %{_sysconfdir}/osmocom
 | 
			
		||||
%config(noreplace) %{_sysconfdir}/osmocom/osmo-trx-ipc.cfg
 | 
			
		||||
%{_unitdir}/osmo-trx-ipc.service
 | 
			
		||||
 | 
			
		||||
%files ipc-test
 | 
			
		||||
%{_bindir}/ipc-driver-test
 | 
			
		||||
 | 
			
		||||
%changelog
 | 
			
		||||
@@ -8,11 +8,8 @@ Type=simple
 | 
			
		||||
Restart=always
 | 
			
		||||
StateDirectory=osmocom
 | 
			
		||||
WorkingDirectory=%S/osmocom
 | 
			
		||||
User=osmocom
 | 
			
		||||
Group=osmocom
 | 
			
		||||
ExecStart=/usr/bin/osmo-trx-ipc -C /etc/osmocom/osmo-trx-ipc.cfg
 | 
			
		||||
RestartSec=2
 | 
			
		||||
AmbientCapabilities=CAP_SYS_NICE
 | 
			
		||||
# CPU scheduling policy:
 | 
			
		||||
CPUSchedulingPolicy=rr
 | 
			
		||||
# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,8 @@ Type=simple
 | 
			
		||||
Restart=always
 | 
			
		||||
StateDirectory=osmocom
 | 
			
		||||
WorkingDirectory=%S/osmocom
 | 
			
		||||
User=osmocom
 | 
			
		||||
Group=osmocom
 | 
			
		||||
ExecStart=/usr/bin/osmo-trx-lms -C /etc/osmocom/osmo-trx-lms.cfg
 | 
			
		||||
RestartSec=2
 | 
			
		||||
AmbientCapabilities=CAP_SYS_NICE
 | 
			
		||||
# CPU scheduling policy:
 | 
			
		||||
CPUSchedulingPolicy=rr
 | 
			
		||||
# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,9 @@ Type=simple
 | 
			
		||||
Restart=always
 | 
			
		||||
StateDirectory=osmocom
 | 
			
		||||
WorkingDirectory=%S/osmocom
 | 
			
		||||
Environment=HOME=%S/osmocom
 | 
			
		||||
User=osmocom
 | 
			
		||||
Group=osmocom
 | 
			
		||||
Environment=HOME=%h
 | 
			
		||||
ExecStart=/usr/bin/osmo-trx-uhd -C /etc/osmocom/osmo-trx-uhd.cfg
 | 
			
		||||
RestartSec=2
 | 
			
		||||
AmbientCapabilities=CAP_SYS_NICE
 | 
			
		||||
# CPU scheduling policy:
 | 
			
		||||
CPUSchedulingPolicy=rr
 | 
			
		||||
# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,8 @@ Type=simple
 | 
			
		||||
Restart=always
 | 
			
		||||
StateDirectory=osmocom
 | 
			
		||||
WorkingDirectory=%S/osmocom
 | 
			
		||||
User=osmocom
 | 
			
		||||
Group=osmocom
 | 
			
		||||
ExecStart=/usr/bin/osmo-trx-usrp1 -C /etc/osmocom/osmo-trx-usrp1.cfg
 | 
			
		||||
RestartSec=2
 | 
			
		||||
AmbientCapabilities=CAP_SYS_NICE
 | 
			
		||||
# CPU scheduling policy:
 | 
			
		||||
CPUSchedulingPolicy=rr
 | 
			
		||||
# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										62
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,65 +1,3 @@
 | 
			
		||||
osmo-trx (1.7.1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Oliver Smith ]
 | 
			
		||||
  * contrib/jenkins: remove broken chroot + qemu code
 | 
			
		||||
 | 
			
		||||
  [ Neels Hofmeyr ]
 | 
			
		||||
  * comma_delimited_to_vector() optimization CID#465430
 | 
			
		||||
 | 
			
		||||
 -- Oliver Smith <osmith@sysmocom.de>  Wed, 12 Feb 2025 12:43:24 +0100
 | 
			
		||||
 | 
			
		||||
osmo-trx (1.7.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Eric ]
 | 
			
		||||
  * ms: adjust ts advance
 | 
			
		||||
  * ms: reduce rx burst queue size
 | 
			
		||||
  * ms: init blade with fpga control
 | 
			
		||||
  * devices: fix wrong gain to power mapping
 | 
			
		||||
  * ms: get rid of std::thread
 | 
			
		||||
  * ms: add demod test tool and data
 | 
			
		||||
 | 
			
		||||
  [ Vadim Yanitskiy ]
 | 
			
		||||
  * osmo-trx-ms: bump osmocom-bb submodule commit
 | 
			
		||||
  * Transceiver::ctrl_sock_handle_rx(): fix copy-pasted comments
 | 
			
		||||
  * build: include version files into the release tarball
 | 
			
		||||
  * doc/examples: fix missing config files in release tarballs
 | 
			
		||||
  * README.md: cosmetic: fix a typo
 | 
			
		||||
 | 
			
		||||
  [ Harald Welte ]
 | 
			
		||||
  * osmo-trx-uhd: Make sure HOME environment variable is set
 | 
			
		||||
  * README.md: Improve markdown formatting
 | 
			
		||||
  * README.md: Add Forum and Issue Tracker links
 | 
			
		||||
  * Add funding link to github mirror
 | 
			
		||||
  * README.md: Remove stray apostrophe
 | 
			
		||||
 | 
			
		||||
  [ Andreas Eversberg ]
 | 
			
		||||
  * Use uniform log format for default config files
 | 
			
		||||
 | 
			
		||||
  [ Eric Wild ]
 | 
			
		||||
  * ms: do not set the blade tuning mode
 | 
			
		||||
  * ms: hard preswapped VA gsm bits
 | 
			
		||||
  * ms: add sigproclib demod
 | 
			
		||||
  * ms: fix up template deduction failure
 | 
			
		||||
  * ms: update osmocom-bb submodule
 | 
			
		||||
  * ms: disabe uhd ms build
 | 
			
		||||
  * transceiver: use log level cache
 | 
			
		||||
 | 
			
		||||
  [ Oliver Smith ]
 | 
			
		||||
  * gitignore: add .version
 | 
			
		||||
  * debian/rules: make configure args diff friendly
 | 
			
		||||
  * debian: add osmo-trx-ms-blade
 | 
			
		||||
  * contrib/jenkins: make configure args diff friendly
 | 
			
		||||
  * contrib/jenkins: add --with-bladerf
 | 
			
		||||
  * contrib: remove rpm spec file
 | 
			
		||||
  * contrib/systemd: run as osmocom user
 | 
			
		||||
  * contrib/systemd/osmo-trx-uhd: fix HOME=
 | 
			
		||||
 | 
			
		||||
  [ Pau Espin Pedrol ]
 | 
			
		||||
  * code-architecture.adoc: Fix missing alignment in digraph
 | 
			
		||||
  * doc: Introduce documentation for osmo-trx-ipc and its IPC interface
 | 
			
		||||
 | 
			
		||||
 -- Oliver Smith <osmith@sysmocom.de>  Wed, 24 Jul 2024 15:57:14 +0200
 | 
			
		||||
 | 
			
		||||
osmo-trx (1.6.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Vadim Yanitskiy ]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -15,8 +15,8 @@ Build-Depends: debhelper (>= 10),
 | 
			
		||||
               libusrp-dev,
 | 
			
		||||
               liblimesuite-dev,
 | 
			
		||||
               libbladerf-dev,
 | 
			
		||||
               libosmocore-dev (>= 1.10.0),
 | 
			
		||||
               osmo-gsm-manuals-dev (>= 1.6.0)
 | 
			
		||||
               libosmocore-dev (>= 1.9.0),
 | 
			
		||||
               osmo-gsm-manuals-dev (>= 1.5.0)
 | 
			
		||||
Standards-Version: 3.9.6
 | 
			
		||||
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-trx
 | 
			
		||||
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-trx
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								debian/osmo-trx-ipc.postinst
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								debian/osmo-trx-ipc.postinst
									
									
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
			
		||||
#!/bin/sh -e
 | 
			
		||||
case "$1" in
 | 
			
		||||
	configure)
 | 
			
		||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
			
		||||
		if ! getent group osmocom >/dev/null; then
 | 
			
		||||
			groupadd --system osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		if ! getent passwd osmocom >/dev/null; then
 | 
			
		||||
			useradd \
 | 
			
		||||
				--system \
 | 
			
		||||
				--gid osmocom \
 | 
			
		||||
				--home-dir /var/lib/osmocom \
 | 
			
		||||
				--shell /sbin/nologin \
 | 
			
		||||
				--comment "Open Source Mobile Communications" \
 | 
			
		||||
				osmocom
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
			
		||||
		if dpkg --compare-versions "$2" le "1.13.0"; then
 | 
			
		||||
			if [ -e /etc/osmocom/osmo-trx-ipc.cfg ]; then
 | 
			
		||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-trx-ipc.cfg
 | 
			
		||||
				chmod -v 0660 /etc/osmocom/osmo-trx-ipc.cfg
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			if [ -d /etc/osmocom ]; then
 | 
			
		||||
				chown -v root:osmocom /etc/osmocom
 | 
			
		||||
				chmod -v 2775 /etc/osmocom
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			mkdir -p /var/lib/osmocom
 | 
			
		||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
			
		||||
# generated by other debhelper scripts.
 | 
			
		||||
#DEBHELPER#
 | 
			
		||||
							
								
								
									
										38
									
								
								debian/osmo-trx-lms.postinst
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								debian/osmo-trx-lms.postinst
									
									
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
			
		||||
#!/bin/sh -e
 | 
			
		||||
case "$1" in
 | 
			
		||||
	configure)
 | 
			
		||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
			
		||||
		if ! getent group osmocom >/dev/null; then
 | 
			
		||||
			groupadd --system osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		if ! getent passwd osmocom >/dev/null; then
 | 
			
		||||
			useradd \
 | 
			
		||||
				--system \
 | 
			
		||||
				--gid osmocom \
 | 
			
		||||
				--home-dir /var/lib/osmocom \
 | 
			
		||||
				--shell /sbin/nologin \
 | 
			
		||||
				--comment "Open Source Mobile Communications" \
 | 
			
		||||
				osmocom
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
			
		||||
		if dpkg --compare-versions "$2" le "1.13.0"; then
 | 
			
		||||
			if [ -e /etc/osmocom/osmo-trx-lms.cfg ]; then
 | 
			
		||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-trx-lms.cfg
 | 
			
		||||
				chmod -v 0660 /etc/osmocom/osmo-trx-lms.cfg
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			if [ -d /etc/osmocom ]; then
 | 
			
		||||
				chown -v root:osmocom /etc/osmocom
 | 
			
		||||
				chmod -v 2775 /etc/osmocom
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			mkdir -p /var/lib/osmocom
 | 
			
		||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
			
		||||
# generated by other debhelper scripts.
 | 
			
		||||
#DEBHELPER#
 | 
			
		||||
							
								
								
									
										38
									
								
								debian/osmo-trx-uhd.postinst
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								debian/osmo-trx-uhd.postinst
									
									
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
			
		||||
#!/bin/sh -e
 | 
			
		||||
case "$1" in
 | 
			
		||||
	configure)
 | 
			
		||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
			
		||||
		if ! getent group osmocom >/dev/null; then
 | 
			
		||||
			groupadd --system osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		if ! getent passwd osmocom >/dev/null; then
 | 
			
		||||
			useradd \
 | 
			
		||||
				--system \
 | 
			
		||||
				--gid osmocom \
 | 
			
		||||
				--home-dir /var/lib/osmocom \
 | 
			
		||||
				--shell /sbin/nologin \
 | 
			
		||||
				--comment "Open Source Mobile Communications" \
 | 
			
		||||
				osmocom
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
			
		||||
		if dpkg --compare-versions "$2" le "1.13.0"; then
 | 
			
		||||
			if [ -e /etc/osmocom/osmo-trx-uhd.cfg ]; then
 | 
			
		||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-trx-uhd.cfg
 | 
			
		||||
				chmod -v 0660 /etc/osmocom/osmo-trx-uhd.cfg
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			if [ -d /etc/osmocom ]; then
 | 
			
		||||
				chown -v root:osmocom /etc/osmocom
 | 
			
		||||
				chmod -v 2775 /etc/osmocom
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			mkdir -p /var/lib/osmocom
 | 
			
		||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
			
		||||
# generated by other debhelper scripts.
 | 
			
		||||
#DEBHELPER#
 | 
			
		||||
							
								
								
									
										38
									
								
								debian/osmo-trx-usrp1.postinst
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								debian/osmo-trx-usrp1.postinst
									
									
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
			
		||||
#!/bin/sh -e
 | 
			
		||||
case "$1" in
 | 
			
		||||
	configure)
 | 
			
		||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
			
		||||
		if ! getent group osmocom >/dev/null; then
 | 
			
		||||
			groupadd --system osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		if ! getent passwd osmocom >/dev/null; then
 | 
			
		||||
			useradd \
 | 
			
		||||
				--system \
 | 
			
		||||
				--gid osmocom \
 | 
			
		||||
				--home-dir /var/lib/osmocom \
 | 
			
		||||
				--shell /sbin/nologin \
 | 
			
		||||
				--comment "Open Source Mobile Communications" \
 | 
			
		||||
				osmocom
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
			
		||||
		if dpkg --compare-versions "$2" le "1.13.0"; then
 | 
			
		||||
			if [ -e /etc/osmocom/osmo-trx-usrp1.cfg ]; then
 | 
			
		||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-trx-usrp1.cfg
 | 
			
		||||
				chmod -v 0660 /etc/osmocom/osmo-trx-usrp1.cfg
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			if [ -d /etc/osmocom ]; then
 | 
			
		||||
				chown -v root:osmocom /etc/osmocom
 | 
			
		||||
				chmod -v 2775 /etc/osmocom
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			mkdir -p /var/lib/osmocom
 | 
			
		||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
			
		||||
# generated by other debhelper scripts.
 | 
			
		||||
#DEBHELPER#
 | 
			
		||||
@@ -8,6 +8,7 @@ EXTRA_DIST = \
 | 
			
		||||
	osmo-trx-lms/osmo-trx-limesdr.cfg \
 | 
			
		||||
	osmo-trx-lms/osmo-trx-lms.cfg \
 | 
			
		||||
	osmo-trx-ipc/osmo-trx-ipc.cfg \
 | 
			
		||||
	osmo-trx-ms-blade/mssdr.cfg \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
OSMOCONF_FILES =
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								doc/examples/osmo-trx-ms-blade/mssdr.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								doc/examples/osmo-trx-ms-blade/mssdr.cfg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
log stderr
 | 
			
		||||
 logging filter all 1
 | 
			
		||||
 logging color 1
 | 
			
		||||
 logging print category-hex 0
 | 
			
		||||
 logging print category 1
 | 
			
		||||
 logging timestamp 0
 | 
			
		||||
 logging print file basename last
 | 
			
		||||
 logging print level 1
 | 
			
		||||
 logging level set-all notice
 | 
			
		||||
!
 | 
			
		||||
line vty
 | 
			
		||||
 no login
 | 
			
		||||
!
 | 
			
		||||
# cpu-sched
 | 
			
		||||
#  policy rr 18
 | 
			
		||||
mssdr
 | 
			
		||||
 ul-freq-override 881e6
 | 
			
		||||
 dl-freq-override 926e6
 | 
			
		||||
 ul-gain-override 30
 | 
			
		||||
 dl-gain-override 30
 | 
			
		||||
 viterbi-eq enable
 | 
			
		||||
 rx-agc enable
 | 
			
		||||
 | 
			
		||||
@@ -9,7 +9,7 @@ digraph hierarchy {
 | 
			
		||||
node[shape=record,style=filled,fillcolor=gray95]
 | 
			
		||||
edge[dir=back, arrowtail=empty]
 | 
			
		||||
 | 
			
		||||
2[label = "{Transceiver|+ constructor()\l+ destructor()\l+ init()\l+ numChans()\l+ receiveFIFO()\l+ setSignalHandler()\l}"]
 | 
			
		||||
2[label = "{Transceiver|+ constructor()\l+ destructor()\l+ init()\l+ numChans()\l+ receiveFIFO()\l+ setSignalHandler()}"]
 | 
			
		||||
3[label = "{RadioInterface|...}"]
 | 
			
		||||
4[label = "{RadioInterfaceResamp|...}"]
 | 
			
		||||
5[label = "{RadioInterfaceMulti|...}"]
 | 
			
		||||
@@ -17,7 +17,6 @@ edge[dir=back, arrowtail=empty]
 | 
			
		||||
7[label = "{UHDDevice|...}"]
 | 
			
		||||
8[label = "{LMSDevice|...}"]
 | 
			
		||||
9[label = "{USRPDevice|...}"]
 | 
			
		||||
10[label = "{IPCDevice|...}"]
 | 
			
		||||
 | 
			
		||||
2->3[arrowtail=odiamond]
 | 
			
		||||
3->4[constraint=false]
 | 
			
		||||
@@ -26,7 +25,6 @@ edge[dir=back, arrowtail=empty]
 | 
			
		||||
6->7
 | 
			
		||||
6->8
 | 
			
		||||
6->9
 | 
			
		||||
6->10
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,301 +0,0 @@
 | 
			
		||||
[[ipc_if]]
 | 
			
		||||
== osmo-trx-ipc IPC Interface
 | 
			
		||||
 | 
			
		||||
This interface is the one used by _osmo_trx_ipc_ backend to communicate to a
 | 
			
		||||
third party process in charge of driving the lowest layer device-specific bits
 | 
			
		||||
(from now on the Driver).
 | 
			
		||||
 | 
			
		||||
It consists of a set of Unix Domain (UD) sockets for the control plane, plus a
 | 
			
		||||
shared memory region for the data plane.
 | 
			
		||||
 | 
			
		||||
Related code can be found in the
 | 
			
		||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc[Transceiver52M/device/ipc/]
 | 
			
		||||
directory in _osmo-trx.git_.
 | 
			
		||||
 | 
			
		||||
If you are a potential driver implementator, the
 | 
			
		||||
various primitives and data structures are publicly available in header file
 | 
			
		||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/shm.h[Transceiver52M/device/ipc/shm.h].
 | 
			
		||||
 | 
			
		||||
=== Control plane
 | 
			
		||||
 | 
			
		||||
Control plane protocol is transmitted over Unix Domain (UD) sockets using
 | 
			
		||||
message based primitives. Each primitive has a type identified by an integer,
 | 
			
		||||
and each type of primitive has a number of extra attributes attached to it. The
 | 
			
		||||
IPC interface consists of 2 types of UD sockets:
 | 
			
		||||
 | 
			
		||||
* _Master_ UD socket: One per osmo-trx-ipc process.
 | 
			
		||||
 | 
			
		||||
* _Channel_ UD socket: One for each channel managed by osmo-trx-ipc process.
 | 
			
		||||
 | 
			
		||||
The _Driver_ is in all cases expected to take the server role when creating UD
 | 
			
		||||
sockets, while _osmo-trx-ipc_ takes the client role and connects to sockets
 | 
			
		||||
provided by the driver.
 | 
			
		||||
 | 
			
		||||
=== Master UD socket
 | 
			
		||||
 | 
			
		||||
During startup, _osmo-trx-ipc_ will try connecting to the _Driver_ Master UD
 | 
			
		||||
socket located in the path provided by its own (VTY) configuration. As a result,
 | 
			
		||||
it means the _Driver_ process must be running and listening on the Master UD
 | 
			
		||||
socket before _osmo-trx-ipc_ is started, otherwise _osmo-trx-ipc_ will fail and
 | 
			
		||||
exit.
 | 
			
		||||
 | 
			
		||||
Once connected, _osmo-trx-ipc_ will submit a `GREETING_REQ` message primitive
 | 
			
		||||
announcing the maximum supported protocol version (first version ever is `1`,
 | 
			
		||||
increasing over time).
 | 
			
		||||
 | 
			
		||||
The _Driver_ shall then answer in `GREETING_CNF` message primitive with its own
 | 
			
		||||
maximum supported version (`<=` version received), providing 0 if none is
 | 
			
		||||
supported.
 | 
			
		||||
 | 
			
		||||
If _osmo-trx-ipc_ receives back the requested version, then both sides agreed
 | 
			
		||||
on the protocol version to use.
 | 
			
		||||
If _osmo-trx-ipc_ receives back a lower version, it shall decide to continue
 | 
			
		||||
with version negotiation using a lower version, until a supported version or 0
 | 
			
		||||
is received. If finally 0 is received, _osmo-trx-ipc_ will disconnect and exit
 | 
			
		||||
with failure.
 | 
			
		||||
 | 
			
		||||
Once the version is negotiated (`v1` as of current date), _osmo-trx-ipc_ will
 | 
			
		||||
ask for device information and available characeristics to the _Driver_ using
 | 
			
		||||
the `INFO_REQ` message primitive.
 | 
			
		||||
 | 
			
		||||
The _Driver_ shall then answer with a `INFO_CNF` message
 | 
			
		||||
containing information, such as:
 | 
			
		||||
 | 
			
		||||
* String containing device description
 | 
			
		||||
 | 
			
		||||
* Available reference clocks,
 | 
			
		||||
 | 
			
		||||
* {rx,tx} I/Q scaling factors
 | 
			
		||||
 | 
			
		||||
* Maximum number of channels supported
 | 
			
		||||
 | 
			
		||||
* for each channel:
 | 
			
		||||
 | 
			
		||||
** List of available {rx,tx} paths/antennas.
 | 
			
		||||
 | 
			
		||||
** {min,max}{rx,tx} gains
 | 
			
		||||
 | 
			
		||||
** Nominal transmit power
 | 
			
		||||
 | 
			
		||||
All the information received from the _Driver_ during `INFO_CNF` will be used by
 | 
			
		||||
_osmo-trx-ipc_ to decide whether it can fullfil the requested configuration from
 | 
			
		||||
the user, and proceed to open the device, or exit with a failure (for instance
 | 
			
		||||
number of channels, referece clock or tx/rx antenna selected by the user cannot
 | 
			
		||||
be fullfilled).
 | 
			
		||||
 | 
			
		||||
_osmo-trx-ipc_ will then proceed to open the device and do an initial
 | 
			
		||||
configuration using an `OPEN_REQ` message, where it will provide the _Driver_
 | 
			
		||||
with the desired selected configuration (such as number of channels, rx/tx
 | 
			
		||||
paths, clock reference, bandwidth filters, etc.).
 | 
			
		||||
 | 
			
		||||
The _Driver_ shall then configure the device and send back a `OPEN_CNF` with:
 | 
			
		||||
 | 
			
		||||
* `return_code` integer attribute set to `0` on success or `!0` on error.
 | 
			
		||||
 | 
			
		||||
* Name of the Posix Shared Memory region where data plane is going to be
 | 
			
		||||
transmitted.
 | 
			
		||||
 | 
			
		||||
* One path for each channel, containing the just-created UD socket to manage
 | 
			
		||||
that channel (for instance by taking Master UD socket path and appending
 | 
			
		||||
`_$chan_idx`).
 | 
			
		||||
 | 
			
		||||
* Path Delay: this is the loopback path delay in samples (= used as a timestamp
 | 
			
		||||
offset internally by _osmo-trx-ipc_), this value contains the analog delay as
 | 
			
		||||
well as the delay introduced by the digital filters in the fpga in the sdr
 | 
			
		||||
devices, and is therefore device type and bandwidth/sample rate dependant. This
 | 
			
		||||
can not be omitted, wrong values will lead to a _osmo-trx-ipc_ that just doesn't
 | 
			
		||||
detect any bursts.
 | 
			
		||||
 | 
			
		||||
Finally, _osmo-trx-ipc_ will connect to each channel's UD socket (see next
 | 
			
		||||
section).
 | 
			
		||||
 | 
			
		||||
Upon _osmo-trx-ipc_ closing the UD master socket connection, the _Driver_ shall
 | 
			
		||||
go into _closed_ state: stop all processing and instruct the device to power
 | 
			
		||||
off.
 | 
			
		||||
 | 
			
		||||
TIP: See
 | 
			
		||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/shm.h[Transceiver52M/device/ipc/shm.h]
 | 
			
		||||
for the detailed definition of all the related message primitives and data
 | 
			
		||||
types for this socket.
 | 
			
		||||
 | 
			
		||||
=== Channel UD Socket
 | 
			
		||||
 | 
			
		||||
This socket can be used by _osmo-trx-ipc_ to start/stop data plane processing or
 | 
			
		||||
change channel's parameters such as Rx/Tx Frequency, Rx/Tx gains, etc.
 | 
			
		||||
 | 
			
		||||
A channel can be either in _started_ or _stopped_ state. When a channel is
 | 
			
		||||
created (during `OPEN_REQ` in the Master UD Socket), it's by default in
 | 
			
		||||
_stopped_ state. `START_REQ` and `STOP_REQ` messages control this state, and
 | 
			
		||||
eventual failures can be reported through `START_CNF` and `STOP_CNF` by the
 | 
			
		||||
_Driver_.
 | 
			
		||||
 | 
			
		||||
The message `START_REQ` instructs the _Driver_ to start processing data in the
 | 
			
		||||
data plane. Similary, `STOP_REQ` instructs the _Driver_ to stop processing data
 | 
			
		||||
in the data plane.
 | 
			
		||||
 | 
			
		||||
Some parameters are usually changed only when the channel is in stopped mode,
 | 
			
		||||
for instance Rx/Tx Frequency.
 | 
			
		||||
 | 
			
		||||
TIP: See
 | 
			
		||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/shm.h[Transceiver52M/device/ipc/shm.h]
 | 
			
		||||
for the detailed definition of all the related message primitives and data
 | 
			
		||||
types for this socket.
 | 
			
		||||
 | 
			
		||||
=== Data Plane
 | 
			
		||||
 | 
			
		||||
Data plane protocol is implemented by means of a ring buffer structure on top of
 | 
			
		||||
Posix Shared Memory (see `man 7 shm_overview`) between _osmo-trx-ipc_ process
 | 
			
		||||
and the _Driver_.
 | 
			
		||||
 | 
			
		||||
The Posix Shared Memory region is created and its memory structure prepared by
 | 
			
		||||
the _Driver_ and its name shared with _osmo-trx-ipc_ during _OPEN_CNF_ message
 | 
			
		||||
in the Master UD Socket from the Control Plane. Resource allocation for the
 | 
			
		||||
shared memory area and cleanup is up to the ipc server, as is mutex
 | 
			
		||||
initialization for the buffers.
 | 
			
		||||
 | 
			
		||||
==== Posix Shared Memory structure
 | 
			
		||||
 | 
			
		||||
[[fig-shm-structure]]
 | 
			
		||||
.General overview of Posix Shared Memory structure
 | 
			
		||||
[graphviz]
 | 
			
		||||
----
 | 
			
		||||
digraph hierarchy {
 | 
			
		||||
node[shape=record,style=filled,fillcolor=gray95]
 | 
			
		||||
edge[dir=back, arrowtail=empty]
 | 
			
		||||
 | 
			
		||||
SHM[label = "{Posix Shared Memory region|+ num_chans\l+ Channels[]\l}"]
 | 
			
		||||
CHAN0[label = "{Channel 0|...}"]
 | 
			
		||||
CHAN1[label = "{Channel 1|...}"]
 | 
			
		||||
CHANN[label = "{Channel ...|}"]
 | 
			
		||||
STREAM0_UL[label = "{UL Stream|+ semaphore\l+ read_next\l+ write_next\l+ buffer_size /* In samples */\l+ num_buffers\l+ sample_buffers[]\l}"]
 | 
			
		||||
STREAM0_DL[label = "{DL Stream|+ semaphore\l+ read_next\l+ write_next\l+ buffer_size /* In samples */\l+ num_buffers\l+ sample_buffers[]\l}"]
 | 
			
		||||
STREAM1_UL[label = "{UL Stream|...}"]
 | 
			
		||||
STREAM1_DL[label = "{DL Stream|...}"]
 | 
			
		||||
STREAMN_UL[label = "{UL Stream|...}"]
 | 
			
		||||
STREAMN_DL[label = "{DL Stream|...}"]
 | 
			
		||||
BUF_0DL0[label = "{DL Sample Buffer 0|+ timestamp\l+ buffer_size /* In samples */\l+ samples[] = [16bit I + 16bit Q,...]\l}"]
 | 
			
		||||
BUF_0DLN[label = "{DL Sample Buffer ....|...}"]
 | 
			
		||||
BUF_0UL0[label = "{UL Sample Buffer 0|+ timestamp\l+ buffer_size /* In samples */\l+ samples[] = [16bit I + 16bit Q,...]\l}"]
 | 
			
		||||
BUF_0ULN[label = "{UL Sample Buffer ...|...}"]
 | 
			
		||||
 | 
			
		||||
SHM->CHAN0
 | 
			
		||||
SHM->CHAN1
 | 
			
		||||
SHM->CHANN
 | 
			
		||||
 | 
			
		||||
CHAN0->STREAM0_DL
 | 
			
		||||
CHAN0->STREAM0_UL
 | 
			
		||||
STREAM0_DL->BUF_0DL0
 | 
			
		||||
STREAM0_DL->BUF_0DLN
 | 
			
		||||
STREAM0_UL->BUF_0UL0
 | 
			
		||||
STREAM0_UL->BUF_0ULN
 | 
			
		||||
 | 
			
		||||
CHAN1->STREAM1_UL
 | 
			
		||||
CHAN1->STREAM1_DL
 | 
			
		||||
 | 
			
		||||
CHANN->STREAMN_UL
 | 
			
		||||
CHANN->STREAMN_DL
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
The Posix Shared Memory region contains an array of _Channels_.
 | 
			
		||||
 | 
			
		||||
Each _Channel_ contains 2 Streams:
 | 
			
		||||
 | 
			
		||||
* Downlink _Stream_
 | 
			
		||||
 | 
			
		||||
* Uplink _Stream_
 | 
			
		||||
 | 
			
		||||
Each _Stream_ handles a ring buffer, which is implemented as:
 | 
			
		||||
 | 
			
		||||
* An array of pointers to _Sample Buffer_ structures.
 | 
			
		||||
 | 
			
		||||
* Variables containing the number of buffers in the array, as well as the
 | 
			
		||||
maximum size in samples for each Sample Buffer.
 | 
			
		||||
 | 
			
		||||
* Variables containing `next_read` and `next_write` _Sample Buffer_ (its index
 | 
			
		||||
in the array of pointers).
 | 
			
		||||
 | 
			
		||||
* Unnamed Posix semaphores to do the required locking while using the ring
 | 
			
		||||
buffer.
 | 
			
		||||
 | 
			
		||||
Each _Sample Buffer_ contains:
 | 
			
		||||
 | 
			
		||||
* A `timestamp` variable, containing the position in the stream of the first
 | 
			
		||||
sample in the buffer
 | 
			
		||||
 | 
			
		||||
* A `data_len` variable, containing the amount of samples available to process
 | 
			
		||||
in the buffer
 | 
			
		||||
 | 
			
		||||
* An array of samples of size specified by the stream struct it is part of.
 | 
			
		||||
 | 
			
		||||
==== Posix Shared Memory format
 | 
			
		||||
 | 
			
		||||
The Posix Shared memory region shall be formatted applying the following
 | 
			
		||||
considerations:
 | 
			
		||||
 | 
			
		||||
* All pointers in the memory region are encoded as offsets from the start
 | 
			
		||||
address of the region itself, to allow different processes with different
 | 
			
		||||
address spaces to decode them.
 | 
			
		||||
 | 
			
		||||
* All structs must be force-aligned to 8 bytes
 | 
			
		||||
 | 
			
		||||
* Number of buffers must be power of 2 (2,4,8,16,...) - 4 appears to be plenty
 | 
			
		||||
 | 
			
		||||
* IQ samples format: One (complex) sample consists of 16bit i + 16bit q, so the
 | 
			
		||||
buffer size is number of IQ pairs.
 | 
			
		||||
 | 
			
		||||
* A reasonable per-buffer size (in samples) is 2500, since this happens to be
 | 
			
		||||
the ususal TX (downlink) buffer size used by _osmo-trx-ipc_ with the b210 (rx
 | 
			
		||||
over-the-wire packet size for the b210 is 2040 samples, so the larger value of
 | 
			
		||||
both is convenient).
 | 
			
		||||
 | 
			
		||||
TIP: See
 | 
			
		||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/shm.h[Transceiver52M/device/ipc/shm.h]
 | 
			
		||||
for the detailed definition of all the objects being part of the Posix Shared
 | 
			
		||||
memory region structure
 | 
			
		||||
 | 
			
		||||
==== Posix Shared Memory procedures
 | 
			
		||||
 | 
			
		||||
The queue in the shared memory area is not supposed to be used for actual
 | 
			
		||||
buffering of data, only for exchange, so the general expectation is that it is
 | 
			
		||||
mostly empty. The only exception to that might be minor processing delays, and
 | 
			
		||||
during startup.
 | 
			
		||||
 | 
			
		||||
Care must be taken to ensure that only timed waits for the mutex protecting it
 | 
			
		||||
and the condition variables are used, in order to ensure that no deadlock occurs
 | 
			
		||||
should the other side die/quit.
 | 
			
		||||
 | 
			
		||||
Thread cancellation should be disabled during reads/writes from/to the queue. In
 | 
			
		||||
general a timeout can be considered a non recoverable error during regular
 | 
			
		||||
processing after startup, at least with the current timeout value of one second.
 | 
			
		||||
 | 
			
		||||
Should over- or underflows occur a corresponding message should be sent towards
 | 
			
		||||
_osmo-trx-ipc_.
 | 
			
		||||
 | 
			
		||||
Upon **read** of `N` samples, the reader does something like:
 | 
			
		||||
 | 
			
		||||
. Acquire the semaphore in the channel's stream object.
 | 
			
		||||
 | 
			
		||||
. Read `stream->next_read`, if `next_read==next_write`, become blocked in
 | 
			
		||||
another sempahore (unlocking the previous one) until writer signals us, then
 | 
			
		||||
`buff = stream->buffers[next_read]`
 | 
			
		||||
 | 
			
		||||
. Read `buff->data_len` samples, reset the buffer data (`data_len=0`),
 | 
			
		||||
increment `next_read` and if read samples is `<N`, continue with next buffer
 | 
			
		||||
until `next_read==next_write`, then block again or if timeout elapsed, then  we
 | 
			
		||||
reach conditon buffer underflow and `return len < N`.
 | 
			
		||||
 | 
			
		||||
. Release the semaphore
 | 
			
		||||
 | 
			
		||||
Upon **write** of `N` samples, the writer does something like:
 | 
			
		||||
 | 
			
		||||
. Acquire the semapore in the channel's stream object.
 | 
			
		||||
 | 
			
		||||
. Write samples to `buff = stream->buffers[next_write]`. If `data_len!=0`,
 | 
			
		||||
signal `buffer_overflow` (increase field in stream object) and probably
 | 
			
		||||
increase next_read`.
 | 
			
		||||
 | 
			
		||||
. Increase `next_write`.
 | 
			
		||||
 | 
			
		||||
. If `next_write` was `== next_read`, signal the reader through the other
 | 
			
		||||
semaphore that it can continue reading.
 | 
			
		||||
@@ -71,103 +71,3 @@ with a memory buffer. In this mode, data written to the USRP is actually stored
 | 
			
		||||
in a buffer, and read commands to the USRP simply pull data from this buffer.
 | 
			
		||||
This was very useful in early testing, and still may be useful in testing basic
 | 
			
		||||
Transceiver and radioInterface functionality.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[backend_ipc]]
 | 
			
		||||
=== `osmo-trx-ipc` Inter Process Communication backend
 | 
			
		||||
 | 
			
		||||
This OsmoTRX model provides its own Inter Process Communication (IPC) interface
 | 
			
		||||
to drive the radio device driver (from now on the Driver), allowing for third
 | 
			
		||||
party processes to implement the lowest layer device-specific bits without being
 | 
			
		||||
affected by copyleft licenses of OsmoTRX.
 | 
			
		||||
 | 
			
		||||
For more information on such interface, see section <<ipc_if>>.
 | 
			
		||||
 | 
			
		||||
[[fig-backend-ipc]]
 | 
			
		||||
.Architecture with _osmo-trx-ipc_ and its IPC _Driver_
 | 
			
		||||
[graphviz]
 | 
			
		||||
----
 | 
			
		||||
digraph G {
 | 
			
		||||
        rankdir=LR;
 | 
			
		||||
        MS0 [label="MS"];
 | 
			
		||||
        MS1 [label="MS"];
 | 
			
		||||
        OsmoTRX [label="osmo-trx-ipc", color=red];
 | 
			
		||||
        BTS;
 | 
			
		||||
 | 
			
		||||
        subgraph cluster_ipc_driver {
 | 
			
		||||
                label = "IPC Driver";
 | 
			
		||||
                color=red;
 | 
			
		||||
                RE [label = "Radio Equipment"];
 | 
			
		||||
                REC [label="Radio Equipment Controller"];
 | 
			
		||||
                RE->REC;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        REC->OsmoTRX [label="IPC Interface", color=red];
 | 
			
		||||
 | 
			
		||||
        MS0->RE [label="Um"];
 | 
			
		||||
        MS1->RE [label="Um"];
 | 
			
		||||
        OsmoTRX->BTS [label="bursts over UDP"];
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
A sample config file for this OsmoTRX model can be found in _osmo-trx.git_ https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/doc/examples/osmo-trx-ipc/osmo-trx-ipc.cfg[doc/examples/osmo-trx-ipc/osmo-trx-ipc.cfg]
 | 
			
		||||
 | 
			
		||||
In the config file, the following VTY command can be used to set up the IPC UD Master Socket _osmo-trx-ipc_ will connect to at startup:
 | 
			
		||||
 | 
			
		||||
.Example: _osmo-trx-ipc_ will connect to UD Master Socket /tmp/ipc_sock0 upon startup
 | 
			
		||||
----
 | 
			
		||||
dev-args ipc_msock=/tmp/ipc_sock0
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
==== ipc-device-test
 | 
			
		||||
 | 
			
		||||
When built with `--with-ipc --with-uhd` configure options, _osmo-trx.git_ will
 | 
			
		||||
build the test program called _ipc-driver-test_. This program implements the
 | 
			
		||||
_Driver_ side of the osmo-trx-ipc interface (see <<ipc_if>> for more
 | 
			
		||||
information) on one side, and also interacts internally with UHD (eg B210 as
 | 
			
		||||
when using osmo-trx-uhd).
 | 
			
		||||
 | 
			
		||||
You can use this small program as a reference to:
 | 
			
		||||
 | 
			
		||||
* Test and experiment with _osmo-trx-ipc_.
 | 
			
		||||
 | 
			
		||||
* Write your own IPC _Driver_ connecting to osmo-trx-ipc.
 | 
			
		||||
 | 
			
		||||
[[fig-backend-ipc-device-test]]
 | 
			
		||||
.Architecture with _osmo-trx-ipc_ and ipc-device-test as IPC _Driver_
 | 
			
		||||
[graphviz]
 | 
			
		||||
----
 | 
			
		||||
digraph G {
 | 
			
		||||
        rankdir=LR;
 | 
			
		||||
        MS0 [label="MS"];
 | 
			
		||||
        MS1 [label="MS"];
 | 
			
		||||
        SDR;
 | 
			
		||||
        ipc_device_test[label = "ipc-device-test", color=red];
 | 
			
		||||
        OsmoTRX [label="osmo-trx-ipc", color=red];
 | 
			
		||||
        BTS;
 | 
			
		||||
 | 
			
		||||
        MS0->SDR [label="Um"];
 | 
			
		||||
        MS1->SDR [label="Um"];
 | 
			
		||||
        SDR->ipc_device_test [label="UHD"];
 | 
			
		||||
        ipc_device_test->OsmoTRX [label="IPC Interface", color=red];
 | 
			
		||||
        OsmoTRX->BTS [label="bursts over UDP"];
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
The code for this app is found here:
 | 
			
		||||
 | 
			
		||||
* https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/ipc-driver-test.h[Transceiver52M/device/ipc/ipc-driver-test.h]
 | 
			
		||||
 | 
			
		||||
* https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/ipc-driver-test.c[Transceiver52M/device/ipc/ipc-driver-test.c]
 | 
			
		||||
 | 
			
		||||
Those files use the server-side (_Driver_ side) code to operate the Posix Shared
 | 
			
		||||
Memory region implemented in files `shm.c`, `shm.h`, `ipc_shm.c` and `ipc_shm.h`
 | 
			
		||||
in the same directory.
 | 
			
		||||
 | 
			
		||||
Most of the code in that same directory is deliverately released under a BSD
 | 
			
		||||
license (unlike most of _osmo-trx.git_), allowing third parties to reuse/recycle
 | 
			
		||||
the code on their implemented _Driver_ program no matter it being proprietary or
 | 
			
		||||
under an open license. However, care must be taken with external dependencies,
 | 
			
		||||
as for instance shm.c uses the talloc memory allocator, which is GPL licensed
 | 
			
		||||
and hence cannot be used in a proprietary driver.
 | 
			
		||||
@@ -35,8 +35,6 @@ include::./common/chapters/vty_cpu_sched.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/trx_if.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/ipc_if.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/port_numbers.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/bibliography.adoc[]
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user