Hi Marcus,

Thank you for the reply. I am using SBX (40MHz)  daughterboards for X310.
For my software setting, I'm not sure what is the best way to present the
details. So I copied my code below. Hopeful it is not messy for you to
review.

Thanks,
Hua


============================================================

int main() {
    sdr_para sp;
    sp.is_usrp_enabled = true;
    sp.is_debg_enabled = false;

    sp.ip_addrs = "addr=192.168.10.2,type=x300,master_clock_rate=200e6";
    sp.chan_num = 2;
    sp.chan_str = "0,1";
    sp.sync_opt = "internal"; //"pps", "mimo"
    sp.cen_freq = 915e6;
    sp.sam_rate = 2e6;
    sp.tx_ant_name = "TX/RX";
    sp.rx_ant_name = "RX2";
    sp.analg_bw = sp.sam_rate;
    sp.tx_gain = 15;
    sp.rx_gain = 0;

    sdr = new sdr_dev(sp);

    // transmit
    sdr -> usrp_transmit(buf, num_samps);

    // receiver
    sdr -> usrp_receive(buf, num_samps);

}

void sdr_dev::configure_usrp(sdr_para sp) {

    is_usrp_enabled = sp.is_usrp_enabled;
    is_debg_enabled = sp.is_debg_enabled;

    ip_addrs = sp.ip_addrs; //
    chan_str = sp.chan_str; // specify "0", "1", "0,1", etc
    chan_num = sp.chan_num;
    sync_opt = sp.sync_opt; //"pps", "mimo", "default"

    cen_freq = sp.cen_freq;
    sam_rate = sp.sam_rate;

    analg_bw = sp.analg_bw;
    tx_gain = sp.tx_gain;
    rx_gain = sp.rx_gain;

    tx_ant_name = sp.tx_ant_name;
    rx_ant_name = sp.rx_ant_name;

    seconds_in_future = 1.0;

    //create a usrp device
    uhd::set_thread_priority_safe();
    usrp = uhd::usrp::multi_usrp::make(ip_addrs);
    //cout << boost::format("Using Device: %s") % usrp->get_pp_string() <<
endl;

    //always select the subdevice first, the channel mapping affects the
other settings
    // usrp->set_rx_subdev_spec(subdev); //sets across all mboards
    // usrp->set_tx_subdev_spec(subdev); //sets across all mboards

    // clock and time sync_opthronization
    if (sync_opt == "pps") {
        usrp -> set_clock_source("external");
        usrp -> set_time_source("external");
        usrp -> set_time_unknown_pps(uhd::time_spec_t(0.0));
        this_thread::sleep_for(chrono::seconds(1)); //wait for pps sync_opt
pulse
    } else if (sync_opt == "mimo") {
        cout << "MIMO cable" << endl;
        UHD_ASSERT_THROW(usrp -> get_num_mboards() == 2);
        //make mboard 1 a slave over the MIMO Cable
        usrp -> set_clock_source("mimo", 1);
        usrp -> set_time_source("mimo", 1);
        //set time on the master (mboard 0)
        usrp -> set_time_now(uhd::time_spec_t(0.0), 0);
        //sleep a bit while the slave locks its time to the master
        this_thread::sleep_for(chrono::milliseconds(500));
    } else {
        usrp -> set_time_now(uhd::time_spec_t(1.0));
    }

    //set the center frequency
    uhd::tune_request_t tune_request(cen_freq);
    tune_request.args = uhd::device_addr_t("mode_n=integer");
    for (int ch = 0; ch < chan_num; ch++) {
        usrp -> set_rx_freq(tune_request, ch);
        usrp -> set_tx_freq(tune_request, ch);
        cout << boost::format("Actual RX Freq: %f MHz...") % (usrp ->
get_rx_freq(ch) / 1e6) << endl;
        cout << boost::format("Actual TX Freq: %f MHz...") % (usrp ->
get_tx_freq(ch) / 1e6) << endl;

        //set the rx sample rate (sets across all channels)
        usrp -> set_rx_rate(sam_rate, ch);
        usrp -> set_tx_rate(sam_rate, ch);
        cout << boost::format("Actual RX Rate: %f Msps...") % (usrp ->
get_rx_rate(ch) / 1e6) << endl;
        cout << boost::format("Actual TX Rate: %f Msps...") % (usrp ->
get_tx_rate(ch) / 1e6) << endl;

        //set antenna ...
        usrp -> set_rx_antenna(rx_ant_name, ch);
        usrp -> set_tx_antenna(tx_ant_name, ch);
        cout << "Rx antenna is " << usrp -> get_rx_antenna(ch) << endl;
        cout << "Tx antenna is " << usrp -> get_tx_antenna(ch) << endl;

        //set the rf gain
        usrp -> set_rx_gain(rx_gain, ch);
        usrp -> set_tx_gain(tx_gain, ch);
        cout << boost::format("Actual RX Gain: %f dB...") % usrp ->
get_rx_gain(ch) << endl;
        cout << boost::format("Actual TX Gain: %f dB...") % usrp ->
get_tx_gain(ch) << endl;

        //set the analog frontend filter bandwidth
        usrp -> set_rx_bandwidth(analg_bw, ch);
        usrp -> set_tx_bandwidth(analg_bw, ch);
        cout << boost::format("Actual RX Bandwidth: %f MHz...") % (usrp ->
get_rx_bandwidth(ch) / 1e6) << endl;
        cout << boost::format("Actual TX Bandwidth: %f MHz...") % (usrp ->
get_tx_bandwidth(ch) / 1e6) << endl;

        usrp -> set_rx_dc_offset(false, ch);

    }

    //detect which channels to use
    cout << "RX channel num: " << usrp -> get_rx_num_channels() << endl;
    cout << "TX channel num: " << usrp -> get_tx_num_channels() << endl;
    vector < string > channel_strings;
    boost::split(channel_strings, chan_str, boost::is_any_of("\"',"));
    for (size_t ch = 0; ch < channel_strings.size(); ch++) {
        size_t chan = stoi(channel_strings[ch]);
        if (chan >= usrp -> get_rx_num_channels()) {
            throw runtime_error("Invalid channel(s) specified.");
        } else {
            channel_nums.push_back(stoi(channel_strings[ch]));
        }
    }

    //create a receive streamer
    //linearly map channels (index0 = channel0, index1 = channel1, ...)
    uhd::stream_args_t stream_args("fc32"); //complex floats
    stream_args.channels = channel_nums;
    rx_stream = usrp -> get_rx_stream(stream_args);
    tx_stream = usrp -> get_tx_stream(stream_args);

    // pkt max size
    tx_max_num_samps = tx_stream -> get_max_num_samps();
    rx_max_num_samps = rx_stream -> get_max_num_samps();
    cout << "tx_max_num_samps = " << tx_max_num_samps << endl;
    cout << "rx_max_num_samps = " << rx_max_num_samps << endl;

    // issue command to receive data from usrp
    uhd::stream_cmd_t
stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
    stream_cmd.num_samps = 0;
    stream_cmd.stream_now = false;
    stream_cmd.time_spec = usrp -> get_time_now() +
uhd::time_spec_t(seconds_in_future);
    rx_stream -> issue_stream_cmd(stream_cmd); //tells all channels to
stream

    //cout<<"time real: " <<stream_cmd.time_spec.get_real_secs() << endl;
    //cout<<"time full: " <<stream_cmd.time_spec.get_full_secs() << endl;
    //cout<<"time frac: " <<stream_cmd.time_spec.get_frac_secs() << endl;
    //the first call to recv() will block this many seconds before receiving
    timeout = seconds_in_future + 0.1; //timeout (delay before receive +
padding)

    cout << "^^^^^^^^^^^^^^^^^^^^^^^^ complete SDR initialization
