![]() |
four_multi
Multi-Antenna,Multi-Node,Multi-Band,Multi-Cell
|
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 }