[MERGED] osmo-trx[master]: Add support to set Rx/TxAntenna

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

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

Harald Welte gerrit-no-reply at lists.osmocom.org
Thu Feb 8 08:50:02 UTC 2018


Harald Welte has submitted this change and it was merged.

Change subject: Add support to set Rx/TxAntenna
......................................................................


Add support to set Rx/TxAntenna

Some devices have different Rx or Tx ports with different RF characteristics.
For instance LimeSDR has H (High), L (Low) and W (Wide) band Rx ports,
each of one being more suitable to a specific range of frequencies.

In case one wants to support several GSM bands, the best option is to
use the WideBand port and connect the antenna physically to that port in
the board. Then the firmware must be instructed ro read from that port.
Support for Rx/Tx port configuration is already in there for all the
layers (Limesuite, SoapySDR, SoapyUHD, UHD), but we are missing the
required bits in osmo-trx to make use of the available UHD API. This
commit addresses it.

Before this patch, the Rx/Tx paths configured could be changed by means
of the LimeSuiteGUI app, but after running osmo-trx, the values were
changed to the default ones.

One can now start using osmo-trx with 1 channel and specific Rx/Tx ports
by using for instance: osmo-trx -c 1 -y BAND1 -z LNAW

Default behaviour if no specific path or an empry path is passed ("") is
to do the same as preiously, ie. nothing by not calling the
set{T,R}xAntenna APIs.

One can also configure only specific channels, for instance to configure
only the first Tx channel and the second Rx channel:
osmo-trx -c 2 -y BAND1, -z ,LNAW

Change-Id: I1735e6ab05a05b0312d6d679b16ebd4a2260fa23
---
M Transceiver52M/UHDDevice.cpp
M Transceiver52M/USRPDevice.cpp
M Transceiver52M/USRPDevice.h
M Transceiver52M/osmo-trx.cpp
M Transceiver52M/radioDevice.h
5 files changed, 253 insertions(+), 10 deletions(-)

Approvals:
  Vadim Yanitskiy: Looks good to me, but someone else must approve
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/Transceiver52M/UHDDevice.cpp b/Transceiver52M/UHDDevice.cpp
index 1120299..1687a60 100644
--- a/Transceiver52M/UHDDevice.cpp
+++ b/Transceiver52M/UHDDevice.cpp
@@ -208,7 +208,9 @@
 class uhd_device : public RadioDevice {
 public:
 	uhd_device(size_t tx_sps, size_t rx_sps, InterfaceType type,
-		   size_t chans, double offset);
+		   size_t chans, double offset,
+		   const std::vector<std::string>& tx_paths,
+		   const std::vector<std::string>& rx_paths);
 	~uhd_device();
 
 	int open(const std::string &args, int ref, bool swap_channels);
@@ -248,6 +250,11 @@
 	double getRxFreq(size_t chan);
 	double getRxFreq();
 
+	bool setRxAntenna(const std::string &ant, size_t chan);
+	std::string getRxAntenna(size_t chan);
+	bool setTxAntenna(const std::string &ant, size_t chan);
+	std::string getTxAntenna(size_t chan);
+
 	inline double getSampleRate() { return tx_rate; }
 	inline double numberRead() { return rx_pkt_cnt; }
 	inline double numberWritten() { return 0; }
@@ -280,6 +287,7 @@
 
 	std::vector<double> tx_gains, rx_gains;
 	std::vector<double> tx_freqs, rx_freqs;
+	std::vector<std::string> tx_paths, rx_paths;
 	size_t tx_spp, rx_spp;
 
 	bool started;
@@ -295,6 +303,7 @@
 	void init_gains();
 	void set_channels(bool swap);
 	void set_rates();
+	bool set_antennas();
 	bool parse_dev_type();
 	bool flush_recv(size_t num_pkts);
 	int check_rx_md_err(uhd::rx_metadata_t &md, ssize_t num_smpls);
