aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/UHDDevice.cpp
diff options
context:
space:
mode:
authorThomas Tsou <tom@tsou.cc>2013-04-08 14:18:26 -0400
committerThomas Tsou <tom@tsou.cc>2013-10-18 13:03:41 -0400
commitcb69f084107367eb1a95cd0e6ef3a379361f3e7c (patch)
tree7e06d370c266df839da53437275aeff1eb9235a7 /Transceiver52M/UHDDevice.cpp
parent312e387630c6a2d6a6b0c7fc80f3661acfdfd0ed (diff)
Transceiver52M: Set resampling option automatically based on device
Remove the built time resampling selection and link both options. Move the normal push/pullBuffer() calls back to the base class and overload them in the inherited resampling class. USRP2/N2xx devices are the only devices that require resampling so return that resampling is necessary on the device open(), which is the point at which the device type will be known. The GSM transceiver only operates at a whole number multiple of the GSM rate and doesn't care about the actual device rate and if resampling is used. Therefore GSM specific portion of the transceiver should only need to submit the samples-per-symbol value to the device interface. Then, the device should be able to determine the appropriate sample rate (400 ksps or 270.833 ksps) and if resampling is appropriate. Signed-off-by: Thomas Tsou <tom@tsou.cc>
Diffstat (limited to 'Transceiver52M/UHDDevice.cpp')
-rw-r--r--Transceiver52M/UHDDevice.cpp82
1 files changed, 58 insertions, 24 deletions
diff --git a/Transceiver52M/UHDDevice.cpp b/Transceiver52M/UHDDevice.cpp
index 6ce3380..575cb01 100644
--- a/Transceiver52M/UHDDevice.cpp
+++ b/Transceiver52M/UHDDevice.cpp
@@ -32,7 +32,9 @@
#include "config.h"
#endif
-#define B100_CLK_RT 52e6
+#define B100_CLK_RT 52e6
+#define B100_BASE_RT GSMRATE
+#define USRP2_BASE_RT 400e3
#define TX_AMPL 0.3
#define SAMPLE_BUF_SZ (1 << 20)
@@ -91,6 +93,29 @@ static double get_dev_offset(enum uhd_dev_type type, int sps)
return 0.0;
}
+/*
+ * Select sample rate based on device type and requested samples-per-symbol.
+ * The base rate is either GSM symbol rate, 270.833 kHz, or the minimum
+ * usable channel spacing of 400 kHz.
+ */
+static double select_rate(uhd_dev_type type, int sps)
+{
+ if ((sps != 4) && (sps != 2) && (sps != 1))
+ return -9999.99;
+
+ switch (type) {
+ case USRP2:
+ return USRP2_BASE_RT * sps;
+ break;
+ case B100:
+ return B100_BASE_RT * sps;
+ break;
+ }
+
+ LOG(ALERT) << "Unknown device type " << type;
+ return -9999.99;
+}
+
/** Timestamp conversion
@param timestamp a UHD or OpenBTS timestamp
@param rate sample rate
@@ -181,10 +206,10 @@ private:
*/
class uhd_device : public RadioDevice {
public:
- uhd_device(double rate, int sps, bool skip_rx);
+ uhd_device(int sps, bool skip_rx);
~uhd_device();
- bool open(const std::string &args);
+ int open(const std::string &args);
bool start();
bool stop();
void restart(uhd::time_spec_t ts);
@@ -306,9 +331,8 @@ void uhd_msg_handler(uhd::msg::type_t type, const std::string &msg)
}
}
-uhd_device::uhd_device(double rate, int sps, bool skip_rx)
- : desired_smpl_rt(rate), actual_smpl_rt(0),
- tx_gain(0.0), tx_gain_min(0.0), tx_gain_max(0.0),
+uhd_device::uhd_device(int sps, bool skip_rx)
+ : tx_gain(0.0), tx_gain_min(0.0), tx_gain_max(0.0),
rx_gain(0.0), rx_gain_min(0.0), rx_gain_max(0.0),
tx_freq(0.0), rx_freq(0.0), tx_spp(0), rx_spp(0),
started(false), aligned(false), rx_pkt_cnt(0), drop_cnt(0),
@@ -374,6 +398,9 @@ int uhd_device::set_master_clk(double clk_rate)
int uhd_device::set_rates(double rate)
{
+ double offset_limit = 10.0;
+ double tx_offset, rx_offset;
+
// B100 is the only device where we set FPGA clocking
if (dev_type == B100) {
if (set_master_clk(B100_CLK_RT) < 0)
@@ -385,14 +412,14 @@ int uhd_device::set_rates(double rate)
usrp_dev->set_rx_rate(rate);
actual_smpl_rt = usrp_dev->get_tx_rate();
- if (actual_smpl_rt != rate) {
+ tx_offset = actual_smpl_rt - rate;
+ rx_offset = usrp_dev->get_rx_rate() - rate;
+ if ((tx_offset > offset_limit) || (rx_offset > offset_limit)) {
LOG(ALERT) << "Actual sample rate differs from desired rate";
+ LOG(ALERT) << "Tx/Rx (" << actual_smpl_rt << "/"
+ << usrp_dev->get_rx_rate() << ")";
return -1;
}
- if (usrp_dev->get_rx_rate() != actual_smpl_rt) {
- LOG(ALERT) << "Transmit and receive sample rates do not match";
- return -1.0;
- }
return 0;
}
@@ -427,15 +454,15 @@ bool uhd_device::parse_dev_type()
{
std::string mboard_str, dev_str;
uhd::property_tree::sptr prop_tree;
- size_t usrp1_str, usrp2_str, b100_str1, b100_str2;
+ size_t usrp1_str, usrp2_str, b100_str;
prop_tree = usrp_dev->get_device()->get_tree();
dev_str = prop_tree->access<std::string>("/name").get();
mboard_str = usrp_dev->get_mboard_name();
usrp1_str = dev_str.find("USRP1");
- b100_str1 = dev_str.find("B-Series");
- b100_str2 = mboard_str.find("B100");
+ usrp2_str = dev_str.find("USRP2");
+ b100_str = mboard_str.find("B100");
if (usrp1_str != std::string::npos) {
LOG(ALERT) << "USRP1 is not supported using the UHD driver";
@@ -444,14 +471,17 @@ bool uhd_device::parse_dev_type()
return false;
}
- if ((b100_str1 != std::string::npos) || (b100_str2 != std::string::npos)) {
+ if (b100_str != std::string::npos) {
tx_window = TX_WINDOW_USRP1;
LOG(INFO) << "Using USRP1 type transmit window for "
<< dev_str << " " << mboard_str;
dev_type = B100;
return true;
- } else {
+ } else if (usrp2_str != std::string::npos) {
dev_type = USRP2;
+ } else {
+ LOG(ALERT) << "Unknown UHD device type";
+ return false;
}
tx_window = TX_WINDOW_FIXED;
@@ -460,7 +490,7 @@ bool uhd_device::parse_dev_type()
return true;
}
-bool uhd_device::open(const std::string &args)
+int uhd_device::open(const std::string &args)
{
// Register msg handler
uhd::msg::register_handler(&uhd_msg_handler);
@@ -470,7 +500,7 @@ bool uhd_device::open(const std::string &args)
uhd::device_addrs_t dev_addrs = uhd::device::find(addr);
if (dev_addrs.size() == 0) {
LOG(ALERT) << "No UHD devices found with address '" << args << "'";
- return false;
+ return -1;
}
// Use the first found device
@@ -479,12 +509,12 @@ bool uhd_device::open(const std::string &args)
usrp_dev = uhd::usrp::multi_usrp::make(dev_addrs[0]);
} catch(...) {
LOG(ALERT) << "UHD make failed, device " << dev_addrs[0].to_string();
- return false;
+ return -1;
}
// Check for a valid device type and set bus type
if (!parse_dev_type())
- return false;
+ return -1;
#ifdef EXTREF
set_ref_clk(true);
@@ -499,8 +529,9 @@ bool uhd_device::open(const std::string &args)
rx_spp = rx_stream->get_max_num_samps();
// Set rates
+ desired_smpl_rt = select_rate(dev_type, sps);
if (set_rates(desired_smpl_rt) < 0)
- return false;
+ return -1;
// Create receive buffer
size_t buf_len = SAMPLE_BUF_SZ / sizeof(uint32_t);
@@ -521,7 +552,10 @@ bool uhd_device::open(const std::string &args)
// Print configuration
LOG(INFO) << "\n" << usrp_dev->get_pp_string();
- return true;
+ if (dev_type == USRP2)
+ return RESAMP;
+
+ return NORMAL;
}
bool uhd_device::flush_recv(size_t num_pkts)
@@ -1021,7 +1055,7 @@ std::string smpl_buf::str_code(ssize_t code)
}
}
-RadioDevice *RadioDevice::make(double smpl_rt, int sps, bool skip_rx)
+RadioDevice *RadioDevice::make(int sps, bool skip_rx)
{
- return new uhd_device(smpl_rt, sps, skip_rx);
+ return new uhd_device(sps, skip_rx);
}