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