Advertisement
ANIK123

uhd time sync

May 21st, 2017
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.42 KB | None | 0 0
  1. #include <uhd/utils/thread_priority.hpp>
  2. #include <uhd/utils/safe_main.hpp>
  3. #include <uhd/usrp/multi_usrp.hpp>
  4. #include <boost/program_options.hpp>
  5. #include <boost/thread.hpp>
  6. #include <fstream>
  7. #include <thread>
  8. #include <csignal>
  9.  
  10. static bool stop_signal_called = false;
  11.  
  12. void sig_int_handler(int) {
  13.     std::cout << "SIG INT HANDLED" << std::endl;
  14.     stop_signal_called = true;
  15. }
  16.  
  17. /*!
  18.  * Wrapper on top of uhd device
  19.  */
  20. class USRPController {
  21. public:
  22.     uhd::usrp::multi_usrp::sptr device;
  23.  
  24.     USRPController(std::string serial, double rate, double freq, double gain, std::string file_name,
  25.                    std::string time_source) :
  26.             serial(serial), rate(rate), freq(freq), gain(gain) {
  27.         log_prepend = "[DEV " + serial + "] ";
  28.         std::cout << log_prepend << "Creating.." << std::endl;
  29.  
  30.         // I using b205mini, that means it don't have ethernet interface, just usb (access via serial number only)
  31.         // Now UHD doesn't support multi-serials in dev-args
  32.         this->device = uhd::usrp::multi_usrp::make("serial=" + serial);
  33.         this->device->set_time_source(time_source); //applies to all mboards
  34.         this->device->set_rx_subdev_spec(std::string("A:A"));
  35.  
  36.         uhd::tune_request_t tune_request(this->freq);
  37.         this->device->set_rx_freq(tune_request);
  38.         this->device->set_rx_gain(this->gain);
  39.         this->device->set_rx_rate(this->rate);
  40.         this->device->set_rx_bandwidth(this->rate);
  41.         this->device->set_rx_antenna("RX2");
  42.  
  43.         std::string cpu_format = "fc32";
  44.         std::string wire_format = "sc16";
  45.         uhd::stream_args_t stream_args(cpu_format, wire_format);
  46.         this->rx_stream = this->device->get_rx_stream(stream_args);
  47.  
  48.         full_file_name = "/path/to/files/" + file_name;
  49.  
  50.         size_t samps_per_buff = 10000;// samples per buffer
  51.         this->buff = std::vector<std::complex<float>>(samps_per_buff);
  52.         outfile.open(full_file_name.c_str(), std::ofstream::binary);
  53.     }
  54.  
  55.     void start(uhd::time_spec_t cmd_time) {
  56.         //setup streaming
  57.         uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
  58.         stream_cmd.num_samps = size_t(0);
  59.         stream_cmd.stream_now = false;
  60.         stream_cmd.time_spec = uhd::time_spec_t(cmd_time);
  61.         this->rx_stream->issue_stream_cmd(stream_cmd);
  62.     }
  63.  
  64.     /*!
  65.      * Read from device & writing to file will be executed in separate thread
  66.      * @return
  67.      */
  68.     bool work() {
  69.         size_t num_rx_samps = this->rx_stream->recv(&buff.front(), buff.size(), md, 3.0, true);
  70.  
  71.         if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) {
  72.             std::cout << log_prepend << boost::format("Timeout while streaming") << std::endl;
  73.         } else if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) {
  74.             if (overflow_message) {
  75.                 overflow_message = false;
  76.                 std::cerr << log_prepend << boost::format(
  77.                         "Got an overflow indication. Please consider the following:\n"
  78.                                 "  Your write medium must sustain a rate of %fMB/s.\n"
  79.                                 "  Dropped samples will not be written to the file.\n"
  80.                                 "  Please modify this example for your purposes.\n"
  81.                                 "  This message will not appear again.\n"
  82.                 ) % (this->device->get_rx_rate() * sizeof(std::complex<float>) / 1e6);
  83.             }
  84.             return true;
  85.         } else if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_NONE) {
  86. //            its o'k'?))
  87.         } else {
  88.             std::string error = str(boost::format("Uncaught error at %s %s") % (log_prepend, md.strerror()));
  89.             throw std::runtime_error(error);
  90.         }
  91.  
  92.         if (outfile.is_open()) {
  93.             outfile.write((const char *) &buff.front(), num_rx_samps * sizeof(std::complex<float>));
  94.         }
  95.  
  96.         return true;
  97.     }
  98.  
  99. private:
  100.     std::string serial;
  101.     double rate;
  102.     double freq;
  103.     double gain;
  104.  
  105.     uhd::rx_streamer::sptr rx_stream;
  106.     std::vector<std::complex<float>> buff;
  107.     uhd::rx_metadata_t md;
  108.     bool overflow_message = true;
  109.     std::string full_file_name;
  110.     std::string log_prepend;
  111.     std::ofstream outfile;
  112. };
  113.  
  114. void deviceThreadFunc(USRPController *controller) {
  115.     while (not stop_signal_called) {
  116.         if (not controller->work()) break;
  117.     }
  118. }
  119.  
  120. /*!
  121.  * Just check if time is same on devices
  122.  * @param dev1
  123.  * @param dev2
  124.  */
  125. void ppsControl(USRPController *dev1, USRPController *dev2) {
  126.     while (not stop_signal_called) {
  127.         const uhd::time_spec_t dtime1 = dev1->device->get_time_now();
  128.         const uhd::time_spec_t dtime2 = dev2->device->get_time_now();
  129.         if (dtime1.get_real_secs() != dtime2.get_real_secs()) {
  130.             std::cout << "not same: " << dtime1.get_real_secs() << " " << dtime2.get_real_secs() << std::endl;
  131.         } else {
  132.             std::cout << "is same! : " << dtime1.get_real_secs() << " " << dtime2.get_real_secs() << std::endl;
  133.         }
  134.         boost::this_thread::sleep(boost::posix_time::milliseconds(100));
  135.     }
  136. }
  137.  
  138. int UHD_SAFE_MAIN(int argc, char *argv[]) {
  139.     uhd::set_thread_priority_safe();
  140.  
  141.     std::signal(SIGINT, &sig_int_handler);
  142.     std::signal(SIGHUP, &sig_int_handler);
  143.  
  144.     double rate(5e6);
  145.     double gain(32);
  146.  
  147.     USRPController *device_one = new USRPController("serial1", rate, 400e6, gain, "channels1", "internal");
  148.     USRPController *device_two = new USRPController("serial2", rate, 400e6, gain, "channels2", "internal");
  149.  
  150.     boost::this_thread::sleep(boost::posix_time::seconds(3));
  151.    
  152.     // Got time Once and share to devices
  153.     long ttt = clock();
  154.     device_one->device->set_time_now(ttt);
  155.     device_two->device->set_time_now(ttt);
  156.  
  157.     std::thread ppmControlThread(ppsControl, device_one, device_two);
  158.  
  159.     boost::this_thread::sleep(boost::posix_time::seconds(3));
  160.    
  161.     uhd::time_spec_t start_timeout = uhd::time_spec_t(7.0);
  162.     uhd::time_spec_t cmd_time_one = device_one->device->get_time_now() + start_timeout;
  163.     uhd::time_spec_t cmd_time_two = device_two->device->get_time_now() + start_timeout;
  164.  
  165.     device_one->start(cmd_time_one);
  166.     device_two->start(cmd_time_two);
  167.  
  168.     std::thread first(deviceThreadFunc, device_one);
  169.     std::thread second(deviceThreadFunc, device_two);
  170.  
  171.     first.join();
  172.     second.join();
  173.  
  174.     return EXIT_SUCCESS;
  175. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement