/* -*- c++ -*- */ /* * Copyright 2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * * SPDX-License-Identifier: GPL-3.0-or-later * */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include "number_sink_impl.h" #include <gnuradio/fft/fft.h> #include <gnuradio/io_signature.h> #include <qwt_symbol.h> #include <volk/volk.h> #include <cmath> #include <cstring> #ifdef _MSC_VER #define isfinite _finite #include <float.h> namespace std { using ::_finite; } #endif namespace gr { namespace qtgui { number_sink::sptr number_sink::make( size_t itemsize, float average, graph_t graph_type, int nconnections, QWidget* parent) { return gnuradio::make_block_sptr<number_sink_impl>( itemsize, average, graph_type, nconnections, parent); } number_sink_impl::number_sink_impl( size_t itemsize, float average, graph_t graph_type, int nconnections, QWidget* parent) : sync_block("number_sink", io_signature::make(nconnections, nconnections, itemsize), io_signature::make(0, 0, 0)), d_itemsize(itemsize), d_average(average), d_type(graph_type), d_nconnections(nconnections), d_parent(parent), d_avg_value(nconnections), d_iir(nconnections) { for (int n = 0; n < d_nconnections; n++) { d_avg_value[n] = 0; d_iir[n].set_taps(d_average); } // Set alignment properties for VOLK const int alignment_multiple = volk_get_alignment() / d_itemsize; set_alignment(std::max(1, alignment_multiple)); initialize(); } number_sink_impl::~number_sink_impl() {} bool number_sink_impl::check_topology(int ninputs, int noutputs) { return ninputs == d_nconnections; } void number_sink_impl::initialize() { if (qApp != NULL) { d_qApplication = qApp; } else { d_qApplication = new QApplication(d_argc, &d_argv); } d_main_gui = new NumberDisplayForm(d_nconnections, d_type, d_parent); d_main_gui->setAverage(d_average); // initialize update time to 10 times a second set_update_time(0.1); } void number_sink_impl::exec_() { d_qApplication->exec(); } QWidget* number_sink_impl::qwidget() { return d_main_gui; } void number_sink_impl::set_update_time(double t) { // convert update time to ticks gr::high_res_timer_type tps = gr::high_res_timer_tps(); d_main_gui->setUpdateTime(t); d_update_time = t * tps; d_last_time = 0; } void number_sink_impl::set_average(const float avg) { d_average = avg; for (int n = 0; n < d_nconnections; n++) { d_avg_value[n] = 0; d_iir[n].set_taps(d_average); } d_main_gui->setAverage(avg); } void number_sink_impl::set_graph_type(const graph_t type) { d_main_gui->setGraphType(type); } void number_sink_impl::set_color(unsigned int which, const std::string& min, const std::string& max) { d_main_gui->setColor(which, QColor(min.c_str()), QColor(max.c_str())); } void number_sink_impl::set_color(unsigned int which, int min, int max) { d_main_gui->setColor(which, QColor(min), QColor(max)); } void number_sink_impl::set_label(unsigned int which, const std::string& label) { d_main_gui->setLabel(which, label); } void number_sink_impl::set_min(unsigned int which, float min) { d_main_gui->setScaleMin(which, min); } void number_sink_impl::set_max(unsigned int which, float max) { d_main_gui->setScaleMax(which, max); } void number_sink_impl::set_title(const std::string& title) { d_main_gui->setTitle(title); } void number_sink_impl::set_unit(unsigned int which, const std::string& unit) { d_main_gui->setUnit(which, unit); } void number_sink_impl::set_factor(unsigned int which, float factor) { d_main_gui->setFactor(which, factor); } float number_sink_impl::average() const { return d_average; } graph_t number_sink_impl::graph_type() const { return d_main_gui->graphType(); } std::string number_sink_impl::color_min(unsigned int which) const { return d_main_gui->colorMin(which).name().toStdString(); } std::string number_sink_impl::color_max(unsigned int which) const { return d_main_gui->colorMax(which).name().toStdString(); } std::string number_sink_impl::label(unsigned int which) const { return d_main_gui->label(which); } float number_sink_impl::min(unsigned int which) const { return d_main_gui->scaleMin(which); } float number_sink_impl::max(unsigned int which) const { return d_main_gui->scaleMax(which); } std::string number_sink_impl::title() const { return d_main_gui->title(); } std::string number_sink_impl::unit(unsigned int which) const { return d_main_gui->unit(which); } float number_sink_impl::factor(unsigned int which) const { return d_main_gui->factor(which); } void number_sink_impl::enable_menu(bool en) { // d_main_gui->enableMenu(en); } void number_sink_impl::enable_autoscale(bool en) { d_main_gui->autoScale(en); } void number_sink_impl::reset() { gr::thread::scoped_lock lock(d_setlock); _reset(); } void number_sink_impl::_reset() {} void number_sink_impl::_gui_update_trigger() { // Only update the time if different than the current interval // add some slop in cpu ticks for double comparison gr::high_res_timer_type tps = gr::high_res_timer_tps(); double t = d_main_gui->updateTime(); if ((d_update_time < (tps * t - 10)) || ((tps * t + 10) < d_update_time)) { set_update_time(t); } float a = d_main_gui->average(); if (a != d_average) { set_average(a); } } float number_sink_impl::get_item(const void* input_items, int n) { char* inc; short* ins; float* inf; switch (d_itemsize) { case (1): inc = (char*)input_items; return static_cast<float>(inc[n]); break; case (2): ins = (short*)input_items; return static_cast<float>(ins[n]); break; case (4): inf = (float*)input_items; return static_cast<float>(inf[n]); break; default: throw std::runtime_error("item size not supported"); } return 0; } int number_sink_impl::work(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) { gr::thread::scoped_lock lock(d_setlock); _gui_update_trigger(); if (d_average > 0) { for (int n = 0; n < d_nconnections; n++) { for (int i = 0; i < noutput_items; i++) { float x = get_item(input_items[n], i); if (std::isfinite(x)) d_avg_value[n] = d_iir[n].filter(x); } } } // Plot if we are able to update if ((gr::high_res_timer_now() - d_last_time) > d_update_time) { d_last_time = gr::high_res_timer_now(); std::vector<float> d(d_nconnections); if (d_average > 0) { for (int n = 0; n < d_nconnections; n++) d[n] = d_avg_value[n]; } else { for (int n = 0; n < d_nconnections; n++) { float x = get_item(input_items[n], 0); if (std::isfinite(x)) d[n] = x; } } d_qApplication->postEvent(d_main_gui, new NumberUpdateEvent(d)); } return noutput_items; ; } } /* namespace qtgui */ } /* namespace gr */