@@ -353,7 +362,9 @@
 }
 
 uhd_device::uhd_device(size_t tx_sps, size_t rx_sps,
-		       InterfaceType iface, size_t chans, double offset)
+		       InterfaceType iface, size_t chans, double offset,
+		       const std::vector<std::string>& tx_paths,
+		       const std::vector<std::string>& rx_paths)
 	: tx_gain_min(0.0), tx_gain_max(0.0),
 	  rx_gain_min(0.0), rx_gain_max(0.0),
 	  tx_spp(0), rx_spp(0),
@@ -365,6 +376,8 @@
 	this->chans = chans;
 	this->offset = offset;
 	this->iface = iface;
+	this->tx_paths = tx_paths;
+	this->rx_paths = rx_paths;
 }
 
 uhd_device::~uhd_device()
@@ -439,6 +452,33 @@
 
 	ts_offset = static_cast<TIMESTAMP>(desc.offset * rx_rate);
 	LOG(INFO) << "Rates configured for " << desc.str;
+}
+
+bool uhd_device::set_antennas()
+{
+	unsigned int i;
+
+	for (i = 0; i < tx_paths.size(); i++) {
+		if (tx_paths[i] == "")
+			continue;
+		LOG(DEBUG) << "Configuring channel " << i << " with antenna " << tx_paths[i];
+		if (!setTxAntenna(tx_paths[i], i)) {
+			LOG(ALERT) << "Failed configuring channel " << i << " with antenna " << tx_paths[i];
+			return false;
+		}
+	}
+
+	for (i = 0; i < rx_paths.size(); i++) {
+		if (rx_paths[i] == "")
+			continue;
+		LOG(DEBUG) << "Configuring channel " << i << " with antenna " << rx_paths[i];
+		if (!setRxAntenna(rx_paths[i], i)) {
+			LOG(ALERT) << "Failed configuring channel " << i << " with antenna " << rx_paths[i];
+			return false;
+		}
+	}
+	LOG(INFO) << "Antennas configured successfully";
+	return true;
 }
 
 double uhd_device::setTxGain(double db, size_t chan)
@@ -641,6 +681,11 @@
 		set_channels(swap_channels);
         } catch (const std::exception &e) {
 		LOG(ALERT) << "Channel setting failed - " << e.what();
+		return -1;
+	}
+
+	if (!set_antennas()) {
+		LOG(ALERT) << "UHD antenna setting failed";
 		return -1;
 	}
 
@@ -1165,6 +1210,78 @@
 	return rx_freqs[chan];
 }
 
