From b9501b75d8249cc95226cb5eae2e3dcb89349a3a Mon Sep 17 00:00:00 2001 From: manjaro Date: Thu, 14 Jan 2021 00:05:16 +0000 Subject: [PATCH] Add cpp streaming --- sdr/.gitignore | 73 +++++++++++ sdr/sdr.pro | 8 ++ sdr/uhd_io.cpp | 23 ++-- sdr/uhd_io_cpp.cpp | 321 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 414 insertions(+), 11 deletions(-) create mode 100644 sdr/.gitignore create mode 100644 sdr/sdr.pro create mode 100644 sdr/uhd_io_cpp.cpp diff --git a/sdr/.gitignore b/sdr/.gitignore new file mode 100644 index 0000000..fab7372 --- /dev/null +++ b/sdr/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/sdr/sdr.pro b/sdr/sdr.pro new file mode 100644 index 0000000..cb286af --- /dev/null +++ b/sdr/sdr.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt + +SOURCES += \ + uhd_io_cpp.cpp +LIBS += -luhd -lpthread diff --git a/sdr/uhd_io.cpp b/sdr/uhd_io.cpp index 9b4cd28..4047dde 100644 --- a/sdr/uhd_io.cpp +++ b/sdr/uhd_io.cpp @@ -12,7 +12,7 @@ #include #include #include -bool stop_signal_called = false; +static bool stop_signal_called = false; #define UHD_DO(X) \ {\ uhd_error e = (X);\ @@ -37,20 +37,22 @@ int main(int /*argc*/, char * /*argv*/[]) char dev_args[] = ""; char error_string[512]; //Sample rate in Hz - double sprate = 61440000/3; - //交通广播 FM 90.8 - double rx_freq = 107.7e6; + double sprate = 61440000 /2 ; + //接收频率 + double rx_freq = 200.0e6; double rx_sprate = sprate; double rx_gain = 55.0; bool rx_agc = false; - double rx_bw = 200000; + double rx_bw = sprate/1.2; + //模组,左侧=0 右侧=1 size_t rx_channel = 0; - //转发到106 - double tx_freq = 88.5e6; + //转发频率 + double tx_freq = 100.0e6; double tx_sprate = sprate; - double tx_gain = 100; - double tx_bw = 200000; - size_t tx_channel = 0; + double tx_gain = 70; + double tx_bw = sprate/1.2; + //模组,左侧=0 右侧=1 + size_t tx_channel = 1; //设备句柄 uhd_usrp_handle usrp = 0; @@ -142,7 +144,6 @@ int main(int /*argc*/, char * /*argv*/[]) size_t rx_sps_buff = 0; size_t tx_sps_buff = 0; - // Set rate fprintf(stderr, "Setting RX Rate: %f...\n", rx_sprate); UHD_DO(uhd_usrp_set_rx_rate(usrp, rx_sprate, rx_channel)); diff --git a/sdr/uhd_io_cpp.cpp b/sdr/uhd_io_cpp.cpp new file mode 100644 index 0000000..cc2b221 --- /dev/null +++ b/sdr/uhd_io_cpp.cpp @@ -0,0 +1,321 @@ +/* + * Copyright 2015 Ettus Research LLC + * Copyright 2018 Ettus Research, a National Instruments Company + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using uhd::tune_request_t; +using uhd::tx_streamer; +using uhd::usrp::multi_usrp; +using uhd::rx_streamer; +using std::thread; +using std::cerr; +using std::endl; + +static bool stop_signal_called = false; +void sigint_handler(int code){ + (void)code; + stop_signal_called = true; +} + +struct tag_channelOptions{ + std::string type = "sc16"; //sample type: fc64, fc32, or sc16 + std::string ant = "TX/RX"; //antenna selection + std::string subdev; //subdevice specification + std::string wirefmt; //wire format (sc8 or sc16) + size_t channel = 0; //which channel to use + size_t spb = 10000; //samples per buffer + double rate = 61.44e6/2; //rate of outgoing samples + double freq = 1.0e9; //RF center frequency in Hz + double gain = 55; //gain for the RF chain + double bw = rate * 0.8; //analog frontend filter bandwidth in Hz + double lo_offset = 0; //Offset for frontend LO in Hz (optional) + bool int_n_mod = false; //int-n mode + double setup_time = 3.0; //setup time for rx +}; +bool check_tx_status(const std::string & ref, multi_usrp::sptr usrp); +bool check_rx_status(const std::string & ref, multi_usrp::sptr usrp,const tag_channelOptions & op); + +template +void do_io( + const tag_channelOptions & oprx, + const tag_channelOptions & optx, + rx_streamer::sptr rx, + tx_streamer::sptr tx) +{ + std::vector< std::shared_ptr< FMT > > vec_buffer; + const int bufsz = 65536; + for (int i=0;i (new FMT[oprx.spb])); + + long long rx_count = 0, tx_count = 0; + + auto thcall_rx = [&]()->void{ + uhd::rx_metadata_t md_rx; + uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + stream_cmd.num_samps = size_t(oprx.spb); + stream_cmd.stream_now = true; + stream_cmd.time_spec = uhd::time_spec_t(); + rx->issue_stream_cmd(stream_cmd); + while (!stop_signal_called) + { + const size_t samples_recv = rx->recv((void *)(vec_buffer[rx_count % bufsz].get()),oprx.spb,md_rx,0.1,false); + ++rx_count; + if (md_rx.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) + fputs("Time out.",stderr); + else if (md_rx.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) + fputs("Over flow",stderr); + else if (md_rx.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) + cerr << "Receiver error: "<< md_rx.strerror() << endl ; + if (samples_recv != oprx.spb) + cerr << "Receiver error, samples_recv "<void{ + uhd::tx_metadata_t md_tx; + md_tx.end_of_burst = false; + md_tx.start_of_burst = false; + while (!stop_signal_called) + { + const size_t samples_sent = tx->send((void *)(vec_buffer[tx_count % bufsz].get()),oprx.spb,md_tx,0.1); + if (tx_countset_clock_source(ref); + + //Set Tx channal---------------------- + + tag_channelOptions tx_op; + tx_op.channel = 1;//using channel No.2 + tx_op.freq = 88.0e6; + //subdevice specification + if (tx_op.subdev.size()) + usrp->set_tx_subdev_spec(tx_op.subdev); + cerr << "TX Using Device: " << usrp->get_pp_string() << endl; + + cerr << "Setting TX Rate: " << (tx_op.rate / 1e6) << "Msps..." << endl; + usrp->set_tx_rate(tx_op.rate); + cerr << "Actual TX Rate: " << usrp->get_tx_rate() / 1e6 << "Msps..." << endl; + + // set the center frequency + cerr << "Setting TX Freq: " << (tx_op.freq / 1e6) <<"MHz..." << endl; + cerr << "Setting TX LO Offset: " << (tx_op.lo_offset / 1e6) << "MHz..." <set_tx_freq(tune_request_tx); + cerr << "Actual TX Freq: " << (usrp->get_tx_freq() / 1e6) << "MHz..." << endl; + + // set the rf gain + cerr << "Setting TX Gain: " << tx_op.gain <<" dB..." << endl; + usrp->set_tx_gain(tx_op.gain); + cerr << "Actual TX Gain: " << usrp->get_tx_gain() << " dB..." << endl; + + // set the analog frontend filter bandwidth + cerr << "Setting TX Bandwidth: " << (tx_op.bw / 1e6) << "MHz..." << endl; + usrp->set_tx_bandwidth(tx_op.bw); + cerr << "Actual TX Bandwidth: " << usrp->get_tx_bandwidth() / 1e6 << "MHz..." << endl; + // set the antenna + if (tx_op.ant.size()) + usrp->set_tx_antenna(tx_op.ant); + + //Set Rx Channel + tag_channelOptions rx_op; + rx_op.ant = "RX2"; + rx_op.channel = 0; + //subdevice specification + if (rx_op.subdev.size()) + usrp->set_rx_subdev_spec(rx_op.subdev); + cerr << "RX Using Device: " << usrp->get_pp_string() << endl; + + cerr << "Setting RX Rate: " << (rx_op.rate / 1e6) << "Msps..." << endl; + usrp->set_rx_rate(rx_op.rate); + cerr << "Actual RX Rate: " << usrp->get_rx_rate() / 1e6 << "Msps..." << endl; + + // set the center frequency + cerr << "Setting RX Freq: " << (rx_op.freq / 1e6) <<"MHz..." << endl; + cerr << "Setting RX LO Offset: " << (rx_op.lo_offset / 1e6) << "MHz..." <set_rx_freq(tune_request_rx); + cerr << "Actual RX Freq: " << (usrp->get_rx_freq() / 1e6) << "MHz..." << endl; + + // set the rf gain + cerr << "Setting RX Gain: " << rx_op.gain <<" dB..." << endl; + usrp->set_rx_gain(rx_op.gain); + cerr << "Actual RX Gain: " << usrp->get_rx_gain() << " dB..." << endl; + + // set the analog frontend filter bandwidth + cerr << "Setting RX Bandwidth: " << (rx_op.bw / 1e6) << "MHz..." << endl; + usrp->set_rx_bandwidth(rx_op.bw); + cerr << "Actual RX Bandwidth: " << usrp->get_rx_bandwidth() / 1e6 << "MHz..." << endl; + // set the antenna + if (rx_op.ant.size()) + usrp->set_rx_antenna(rx_op.ant); + + check_tx_status(ref,usrp); + check_rx_status(ref,usrp,rx_op); + // create a transmit streamer + std::vector channel_nums_tx; + uhd::stream_args_t stream_args_tx(tx_op.type, tx_op.wirefmt); + channel_nums_tx.push_back(tx_op.channel); + stream_args_tx.channels = channel_nums_tx; + tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args_tx); + + // create a receive streamer + uhd::stream_args_t stream_args_rx(rx_op.type, rx_op.wirefmt); + std::vector channel_nums_rx; + channel_nums_rx.push_back(rx_op.channel); + stream_args_rx.channels = channel_nums_rx; + rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args_rx); + + + do_io(rx_op,tx_op,rx_stream,tx_stream); + + // finished + cerr << endl << "Done!" << endl << endl; + + return EXIT_SUCCESS; +} + + +bool check_tx_status(const std::string & ref, multi_usrp::sptr usrp) +{ + // Check Ref and LO Lock detect + std::vector sensor_names; + sensor_names = usrp->get_tx_sensor_names(0); + if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") + != sensor_names.end()) { + uhd::sensor_value_t lo_locked = usrp->get_tx_sensor("lo_locked", 0); + cerr <<"Checking TX: "<< lo_locked.to_pp_string() << std::endl; + UHD_ASSERT_THROW(lo_locked.to_bool()); + } + sensor_names = usrp->get_mboard_sensor_names(0); + if ((ref == "mimo") + and (std::find(sensor_names.begin(), sensor_names.end(), "mimo_locked") + != sensor_names.end())) { + uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked", 0); + std::cerr << "Checking TX: "<< mimo_locked.to_pp_string() << std::endl; + UHD_ASSERT_THROW(mimo_locked.to_bool()); + } + if ((ref == "external") + and (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") + != sensor_names.end())) { + uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked", 0); + std::cout << "Checking TX: %s ..."<< ref_locked.to_pp_string() << std::endl; + UHD_ASSERT_THROW(ref_locked.to_bool()); + } + return true; +} +typedef std::function get_sensor_fn_t; +bool check_locked_sensor(std::vector sensor_names, + const char* sensor_name, + get_sensor_fn_t get_sensor_fn, + double setup_time) +{ + if (std::find(sensor_names.begin(), sensor_names.end(), sensor_name) + == sensor_names.end()) + return false; + + auto setup_timeout = std::chrono::steady_clock::now() + + std::chrono::milliseconds(int64_t(setup_time * 1000)); + bool lock_detected = false; + + std::cerr << "Checking RX Waiting for: " << sensor_name; + std::cerr.flush(); + + while (true) { + if (lock_detected and (std::chrono::steady_clock::now() > setup_timeout)) { + std::cerr << " locked." << std::endl; + break; + } + if (get_sensor_fn(sensor_name).to_bool()) { + std::cerr << "+"; + std::cerr.flush(); + lock_detected = true; + } else { + if (std::chrono::steady_clock::now() > setup_timeout) { + std::cerr << std::endl; + std::cerr << "timed out waiting for consecutive locks on sensor : "<get_rx_sensor_names(op.channel), + "lo_locked", + [usrp, op](const std::string& sensor_name) { + return usrp->get_rx_sensor(sensor_name, op.channel); + }, + op.setup_time); + if (ref == "mimo") { + check_locked_sensor(usrp->get_mboard_sensor_names(0), + "mimo_locked", + [usrp](const std::string& sensor_name) { + return usrp->get_mboard_sensor(sensor_name); + }, + op.setup_time); + } + if (ref == "external") { + check_locked_sensor(usrp->get_mboard_sensor_names(0), + "ref_locked", + [usrp](const std::string& sensor_name) { + return usrp->get_mboard_sensor(sensor_name); + }, + op.setup_time); + } + return true; +} -- GitLab