commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 08/21: qtgui: Better support for waterfall


From: git
Subject: [Commit-gnuradio] [gnuradio] 08/21: qtgui: Better support for waterfall PDU message port.
Date: Fri, 30 Oct 2015 21:11:26 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch master
in repository gnuradio.

commit 933173593354c88e6ad03c28656340fb6f619ea6
Author: Tom Rondeau <address@hidden>
Date:   Mon Oct 26 12:22:32 2015 -0400

    qtgui: Better support for waterfall PDU message port.
    
    Handles changes in FFT size and half frequency display for float
    version.
---
 .../include/gnuradio/qtgui/waterfallGlobalData.h   |   3 +-
 gr-qtgui/lib/WaterfallDisplayPlot.cc               |  39 ++++++--
 gr-qtgui/lib/waterfallGlobalData.cc                |  10 +-
 gr-qtgui/lib/waterfall_sink_c_impl.cc              | 103 ++++++++++++++-------
 gr-qtgui/lib/waterfall_sink_c_impl.h               |   2 +-
 gr-qtgui/lib/waterfall_sink_f_impl.cc              |  97 ++++++++++++-------
 gr-qtgui/lib/waterfall_sink_f_impl.h               |   2 +-
 7 files changed, 173 insertions(+), 83 deletions(-)

diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfallGlobalData.h 
b/gr-qtgui/include/gnuradio/qtgui/waterfallGlobalData.h
index 8ab9590..b0326b9 100644
--- a/gr-qtgui/include/gnuradio/qtgui/waterfallGlobalData.h
+++ b/gr-qtgui/include/gnuradio/qtgui/waterfallGlobalData.h
@@ -40,7 +40,8 @@ public:
   virtual void reset();
   virtual void copy(const WaterfallData*);
 
-  virtual void resizeData(const double, const double, const uint64_t);
+  virtual void resizeData(const double, const double,
+                          const uint64_t, const int history=0);
 
   virtual QwtRasterData *copy() const;
 
diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc 
b/gr-qtgui/lib/WaterfallDisplayPlot.cc
index 19da4d1..676e407 100644
--- a/gr-qtgui/lib/WaterfallDisplayPlot.cc
+++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc
@@ -210,7 +210,8 @@ void
 WaterfallDisplayPlot::resetAxis()
 {
   for(int i = 0; i < d_nplots; i++) {
-    d_data[i]->resizeData(d_start_frequency, d_stop_frequency, d_numPoints);
+    d_data[i]->resizeData(d_start_frequency, d_stop_frequency,
+                          d_numPoints, d_nrows);
     d_data[i]->reset();
   }
 
@@ -287,16 +288,34 @@ WaterfallDisplayPlot::plotNewData(const 
std::vector<double*> dataPoints,
   int64_t _in_index = d_half_freq ? _npoints_in : 0;
 
   if(!d_stop) {
-    if(numDataPoints > 0 && timestamp == 0){
-      d_numPoints = numDataPoints/d_nrows;
+    if(_npoints_in > 0 && timestamp == 0){
+      d_numPoints = _npoints_in/d_nrows;
       resetAxis();
 
-      //you got an entire waterfall plot, just plot it
-      for(int i = 0; i < d_nplots; i++) {
-        d_data[i]->setSpectrumDataBuffer(dataPoints[i]);
-        d_data[i]->setNumLinesToUpdate(0);
-        d_spectrogram[i]->invalidateCache();
-        d_spectrogram[i]->itemChanged();
+      // If not displaying just the positive half of the spectrum,
+      // plot the full thing now.
+      if(!d_half_freq) {
+        for(int i = 0; i < d_nplots; i++) {
+          d_data[i]->setSpectrumDataBuffer(dataPoints[i]);
+          d_data[i]->setNumLinesToUpdate(0);
+          d_spectrogram[i]->invalidateCache();
+          d_spectrogram[i]->itemChanged();
+        }
+      }
+
+      // Otherwise, loop through our input data vector and only plot
+      // the second half of each row.
+      else {
+        for(int i = 0; i < d_nplots; i++) {
+          d_data[i]->setSpectrumDataBuffer(&(dataPoints[i][d_numPoints]));
+          for(int n = 1; n < d_nrows; n++) {
+            d_data[i]->addFFTData(&(dataPoints[i][d_numPoints + 
2*n*d_numPoints]),
+                                  d_numPoints, 0);
+            d_data[i]->incrementNumLinesToUpdate();
+          }
+          d_spectrogram[i]->invalidateCache();
+          d_spectrogram[i]->itemChanged();
+        }
       }
 
       QwtTimeScaleDraw* timeScale = 
(QwtTimeScaleDraw*)axisScaleDraw(QwtPlot::yLeft);
@@ -309,7 +328,7 @@ WaterfallDisplayPlot::plotNewData(const 
std::vector<double*> dataPoints,
       replot();
     }
 
-    else if(numDataPoints > 0) {
+    else if(_npoints_in > 0) {
       if(_npoints_in != d_numPoints) {
         d_numPoints = _npoints_in;
         resetAxis();
diff --git a/gr-qtgui/lib/waterfallGlobalData.cc 
b/gr-qtgui/lib/waterfallGlobalData.cc
index a7e8db0..5d500e5 100644
--- a/gr-qtgui/lib/waterfallGlobalData.cc
+++ b/gr-qtgui/lib/waterfallGlobalData.cc
@@ -99,8 +99,13 @@ void WaterfallData::copy(const WaterfallData* rhs)
 
 void WaterfallData::resizeData(const double startFreq,
                               const double stopFreq,
-                              const uint64_t fftPoints)
+                              const uint64_t fftPoints,
+                               const int history)
 {
+  if(history > 0) {
+    _historyLength = history;
+  }
+
 #if QWT_VERSION < 0x060000
   if((fftPoints != getNumFFTPoints()) ||
      (boundingRect().width() != (stopFreq - startFreq)) ||
@@ -108,7 +113,7 @@ void WaterfallData::resizeData(const double startFreq,
 
     setBoundingRect(QwtDoubleRect(startFreq, 0,
                                  stopFreq-startFreq,
-                                 boundingRect().height()));
+                                 static_cast<double>(_historyLength)));
     _fftPoints = fftPoints;
     delete[] _spectrumData;
     _spectrumData = new double[_fftPoints * _historyLength];
@@ -120,6 +125,7 @@ void WaterfallData::resizeData(const double startFreq,
      (interval(Qt::XAxis).minValue() != startFreq)){
 
     setInterval(Qt::XAxis, QwtInterval(startFreq, stopFreq));
+    setInterval(Qt::YAxis, QwtInterval(0, _historyLength));
 
     _fftPoints = fftPoints;
     delete[] _spectrumData;
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc 
b/gr-qtgui/lib/waterfall_sink_c_impl.cc
index f5c6d34..60464f5 100644
--- a/gr-qtgui/lib/waterfall_sink_c_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2012,2014 Free Software Foundation, Inc.
+ * Copyright 2012,2014-2015 Free Software Foundation, Inc.
  *
  * This file is part of GNU Radio
  *
@@ -88,7 +88,7 @@ namespace gr {
                                                        volk_get_alignment()));
         d_magbufs.push_back((double*)volk_malloc(d_fftsize*sizeof(double),
                                                  volk_get_alignment()));
-        memset(d_residbufs[i], 0, d_fftsize*sizeof(float));
+        memset(d_residbufs[i], 0, d_fftsize*sizeof(gr_complex));
         memset(d_magbufs[i], 0, d_fftsize*sizeof(double));
       }
 
@@ -444,12 +444,18 @@ namespace gr {
           memset(d_magbufs[i], 0, newfftsize*sizeof(double));
         }
 
-        
d_residbufs.push_back((gr_complex*)volk_malloc(d_fftsize*sizeof(gr_complex),
-                                                       volk_get_alignment()));
-        d_pdu_magbuf = (double*)volk_malloc(d_fftsize*sizeof(double)*d_nrows, 
volk_get_alignment());
-        d_magbufs.push_back(d_pdu_magbuf);
-        memset(d_pdu_magbuf, 0, d_fftsize*sizeof(double)*d_nrows);
-        memset(d_residbufs[d_nconnections], 0, d_fftsize*sizeof(gr_complex));
+        // Handle the PDU buffers separately because of the different
+        // size requirement of the pdu_magbuf.
+        volk_free(d_residbufs[d_nconnections]);
+        volk_free(d_pdu_magbuf);
+
+        d_residbufs[d_nconnections] = 
(gr_complex*)volk_malloc(newfftsize*sizeof(gr_complex),
+                                                               
volk_get_alignment());
+        d_pdu_magbuf = (double*)volk_malloc(newfftsize*sizeof(double)*d_nrows,
+                                            volk_get_alignment());
+        d_magbufs[d_nconnections] = d_pdu_magbuf;
+        memset(d_residbufs[d_nconnections], 0, newfftsize*sizeof(gr_complex));
+        memset(d_pdu_magbuf, 0, newfftsize*sizeof(double)*d_nrows);
 
         // Set new fft size and reset buffer index
         // (throws away any currently held data, but who cares?)
@@ -467,6 +473,8 @@ namespace gr {
         d_fbuf = (float*)volk_malloc(d_fftsize*sizeof(float),
                                      volk_get_alignment());
         memset(d_fbuf, 0, d_fftsize*sizeof(float));
+
+        d_last_time = 0;
       }
     }
 
@@ -560,57 +568,81 @@ namespace gr {
     void
     waterfall_sink_c_impl::handle_pdus(pmt::pmt_t msg)
     {
-      int j = 0;
-      size_t len = 0;
+      size_t len;
       size_t start = 0;
-      if(pmt::is_pair(msg)) {
-        pmt::pmt_t dict = pmt::car(msg);
-        pmt::pmt_t samples = pmt::cdr(msg);
+      pmt::pmt_t dict, samples;
 
-        len = pmt::length(samples);
-        if(len % d_fftsize != 0) {
-          throw std::runtime_error("waterfall_sink_c::handle_pdus: PDU must be 
"
-                                   "a multiple of the FFT size.");
-        }
+      // Test to make sure this is either a PDU or a uniform vector of
+      // samples. Get the samples PMT and the dictionary if it's a PDU.
+      // If not, we throw an error and exit.
+      if(pmt::is_pair(msg)) {
+        dict = pmt::car(msg);
+        samples = pmt::cdr(msg);
 
         pmt::pmt_t start_key = pmt::string_to_symbol("start");
         if(pmt::dict_has_key(dict, start_key)) {
           start = pmt::to_uint64(pmt::dict_ref(dict, start_key, pmt::PMT_NIL));
         }
+      }
+      else if(pmt::is_uniform_vector(msg)) {
+        samples = msg;
+      }
+      else {
+        throw std::runtime_error("time_sink_c: message must be either "
+                                 "a PDU or a uniform vector of samples.");
+      }
 
-        gr::high_res_timer_type ref_start = (uint64_t)start * 
(double)(1.0/d_bandwidth) * 1000000;
+      len = pmt::length(samples);
 
-        const gr_complex *in;
-        if(pmt::is_c32vector(samples)) {
-          in = (const gr_complex*)pmt::c32vector_elements(samples, len);
-        }
-        else {
-          throw std::runtime_error("waterfall_sink_c: unknown data type "
-                                   "of samples; must be complex.");
-        }
+      const gr_complex *in;
+      if(pmt::is_c32vector(samples)) {
+        in = (const gr_complex*)pmt::c32vector_elements(samples, len);
+      }
+      else {
+        throw std::runtime_error("waterfall_sink_c: unknown data type "
+                                 "of samples; must be complex.");
+      }
 
-        int stride = (len - d_fftsize)/d_nrows;
+      // Plot if we're past the last update time
+      if(gr::high_res_timer_now() - d_last_time > d_update_time) {
+        d_last_time = gr::high_res_timer_now();
 
-        set_time_per_fft(1.0/d_bandwidth * stride);
-        std::ostringstream title("");
-        title << "Time (+" << (uint64_t)ref_start << "us)";
-        set_time_title(title.str());
         // Update the FFT size from the application
         fftresize();
         windowreset();
         check_clicked();
 
+        gr::high_res_timer_type ref_start = (uint64_t)start * 
(double)(1.0/d_bandwidth) * 1000000;
+
+        int stride = std::max(0, (int)(len - d_fftsize)/(int)(d_nrows));
+
+        set_time_per_fft(1.0/d_bandwidth * stride);
+        std::ostringstream title("");
+        title << "Time (+" << (uint64_t)ref_start << "us)";
+        set_time_title(title.str());
+
+        int j = 0;
+        size_t min = 0;
+        size_t max = std::min(d_fftsize, static_cast<int>(len));
         for(size_t i=0; j < d_nrows; i+=stride) {
+          // Clear residbufs if len < d_fftsize
+          memset(d_residbufs[d_nconnections], 0x00, 
sizeof(gr_complex)*d_fftsize);
 
-          memcpy(d_residbufs[d_nconnections], &in[j * stride],
-                 sizeof(gr_complex)*d_fftsize);
+          // Copy in as much of the input samples as we can
+          memcpy(d_residbufs[d_nconnections], &in[min], 
sizeof(gr_complex)*(max-min));
 
+          // Apply the window and FFT; copy data into the PDU
+          // magnitude buffer.
           fft(d_fbuf, d_residbufs[d_nconnections], d_fftsize);
           for(int x = 0; x < d_fftsize; x++) {
             d_pdu_magbuf[j * d_fftsize + x] = (double)d_fbuf[x];
           }
-          j++;
 
+          // Increment our indices; set max up to the number of
+          // samples in the input PDU.
+          min += stride;
+          max = std::min(max + stride, len);
+          j++;
         }
 
         //update gui per-pdu
@@ -618,7 +650,6 @@ namespace gr {
                                   new WaterfallUpdateEvent(d_magbufs,
                                                            d_fftsize*d_nrows,
                                                            0));
-
       }
     }
 
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.h 
b/gr-qtgui/lib/waterfall_sink_c_impl.h
index 5fe3574..3e7f9dd 100644
--- a/gr-qtgui/lib/waterfall_sink_c_impl.h
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.h
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2015 Free Software Foundation, Inc.
  *
  * This file is part of GNU Radio
  *
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc 
b/gr-qtgui/lib/waterfall_sink_f_impl.cc
index 90043b9..662c31f 100644
--- a/gr-qtgui/lib/waterfall_sink_f_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2012,2014 Free Software Foundation, Inc.
+ * Copyright 2012,2014-2015 Free Software Foundation, Inc.
  *
  * This file is part of GNU Radio
  *
@@ -452,13 +452,18 @@ namespace gr {
          memset(d_magbufs[i], 0, newfftsize*sizeof(double));
        }
 
-        d_residbufs.push_back((float*)volk_malloc(d_fftsize*sizeof(float),
-                                                  volk_get_alignment()));
-        d_pdu_magbuf = (double*)volk_malloc(d_fftsize*sizeof(double)*d_nrows,
+        // Handle the PDU buffers separately because of the different
+        // size requirement of the pdu_magbuf.
+        volk_free(d_residbufs[d_nconnections]);
+        volk_free(d_pdu_magbuf);
+
+        d_residbufs[d_nconnections] = 
(float*)volk_malloc(newfftsize*sizeof(float),
+                                                          
volk_get_alignment());
+        d_pdu_magbuf = (double*)volk_malloc(newfftsize*sizeof(double)*d_nrows,
                                             volk_get_alignment());
-        d_magbufs.push_back(d_pdu_magbuf);
-        memset(d_pdu_magbuf, 0, d_fftsize*sizeof(double)*d_nrows);
-        memset(d_residbufs[d_nconnections], 0, d_fftsize*sizeof(float));
+        d_magbufs[d_nconnections] = d_pdu_magbuf;
+        memset(d_residbufs[d_nconnections], 0, newfftsize*sizeof(float));
+        memset(d_pdu_magbuf, 0, newfftsize*sizeof(double)*d_nrows);
 
        // Set new fft size and reset buffer index
        // (throws away any currently held data, but who cares?)
@@ -476,6 +481,8 @@ namespace gr {
        d_fbuf = (float*)volk_malloc(d_fftsize*sizeof(float),
                                      volk_get_alignment());
        memset(d_fbuf, 0, d_fftsize*sizeof(float));
+
+        d_last_time = 0;
       }
     }
 
@@ -569,54 +576,80 @@ namespace gr {
     void
     waterfall_sink_f_impl::handle_pdus(pmt::pmt_t msg)
     {
-      int j = 0;
-      size_t len = 0;
+      size_t len;
       size_t start = 0;
-      if(pmt::is_pair(msg)) {
-        pmt::pmt_t dict = pmt::car(msg);
-        pmt::pmt_t samples = pmt::cdr(msg);
+      pmt::pmt_t dict, samples;
 
-        len = pmt::length(samples);
-        if(len % d_fftsize != 0) {
-          throw std::runtime_error("waterfall_sink_f::handle_pdus: PDU must be 
"
-                                   "a multiple of the FFT size.");
-        }
+      // Test to make sure this is either a PDU or a uniform vector of
+      // samples. Get the samples PMT and the dictionary if it's a PDU.
+      // If not, we throw an error and exit.
+      if(pmt::is_pair(msg)) {
+        dict = pmt::car(msg);
+        samples = pmt::cdr(msg);
 
         pmt::pmt_t start_key = pmt::string_to_symbol("start");
         if(pmt::dict_has_key(dict, start_key)) {
           start = pmt::to_uint64(pmt::dict_ref(dict, start_key, pmt::PMT_NIL));
         }
+      }
+      else if(pmt::is_uniform_vector(msg)) {
+        samples = msg;
+      }
+      else {
+        throw std::runtime_error("time_sink_c: message must be either "
+                                 "a PDU or a uniform vector of samples.");
+      }
 
-        gr::high_res_timer_type ref_start = (uint64_t)start * 
(double)(1.0/d_bandwidth) * 1000000;
+      len = pmt::length(samples);
 
-        const float *in;
-        if(pmt::is_f32vector(samples)) {
-          in = (const float*)pmt::f32vector_elements(samples, len);
-        }
-        else {
-          throw std::runtime_error("waterfall sink: unknown data type of 
samples; must be float.");
-        }
+      const float *in;
+      if(pmt::is_f32vector(samples)) {
+        in = (const float*)pmt::f32vector_elements(samples, len);
+      }
+      else {
+        throw std::runtime_error("waterfall sink: unknown data type "
+                                 "of samples; must be float.");
+      }
 
-        int stride = (len - d_fftsize)/(d_nrows-1);
+      // Plot if we're past the last update time
+      if(gr::high_res_timer_now() - d_last_time > d_update_time) {
+        d_last_time = gr::high_res_timer_now();
 
-        set_time_per_fft(1.0/d_bandwidth * stride);
-        std::ostringstream title("");
-        title << "Time (+" << (uint64_t)ref_start << "us)";
-        set_time_title(title.str());
         // Update the FFT size from the application
         fftresize();
         windowreset();
         check_clicked();
 
+        gr::high_res_timer_type ref_start = (uint64_t)start * 
(double)(1.0/d_bandwidth) * 1000000;
+
+        int stride = std::max(0, (int)(len - d_fftsize)/(int)(d_nrows));
+
+        set_time_per_fft(1.0/d_bandwidth * stride);
+        std::ostringstream title("");
+        title << "Time (+" << (uint64_t)ref_start << "us)";
+        set_time_title(title.str());
+
+        int j = 0;
+        size_t min = 0;
+        size_t max = std::min(d_fftsize, static_cast<int>(len));
         for(size_t i=0; j < d_nrows; i+=stride) {
+          // Clear residbufs if len < d_fftsize
+          memset(d_residbufs[d_nconnections], 0x00, sizeof(float)*d_fftsize);
 
-          memcpy(d_residbufs[d_nconnections], &in[j * stride],
-                 sizeof(float)*d_fftsize);
+          // Copy in as much of the input samples as we can
+          memcpy(d_residbufs[d_nconnections], &in[min], 
sizeof(float)*(max-min));
 
+          // Apply the window and FFT; copy data into the PDU
+          // magnitude buffer.
           fft(d_fbuf, d_residbufs[d_nconnections], d_fftsize);
           for(int x = 0; x < d_fftsize; x++) {
             d_pdu_magbuf[j * d_fftsize + x] = (double)d_fbuf[x];
           }
+
+          // Increment our indices; set max up to the number of
+          // samples in the input PDU.
+          min += stride;
+          max = std::min(max + stride, len);
           j++;
         }
 
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h 
b/gr-qtgui/lib/waterfall_sink_f_impl.h
index 68aa5eb..e4f855c 100644
--- a/gr-qtgui/lib/waterfall_sink_f_impl.h
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.h
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2015 Free Software Foundation, Inc.
  *
  * This file is part of GNU Radio
  *



reply via email to

[Prev in Thread] Current Thread [Next in Thread]