four_multi
Multi-Antenna,Multi-Node,Multi-Band,Multi-Cell
utils/rxm.cpp
00001 //
00002 // Copyright 2011-2013 KTH Royal Institute of Technology
00003 //
00004 // This program is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU General Public License as published by
00006 // the Free Software Foundation, either version 3 of the License, or
00007 // (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 
00018 
00019 #include <fstream> 
00020 #include <uhd/utils/thread_priority.hpp>
00021 #include <uhd/utils/safe_main.hpp>
00022 #include <uhd/usrp/multi_usrp.hpp>
00023 #include <boost/program_options.hpp>
00024 #include <boost/format.hpp>
00025 #include <iostream>
00026 #include <complex>
00027 #include <uhd/types/clock_config.hpp>
00028 #include <itpp/itbase.h>
00029 #include <four_multi/get_usrp2_ip_addr.hpp>
00030 #include <four_multi/gps.hpp>
00031 
00032 
00033 
00034 namespace po = boost::program_options;
00035 
00036 int UHD_SAFE_MAIN(int argc, char *argv[]){
00037     
00038     
00039 
00040 
00041     double d_rate;
00042     static const time_t time_available_for_trigger=1;
00043 
00044     //variables to be set by po
00045     std::string args;
00046     time_t seconds_in_future=1;
00047     uint32_t total_num_samps, gps_time_combined;
00048     uint32_t no_chan, skip_ant;
00049     double freq;
00050     std::string filename, dev_name;
00051     bool use_external_10MHz, use_J1;
00052 
00053     std::string gains_str;
00054     itpp::vec gains; // IT++ class
00055     //std::vector<double> gains_vec;
00056     std::string IP_addresses, IP_addresses1;  // Adresses of the USRPs
00057     
00058 
00059     // Internal variables 
00060     uhd::clock_config_t my_clock_config; 
00061 
00062     //setup the program options
00063     po::options_description desc("Allowed options");
00064     desc.add_options()
00065         ("10MHz",po::value<bool>(&use_external_10MHz)->default_value(false), 
00066          "external 10MHz on 'REF CLOCK' connector (true=1=yes)")
00067       ("gps_time_combined", po::value<uint32_t>(&gps_time_combined)->default_value(0), "start time triggering using GPS and PPS (h*3600+m*60+s, or =0 no triggering)")
00068 ("dev_name",po::value<std::string>(&dev_name)->default_value("/dev/ttyUSB0"), "Name of GPS device") 
00069        ("help", "help message")
00070         ("rate", po::value<double>(&d_rate)->default_value(25e6), "sample rate")
00071         ("nsamps", po::value<uint32_t>(&total_num_samps)->default_value(1000), "total number of samples to receive")
00072         ("nchan", po::value<uint32_t>(&no_chan)->default_value(1), "number of usrp2:s")
00073         ("skip_ant",po::value<uint32_t>(&skip_ant)->default_value(0), 
00074           "Example: if skip_ant=1 then the first USPR2 should have address 192.168.20.2")
00075          ("freq", po::value<double>(&freq)->default_value(2420e6), "rf center frequency in Hz")
00076       ("filename",po::value<std::string>(&filename)->default_value("data_from_usrp.dat"), "output filename") 
00077      ("gains",po::value<std::string>(&gains_str)->default_value("0 0 0 0"), 
00078    "set the receiver gains")
00079         ("use_J1",po::value<bool>(&use_J1)->default_value(true), "Use J1 as input")
00080  
00081     ;
00082     po::variables_map vm;
00083     po::store(po::parse_command_line(argc, argv, desc), vm);
00084     po::notify(vm);
00085     
00086 
00087 
00088     //print the help message
00089     if (vm.count("help")){
00090         std::cout << boost::format("UHD RX Timed Samples %s") % desc << std::endl;
00091         return ~0;
00092     }
00093 
00094     if (!(uhd::set_thread_priority_safe(1,true))) {
00095       std::cout << "Problem setting thread priority" << std::endl;
00096       return 1;
00097     };
00098 
00099 
00100        
00101    gains=gains_str.c_str();  
00102    IP_addresses=get_usrp2_ip_addr(no_chan+skip_ant);
00103 
00104    std::istringstream iss(IP_addresses);
00105   
00106    // Skip skip_ant addresses:
00107    for (uint32_t i1=0;i1<skip_ant;i1++) {
00108      std::string subs;
00109      iss >> subs;
00110    };
00111 
00112 
00113    //create a usrp device
00114    uhd::device_addr_t dev_addr;
00115 
00116 
00117   for (uint32_t i1=0;i1<no_chan;i1++) {
00118     std::string subs;
00119     std::string numb;
00120     std::stringstream ss;
00121 
00122     ss << i1;
00123     ss >> numb;
00124     numb="addr"+numb;
00125     iss >> subs;
00126     dev_addr[numb]=subs;
00127     IP_addresses1+=subs;
00128     if (i1<(no_chan-1)){
00129       IP_addresses1+=" ";
00130     }
00131     dev_addr[numb]=subs;
00132 
00133   };
00134 
00135 
00136 
00137 
00138 
00139    uhd::usrp::multi_usrp::sptr d_mdev=uhd::usrp::multi_usrp::make(dev_addr);
00140    uhd::device::sptr dev = d_mdev->get_device();
00141    
00142 
00143    std::string config = d_mdev->get_pp_string();
00144    uint32_t temp;
00145    bool is_basic, is_xcvr2450;
00146    
00147    std::cout << "config=" << config << std::endl;
00148 
00149    temp=config.find("Basic");
00150    if (temp<config.length())
00151      is_basic=true;
00152    else
00153      is_basic=false;    
00154 
00155    temp=config.find("XCVR2450");
00156    if (temp<config.length())
00157      is_xcvr2450=true; 
00158    else
00159      is_xcvr2450=false;
00160 
00161    std::cout << "is_basic=" << is_basic << std::endl;
00162    std::cout << "is_xcvr2450=" << is_xcvr2450 << std::endl;
00163 
00164    if (is_basic & is_xcvr2450) {
00165      std::cout << "Either basic db or xcvr2450 must be used, not both. \n";
00166      exit(1);
00167    };
00168    if (!(is_basic | is_xcvr2450)) {
00169      std::cout << "Either basic db or xcvr2450 must be used \n";
00170      exit(1);
00171    };
00172 
00173 
00174    if (is_basic) {
00175      uhd::usrp::subdev_spec_t spec("A:A");
00176      for (uint32_t i1=0;i1<no_chan;i1++) {
00177         d_mdev->set_rx_subdev_spec(spec, i1);
00178      };
00179    };
00180    if (is_xcvr2450) {
00181      if (use_J1) {
00182        for (uint32_t i1=0;i1<no_chan;i1++) {
00183          d_mdev->set_tx_antenna("J2",i1);
00184          d_mdev->set_rx_antenna("J1",i1);
00185        };
00186      } else {
00187        for (uint32_t i1=0;i1<no_chan;i1++) {
00188          d_mdev->set_tx_antenna("J1",i1);
00189          d_mdev->set_rx_antenna("J2",i1);
00190        };
00191      };
00192    };
00193 
00194 
00195    d_mdev->set_rx_rate(d_rate);
00196    d_mdev->set_tx_rate(d_rate);
00197 
00198    
00199 
00200    uhd::tune_result_t tr;
00201 
00202    for (uint32_t i1=0;i1<no_chan;i1++) {
00203      tr=d_mdev->set_rx_freq(freq,i1);
00204      if ((int) i1<gains.size())        
00205        d_mdev->set_rx_gain(gains(i1),i1);
00206      else {
00207        d_mdev->set_rx_gain(gains(gains.size()-1),i1);
00208      };
00209    };
00210    
00211 
00212 
00213    my_clock_config.pps_source=uhd::clock_config_t::PPS_SMA; //PZ      
00214    my_clock_config.pps_polarity=uhd::clock_config_t::PPS_POS; //PZ      
00215 
00216    // Lock to 10MHz
00217    if (use_external_10MHz) 
00218       my_clock_config.ref_source=uhd::clock_config_t::REF_SMA; //PZ
00219    else
00220       my_clock_config.ref_source=uhd::clock_config_t::REF_INT; //PZ
00221    
00222 
00223   for (uint32_t i1=0;i1<no_chan;i1++) 
00224     d_mdev->set_clock_config(my_clock_config, i1);
00225 
00226 
00227     usleep(1e5); // Wait for freq and gain to settle
00228 
00229     if (gps_time_combined==0) {
00230       for (uint32_t i1=0;i1<no_chan;i1++) {
00231         d_mdev->set_time_now(uhd::time_spec_t(0.0));
00232       };
00233     } else {
00234       
00235       // Sync the node to pps   
00236       //uhd::time_spec_t offset_time(0.0);
00237       if (gps_time_combined>1) {
00238         gps_wait_until(dev_name.c_str(),gps_time_combined);
00239       };
00240       d_mdev->set_time_next_pps(uhd::time_spec_t(0.0));
00241       std::cout << "Wait for pps!" << std::endl;
00242       usleep(1e6*time_available_for_trigger); 
00243       std::cout << "Sync done" << std::endl;
00244     };
00245       
00246     //} else {
00247     //    offset_time=d_mdev->get_time_now(0);
00248     //};
00249 
00250    // Create storage for the entire received signal.
00251    std::complex<int16_t> *d_buffer_rx;
00252    std::vector<void *> d_rx_buffers;
00253 
00254    for (uint32_t i1=0;i1<no_chan;i1++) {
00255      d_buffer_rx = new std::complex<int16_t>[total_num_samps];   
00256      d_rx_buffers.push_back(d_buffer_rx);
00257    };
00258 
00259     
00260 
00261     //setup streaming
00262     //std::cout << std::endl;
00263     //std::cout << boost::format("Begin streaming %u samples, %d seconds in the future...")
00264     //    % total_num_samps % seconds_in_future << std::endl;
00265     uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
00266     stream_cmd.num_samps = total_num_samps;
00267     stream_cmd.stream_now = false;
00268     stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future);
00269     d_mdev->issue_stream_cmd(stream_cmd);
00270 
00271 
00272     uhd::rx_metadata_t md_rx;
00273     unsigned int num_rx_samps=0;
00274 
00275 
00276     while (num_rx_samps==0) {
00277 
00278    
00279       num_rx_samps=dev->recv(
00280                                      d_rx_buffers,
00281                                      total_num_samps,
00282                                      md_rx,
00283             uhd::io_type_t::COMPLEX_INT16, // PZ
00284             uhd::device::RECV_MODE_FULL_BUFF // PZ
00285        );
00286 
00287 
00288 
00289     };
00290 
00291     
00292 
00293 
00294     //finished
00295     std::cout << std::endl << "Done!" << std::endl << std::endl; // PZ
00296 
00297     // Save output to disc
00298     std::ofstream s1(filename.c_str(), std::ios::binary);   // PZ
00299     for (uint32_t i1=0;i1<no_chan;i1++) {
00300       d_buffer_rx = (std::complex<short int>*) d_rx_buffers[i1];
00301       s1.write((char *) d_buffer_rx ,4*total_num_samps); //ZP
00302     };
00303     s1.flush(); //PZ
00304     s1.close(); //PZ
00305 
00306 
00307 
00308 
00309     return 0;
00310 }
 All Classes Functions Variables