summaryrefslogtreecommitdiff
path: root/gr-qtgui
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2012-07-24 09:49:53 -0400
committerTom Rondeau <trondeau@vt.edu>2012-07-24 09:53:02 -0400
commit582dc9b920918b2589e97679dcc0e2fbecb12aa2 (patch)
treececcfe2695e9e6407029401bc0cb38220bbdaab6 /gr-qtgui
parent303489b78f95b6b3e6cd80a466c141fafecd4191 (diff)
qtgui: fixes to waterfall plots.
Fixes number of items returned, a bit of speed improvements, and ability to auto scale through menu.
Diffstat (limited to 'gr-qtgui')
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.cc24
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.h1
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.cc31
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.h1
-rw-r--r--gr-qtgui/lib/waterfalldisplayform.cc29
-rw-r--r--gr-qtgui/lib/waterfalldisplayform.h5
6 files changed, 81 insertions, 10 deletions
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc b/gr-qtgui/lib/waterfall_sink_c_impl.cc
index 5336f6bd15..86ab87e3d8 100644
--- a/gr-qtgui/lib/waterfall_sink_c_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc
@@ -66,11 +66,15 @@ namespace gr {
d_shift = true;
d_fft = new fft::fft_complex(d_fftsize, true);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
d_index = 0;
for(int i = 0; i < d_nconnections; i++) {
d_residbufs.push_back(fft::malloc_complex(d_fftsize));
d_magbufs.push_back(fft::malloc_double(d_fftsize));
+ memset(d_residbufs[i], 0, d_fftsize*sizeof(float));
+ memset(d_magbufs[i], 0, d_fftsize*sizeof(double));
}
buildwindow();
@@ -85,6 +89,7 @@ namespace gr {
fft::free(d_magbufs[i]);
}
delete d_fft;
+ fft::free(d_fbuf);
}
void
@@ -269,6 +274,7 @@ namespace gr {
waterfall_sink_c_impl::fftresize()
{
int newfftsize = d_main_gui->GetFFTSize();
+ d_fftavg = d_main_gui->GetFFTAverage();
if(newfftsize != d_fftsize) {
@@ -279,6 +285,9 @@ namespace gr {
d_residbufs[i] = fft::malloc_complex(newfftsize);
d_magbufs[i] = fft::malloc_double(newfftsize);
+
+ memset(d_residbufs[i], 0, newfftsize*sizeof(gr_complex));
+ memset(d_magbufs[i], 0, newfftsize*sizeof(double));
}
// Set new fft size and reset buffer index
@@ -292,6 +301,10 @@ namespace gr {
// Reset FFTW plan for new size
delete d_fft;
d_fft = new fft::fft_complex(d_fftsize, true);
+
+ fft::free(d_fbuf);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
}
}
@@ -314,16 +327,17 @@ namespace gr {
// If we have enough input for one full FFT, do it
if(datasize >= resid) {
- float *fbuf = fft::malloc_float(d_fftsize);
for(int n = 0; n < d_nconnections; n++) {
// Fill up residbuf with d_fftsize number of items
in = (const gr_complex*)input_items[n];
memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*resid);
- fft(fbuf, d_residbufs[n], d_fftsize);
- volk_32f_convert_64f_a(d_magbufs[n], fbuf, d_fftsize);
+ fft(d_fbuf, d_residbufs[n], d_fftsize);
+ for(int x = 0; x < d_fftsize; x++) {
+ d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]);
+ }
+ //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize);
}
- fft::free(fbuf);
if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
d_last_time = gruel::high_res_timer_now();
@@ -347,7 +361,7 @@ namespace gr {
}
}
- return noutput_items;
+ return j;
}
} /* namespace qtgui */
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.h b/gr-qtgui/lib/waterfall_sink_c_impl.h
index 17c236dd03..506c3f4004 100644
--- a/gr-qtgui/lib/waterfall_sink_c_impl.h
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.h
@@ -55,6 +55,7 @@ namespace gr {
int d_index;
std::vector<gr_complex*> d_residbufs;
std::vector<double*> d_magbufs;
+ float *d_fbuf;
QWidget *d_parent;
WaterfallDisplayForm *d_main_gui;
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc
index e6edb24ef0..a747c99774 100644
--- a/gr-qtgui/lib/waterfall_sink_f_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc
@@ -66,11 +66,15 @@ namespace gr {
d_shift = true;
d_fft = new fft::fft_complex(d_fftsize, true);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
d_index = 0;
for(int i = 0; i < d_nconnections; i++) {
d_residbufs.push_back(fft::malloc_float(d_fftsize));
d_magbufs.push_back(fft::malloc_double(d_fftsize));
+ memset(d_residbufs[i], 0, d_fftsize*sizeof(float));
+ memset(d_magbufs[i], 0, d_fftsize*sizeof(double));
}
buildwindow();
@@ -85,6 +89,7 @@ namespace gr {
fft::free(d_magbufs[i]);
}
delete d_fft;
+ fft::free(d_fbuf);
}
void
@@ -239,6 +244,14 @@ namespace gr {
volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(),
size, 1.0, size);
+
+ // Perform shift operation
+ unsigned int len = (unsigned int)(floor(size/2.0));
+ float *tmp = (float*)malloc(sizeof(float)*len);
+ memcpy(tmp, &data_out[0], sizeof(float)*len);
+ memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len));
+ memcpy(&data_out[size - len], tmp, sizeof(float)*len);
+ free(tmp);
}
void
@@ -275,6 +288,9 @@ namespace gr {
d_residbufs[i] = fft::malloc_float(newfftsize);
d_magbufs[i] = fft::malloc_double(newfftsize);
+
+ memset(d_residbufs[i], 0, newfftsize*sizeof(float));
+ memset(d_magbufs[i], 0, newfftsize*sizeof(double));
}
// Set new fft size and reset buffer index
@@ -288,6 +304,10 @@ namespace gr {
// Reset FFTW plan for new size
delete d_fft;
d_fft = new fft::fft_complex(d_fftsize, true);
+
+ fft::free(d_fbuf);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
}
}
@@ -310,16 +330,17 @@ namespace gr {
// If we have enough input for one full FFT, do it
if(datasize >= resid) {
- float *fbuf = fft::malloc_float(d_fftsize);
for(int n = 0; n < d_nconnections; n++) {
// Fill up residbuf with d_fftsize number of items
in = (const float*)input_items[n];
memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*resid);
- fft(fbuf, d_residbufs[n], d_fftsize);
- volk_32f_convert_64f_a(d_magbufs[n], fbuf, d_fftsize);
+ fft(d_fbuf, d_residbufs[n], d_fftsize);
+ for(int x = 0; x < d_fftsize; x++) {
+ d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]);
+ }
+ //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize);
}
- fft::free(fbuf);
if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
d_last_time = gruel::high_res_timer_now();
@@ -343,7 +364,7 @@ namespace gr {
}
}
- return noutput_items;
+ return j;
}
} /* namespace qtgui */
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h b/gr-qtgui/lib/waterfall_sink_f_impl.h
index 05b5b0bcd4..74f387b7e8 100644
--- a/gr-qtgui/lib/waterfall_sink_f_impl.h
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.h
@@ -56,6 +56,7 @@ namespace gr {
int d_index;
std::vector<float*> d_residbufs;
std::vector<double*> d_magbufs;
+ float *d_fbuf;
QWidget *d_parent;
WaterfallDisplayForm *d_main_gui;
diff --git a/gr-qtgui/lib/waterfalldisplayform.cc b/gr-qtgui/lib/waterfalldisplayform.cc
index 6673ce3ad5..a6000a3009 100644
--- a/gr-qtgui/lib/waterfalldisplayform.cc
+++ b/gr-qtgui/lib/waterfalldisplayform.cc
@@ -41,12 +41,20 @@ WaterfallDisplayForm::WaterfallDisplayForm(int nplots, QWidget* parent)
_fftsize = 1024;
_fftavg = 1.0;
+ _min_val = 1000;
+ _max_val = -1000;
+
+ QAction *autoscale_act = new QAction("Auto Scale", this);
+ autoscale_act->setStatusTip(tr("Autoscale intensity range"));
+ connect(autoscale_act, SIGNAL(triggered()), this, SLOT(AutoScale()));
+
FFTSizeMenu *sizemenu = new FFTSizeMenu(this);
FFTAverageMenu *avgmenu = new FFTAverageMenu(this);
FFTWindowMenu *winmenu = new FFTWindowMenu(this);
_menu->addMenu(sizemenu);
_menu->addMenu(avgmenu);
_menu->addMenu(winmenu);
+ _menu->addAction(autoscale_act);
connect(sizemenu, SIGNAL(whichTrigger(int)),
this, SLOT(SetFFTSize(const int)));
connect(avgmenu, SIGNAL(whichTrigger(float)),
@@ -81,6 +89,18 @@ WaterfallDisplayForm::newData(const QEvent *updateEvent)
const std::vector<double*> dataPoints = event->getPoints();
const uint64_t numDataPoints = event->getNumDataPoints();
const gruel::high_res_timer_type dataTimestamp = event->getDataTimestamp();
+
+ _min_val = 1000;
+ _max_val = -1000;
+ for(size_t i=0; i < dataPoints.size(); i++) {
+ double *min_val = std::min_element(&dataPoints[i][0], &dataPoints[i][numDataPoints-1]);
+ double *max_val = std::max_element(&dataPoints[i][0], &dataPoints[i][numDataPoints-1]);
+ if(*min_val < _min_val)
+ _min_val = *min_val;
+ if(*max_val > _max_val)
+ _max_val = *max_val;
+ }
+
getPlot()->PlotNewData(dataPoints, numDataPoints,
d_update_time, dataTimestamp, 0);
}
@@ -161,3 +181,12 @@ WaterfallDisplayForm::SetIntensityRange(const double minIntensity,
{
getPlot()->SetIntensityRange(minIntensity, maxIntensity);
}
+
+void
+WaterfallDisplayForm::AutoScale()
+{
+ double min_int = _min_val - 5;
+ double max_int = _max_val + 10;
+
+ getPlot()->SetIntensityRange(min_int, max_int);
+}
diff --git a/gr-qtgui/lib/waterfalldisplayform.h b/gr-qtgui/lib/waterfalldisplayform.h
index 0235ddeeeb..03c0e29be7 100644
--- a/gr-qtgui/lib/waterfalldisplayform.h
+++ b/gr-qtgui/lib/waterfalldisplayform.h
@@ -59,6 +59,8 @@ public slots:
void SetIntensityRange(const double minIntensity,
const double maxIntensity);
+ void AutoScale();
+
private slots:
void newData(const QEvent *updateEvent);
@@ -72,6 +74,9 @@ private:
int _fftsize;
float _fftavg;
gr::filter::firdes::win_type _fftwintype;
+
+ double _min_val;
+ double _max_val;
};
#endif /* WATERFALL_DISPLAY_FORM_H */