mcbts: Add multi-ARFCN radio support

Add new radio interface "radioInterfaceMulti" for multi-carrier
support.

Only USRP B200/B210 devices are supported because of sample
rate requirements (3.2 Msps).

Only 4 SPS operation Tx/RX is supported.

8-PSK is supported.

Other options may be added at a later time

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
diff --git a/Transceiver52M/osmo-trx.cpp b/Transceiver52M/osmo-trx.cpp
index 9dcda5f..ac9cc48 100644
--- a/Transceiver52M/osmo-trx.cpp
+++ b/Transceiver52M/osmo-trx.cpp
@@ -74,6 +74,7 @@
 	bool extref;
 	Transceiver::FillerType filler;
 	bool diversity;
+	bool mcbts;
 	double offset;
 	double rssi_offset;
 	bool swap_channels;
@@ -127,7 +128,7 @@
  */
 bool trx_setup_config(struct trx_config *config)
 {
-	std::string refstr, fillstr, divstr, edgestr;
+	std::string refstr, fillstr, divstr, mcstr, edgestr;
 
 	if (!testConfig())
 		return false;
@@ -163,13 +164,29 @@
 			config->diversity = DEFAULT_DIVERSITY;
 	}
 
-	/* Diversity only supported on 2 channels */
-	if (config->diversity)
+	if (!config->chans)
+		config->chans = DEFAULT_CHANS;
+
+	if (config->mcbts && ((config->chans < 0) || (config->chans > 5))) {
+		std::cout << "Unsupported number of channels" << std::endl;
+		return false;
+	}
+
+	/* Diversity only supported on 2 channels without multi-carrier */
+	if (config->diversity && config->mcbts) {
+		std::cout << "Multi-carrier diversity unsupported" << std::endl;
+		return false;
+	}
+	if (config->diversity && (config->chans != 2)) {
+		std::cout << "Setting channels to 2 for diversity" << std::endl;
 		config->chans = 2;
+	}
 
 	edgestr = config->edge ? "Enabled" : "Disabled";
 	refstr = config->extref ? "Enabled" : "Disabled";
 	divstr = config->diversity ? "Enabled" : "Disabled";
+	mcstr = config->mcbts ? "Enabled" : "Disabled";
+
 	switch (config->filler) {
 	case Transceiver::FILLER_DUMMY:
 		fillstr = "Dummy bursts";
@@ -200,6 +217,7 @@
 	ost << "   EDGE support............ " << edgestr << std::endl;
 	ost << "   External Reference...... " << refstr << std::endl;
 	ost << "   C0 Filler Table......... " << fillstr << std::endl;
+	ost << "   Multi-Carrier........... " << mcstr << std::endl;
 	ost << "   Diversity............... " << divstr << std::endl;
 	ost << "   Tuning offset........... " << config->offset << std::endl;
 	ost << "   RSSI to dBm offset...... " << config->rssi_offset << std::endl;
@@ -235,6 +253,10 @@
 		radio = new RadioInterfaceDiversity(usrp, config->tx_sps,
 						    config->chans);
 		break;
+	case RadioDevice::MULTI_ARFCN:
+		radio = new RadioInterfaceMulti(usrp, config->tx_sps,
+						config->rx_sps, config->chans);
+		break;
 	default:
 		LOG(ALERT) << "Unsupported radio interface configuration";
 		return NULL;
@@ -309,6 +331,7 @@
 		"  -p    Base port number\n"
 		"  -e    Enable EDGE receiver\n"
 		"  -d    Enable dual channel diversity receiver\n"
+		"  -m    Enable multi-ARFCN transceiver (default=disabled)\n"
 		"  -x    Enable external 10 MHz reference\n"
 		"  -s    Tx samples-per-symbol (1 or 4)\n"
 		"  -b    Rx samples-per-symbol (1 or 4)\n"
@@ -334,13 +357,14 @@
 	config->rach_delay = 0;
 	config->extref = false;
 	config->filler = Transceiver::FILLER_ZERO;
+	config->mcbts = false;
 	config->diversity = false;
 	config->offset = 0.0;
 	config->rssi_offset = 0.0;
 	config->swap_channels = false;
 	config->edge = false;
 
-	while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:b:r:A:R:Se")) != -1) {
+	while ((option = getopt(argc, argv, "ha:l:i:p:c:dmxfo:s:b:r:A:R:Se")) != -1) {
 		switch (option) {
 		case 'h':
 			print_help();
@@ -361,6 +385,9 @@
 		case 'c':
 			config->chans = atoi(optarg);
 			break;
+		case 'm':
+			config->mcbts = true;
+			break;
 		case 'd':
 			config->diversity = true;
 			break;
@@ -403,8 +430,8 @@
 		}
 	}
 
-	/* Force 4 SPS for EDGE configurations */
-	if (config->edge) {
+	/* Force 4 SPS for EDGE or multi-ARFCN configurations */
+	if ((config->edge) || (config->mcbts)) {
 		config->tx_sps = 4;
 		config->rx_sps = 4;
 	}
@@ -412,7 +439,8 @@
 	if (config->edge && (config->filler == Transceiver::FILLER_NORM_RAND))
 		config->filler = Transceiver::FILLER_EDGE_RAND;
 
-	if ((config->tx_sps != 1) && (config->tx_sps != 4)) {
+	if ((config->tx_sps != 1) && (config->tx_sps != 4) &&
+	    (config->rx_sps != 1) && (config->rx_sps != 4)) {
 		printf("Unsupported samples-per-symbol %i\n\n", config->tx_sps);
 		print_help();
 		exit(0);
@@ -455,6 +483,9 @@
 	srandom(time(NULL));
 
 	/* Create the low level device object */
+	if (config.mcbts)
+		iface = RadioDevice::MULTI_ARFCN;
+
 	usrp = RadioDevice::make(config.tx_sps, config.rx_sps, iface,
 				 config.chans, config.offset);
 	type = usrp->open(config.dev_args, config.extref, config.swap_channels);