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]

Reply via email to