+bool uhd_device::setRxAntenna(const std::string &ant, size_t chan)
+{
+	std::vector<std::string> avail;
+	if (chan >= rx_paths.size()) {
+		LOG(ALERT) << "Requested non-existent channel " << chan;
+		return false;
+	}
+
+	avail = usrp_dev->get_rx_antennas(chan);
+	if (std::find(avail.begin(), avail.end(), ant) == avail.end()) {
+		LOG(ALERT) << "Requested non-existent Rx antenna " << ant << " on channel " << chan;
+		LOG(INFO) << "Available Rx antennas: ";
+		for (std::vector<std::string>::const_iterator i = avail.begin(); i != avail.end(); ++i)
+			LOG(INFO) << "- '" << *i << "'";
+		return false;
+	}
+	usrp_dev->set_rx_antenna(ant, chan);
+	rx_paths[chan] = usrp_dev->get_rx_antenna(chan);
+
+	if (ant != rx_paths[chan]) {
+		LOG(ALERT) << "Failed setting antenna " << ant << " on channel " << chan << ", got instead " << rx_paths[chan];
+		return false;
+	}
+
+	return true;
+}
+
+std::string uhd_device::getRxAntenna(size_t chan)
+{
+	if (chan >= rx_paths.size()) {
+		LOG(ALERT) << "Requested non-existent channel " << chan;
+		return "";
+	}
+	return usrp_dev->get_rx_antenna(chan);
+}
+
+bool uhd_device::setTxAntenna(const std::string &ant, size_t chan)
+{
+	std::vector<std::string> avail;
+	if (chan >= tx_paths.size()) {
+		LOG(ALERT) << "Requested non-existent channel " << chan;
+		return false;
+	}
+
+	avail = usrp_dev->get_tx_antennas(chan);
+	if (std::find(avail.begin(), avail.end(), ant) == avail.end()) {
+		LOG(ALERT) << "Requested non-existent Tx antenna " << ant << " on channel " << chan;
+		LOG(INFO) << "Available Tx antennas: ";
+		for (std::vector<std::string>::const_iterator i = avail.begin(); i != avail.end(); ++i)
+			LOG(INFO) << "- '" << *i << "'";
+		return false;
+	}
+	usrp_dev->set_tx_antenna(ant, chan);
+	tx_paths[chan] = usrp_dev->get_tx_antenna(chan);
+
+	if (ant != tx_paths[chan]) {
+		LOG(ALERT) << "Failed setting antenna " << ant << " on channel " << chan << ", got instead " << tx_paths[chan];
+		return false;
+	}
+
+	return true;
+}
+
+std::string uhd_device::getTxAntenna(size_t chan)
+{
+	if (chan >= tx_paths.size()) {
+		LOG(ALERT) << "Requested non-existent channel " << chan;
+		return "";
+	}
+	return usrp_dev->get_tx_antenna(chan);
+}
+
 /*
  * Only allow sampling the Rx path lower than Tx and not vice-versa.
  * Using Tx with 4 SPS and Rx at 1 SPS is the only allowed mixed
@@ -1451,7 +1568,9 @@
 }
 
 RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps,
-			       InterfaceType iface, size_t chans, double offset)
+			       InterfaceType iface, size_t chans, double offset,
+			       const std::vector<std::string>& tx_paths,
+			       const std::vector<std::string>& rx_paths)
 {
-	return new uhd_device(tx_sps, rx_sps, iface, chans, offset);
+	return new uhd_device(tx_sps, rx_sps, iface, chans, offset, tx_paths, rx_paths);
 }
diff --git a/Transceiver52M/USRPDevice.cpp b/Transceiver52M/USRPDevice.cpp
index 162bb24..f7f24e9 100644
--- a/Transceiver52M/USRPDevice.cpp
+++ b/Transceiver52M/USRPDevice.cpp
@@ -313,6 +313,46 @@
   return dB;
 }
 
+bool USRPDevice::setRxAntenna(const std::string &ant, size_t chan)
+{
+	if (chan >= rx_paths.size()) {
+		LOG(ALERT) << "Requested non-existent channel " << chan;
+		return false;
+	}
+	LOG(ALERT) << "Not implemented";
+	return true;
+}
+
+std::string USRPDevice::getRxAntenna(size_t chan)
+{
+	if (chan >= rx_paths.size()) {
+		LOG(ALERT) << "Requested non-existent channel " << chan;
+		return "";
+	}
+	LOG(ALERT) << "Not implemented";
+	return "";
+}
+
+bool USRPDevice::setTxAntenna(const std::string &ant, size_t chan)
+{
+	if (chan >= tx_paths.size()) {
+		LOG(ALERT) << "Requested non-existent channel " << chan;
+		return false;
+	}
+	LOG(ALERT) << "Not implemented";
+	return true;
+}
+
+std::string USRPDevice::getTxAntenna(size_t chan)
+{
+	if (chan >= tx_paths.size()) {
+		LOG(ALERT) << "Requested non-existent channel " << chan;
+		return "";
+	}
+	LOG(ALERT) << "Not implemented";
+	return "";
+}
+
 
 // NOTE: Assumes sequential reads
 int USRPDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
@@ -600,7 +640,9 @@
 #endif
 
 RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps,
-			       RadioDevice::InterfaceType, size_t chans, double)
+			       InterfaceType iface, size_t chans, double offset,
+			       const std::vector<std::string>& tx_paths,
+			       const std::vector<std::string>& rx_paths)
 {
 	return new USRPDevice(tx_sps);
 }
diff --git a/Transceiver52M/USRPDevice.h b/Transceiver52M/USRPDevice.h
index 3cbf672..f5fbe85 100644
--- a/Transceiver52M/USRPDevice.h
+++ b/Transceiver52M/USRPDevice.h
@@ -179,6 +179,18 @@
   /** return minimum Rx Gain **/
   double minTxGain(void);
 
