1 /* -*- c++ -*- */
2 /*
3 * Copyright 2012,2014 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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include "vector_sink_f_impl.h"
28
29 #include <gnuradio/io_signature.h>
30 #include <gnuradio/prefs.h>
31
32 #include <qwt_symbol.h>
33 #include <volk/volk.h>
34
35 #include <string.h>
36
37 namespace gr {
38 namespace qtgui {
39
40 static const std::string MSG_PORT_OUT_XVAL = "xval";
41
make(unsigned int vlen,double x_start,double x_step,const std::string & x_axis_label,const std::string & y_axis_label,const std::string & name,int nconnections,QWidget * parent)42 vector_sink_f::sptr vector_sink_f::make(unsigned int vlen,
43 double x_start,
44 double x_step,
45 const std::string& x_axis_label,
46 const std::string& y_axis_label,
47 const std::string& name,
48 int nconnections,
49 QWidget* parent)
50 {
51 return gnuradio::get_initial_sptr(new vector_sink_f_impl(
52 vlen, x_start, x_step, x_axis_label, y_axis_label, name, nconnections, parent));
53 }
54
vector_sink_f_impl(unsigned int vlen,double x_start,double x_step,const std::string & x_axis_label,const std::string & y_axis_label,const std::string & name,int nconnections,QWidget * parent)55 vector_sink_f_impl::vector_sink_f_impl(unsigned int vlen,
56 double x_start,
57 double x_step,
58 const std::string& x_axis_label,
59 const std::string& y_axis_label,
60 const std::string& name,
61 int nconnections,
62 QWidget* parent)
63 : sync_block("vector_sink_f",
64 io_signature::make(1, -1, sizeof(float) * vlen),
65 io_signature::make(0, 0, 0)),
66 d_vlen(vlen),
67 d_vecavg(1.0),
68 d_name(name),
69 d_nconnections(nconnections),
70 d_port(pmt::mp(MSG_PORT_OUT_XVAL)),
71 d_msg(pmt::mp("x")),
72 d_parent(parent)
73 {
74 // Required now for Qt; argc must be greater than 0 and argv
75 // must have at least one valid character. Must be valid through
76 // life of the qApplication:
77 // http://harmattan-dev.nokia.com/docs/library/html/qt4/qapplication.html
78 d_argc = 1;
79 d_argv = new char;
80 d_argv[0] = '\0';
81
82 // setup output message port to post frequency when display is
83 // double-clicked
84 message_port_register_out(d_port);
85
86 d_main_gui = NULL;
87
88 for (int i = 0; i < d_nconnections; i++) {
89 d_magbufs.push_back(
90 (double*)volk_malloc(d_vlen * sizeof(double), volk_get_alignment()));
91 memset(d_magbufs[i], 0, d_vlen * sizeof(double));
92 }
93
94 initialize(name, x_axis_label, y_axis_label, x_start, x_step);
95 }
96
~vector_sink_f_impl()97 vector_sink_f_impl::~vector_sink_f_impl()
98 {
99 if (!d_main_gui->isClosed()) {
100 d_main_gui->close();
101 }
102
103 for (int i = 0; i < d_nconnections; i++) {
104 volk_free(d_magbufs[i]);
105 }
106
107 delete d_argv;
108 }
109
check_topology(int ninputs,int noutputs)110 bool vector_sink_f_impl::check_topology(int ninputs, int noutputs)
111 {
112 return ninputs == d_nconnections;
113 }
114
initialize(const std::string & name,const std::string & x_axis_label,const std::string & y_axis_label,double x_start,double x_step)115 void vector_sink_f_impl::initialize(const std::string& name,
116 const std::string& x_axis_label,
117 const std::string& y_axis_label,
118 double x_start,
119 double x_step)
120 {
121 if (qApp != NULL) {
122 d_qApplication = qApp;
123 } else {
124 #if QT_VERSION >= 0x040500 && QT_VERSION < 0x050000
125 std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
126 QApplication::setGraphicsSystem(QString(style.c_str()));
127 #endif
128 d_qApplication = new QApplication(d_argc, &d_argv);
129 }
130
131 // If a style sheet is set in the prefs file, enable it here.
132 check_set_qss(d_qApplication);
133
134 d_main_gui = new VectorDisplayForm(d_nconnections, d_parent);
135 d_main_gui->setVecSize(d_vlen);
136 set_x_axis(x_start, x_step);
137
138 if (!name.empty())
139 set_title(name);
140 set_x_axis_label(x_axis_label);
141 set_y_axis_label(y_axis_label);
142
143 // initialize update time to 10 times a second
144 set_update_time(0.1);
145 }
146
exec_()147 void vector_sink_f_impl::exec_() { d_qApplication->exec(); }
148
qwidget()149 QWidget* vector_sink_f_impl::qwidget() { return d_main_gui; }
150
151 #ifdef ENABLE_PYTHON
pyqwidget()152 PyObject* vector_sink_f_impl::pyqwidget()
153 {
154 PyObject* w = PyLong_FromVoidPtr((void*)d_main_gui);
155 PyObject* retarg = Py_BuildValue("N", w);
156 return retarg;
157 }
158 #else
pyqwidget()159 void* vector_sink_f_impl::pyqwidget() { return NULL; }
160 #endif
161
vlen() const162 unsigned int vector_sink_f_impl::vlen() const { return d_vlen; }
163
set_vec_average(const float avg)164 void vector_sink_f_impl::set_vec_average(const float avg)
165 {
166 if (avg < 0 || avg > 1.0) {
167 GR_LOG_ALERT(d_logger,
168 "Invalid average value received in set_vec_average(), must be "
169 "within [0, 1].");
170 return;
171 }
172 d_main_gui->setVecAverage(avg);
173 d_vecavg = avg;
174 }
175
vec_average() const176 float vector_sink_f_impl::vec_average() const { return d_vecavg; }
177
set_x_axis(const double start,const double step)178 void vector_sink_f_impl::set_x_axis(const double start, const double step)
179 {
180 d_main_gui->setXaxis(start, step);
181 }
182
set_y_axis(double min,double max)183 void vector_sink_f_impl::set_y_axis(double min, double max)
184 {
185 d_main_gui->setYaxis(min, max);
186 }
187
set_ref_level(double ref_level)188 void vector_sink_f_impl::set_ref_level(double ref_level)
189 {
190 d_main_gui->setRefLevel(ref_level);
191 }
192
set_x_axis_label(const std::string & label)193 void vector_sink_f_impl::set_x_axis_label(const std::string& label)
194 {
195 d_main_gui->setXAxisLabel(label.c_str());
196 }
197
set_y_axis_label(const std::string & label)198 void vector_sink_f_impl::set_y_axis_label(const std::string& label)
199 {
200 d_main_gui->setYAxisLabel(label.c_str());
201 }
202
set_x_axis_units(const std::string & units)203 void vector_sink_f_impl::set_x_axis_units(const std::string& units)
204 {
205 d_main_gui->getPlot()->setXAxisUnit(units.c_str());
206 }
207
set_y_axis_units(const std::string & units)208 void vector_sink_f_impl::set_y_axis_units(const std::string& units)
209 {
210 d_main_gui->getPlot()->setYAxisUnit(units.c_str());
211 }
212
set_update_time(double t)213 void vector_sink_f_impl::set_update_time(double t)
214 {
215 // convert update time to ticks
216 gr::high_res_timer_type tps = gr::high_res_timer_tps();
217 d_update_time = t * tps;
218 d_main_gui->setUpdateTime(t);
219 d_last_time = 0;
220 }
221
set_title(const std::string & title)222 void vector_sink_f_impl::set_title(const std::string& title)
223 {
224 d_main_gui->setTitle(title.c_str());
225 }
226
set_line_label(unsigned int which,const std::string & label)227 void vector_sink_f_impl::set_line_label(unsigned int which, const std::string& label)
228 {
229 d_main_gui->setLineLabel(which, label.c_str());
230 }
231
set_line_color(unsigned int which,const std::string & color)232 void vector_sink_f_impl::set_line_color(unsigned int which, const std::string& color)
233 {
234 d_main_gui->setLineColor(which, color.c_str());
235 }
236
set_line_width(unsigned int which,int width)237 void vector_sink_f_impl::set_line_width(unsigned int which, int width)
238 {
239 d_main_gui->setLineWidth(which, width);
240 }
241
set_line_style(unsigned int which,int style)242 void vector_sink_f_impl::set_line_style(unsigned int which, int style)
243 {
244 d_main_gui->setLineStyle(which, (Qt::PenStyle)style);
245 }
246
set_line_marker(unsigned int which,int marker)247 void vector_sink_f_impl::set_line_marker(unsigned int which, int marker)
248 {
249 d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker);
250 }
251
set_line_alpha(unsigned int which,double alpha)252 void vector_sink_f_impl::set_line_alpha(unsigned int which, double alpha)
253 {
254 d_main_gui->setMarkerAlpha(which, (int)(255.0 * alpha));
255 }
256
set_size(int width,int height)257 void vector_sink_f_impl::set_size(int width, int height)
258 {
259 d_main_gui->resize(QSize(width, height));
260 }
261
title()262 std::string vector_sink_f_impl::title() { return d_main_gui->title().toStdString(); }
263
line_label(unsigned int which)264 std::string vector_sink_f_impl::line_label(unsigned int which)
265 {
266 return d_main_gui->lineLabel(which).toStdString();
267 }
268
line_color(unsigned int which)269 std::string vector_sink_f_impl::line_color(unsigned int which)
270 {
271 return d_main_gui->lineColor(which).toStdString();
272 }
273
line_width(unsigned int which)274 int vector_sink_f_impl::line_width(unsigned int which)
275 {
276 return d_main_gui->lineWidth(which);
277 }
278
line_style(unsigned int which)279 int vector_sink_f_impl::line_style(unsigned int which)
280 {
281 return d_main_gui->lineStyle(which);
282 }
283
line_marker(unsigned int which)284 int vector_sink_f_impl::line_marker(unsigned int which)
285 {
286 return d_main_gui->lineMarker(which);
287 }
288
line_alpha(unsigned int which)289 double vector_sink_f_impl::line_alpha(unsigned int which)
290 {
291 return (double)(d_main_gui->markerAlpha(which)) / 255.0;
292 }
293
enable_menu(bool en)294 void vector_sink_f_impl::enable_menu(bool en) { d_main_gui->enableMenu(en); }
295
enable_grid(bool en)296 void vector_sink_f_impl::enable_grid(bool en) { d_main_gui->setGrid(en); }
297
enable_autoscale(bool en)298 void vector_sink_f_impl::enable_autoscale(bool en) { d_main_gui->autoScale(en); }
299
clear_max_hold()300 void vector_sink_f_impl::clear_max_hold() { d_main_gui->clearMaxHold(); }
301
clear_min_hold()302 void vector_sink_f_impl::clear_min_hold() { d_main_gui->clearMinHold(); }
303
reset()304 void vector_sink_f_impl::reset()
305 {
306 // nop
307 }
308
check_clicked()309 void vector_sink_f_impl::check_clicked()
310 {
311 if (d_main_gui->checkClicked()) {
312 double xval = d_main_gui->getClickedXVal();
313 message_port_pub(d_port, pmt::cons(d_msg, pmt::from_double(xval)));
314 }
315 }
316
work(int noutput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)317 int vector_sink_f_impl::work(int noutput_items,
318 gr_vector_const_void_star& input_items,
319 gr_vector_void_star& output_items)
320 {
321 const float* in = (const float*)input_items[0];
322
323 // See if we generate a message
324 check_clicked();
325
326 for (int i = 0; i < noutput_items; i++) {
327 if (gr::high_res_timer_now() - d_last_time > d_update_time) {
328 for (int n = 0; n < d_nconnections; n++) {
329 in = ((const float*)input_items[n]) + d_vlen;
330 for (unsigned int x = 0; x < d_vlen; x++) {
331 d_magbufs[n][x] =
332 (double)((1.0 - d_vecavg) * d_magbufs[n][x] + (d_vecavg)*in[x]);
333 }
334 }
335 d_last_time = gr::high_res_timer_now();
336 d_qApplication->postEvent(d_main_gui, new FreqUpdateEvent(d_magbufs, d_vlen));
337 }
338 }
339
340 return noutput_items;
341 }
342
343 } /* namespace qtgui */
344 } /* namespace gr */
345