Cleanup on qwt config to not require qwt includes to be in a subdirectory.
[debian/gnuradio] / gr-qtgui / src / lib / fftdisplay.cc
1 #ifndef FFT_DISPLAY_CC
2 #define FFT_DISPLAY_CC
3
4 #include <qwt_painter.h>
5 #include <qwt_plot_canvas.h>
6 #include <qwt_plot_curve.h>
7 #include <qwt_scale_engine.h>
8 #include <qapplication.h>
9 #include <fftdisplay.h>
10
11 const int fft_display_event::EVENT_TYPE_ID = QEvent::User+100;
12
13 fft_display_event::fft_display_event( std::vector<gr_complex>* fft_data, const float start_frequency, const float stop_frequency):QCustomEvent(fft_display_event::EVENT_TYPE_ID){
14         d_fft_data.resize(fft_data->size());
15         for(unsigned int i = 0; i < fft_data->size(); i++){
16                 d_fft_data[i] = fft_data->operator[](i);
17         }
18         d_start_frequency = start_frequency;
19         d_stop_frequency = stop_frequency;
20 }
21
22 fft_display_event::~fft_display_event(){
23
24 }
25
26 const std::vector<gr_complex>& fft_display_event::get_fft_data() const{
27         return d_fft_data;
28 }
29
30 float fft_display_event::get_start_frequency()const{
31         return d_start_frequency;
32 }
33
34 float fft_display_event::get_stop_frequency()const{
35         return d_stop_frequency;
36 }
37
38 fft_display::fft_display(const unsigned int fft_size, QWidget* parent):
39         QwtPlot(parent)
40 {
41         // Disable polygon clipping
42         QwtPainter::setDeviceClipping(false);
43
44         // We don't need the cache here
45         canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
46         canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
47
48         canvas()->setPaletteBackgroundColor(QColor("white"));
49
50         d_fft_bin_size = fft_size;
51         if(d_fft_bin_size < 1){
52                 d_fft_bin_size = 1;
53         }
54
55         d_start_frequency = 0.0;
56         d_stop_frequency = 4000.0;
57
58         d_fft_data = new std::vector<gr_complex>(d_fft_bin_size);
59         d_plot_data = new double[d_fft_bin_size];
60         d_x_data = new double[d_fft_bin_size];
61         for( unsigned int i = 0; i < d_fft_bin_size; i++){
62                 d_fft_data->operator[](i) = gr_complex(static_cast<float>(i), 0.0);
63                 d_x_data[i] = d_start_frequency + ((d_stop_frequency-d_start_frequency) / static_cast<float>(d_fft_bin_size)*static_cast<float>(i));
64                 d_plot_data[i] = 1.0;
65         }
66         
67         // Set the Appropriate Axis Scale Engine
68 #warning Pass the axis info as necessary...
69         if(true){
70                 setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
71         }
72         else{
73                 setAxisScaleEngine(QwtPlot::yLeft, new QwtLog10ScaleEngine);
74         }
75
76         QwtPlotCurve* fft_plot_curve = new QwtPlotCurve("FFT Spectrum");
77         fft_plot_curve->attach(this);
78         fft_plot_curve->setPen(QPen(Qt::blue));
79         fft_plot_curve->setRawData(d_x_data, d_plot_data, d_fft_bin_size);
80
81         setTitle("Spectral Display");
82 }
83
84 fft_display::~fft_display(){
85         /* The Qwt objects are destroyed by Qt when their parent is destroyed */
86
87         delete[] d_plot_data;
88         delete[] d_x_data;
89         delete d_fft_data;
90 }
91
92
93 void fft_display::set_data(const std::vector<gr_complex>& input_data){
94         unsigned int min_points = d_fft_data->size();
95         if(min_points < input_data.size()){
96                 min_points = input_data.size();
97         }
98         if(min_points > d_fft_bin_size){
99                 min_points = d_fft_bin_size;
100         }
101         for(unsigned int point = 0; point < min_points; point++){
102                 d_fft_data->operator[](point) = input_data[point];
103         }
104 }
105
106 void fft_display::update_display(){
107
108         // Tell the event loop to display the new data - the event loop handles deleting this object
109         qApp->postEvent(this, new fft_display_event(d_fft_data, d_start_frequency, d_stop_frequency));
110
111 }
112
113 void fft_display::customEvent(QCustomEvent* e){
114         if(e->type() == fft_display_event::EVENT_TYPE_ID){
115                 fft_display_event* fft_display_event_ptr = (fft_display_event*)e;
116                 // Write out the FFT data to the display here
117
118                 gr_complex data_value;
119                 for(unsigned int number = 0; number < fft_display_event_ptr->get_fft_data().size(); number++){
120                         data_value = fft_display_event_ptr->get_fft_data()[number];
121                         d_plot_data[number] = abs(data_value);
122 #warning Add code here for handling magnitude, scaling, etc...
123
124                         d_x_data[number] = d_start_frequency + ((d_stop_frequency-d_start_frequency) / static_cast<float>(d_fft_bin_size)*static_cast<float>(number));
125                 }
126
127                 // Axis 
128                 setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)");
129                 setAxisScale(QwtPlot::xBottom, fft_display_event_ptr->get_start_frequency(), fft_display_event_ptr->get_stop_frequency());
130
131                 setAxisTitle(QwtPlot::yLeft, "Values");
132                 replot();
133         }
134 }
135
136 void fft_display::set_start_frequency(const float new_freq){
137         d_start_frequency = new_freq;
138 }
139
140 float fft_display::get_start_frequency()const{
141         return d_start_frequency;
142 }
143
144 void fft_display::set_stop_frequency(const float new_freq){
145         d_stop_frequency = new_freq;
146 }
147
148 float fft_display::get_stop_frequency()const{
149         return d_stop_frequency;
150 }
151
152 unsigned int fft_display::get_fft_bin_size()const{
153         return d_fft_bin_size;
154 }
155
156
157 #endif /* FFT_DISPLAY_CC */