+  /** sets the RX path to use, returns true if successful and false otherwise */
+  bool setRxAntenna(const std::string &ant, size_t chan = 0);
+
+  /* return the used RX path */
+  std::string getRxAntenna(size_t chan = 0);
+
+  /** sets the RX path to use, returns true if successful and false otherwise */
+  bool setTxAntenna(const std::string &ant, size_t chan = 0);
+
+  /* return the used RX path */
+  std::string getTxAntenna(size_t chan = 0);
+
   /** Return internal status values */
   inline double getTxFreq(size_t chan = 0) { return 0; }
   inline double getRxFreq(size_t chan = 0) { return 0; }
diff --git a/Transceiver52M/osmo-trx.cpp b/Transceiver52M/osmo-trx.cpp
index 44da638..8c34893 100644
--- a/Transceiver52M/osmo-trx.cpp
+++ b/Transceiver52M/osmo-trx.cpp
@@ -28,6 +28,10 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <sched.h>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <iostream>
 
 #include <GSMCommon.h>
 #include <Logger.h>
@@ -79,6 +83,8 @@
 	bool swap_channels;
 	bool edge;
 	int sched_rr;
+	std::vector<std::string> rx_paths;
+	std::vector<std::string> tx_paths;
 };
 
 volatile bool gshutdown = false;
@@ -93,6 +99,7 @@
 bool trx_setup_config(struct trx_config *config)
 {
 	std::string refstr, fillstr, divstr, mcstr, edgestr;
+	std::vector<std::string>::const_iterator si;
 
 	if (config->mcbts && config->chans > 5) {
 		std::cout << "Unsupported number of channels" << std::endl;
@@ -144,8 +151,16 @@
 	ost << "   Tuning offset........... " << config->offset << std::endl;
 	ost << "   RSSI to dBm offset...... " << config->rssi_offset << std::endl;
 	ost << "   Swap channels........... " << config->swap_channels << std::endl;
-	std::cout << ost << std::endl;
+	ost << "   Tx Antennas.............";
+		for (si = config->tx_paths.begin(); si != config->tx_paths.end(); ++si)
+			ost << " '" << ((*si != "") ? *si : "<default>") <<  "'";
+		ost << std::endl;
+	ost << "   Rx Antennas.............";
+		for (si = config->rx_paths.begin(); si != config->rx_paths.end(); ++si)
+			ost << " '" << ((*si != "") ? *si : "<default>") <<  "'";
+		ost << std::endl;
 
+	std::cout << ost << std::endl;
 	return true;
 }
 
@@ -241,6 +256,21 @@
 	}
 }
 
