diff --git a/sdr/uhd_io.cpp b/sdr/uhd_io.cpp index 4047dde8b3c0415a974a4b9fc58ad69f5d625cfa..819239d3f7705a41de0f85080780f341a90e6e11 100644 --- a/sdr/uhd_io.cpp +++ b/sdr/uhd_io.cpp @@ -37,22 +37,22 @@ int main(int /*argc*/, char * /*argv*/[]) char dev_args[] = ""; char error_string[512]; //Sample rate in Hz - double sprate = 61440000 /2 ; + double sprate = 61.44e6/2 ; //接收频率 - double rx_freq = 200.0e6; + double rx_freq = 107.7e6; double rx_sprate = sprate; double rx_gain = 55.0; bool rx_agc = false; - double rx_bw = sprate/1.2; + double rx_bw = 400000; //模组,左侧=0 右侧=1 size_t rx_channel = 0; //转发频率 - double tx_freq = 100.0e6; + double tx_freq = 89.0e6; double tx_sprate = sprate; double tx_gain = 70; - double tx_bw = sprate/1.2; + double tx_bw = 400000; //模组,左侧=0 右侧=1 - size_t tx_channel = 1; + size_t tx_channel = 0; //设备句柄 uhd_usrp_handle usrp = 0; @@ -237,13 +237,16 @@ int main(int /*argc*/, char * /*argv*/[]) fprintf(stderr, "Issuing stream command.\n"); UHD_DO(uhd_rx_streamer_issue_stream_cmd(rx_streamer, &rx_stream_cmd)); - uhd_usrp_set_time_now(usrp,0,0,0); + //uhd_usrp_set_time_now(usrp,0,0,0); size_t num_samps_sent = 0; // Actual streaming, TX Threading std::thread th_send([&]()->void { + try{ while (!stop_signal_called) { + if (rx_pos<5) + continue; SPTYPE * tx_buff = io_buff[tx_pos % sz_buffer]; const void ** tx_buff_ptr = (const void **) &tx_buff; UHD_DO(uhd_tx_streamer_send(tx_streamer, tx_buff_ptr, tx_sps_buff, &tx_meta, 1, &num_samps_sent)); diff --git a/sdr/uhd_io_cpp.cpp b/sdr/uhd_io_cpp.cpp index cc2b22121a534f91a0d640ea82cb8f6dbd064793..adc0b127d9f66edbeb7858baefbf63652f72ed30 100644 --- a/sdr/uhd_io_cpp.cpp +++ b/sdr/uhd_io_cpp.cpp @@ -3,6 +3,7 @@ * Copyright 2018 Ettus Research, a National Instruments Company * * SPDX-License-Identifier: GPL-3.0-or-later + * 丁劲犇修改 2021 */ #include @@ -29,39 +30,52 @@ void sigint_handler(int code){ (void)code; stop_signal_called = true; } - +/*! + * \brief The tag_channelOptions struct + * 通道配置参数 + */ 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 + std::string type = "sc16"; //样点类型,为上位机上类型: fc64, fc32, or sc16 + std::string ant = "TX/RX"; //天线选取,B210 有 TX/RX 或者 RX2两个 + std::string subdev; //子设备,本例子没有配置 + std::string wirefmt; //内部类型 (sc8 or sc16),是片上处理的类型 + size_t channel = 0; //通道号,可以是0(左侧)或者1(右侧) + size_t spb = 10000; //缓冲大小,太小会丢包,太大会超时 + double rate = 61.44e6/2; //采样率,单位Hz + double freq = 1.0e9; //射频频率,单位Hz + double gain = 55; //射频增益,单位dB + double bw = rate; //滤波带宽,默认为采样窗口 + double lo_offset = 0; //LO偏移,单位 Hz (缺省) + bool int_n_mod = false; //int-n 模式(本例不配置) + bool docheck = true; //在开始前执行检查 + double setup_time = 1.0; //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 +/*! + * 范例吞吐函数,使用环形队列保持跟随收发 + */ +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; + std::vector< int > vec_buffersz; const int bufsz = 65536; for (int i=0;i (new FMT[oprx.spb])); - + { + vec_buffer.push_back(std::shared_ptr< FMT > (new FMT[oprx.spb * 2])); + vec_buffersz.push_back(0); + } + //收发计数 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); @@ -71,7 +85,7 @@ void do_io( 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); + vec_buffersz[rx_count % bufsz] = 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); @@ -79,18 +93,23 @@ void do_io( 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; + long long last_tx = -1; while (!stop_signal_called) { - const size_t samples_sent = tx->send((void *)(vec_buffer[tx_count % bufsz].get()),oprx.spb,md_tx,0.1); + //等待一会数据,以便TX可以保持跟随。也可以不设置,这样开始时会争夺。 + if (rx_count<100) + continue; + if (last_tx==tx_count) + cerr<<"Blocked!"<send((void *)(vec_buffer[tx_count % bufsz].get()),vec_buffersz[tx_count % bufsz],md_tx,0.1); + last_tx = tx_count; if (tx_countset_clock_source(ref); - //Set Tx channal---------------------- - + //3.配置发射 tag_channelOptions tx_op; - tx_op.channel = 1;//using channel No.2 - tx_op.freq = 88.0e6; - //subdevice specification + tx_op.channel = 0; + tx_op.freq = 89e6; + tx_op.bw = 200e3; + tx_op.gain=70; + //3.1子设备配置(默认) if (tx_op.subdev.size()) usrp->set_tx_subdev_spec(tx_op.subdev); cerr << "TX Using Device: " << usrp->get_pp_string() << endl; - + //3.2速率配置 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 + //3.3中心频率配置 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 + //3.4增益配置 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 + //3.5模拟前端滤波器带宽配置 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 + //3.6指定天线 if (tx_op.ant.size()) usrp->set_tx_antenna(tx_op.ant); - //Set Rx Channel + //4.配置接收 tag_channelOptions rx_op; rx_op.ant = "RX2"; rx_op.channel = 0; - //subdevice specification + rx_op.bw = 200e3; + rx_op.freq = 107.7e6; + rx_op.gain = 50; + //4.1 子设备 if (rx_op.subdev.size()) usrp->set_rx_subdev_spec(rx_op.subdev); cerr << "RX Using Device: " << usrp->get_pp_string() << endl; - + //4.2 采样率 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 + //4.3 中心频率 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 + //4.4 增益 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 + //4.5 前端模拟滤波带宽 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 + //4.6 选择天线 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 + //5 检查状态 + if (tx_op.docheck) check_tx_status(ref,usrp); + if (rx_op.docheck) check_rx_status(ref,usrp,rx_op); + + //6.创建流对象实例 + //6.1 发射 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 + // 6.2 接收 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