============================================================
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 <mailto: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 <mailto: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 <mailto: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
<mailto:usrp-users@lists.ettus.com>
To unsubscribe send an email to
usrp-users-le...@lists.ettus.com
<mailto:usrp-users-le...@lists.ettus.com>
_______________________________________________
USRP-users mailing list -- usrp-users@lists.ettus.com
<mailto:usrp-users@lists.ettus.com>
To unsubscribe send an email to
usrp-users-le...@lists.ettus.com
<mailto:usrp-users-le...@lists.ettus.com>