devices: add freq/gain override for uhd

This allows using arbitrary gain and frequencies.

Change-Id: I3c1b9a067cafc6d696b9aa2da8ee0480ec1e094f
diff --git a/CommonLibs/config_defs.h b/CommonLibs/config_defs.h
index 33be73f..bf49bcf 100644
--- a/CommonLibs/config_defs.h
+++ b/CommonLibs/config_defs.h
@@ -57,4 +57,14 @@
 	unsigned int stack_size;
 	unsigned int num_chans;
 	struct trx_chan chans[TRX_CHAN_MAX];
+	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;
 };
diff --git a/CommonLibs/trx_vty.c b/CommonLibs/trx_vty.c
index 6724189..1878d83 100644
--- a/CommonLibs/trx_vty.c
+++ b/CommonLibs/trx_vty.c
@@ -285,6 +285,60 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN_ATTR(cfg_ul_freq_override, cfg_ul_freq_override_cmd,
+	   "ul-freq-override FLOAT",
+	   "Overrides Rx carrier frequency\n"
+	   "Frequency in Hz (e.g. 145300000)\n",
+	   CMD_ATTR_HIDDEN)
+{
+	struct trx_ctx *trx = trx_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 Tx carrier frequency\n"
+	   "Frequency in Hz (e.g. 145300000)\n",
+	   CMD_ATTR_HIDDEN)
+{
+	struct trx_ctx *trx = trx_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 Rx gain\n"
+	   "gain in dB\n",
+	   CMD_ATTR_HIDDEN)
+{
+	struct trx_ctx *trx = trx_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 Tx gain\n"
+	   "gain in dB\n",
+	   CMD_ATTR_HIDDEN)
+{
+	struct trx_ctx *trx = trx_from_vty(vty);
+
+	trx->cfg.overrides.dl_gain_override = true;
+	trx->cfg.overrides.dl_gain = atof(argv[0]);
+
+	return CMD_SUCCESS;
+}
+
 DEFUN(cfg_swap_channels, cfg_swap_channels_cmd,
 	"swap-channels (disable|enable)",
 	"Swap primary and secondary channels of the PHY (if any)\n"
@@ -638,6 +692,14 @@
 		vty_out(vty, " stack-size %u%s", trx->cfg.stack_size, VTY_NEWLINE);
 	if (trx->cfg.ul_fn_offset != 0)
 		vty_out(vty, " ul-fn-offset %d%s", trx->cfg.ul_fn_offset, 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);
 	trx_rate_ctr_threshold_write_config(vty, " ");
 
 	for (i = 0; i < trx->cfg.num_chans; i++) {
@@ -803,6 +865,10 @@
 
 	install_element(TRX_NODE, &cfg_chan_cmd);
 	install_element(TRX_NODE, &cfg_ul_fn_offset_cmd);
+	install_element(TRX_NODE, &cfg_ul_freq_override_cmd);
+	install_element(TRX_NODE, &cfg_dl_freq_override_cmd);
+	install_element(TRX_NODE, &cfg_ul_gain_override_cmd);
+	install_element(TRX_NODE, &cfg_dl_gain_override_cmd);
 	install_node(&chan_node, dummy_config_write);
 	install_element(CHAN_NODE, &cfg_chan_rx_path_cmd);
 	install_element(CHAN_NODE, &cfg_chan_tx_path_cmd);
diff --git a/Transceiver52M/device/uhd/UHDDevice.cpp b/Transceiver52M/device/uhd/UHDDevice.cpp
index 95ea8e7..ec772aa 100644
--- a/Transceiver52M/device/uhd/UHDDevice.cpp
+++ b/Transceiver52M/device/uhd/UHDDevice.cpp
@@ -295,6 +295,9 @@
 		return 0.0f;
 	}
 
+	if (cfg->overrides.ul_gain_override)
+		return rx_gains[chan];
+
 	usrp_dev->set_rx_gain(db, chan);
 	rx_gains[chan] = usrp_dev->get_rx_gain(chan);
 
@@ -337,6 +340,9 @@
 		return 0.0f;
 	}
 
+	if (cfg->overrides.dl_gain_override)
+		return atten; // ensures caller does not apply digital attenuation
+
 	get_dev_band_desc(desc);
 	tx_power = desc.nom_out_tx_power - atten;
 	db = TxPower2TxGain(desc, tx_power);
@@ -626,6 +632,32 @@
 	// Print configuration
 	LOGC(DDEV, INFO) << "Device configuration: " << usrp_dev->get_pp_string();
 
+	if (cfg->overrides.dl_freq_override) {
+		uhd::tune_request_t treq_tx = uhd::tune_request_t(cfg->overrides.dl_freq, 0);
+		auto tres = usrp_dev->set_tx_freq(treq_tx, 0);
+		tx_freqs[0] = usrp_dev->get_tx_freq(0);
+		LOGCHAN(0, DDEV, INFO) << "OVERRIDE set_freq(" << tx_freqs[0] << ", TX): " << tres.to_pp_string() << std::endl;
+	}
+
+	if (cfg->overrides.ul_freq_override) {
+		uhd::tune_request_t treq_rx = uhd::tune_request_t(cfg->overrides.ul_freq, 0);
+		auto tres = usrp_dev->set_rx_freq(treq_rx, 0);
+		rx_freqs[0] = usrp_dev->get_rx_freq(0);
+		LOGCHAN(0, DDEV, INFO) << "OVERRIDE set_freq(" << rx_freqs[0] << ", RX): " << tres.to_pp_string() << std::endl;
+	}
+
+	if (cfg->overrides.ul_gain_override) {
+		usrp_dev->set_rx_gain(cfg->overrides.ul_gain, 0);
+		rx_gains[0] = usrp_dev->get_rx_gain(0);
+		LOGCHAN(0, DDEV, INFO) << " OVERRIDE RX gain:" << rx_gains[0] << std::endl;
+	}
+
+	if (cfg->overrides.dl_gain_override) {
+		usrp_dev->set_tx_gain(cfg->overrides.dl_gain, 0);
+		tx_gains[0] = usrp_dev->get_tx_gain(0);
+		LOGCHAN(0, DDEV, INFO) << " OVERRIDE TX gain:" << tx_gains[0] << std::endl;
+	}
+
 	if (iface == MULTI_ARFCN)
 		return MULTI_ARFCN;
 
@@ -978,6 +1010,9 @@
 	uhd::tune_result_t tres;
 	std::string str_dir = tx ? "Tx" : "Rx";
 
+	if (cfg->overrides.dl_freq_override || cfg->overrides.ul_freq_override)
+		return true;
+
 	if (!update_band_from_freq(freq, chan, tx))
 		return false;