dom11990

streamtest.cpp

Apr 5th, 2017
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.16 KB | None | 0 0
  1. #include <uhd/usrp/multi_usrp.hpp>
  2. #include <vector>
  3. #include <complex>
  4. #include <boost/shared_ptr.hpp>
  5. #include <boost/thread/future.hpp>
  6. #include <boost/thread/shared_mutex.hpp>
  7.  
  8. #define LOG_DEBUG std::cout
  9. #define newl std::endl;
  10.  
  11. void Receive_Thread(boost::shared_ptr<uhd::usrp::multi_usrp> usrp,
  12.         boost::shared_mutex& mutex);
  13.  
  14. /**
  15.  * Generates a simple tone based on the specified parameters
  16.  * @param data buffer is automatically resized appropriately
  17.  * @param freq tone frequency in hertz
  18.  * @param amplitude max amplitude
  19.  * @param fs sample rate in hertz
  20.  * @param size number of samples
  21.  */
  22. void Generate_Tone(std::vector<std::complex<float>>&data, double freq,
  23.         double amplitude, double fs, double size);
  24.  
  25. /**
  26.  * Dumps the vector to a simple python file that can be used for visualization
  27.  * @param data iq vector
  28.  * @param rate sample rate with which the data was acquired
  29.  * @param path save location including file name e.g. "/home/bob/file.py"
  30.  */
  31. void Dump_to_Py(std::vector<std::complex<float> >& data, float rate,
  32.         const std::string& path);
  33.  
  34. //
  35. int main() {
  36.  
  37.     auto _usrp = uhd::usrp::multi_usrp::make(std::string(""));
  38.  
  39.     //configure tx first
  40.     bool ack_reveived = false;
  41.     std::vector<std::complex<float>> buffer;
  42.     double rate = 1e6;
  43.     double atten = 20;
  44.     _usrp->set_tx_rate(rate);
  45.     _usrp->set_tx_bandwidth(56e6);
  46.     _usrp->set_tx_gain(30 + atten);
  47.     uhd::tune_request_t tune(3.8e9);
  48.     _usrp->set_tx_freq(tune);
  49.  
  50.     //create a 1kHz tone vector, 100k samples, 1M sample rate
  51.     Generate_Tone(buffer, 1e3, 0.8, rate, 100e3);
  52.     uhd::tx_metadata_t meta_data;
  53.     meta_data.has_time_spec = false;
  54.     meta_data.end_of_burst = true;
  55.     meta_data.start_of_burst = true;
  56.     LOG_DEBUG << "Tx waiting for Rx to begin receiving... " << newl;
  57.  
  58.  
  59.     //configure and run an acquisition, use the mutex to know when the
  60.     //acquisition begins
  61.     boost::shared_mutex mutex;
  62.     mutex.lock();
  63.    
  64.     //**************************************************************************
  65.     //uncomment to see the issue disappear
  66.     //uhd::stream_args_t stream_args("fc32"); // complex floats
  67.     //auto streamer = _usrp->get_tx_stream(stream_args);
  68.     //**************************************************************************
  69.     auto rx_future = boost::async(boost::bind(&Receive_Thread,
  70.             _usrp, boost::ref(mutex)));
  71.  
  72.     mutex.lock();
  73.     LOG_DEBUG << "Got lock" << newl;
  74.     //wait 100ms to show that the data rx is receiving is reasonable
  75.     //play with this sleep to see the '0's move around in the captured waveform
  76.     usleep(100 * 1000);
  77.     LOG_DEBUG << "Creating  tx streamer" << newl;
  78.     uhd::stream_args_t stream_args("fc32"); // complex floats
  79.     stream_args.channels = std::vector<size_t>(1, 0);
  80.     auto streamer = _usrp->get_tx_stream(stream_args);
  81.  
  82.     LOG_DEBUG << "Transmitting..." << newl;
  83.     auto sent = streamer->send(&buffer.at(0), buffer.size(), meta_data, 2);
  84.  
  85.     LOG_DEBUG << "Tx done" << newl;
  86.     LOG_DEBUG << "Waiting for rx to complete..." << newl;
  87.     rx_future.get();
  88.     LOG_DEBUG << "Rx done" << newl;
  89. }
  90.  
  91. void Receive_Thread(boost::shared_ptr<uhd::usrp::multi_usrp> usrp, boost::shared_mutex& mutex) {
  92.     LOG_DEBUG << "rx thread started" << newl;
  93.  
  94.     double rate = 1e6;
  95.     usrp->set_rx_rate(rate);
  96.     usrp->set_rx_bandwidth(56e6);
  97.     usrp->set_rx_gain(45);
  98.     //offset the LO slightly
  99.     uhd::tune_request_t tune(3.8e9 + 100e3);
  100.     usrp->set_rx_freq(tune);
  101.     std::vector<std::complex<float>> iq_data;
  102.     size_t count = 300000;
  103.     iq_data.resize(count);
  104.  
  105.     uhd::stream_args_t stream_args("fc32"); // complex floats
  106.     stream_args.channels = std::vector<size_t>(1, 0);
  107.  
  108.     auto rx_stream = usrp->get_rx_stream(stream_args);
  109.  
  110.     uhd::stream_cmd_t start_stream_cmd(
  111.             uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
  112.     start_stream_cmd.stream_now = true;
  113.     start_stream_cmd.num_samps = 0;
  114.     // create the stream
  115.     LOG_DEBUG << "Rx streaming started..." << newl;
  116.     rx_stream->issue_stream_cmd(start_stream_cmd);
  117.     //let the main (tx) thread know we're aquiring now
  118.     mutex.unlock();
  119.  
  120.     size_t acquired = 0;
  121.     uhd::rx_metadata_t rx_metadata;
  122.     while (acquired < count) {
  123.         acquired += rx_stream->recv(&iq_data.at(acquired), 50000, rx_metadata, 1);
  124.         LOG_DEBUG << "Received: " << acquired << newl;
  125.     }
  126.  
  127.     //stop
  128.     uhd::stream_cmd_t stop_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
  129.     stop_cmd.stream_now = true;
  130.     stop_cmd.num_samps = 0;
  131.     rx_stream->issue_stream_cmd(stop_cmd);
  132.    
  133.     //do a simple tally of consecutive zeros
  134.     bool prev_was_0 = false;    
  135.     size_t zero_count = 0;
  136.     for(auto & elem : iq_data){
  137.         if(elem.real() == 0.0 && elem.imag() == 0){
  138.             if(prev_was_0){
  139.                 zero_count++;
  140.             }
  141.             prev_was_0 = true;
  142.         }
  143.     }
  144.     LOG_DEBUG << "Consecutive zeros count: " << zero_count << newl;
  145.     Dump_to_Py(iq_data, rate, "/home/server/capture.py");
  146. }
  147. //
  148. void Generate_Tone(std::vector<std::complex<float>>&data, double freq,
  149.         double amplitude, double fs, double size) {
  150.  
  151.     data.resize(size);
  152.     for (int i = 0; i < size; i++) {
  153.         double phase = 2 * M_PI * freq / fs*i;
  154.         data.at(i) = std::complex<float>(amplitude * std::cos(phase),
  155.                 amplitude * std::sin(phase));
  156.     }
  157. }
  158.  
  159. //
  160. void Dump_to_Py(std::vector<std::complex<float> >& data, float rate,
  161.         const std::string& path) {
  162.     FILE* fid = fopen(&path.front(), "w");
  163.  
  164.     fprintf(fid, "import numpy as np\n");
  165.     fprintf(fid, "import pylab as pl\n");
  166.     fprintf(fid, "if(__name__ == \"__main__\"):\n");
  167.     fprintf(fid, "    x = np.zeros(%d, dtype=np.complex64)\n", data.size());
  168.  
  169.     for (int i = 0; i < data.size(); i++) {
  170.         fprintf(fid, "    x[%4u] = %12.4e + 1j*%12.4e\n", i, data.at(i).real()
  171.                 , data.at(i).imag());
  172.     }
  173.     fprintf(fid, "    pl.figure()\n");
  174.     fprintf(fid, "    pl.plot(np.real(x))\n");
  175.     fprintf(fid, "    pl.plot(np.imag(x))\n");
  176.     fprintf(fid, "    pl.show()\n");
  177.     //    fprintf(fid, "    return x, %f\n",rate);
  178.     fclose(fid);
  179. }
Add Comment
Please, Sign In to add comment