^^^^^^^^^^^^^^^^^^^^^" << endl;
}

sdr_dev::~sdr_dev() {}

void sdr_dev::set_time_for_receiving(double sec_in_future) {

    // issue command to receive data from usrp
    uhd::stream_cmd_t
stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
    stream_cmd.num_samps = 0;
    stream_cmd.stream_now = false;
    stream_cmd.time_spec = usrp -> get_time_now() +
uhd::time_spec_t(sec_in_future);
    rx_stream -> issue_stream_cmd(stream_cmd);

}

size_t sdr_dev::receive(vector < complex < float > * > rx_buff_ptr, size_t
requested_num_samps) {

    if (is_usrp_enabled == true)
        return usrp_receive(rx_buff_ptr, requested_num_samps);
    else
        return simu_receive(rx_buff_ptr, requested_num_samps);

}

// predefined functions
size_t sdr_dev::usrp_receive(vector < complex < float > * > rx_buff_ptr,
size_t requested_num_samps) {
    size_t acc_num_samps = 0;
    size_t total_num_samps = requested_num_samps;

    vector < complex < float > * > rx_buff_ptr_tmp = rx_buff_ptr;

    while (acc_num_samps < total_num_samps) {

        for (int i = 0; i < rx_buff_ptr.size(); i++) rx_buff_ptr_tmp[i] = &
rx_buff_ptr[i][acc_num_samps];

        size_t num_rx_samps = rx_stream -> recv(rx_buff_ptr_tmp,
total_num_samps - acc_num_samps, rx_md, timeout);

        //use a small timeout for subsequent packets
        timeout = 0.1;
        if (is_debg_enabled == true) {
            //handle the error code
            if (rx_md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT)
break;
            if (rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) {
                throw runtime_error(str(boost::format("Receiver error %s")
% rx_md.strerror()));
            }
            cout << boost::format("Received packet: %u samples, %u full
secs, %f frac secs")\ %
                num_rx_samps\ %
                rx_md.time_spec.get_full_secs()\ %
                rx_md.time_spec.get_frac_secs()\ <<
                endl;
        }
        acc_num_samps += num_rx_samps;
    }
    if (acc_num_samps < total_num_samps) {
        cerr << "Receive timeout before all samples received..." << endl;
    }

    return acc_num_samps;
}

size_t sdr_dev::transmit(vector < complex < float > * > tx_buff_ptr, size_t
requested_num_samps) {

    if (is_usrp_enabled == true)
        return usrp_transmit(tx_buff_ptr, requested_num_samps);
    else
        return simu_transmit(tx_buff_ptr, requested_num_samps);

}

size_t sdr_dev::usrp_transmit(vector < complex < float > * > tx_buff_ptr,
size_t requested_num_samps) {
    //setup metadata for the first packet
    tx_md.start_of_burst = true; // not clear what is the difference
between "false" and "true"
    tx_md.end_of_burst = false;
    tx_md.has_time_spec = true; //??? should be true or false
    tx_md.time_spec = usrp -> get_time_now() + uhd::time_spec_t(0.001);
//0.1

    //the first call to send() will block this many seconds before sending:
    timeout = seconds_in_future + 0.1; //timeout (delay before transmit +
padding)

    vector < complex < float > * > tx_buff_ptr_tmp = tx_buff_ptr;

    size_t acc_num_samps = 0; //number of accumulated samples
    size_t total_num_samps = requested_num_samps;
    while (acc_num_samps < total_num_samps) {
        size_t samps_to_send = total_num_samps - acc_num_samps;
        if (samps_to_send > tx_max_num_samps) {
            samps_to_send = tx_max_num_samps;
        } else {
            //tx_md.end_of_burst = true;
        }

        for (int i = 0; i < tx_buff_ptr.size(); i++) tx_buff_ptr_tmp[i] = &
tx_buff_ptr[i][acc_num_samps];

        //send a single packet
        size_t num_tx_samps = tx_stream -> send(tx_buff_ptr_tmp,
samps_to_send, tx_md, timeout);
        //do not use time spec for subsequent packets
        tx_md.has_time_spec = false;
        tx_md.start_of_burst = false;

        if (num_tx_samps < samps_to_send) {
            cerr << "Send timeout..." << endl;
        }
        if (is_debg_enabled == true) {
            cout << boost::format("Sent packet: %u samples") % num_tx_samps
<< endl;
        }
        acc_num_samps += num_tx_samps;
    }

    //tx_md.end_of_burst = true;
    tx_stream -> send("", 0, tx_md);

    if (is_debg_enabled == true) {
        cout << endl << "Waiting for async_opt burst ACK... " << flush;
        size_t acks = 0;
        //loop through all messages for the ACK packets (may have underflow
messages in queue)
        while (acks < channel_nums.size() and tx_stream ->
recv_async_msg(async_md, seconds_in_future)) {
            if (async_md.event_code ==
uhd::async_metadata_t::EVENT_CODE_BURST_ACK) acks++;
        }

        if (acks < channel_nums.size()) {
            cout << "fail" << endl;
        } else {
            cout << "ack received" << endl;
        }
    }

    return acc_num_samps;
}

