diff options
author | Tom Rondeau <trondeau@vt.edu> | 2012-07-24 09:49:53 -0400 |
---|---|---|
committer | Tom Rondeau <trondeau@vt.edu> | 2012-07-24 09:53:02 -0400 |
commit | 582dc9b920918b2589e97679dcc0e2fbecb12aa2 (patch) | |
tree | ceccfe2695e9e6407029401bc0cb38220bbdaab6 /gr-qtgui | |
parent | 303489b78f95b6b3e6cd80a466c141fafecd4191 (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.cc | 24 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfall_sink_c_impl.h | 1 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfall_sink_f_impl.cc | 31 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfall_sink_f_impl.h | 1 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfalldisplayform.cc | 29 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfalldisplayform.h | 5 |
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 */ |