Add support to set Rx/TxAntenna
Change-Id: I1735e6ab05a05b0312d6d679b16ebd4a2260fa23
This commit is contained in:
parent
99eb07e232
commit
ddbbc8ccbd
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Device support for Ettus Research UHD driver
|
||||
* Device support for Ettus Research UHD driver
|
||||
*
|
||||
* Copyright 2010,2011 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2015 Ettus Research LLC
|
||||
|
@ -143,8 +143,8 @@ class smpl_buf {
|
|||
public:
|
||||
/** Sample buffer constructor
|
||||
@param len number of 32-bit samples the buffer should hold
|
||||
@param rate sample clockrate
|
||||
@param timestamp
|
||||
@param rate sample clockrate
|
||||
@param timestamp
|
||||
*/
|
||||
smpl_buf(size_t len, double rate);
|
||||
~smpl_buf();
|
||||
|
@ -172,7 +172,7 @@ public:
|
|||
*/
|
||||
std::string str_status(size_t ts) const;
|
||||
|
||||
/** Formatted error string
|
||||
/** Formatted error string
|
||||
@param code an error code
|
||||
@return a formatted error string
|
||||
*/
|
||||
|
@ -208,7 +208,9 @@ private:
|
|||
class uhd_device : public RadioDevice {
|
||||
public:
|
||||
uhd_device(size_t tx_sps, size_t rx_sps, InterfaceType type,
|
||||
size_t chans, double offset);
|
||||
size_t chans, double offset,
|
||||
const std::vector<std::string>& tx_paths,
|
||||
const std::vector<std::string>& rx_paths);
|
||||
~uhd_device();
|
||||
|
||||
int open(const std::string &args, int ref, bool swap_channels);
|
||||
|
@ -248,6 +250,11 @@ public:
|
|||
double getRxFreq(size_t chan);
|
||||
double getRxFreq();
|
||||
|
||||
bool setRxAntenna(const std::string &ant, size_t chan);
|
||||
std::string getRxAntenna(size_t chan);
|
||||
bool setTxAntenna(const std::string &ant, size_t chan);
|
||||
std::string getTxAntenna(size_t chan);
|
||||
|
||||
inline double getSampleRate() { return tx_rate; }
|
||||
inline double numberRead() { return rx_pkt_cnt; }
|
||||
inline double numberWritten() { return 0; }
|
||||
|
@ -280,6 +287,7 @@ private:
|
|||
|
||||
std::vector<double> tx_gains, rx_gains;
|
||||
std::vector<double> tx_freqs, rx_freqs;
|
||||
std::vector<std::string> tx_paths, rx_paths;
|
||||
size_t tx_spp, rx_spp;
|
||||
|
||||
bool started;
|
||||
|
@ -295,6 +303,7 @@ private:
|
|||
void init_gains();
|
||||
void set_channels(bool swap);
|
||||
void set_rates();
|
||||
bool set_antennas();
|
||||
bool parse_dev_type();
|
||||
bool flush_recv(size_t num_pkts);
|
||||
int check_rx_md_err(uhd::rx_metadata_t &md, ssize_t num_smpls);
|
||||
|
@ -353,7 +362,9 @@ static void thread_enable_cancel(bool cancel)
|
|||
}
|
||||
|
||||
uhd_device::uhd_device(size_t tx_sps, size_t rx_sps,
|
||||
InterfaceType iface, size_t chans, double offset)
|
||||
InterfaceType iface, size_t chans, double offset,
|
||||
const std::vector<std::string>& tx_paths,
|
||||
const std::vector<std::string>& rx_paths)
|
||||
: 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),
|
||||
|
@ -365,6 +376,8 @@ uhd_device::uhd_device(size_t tx_sps, size_t rx_sps,
|
|||
this->chans = chans;
|
||||
this->offset = offset;
|
||||
this->iface = iface;
|
||||
this->tx_paths = tx_paths;
|
||||
this->rx_paths = rx_paths;
|
||||
}
|
||||
|
||||
uhd_device::~uhd_device()
|
||||
|
@ -441,6 +454,33 @@ void uhd_device::set_rates()
|
|||
LOG(INFO) << "Rates configured for " << desc.str;
|
||||
}
|
||||
|
||||
bool uhd_device::set_antennas()
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < tx_paths.size(); i++) {
|
||||
if (tx_paths[i] == "")
|
||||
continue;
|
||||
LOG(DEBUG) << "Configuring channel " << i << " with antenna " << tx_paths[i];
|
||||
if (!setTxAntenna(tx_paths[i], i)) {
|
||||
LOG(ALERT) << "Failed configuring channel " << i << " with antenna " << tx_paths[i];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < rx_paths.size(); i++) {
|
||||
if (rx_paths[i] == "")
|
||||
continue;
|
||||
LOG(DEBUG) << "Configuring channel " << i << " with antenna " << tx_paths[i];
|
||||
if (!setRxAntenna(rx_paths[i], i)) {
|
||||
LOG(ALERT) << "Failed configuring channel " << i << " with antenna " << rx_paths[i];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
LOG(INFO) << "Antennas configured successfully";
|
||||
return true;
|
||||
}
|
||||
|
||||
double uhd_device::setTxGain(double db, size_t chan)
|
||||
{
|
||||
if (iface == MULTI_ARFCN)
|
||||
|
@ -644,6 +684,11 @@ int uhd_device::open(const std::string &args, int ref, bool swap_channels)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!set_antennas()) {
|
||||
LOG(ALERT) << "UHD antenna setting failed";
|
||||
return -1;
|
||||
}
|
||||
|
||||
tx_freqs.resize(chans);
|
||||
rx_freqs.resize(chans);
|
||||
tx_gains.resize(chans);
|
||||
|
@ -705,7 +750,7 @@ int uhd_device::open(const std::string &args, int ref, bool swap_channels)
|
|||
for (size_t i = 0; i < rx_buffers.size(); i++)
|
||||
rx_buffers[i] = new smpl_buf(buf_len, rx_rate);
|
||||
|
||||
// Initialize and shadow gain values
|
||||
// Initialize and shadow gain values
|
||||
init_gains();
|
||||
|
||||
// Print configuration
|
||||
|
@ -926,7 +971,7 @@ int uhd_device::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
|
|||
|
||||
rx_pkt_cnt++;
|
||||
|
||||
// Check for errors
|
||||
// Check for errors
|
||||
rc = check_rx_md_err(metadata, num_smpls);
|
||||
switch (rc) {
|
||||
case ERROR_UNRECOVERABLE:
|
||||
|
@ -1165,6 +1210,72 @@ double uhd_device::getRxFreq(size_t chan)
|
|||
return rx_freqs[chan];
|
||||
}
|
||||
|
||||
bool uhd_device::setRxAntenna(const std::string &ant, size_t chan)
|
||||
{
|
||||
std::vector<std::string> avail;
|
||||
if (chan >= rx_paths.size()) {
|
||||
LOG(ALERT) << "Requested non-existent channel " << chan;
|
||||
return false;
|
||||
}
|
||||
|
||||
avail = usrp_dev->get_rx_antennas(chan);
|
||||
if (std::find(avail.begin(), avail.end(), ant) == avail.end()) {
|
||||
LOG(ALERT) << "Requested non-existent antenna " << ant << " on channel " << chan;
|
||||
return false;
|
||||
}
|
||||
usrp_dev->set_rx_antenna(ant, chan);
|
||||
rx_paths[chan] = usrp_dev->get_rx_antenna(chan);
|
||||
|
||||
if (ant != rx_paths[chan]) {
|
||||
LOG(ALERT) << "Failed setting antenna " << ant << " on channel " << chan << ", got instead " << rx_paths[chan];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string uhd_device::getRxAntenna(size_t chan)
|
||||
{
|
||||
if (chan >= rx_paths.size()) {
|
||||
LOG(ALERT) << "Requested non-existent channel " << chan;
|
||||
return "";
|
||||
}
|
||||
return usrp_dev->get_rx_antenna(chan);
|
||||
}
|
||||
|
||||
bool uhd_device::setTxAntenna(const std::string &ant, size_t chan)
|
||||
{
|
||||
std::vector<std::string> avail;
|
||||
if (chan >= tx_paths.size()) {
|
||||
LOG(ALERT) << "Requested non-existent channel " << chan;
|
||||
return false;
|
||||
}
|
||||
|
||||
avail = usrp_dev->get_tx_antennas(chan);
|
||||
if (std::find(avail.begin(), avail.end(), ant) == avail.end()) {
|
||||
LOG(ALERT) << "Requested non-existent antenna " << ant << " on channel " << chan;
|
||||
return false;
|
||||
}
|
||||
usrp_dev->set_tx_antenna(ant, chan);
|
||||
tx_paths[chan] = usrp_dev->get_tx_antenna(chan);
|
||||
|
||||
if (ant != tx_paths[chan]) {
|
||||
LOG(ALERT) << "Failed setting antenna " << ant << " on channel " << chan << ", got instead " << tx_paths[chan];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string uhd_device::getTxAntenna(size_t chan)
|
||||
{
|
||||
if (chan >= tx_paths.size()) {
|
||||
LOG(ALERT) << "Requested non-existent channel " << chan;
|
||||
return "";
|
||||
}
|
||||
return usrp_dev->get_tx_antenna(chan);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only allow sampling the Rx path lower than Tx and not vice-versa.
|
||||
* Using Tx with 4 SPS and Rx at 1 SPS is the only allowed mixed
|
||||
|
@ -1451,7 +1562,9 @@ std::string smpl_buf::str_code(ssize_t code)
|
|||
}
|
||||
|
||||
RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps,
|
||||
InterfaceType iface, size_t chans, double offset)
|
||||
InterfaceType iface, size_t chans, double offset,
|
||||
const std::vector<std::string>& tx_paths,
|
||||
const std::vector<std::string>& rx_paths)
|
||||
{
|
||||
return new uhd_device(tx_sps, rx_sps, iface, chans, offset);
|
||||
return new uhd_device(tx_sps, rx_sps, iface, chans, offset, tx_paths, rx_paths);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
Compilation Flags
|
||||
|
||||
SWLOOPBACK compile for software loopback testing
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
@ -80,7 +80,7 @@ USRPDevice::USRPDevice(size_t sps)
|
|||
else
|
||||
pingOffset = 0;
|
||||
|
||||
#ifdef SWLOOPBACK
|
||||
#ifdef SWLOOPBACK
|
||||
samplePeriod = 1.0e6/actualSampleRate;
|
||||
loopbackBufferSize = 0;
|
||||
gettimeofday(&lastReadTime,NULL);
|
||||
|
@ -93,9 +93,9 @@ int USRPDevice::open(const std::string &, int, bool)
|
|||
writeLock.unlock();
|
||||
|
||||
LOG(INFO) << "opening USRP device..";
|
||||
#ifndef SWLOOPBACK
|
||||
#ifndef SWLOOPBACK
|
||||
string rbf = "std_inband.rbf";
|
||||
//string rbf = "inband_1rxhb_1tx.rbf";
|
||||
//string rbf = "inband_1rxhb_1tx.rbf";
|
||||
m_uRx.reset();
|
||||
if (!skipRx) {
|
||||
try {
|
||||
|
@ -144,7 +144,7 @@ int USRPDevice::open(const std::string &, int, bool)
|
|||
|
||||
if (!skipRx) m_uRx->stop();
|
||||
m_uTx->stop();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
switch (dboardConfig) {
|
||||
|
@ -175,19 +175,19 @@ int USRPDevice::open(const std::string &, int, bool)
|
|||
samplesRead = 0;
|
||||
samplesWritten = 0;
|
||||
started = false;
|
||||
|
||||
|
||||
return NORMAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool USRPDevice::start()
|
||||
bool USRPDevice::start()
|
||||
{
|
||||
LOG(INFO) << "starting USRP...";
|
||||
#ifndef SWLOOPBACK
|
||||
#ifndef SWLOOPBACK
|
||||
if (!m_uRx && !skipRx) return false;
|
||||
if (!m_uTx) return false;
|
||||
|
||||
|
||||
if (!skipRx) m_uRx->stop();
|
||||
m_uTx->stop();
|
||||
|
||||
|
@ -217,8 +217,8 @@ bool USRPDevice::start()
|
|||
hi32Timestamp = 0;
|
||||
isAligned = false;
|
||||
|
||||
|
||||
if (!skipRx)
|
||||
|
||||
if (!skipRx)
|
||||
started = (m_uRx->start() && m_uTx->start());
|
||||
else
|
||||
started = m_uTx->start();
|
||||
|
@ -229,14 +229,14 @@ bool USRPDevice::start()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool USRPDevice::stop()
|
||||
bool USRPDevice::stop()
|
||||
{
|
||||
#ifndef SWLOOPBACK
|
||||
#ifndef SWLOOPBACK
|
||||
if (!m_uRx) return false;
|
||||
if (!m_uTx) return false;
|
||||
|
||||
|
||||
delete[] currData;
|
||||
|
||||
|
||||
started = !(m_uRx->stop() && m_uTx->stop());
|
||||
return !started;
|
||||
#else
|
||||
|
@ -257,7 +257,7 @@ double USRPDevice::minTxGain()
|
|||
double USRPDevice::maxRxGain()
|
||||
{
|
||||
return m_dbRx->gain_max();
|
||||
}
|
||||
}
|
||||
|
||||
double USRPDevice::minRxGain()
|
||||
{
|
||||
|
@ -313,28 +313,68 @@ double USRPDevice::setRxGain(double dB, size_t chan)
|
|||
return dB;
|
||||
}
|
||||
|
||||
bool USRPDevice::setRxAntenna(const std::string &ant, size_t chan)
|
||||
{
|
||||
if (chan >= rx_paths.size()) {
|
||||
LOG(ALERT) << "Requested non-existent channel " << chan;
|
||||
return false;
|
||||
}
|
||||
LOG(ALERT) << "Not implemented";
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string USRPDevice::getRxAntenna(size_t chan)
|
||||
{
|
||||
if (chan >= rx_paths.size()) {
|
||||
LOG(ALERT) << "Requested non-existent channel " << chan;
|
||||
return "";
|
||||
}
|
||||
LOG(ALERT) << "Not implemented";
|
||||
return "";
|
||||
}
|
||||
|
||||
bool USRPDevice::setTxAntenna(const std::string &ant, size_t chan)
|
||||
{
|
||||
if (chan >= tx_paths.size()) {
|
||||
LOG(ALERT) << "Requested non-existent channel " << chan;
|
||||
return false;
|
||||
}
|
||||
LOG(ALERT) << "Not implemented";
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string USRPDevice::getTxAntenna(size_t chan)
|
||||
{
|
||||
if (chan >= tx_paths.size()) {
|
||||
LOG(ALERT) << "Requested non-existent channel " << chan;
|
||||
return "";
|
||||
}
|
||||
LOG(ALERT) << "Not implemented";
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Assumes sequential reads
|
||||
int USRPDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
|
||||
TIMESTAMP timestamp, bool *underrun, unsigned *RSSI)
|
||||
{
|
||||
#ifndef SWLOOPBACK
|
||||
#ifndef SWLOOPBACK
|
||||
if (!m_uRx)
|
||||
return 0;
|
||||
|
||||
short *buf = bufs[0];
|
||||
|
||||
timestamp += timestampOffset;
|
||||
|
||||
|
||||
if (timestamp + len < timeStart) {
|
||||
memset(buf,0,len*2*sizeof(short));
|
||||
return len;
|
||||
}
|
||||
|
||||
if (underrun) *underrun = false;
|
||||
|
||||
|
||||
uint32_t readBuf[2000];
|
||||
|
||||
|
||||
while (1) {
|
||||
//guestimate USB read size
|
||||
int readLen=0;
|
||||
|
@ -344,7 +384,7 @@ int USRPDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
|
|||
readLen = 512 * ((int) ceil((float) numSamplesNeeded/126.0));
|
||||
if (readLen > 8000) readLen= (8000/512)*512;
|
||||
}
|
||||
|
||||
|
||||
// read USRP packets, parse and save A/D data as needed
|
||||
readLen = m_uRx->read((void *)readBuf,readLen,overrun);
|
||||
for(int pktNum = 0; pktNum < (readLen/512); pktNum++) {
|
||||
|
@ -381,13 +421,13 @@ int USRPDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
|
|||
continue;
|
||||
}
|
||||
if ((word0 >> 28) & 0x04) {
|
||||
if (underrun) *underrun = true;
|
||||
if (underrun) *underrun = true;
|
||||
LOG(DEBUG) << "UNDERRUN in TRX->USRP interface";
|
||||
}
|
||||
if (RSSI) *RSSI = (word0 >> 21) & 0x3f;
|
||||
|
||||
|
||||
if (!isAligned) continue;
|
||||
|
||||
|
||||
unsigned cursorStart = pktTimestamp - timeStart + dataStart;
|
||||
while (cursorStart*2 > currDataSize) {
|
||||
cursorStart -= currDataSize/2;
|
||||
|
@ -400,17 +440,17 @@ int USRPDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
|
|||
else {
|
||||
memcpy(data+cursorStart*2,tmpBuf+2,payloadSz);
|
||||
}
|
||||
if (pktTimestamp + payloadSz/2/sizeof(short) > timeEnd)
|
||||
if (pktTimestamp + payloadSz/2/sizeof(short) > timeEnd)
|
||||
timeEnd = pktTimestamp+payloadSz/2/sizeof(short);
|
||||
|
||||
LOG(DEBUG) << "timeStart: " << timeStart << ", timeEnd: " << timeEnd << ", pktTimestamp: " << pktTimestamp;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// copy desired data to buf
|
||||
unsigned bufStart = dataStart+(timestamp-timeStart);
|
||||
if (bufStart + len < currDataSize/2) {
|
||||
if (bufStart + len < currDataSize/2) {
|
||||
LOG(DEBUG) << "bufStart: " << bufStart;
|
||||
memcpy(buf,data+bufStart*2,len*2*sizeof(short));
|
||||
memset(data+bufStart*2,0,len*2*sizeof(short));
|
||||
|
@ -428,21 +468,21 @@ int USRPDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
|
|||
timeStart = timestamp + len;
|
||||
|
||||
return len;
|
||||
|
||||
|
||||
#else
|
||||
if (loopbackBufferSize < 2) return 0;
|
||||
int numSamples = 0;
|
||||
struct timeval currTime;
|
||||
gettimeofday(&currTime,NULL);
|
||||
double timeElapsed = (currTime.tv_sec - lastReadTime.tv_sec)*1.0e6 +
|
||||
double timeElapsed = (currTime.tv_sec - lastReadTime.tv_sec)*1.0e6 +
|
||||
(currTime.tv_usec - lastReadTime.tv_usec);
|
||||
if (timeElapsed < samplePeriod) {return 0;}
|
||||
int numSamplesToRead = (int) floor(timeElapsed/samplePeriod);
|
||||
if (numSamplesToRead < len) return 0;
|
||||
|
||||
|
||||
if (numSamplesToRead > len) numSamplesToRead = len;
|
||||
if (numSamplesToRead > loopbackBufferSize/2) {
|
||||
firstRead =false;
|
||||
firstRead =false;
|
||||
numSamplesToRead = loopbackBufferSize/2;
|
||||
}
|
||||
memcpy(buf,loopbackBuffer,sizeof(short)*2*numSamplesToRead);
|
||||
|
@ -460,7 +500,7 @@ int USRPDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
|
|||
firstRead = true;
|
||||
}
|
||||
samplesRead += numSamples;
|
||||
|
||||
|
||||
return numSamples;
|
||||
#endif
|
||||
}
|
||||
|
@ -471,7 +511,7 @@ int USRPDevice::writeSamples(std::vector<short *> &bufs, int len,
|
|||
{
|
||||
writeLock.lock();
|
||||
|
||||
#ifndef SWLOOPBACK
|
||||
#ifndef SWLOOPBACK
|
||||
if (!m_uTx)
|
||||
return 0;
|
||||
|
||||
|
@ -518,14 +558,14 @@ int USRPDevice::writeSamples(std::vector<short *> &bufs, int len,
|
|||
memcpy(loopbackBuffer+loopbackBufferSize,buf,sizeof(short)*2*len);
|
||||
samplesWritten += retVal;
|
||||
loopbackBufferSize += retVal*2;
|
||||
|
||||
|
||||
return retVal;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool USRPDevice::updateAlignment(TIMESTAMP timestamp)
|
||||
bool USRPDevice::updateAlignment(TIMESTAMP timestamp)
|
||||
{
|
||||
#ifndef SWLOOPBACK
|
||||
#ifndef SWLOOPBACK
|
||||
short data[] = {0x00,0x02,0x00,0x00};
|
||||
uint32_t *wordPtr = (uint32_t *) data;
|
||||
*wordPtr = host_to_usrp_u32(*wordPtr);
|
||||
|
@ -542,7 +582,7 @@ bool USRPDevice::updateAlignment(TIMESTAMP timestamp)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef SWLOOPBACK
|
||||
#ifndef SWLOOPBACK
|
||||
bool USRPDevice::setTxFreq(double wFreq, size_t chan)
|
||||
{
|
||||
usrp_tune_result result;
|
||||
|
@ -600,7 +640,9 @@ bool USRPDevice::setRxFreq(double wFreq) { return true;};
|
|||
#endif
|
||||
|
||||
RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps,
|
||||
RadioDevice::InterfaceType, size_t chans, double)
|
||||
InterfaceType iface, size_t chans, double offset,
|
||||
const std::vector<std::string>& tx_paths,
|
||||
const std::vector<std::string>& rx_paths)
|
||||
{
|
||||
return new USRPDevice(tx_sps);
|
||||
}
|
||||
|
|
|
@ -83,10 +83,10 @@ private:
|
|||
|
||||
double rxGain;
|
||||
|
||||
#ifdef SWLOOPBACK
|
||||
#ifdef SWLOOPBACK
|
||||
short loopbackBuffer[1000000];
|
||||
int loopbackBufferSize;
|
||||
double samplePeriod;
|
||||
double samplePeriod;
|
||||
|
||||
struct timeval startTime;
|
||||
struct timeval lastReadTime;
|
||||
|
@ -179,6 +179,18 @@ private:
|
|||
/** return minimum Rx Gain **/
|
||||
double minTxGain(void);
|
||||
|
||||
/** sets the RX path to use, returns true if successful and false otherwise */
|
||||
bool setRxAntenna(const std::string &ant, size_t chan = 0);
|
||||
|
||||
/* return the used RX path */
|
||||
std::string getRxAntenna(size_t chan = 0);
|
||||
|
||||
/** sets the RX path to use, returns true if successful and false otherwise */
|
||||
bool setTxAntenna(const std::string &ant, size_t chan = 0);
|
||||
|
||||
/* return the used RX path */
|
||||
std::string getTxAntenna(size_t chan = 0);
|
||||
|
||||
/** Return internal status values */
|
||||
inline double getTxFreq(size_t chan = 0) { return 0; }
|
||||
inline double getRxFreq(size_t chan = 0) { return 0; }
|
||||
|
@ -189,4 +201,3 @@ private:
|
|||
};
|
||||
|
||||
#endif // _USRP_DEVICE_H_
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <GSMCommon.h>
|
||||
#include <Logger.h>
|
||||
|
@ -79,6 +83,8 @@ struct trx_config {
|
|||
bool swap_channels;
|
||||
bool edge;
|
||||
int sched_rr;
|
||||
std::vector<std::string> rx_paths;
|
||||
std::vector<std::string> tx_paths;
|
||||
};
|
||||
|
||||
volatile bool gshutdown = false;
|
||||
|
@ -241,6 +247,21 @@ static void setup_signal_handlers()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static std::vector<std::string> comma_delimited_to_vector(char* opt) {
|
||||
std::string str = std::string(opt);
|
||||
std::vector<std::string> result;
|
||||
std::stringstream ss(str);
|
||||
|
||||
while( ss.good() )
|
||||
{
|
||||
std::string substr;
|
||||
getline(ss, substr, ',');
|
||||
result.push_back(substr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void print_help()
|
||||
{
|
||||
fprintf(stdout, "Options:\n"
|
||||
|
@ -263,7 +284,9 @@ static void print_help()
|
|||
" -A Random Access Burst test mode with delay\n"
|
||||
" -R RSSI to dBm offset in dB (default=0)\n"
|
||||
" -S Swap channels (UmTRX only)\n"
|
||||
" -t SCHED_RR real-time priority (1..32)\n",
|
||||
" -t SCHED_RR real-time priority (1..32)\n"
|
||||
" -y comma-delimited list of Tx paths (num elements matches -c)\n"
|
||||
" -z comma-delimited list of Rx paths (num elements matches -c)\n",
|
||||
"EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
|
||||
}
|
||||
|
||||
|
@ -289,8 +312,10 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
|
|||
config->swap_channels = false;
|
||||
config->edge = false;
|
||||
config->sched_rr = -1;
|
||||
config->tx_paths = std::vector<std::string>(DEFAULT_CHANS, "");
|
||||
config->rx_paths = std::vector<std::string>(DEFAULT_CHANS, "");
|
||||
|
||||
while ((option = getopt(argc, argv, "ha:l:i:j:p:c:dmxgfo:s:b:r:A:R:Set:")) != -1) {
|
||||
while ((option = getopt(argc, argv, "ha:l:i:j:p:c:dmxgfo:s:b:r:A:R:Set:y:z:")) != -1) {
|
||||
switch (option) {
|
||||
case 'h':
|
||||
print_help();
|
||||
|
@ -355,6 +380,11 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
|
|||
case 't':
|
||||
config->sched_rr = atoi(optarg);
|
||||
break;
|
||||
case 'y':
|
||||
config->tx_paths = comma_delimited_to_vector(optarg);
|
||||
case 'z':
|
||||
config->rx_paths = comma_delimited_to_vector(optarg);
|
||||
break;
|
||||
default:
|
||||
print_help();
|
||||
exit(0);
|
||||
|
@ -391,6 +421,12 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
|
|||
goto bad_config;
|
||||
}
|
||||
|
||||
if(config->tx_paths.size() != config->chans ||
|
||||
config->rx_paths.size() != config->chans) {
|
||||
printf("Num of channels and num of tx/rx_paths doesn't match\n\n");
|
||||
goto bad_config;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
bad_config:
|
||||
|
@ -480,7 +516,7 @@ int main(int argc, char *argv[])
|
|||
ref = RadioDevice::REF_INTERNAL;
|
||||
|
||||
usrp = RadioDevice::make(config.tx_sps, config.rx_sps, iface,
|
||||
config.chans, config.offset);
|
||||
config.chans, config.offset, config.tx_paths, config.rx_paths);
|
||||
type = usrp->open(config.dev_args, ref, config.swap_channels);
|
||||
if (type < 0) {
|
||||
LOG(ALERT) << "Failed to create radio device" << std::endl;
|
||||
|
|
|
@ -50,7 +50,9 @@ class RadioDevice {
|
|||
};
|
||||
|
||||
static RadioDevice *make(size_t tx_sps, size_t rx_sps, InterfaceType type,
|
||||
size_t chans = 1, double offset = 0.0);
|
||||
size_t chans = 1, double offset = 0.0,
|
||||
const std::vector<std::string>& tx_paths = std::vector<std::string>(1, ""),
|
||||
const std::vector<std::string>& rx_paths = std::vector<std::string>(1, ""));
|
||||
|
||||
/** Initialize the USRP */
|
||||
virtual int open(const std::string &args, int ref, bool swap_channels)=0;
|
||||
|
@ -136,6 +138,18 @@ class RadioDevice {
|
|||
/** return minimum Tx Gain **/
|
||||
virtual double minTxGain(void) = 0;
|
||||
|
||||
/** sets the RX path to use, returns true if successful and false otherwise */
|
||||
virtual bool setRxAntenna(const std::string &ant, size_t chan = 0) = 0;
|
||||
|
||||
/* return the used RX path */
|
||||
virtual std::string getRxAntenna(size_t chan = 0) = 0;
|
||||
|
||||
/** sets the RX path to use, returns true if successful and false otherwise */
|
||||
virtual bool setTxAntenna(const std::string &ant, size_t chan = 0) = 0;
|
||||
|
||||
/* return the used RX path */
|
||||
virtual std::string getTxAntenna(size_t chan = 0) = 0;
|
||||
|
||||
/** Return internal status values */
|
||||
virtual double getTxFreq(size_t chan = 0) = 0;
|
||||
virtual double getRxFreq(size_t chan = 0) = 0;
|
||||
|
|
Loading…
Reference in New Issue