On Mon, May 17, 2021 at 3:24 PM Marcus D Leech <patchvonbr...@gmail.com>
wrote:

> You haven’t said what type of daughter cards you’re using.
>
> Nor exactly how you’re setting things up
> In your software.
>
> Sent from my iPhone
>
> On May 17, 2021, at 1:56 PM, Zeng, Huacheng <huacheng.z...@gmail.com>
> wrote:
>
> 
> An update - I update UHD to 4.0 version and run the code again. With this
> version I got some warning message (see below). Did I set up the X310 usrp
> improperly?
>
>
> [INFO] [UHD] linux; GNU C++ version 7.5.0; Boost_106501;
> UHD_4.0.0.HEAD-0-g90ce6062
> [INFO] [X300] X300 initialization sequence...
> [INFO] [X300] Maximum frame size: 1472 bytes.
> [INFO] [X300] Radio 1x clock: 200 MHz
> [WARNING] [RFNOC::GRAPH] One or more blocks timed out during flush!
> Actual RX Freq: 915.000000 MHz...
> Actual TX Freq: 915.000000 MHz...
> Actual RX Rate: 2.000000 Msps...
> Actual TX Rate: 2.000000 Msps...
> Rx antenna is RX2
> Tx antenna is TX/RX
> Actual RX Gain: 0.000000 dB...
> Actual TX Gain: 15.000000 dB...
> Actual RX Bandwidth: 2.000000 MHz...
> Actual TX Bandwidth: 2.000000 MHz...
> Actual RX Freq: 915.000000 MHz...
> Actual TX Freq: 915.000000 MHz...
> Actual RX Rate: 2.000000 Msps...
> Actual TX Rate: 2.000000 Msps...
> Rx antenna is RX2
> Tx antenna is TX/RX
> Actual RX Gain: 0.000000 dB...
> Actual TX Gain: 15.000000 dB...
> Actual RX Bandwidth: 2.000000 MHz...
> Actual TX Bandwidth: 2.000000 MHz...
> RX channel num: 2
> TX channel num: 2
> [WARNING] [0/Radio#0] Attempting to set tick rate to 0. Skipping.
> [WARNING] [0/Radio#1] Attempting to set tick rate to 0. Skipping.
> [WARNING] [0/Radio#1] Attempting to set tick rate to 0. Skipping.
> [WARNING] [0/Radio#0] Attempting to set tick rate to 0. Skipping.
> tx_max_num_samps = 364
> rx_max_num_samps = 364
>
> Thanks,
> Hua
>
> On Mon, May 17, 2021 at 12:04 PM Huacheng Zeng <zenghuach...@gmail.com>
> wrote:
>
>> Hi all,
>>
>> I am using X310 as an MIMO transmitter to send two data streams. I
>> observed from the received signal that the two data streams are misaligned
>> in the time domain. I suspect that it is the X310's timing/frequency
>> synchronization problem. Below is the output information. Is there any C++
>> API reference for setting up X310 as a MIMO transmitter/receiver? Any
>> suggestions would be appreciated.
>>
>> Thanks,
>> Hua
>>
>>
>> [INFO] [UHD] linux; GNU C++ version 5.4.0 20160609; Boost_105800;
>> UHD_3.13.1.HEAD-0-gbbce3e45
>> --------------------------------------------------
>> -- UHD Device 0
>> --------------------------------------------------
>> Device Address:
>>     serial: 31804F1
>>     addr: 192.168.10.2
>>     fpga: HG
>>     name:
>>     product: X310
>>     type: x300
>>
>>
>>
>> [INFO] [UHD] linux; GNU C++ version 5.4.0 20160609; Boost_105800;
>> UHD_3.13.1.HEAD-0-gbbce3e45
>> [INFO] [X300] X300 initialization sequence...
>> [INFO] [X300] Maximum frame size: 1472 bytes.
>> [INFO] [X300] Radio 1x clock: 200 MHz
>> [INFO] [GPS] No GPSDO found
>> [INFO] [0/DmaFIFO_0] Initializing block control (NOC ID:
>> 0xF1F0D00000000000)
>> [INFO] [0/DmaFIFO_0] BIST passed (Throughput: *1292* MB/s)
>> [INFO] [0/DmaFIFO_0] BIST passed (Throughput: *1299* MB/s)
>> [INFO] [0/Radio_0] Initializing block control (NOC ID: 0x12AD100000000001)
>> [INFO] [0/Radio_1] Initializing block control (NOC ID: 0x12AD100000000001)
>> [INFO] [0/DDC_0] Initializing block control (NOC ID: 0xDDC0000000000000)
>> [INFO] [0/DDC_1] Initializing block control (NOC ID: 0xDDC0000000000000)
>> [INFO] [0/DUC_0] Initializing block control (NOC ID: 0xD0C0000000000000)
>> [INFO] [0/DUC_1] Initializing block control (NOC ID: 0xD0C0000000000000)
>> Actual RX Freq: 915.000000 MHz...
>> Actual TX Freq: 915.000000 MHz...
>> Actual RX Rate: 2.000000 Msps...
>> Actual TX Rate: 2.000000 Msps...
>> Rx antenna is RX2
>> Tx antenna is TX/RX
>> Actual RX Gain: 0.000000 dB...
>> Actual TX Gain: 15.000000 dB...
>> Actual RX Bandwidth: 2.000000 MHz...
>> Actual TX Bandwidth: 2.000000 MHz...
>> Actual RX Freq: 915.000000 MHz...
>> Actual TX Freq: 915.000000 MHz...
>> Actual RX Rate: 2.000000 Msps...
>> Actual TX Rate: 2.000000 Msps...
>> Rx antenna is RX2
>> Tx antenna is TX/RX
>> Actual RX Gain: 0.000000 dB...
>> Actual TX Gain: 15.000000 dB...
>> Actual RX Bandwidth: 2.000000 MHz...
>> Actual TX Bandwidth: 2.000000 MHz...
>> RX channel num: 2
>> TX channel num: 2
>> tx_max_num_samps = 364
>> rx_max_num_samps = 364
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> USRP-users mailing list -- usrp-users@lists.ettus.com
>> To unsubscribe send an email to usrp-users-le...@lists.ettus.com
>>
> _______________________________________________
> USRP-users mailing list -- usrp-users@lists.ettus.com
> To unsubscribe send an email to usrp-users-le...@lists.ettus.com
>
>
_______________________________________________
USRP-users mailing list -- usrp-users@lists.ettus.com
To unsubscribe send an email to usrp-users-le...@lists.ettus.com

Reply via email to