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