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