Hi all,
we use a X410 and send 60k samples via localhost. We increase the frequency
within the frame every 6k samples. We observe a frequency selectivity of the
USRP. Can you help us on that? In the attachment [0], you can find the MWE (we
tried to keep it as small as possible). Let us explain the problem in the
following plot:
[cid:8da814dd-5c1c-40b6-b1c3-5b63bbe2ae97]
In the left column, you can find the transmitted signal, in the right column
the received signal. In the lower row, you see the spectrogram. One can clearly
see that the signal gets attenuated, depending on the frequency. One would
expect the amplitude to remain constant.
The transmitted signal changes every 6k signal its frequency. Within these 6k
samples, we simply send complex exponentials. The frequencies are: [-25, -19.44
-13.9, -8.3, - 2.78 2.78 8.3 13.9, 19.4 25].
Rf config:
```cpp
const double FS = 50e6;
Config conf;
conf.txAnalogFilterBw = 400e6;
conf.rxAnalogFilterBw = 400e6;
conf.txGain = 35;
conf.rxGain = 35;
conf.txCarrierFrequency = 2e9;
conf.rxCarrierFrequency = 2e9;
conf.txSamplingRate = FS;
conf.rxSamplingRate = FS;
```
For different RfConfigs, the results are less distinct.
Kind regards,
Tobias
Attachments:
[0]: usrp_mwe.cpp
Barkhausen Institut
www.barkhauseninstitut.org
Barkhausen Institut gGmbH | Sitz: Würzburger Straße 46, 01187 Dresden, Germany
| Registergericht: Amtsgericht Dresden, HRB 37267 | Geschäftsführer: Prof. Dr.
Gerhard Fettweis, Dr. Tim Hentschel | Vorsitzender der
Gesellschafterdelegation: Dr. Andreas Handschuh
Hinweise zum Datenschutz und zur Verarbeitung Ihrer Daten finden Sie unter:
https://barkhauseninstitut.org/data-privacy
This email and any attachments are intended only for the person to whom this
email is addressed and may contain confidential and/or privileged information.
If you received this email in error, please do not disclose the contents to
anyone, but notify the sender by return email and delete this email (and any
attachments) from your system. Information on data protection and processing of
your personal information: https://barkhauseninstitut.org/data-privacy
#include <chrono>
#include <complex>
#include <fstream>
#include <thread>
#include <vector>
#include "uhd/usrp/multi_usrp.hpp"
typedef std::complex<float> sample;
typedef std::vector<sample> samples_vec;
using namespace std::chrono;
const size_t SPB = 2e3;
const size_t NO_SAMPLES = 60e3;
const size_t NO_PACKAGES = NO_SAMPLES / SPB;
const double PI = std::acos(-1);
const std::complex<double> J = sample(0, 1);
double SEND_TIME = 4.f;
struct Config {
float txSamplingRate, rxSamplingRate;
float txCarrierFrequency, rxCarrierFrequency;
float txAnalogFilterBw, rxAnalogFilterBw;
float txGain, rxGain;
};
std::ofstream createCsv(const std::string &filename) {
std::cout << "Storing samples to " << filename << std::endl;
std::ofstream csvStream(filename);
csvStream << "real,imag" << std::endl;
return csvStream;
}
void dumpSamples(const std::vector<samples_vec> &samples,
std::ofstream &stream) {
const samples_vec &samplesFirstChannel = samples[0];
for (size_t sampleIdx = 0; sampleIdx < NO_SAMPLES; sampleIdx++) {
const std::complex<float> &sample = samplesFirstChannel[sampleIdx];
stream << sample.real() << "," << sample.imag() << std::endl;
}
}
std::vector<samples_vec> createWaveform(const int noSignals,
const double fStart, const double fStop,
const double fSampling) {
std::vector<samples_vec> samples;
samples_vec samplesFirstChannel(NO_SAMPLES, sample(0, 0));
double stepSize = (fStop - fStart) / (noSignals - 1);
int zohLength = NO_SAMPLES / noSignals;
int fIdx = 0;
double f = 0;
double t = 0;
for (size_t sampleIdx = 0; sampleIdx < NO_SAMPLES; sampleIdx++) {
if (sampleIdx > 0 && sampleIdx % zohLength == 0) fIdx++;
f = fStart + fIdx * stepSize;
t = sampleIdx / fSampling;
samplesFirstChannel[sampleIdx] = std::exp(J * 2.0 * PI * f * t);
}
samples.emplace_back(samplesFirstChannel);
return samples;
}
void setRfConfig(const Config &conf, uhd::usrp::multi_usrp::sptr usrpDevice) {
// configure transmitter
usrpDevice->set_tx_rate(conf.txSamplingRate);
usrpDevice->set_tx_subdev_spec(uhd::usrp::subdev_spec_t("A:0"), 0);
uhd::tune_request_t txTuneRequest(conf.txCarrierFrequency);
usrpDevice->set_tx_freq(txTuneRequest, 0);
usrpDevice->set_tx_gain(conf.txGain, 0);
usrpDevice->set_tx_bandwidth(conf.txAnalogFilterBw, 0);
// configure receiver
usrpDevice->set_rx_rate(conf.rxSamplingRate);
usrpDevice->set_rx_subdev_spec(uhd::usrp::subdev_spec_t("A:0"), 0);
uhd::tune_request_t rxTuneRequest(conf.rxCarrierFrequency);
usrpDevice->set_rx_freq(rxTuneRequest, 0);
usrpDevice->set_rx_gain(conf.rxGain, 0);
usrpDevice->set_rx_bandwidth(conf.rxAnalogFilterBw, 0);
usrpDevice->set_sync_source("internal", "internal");
}
void setTimeToZeroNextPps(uhd::usrp::multi_usrp::sptr usrpDevice) {
usrpDevice->set_time_next_pps(uhd::time_spec_t(0.f));
// wait for next pps
const uhd::time_spec_t lastPpsTime = usrpDevice->get_time_last_pps();
while (lastPpsTime == usrpDevice->get_time_last_pps()) {
}
}
void receive(std::vector<samples_vec> &buffer,
uhd::rx_streamer::sptr rxStreamer) {
uhd::stream_cmd_t streamCmd =
uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE;
streamCmd.time_spec = uhd::time_spec_t(SEND_TIME);
streamCmd.num_samps = NO_SAMPLES;
streamCmd.stream_now = false;
rxStreamer->issue_stream_cmd(streamCmd);
uhd::rx_metadata_t mdRx;
double timeout = SEND_TIME;
for (size_t packageIdx = 0; packageIdx < NO_PACKAGES; packageIdx++) {
rxStreamer->recv({buffer[0].data() + packageIdx * SPB}, SPB, mdRx,
timeout);
timeout = 0.1f;
}
}
void transmit(uhd::tx_streamer::sptr txStreamer,
uhd::usrp::multi_usrp::sptr usrpDevice,
std::vector<samples_vec> &buffer) {
// specifiy on specifications of how to stream the command
uhd::tx_metadata_t mdTx;
mdTx.start_of_burst = true;
mdTx.end_of_burst = false;
mdTx.has_time_spec = true;
mdTx.time_spec = uhd::time_spec_t(SEND_TIME);
for (size_t packageIdx = 0; packageIdx < NO_PACKAGES; packageIdx++) {
txStreamer->send({buffer[0].data() + packageIdx * SPB}, SPB, mdTx,
0.1f);
mdTx.start_of_burst = false;
}
mdTx.end_of_burst = true;
txStreamer->send("", 0, mdTx);
std::this_thread::sleep_for(
std::chrono::seconds(static_cast<int>(SEND_TIME) + 2));
}
int main() {
const double FS = 50e6;
Config conf;
conf.txAnalogFilterBw = 400e6;
conf.rxAnalogFilterBw = 400e6;
conf.txGain = 35;
conf.rxGain = 35;
conf.txCarrierFrequency = 2e9;
conf.rxCarrierFrequency = 2e9;
conf.txSamplingRate = FS;
conf.rxSamplingRate = FS;
uhd::usrp::multi_usrp::sptr usrpDevice =
uhd::usrp::multi_usrp::make(uhd::device_addr_t("addr=localhost"));
setRfConfig(conf, usrpDevice);
// create streamer
uhd::stream_args_t txStreamArgs("fc32", "sc16");
txStreamArgs.channels = std::vector<size_t>({0});
auto txStreamer = usrpDevice->get_tx_stream(txStreamArgs);
uhd::stream_args_t rxStreamArgs("fc32", "sc16");
rxStreamArgs.channels = std::vector<size_t>({0});
auto rxStreamer = usrpDevice->get_rx_stream(rxStreamArgs);
// create buffers for signals
std::vector<samples_vec> transmittedSamples =
createWaveform(10, -FS / 2, FS / 2, FS);
std::vector<samples_vec> receivedSamples(
{samples_vec(NO_SAMPLES, sample(0, 0))});
setTimeToZeroNextPps(usrpDevice);
std::thread transmitThread(transmit, txStreamer, usrpDevice,
std::ref(transmittedSamples));
std::thread receiveThread(receive, std::ref(receivedSamples), rxStreamer);
transmitThread.join();
receiveThread.join();
std::ofstream rxCsvFile = createCsv("rxSamples.csv");
std::ofstream txCsvFile = createCsv("txSamples.csv");
dumpSamples(receivedSamples, rxCsvFile);
dumpSamples(transmittedSamples, txCsvFile);
}
_______________________________________________
USRP-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]