aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/UHDDevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Transceiver52M/UHDDevice.cpp')
-rw-r--r--Transceiver52M/UHDDevice.cpp263
1 files changed, 174 insertions, 89 deletions
diff --git a/Transceiver52M/UHDDevice.cpp b/Transceiver52M/UHDDevice.cpp
index 7a1a74d..224ebd0 100644
--- a/Transceiver52M/UHDDevice.cpp
+++ b/Transceiver52M/UHDDevice.cpp
@@ -211,7 +211,7 @@ private:
*/
class uhd_device : public RadioDevice {
public:
- uhd_device(int sps, bool skip_rx);
+ uhd_device(size_t sps, size_t chans);
~uhd_device();
int open(const std::string &args, bool extref);
@@ -221,16 +221,16 @@ public:
void setPriority();
enum TxWindowType getWindowType() { return tx_window; }
- int readSamples(short *buf, int len, bool *overrun,
+ int readSamples(std::vector<short *> &bufs, int len, bool *overrun,
TIMESTAMP timestamp, bool *underrun, unsigned *RSSI);
- int writeSamples(short *buf, int len, bool *underrun,
+ int writeSamples(std::vector<short *> &bufs, int len, bool *underrun,
TIMESTAMP timestamp, bool isControl);
bool updateAlignment(TIMESTAMP timestamp);
- bool setTxFreq(double wFreq);
- bool setRxFreq(double wFreq);
+ bool setTxFreq(double wFreq, size_t chan);
+ bool setRxFreq(double wFreq, size_t chan);
inline TIMESTAMP initialWriteTimestamp() { return 0; }
inline TIMESTAMP initialReadTimestamp() { return 0; }
@@ -238,17 +238,18 @@ public:
inline double fullScaleInputValue() { return 32000 * TX_AMPL; }
inline double fullScaleOutputValue() { return 32000; }
- double setRxGain(double db);
- double getRxGain(void) { return rx_gain; }
+ double setRxGain(double db, size_t chan);
+ double getRxGain(size_t chan);
double maxRxGain(void) { return rx_gain_max; }
double minRxGain(void) { return rx_gain_min; }
- double setTxGain(double db);
+ double setTxGain(double db, size_t chan);
double maxTxGain(void) { return tx_gain_max; }
double minTxGain(void) { return tx_gain_min; }
- double getTxFreq() { return tx_freq; }
- double getRxFreq() { return rx_freq; }
+ double getTxFreq(size_t chan);
+ double getRxFreq(size_t chan);
+ double getRxFreq();
inline double getSampleRate() { return tx_rate; }
inline double numberRead() { return rx_pkt_cnt; }
@@ -272,25 +273,25 @@ private:
enum TxWindowType tx_window;
enum uhd_dev_type dev_type;
- int sps;
+ size_t sps, chans;
double tx_rate, rx_rate;
- double tx_gain, tx_gain_min, tx_gain_max;
- double rx_gain, rx_gain_min, rx_gain_max;
+ double tx_gain_min, tx_gain_max;
+ double rx_gain_min, rx_gain_max;
- double tx_freq, rx_freq;
+ std::vector<double> tx_gains, rx_gains;
+ std::vector<double> tx_freqs, rx_freqs;
size_t tx_spp, rx_spp;
bool started;
bool aligned;
- bool skip_rx;
size_t rx_pkt_cnt;
size_t drop_cnt;
uhd::time_spec_t prev_ts;
TIMESTAMP ts_offset;
- smpl_buf *rx_smpl_buf;
+ std::vector<smpl_buf *> rx_buffers;
void init_gains();
int set_master_clk(double rate);
@@ -335,23 +336,23 @@ void uhd_msg_handler(uhd::msg::type_t type, const std::string &msg)
}
}
-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),
+uhd_device::uhd_device(size_t sps, size_t chans)
+ : 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),
started(false), aligned(false), rx_pkt_cnt(0), drop_cnt(0),
- prev_ts(0,0), ts_offset(0), rx_smpl_buf(NULL)
+ prev_ts(0,0), ts_offset(0)
{
this->sps = sps;
- this->skip_rx = skip_rx;
+ this->chans = chans;
}
uhd_device::~uhd_device()
{
stop();
- if (rx_smpl_buf)
- delete rx_smpl_buf;
+ for (size_t i = 0; i < rx_buffers.size(); i++)
+ delete rx_buffers[i];
}
void uhd_device::init_gains()
@@ -366,13 +367,18 @@ void uhd_device::init_gains()
rx_gain_min = range.start();
rx_gain_max = range.stop();
- usrp_dev->set_tx_gain((tx_gain_min + tx_gain_max) / 2);
- usrp_dev->set_rx_gain((rx_gain_min + rx_gain_max) / 2);
+ for (size_t i = 0; i < tx_gains.size(); i++) {
+ usrp_dev->set_tx_gain((tx_gain_min + tx_gain_max) / 2, i);
+ tx_gains[i] = usrp_dev->get_tx_gain(i);
+ }
- tx_gain = usrp_dev->get_tx_gain();
- rx_gain = usrp_dev->get_rx_gain();
+ for (size_t i = 0; i < rx_gains.size(); i++) {
+ usrp_dev->set_rx_gain((rx_gain_min + rx_gain_max) / 2, i);
+ rx_gains[i] = usrp_dev->get_rx_gain(i);
+ }
return;
+
}
int uhd_device::set_master_clk(double clk_rate)
@@ -435,24 +441,44 @@ int uhd_device::set_rates(double tx_rate, double rx_rate)
return 0;
}
-double uhd_device::setTxGain(double db)
+double uhd_device::setTxGain(double db, size_t chan)
{
- usrp_dev->set_tx_gain(db);
- tx_gain = usrp_dev->get_tx_gain();
+ if (chan >= tx_gains.size()) {
+ LOG(ALERT) << "Requested non-existent channel" << chan;
+ return 0.0f;
+ }
+
+ usrp_dev->set_tx_gain(db, chan);
+ tx_gains[chan] = usrp_dev->get_tx_gain(chan);
- LOG(INFO) << "Set TX gain to " << tx_gain << "dB";
+ LOG(INFO) << "Set TX gain to " << tx_gains[chan] << "dB";
- return tx_gain;
+ return tx_gains[chan];
}
-double uhd_device::setRxGain(double db)
+double uhd_device::setRxGain(double db, size_t chan)
{
- usrp_dev->set_rx_gain(db);
- rx_gain = usrp_dev->get_rx_gain();
+ if (chan >= rx_gains.size()) {
+ LOG(ALERT) << "Requested non-existent channel " << chan;
+ return 0.0f;
+ }
- LOG(INFO) << "Set RX gain to " << rx_gain << "dB";
+ usrp_dev->set_rx_gain(db, chan);
+ rx_gains[chan] = usrp_dev->get_rx_gain(chan);
- return rx_gain;
+ LOG(INFO) << "Set RX gain to " << rx_gains[chan] << "dB";
+
+ return rx_gains[chan];
+}
+
+double uhd_device::getRxGain(size_t chan)
+{
+ if (chan >= rx_gains.size()) {
+ LOG(ALERT) << "Requested non-existent channel " << chan;
+ return 0.0f;
+ }
+
+ return rx_gains[chan];
}
/*
@@ -533,11 +559,30 @@ int uhd_device::open(const std::string &args, bool extref)
if (!parse_dev_type())
return -1;
+ // Verify and set channels
+ 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);
+ } else if (chans != 1) {
+ LOG(ALERT) << "Invalid channel combination for device";
+ return -1;
+ }
+
+ tx_freqs.resize(chans);
+ rx_freqs.resize(chans);
+ tx_gains.resize(chans);
+ rx_gains.resize(chans);
+ rx_buffers.resize(chans);
+
if (extref)
usrp_dev->set_clock_source("external");
// Create TX and RX streamers
uhd::stream_args_t stream_args("sc16");
+ for (size_t i = 0; i < chans; i++)
+ stream_args.channels.push_back(i);
+
tx_stream = usrp_dev->get_tx_stream(stream_args);
rx_stream = usrp_dev->get_rx_stream(stream_args);
@@ -553,7 +598,8 @@ int uhd_device::open(const std::string &args, bool extref)
// Create receive buffer
size_t buf_len = SAMPLE_BUF_SZ / sizeof(uint32_t);
- rx_smpl_buf = new smpl_buf(buf_len, rx_rate);
+ for (size_t i = 0; i < rx_buffers.size(); i++)
+ rx_buffers[i] = new smpl_buf(buf_len, rx_rate);
// Set receive chain sample offset
double offset = get_dev_offset(dev_type, sps);
@@ -608,16 +654,13 @@ bool uhd_device::flush_recv(size_t num_pkts)
void uhd_device::restart(uhd::time_spec_t ts)
{
- uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
- usrp_dev->issue_stream_cmd(cmd);
-
- flush_recv(50);
-
usrp_dev->set_time_now(ts);
aligned = false;
- cmd = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
- cmd.stream_now = true;
+ uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
+ cmd.time_spec = uhd::time_spec_t(0.1);
+ cmd.stream_now = false;
+
usrp_dev->issue_stream_cmd(cmd);
}
@@ -707,16 +750,17 @@ int uhd_device::check_rx_md_err(uhd::rx_metadata_t &md, ssize_t num_smpls)
return 0;
}
-int uhd_device::readSamples(short *buf, int len, bool *overrun,
- TIMESTAMP timestamp, bool *underrun, unsigned *RSSI)
+int uhd_device::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
+ TIMESTAMP timestamp, bool *underrun, unsigned *RSSI)
{
ssize_t rc;
uhd::time_spec_t ts;
uhd::rx_metadata_t metadata;
- uint32_t pkt_buf[rx_spp];
- if (skip_rx)
- return 0;
+ if (bufs.size() != chans) {
+ LOG(ALERT) << "Invalid channel combination " << bufs.size();
+ return -1;
+ }
*overrun = false;
*underrun = false;
@@ -728,21 +772,25 @@ int uhd_device::readSamples(short *buf, int len, bool *overrun,
LOG(DEBUG) << "Requested timestamp = " << ts.get_real_secs();
// Check that timestamp is valid
- rc = rx_smpl_buf->avail_smpls(timestamp);
+ rc = rx_buffers[0]->avail_smpls(timestamp);
if (rc < 0) {
- LOG(ERR) << rx_smpl_buf->str_code(rc);
- LOG(ERR) << rx_smpl_buf->str_status();
+ LOG(ERR) << rx_buffers[0]->str_code(rc);
+ LOG(ERR) << rx_buffers[0]->str_status();
return 0;
}
+ // Create vector buffer
+ std::vector<std::vector<short> >
+ pkt_bufs(chans, std::vector<short>(2 * rx_spp));
+
+ std::vector<short *> pkt_ptrs;
+ for (size_t i = 0; i < pkt_bufs.size(); i++)
+ pkt_ptrs.push_back(&pkt_bufs[i].front());
+
// Receive samples from the usrp until we have enough
- while (rx_smpl_buf->avail_smpls(timestamp) < len) {
- size_t num_smpls = rx_stream->recv(
- (void*)pkt_buf,
- rx_spp,
- metadata,
- 0.1,
- true);
+ while (rx_buffers[0]->avail_smpls(timestamp) < len) {
+ size_t num_smpls = rx_stream->recv(pkt_ptrs, rx_spp,
+ metadata, 0.1, true);
rx_pkt_cnt++;
// Check for errors
@@ -758,36 +806,39 @@ int uhd_device::readSamples(short *buf, int len, bool *overrun,
continue;
}
-
ts = metadata.time_spec;
LOG(DEBUG) << "Received timestamp = " << ts.get_real_secs();
- rc = rx_smpl_buf->write(pkt_buf,
- num_smpls,
- metadata.time_spec);
-
- // Continue on local overrun, exit on other errors
- if ((rc < 0)) {
- LOG(ERR) << rx_smpl_buf->str_code(rc);
- LOG(ERR) << rx_smpl_buf->str_status();
- if (rc != smpl_buf::ERROR_OVERFLOW)
- return 0;
+ for (size_t i = 0; i < rx_buffers.size(); i++) {
+ rc = rx_buffers[i]->write((short *) &pkt_bufs[i].front(),
+ num_smpls,
+ metadata.time_spec);
+
+ // Continue on local overrun, exit on other errors
+ if ((rc < 0)) {
+ LOG(ERR) << rx_buffers[i]->str_code(rc);
+ LOG(ERR) << rx_buffers[i]->str_status();
+ if (rc != smpl_buf::ERROR_OVERFLOW)
+ return 0;
+ }
}
}
// We have enough samples
- rc = rx_smpl_buf->read(buf, len, timestamp);
- if ((rc < 0) || (rc != len)) {
- LOG(ERR) << rx_smpl_buf->str_code(rc);
- LOG(ERR) << rx_smpl_buf->str_status();
- return 0;
+ for (size_t i = 0; i < rx_buffers.size(); i++) {
+ rc = rx_buffers[i]->read(bufs[i], len, timestamp);
+ if ((rc < 0) || (rc != len)) {
+ LOG(ERR) << rx_buffers[i]->str_code(rc);
+ LOG(ERR) << rx_buffers[i]->str_status();
+ return 0;
+ }
}
return len;
}
-int uhd_device::writeSamples(short *buf, int len, bool *underrun,
- unsigned long long timestamp,bool isControl)
+int uhd_device::writeSamples(std::vector<short *> &bufs, int len, bool *underrun,
+ unsigned long long timestamp,bool isControl)
{
uhd::tx_metadata_t metadata;
metadata.has_time_spec = true;
@@ -803,6 +854,11 @@ int uhd_device::writeSamples(short *buf, int len, bool *underrun,
return 0;
}
+ if (bufs.size() != chans) {
+ LOG(ALERT) << "Invalid channel combination " << bufs.size();
+ return -1;
+ }
+
// Drop a fixed number of packets (magic value)
if (!aligned) {
drop_cnt++;
@@ -822,8 +878,7 @@ int uhd_device::writeSamples(short *buf, int len, bool *underrun,
}
}
- size_t num_smpls = tx_stream->send(buf, len, metadata);
-
+ size_t num_smpls = tx_stream->send(bufs, len, metadata);
if (num_smpls != (unsigned) len) {
LOG(ALERT) << "UHD: Device send timed out";
LOG(ALERT) << "UHD: Version " << uhd::get_version_string();
@@ -839,24 +894,54 @@ bool uhd_device::updateAlignment(TIMESTAMP timestamp)
return true;
}
-bool uhd_device::setTxFreq(double wFreq)
+bool uhd_device::setTxFreq(double wFreq, size_t chan)
{
- uhd::tune_result_t tr = usrp_dev->set_tx_freq(wFreq);
+ if (chan >= tx_freqs.size()) {
+ LOG(ALERT) << "Requested non-existent channel " << chan;
+ return false;
+ }
+
+ uhd::tune_result_t tr = usrp_dev->set_tx_freq(wFreq, chan);
LOG(INFO) << "\n" << tr.to_pp_string();
- tx_freq = usrp_dev->get_tx_freq();
+ tx_freqs[chan] = usrp_dev->get_tx_freq(chan);
return true;
}
-bool uhd_device::setRxFreq(double wFreq)
+bool uhd_device::setRxFreq(double wFreq, size_t chan)
{
- uhd::tune_result_t tr = usrp_dev->set_rx_freq(wFreq);
+ if (chan >= rx_freqs.size()) {
+ LOG(ALERT) << "Requested non-existent channel " << chan;
+ return false;
+ }
+
+ uhd::tune_result_t tr = usrp_dev->set_rx_freq(wFreq, chan);
LOG(INFO) << "\n" << tr.to_pp_string();
- rx_freq = usrp_dev->get_rx_freq();
+ rx_freqs[chan] = usrp_dev->get_rx_freq(chan);
return true;
}
+double uhd_device::getTxFreq(size_t chan)
+{
+ if (chan >= tx_freqs.size()) {
+ LOG(ALERT) << "Requested non-existent channel " << chan;
+ return 0.0;
+ }
+
+ return tx_freqs[chan];
+}
+
+double uhd_device::getRxFreq(size_t chan)
+{
+ if (chan >= rx_freqs.size()) {
+ LOG(ALERT) << "Requested non-existent channel " << chan;
+ return 0.0;
+ }
+
+ return rx_freqs[chan];
+}
+
bool uhd_device::recv_async_msg()
{
uhd::async_metadata_t md;
@@ -1085,7 +1170,7 @@ std::string smpl_buf::str_code(ssize_t code)
}
}
-RadioDevice *RadioDevice::make(int sps, bool skip_rx)
+RadioDevice *RadioDevice::make(size_t sps, size_t chans)
{
- return new uhd_device(sps, skip_rx);
+ return new uhd_device(sps, chans);
}