1 /* -*- c++ -*- */
2 /*
3  * Copyright 2015 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include <gnuradio/qtgui/freqcontrolpanel.h>
24 
25 #include <cmath>
26 
FreqControlPanel(FreqDisplayForm * form)27 FreqControlPanel::FreqControlPanel(FreqDisplayForm* form) : QVBoxLayout(), d_parent(form)
28 {
29     // Set up the box for trace items
30     d_trace_box = new QGroupBox("Trace Options");
31     d_trace_layout = new QVBoxLayout;
32     d_maxhold_check = new QCheckBox("Max Hold");
33     d_minhold_check = new QCheckBox("Min Hold");
34 
35     d_avg_layout = new QHBoxLayout;
36     d_avg_label = new QLabel("Avg:");
37     d_slider_max = 100;
38     d_slider_min = 1;
39     d_slider_step = 1;
40     d_avg_slider = new QSlider(Qt::Horizontal);
41     d_avg_slider->setRange(d_slider_min, d_slider_max);
42     d_avg_slider->setTickInterval(d_slider_step);
43     d_avg_slider->setValue(d_slider_max);
44     d_avg_layout->addWidget(d_avg_label);
45     d_avg_layout->addWidget(d_avg_slider);
46 
47     // Set up the box for axis items
48     d_axes_box = new QGroupBox("Axis Options");
49     d_axes_layout = new QVBoxLayout;
50 
51     d_grid_check = new QCheckBox("Grid");
52     d_axislabels_check = new QCheckBox("Axis Labels");
53     d_yrange_layout = new QHBoxLayout;
54     d_yrange_label = new QLabel("Y Range:");
55     d_yrange_plus = new QPushButton("+");
56     d_yrange_minus = new QPushButton("-");
57     d_yrange_plus->setMaximumWidth(30);
58     d_yrange_plus->setMinimumWidth(30);
59     d_yrange_minus->setMaximumWidth(30);
60     d_yrange_minus->setMinimumWidth(30);
61     d_yrange_layout->addWidget(d_yrange_label);
62     d_yrange_layout->addWidget(d_yrange_plus);
63     d_yrange_layout->addWidget(d_yrange_minus);
64 
65     d_ymin_layout = new QHBoxLayout;
66     d_ymin_label = new QLabel("Ref Level:");
67     d_ymin_plus = new QPushButton("+");
68     d_ymin_minus = new QPushButton("-");
69     d_ymin_plus->setMaximumWidth(30);
70     d_ymin_plus->setMinimumWidth(30);
71     d_ymin_minus->setMaximumWidth(30);
72     d_ymin_minus->setMinimumWidth(30);
73     d_ymin_layout->addWidget(d_ymin_label);
74     d_ymin_layout->addWidget(d_ymin_plus);
75     d_ymin_layout->addWidget(d_ymin_minus);
76 
77     d_autoscale_button = new QPushButton("Autoscale");
78 
79 
80     // Set up the box for FFT settings
81     d_fft_box = new QGroupBox("FFT");
82     d_fft_layout = new QVBoxLayout;
83     d_fft_size_combo = new QComboBox();
84     d_fft_size_combo->addItem("32");
85     d_fft_size_combo->addItem("64");
86     d_fft_size_combo->addItem("128");
87     d_fft_size_combo->addItem("256");
88     d_fft_size_combo->addItem("512");
89     d_fft_size_combo->addItem("1024");
90     d_fft_size_combo->addItem("2048");
91     d_fft_size_combo->addItem("4096");
92 
93     d_fft_win_combo = new QComboBox();
94     d_fft_win_combo->addItem("None");
95     d_fft_win_combo->addItem("Hamming");
96     d_fft_win_combo->addItem("Hann");
97     d_fft_win_combo->addItem("Blackman");
98     d_fft_win_combo->addItem("Blackman-harris");
99     d_fft_win_combo->addItem("Rectangular");
100     d_fft_win_combo->addItem("Kaiser");
101     d_fft_win_combo->addItem("Flat-top");
102 
103     // Trigger box setup
104     d_trigger_box = new QGroupBox("Trigger");
105     d_trigger_layout = new QVBoxLayout;
106     d_trigger_mode_combo = new QComboBox();
107     d_trigger_mode_combo->addItem("Free");
108     d_trigger_mode_combo->addItem("Auto");
109     d_trigger_mode_combo->addItem("Normal");
110     d_trigger_mode_combo->addItem("Tag");
111 
112     d_trigger_level_layout = new QHBoxLayout;
113     d_trigger_level_label = new QLabel("Level:");
114     d_trigger_level_plus = new QPushButton("+");
115     d_trigger_level_minus = new QPushButton("-");
116     d_trigger_level_plus->setMaximumWidth(30);
117     d_trigger_level_minus->setMaximumWidth(30);
118     d_trigger_level_layout->addWidget(d_trigger_level_label);
119     d_trigger_level_layout->addWidget(d_trigger_level_plus);
120     d_trigger_level_layout->addWidget(d_trigger_level_minus);
121 
122 
123     // Set up the box for other items
124     d_extras_box = new QGroupBox("Extras");
125     d_extras_layout = new QVBoxLayout;
126     d_stop_button = new QPushButton("Stop");
127     d_stop_button->setCheckable(true);
128 
129     // Set up the boxes into the layout
130     d_trace_layout->addWidget(d_maxhold_check);
131     d_trace_layout->addWidget(d_minhold_check);
132     d_trace_layout->addLayout(d_avg_layout);
133     d_trace_box->setLayout(d_trace_layout);
134 
135     d_axes_layout->addWidget(d_grid_check);
136     d_axes_layout->addWidget(d_axislabels_check);
137     d_axes_layout->addLayout(d_yrange_layout);
138     d_axes_layout->addLayout(d_ymin_layout);
139     d_axes_layout->addWidget(d_autoscale_button);
140     d_axes_box->setLayout(d_axes_layout);
141 
142     d_fft_layout->addWidget(d_fft_size_combo);
143     d_fft_layout->addWidget(d_fft_win_combo);
144     d_fft_box->setLayout(d_fft_layout);
145 
146     d_trigger_layout->addWidget(d_trigger_mode_combo);
147     d_trigger_layout->addLayout(d_trigger_level_layout);
148     d_trigger_box->setLayout(d_trigger_layout);
149 
150     d_extras_layout->addWidget(d_stop_button);
151     d_extras_box->setLayout(d_extras_layout);
152 
153     addWidget(d_trace_box);
154     addWidget(d_axes_box);
155     addWidget(d_fft_box);
156     addWidget(d_trigger_box);
157     addWidget(d_extras_box);
158 
159     addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding));
160 
161     connect(d_maxhold_check, SIGNAL(clicked(bool)), d_parent, SLOT(notifyMaxHold(bool)));
162     connect(d_minhold_check, SIGNAL(clicked(bool)), d_parent, SLOT(notifyMinHold(bool)));
163 
164     connect(d_avg_slider, SIGNAL(valueChanged(int)), this, SLOT(notifyAvgSlider(int)));
165     connect(this, SIGNAL(signalAvgSlider(float)), d_parent, SLOT(setFFTAverage(float)));
166 
167     connect(d_grid_check, SIGNAL(clicked(bool)), d_parent, SLOT(setGrid(bool)));
168 
169     connect(
170         d_axislabels_check, SIGNAL(clicked(bool)), d_parent, SLOT(setAxisLabels(bool)));
171 
172     connect(d_ymin_plus, SIGNAL(pressed(void)), d_parent, SLOT(notifyYAxisPlus(void)));
173     connect(d_ymin_minus, SIGNAL(pressed(void)), d_parent, SLOT(notifyYAxisMinus(void)));
174     connect(d_yrange_plus, SIGNAL(pressed(void)), d_parent, SLOT(notifyYRangePlus(void)));
175     connect(
176         d_yrange_minus, SIGNAL(pressed(void)), d_parent, SLOT(notifyYRangeMinus(void)));
177 
178     connect(
179         d_autoscale_button, SIGNAL(pressed(void)), d_parent, SLOT(autoScaleShot(void)));
180 
181     connect(d_fft_size_combo,
182             SIGNAL(currentIndexChanged(const QString&)),
183             d_parent,
184             SLOT(notifyFFTSize(const QString&)));
185     connect(d_fft_win_combo,
186             SIGNAL(currentIndexChanged(const QString&)),
187             d_parent,
188             SLOT(notifyFFTWindow(const QString&)));
189 
190     connect(d_trigger_mode_combo,
191             SIGNAL(currentIndexChanged(const QString&)),
192             d_parent,
193             SLOT(notifyTriggerMode(const QString&)));
194     connect(d_trigger_level_plus,
195             SIGNAL(pressed(void)),
196             d_parent,
197             SLOT(notifyTriggerLevelPlus()));
198     connect(d_trigger_level_minus,
199             SIGNAL(pressed(void)),
200             d_parent,
201             SLOT(notifyTriggerLevelMinus()));
202 
203     connect(d_stop_button, SIGNAL(pressed(void)), d_parent, SLOT(setStop(void)));
204     connect(
205         this, SIGNAL(signalToggleStopButton(void)), d_stop_button, SLOT(toggle(void)));
206 }
207 
~FreqControlPanel()208 FreqControlPanel::~FreqControlPanel()
209 {
210     removeWidget(d_axes_box);
211     removeWidget(d_trace_box);
212     removeWidget(d_fft_box);
213     removeWidget(d_trigger_box);
214     removeWidget(d_extras_box);
215     delete d_axes_box;
216     delete d_trace_box;
217     delete d_fft_box;
218     delete d_trigger_box;
219     delete d_extras_box;
220 
221     // All other children of the boxes are automatically deleted.
222 }
223 
toggleGrid(bool en)224 void FreqControlPanel::toggleGrid(bool en) { d_grid_check->setChecked(en); }
225 
toggleAxisLabels(bool en)226 void FreqControlPanel::toggleAxisLabels(bool en) { d_axislabels_check->setChecked(en); }
227 
toggleMaxHold(bool en)228 void FreqControlPanel::toggleMaxHold(bool en) { d_maxhold_check->setChecked(en); }
229 
toggleMinHold(bool en)230 void FreqControlPanel::toggleMinHold(bool en) { d_minhold_check->setChecked(en); }
231 
notifyAvgSlider(int val)232 void FreqControlPanel::notifyAvgSlider(int val)
233 {
234     float fval = static_cast<float>(val) / (d_slider_max - d_slider_min + 1);
235     emit signalAvgSlider(fval);
236     emit signalAvg(true);
237 }
238 
setFFTAverage(float val)239 void FreqControlPanel::setFFTAverage(float val)
240 {
241     int slider_val = static_cast<int>(roundf(val * (d_slider_max - d_slider_min + 1)));
242     if (slider_val > d_slider_max)
243         slider_val = d_slider_max;
244     else if (slider_val < d_slider_min)
245         slider_val = d_slider_min;
246     d_avg_slider->setValue(slider_val);
247 }
248 
toggleFFTSize(int val)249 void FreqControlPanel::toggleFFTSize(int val)
250 {
251     int index = static_cast<int>(round(logf(static_cast<float>(val)) / logf(2.0f))) - 5;
252     d_fft_size_combo->setCurrentIndex(index);
253 }
254 
toggleFFTWindow(const gr::filter::firdes::win_type win)255 void FreqControlPanel::toggleFFTWindow(const gr::filter::firdes::win_type win)
256 {
257     if (win == -1)
258         d_fft_win_combo->setCurrentIndex(0);
259     if (win == gr::filter::firdes::WIN_HAMMING)
260         d_fft_win_combo->setCurrentIndex(1);
261     else if (win == gr::filter::firdes::WIN_HANN)
262         d_fft_win_combo->setCurrentIndex(2);
263     else if (win == gr::filter::firdes::WIN_BLACKMAN)
264         d_fft_win_combo->setCurrentIndex(3);
265     else if (win == gr::filter::firdes::WIN_BLACKMAN_hARRIS)
266         d_fft_win_combo->setCurrentIndex(4);
267     else if (win == gr::filter::firdes::WIN_RECTANGULAR)
268         d_fft_win_combo->setCurrentIndex(5);
269     else if (win == gr::filter::firdes::WIN_KAISER)
270         d_fft_win_combo->setCurrentIndex(6);
271     else if (win == gr::filter::firdes::WIN_FLATTOP)
272         d_fft_win_combo->setCurrentIndex(7);
273 }
274 
toggleTriggerMode(gr::qtgui::trigger_mode mode)275 void FreqControlPanel::toggleTriggerMode(gr::qtgui::trigger_mode mode)
276 {
277     d_trigger_mode_combo->setCurrentIndex(static_cast<int>(mode));
278 }
279 
toggleStopButton()280 void FreqControlPanel::toggleStopButton() { emit signalToggleStopButton(); }
281