+
+static std::vector<std::string> comma_delimited_to_vector(char* opt) {
+	std::string str = std::string(opt);
+	std::vector<std::string> result;
+	std::stringstream ss(str);
+
+	while( ss.good() )
+	{
+	    std::string substr;
+	    getline(ss, substr, ',');
+	    result.push_back(substr);
+	}
+	return result;
+}
+
 static void print_help()
 {
 	fprintf(stdout, "Options:\n"
@@ -263,13 +293,16 @@
 		"  -A    Random Access Burst test mode with delay\n"
 		"  -R    RSSI to dBm offset in dB (default=0)\n"
 		"  -S    Swap channels (UmTRX only)\n"
-		"  -t    SCHED_RR real-time priority (1..32)\n",
+		"  -t    SCHED_RR real-time priority (1..32)\n"
+		"  -y    comma-delimited list of Tx paths (num elements matches -c)\n"
+		"  -z    comma-delimited list of Rx paths (num elements matches -c)\n",
 		"EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
 }
 
 static void handle_options(int argc, char **argv, struct trx_config *config)
 {
 	int option;
+	bool tx_path_set = false, rx_path_set = false;
 
 	config->log_level = "NOTICE";
 	config->local_addr = DEFAULT_TRX_IP;
@@ -289,8 +322,10 @@
 	config->swap_channels = false;
 	config->edge = false;
 	config->sched_rr = -1;
+	config->tx_paths = std::vector<std::string>(DEFAULT_CHANS, "");
+	config->rx_paths = std::vector<std::string>(DEFAULT_CHANS, "");
 
-	while ((option = getopt(argc, argv, "ha:l:i:j:p:c:dmxgfo:s:b:r:A:R:Set:")) != -1) {
+	while ((option = getopt(argc, argv, "ha:l:i:j:p:c:dmxgfo:s:b:r:A:R:Set:y:z:")) != -1) {
 		switch (option) {
 		case 'h':
 			print_help();
@@ -355,6 +390,14 @@
 		case 't':
 			config->sched_rr = atoi(optarg);
 			break;
+		case 'y':
+			config->tx_paths = comma_delimited_to_vector(optarg);
+			tx_path_set = true;
+			break;
+		case 'z':
+			config->rx_paths = comma_delimited_to_vector(optarg);
+			rx_path_set = true;
+			break;
 		default:
 			print_help();
 			exit(0);
@@ -388,6 +431,19 @@
 
 	if (config->rach_delay > 68) {
 		printf("RACH delay is too big %i\n\n", config->rach_delay);
+		goto bad_config;
+	}
+
+	if (!tx_path_set) {
+		config->tx_paths = std::vector<std::string>(config->chans, "");
+	} else if (config->tx_paths.size() != config->chans) {
+		printf("Num of channels and num of Tx Antennas doesn't match\n\n");
+		goto bad_config;
+	}
+	if (!rx_path_set) {
+		config->rx_paths = std::vector<std::string>(config->chans, "");
+	} else if (config->rx_paths.size() != config->chans) {
+		printf("Num of channels and num of Rx Antennas doesn't match\n\n");
 		goto bad_config;
 	}
 
@@ -480,7 +536,7 @@
 		ref = RadioDevice::REF_INTERNAL;
 
 	usrp = RadioDevice::make(config.tx_sps, config.rx_sps, iface,
-				 config.chans, config.offset);
+				 config.chans, config.offset, config.tx_paths, config.rx_paths);
 	type = usrp->open(config.dev_args, ref, config.swap_channels);
 	if (type < 0) {
 		LOG(ALERT) << "Failed to create radio device" << std::endl;
diff --git a/Transceiver52M/radioDevice.h b/Transceiver52M/radioDevice.h
index 3624c58..dfa1c78 100644
--- a/Transceiver52M/radioDevice.h
+++ b/Transceiver52M/radioDevice.h
@@ -50,7 +50,9 @@
   };
 
   static RadioDevice *make(size_t tx_sps, size_t rx_sps, InterfaceType type,
-                           size_t chans = 1, double offset = 0.0);
+                           size_t chans = 1, double offset = 0.0,
+                           const std::vector<std::string>& tx_paths = std::vector<std::string>(1, ""),
+                           const std::vector<std::string>& rx_paths = std::vector<std::string>(1, ""));
 
   /** Initialize the USRP */
   virtual int open(const std::string &args, int ref, bool swap_channels)=0;
@@ -136,6 +138,18 @@
   /** return minimum Tx Gain **/
   virtual double minTxGain(void) = 0;
 
+  /** sets the RX path to use, returns true if successful and false otherwise */
+  virtual bool setRxAntenna(const std::string &ant, size_t chan = 0) = 0;
+
+  /** return the used RX path */
+  virtual std::string getRxAntenna(size_t chan = 0) = 0;
+
+  /** sets the RX path to use, returns true if successful and false otherwise */
+  virtual bool setTxAntenna(const std::string &ant, size_t chan = 0) = 0;
+
+  /** return the used RX path */
+  virtual std::string getTxAntenna(size_t chan = 0) = 0;
+
   /** Return internal status values */
   virtual double getTxFreq(size_t chan = 0) = 0;
   virtual double getRxFreq(size_t chan = 0) = 0;

-- 
To view, visit https://gerrit.osmocom.org/6238
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I1735e6ab05a05b0312d6d679b16ebd4a2260fa23
Gerrit-PatchSet: 3
Gerrit-Project: osmo-trx
Gerrit-Branch: master
Gerrit-Owner: Pau Espin Pedrol <pespin at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Pau Espin Pedrol <pespin at sysmocom.de>
Gerrit-Reviewer: Vadim Yanitskiy <axilirator at gmail.com>



More information about the gerrit-log mailing list