[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
*
- [Commit-gnuradio] [gnuradio] branch master updated (1aface8 -> f8a84eb), git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 03/21: grc: disconnect hidden blocks, git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 01/21: blocks: Add Complex to IChar block, git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 13/21: qtgui: time display: fixes a threading issue., git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 02/21: grc: fix port placement for hidden ports, git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 06/21: qtgui: whitespace and line formatting, git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 12/21: qtgui: histogram plotter supports PDU message plotting., git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 08/21: qtgui: Better support for waterfall PDU message port.,
git <=
- [Commit-gnuradio] [gnuradio] 05/21: qtgui: added documentation describing pdus message input port., git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 04/21: qtgui: Throw an error if the PDU is not a multiple of the fft size., git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 17/21: Merge branch 'maint', git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 18/21: Merge remote-tracking branch 'miek/complex-to-ichar', git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 20/21: Merge branch 'maint', git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 11/21: qtgui: time raster plotters support PDU message plotting., git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 09/21: qtgui: constellation plotter supports PDU message plotting., git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 21/21: Merge remote-tracking branch 'tom/qtgui/pdu_handling', git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 15/21: qtgui: documenting message input support., git, 2015/10/30
- [Commit-gnuradio] [gnuradio] 07/21: qtgui: freq plotters support PDU message plotting., git, 2015/10/30