aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Tsou <tom@tsou.cc>2014-02-13 15:09:00 -0500
committerThomas Tsou <tom@tsou.cc>2014-03-03 23:17:57 -0500
commit3ebc772dc211ad9c506e413683f66d833fd7e0da (patch)
tree5301484a1e2d77c6a47895c3fa8ed5a6ea69049e
parent18d3b833bce36c543993852ab1b59724f8a60ece (diff)
Transceiver52M: Enable B210 dual channel support
The main difference between existing UmTRX dual channel is the single LO on B210 transmit and receive front-ends vs. independent tuning paths. In order to support dual-ARFCN frequencies, baseband offset conversion must be applied by tuning the FPGA CORDIC for each channel. For B210, the following tuning order is applied. 1. If the new frequency of channel A is within the baseband range of channel B, then retune both channels with the RF centered and equal valued positive and negative baseband shifts. 2. If the new frequency of channel A is not with the baseband range of channel B, then retune channel A directly (without manual applied offset). Channel B will no longer be tuned to the previous frequency. Signed-off-by: Thomas Tsou <tom@tsou.cc>
-rw-r--r--Transceiver52M/UHDDevice.cpp101
1 files changed, 89 insertions, 12 deletions
diff --git a/Transceiver52M/UHDDevice.cpp b/Transceiver52M/UHDDevice.cpp
index 758b6c2..dbd0a20 100644
--- a/Transceiver52M/UHDDevice.cpp
+++ b/Transceiver52M/UHDDevice.cpp
@@ -349,6 +349,9 @@ private:
std::string str_code(uhd::rx_metadata_t metadata);
std::string str_code(uhd::async_metadata_t metadata);
+ uhd::tune_request_t select_freq(double wFreq, size_t chan, bool tx);
+ bool set_freq(double freq, size_t chan, bool tx);
+
Thread async_event_thrd;
bool diversity;
};
@@ -618,7 +621,8 @@ int uhd_device::open(const std::string &args, bool extref)
return -1;
// Verify and set channels
- if ((dev_type == UMTRX) && (chans == 2)) {
+ if ((dev_type == B210) && (chans == 2)) {
+ } else if ((dev_type == UMTRX) && (chans == 2)) {
uhd::usrp::subdev_spec_t subdev_spec("A:0 B:0");
usrp_dev->set_tx_subdev_spec(subdev_spec);
usrp_dev->set_rx_subdev_spec(subdev_spec);
@@ -656,7 +660,9 @@ int uhd_device::open(const std::string &args, bool extref)
else
_rx_rate = _tx_rate / sps;
- if ((_tx_rate > 0.0) && (set_rates(_tx_rate, _rx_rate) < 0))
+ if ((_tx_rate < 0.0) || (_rx_rate < 0.0))
+ return -1;
+ if (set_rates(_tx_rate, _rx_rate) < 0)
return -1;
// Create receive buffer
@@ -968,6 +974,82 @@ bool uhd_device::updateAlignment(TIMESTAMP timestamp)
return true;
}
+uhd::tune_request_t uhd_device::select_freq(double freq, size_t chan, bool tx)
+{
+ double rf_spread, rf_freq;
+ std::vector<double> freqs;
+ uhd::tune_request_t treq(freq);
+
+ if (chans == 1)
+ return treq;
+ else if ((dev_type == UMTRX) && (chans == 2))
+ return treq;
+ else if ((dev_type != B210) || (chans > 2) || (chan > 1)) {
+ LOG(ALERT) << chans << " channels unsupported";
+ return treq;
+ }
+
+ if (tx)
+ freqs = tx_freqs;
+ else
+ freqs = rx_freqs;
+
+ /* Tune directly if other channel isn't tuned */
+ if (freqs[!chan] < 10.0)
+ return treq;
+
+ /* Find center frequency between channels */
+ rf_spread = fabs(freqs[!chan] - freq);
+ if (rf_spread > B2XX_CLK_RT) {
+ LOG(ALERT) << rf_spread << "Hz tuning spread not supported\n";
+ return treq;
+ }
+
+ rf_freq = (freqs[!chan] + freq) / 2.0f;
+
+ treq.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL;
+ treq.target_freq = freq;
+ treq.rf_freq = rf_freq;
+
+ return treq;
+}
+
+bool uhd_device::set_freq(double freq, size_t chan, bool tx)
+{
+ std::vector<double> freqs;
+ uhd::tune_result_t tres;
+ uhd::tune_request_t treq = select_freq(freq, chan, tx);
+
+ if (tx) {
+ tres = usrp_dev->set_tx_freq(treq, chan);
+ tx_freqs[chan] = usrp_dev->get_tx_freq(chan);
+ } else {
+ tres = usrp_dev->set_rx_freq(treq, chan);
+ rx_freqs[chan] = usrp_dev->get_rx_freq(chan);
+ }
+ LOG(INFO) << "\n" << tres.to_pp_string() << std::endl;
+
+ /* Manual RF policy means we intentionally tuned with a baseband
+ * offset for dual-channel purposes. Now retune the other channel
+ * with the opposite corresponding frequency offset
+ */
+ if (treq.rf_freq_policy == uhd::tune_request_t::POLICY_MANUAL) {
+ if (tx) {
+ treq = select_freq(tx_freqs[!chan], !chan, true);
+ tres = usrp_dev->set_tx_freq(treq, !chan);
+ tx_freqs[!chan] = usrp_dev->get_tx_freq(!chan);
+ } else {
+ treq = select_freq(rx_freqs[!chan], !chan, false);
+ tres = usrp_dev->set_rx_freq(treq, !chan);
+ rx_freqs[!chan] = usrp_dev->get_rx_freq(!chan);
+
+ }
+ LOG(INFO) << "\n" << tres.to_pp_string() << std::endl;
+ }
+
+ return true;
+}
+
bool uhd_device::setTxFreq(double wFreq, size_t chan)
{
if (chan >= tx_freqs.size()) {
@@ -975,11 +1057,7 @@ bool uhd_device::setTxFreq(double wFreq, size_t chan)
return false;
}
- uhd::tune_result_t tr = usrp_dev->set_tx_freq(wFreq, chan);
- LOG(INFO) << "\n" << tr.to_pp_string();
- tx_freqs[chan] = usrp_dev->get_tx_freq(chan);
-
- return true;
+ return set_freq(wFreq, chan, true);
}
bool uhd_device::setRxFreq(double wFreq, size_t chan)
@@ -989,11 +1067,7 @@ bool uhd_device::setRxFreq(double wFreq, size_t chan)
return false;
}
- uhd::tune_result_t tr = usrp_dev->set_rx_freq(wFreq, chan);
- LOG(INFO) << "\n" << tr.to_pp_string();
- rx_freqs[chan] = usrp_dev->get_rx_freq(chan);
-
- return true;
+ return set_freq(wFreq, chan, false);
}
double uhd_device::getTxFreq(size_t chan)
@@ -1055,6 +1129,9 @@ std::string uhd_device::str_code(uhd::rx_metadata_t metadata)
case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
ost << "An internal receive buffer has filled";
break;
+ case uhd::rx_metadata_t::ERROR_CODE_ALIGNMENT:
+ ost << "Multi-channel alignment failed";
+ break;
case uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET:
ost << "The packet could not be parsed";
break;