Add FFT function @ DSO mode
@ -57,5 +57,16 @@
|
||||
<file>icons/start_dis_cn.png</file>
|
||||
<file>icons/settings.png</file>
|
||||
<file>darkstyle/style.qss</file>
|
||||
<file>icons/export.png</file>
|
||||
<file>icons/single.png</file>
|
||||
<file>icons/single_dis.png</file>
|
||||
<file>icons/math.png</file>
|
||||
<file>icons/math_dis.png</file>
|
||||
<file>icons/fft.png</file>
|
||||
<file>icons/Blackman.png</file>
|
||||
<file>icons/Flat_top.png</file>
|
||||
<file>icons/Hamming.png</file>
|
||||
<file>icons/Hann.png</file>
|
||||
<file>icons/Rectangle.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -29,4 +29,10 @@
|
||||
#define begin_element(x) (&x[0])
|
||||
#define end_element(x) (&x[countof(x)])
|
||||
|
||||
enum View_type {
|
||||
TIME_VIEW,
|
||||
FFT_VIEW,
|
||||
ALL_VIEW
|
||||
};
|
||||
|
||||
#endif // DSVIEW_EXTDEF_H
|
||||
|
BIN
DSView/icons/about.png
Normal file → Executable file
Before Width: | Height: | Size: 954 B After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 942 B After Width: | Height: | Size: 919 B |
BIN
DSView/icons/file.png
Normal file → Executable file
Before Width: | Height: | Size: 1012 B After Width: | Height: | Size: 1.8 KiB |
BIN
DSView/icons/file_dis.png
Normal file → Executable file
Before Width: | Height: | Size: 641 B After Width: | Height: | Size: 1.9 KiB |
BIN
DSView/icons/instant.png
Normal file → Executable file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
DSView/icons/measure.png
Normal file → Executable file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 4.0 KiB |
BIN
DSView/icons/measure_dis.png
Normal file → Executable file
Before Width: | Height: | Size: 1002 B After Width: | Height: | Size: 4.0 KiB |
BIN
DSView/icons/params.png
Normal file → Executable file
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 3.4 KiB |
BIN
DSView/icons/params_dis.png
Normal file → Executable file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.4 KiB |
BIN
DSView/icons/protocol.png
Normal file → Executable file
Before Width: | Height: | Size: 967 B After Width: | Height: | Size: 4.1 KiB |
BIN
DSView/icons/protocol_cn.png
Normal file → Executable file
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 3.2 KiB |
BIN
DSView/icons/protocol_dis.png
Normal file → Executable file
Before Width: | Height: | Size: 931 B After Width: | Height: | Size: 4.1 KiB |
BIN
DSView/icons/search-bar.png
Normal file → Executable file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.6 KiB |
BIN
DSView/icons/search-bar_dis.png
Normal file → Executable file
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.6 KiB |
BIN
DSView/icons/start.png
Normal file → Executable file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.1 KiB |
BIN
DSView/icons/stop.png
Normal file → Executable file
Before Width: | Height: | Size: 628 B After Width: | Height: | Size: 2.1 KiB |
BIN
DSView/icons/trigger.png
Normal file → Executable file
Before Width: | Height: | Size: 840 B After Width: | Height: | Size: 4.0 KiB |
BIN
DSView/icons/trigger_dis.png
Normal file → Executable file
Before Width: | Height: | Size: 820 B After Width: | Height: | Size: 4.0 KiB |
BIN
DSView/icons/wiki.png
Normal file → Executable file
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.5 KiB |
@ -1,7 +1,241 @@
|
||||
#include "fftstack.h"
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "mathstack.h"
|
||||
|
||||
FftStack::FftStack()
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#include <pv/data/dso.h>
|
||||
#include <pv/data/dsosnapshot.h>
|
||||
#include <pv/sigsession.h>
|
||||
#include <pv/view/dsosignal.h>
|
||||
|
||||
#define PI 3.1415
|
||||
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
|
||||
const QString MathStack::windows_support[5] = {
|
||||
"Rectangle",
|
||||
"Hann",
|
||||
"Hamming",
|
||||
"Blackman",
|
||||
"Flat_top"
|
||||
};
|
||||
|
||||
const uint64_t MathStack::length_support[5] = {
|
||||
1024,
|
||||
2048,
|
||||
4096,
|
||||
8192,
|
||||
16384,
|
||||
};
|
||||
|
||||
MathStack::MathStack(pv::SigSession &session, int index) :
|
||||
_session(session),
|
||||
_index(index),
|
||||
_dc_ignore(true),
|
||||
_sample_interval(1),
|
||||
_math_state(Init)
|
||||
{
|
||||
}
|
||||
|
||||
MathStack::~MathStack()
|
||||
{
|
||||
_xn.clear();
|
||||
_xk.clear();
|
||||
_power_spectrum.clear();
|
||||
fftw_destroy_plan(_fft_plan);
|
||||
}
|
||||
|
||||
void MathStack::clear()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int MathStack::get_index() const
|
||||
{
|
||||
return _index;
|
||||
}
|
||||
|
||||
uint64_t MathStack::get_sample_num() const
|
||||
{
|
||||
return _sample_num;
|
||||
}
|
||||
|
||||
void MathStack::set_sample_num(uint64_t num)
|
||||
{
|
||||
_sample_num = num;
|
||||
_xn.resize(_sample_num);
|
||||
_xk.resize(_sample_num);
|
||||
_power_spectrum.resize(_sample_num/2+1);
|
||||
_fft_plan = fftw_plan_r2r_1d(_sample_num, _xn.data(), _xk.data(),
|
||||
FFTW_R2HC, FFTW_ESTIMATE);
|
||||
}
|
||||
|
||||
int MathStack::get_windows_index() const
|
||||
{
|
||||
return _windows_index;
|
||||
}
|
||||
|
||||
void MathStack::set_windows_index(int index)
|
||||
{
|
||||
_windows_index = index;
|
||||
}
|
||||
|
||||
bool MathStack::dc_ignored() const
|
||||
{
|
||||
return _dc_ignore;
|
||||
}
|
||||
|
||||
void MathStack::set_dc_ignore(bool ignore)
|
||||
{
|
||||
_dc_ignore = ignore;
|
||||
}
|
||||
|
||||
int MathStack::get_sample_interval() const
|
||||
{
|
||||
return _sample_interval;
|
||||
}
|
||||
|
||||
void MathStack::set_sample_interval(int interval)
|
||||
{
|
||||
_sample_interval = interval;
|
||||
}
|
||||
|
||||
const std::vector<QString> MathStack::get_windows_support() const
|
||||
{
|
||||
std::vector<QString> windows;
|
||||
for (size_t i = 0; i < sizeof(windows_support)/sizeof(windows_support[0]); i++)
|
||||
{
|
||||
windows.push_back(windows_support[i]);
|
||||
}
|
||||
return windows;
|
||||
}
|
||||
|
||||
const std::vector<uint64_t> MathStack::get_length_support() const
|
||||
{
|
||||
std::vector<uint64_t> length;
|
||||
for (size_t i = 0; i < sizeof(length_support)/sizeof(length_support[0]); i++)
|
||||
{
|
||||
length.push_back(length_support[i]);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
const std::vector<double> MathStack::get_fft_spectrum() const
|
||||
{
|
||||
std::vector<double> empty;
|
||||
if (_math_state == Stopped)
|
||||
return _power_spectrum;
|
||||
else
|
||||
return empty;
|
||||
}
|
||||
|
||||
const double MathStack::get_fft_spectrum(uint64_t index) const
|
||||
{
|
||||
if (_math_state == Stopped && index < _power_spectrum.size())
|
||||
return _power_spectrum[index];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MathStack::calc_fft()
|
||||
{
|
||||
_math_state = Running;
|
||||
// Get the dso data
|
||||
boost::shared_ptr<pv::data::Dso> data;
|
||||
boost::shared_ptr<pv::view::DsoSignal> dsoSig;
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
|
||||
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
|
||||
if (dsoSig->get_index() == _index && dsoSig->enabled()) {
|
||||
data = dsoSig->dso_data();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
// Check we have a snapshot of data
|
||||
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
|
||||
data->get_snapshots();
|
||||
if (snapshots.empty())
|
||||
return;
|
||||
_snapshot = snapshots.front();
|
||||
|
||||
if (_snapshot->get_sample_count() < _sample_num*_sample_interval)
|
||||
return;
|
||||
|
||||
// Get the samplerate and start time
|
||||
_start_time = data->get_start_time();
|
||||
_samplerate = data->samplerate();
|
||||
if (_samplerate == 0.0)
|
||||
_samplerate = 1.0;
|
||||
|
||||
// prepare _xn data
|
||||
const double offset = dsoSig->get_zeroValue();
|
||||
const double vscale = dsoSig->get_vDialValue() * dsoSig->get_factor() * DS_CONF_DSO_VDIVS / (1000*255.0);
|
||||
const uint16_t step = _snapshot->get_channel_num() * _sample_interval;
|
||||
const uint8_t *const samples = _snapshot->get_samples(0, _sample_num*_sample_interval-1, _index);
|
||||
double wsum = 0;
|
||||
for (int i = 0; i < _sample_num; i++) {
|
||||
double w = window(i, _windows_index);
|
||||
_xn[i] = ((double)samples[i*step] - offset) * vscale * w;
|
||||
wsum += w;
|
||||
}
|
||||
|
||||
// fft
|
||||
fftw_execute(_fft_plan);
|
||||
|
||||
// calculate power spectrum
|
||||
_power_spectrum[0] = abs(_xk[0])/wsum; /* DC component */
|
||||
for (int k = 1; k < (_sample_num + 1) / 2; ++k) /* (k < N/2 rounded up) */
|
||||
_power_spectrum[k] = sqrt((_xk[k]*_xk[k] + _xk[_sample_num-k]*_xk[_sample_num-k]) * 2) / wsum;
|
||||
if (_sample_num % 2 == 0) /* N is even */
|
||||
_power_spectrum[_sample_num/2] = abs(_xk[_sample_num/2])/wsum; /* Nyquist freq. */
|
||||
|
||||
_math_state = Stopped;
|
||||
}
|
||||
|
||||
double MathStack::window(uint64_t i, int type)
|
||||
{
|
||||
const double n_m_1 = _sample_num-1;
|
||||
switch(type) {
|
||||
case 1: // Hann window
|
||||
return 0.5*(1-cos(2*PI*i/n_m_1));
|
||||
case 2: // Hamming window
|
||||
return 0.54-0.46*cos(2*PI*i/n_m_1);
|
||||
case 3: // Blackman window
|
||||
return 0.42659-0.49656*cos(2*PI*i/n_m_1) + 0.076849*cos(4*PI*i/n_m_1);
|
||||
case 4: // Flat_top window
|
||||
return 1-1.93*cos(2*PI*i/n_m_1)+1.29*cos(4*PI*i/n_m_1)-
|
||||
0.388*cos(6*PI*i/n_m_1)+0.028*cos(8*PI*i/n_m_1);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
@ -1,11 +1,119 @@
|
||||
#ifndef FFTSTACK_H
|
||||
#define FFTSTACK_H
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef DSVIEW_PV_DATA_MATHSTACK_H
|
||||
#define DSVIEW_PV_DATA_MATHSTACK_H
|
||||
|
||||
class FftStack
|
||||
#include "signaldata.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include <fftw3.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
namespace pv {
|
||||
|
||||
class SigSession;
|
||||
|
||||
namespace view {
|
||||
class DsoSignal;
|
||||
}
|
||||
|
||||
namespace data {
|
||||
|
||||
class DsoSnapshot;
|
||||
class Dso;
|
||||
|
||||
class MathStack : public QObject, public SignalData
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
static const QString windows_support[5];
|
||||
static const uint64_t length_support[5];
|
||||
|
||||
public:
|
||||
FftStack();
|
||||
enum math_state {
|
||||
Init,
|
||||
Stopped,
|
||||
Running
|
||||
};
|
||||
|
||||
public:
|
||||
MathStack(pv::SigSession &_session, int index);
|
||||
virtual ~MathStack();
|
||||
void clear();
|
||||
|
||||
int get_index() const;
|
||||
|
||||
uint64_t get_sample_num() const;
|
||||
void set_sample_num(uint64_t num);
|
||||
|
||||
int get_windows_index() const;
|
||||
void set_windows_index(int index);
|
||||
|
||||
const std::vector<QString> get_windows_support() const;
|
||||
const std::vector<uint64_t> get_length_support() const;
|
||||
|
||||
bool dc_ignored() const;
|
||||
void set_dc_ignore(bool ignore);
|
||||
|
||||
int get_sample_interval() const;
|
||||
void set_sample_interval(int interval);
|
||||
|
||||
const std::vector<double> get_fft_spectrum() const;
|
||||
const double get_fft_spectrum(uint64_t index) const;
|
||||
|
||||
void calc_fft();
|
||||
|
||||
double window(uint64_t i, int type);
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
pv::SigSession &_session;
|
||||
|
||||
int _index;
|
||||
uint64_t _sample_num;
|
||||
int _windows_index;
|
||||
bool _dc_ignore;
|
||||
int _sample_interval;
|
||||
|
||||
boost::shared_ptr<pv::data::DsoSnapshot> _snapshot;
|
||||
|
||||
std::unique_ptr<boost::thread> _math_thread;
|
||||
math_state _math_state;
|
||||
|
||||
fftw_plan _fft_plan;
|
||||
std::vector<double> _xn;
|
||||
std::vector<double> _xk;
|
||||
std::vector<double> _power_spectrum;
|
||||
};
|
||||
|
||||
#endif // FFTSTACK_H
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
||||
#endif // DSVIEW_PV_DATA_MATHSTACK_H
|
||||
|
@ -1,7 +1,257 @@
|
||||
/*
|
||||
* This file is part of the DSView project.
|
||||
* DSView is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "fftoptions.h"
|
||||
|
||||
FftOptions::FftOptions()
|
||||
{
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QListWidget>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "../sigsession.h"
|
||||
#include "../data/mathstack.h"
|
||||
#include "../view/trace.h"
|
||||
#include "../view/dsosignal.h"
|
||||
#include "../view/mathtrace.h"
|
||||
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
namespace pv {
|
||||
namespace dialogs {
|
||||
|
||||
FftOptions::FftOptions(QWidget *parent, SigSession &session) :
|
||||
QDialog(parent),
|
||||
_session(session),
|
||||
_button_box(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
|
||||
Qt::Horizontal, this)
|
||||
{
|
||||
_en_checkbox = new QCheckBox(this);
|
||||
_len_combobox = new QComboBox(this);
|
||||
_interval_combobox = new QComboBox(this);
|
||||
_ch_combobox = new QComboBox(this);
|
||||
_window_combobox = new QComboBox(this);
|
||||
_dc_checkbox = new QCheckBox(this);
|
||||
_dc_checkbox->setChecked(true);
|
||||
_view_combobox = new QComboBox(this);
|
||||
_dbv_combobox = new QComboBox(this);
|
||||
|
||||
// setup _ch_combobox
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
|
||||
boost::shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
|
||||
_ch_combobox->addItem(dsoSig->get_name(), qVariantFromValue(dsoSig->get_index()));
|
||||
}
|
||||
}
|
||||
|
||||
// setup _window_combobox _len_combobox
|
||||
_sample_limit = 0;
|
||||
GVariant* gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_MAX_DSO_SAMPLELIMITS);
|
||||
if (gvar != NULL) {
|
||||
_sample_limit = g_variant_get_uint64(gvar) * 0.5;
|
||||
g_variant_unref(gvar);
|
||||
} else {
|
||||
qDebug() << "ERROR: config_get SR_CONF_MAX_DSO_SAMPLELIMITS failed.";
|
||||
}
|
||||
std::vector<QString> windows;
|
||||
std::vector<uint64_t> length;
|
||||
std::vector<QString> view_modes;
|
||||
std::vector<int> dbv_ranges;
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::Trace> t, _session.get_math_signals()) {
|
||||
boost::shared_ptr<view::MathTrace> mathTrace;
|
||||
if (mathTrace = dynamic_pointer_cast<view::MathTrace>(t)) {
|
||||
windows = mathTrace->get_math_stack()->get_windows_support();
|
||||
length = mathTrace->get_math_stack()->get_length_support();
|
||||
view_modes = mathTrace->get_view_modes_support();
|
||||
dbv_ranges = mathTrace->get_dbv_ranges();
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(windows.size() > 0);
|
||||
assert(length.size() > 0);
|
||||
assert(view_modes.size() > 0);
|
||||
assert(dbv_ranges.size() > 0);
|
||||
for (int i = 0; i < windows.size(); i++)
|
||||
{
|
||||
_window_combobox->addItem(windows[i],
|
||||
qVariantFromValue(i));
|
||||
}
|
||||
for (int i = 0; i < length.size(); i++)
|
||||
{
|
||||
if (length[i] < _sample_limit)
|
||||
_len_combobox->addItem(QString::number(length[i]),
|
||||
qVariantFromValue(length[i]));
|
||||
else
|
||||
break;
|
||||
}
|
||||
assert(_len_combobox->count() > 0);
|
||||
_len_combobox->setCurrentIndex(_len_combobox->count()-1);
|
||||
|
||||
const int max_interval = _sample_limit/_len_combobox->currentData().toLongLong();
|
||||
for (int i = 1; i <= max_interval; i*=2)
|
||||
{
|
||||
_interval_combobox->addItem(QString::number(i),
|
||||
qVariantFromValue(i));
|
||||
}
|
||||
for (int i = 0; i < view_modes.size(); i++)
|
||||
{
|
||||
_view_combobox->addItem(view_modes[i],
|
||||
qVariantFromValue(i));
|
||||
}
|
||||
for (int i = 0; i < dbv_ranges.size(); i++)
|
||||
{
|
||||
_dbv_combobox->addItem(QString::number(dbv_ranges[i]),
|
||||
qVariantFromValue(dbv_ranges[i]));
|
||||
}
|
||||
|
||||
// load current settings
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::Trace> t, _session.get_math_signals()) {
|
||||
boost::shared_ptr<view::MathTrace> mathTrace;
|
||||
if (mathTrace = dynamic_pointer_cast<view::MathTrace>(t)) {
|
||||
if (mathTrace->enabled()) {
|
||||
_en_checkbox->setChecked(true);
|
||||
for (int i = 0; i < _ch_combobox->count(); i++) {
|
||||
if (mathTrace->get_index() == _ch_combobox->itemData(i).toInt()) {
|
||||
_ch_combobox->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < _len_combobox->count(); i++) {
|
||||
if (mathTrace->get_math_stack()->get_sample_num() == _len_combobox->itemData(i).toLongLong()) {
|
||||
_len_combobox->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_interval_combobox->clear();
|
||||
const int max_interval = _sample_limit/_len_combobox->currentData().toLongLong();
|
||||
for (int i = 1; i <= max_interval; i*=2)
|
||||
{
|
||||
_interval_combobox->addItem(QString::number(i),
|
||||
qVariantFromValue(i));
|
||||
}
|
||||
for (int i = 0; i < _interval_combobox->count(); i++) {
|
||||
if (mathTrace->get_math_stack()->get_sample_interval() == _interval_combobox->itemData(i).toInt()) {
|
||||
_interval_combobox->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < _dbv_combobox->count(); i++) {
|
||||
if (mathTrace->dbv_range() == _dbv_combobox->itemData(i).toLongLong()) {
|
||||
_dbv_combobox->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_window_combobox->setCurrentIndex(mathTrace->get_math_stack()->get_windows_index());
|
||||
_dc_checkbox->setChecked(mathTrace->get_math_stack()->dc_ignored());
|
||||
_view_combobox->setCurrentIndex(mathTrace->view_mode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_flayout = new QFormLayout();
|
||||
_flayout->addRow(new QLabel(tr("FFT Enable: "), this), _en_checkbox);
|
||||
_flayout->addRow(new QLabel(tr("FFT Length: "), this), _len_combobox);
|
||||
_flayout->addRow(new QLabel(tr("Sample Interval: "), this), _interval_combobox);
|
||||
_flayout->addRow(new QLabel(tr("FFT Source: "), this), _ch_combobox);
|
||||
_flayout->addRow(new QLabel(tr("FFT Window: "), this), _window_combobox);
|
||||
_flayout->addRow(new QLabel(tr("DC Ignored: "), this), _dc_checkbox);
|
||||
_flayout->addRow(new QLabel(tr("Y-axis Mode: "), this), _view_combobox);
|
||||
_flayout->addRow(new QLabel(tr("DBV Range: "), this), _dbv_combobox);
|
||||
|
||||
_hlayout = new QHBoxLayout();
|
||||
_hlayout->addLayout(_flayout);
|
||||
_hint_label = new QLabel(this);
|
||||
QString hint_pic= ":/icons/" + _window_combobox->currentText()+".png";
|
||||
QPixmap pixmap(hint_pic);
|
||||
_hint_label->setPixmap(pixmap);
|
||||
_hlayout->addWidget(_hint_label);
|
||||
|
||||
_layout = new QVBoxLayout(this);
|
||||
_layout->addLayout(_hlayout);
|
||||
_layout->addWidget(&_button_box);
|
||||
setLayout(_layout);
|
||||
|
||||
connect(&_button_box, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(&_button_box, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
connect(_window_combobox, SIGNAL(currentIndexChanged(QString)), this, SLOT(window_changed(QString)));
|
||||
connect(_len_combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(len_changed(int)));
|
||||
}
|
||||
|
||||
void FftOptions::accept()
|
||||
{
|
||||
using namespace Qt;
|
||||
|
||||
QDialog::accept();
|
||||
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::Trace> t, _session.get_math_signals()) {
|
||||
boost::shared_ptr<view::MathTrace> mathTrace;
|
||||
if (mathTrace = dynamic_pointer_cast<view::MathTrace>(t)) {
|
||||
mathTrace->set_enable(false);
|
||||
if (mathTrace->get_index() == _ch_combobox->currentData().toInt()) {
|
||||
mathTrace->get_math_stack()->set_dc_ignore(_dc_checkbox->isChecked());
|
||||
mathTrace->get_math_stack()->set_sample_num(_len_combobox->currentData().toULongLong());
|
||||
mathTrace->get_math_stack()->set_sample_interval(_interval_combobox->currentData().toInt());
|
||||
mathTrace->get_math_stack()->set_windows_index(_window_combobox->currentData().toInt());
|
||||
mathTrace->set_view_mode(_view_combobox->currentData().toInt());
|
||||
//mathTrace->init_zoom();
|
||||
mathTrace->set_dbv_range(_dbv_combobox->currentData().toInt());
|
||||
mathTrace->set_enable(_en_checkbox->isChecked());
|
||||
if (_session.get_capture_state() == SigSession::Stopped &&
|
||||
mathTrace->enabled())
|
||||
mathTrace->get_math_stack()->calc_fft();
|
||||
}
|
||||
}
|
||||
}
|
||||
_session.mathTraces_rebuild();
|
||||
}
|
||||
|
||||
void FftOptions::reject()
|
||||
{
|
||||
using namespace Qt;
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void FftOptions::window_changed(QString str)
|
||||
{
|
||||
QString hint_pic= ":/icons/" + str +".png";
|
||||
QPixmap pixmap(hint_pic);
|
||||
_hint_label->setPixmap(pixmap);
|
||||
}
|
||||
|
||||
void FftOptions::len_changed(int index)
|
||||
{
|
||||
int pre_index = _interval_combobox->currentIndex();
|
||||
_interval_combobox->clear();
|
||||
const int max_interval = _sample_limit/_len_combobox->itemData(index).toLongLong();
|
||||
for (int i = 1; i <= max_interval; i*=2)
|
||||
{
|
||||
_interval_combobox->addItem(QString::number(i),
|
||||
qVariantFromValue(i));
|
||||
}
|
||||
_interval_combobox->setCurrentIndex(pre_index);
|
||||
}
|
||||
|
||||
} // namespace dialogs
|
||||
} // namespace pv
|
||||
|
@ -1,11 +1,87 @@
|
||||
#ifndef FFTOPTIONS_H
|
||||
#define FFTOPTIONS_H
|
||||
/*
|
||||
* This file is part of the DSView project.
|
||||
* DSView is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
class FftOptions
|
||||
#ifndef DSVIEW_PV_FFTOPTIONS_H
|
||||
#define DSVIEW_PV_FFTOPTIONS_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "../device/devinst.h"
|
||||
|
||||
namespace pv {
|
||||
|
||||
class SigSession;
|
||||
|
||||
namespace dialogs {
|
||||
|
||||
class FftOptions : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
|
||||
public:
|
||||
FftOptions();
|
||||
FftOptions(QWidget *parent, SigSession &session);
|
||||
|
||||
protected:
|
||||
void accept();
|
||||
void reject();
|
||||
|
||||
private slots:
|
||||
void window_changed(QString str);
|
||||
void len_changed(int index);
|
||||
|
||||
private:
|
||||
SigSession &_session;
|
||||
uint64_t _sample_limit;
|
||||
|
||||
QComboBox *_len_combobox;
|
||||
QComboBox *_interval_combobox;
|
||||
QCheckBox *_en_checkbox;
|
||||
QComboBox *_ch_combobox;
|
||||
QComboBox *_window_combobox;
|
||||
QCheckBox *_dc_checkbox;
|
||||
QComboBox *_view_combobox;
|
||||
QComboBox *_dbv_combobox;
|
||||
|
||||
QLabel *_hint_label;
|
||||
QFormLayout *_flayout;
|
||||
QHBoxLayout *_hlayout;
|
||||
QVBoxLayout *_layout;
|
||||
QDialogButtonBox _button_box;
|
||||
|
||||
};
|
||||
|
||||
#endif // FFTOPTIONS_H
|
||||
} // namespace dialogs
|
||||
} // namespace pv
|
||||
|
||||
#endif // DSVIEW_PV_FFTOPTIONS_H
|
||||
|
@ -134,7 +134,7 @@ MeasureDock::MeasureDock(QWidget *parent, View &view, SigSession &session) :
|
||||
connect(_t3_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
|
||||
connect(_fen_checkBox, SIGNAL(stateChanged(int)), &_view, SLOT(set_measure_en(int)));
|
||||
connect(_view.get_viewport(), SIGNAL(measure_updated()), this, SLOT(measure_updated()));
|
||||
connect(&_view, SIGNAL(measure_updated()), this, SLOT(measure_updated()));
|
||||
|
||||
this->setWidget(_widget);
|
||||
_widget->setGeometry(0, 0, sizeHint().width(), 2000);
|
||||
@ -222,10 +222,10 @@ void MeasureDock::cursor_update()
|
||||
|
||||
void MeasureDock::measure_updated()
|
||||
{
|
||||
_width_label->setText(_view.get_viewport()->get_measure("width"));
|
||||
_period_label->setText(_view.get_viewport()->get_measure("period"));
|
||||
_freq_label->setText(_view.get_viewport()->get_measure("frequency"));
|
||||
_duty_label->setText(_view.get_viewport()->get_measure("duty"));
|
||||
_width_label->setText(_view.get_measure("width"));
|
||||
_period_label->setText(_view.get_measure("period"));
|
||||
_freq_label->setText(_view.get_measure("frequency"));
|
||||
_duty_label->setText(_view.get_measure("duty"));
|
||||
}
|
||||
|
||||
void MeasureDock::cursor_moved()
|
||||
|
@ -112,6 +112,7 @@ void MainWindow::setup_ui()
|
||||
{
|
||||
setObjectName(QString::fromUtf8("MainWindow"));
|
||||
setMinimumHeight(680);
|
||||
setMinimumWidth(300);
|
||||
resize(1024, 768);
|
||||
|
||||
// Set the window icon
|
||||
@ -129,7 +130,7 @@ void MainWindow::setup_ui()
|
||||
|
||||
// Setup the sampling bar
|
||||
_sampling_bar = new toolbars::SamplingBar(_session, this);
|
||||
_trig_bar = new toolbars::TrigBar(this);
|
||||
_trig_bar = new toolbars::TrigBar(_session, this);
|
||||
_file_bar = new toolbars::FileBar(_session, this);
|
||||
_logo_bar = new toolbars::LogoBar(_session, this);
|
||||
|
||||
@ -295,18 +296,8 @@ void MainWindow::update_device_list()
|
||||
#ifdef ENABLE_DECODE
|
||||
_protocol_widget->del_all_protocol();
|
||||
#endif
|
||||
_trig_bar->close_all();
|
||||
|
||||
if (_session.get_device()->dev_inst()->mode == LOGIC) {
|
||||
_trig_bar->enable_protocol(true);
|
||||
} else {
|
||||
_trig_bar->enable_protocol(false);
|
||||
}
|
||||
if (_session.get_device()->dev_inst()->mode == DSO) {
|
||||
_sampling_bar->enable_toggle(false);
|
||||
} else {
|
||||
_sampling_bar->enable_toggle(true);
|
||||
}
|
||||
_trig_bar->reload();
|
||||
_sampling_bar->reload();
|
||||
|
||||
shared_ptr<pv::device::DevInst> selected_device = _session.get_device();
|
||||
_device_manager.add_device(selected_device);
|
||||
@ -534,8 +525,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
||||
void MainWindow::on_protocol(bool visible)
|
||||
{
|
||||
#ifdef ENABLE_DECODE
|
||||
if (_session.get_device()->dev_inst()->mode == LOGIC)
|
||||
_protocol_dock->setVisible(visible);
|
||||
_protocol_dock->setVisible(visible);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -42,12 +42,14 @@
|
||||
#include "data/decoderstack.h"
|
||||
#include "data/decode/decoder.h"
|
||||
#include "data/decodermodel.h"
|
||||
#include "data/mathstack.h"
|
||||
|
||||
#include "view/analogsignal.h"
|
||||
#include "view/dsosignal.h"
|
||||
#include "view/logicsignal.h"
|
||||
#include "view/groupsignal.h"
|
||||
#include "view/decodetrace.h"
|
||||
#include "view/mathtrace.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdexcept>
|
||||
@ -496,7 +498,6 @@ set< boost::shared_ptr<data::SignalData> > SigSession::get_data() const
|
||||
assert(sig);
|
||||
data.insert(sig->data());
|
||||
}
|
||||
data.insert(_group_data);
|
||||
|
||||
return data;
|
||||
}
|
||||
@ -605,6 +606,12 @@ void SigSession::read_sample_rate(const sr_dev_inst *const sdi)
|
||||
assert(data);
|
||||
data->set_samplerate(sample_rate);
|
||||
}
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> m, _math_traces)
|
||||
{
|
||||
assert(m);
|
||||
m->get_math_stack()->set_samplerate(sample_rate);
|
||||
}
|
||||
_group_data->set_samplerate(sample_rate);
|
||||
}
|
||||
|
||||
void SigSession::feed_in_header(const sr_dev_inst *sdi)
|
||||
@ -791,10 +798,10 @@ void SigSession::init_signals()
|
||||
_signals.clear();
|
||||
vector< boost::shared_ptr<view::Signal> >().swap(_signals);
|
||||
_signals = sigs;
|
||||
|
||||
signals_changed();
|
||||
data_updated();
|
||||
}
|
||||
|
||||
mathTraces_rebuild();
|
||||
data_updated();
|
||||
}
|
||||
|
||||
void SigSession::reload()
|
||||
@ -854,7 +861,7 @@ void SigSession::reload()
|
||||
_signals = sigs;
|
||||
}
|
||||
|
||||
signals_changed();
|
||||
mathTraces_rebuild();
|
||||
}
|
||||
|
||||
void SigSession::refresh(int holdtime)
|
||||
@ -1009,6 +1016,14 @@ void SigSession::feed_in_dso(const sr_datafeed_dso &dso)
|
||||
return;
|
||||
}
|
||||
|
||||
// reset scale of dso signal
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> m, _math_traces)
|
||||
{
|
||||
assert(m);
|
||||
if (m->enabled())
|
||||
m->get_math_stack()->calc_fft();
|
||||
}
|
||||
|
||||
receive_data(dso.num_samples);
|
||||
data_updated();
|
||||
//if (!_instant)
|
||||
@ -1401,7 +1416,41 @@ pv::data::DecoderModel* SigSession::get_decoder_model() const
|
||||
{
|
||||
return _decoder_model;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void SigSession::mathTraces_rebuild()
|
||||
{
|
||||
bool has_dso_signal = false;
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _signals) {
|
||||
boost::shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
|
||||
has_dso_signal = true;
|
||||
// check already have
|
||||
std::vector< boost::shared_ptr<view::MathTrace> >::iterator iter = _math_traces.begin();
|
||||
for(int i = 0; i < _math_traces.size(); i++, iter++)
|
||||
if ((*iter)->get_index() == dsoSig->get_index())
|
||||
break;
|
||||
// if not, rebuild
|
||||
if (iter == _math_traces.end()) {
|
||||
boost::shared_ptr<data::MathStack> math_stack(
|
||||
new data::MathStack(*this, dsoSig->get_index()));
|
||||
boost::shared_ptr<view::MathTrace> math_trace(
|
||||
new view::MathTrace(*this, math_stack, dsoSig->get_index()));
|
||||
_math_traces.push_back(math_trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_dso_signal)
|
||||
_math_traces.clear();
|
||||
|
||||
signals_changed();
|
||||
}
|
||||
|
||||
vector< boost::shared_ptr<view::MathTrace> > SigSession::get_math_signals()
|
||||
{
|
||||
lock_guard<mutex> lock(_signals_mutex);
|
||||
return _math_traces;
|
||||
}
|
||||
|
||||
} // namespace pv
|
||||
|
@ -78,6 +78,7 @@ namespace view {
|
||||
class Signal;
|
||||
class GroupSignal;
|
||||
class DecodeTrace;
|
||||
class MathTrace;
|
||||
}
|
||||
|
||||
namespace decoder {
|
||||
@ -157,6 +158,9 @@ public:
|
||||
|
||||
pv::data::DecoderModel* get_decoder_model() const;
|
||||
|
||||
std::vector< boost::shared_ptr<view::MathTrace> >
|
||||
get_math_signals();
|
||||
|
||||
#endif
|
||||
|
||||
void init_signals();
|
||||
@ -178,6 +182,8 @@ public:
|
||||
|
||||
bool get_data_lock();
|
||||
|
||||
void mathTraces_rebuild();
|
||||
|
||||
private:
|
||||
void set_capture_state(capture_state state);
|
||||
|
||||
@ -239,6 +245,7 @@ private:
|
||||
std::vector< boost::shared_ptr<view::DecodeTrace> > _decode_traces;
|
||||
pv::data::DecoderModel *_decoder_model;
|
||||
#endif
|
||||
std::vector< boost::shared_ptr<view::MathTrace> > _math_traces;
|
||||
|
||||
mutable boost::mutex _data_mutex;
|
||||
boost::shared_ptr<data::Logic> _logic_data;
|
||||
|
@ -96,7 +96,7 @@ FileBar::FileBar(SigSession &session, QWidget *parent) :
|
||||
|
||||
_action_export = new QAction(this);
|
||||
_action_export->setText(QApplication::translate("File", "&Export...", 0));
|
||||
_action_export->setIcon(QIcon::fromTheme("file",QIcon(":/icons/instant.png")));
|
||||
_action_export->setIcon(QIcon::fromTheme("file",QIcon(":/icons/export.png")));
|
||||
_action_export->setObjectName(QString::fromUtf8("actionExport"));
|
||||
connect(_action_export, SIGNAL(triggered()), this, SLOT(on_actionExport_triggered()));
|
||||
|
||||
|
@ -154,8 +154,8 @@ SamplingBar::SamplingBar(SigSession &session, QWidget *parent) :
|
||||
addWidget(&_sample_count);
|
||||
addWidget(new QLabel(tr(" @ ")));
|
||||
addWidget(&_sample_rate);
|
||||
addWidget(&_run_stop_button);
|
||||
addWidget(&_instant_button);
|
||||
_run_stop_action = addWidget(&_run_stop_button);
|
||||
_instant_action = addWidget(&_instant_button);
|
||||
}
|
||||
|
||||
void SamplingBar::set_device_list(
|
||||
@ -785,5 +785,29 @@ void SamplingBar::show_session_error(
|
||||
msg.exec();
|
||||
}
|
||||
|
||||
void SamplingBar::reload()
|
||||
{
|
||||
if (_session.get_device()->dev_inst()->mode == LOGIC) {
|
||||
_icon_instant = QIcon(":/icons/instant.png");
|
||||
_icon_instant_dis = QIcon(":/icons/instant_dis.png");
|
||||
_instant_button.setIcon(_icon_instant);
|
||||
_run_stop_action->setVisible(true);
|
||||
_instant_action->setVisible(true);
|
||||
enable_toggle(true);
|
||||
} else if (_session.get_device()->dev_inst()->mode == ANALOG) {
|
||||
_run_stop_action->setVisible(true);
|
||||
_instant_action->setVisible(false);
|
||||
enable_toggle(true);
|
||||
} else if (_session.get_device()->dev_inst()->mode == DSO) {
|
||||
_icon_instant = QIcon(":/icons/single.png");
|
||||
_icon_instant_dis = QIcon(":/icons/single_dis.png");
|
||||
_instant_button.setIcon(_icon_instant);
|
||||
_run_stop_action->setVisible(true);
|
||||
_instant_action->setVisible(true);
|
||||
enable_toggle(false);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
} // namespace toolbars
|
||||
} // namespace pv
|
||||
|
@ -120,6 +120,7 @@ private slots:
|
||||
public slots:
|
||||
void on_configure();
|
||||
void zero_adj();
|
||||
void reload();
|
||||
|
||||
private:
|
||||
SigSession &_session;
|
||||
@ -145,6 +146,8 @@ private:
|
||||
QIcon _icon_instant_dis;
|
||||
QToolButton _run_stop_button;
|
||||
QToolButton _instant_button;
|
||||
QAction* _run_stop_action;
|
||||
QAction* _instant_action;
|
||||
|
||||
bool _instant;
|
||||
};
|
||||
|
@ -22,19 +22,27 @@
|
||||
|
||||
|
||||
#include "trigbar.h"
|
||||
#include "../sigsession.h"
|
||||
#include "../device/devinst.h"
|
||||
#include "../dialogs/fftoptions.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
namespace pv {
|
||||
namespace toolbars {
|
||||
|
||||
TrigBar::TrigBar(QWidget *parent) :
|
||||
TrigBar::TrigBar(SigSession &session, QWidget *parent) :
|
||||
QToolBar("Trig Bar", parent),
|
||||
_session(session),
|
||||
_enable(true),
|
||||
_trig_button(this),
|
||||
_protocol_button(this),
|
||||
_measure_button(this),
|
||||
_search_button(this)
|
||||
_search_button(this),
|
||||
_math_button(this)
|
||||
{
|
||||
setMovable(false);
|
||||
setContentsMargins(0,0,0,0);
|
||||
|
||||
connect(&_trig_button, SIGNAL(clicked()),
|
||||
this, SLOT(trigger_clicked()));
|
||||
@ -60,6 +68,8 @@ TrigBar::TrigBar(QWidget *parent) :
|
||||
_search_button.setIcon(QIcon::fromTheme("trig",
|
||||
QIcon(":/icons/search-bar_cn.png")));
|
||||
_search_button.setCheckable(true);
|
||||
_math_button.setIcon(QIcon::fromTheme("trig",
|
||||
QIcon(":/icons/math_cn.png")));
|
||||
#else
|
||||
_trig_button.setIcon(QIcon::fromTheme("trig",
|
||||
QIcon(":/icons/trigger.png")));
|
||||
@ -75,12 +85,29 @@ TrigBar::TrigBar(QWidget *parent) :
|
||||
_search_button.setIcon(QIcon::fromTheme("trig",
|
||||
QIcon(":/icons/search-bar.png")));
|
||||
_search_button.setCheckable(true);
|
||||
_math_button.setIcon(QIcon::fromTheme("trig",
|
||||
QIcon(":/icons/math.png")));
|
||||
#endif
|
||||
|
||||
addWidget(&_trig_button);
|
||||
addWidget(&_protocol_button);
|
||||
addWidget(&_measure_button);
|
||||
addWidget(&_search_button);
|
||||
_action_fft = new QAction(this);
|
||||
_action_fft->setText(QApplication::translate(
|
||||
"Math", "&FFT", 0));
|
||||
_action_fft->setIcon(QIcon::fromTheme("Math",
|
||||
QIcon(":/icons/fft.png")));
|
||||
_action_fft->setObjectName(QString::fromUtf8("actionFft"));
|
||||
connect(_action_fft, SIGNAL(triggered()), this, SLOT(on_actionFft_triggered()));
|
||||
|
||||
_math_menu = new QMenu(this);
|
||||
_math_menu->setContentsMargins(0,0,0,0);
|
||||
_math_menu->addAction(_action_fft);
|
||||
_math_button.setPopupMode(QToolButton::InstantPopup);
|
||||
_math_button.setMenu(_math_menu);
|
||||
|
||||
_trig_action = addWidget(&_trig_button);
|
||||
_protocol_action = addWidget(&_protocol_button);
|
||||
_measure_action = addWidget(&_measure_button);
|
||||
_search_action = addWidget(&_search_button);
|
||||
_math_action = addWidget(&_math_button);
|
||||
}
|
||||
|
||||
void TrigBar::protocol_clicked()
|
||||
@ -109,6 +136,7 @@ void TrigBar::enable_toggle(bool enable)
|
||||
_protocol_button.setDisabled(!enable);
|
||||
_measure_button.setDisabled(!enable);
|
||||
_search_button.setDisabled(!enable);
|
||||
_math_button.setDisabled(!enable);
|
||||
|
||||
#ifdef LANGUAGE_ZH_CN
|
||||
_trig_button.setIcon(enable ? QIcon::fromTheme("trig", QIcon(":/icons/trigger_cn.png")) :
|
||||
@ -119,6 +147,8 @@ void TrigBar::enable_toggle(bool enable)
|
||||
QIcon::fromTheme("trig", QIcon(":/icons/measure_dis_cn.png")));
|
||||
_search_button.setIcon(enable ? QIcon::fromTheme("trig", QIcon(":/icons/search-bar_cn.png")) :
|
||||
QIcon::fromTheme("trig", QIcon(":/icons/search-bar_dis_cn.png")));
|
||||
_math_button.setIcon(enable ? QIcon::fromTheme("trig", QIcon(":/icons/math_cn.png")) :
|
||||
QIcon::fromTheme("trig", QIcon(":/icons/math_dis_cn.png")));
|
||||
#else
|
||||
_trig_button.setIcon(enable ? QIcon::fromTheme("trig", QIcon(":/icons/trigger.png")) :
|
||||
QIcon::fromTheme("trig", QIcon(":/icons/trigger_dis.png")));
|
||||
@ -128,6 +158,9 @@ void TrigBar::enable_toggle(bool enable)
|
||||
QIcon::fromTheme("trig", QIcon(":/icons/measure_dis.png")));
|
||||
_search_button.setIcon(enable ? QIcon::fromTheme("trig", QIcon(":/icons/search-bar.png")) :
|
||||
QIcon::fromTheme("trig", QIcon(":/icons/search-bar_dis.png")));
|
||||
_math_button.setIcon(enable ? QIcon::fromTheme("trig", QIcon(":/icons/math.png")) :
|
||||
QIcon::fromTheme("trig", QIcon(":/icons/math_dis.png")));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -163,5 +196,36 @@ void TrigBar::close_all()
|
||||
}
|
||||
}
|
||||
|
||||
void TrigBar::reload()
|
||||
{
|
||||
close_all();
|
||||
if (_session.get_device()->dev_inst()->mode == LOGIC) {
|
||||
_trig_action->setVisible(true);
|
||||
_protocol_action->setVisible(true);
|
||||
_measure_action->setVisible(true);
|
||||
_search_action->setVisible(true);
|
||||
_math_action->setVisible(false);
|
||||
} else if (_session.get_device()->dev_inst()->mode == ANALOG) {
|
||||
_trig_action->setVisible(false);
|
||||
_protocol_action->setVisible(false);
|
||||
_measure_action->setVisible(true);
|
||||
_search_action->setVisible(false);
|
||||
_math_action->setVisible(false);
|
||||
} else if (_session.get_device()->dev_inst()->mode == DSO) {
|
||||
_trig_action->setVisible(true);
|
||||
_protocol_action->setVisible(false);
|
||||
_measure_action->setVisible(true);
|
||||
_search_action->setVisible(false);
|
||||
_math_action->setVisible(true);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void TrigBar::on_actionFft_triggered()
|
||||
{
|
||||
pv::dialogs::FftOptions fft_dlg(this, _session);
|
||||
fft_dlg.exec();
|
||||
}
|
||||
|
||||
} // namespace toolbars
|
||||
} // namespace pv
|
||||
|
@ -26,19 +26,25 @@
|
||||
|
||||
#include <QToolBar>
|
||||
#include <QToolButton>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
||||
namespace pv {
|
||||
|
||||
class SigSession;
|
||||
|
||||
namespace toolbars {
|
||||
|
||||
class TrigBar : public QToolBar
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TrigBar(QWidget *parent = 0);
|
||||
explicit TrigBar(SigSession &session, QWidget *parent = 0);
|
||||
|
||||
void enable_toggle(bool enable);
|
||||
void enable_protocol(bool enable);
|
||||
void close_all();
|
||||
void reload();
|
||||
|
||||
signals:
|
||||
void on_protocol(bool visible);
|
||||
@ -52,12 +58,24 @@ public slots:
|
||||
void measure_clicked();
|
||||
void search_clicked();
|
||||
|
||||
void on_actionFft_triggered();
|
||||
|
||||
private:
|
||||
SigSession& _session;
|
||||
bool _enable;
|
||||
QToolButton _trig_button;
|
||||
QToolButton _protocol_button;
|
||||
QToolButton _measure_button;
|
||||
QToolButton _search_button;
|
||||
QToolButton _math_button;
|
||||
QAction* _trig_action;
|
||||
QAction* _protocol_action;
|
||||
QAction* _measure_action;
|
||||
QAction* _search_action;
|
||||
QAction* _math_action;
|
||||
|
||||
QMenu* _math_menu;
|
||||
QAction* _action_fft;
|
||||
|
||||
};
|
||||
|
||||
|
@ -54,7 +54,7 @@ const float AnalogSignal::EnvelopeThreshold = 256.0f;
|
||||
AnalogSignal::AnalogSignal(boost::shared_ptr<pv::device::DevInst> dev_inst,
|
||||
boost::shared_ptr<data::Analog> data,
|
||||
const sr_channel * const probe) :
|
||||
Signal(dev_inst, probe, SR_CHANNEL_ANALOG),
|
||||
Signal(dev_inst, probe),
|
||||
_data(data)
|
||||
{
|
||||
_colour = SignalColours[probe->index % countof(SignalColours)];
|
||||
|
@ -836,7 +836,7 @@ void DecodeTrace::on_new_decode_data()
|
||||
void DecodeTrace::on_decode_done()
|
||||
{
|
||||
if (_view) {
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
_view->signals_changed();
|
||||
}
|
||||
_session.decode_done();
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "../../extdef.h"
|
||||
#include "dsosignal.h"
|
||||
#include "pv/data/dso.h"
|
||||
#include "pv/data/dsosnapshot.h"
|
||||
@ -106,13 +107,13 @@ const float DsoSignal::EnvelopeThreshold = 256.0f;
|
||||
const double DsoSignal::TrigMargin = 0.02;
|
||||
|
||||
const int DsoSignal::UpMargin = 30;
|
||||
const int DsoSignal::DownMargin = 30;
|
||||
const int DsoSignal::DownMargin = 0;
|
||||
const int DsoSignal::RightMargin = 30;
|
||||
|
||||
DsoSignal::DsoSignal(boost::shared_ptr<pv::device::DevInst> dev_inst,
|
||||
boost::shared_ptr<data::Dso> data,
|
||||
const sr_channel * const probe):
|
||||
Signal(dev_inst, probe, SR_CHANNEL_DSO),
|
||||
Signal(dev_inst, probe),
|
||||
_data(data),
|
||||
_scale(0),
|
||||
_vDialActive(false),
|
||||
@ -167,9 +168,14 @@ boost::shared_ptr<pv::data::SignalData> DsoSignal::data() const
|
||||
return _data;
|
||||
}
|
||||
|
||||
void DsoSignal::set_view(pv::view::View *view)
|
||||
boost::shared_ptr<pv::data::Dso> DsoSignal::dso_data() const
|
||||
{
|
||||
Trace::set_view(view);
|
||||
return _data;
|
||||
}
|
||||
|
||||
void DsoSignal::set_viewport(pv::view::Viewport *viewport)
|
||||
{
|
||||
Trace::set_viewport(viewport);
|
||||
update_zeroPos();
|
||||
|
||||
const double ms_left = get_view_rect().right() - (MS_RectWidth + MS_RectMargin) * (get_index() + 1);
|
||||
@ -257,7 +263,7 @@ bool DsoSignal::go_vDialPre()
|
||||
if (_view->session().get_capture_state() == SigSession::Stopped)
|
||||
_scale *= pre_vdiv/_vDial->get_value();
|
||||
update_zeroPos();
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
_view->update();
|
||||
return true;
|
||||
} else {
|
||||
@ -276,7 +282,7 @@ bool DsoSignal::go_vDialNext()
|
||||
if (_view->session().get_capture_state() == SigSession::Stopped)
|
||||
_scale *= pre_vdiv/_vDial->get_value();
|
||||
update_zeroPos();
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
_view->update();
|
||||
return true;
|
||||
} else {
|
||||
@ -507,7 +513,7 @@ bool DsoSignal::load_settings()
|
||||
_zero_off = _zeroPos * 255;
|
||||
|
||||
if (_view) {
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
_view->update();
|
||||
}
|
||||
return true;
|
||||
@ -608,6 +614,11 @@ double DsoSignal::get_zeroRate()
|
||||
return _zeroPos;
|
||||
}
|
||||
|
||||
double DsoSignal::get_zeroValue()
|
||||
{
|
||||
return _zero_off;
|
||||
}
|
||||
|
||||
void DsoSignal::set_zeroPos(int pos)
|
||||
{
|
||||
if (enabled()) {
|
||||
@ -644,7 +655,7 @@ void DsoSignal::set_factor(uint64_t factor)
|
||||
_dev_inst->set_config(_probe, NULL, SR_CONF_FACTOR,
|
||||
g_variant_new_uint64(factor));
|
||||
_vDial->set_factor(factor);
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
_view->update();
|
||||
}
|
||||
}
|
||||
@ -668,7 +679,7 @@ uint64_t DsoSignal::get_factor()
|
||||
void DsoSignal::set_ms_show(bool show)
|
||||
{
|
||||
_ms_show = show;
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
}
|
||||
|
||||
bool DsoSignal::get_ms_show() const
|
||||
@ -731,10 +742,10 @@ void DsoSignal::update_zeroPos()
|
||||
|
||||
QRectF DsoSignal::get_view_rect() const
|
||||
{
|
||||
assert(_view);
|
||||
assert(_viewport);
|
||||
return QRectF(0, UpMargin,
|
||||
_view->viewport()->width() - RightMargin,
|
||||
_view->viewport()->height() - UpMargin - DownMargin);
|
||||
_viewport->width() - RightMargin,
|
||||
_viewport->height() - UpMargin - DownMargin);
|
||||
}
|
||||
|
||||
void DsoSignal::paint_back(QPainter &p, int left, int right)
|
||||
@ -745,7 +756,9 @@ void DsoSignal::paint_back(QPainter &p, int left, int right)
|
||||
const int height = get_view_rect().height();
|
||||
const int width = right - left;
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
QPen solidPen(Signal::dsFore);
|
||||
solidPen.setStyle(Qt::SolidLine);
|
||||
p.setPen(solidPen);
|
||||
p.setBrush(Trace::dsBack);
|
||||
p.drawRect(left, UpMargin, width, height);
|
||||
|
||||
@ -772,13 +785,14 @@ void DsoSignal::paint_back(QPainter &p, int left, int right)
|
||||
p.setBrush(Trace::dsBlue);
|
||||
p.drawRect(shown_offset, UpMargin/2 - 3, shown_len, 6);
|
||||
|
||||
QPen pen(Signal::dsFore);
|
||||
pen.setStyle(Qt::DotLine);
|
||||
p.setPen(pen);
|
||||
QPen dashPen(Signal::dsFore);
|
||||
dashPen.setStyle(Qt::DashLine);
|
||||
p.setPen(dashPen);
|
||||
const double spanY =height * 1.0 / DS_CONF_DSO_VDIVS;
|
||||
for (i = 1; i <= DS_CONF_DSO_VDIVS; i++) {
|
||||
const double posY = spanY * i + UpMargin;
|
||||
p.drawLine(left, posY, right, posY);
|
||||
if (i != DS_CONF_DSO_VDIVS)
|
||||
p.drawLine(left, posY, right, posY);
|
||||
const double miniSpanY = spanY / 5;
|
||||
for (j = 1; j < 5; j++) {
|
||||
p.drawLine(width / 2.0f - 5, posY - miniSpanY * j,
|
||||
@ -788,8 +802,8 @@ void DsoSignal::paint_back(QPainter &p, int left, int right)
|
||||
const double spanX = width * 1.0 / DS_CONF_DSO_HDIVS;
|
||||
for (i = 1; i <= DS_CONF_DSO_HDIVS; i++) {
|
||||
const double posX = spanX * i;
|
||||
p.drawLine(posX, UpMargin,
|
||||
posX, height + UpMargin);
|
||||
if (i != DS_CONF_DSO_HDIVS)
|
||||
p.drawLine(posX, UpMargin,posX, height + UpMargin);
|
||||
const double miniSpanX = spanX / 5;
|
||||
for (j = 1; j < 5; j++) {
|
||||
p.drawLine(posX - miniSpanX * j, height / 2.0f + UpMargin - 5,
|
||||
@ -954,7 +968,7 @@ void DsoSignal::paint_trace(QPainter &p,
|
||||
}
|
||||
|
||||
p.drawPolyline(points, point - points);
|
||||
p.eraseRect(get_view_rect().right(), get_view_rect().top(),
|
||||
p.eraseRect(get_view_rect().right()+1, get_view_rect().top(),
|
||||
_view->viewport()->width() - get_view_rect().width(), get_view_rect().height());
|
||||
|
||||
//delete[] samples;
|
||||
@ -1095,7 +1109,7 @@ bool DsoSignal::mouse_press(int right, const QPoint pt)
|
||||
{
|
||||
int y = get_y();
|
||||
bool setted = false;
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view->get_traces());
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view->get_traces(ALL_VIEW));
|
||||
const QRectF vDec_rect = get_rect(DSO_VDEC, y, right);
|
||||
const QRectF vInc_rect = get_rect(DSO_VINC, y, right);
|
||||
const QRectF hDec_rect = get_rect(DSO_HDEC, y, right);
|
||||
@ -1156,7 +1170,7 @@ bool DsoSignal::mouse_wheel(int right, const QPoint pt, const int shift)
|
||||
{
|
||||
int y = get_y();
|
||||
const vector< boost::shared_ptr<Trace> > traces(
|
||||
_view->get_traces());
|
||||
_view->get_traces(ALL_VIEW));
|
||||
bool setted = false;
|
||||
const QRectF vDial_rect = get_rect(DSO_VDIAL, y, right);
|
||||
const QRectF hDial_rect = get_rect(DSO_HDIAL, y, right);
|
||||
@ -1363,7 +1377,7 @@ void DsoSignal::paint_measure(QPainter &p)
|
||||
|
||||
bool setted = false;
|
||||
if (_autoH) {
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view->get_traces());
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view->get_traces(ALL_VIEW));
|
||||
const double upPeriod = get_hDialValue() * DS_CONF_DSO_HDIVS * 0.8;
|
||||
const double dnPeriod = get_hDialValue() * DS_CONF_DSO_HDIVS * 0.2;
|
||||
if (_period > upPeriod) {
|
||||
@ -1404,18 +1418,18 @@ bool DsoSignal::measure(const QPointF &p)
|
||||
{
|
||||
if (_ms_gear_rect.contains(QPoint(p.x(), p.y()))) {
|
||||
_ms_gear_hover = true;
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
return false;
|
||||
} else if (_ms_gear_hover) {
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
_ms_gear_hover = false;
|
||||
}
|
||||
if (_ms_show_rect.contains(QPoint(p.x(), p.y()))) {
|
||||
_ms_show_hover = true;
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
return false;
|
||||
} else if (_ms_show_hover){
|
||||
_view->set_need_update(true);
|
||||
_view->set_update(_viewport, true);
|
||||
_ms_show_hover = false;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,8 @@ public:
|
||||
virtual ~DsoSignal();
|
||||
|
||||
boost::shared_ptr<pv::data::SignalData> data() const;
|
||||
void set_view(pv::view::View *view);
|
||||
boost::shared_ptr<pv::data::Dso> dso_data() const;
|
||||
void set_viewport(pv::view::Viewport *viewport);
|
||||
|
||||
void set_scale(float scale);
|
||||
float get_scale();
|
||||
@ -154,6 +155,7 @@ public:
|
||||
*/
|
||||
int get_zeroPos();
|
||||
double get_zeroRate();
|
||||
double get_zeroValue();
|
||||
/**
|
||||
* Sets the mid-Y position of this signal.
|
||||
*/
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "header.h"
|
||||
#include "view.h"
|
||||
|
||||
#include "../../extdef.h"
|
||||
#include "trace.h"
|
||||
#include "dsosignal.h"
|
||||
#include "logicsignal.h"
|
||||
@ -95,7 +96,7 @@ boost::shared_ptr<pv::view::Trace> Header::get_mTrace(
|
||||
{
|
||||
const int w = width();
|
||||
const vector< boost::shared_ptr<Trace> > traces(
|
||||
_view.get_traces());
|
||||
_view.get_traces(ALL_VIEW));
|
||||
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
|
||||
{
|
||||
@ -120,7 +121,7 @@ void Header::paintEvent(QPaintEvent*)
|
||||
|
||||
const int w = width();
|
||||
const vector< boost::shared_ptr<Trace> > traces(
|
||||
_view.get_traces());
|
||||
_view.get_traces(ALL_VIEW));
|
||||
|
||||
const bool dragging = !_drag_traces.empty();
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
|
||||
@ -137,7 +138,7 @@ void Header::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
assert(event);
|
||||
|
||||
const vector< boost::shared_ptr<Trace> > traces(
|
||||
_view.get_traces());
|
||||
_view.get_traces(ALL_VIEW));
|
||||
|
||||
if (event->button() & Qt::LeftButton) {
|
||||
_mouse_down_point = event->pos();
|
||||
@ -161,7 +162,7 @@ void Header::mousePressEvent(QMouseEvent *event)
|
||||
assert(event);
|
||||
|
||||
const vector< boost::shared_ptr<Trace> > traces(
|
||||
_view.get_traces());
|
||||
_view.get_traces(ALL_VIEW));
|
||||
int action;
|
||||
const bool instant = _view.session().get_instant();
|
||||
if (instant && _view.session().get_capture_state() == SigSession::Running)
|
||||
@ -229,7 +230,7 @@ void Header::mouseReleaseEvent(QMouseEvent *event)
|
||||
if (action == Trace::COLOR && _colorFlag) {
|
||||
_context_trace = mTrace;
|
||||
changeColor(event);
|
||||
_view.set_need_update(true);
|
||||
_view.set_all_update(true);
|
||||
} else if (action == Trace::NAME && _nameFlag) {
|
||||
_context_trace = mTrace;
|
||||
changeName(event);
|
||||
@ -238,7 +239,7 @@ void Header::mouseReleaseEvent(QMouseEvent *event)
|
||||
if (_moveFlag) {
|
||||
//move(event);
|
||||
_view.signals_changed();
|
||||
_view.set_need_update(true);
|
||||
_view.set_all_update(true);
|
||||
}
|
||||
_colorFlag = false;
|
||||
_nameFlag = false;
|
||||
@ -253,7 +254,7 @@ void Header::wheelEvent(QWheelEvent *event)
|
||||
|
||||
if (event->orientation() == Qt::Vertical) {
|
||||
const vector< boost::shared_ptr<Trace> > traces(
|
||||
_view.get_traces());
|
||||
_view.get_traces(ALL_VIEW));
|
||||
// Vertical scrolling
|
||||
double shift = event->delta() / 20.0;
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
|
||||
|
@ -52,7 +52,7 @@ const int LogicSignal::StateRound = 5;
|
||||
LogicSignal::LogicSignal(boost::shared_ptr<pv::device::DevInst> dev_inst,
|
||||
boost::shared_ptr<data::Logic> data,
|
||||
const sr_channel * const probe) :
|
||||
Signal(dev_inst, probe, SR_CHANNEL_LOGIC),
|
||||
Signal(dev_inst, probe),
|
||||
_data(data),
|
||||
_trig(NONTRIG)
|
||||
{
|
||||
|
@ -1,7 +1,488 @@
|
||||
#include "ffttrace.h"
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <extdef.h>
|
||||
#include "mathtrace.h"
|
||||
|
||||
FftTrace::FftTrace()
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
#include "../sigsession.h"
|
||||
#include "../data/dso.h"
|
||||
#include "../data/dsosnapshot.h"
|
||||
#include "../view/dsosignal.h"
|
||||
#include "../view/viewport.h"
|
||||
#include "../device/devinst.h"
|
||||
|
||||
#include "../data/mathstack.h"
|
||||
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
namespace pv {
|
||||
namespace view {
|
||||
|
||||
const int MathTrace::UpMargin = 0;
|
||||
const int MathTrace::DownMargin = 0;
|
||||
const int MathTrace::RightMargin = 30;
|
||||
const QString MathTrace::FFT_ViewMode[2] = {
|
||||
"Linear RMS",
|
||||
"DBV RMS"
|
||||
};
|
||||
|
||||
const QString MathTrace::FreqPrefixes[9] =
|
||||
{"", "", "", "", "K", "M", "G", "T", "P"};
|
||||
const int MathTrace::FirstSIPrefixPower = -9;
|
||||
const int MathTrace::LastSIPrefixPower = 15;
|
||||
const int MathTrace::Pricision = 2;
|
||||
const int MathTrace::FreqMinorDivNum = 10;
|
||||
const int MathTrace::TickHeight = 15;
|
||||
const int MathTrace::VolDivNum = 5;
|
||||
|
||||
const int MathTrace::DbvRanges[4] = {
|
||||
100,
|
||||
120,
|
||||
150,
|
||||
200,
|
||||
};
|
||||
|
||||
const int MathTrace::HoverPointSize = 3;
|
||||
const double MathTrace::VerticalRate = 1.0 / 2000.0;
|
||||
|
||||
MathTrace::MathTrace(pv::SigSession &session,
|
||||
boost::shared_ptr<pv::data::MathStack> math_stack, int index) :
|
||||
Trace("FFT("+QString::number(index)+")", index, SR_CHANNEL_FFT),
|
||||
_session(session),
|
||||
_math_stack(math_stack),
|
||||
_enable(false),
|
||||
_view_mode(0),
|
||||
_hover_en(false),
|
||||
_scale(1),
|
||||
_offset(0)
|
||||
{
|
||||
const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
|
||||
for(size_t i = 0; i < sigs.size(); i++) {
|
||||
const boost::shared_ptr<view::Signal> s(sigs[i]);
|
||||
assert(s);
|
||||
if (dynamic_pointer_cast<DsoSignal>(s) && index == s->get_index())
|
||||
_colour = s->get_colour();
|
||||
}
|
||||
}
|
||||
|
||||
MathTrace::~MathTrace()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool MathTrace::enabled() const
|
||||
{
|
||||
return _enable;
|
||||
}
|
||||
|
||||
void MathTrace::set_enable(bool enable)
|
||||
{
|
||||
_enable = enable;
|
||||
}
|
||||
|
||||
int MathTrace::view_mode() const
|
||||
{
|
||||
return _view_mode;
|
||||
}
|
||||
|
||||
void MathTrace::set_view_mode(int mode)
|
||||
{
|
||||
assert(mode < sizeof(FFT_ViewMode)/sizeof(FFT_ViewMode[0]));
|
||||
_view_mode = mode;
|
||||
}
|
||||
|
||||
std::vector<QString> MathTrace::get_view_modes_support()
|
||||
{
|
||||
std::vector<QString> modes;
|
||||
for (int i = 0; i < sizeof(FFT_ViewMode)/sizeof(FFT_ViewMode[0]); i++) {
|
||||
modes.push_back(FFT_ViewMode[i]);
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
|
||||
const boost::shared_ptr<pv::data::MathStack>& MathTrace::get_math_stack() const
|
||||
{
|
||||
return _math_stack;
|
||||
}
|
||||
|
||||
void MathTrace::init_zoom()
|
||||
{
|
||||
_scale = 1;
|
||||
_offset = 0;
|
||||
}
|
||||
|
||||
void MathTrace::zoom(double steps, int offset)
|
||||
{
|
||||
if (!_view)
|
||||
return;
|
||||
|
||||
const int width = get_view_rect().width();
|
||||
double pre_offset = _offset + _scale*offset/width;
|
||||
_scale *= std::pow(3.0/2.0, -steps);
|
||||
_scale = max(min(_scale, 1.0), 100.0/_math_stack->get_sample_num());
|
||||
_offset = pre_offset - _scale*offset/width;
|
||||
_offset = max(min(_offset, 1-_scale), 0.0);
|
||||
|
||||
_view->set_update(_viewport, true);
|
||||
_view->update();
|
||||
}
|
||||
|
||||
void MathTrace::set_offset(double delta)
|
||||
{
|
||||
int width = get_view_rect().width();
|
||||
_offset = _offset + (delta*_scale / width);
|
||||
_offset = max(min(_offset, 1-_scale), 0.0);
|
||||
|
||||
_view->set_update(_viewport, true);
|
||||
_view->update();
|
||||
}
|
||||
|
||||
double MathTrace::get_offset() const
|
||||
{
|
||||
return _offset;
|
||||
}
|
||||
|
||||
void MathTrace::set_scale(double scale)
|
||||
{
|
||||
_scale = max(min(scale, 1.0), 100.0/_math_stack->get_sample_num());
|
||||
|
||||
_view->set_update(_viewport, true);
|
||||
_view->update();
|
||||
}
|
||||
|
||||
double MathTrace::get_scale() const
|
||||
{
|
||||
return _scale;
|
||||
}
|
||||
|
||||
void MathTrace::set_dbv_range(int range)
|
||||
{
|
||||
_dbv_range = range;
|
||||
}
|
||||
|
||||
int MathTrace::dbv_range() const
|
||||
{
|
||||
return _dbv_range;
|
||||
}
|
||||
|
||||
std::vector<int> MathTrace::get_dbv_ranges()
|
||||
{
|
||||
std::vector<int> range;
|
||||
for (int i = 0; i < sizeof(DbvRanges)/sizeof(DbvRanges[0]); i++) {
|
||||
range.push_back(DbvRanges[i]);
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
QString MathTrace::format_freq(double freq, unsigned precision)
|
||||
{
|
||||
if (freq <= 0) {
|
||||
return "0Hz";
|
||||
} else {
|
||||
const int order = floor(log10f(freq));
|
||||
assert(order >= FirstSIPrefixPower);
|
||||
assert(order <= LastSIPrefixPower);
|
||||
const int prefix = floor((order - FirstSIPrefixPower)/ 3.0f);
|
||||
const double divider = pow(10.0, max(prefix * 3.0 + FirstSIPrefixPower, 0.0));
|
||||
|
||||
QString s;
|
||||
QTextStream ts(&s);
|
||||
ts.setRealNumberPrecision(precision);
|
||||
ts << fixed << freq / divider <<
|
||||
FreqPrefixes[prefix] << "Hz";
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
bool MathTrace::measure(const QPointF &p)
|
||||
{
|
||||
_hover_en = false;
|
||||
if(!_view || !enabled())
|
||||
return false;
|
||||
|
||||
const QRectF window = get_view_rect();
|
||||
if (!window.contains(p))
|
||||
return false;
|
||||
|
||||
const std::vector<double> samples(_math_stack->get_fft_spectrum());
|
||||
if(samples.empty())
|
||||
return false;
|
||||
|
||||
const int full_size = (_math_stack->get_sample_num()/2+1);
|
||||
const double view_off = full_size * _offset;
|
||||
const int view_size = full_size*_scale;
|
||||
const double sample_per_pixels = view_size/window.width();
|
||||
_hover_index = std::round(p.x() * sample_per_pixels + view_off);
|
||||
|
||||
if (_hover_index < full_size)
|
||||
_hover_en = true;
|
||||
|
||||
//_view->set_update(_viewport, true);
|
||||
_view->update();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MathTrace::paint_back(QPainter &p, int left, int right)
|
||||
{
|
||||
if(!_view)
|
||||
return;
|
||||
|
||||
int i, j;
|
||||
const int height = get_view_rect().height();
|
||||
const int width = right - left;
|
||||
|
||||
QPen solidPen(Signal::dsFore);
|
||||
solidPen.setStyle(Qt::SolidLine);
|
||||
p.setPen(solidPen);
|
||||
p.setBrush(Trace::dsBack);
|
||||
p.drawRect(left, UpMargin, width, height);
|
||||
}
|
||||
|
||||
void MathTrace::paint_mid(QPainter &p, int left, int right)
|
||||
{
|
||||
if(!_view)
|
||||
return;
|
||||
assert(right >= left);
|
||||
|
||||
if (enabled()) {
|
||||
const std::vector<double> samples(_math_stack->get_fft_spectrum());
|
||||
if(samples.empty())
|
||||
return;
|
||||
|
||||
QColor trace_colour = _colour;
|
||||
trace_colour.setAlpha(150);
|
||||
p.setPen(trace_colour);
|
||||
|
||||
const int full_size = (_math_stack->get_sample_num()/2+1);
|
||||
const double view_off = full_size * _offset;
|
||||
const int view_start = floor(view_off);
|
||||
const int view_size = full_size*_scale;
|
||||
QPointF *points = new QPointF[samples.size()];
|
||||
QPointF *point = points;
|
||||
|
||||
const bool dc_ignored = _math_stack->dc_ignored();
|
||||
const double height = get_view_rect().height();
|
||||
const double width = right - left;
|
||||
const double pixels_per_sample = width/view_size;
|
||||
|
||||
double vdiv;
|
||||
double vfactor;
|
||||
double voffset;
|
||||
BOOST_FOREACH(const boost::shared_ptr<Signal> s, _session.get_signals()) {
|
||||
boost::shared_ptr<DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<DsoSignal>(s)) {
|
||||
if(dsoSig->get_index() == _math_stack->get_index()) {
|
||||
vdiv = dsoSig->get_vDialValue();
|
||||
vfactor = dsoSig->get_factor();
|
||||
voffset = dsoSig->get_zeroRate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_view_mode == 0) {
|
||||
_vmin = 0;
|
||||
_vmax = (vdiv*DS_CONF_DSO_HDIVS*vfactor)*VerticalRate;
|
||||
} else {
|
||||
_vmax = 20*log10((vdiv*DS_CONF_DSO_HDIVS*vfactor)*VerticalRate);
|
||||
_vmin = _vmax - _dbv_range;
|
||||
}
|
||||
|
||||
//const double max_value = *std::max_element(dc_ignored ? ++samples.begin() : samples.begin(), samples.end());
|
||||
//const double min_value = *std::min_element(dc_ignored ? ++samples.begin() : samples.begin(), samples.end());
|
||||
//_vmax = (_view_mode == 0) ? max_value : 20*log10(max_value);
|
||||
//_vmin = (_view_mode == 0) ? min_value : 20*log10(min_value);
|
||||
const double scale = height / (_vmax - _vmin);
|
||||
|
||||
double x = (view_start-view_off)*pixels_per_sample;
|
||||
uint64_t sample = view_start;
|
||||
if (dc_ignored && sample == 0) {
|
||||
sample++;
|
||||
x += pixels_per_sample;
|
||||
}
|
||||
double min_mag = pow(10.0, _vmin/20);
|
||||
do{
|
||||
double mag = samples[sample];
|
||||
if (_view_mode != 0) {
|
||||
if (mag < min_mag)
|
||||
mag = _vmin;
|
||||
else
|
||||
mag = 20*log10(mag);
|
||||
}
|
||||
const double y = height - (scale * (mag - _vmin));
|
||||
*point++ = QPointF(x, y);
|
||||
x += pixels_per_sample;
|
||||
sample++;
|
||||
}while(x<right && sample < samples.size());
|
||||
|
||||
p.drawPolyline(points, point - points);
|
||||
delete[] points;
|
||||
}
|
||||
}
|
||||
|
||||
void MathTrace::paint_fore(QPainter &p, int left, int right)
|
||||
{
|
||||
using namespace Qt;
|
||||
|
||||
if(!_view)
|
||||
return;
|
||||
assert(right >= left);
|
||||
|
||||
const int text_height = p.boundingRect(0, 0, INT_MAX, INT_MAX,
|
||||
AlignLeft | AlignTop, "8").height();
|
||||
const double width = get_view_rect().width();
|
||||
const double height = get_view_rect().height();
|
||||
double blank_top = 0;
|
||||
double blank_right = width;
|
||||
|
||||
// horizontal ruler
|
||||
const double NyFreq = _session.get_device()->get_sample_rate() / (2.0 * _math_stack->get_sample_interval());
|
||||
const double deltaFreq = _session.get_device()->get_sample_rate() * 1.0 /
|
||||
(_math_stack->get_sample_num() * _math_stack->get_sample_interval());
|
||||
const double FreqRange = NyFreq * _scale;
|
||||
const double FreqOffset = NyFreq * _offset;
|
||||
|
||||
const int order = (int)floor(log10(FreqRange));
|
||||
const double multiplier = (pow(10.0, order) == FreqRange) ? FreqRange/10 : pow(10.0, order);
|
||||
const double freq_per_pixel = FreqRange / width;
|
||||
|
||||
p.setPen(Trace::DARK_FORE);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
double tick_freq = multiplier * (int)floor(FreqOffset / multiplier);
|
||||
int division = (int)round(tick_freq * FreqMinorDivNum / multiplier);
|
||||
double x = (tick_freq - FreqOffset) / freq_per_pixel;
|
||||
do{
|
||||
if (division%FreqMinorDivNum == 0) {
|
||||
QString freq_str = format_freq(tick_freq);
|
||||
double typical_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
|
||||
AlignLeft | AlignTop, freq_str).width() + 10;
|
||||
p.drawLine(x, 1, x, TickHeight);
|
||||
if (x > typical_width/2 && (width-x) > typical_width/2)
|
||||
p.drawText(x-typical_width/2, TickHeight, typical_width, text_height,
|
||||
AlignCenter | AlignTop | TextDontClip, freq_str);
|
||||
} else {
|
||||
p.drawLine(x, 1, x, TickHeight/2);
|
||||
}
|
||||
tick_freq += multiplier/FreqMinorDivNum;
|
||||
division++;
|
||||
x = (tick_freq - FreqOffset) / freq_per_pixel;
|
||||
} while(x < width);
|
||||
blank_top = max(blank_top, (double)TickHeight + text_height);
|
||||
|
||||
// delta Frequency
|
||||
QString freq_str = QString::fromWCharArray(L" \u0394") + "Freq: " + format_freq(deltaFreq,4);
|
||||
p.drawText(0, 0, width, get_view_rect().height(),
|
||||
AlignRight | AlignBottom | TextDontClip, freq_str);
|
||||
double delta_left = width-p.boundingRect(0, 0, INT_MAX, INT_MAX,
|
||||
AlignLeft | AlignTop, freq_str).width();
|
||||
blank_right = min(delta_left, blank_right);
|
||||
|
||||
// Vertical ruler
|
||||
const double vRange = _vmax - _vmin;
|
||||
const double vOffset = _vmin;
|
||||
const double vol_per_tick = vRange / VolDivNum;
|
||||
|
||||
p.setPen(Trace::DARK_FORE);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
double tick_vol = vol_per_tick + vOffset;
|
||||
double y = height - height / VolDivNum;
|
||||
const QString unit = (_view_mode == 0) ? "" : "dbv";
|
||||
do{
|
||||
if (y > text_height && y < (height - text_height)) {
|
||||
QString vol_str = QString::number(tick_vol, 'f', Pricision) + unit;
|
||||
double vol_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
|
||||
AlignLeft | AlignTop, vol_str).width();
|
||||
p.drawLine(width, y, width-TickHeight/2, y);
|
||||
p.drawText(width-TickHeight-vol_width, y-text_height/2, vol_width, text_height,
|
||||
AlignCenter | AlignTop | TextDontClip, vol_str);
|
||||
blank_right = min(width-TickHeight-vol_width, blank_right);
|
||||
}
|
||||
tick_vol += vol_per_tick;
|
||||
y -= height / VolDivNum;
|
||||
} while(y > 0);
|
||||
|
||||
// Hover measure
|
||||
if (_hover_en) {
|
||||
const std::vector<double> samples(_math_stack->get_fft_spectrum());
|
||||
if(samples.empty())
|
||||
return;
|
||||
const int full_size = (_math_stack->get_sample_num()/2+1);
|
||||
const double view_off = full_size * _offset;
|
||||
const int view_size = full_size*_scale;
|
||||
const double scale = height / (_vmax - _vmin);
|
||||
const double pixels_per_sample = width/view_size;
|
||||
double x = (_hover_index-view_off)*pixels_per_sample;
|
||||
double min_mag = pow(10.0, _vmin/20);
|
||||
_hover_value = samples[_hover_index];
|
||||
if (_view_mode != 0) {
|
||||
if (_hover_value < min_mag)
|
||||
_hover_value = _vmin;
|
||||
else
|
||||
_hover_value = 20*log10(_hover_value);
|
||||
}
|
||||
const double y = height - (scale * (_hover_value - _vmin));
|
||||
_hover_point = QPointF(x, y);
|
||||
|
||||
p.setPen(QPen(Trace::DARK_FORE, 1, Qt::DashLine));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawLine(_hover_point.x(), 0, _hover_point.x(), height);
|
||||
|
||||
QString hover_str = QString::number(_hover_value, 'f', 4) + unit + "@" + format_freq(deltaFreq * _hover_index, 4);
|
||||
const int hover_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
|
||||
AlignLeft | AlignTop, hover_str).width();
|
||||
const int hover_height = p.boundingRect(0, 0, INT_MAX, INT_MAX,
|
||||
AlignLeft | AlignTop, hover_str).height();
|
||||
QRectF hover_rect(_hover_point.x(), _hover_point.y()-hover_height, hover_width, hover_height);
|
||||
if (hover_rect.right() > blank_right)
|
||||
hover_rect.moveRight(min(_hover_point.x(), blank_right));
|
||||
if (hover_rect.top() < blank_top)
|
||||
hover_rect.moveTop(max(_hover_point.y(), blank_top));
|
||||
if (hover_rect.top() > 0)
|
||||
p.drawText(hover_rect, AlignCenter | AlignTop | TextDontClip, hover_str);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Trace::DARK_FORE);
|
||||
p.drawEllipse(_hover_point, HoverPointSize, HoverPointSize);
|
||||
}
|
||||
}
|
||||
|
||||
void MathTrace::paint_type_options(QPainter &p, int right, const QPoint pt)
|
||||
{
|
||||
(void)p;
|
||||
(void)pt;
|
||||
(void)right;
|
||||
}
|
||||
|
||||
QRectF MathTrace::get_view_rect() const
|
||||
{
|
||||
assert(_viewport);
|
||||
return QRectF(0, UpMargin,
|
||||
_viewport->width() - RightMargin,
|
||||
_viewport->height() - UpMargin - DownMargin);
|
||||
}
|
||||
|
||||
} // namespace view
|
||||
} // namespace pv
|
||||
|
@ -1,11 +1,156 @@
|
||||
#ifndef FFTTRACE_H
|
||||
#define FFTTRACE_H
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef DSVIEW_PV_VIEW_MATHTRACE_H
|
||||
#define DSVIEW_PV_VIEW_MATHTRACE_H
|
||||
|
||||
class FftTrace
|
||||
#include "trace.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
struct srd_channel;
|
||||
|
||||
namespace pv {
|
||||
|
||||
class SigSession;
|
||||
|
||||
namespace data{
|
||||
class MathStack;
|
||||
}
|
||||
|
||||
namespace view {
|
||||
|
||||
class MathTrace : public Trace
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
static const int UpMargin;
|
||||
static const int DownMargin;
|
||||
static const int RightMargin;
|
||||
static const QString FFT_ViewMode[2];
|
||||
|
||||
static const QString FreqPrefixes[9];
|
||||
static const int FirstSIPrefixPower;
|
||||
static const int LastSIPrefixPower;
|
||||
static const int Pricision;
|
||||
static const int FreqMinorDivNum;
|
||||
static const int TickHeight;
|
||||
static const int VolDivNum;
|
||||
|
||||
static const int DbvRanges[4];
|
||||
|
||||
static const int HoverPointSize;
|
||||
|
||||
static const double VerticalRate;
|
||||
|
||||
public:
|
||||
FftTrace();
|
||||
MathTrace(pv::SigSession &session,
|
||||
boost::shared_ptr<pv::data::MathStack> math_stack, int index);
|
||||
~MathTrace();
|
||||
|
||||
bool enabled() const;
|
||||
void set_enable(bool enable);
|
||||
|
||||
void init_zoom();
|
||||
void zoom(double steps, int offset);
|
||||
bool zoom_hit() const;
|
||||
void set_zoom_hit(bool hit);
|
||||
|
||||
void set_offset(double delta);
|
||||
double get_offset() const;
|
||||
|
||||
void set_scale(double scale);
|
||||
double get_scale() const;
|
||||
|
||||
void set_dbv_range(int range);
|
||||
int dbv_range() const;
|
||||
std::vector<int> get_dbv_ranges();
|
||||
|
||||
int view_mode() const;
|
||||
void set_view_mode(int mode);
|
||||
std::vector<QString> get_view_modes_support();
|
||||
|
||||
const boost::shared_ptr<pv::data::MathStack>& get_math_stack() const;
|
||||
|
||||
static QString format_freq(double freq, unsigned precision = Pricision);
|
||||
|
||||
bool measure(const QPointF &p);
|
||||
|
||||
/**
|
||||
* Paints the background layer of the trace with a QPainter
|
||||
* @param p the QPainter to paint into.
|
||||
* @param left the x-coordinate of the left edge of the signal.
|
||||
* @param right the x-coordinate of the right edge of the signal.
|
||||
**/
|
||||
void paint_back(QPainter &p, int left, int right);
|
||||
|
||||
/**
|
||||
* Paints the mid-layer of the trace with a QPainter
|
||||
* @param p the QPainter to paint into.
|
||||
* @param left the x-coordinate of the left edge of the signal
|
||||
* @param right the x-coordinate of the right edge of the signal
|
||||
**/
|
||||
void paint_mid(QPainter &p, int left, int right);
|
||||
|
||||
/**
|
||||
* Paints the foreground layer of the trace with a QPainter
|
||||
* @param p the QPainter to paint into.
|
||||
* @param left the x-coordinate of the left edge of the signal
|
||||
* @param right the x-coordinate of the right edge of the signal
|
||||
**/
|
||||
void paint_fore(QPainter &p, int left, int right);
|
||||
|
||||
QRectF get_view_rect() const;
|
||||
|
||||
protected:
|
||||
void paint_type_options(QPainter &p, int right, const QPoint pt);
|
||||
|
||||
private:
|
||||
|
||||
private slots:
|
||||
|
||||
private:
|
||||
pv::SigSession &_session;
|
||||
boost::shared_ptr<pv::data::MathStack> _math_stack;
|
||||
|
||||
bool _enable;
|
||||
int _view_mode;
|
||||
|
||||
double _vmax;
|
||||
double _vmin;
|
||||
int _dbv_range;
|
||||
|
||||
uint64_t _hover_index;
|
||||
bool _hover_en;
|
||||
QPointF _hover_point;
|
||||
double _hover_value;
|
||||
|
||||
double _scale;
|
||||
double _offset;
|
||||
};
|
||||
|
||||
#endif // FFTTRACE_H
|
||||
} // namespace view
|
||||
} // namespace pv
|
||||
|
||||
#endif // DSVIEW_PV_VIEW_FFTTRACE_H
|
||||
|
@ -109,7 +109,7 @@ QString Ruler::format_freq(double period, unsigned precision)
|
||||
QString s;
|
||||
QTextStream ts(&s);
|
||||
ts.setRealNumberPrecision(precision);
|
||||
ts << fixed << forcesign << 1 / (period * multiplier) <<
|
||||
ts << fixed << 1 / (period * multiplier) <<
|
||||
FreqPrefixes[prefix] << "Hz";
|
||||
return s;
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ namespace pv {
|
||||
namespace view {
|
||||
|
||||
Signal::Signal(boost::shared_ptr<pv::device::DevInst> dev_inst,
|
||||
const sr_channel *const probe, int type) :
|
||||
Trace(probe->name, probe->index, type),
|
||||
const sr_channel *const probe) :
|
||||
Trace(probe->name, probe->index, probe->type),
|
||||
_dev_inst(dev_inst),
|
||||
_probe(probe)
|
||||
{
|
||||
|
@ -57,7 +57,7 @@ private:
|
||||
|
||||
protected:
|
||||
Signal(boost::shared_ptr<pv::device::DevInst> dev_inst,
|
||||
const sr_channel * const probe, int type);
|
||||
const sr_channel * const probe);
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
|
@ -43,7 +43,7 @@ const QColor Trace::dsRed = QColor(213, 15, 37, 255);
|
||||
const QColor Trace::dsGreen = QColor(0, 153, 37, 200);
|
||||
const QColor Trace::dsGray = QColor(0x88, 0x8A, 0x85, 60);
|
||||
const QColor Trace::dsFore = QColor(0xff, 0xff, 0xff, 60);
|
||||
const QColor Trace::dsBack = QColor(0x16, 0x18, 0x23, 180);
|
||||
const QColor Trace::dsBack = QColor(0x16, 0x18, 0x23, 200);
|
||||
const QColor Trace::dsDisable = QColor(0x88, 0x8A, 0x85, 200);
|
||||
const QColor Trace::dsActive = QColor(17, 133, 209, 255);
|
||||
const QColor Trace::dsLightBlue = QColor(17, 133, 209, 150);
|
||||
@ -53,6 +53,7 @@ const QPen Trace::SignalAxisPen = QColor(128, 128, 128, 64);
|
||||
const QColor Trace::DARK_BACK = QColor(48, 47, 47, 255);
|
||||
const QColor Trace::DARK_FORE = QColor(150, 150, 150, 255);
|
||||
const QColor Trace::DARK_HIGHLIGHT = QColor(32, 32, 32, 255);
|
||||
const QColor Trace::DARK_BLUE = QColor(17, 133, 209, 255);
|
||||
|
||||
const QColor Trace::PROBE_COLORS[8] = {
|
||||
QColor(0x50, 0x50, 0x50), // Black
|
||||
@ -187,7 +188,7 @@ void Trace::set_old_v_offset(int v_offset)
|
||||
|
||||
int Trace::get_zeroPos()
|
||||
{
|
||||
return _v_offset - _view->v_offset();
|
||||
return _v_offset;
|
||||
}
|
||||
|
||||
int Trace::get_totalHeight() const
|
||||
@ -211,6 +212,17 @@ pv::view::View* Trace::get_view() const
|
||||
return _view;
|
||||
}
|
||||
|
||||
void Trace::set_viewport(pv::view::Viewport *viewport)
|
||||
{
|
||||
assert(viewport);
|
||||
_viewport = viewport;
|
||||
}
|
||||
|
||||
pv::view::Viewport* Trace::get_viewport() const
|
||||
{
|
||||
return _viewport;
|
||||
}
|
||||
|
||||
void Trace::paint_back(QPainter &p, int left, int right)
|
||||
{
|
||||
QPen pen(Signal::dsGray);
|
||||
@ -236,6 +248,9 @@ void Trace::paint_fore(QPainter &p, int left, int right)
|
||||
|
||||
void Trace::paint_label(QPainter &p, int right, const QPoint pt)
|
||||
{
|
||||
if (_type == SR_CHANNEL_FFT && !enabled())
|
||||
return;
|
||||
|
||||
compute_text_size(p);
|
||||
const int y = get_y();
|
||||
|
||||
@ -267,7 +282,7 @@ void Trace::paint_label(QPainter &p, int right, const QPoint pt)
|
||||
};
|
||||
|
||||
p.setPen(Qt::transparent);
|
||||
if (_type == SR_CHANNEL_DSO) {
|
||||
if (_type == SR_CHANNEL_DSO || _type == SR_CHANNEL_FFT) {
|
||||
p.setBrush((label_rect.contains(pt) || selected()) ? _colour.darker() : _colour);
|
||||
p.drawPolygon(points, countof(points));
|
||||
} else {
|
||||
@ -284,6 +299,8 @@ void Trace::paint_label(QPainter &p, int right, const QPoint pt)
|
||||
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "A");
|
||||
else if (_type == SR_CHANNEL_DECODER)
|
||||
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "D");
|
||||
else if (_type == SR_CHANNEL_FFT)
|
||||
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "M");
|
||||
else
|
||||
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, QString::number(_index_list.front()));
|
||||
}
|
||||
@ -355,7 +372,7 @@ QRectF Trace::get_view_rect() const
|
||||
|
||||
int Trace::get_y() const
|
||||
{
|
||||
return _v_offset - _view->v_offset();
|
||||
return _v_offset;
|
||||
}
|
||||
|
||||
QColor Trace::get_text_colour() const
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libsigrok4DSL/libsigrok.h>
|
||||
|
||||
#include "selectableitem.h"
|
||||
#include "dsldial.h"
|
||||
|
||||
@ -40,6 +42,7 @@ namespace pv {
|
||||
namespace view {
|
||||
|
||||
class View;
|
||||
class Viewport;
|
||||
|
||||
class Trace : public SelectableItem
|
||||
{
|
||||
@ -73,6 +76,7 @@ public:
|
||||
static const QColor DARK_BACK;
|
||||
static const QColor DARK_FORE;
|
||||
static const QColor DARK_HIGHLIGHT;
|
||||
static const QColor DARK_BLUE;
|
||||
|
||||
static const QColor PROBE_COLORS[8];
|
||||
|
||||
@ -166,6 +170,8 @@ public:
|
||||
|
||||
virtual void set_view(pv::view::View *view);
|
||||
pv::view::View* get_view() const;
|
||||
virtual void set_viewport(pv::view::Viewport *viewport);
|
||||
pv::view::Viewport* get_viewport() const;
|
||||
|
||||
/**
|
||||
* Paints the background layer of the trace with a QPainter
|
||||
@ -290,6 +296,7 @@ signals:
|
||||
|
||||
protected:
|
||||
pv::view::View *_view;
|
||||
pv::view::Viewport *_viewport;
|
||||
|
||||
QString _name;
|
||||
QColor _colour;
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "dsosignal.h"
|
||||
#include "view.h"
|
||||
#include "viewport.h"
|
||||
#include "mathtrace.h"
|
||||
|
||||
#include "../device/devinst.h"
|
||||
#include "pv/sigsession.h"
|
||||
@ -68,25 +69,19 @@ const QColor View::CursorAreaColour(220, 231, 243);
|
||||
const QSizeF View::LabelPadding(4, 4);
|
||||
|
||||
View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget *parent) :
|
||||
QAbstractScrollArea(parent),
|
||||
QScrollArea(parent),
|
||||
_session(session),
|
||||
_sampling_bar(sampling_bar),
|
||||
_viewport(new Viewport(*this)),
|
||||
_ruler(new Ruler(*this)),
|
||||
_header(new Header(*this)),
|
||||
_devmode(new DevMode(this, session)),
|
||||
_scale(1e-8),
|
||||
_preScale(1e-6),
|
||||
_maxscale(1e9),
|
||||
_minscale(1e-15),
|
||||
_offset(0),
|
||||
_preOffset(0),
|
||||
_v_offset(0),
|
||||
_updating_scroll(false),
|
||||
_need_update(false),
|
||||
_show_cursors(false),
|
||||
_trig_pos(0),
|
||||
_hover_point(-1, -1)
|
||||
_hover_point(-1, -1)
|
||||
{
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
|
||||
@ -95,8 +90,60 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
|
||||
connect(verticalScrollBar(), SIGNAL(valueChanged(int)),
|
||||
this, SLOT(v_scroll_value_changed(int)));
|
||||
|
||||
// trace viewport map
|
||||
_trace_view_map[SR_CHANNEL_LOGIC] = TIME_VIEW;
|
||||
_trace_view_map[SR_CHANNEL_GROUP] = TIME_VIEW;
|
||||
_trace_view_map[SR_CHANNEL_DECODER] = TIME_VIEW;
|
||||
_trace_view_map[SR_CHANNEL_ANALOG] = TIME_VIEW;
|
||||
_trace_view_map[SR_CHANNEL_DSO] = TIME_VIEW;
|
||||
_trace_view_map[SR_CHANNEL_FFT] = FFT_VIEW;
|
||||
|
||||
_active_viewport = NULL;
|
||||
_ruler = new Ruler(*this);
|
||||
_header = new Header(*this);
|
||||
_devmode = new DevMode(this, session);
|
||||
|
||||
setViewportMargins(headerWidth(), RulerHeight, 0, 0);
|
||||
setViewport(_viewport);
|
||||
//setViewport(_viewport);
|
||||
|
||||
// windows splitter
|
||||
_time_viewport = new Viewport(*this, TIME_VIEW);
|
||||
_time_viewport->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
_time_viewport->setMinimumHeight(100);
|
||||
connect(_time_viewport, SIGNAL(measure_updated()),
|
||||
this, SLOT(on_measure_updated()));
|
||||
_fft_viewport = new Viewport(*this, FFT_VIEW);
|
||||
_fft_viewport->setVisible(false);
|
||||
_fft_viewport->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
_fft_viewport->setMinimumHeight(100);
|
||||
connect(_fft_viewport, SIGNAL(measure_updated()),
|
||||
this, SLOT(on_measure_updated()));
|
||||
|
||||
_vsplitter = new QSplitter(this);
|
||||
_vsplitter->setOrientation(Qt::Vertical);
|
||||
_vsplitter->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
|
||||
_viewport_list.push_back(_time_viewport);
|
||||
_vsplitter->addWidget(_time_viewport);
|
||||
_vsplitter->setCollapsible(0, false);
|
||||
_vsplitter->setStretchFactor(0, 2);
|
||||
_viewport_list.push_back(_fft_viewport);
|
||||
_vsplitter->addWidget(_fft_viewport);
|
||||
_vsplitter->setCollapsible(1, false);
|
||||
_vsplitter->setStretchFactor(1, 1);
|
||||
|
||||
_viewcenter = new QWidget(this);
|
||||
_viewcenter->setContentsMargins(0,0,0,0);
|
||||
QGridLayout* layout = new QGridLayout(_viewcenter);
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
_viewcenter->setLayout(layout);
|
||||
layout->addWidget(_vsplitter, 0, 0);
|
||||
QWidget* bottom = new QWidget(this);
|
||||
bottom->setFixedHeight(10);
|
||||
layout->addWidget(bottom, 1, 0);
|
||||
setViewport(_viewcenter);
|
||||
connect(_vsplitter, SIGNAL(splitterMoved(int,int)),
|
||||
this, SLOT(splitterMoved(int, int)));
|
||||
|
||||
connect(&_session, SIGNAL(device_setted()),
|
||||
_devmode, SLOT(set_device()));
|
||||
@ -117,12 +164,13 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
|
||||
connect(_header, SIGNAL(header_updated()),
|
||||
this, SLOT(header_updated()));
|
||||
|
||||
_viewport->installEventFilter(this);
|
||||
_time_viewport->installEventFilter(this);
|
||||
_fft_viewport->installEventFilter(this);
|
||||
_ruler->installEventFilter(this);
|
||||
_header->installEventFilter(this);
|
||||
_devmode->installEventFilter(this);
|
||||
|
||||
_viewport->setObjectName(tr("ViewArea_viewport"));
|
||||
_viewcenter->setObjectName(tr("ViewArea_center"));
|
||||
_ruler->setObjectName(tr("ViewArea_ruler"));
|
||||
_header->setObjectName(tr("ViewArea_header"));
|
||||
|
||||
@ -148,11 +196,6 @@ double View::offset() const
|
||||
return _offset;
|
||||
}
|
||||
|
||||
int View::v_offset() const
|
||||
{
|
||||
return _v_offset;
|
||||
}
|
||||
|
||||
double View::get_minscale() const
|
||||
{
|
||||
return _minscale;
|
||||
@ -168,14 +211,15 @@ void View::zoom(double steps)
|
||||
zoom(steps, get_view_width() / 2);
|
||||
}
|
||||
|
||||
void View::set_need_update(bool need_update)
|
||||
void View::set_update(Viewport *viewport, bool need_update)
|
||||
{
|
||||
_need_update = need_update;
|
||||
viewport->set_need_update(need_update);
|
||||
}
|
||||
|
||||
bool View::need_update() const
|
||||
void View::set_all_update(bool need_update)
|
||||
{
|
||||
return _need_update;
|
||||
BOOST_FOREACH(Viewport *viewport, _viewport_list)
|
||||
viewport->set_need_update(need_update);
|
||||
}
|
||||
|
||||
void View::update_sample(bool instant)
|
||||
@ -235,7 +279,7 @@ void View::zoom(double steps, int offset)
|
||||
if (_scale != _preScale || _offset != _preOffset) {
|
||||
_header->update();
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
update_scroll();
|
||||
}
|
||||
//}
|
||||
@ -255,7 +299,7 @@ void View::set_scale_offset(double scale, double offset)
|
||||
update_scroll();
|
||||
_header->update();
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
//}
|
||||
}
|
||||
@ -269,25 +313,57 @@ void View::set_preScale_preOffset()
|
||||
set_scale_offset(_preScale, _preOffset);
|
||||
}
|
||||
|
||||
vector< boost::shared_ptr<Trace> > View::get_traces() const
|
||||
vector< boost::shared_ptr<Trace> > View::get_traces(int type)
|
||||
{
|
||||
// const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
|
||||
// const vector< boost::shared_ptr<GroupSignal> > groups(_session.get_group_signals());
|
||||
//#ifdef ENABLE_DECODE
|
||||
// const vector< boost::shared_ptr<DecodeTrace> > decode_sigs(
|
||||
// _session.get_decode_signals());
|
||||
// vector< boost::shared_ptr<Trace> > traces(
|
||||
// sigs.size() + groups.size() + decode_sigs.size());
|
||||
//#else
|
||||
// vector< boost::shared_ptr<Trace> > traces(sigs.size() + groups.size());
|
||||
//#endif
|
||||
|
||||
// vector< boost::shared_ptr<Trace> >::iterator i = traces.begin();
|
||||
// i = copy(sigs.begin(), sigs.end(), i);
|
||||
//#ifdef ENABLE_DECODE
|
||||
// i = copy(decode_sigs.begin(), decode_sigs.end(), i);
|
||||
//#endif
|
||||
// i = copy(groups.begin(), groups.end(), i);
|
||||
|
||||
// stable_sort(traces.begin(), traces.end(), compare_trace_v_offsets);
|
||||
// return traces;
|
||||
|
||||
const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
|
||||
const vector< boost::shared_ptr<GroupSignal> > groups(_session.get_group_signals());
|
||||
#ifdef ENABLE_DECODE
|
||||
const vector< boost::shared_ptr<DecodeTrace> > decode_sigs(
|
||||
_session.get_decode_signals());
|
||||
vector< boost::shared_ptr<Trace> > traces(
|
||||
sigs.size() + groups.size() + decode_sigs.size());
|
||||
#else
|
||||
vector< boost::shared_ptr<Trace> > traces(sigs.size() + groups.size());
|
||||
#endif
|
||||
const vector< boost::shared_ptr<MathTrace> > maths(_session.get_math_signals());
|
||||
|
||||
vector< boost::shared_ptr<Trace> >::iterator i = traces.begin();
|
||||
i = copy(sigs.begin(), sigs.end(), i);
|
||||
vector< boost::shared_ptr<Trace> > traces;
|
||||
BOOST_FOREACH(boost::shared_ptr<Trace> t, sigs) {
|
||||
if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
|
||||
traces.push_back(t);
|
||||
}
|
||||
#ifdef ENABLE_DECODE
|
||||
i = copy(decode_sigs.begin(), decode_sigs.end(), i);
|
||||
BOOST_FOREACH(boost::shared_ptr<Trace> t, decode_sigs) {
|
||||
if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
|
||||
traces.push_back(t);
|
||||
}
|
||||
#endif
|
||||
i = copy(groups.begin(), groups.end(), i);
|
||||
BOOST_FOREACH(boost::shared_ptr<Trace> t, groups) {
|
||||
if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
|
||||
traces.push_back(t);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(boost::shared_ptr<Trace> t, maths) {
|
||||
if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
|
||||
traces.push_back(t);
|
||||
}
|
||||
|
||||
stable_sort(traces.begin(), traces.end(), compare_trace_v_offsets);
|
||||
return traces;
|
||||
@ -323,21 +399,21 @@ void View::show_cursors(bool show)
|
||||
{
|
||||
_show_cursors = show;
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
|
||||
void View::show_trig_cursor(bool show)
|
||||
{
|
||||
_show_trig_cursor = show;
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
|
||||
void View::show_search_cursor(bool show)
|
||||
{
|
||||
_show_search_cursor = show;
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
|
||||
void View::set_trig_pos(quint64 trig_pos)
|
||||
@ -353,7 +429,7 @@ void View::set_trig_pos(quint64 trig_pos)
|
||||
_trigger_time = _trigger_time.addSecs(secs);
|
||||
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
|
||||
void View::set_search_pos(uint64_t search_pos)
|
||||
@ -365,7 +441,7 @@ void View::set_search_pos(uint64_t search_pos)
|
||||
_search_cursor->set_index(search_pos);
|
||||
set_scale_offset(_scale, time - _scale * get_view_width() / 2);
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
|
||||
uint64_t View::get_trig_pos()
|
||||
@ -385,7 +461,7 @@ const QPointF& View::hover_point() const
|
||||
|
||||
void View::normalize_layout()
|
||||
{
|
||||
const vector< boost::shared_ptr<Trace> > traces(get_traces());
|
||||
const vector< boost::shared_ptr<Trace> > traces(get_traces(ALL_VIEW));
|
||||
|
||||
int v_min = INT_MAX;
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
|
||||
@ -395,7 +471,7 @@ void View::normalize_layout()
|
||||
BOOST_FOREACH(boost::shared_ptr<Trace> t, traces)
|
||||
t->set_v_offset(t->get_v_offset() + delta);
|
||||
|
||||
verticalScrollBar()->setSliderPosition(_v_offset + delta);
|
||||
verticalScrollBar()->setSliderPosition(delta);
|
||||
v_scroll_value_changed(verticalScrollBar()->sliderPosition());
|
||||
}
|
||||
|
||||
@ -422,9 +498,9 @@ void View::get_scroll_layout(double &length, double &offset) const
|
||||
|
||||
void View::update_scroll()
|
||||
{
|
||||
assert(_viewport);
|
||||
assert(_viewcenter);
|
||||
|
||||
const QSize areaSize = _viewport->size();
|
||||
const QSize areaSize = _viewcenter->size();
|
||||
|
||||
// Set the horizontal scroll bar
|
||||
double length = 0, offset = 0;
|
||||
@ -448,8 +524,7 @@ void View::update_scroll()
|
||||
|
||||
// Set the vertical scrollbar
|
||||
verticalScrollBar()->setPageStep(areaSize.height());
|
||||
verticalScrollBar()->setRange(0,
|
||||
_viewport->get_total_height() - areaSize.height());
|
||||
verticalScrollBar()->setRange(0,0);
|
||||
}
|
||||
|
||||
void View::update_scale()
|
||||
@ -473,47 +548,93 @@ void View::update_scale()
|
||||
_trig_cursor->set_index(_trig_pos);
|
||||
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
|
||||
void View::signals_changed()
|
||||
{
|
||||
int total_rows = 0;
|
||||
uint8_t max_height = MaxHeightUnit;
|
||||
const vector< boost::shared_ptr<Trace> > traces(get_traces());
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
|
||||
{
|
||||
assert(t);
|
||||
if (dynamic_pointer_cast<DsoSignal>(t) ||
|
||||
t->enabled())
|
||||
total_rows += t->rows_size();
|
||||
vector< boost::shared_ptr<Trace> > time_traces;
|
||||
vector< boost::shared_ptr<Trace> > fft_traces;
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, get_traces(ALL_VIEW)) {
|
||||
if (_trace_view_map[t->get_type()] == TIME_VIEW)
|
||||
time_traces.push_back(t);
|
||||
else if (_trace_view_map[t->get_type()] == FFT_VIEW)
|
||||
if (t->enabled())
|
||||
fft_traces.push_back(t);
|
||||
}
|
||||
|
||||
const double height = (_viewport->height()
|
||||
- horizontalScrollBar()->height()
|
||||
- 2 * SignalMargin * traces.size()) * 1.0 / total_rows;
|
||||
|
||||
if (_session.get_device()->dev_inst()->mode == LOGIC) {
|
||||
GVariant* gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_MAX_HEIGHT_VALUE);
|
||||
if (gvar != NULL) {
|
||||
max_height = (g_variant_get_byte(gvar) + 1) * MaxHeightUnit;
|
||||
g_variant_unref(gvar);
|
||||
if (!fft_traces.empty()) {
|
||||
if (!_fft_viewport->isVisible()) {
|
||||
_fft_viewport->setVisible(true);
|
||||
_fft_viewport->clear_measure();
|
||||
_viewport_list.push_back(_fft_viewport);
|
||||
_vsplitter->refresh();
|
||||
}
|
||||
BOOST_FOREACH(boost::shared_ptr<Trace> t, fft_traces) {
|
||||
t->set_view(this);
|
||||
t->set_viewport(_fft_viewport);
|
||||
t->set_totalHeight(_fft_viewport->height());
|
||||
t->set_v_offset(_fft_viewport->geometry().bottom());
|
||||
}
|
||||
_signalHeight = (int)((height <= 0) ? 1 : (height >= max_height) ? max_height : height);
|
||||
} else {
|
||||
_signalHeight = (int)((height <= 0) ? 1 : height);
|
||||
}
|
||||
_spanY = _signalHeight + 2 * SignalMargin;
|
||||
int next_v_offset = SignalMargin;
|
||||
BOOST_FOREACH(boost::shared_ptr<Trace> t, traces) {
|
||||
t->set_view(this);
|
||||
const double traceHeight = _signalHeight*t->rows_size();
|
||||
t->set_totalHeight((int)traceHeight);
|
||||
t->set_v_offset(next_v_offset + 0.5 * traceHeight + SignalMargin);
|
||||
next_v_offset += traceHeight + 2 * SignalMargin;
|
||||
}
|
||||
_fft_viewport->setVisible(false);
|
||||
_vsplitter->refresh();
|
||||
|
||||
// Find the decoder in the stack
|
||||
std::list< Viewport *>::iterator iter = _viewport_list.begin();
|
||||
for(int i = 0; i < _viewport_list.size(); i++, iter++)
|
||||
if ((*iter) == _fft_viewport)
|
||||
break;
|
||||
// Delete the element
|
||||
if (iter != _viewport_list.end())
|
||||
_viewport_list.erase(iter);
|
||||
}
|
||||
|
||||
if (!time_traces.empty() && _time_viewport) {
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, time_traces) {
|
||||
assert(t);
|
||||
if (dynamic_pointer_cast<DsoSignal>(t) ||
|
||||
t->enabled())
|
||||
total_rows += t->rows_size();
|
||||
}
|
||||
|
||||
const double height = (_time_viewport->height()
|
||||
- horizontalScrollBar()->height()
|
||||
- 2 * SignalMargin * time_traces.size()) * 1.0 / total_rows;
|
||||
|
||||
if (_session.get_device()->dev_inst()->mode == LOGIC) {
|
||||
GVariant* gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_MAX_HEIGHT_VALUE);
|
||||
if (gvar != NULL) {
|
||||
max_height = (g_variant_get_byte(gvar) + 1) * MaxHeightUnit;
|
||||
g_variant_unref(gvar);
|
||||
}
|
||||
_signalHeight = (int)((height <= 0) ? 1 : (height >= max_height) ? max_height : height);
|
||||
} else if (_session.get_device()->dev_inst()->mode == DSO) {
|
||||
_signalHeight = (_header->height()
|
||||
- horizontalScrollBar()->height()
|
||||
- 2 * SignalMargin * time_traces.size()) * 1.0 / total_rows;
|
||||
} else {
|
||||
_signalHeight = (int)((height <= 0) ? 1 : height);
|
||||
}
|
||||
_spanY = _signalHeight + 2 * SignalMargin;
|
||||
int next_v_offset = SignalMargin;
|
||||
BOOST_FOREACH(boost::shared_ptr<Trace> t, time_traces) {
|
||||
t->set_view(this);
|
||||
t->set_viewport(_time_viewport);
|
||||
const double traceHeight = _signalHeight*t->rows_size();
|
||||
t->set_totalHeight((int)traceHeight);
|
||||
t->set_v_offset(next_v_offset + 0.5 * traceHeight + SignalMargin);
|
||||
next_v_offset += traceHeight + 2 * SignalMargin;
|
||||
|
||||
boost::shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(t))
|
||||
dsoSig->set_scale(dsoSig->get_view_rect().height() / 256.0f);
|
||||
}
|
||||
_time_viewport->clear_measure();
|
||||
}
|
||||
|
||||
_viewport->clear_measure();
|
||||
header_updated();
|
||||
normalize_layout();
|
||||
data_updated();
|
||||
@ -525,7 +646,7 @@ bool View::eventFilter(QObject *object, QEvent *event)
|
||||
if (type == QEvent::MouseMove) {
|
||||
|
||||
const QMouseEvent *const mouse_event = (QMouseEvent*)event;
|
||||
if (object == _ruler || object == _viewport) {
|
||||
if (object == _ruler || object == _time_viewport || object == _fft_viewport) {
|
||||
//_hover_point = QPoint(mouse_event->x(), 0);
|
||||
double cur_periods = (mouse_event->pos().x() * _scale + _offset) / _ruler->get_min_period();
|
||||
double integer_x = (round(cur_periods) * _ruler->get_min_period() - _offset ) / _scale;
|
||||
@ -575,7 +696,7 @@ int View::headerWidth()
|
||||
QFont font = QApplication::font();
|
||||
QFontMetrics fm(font);
|
||||
|
||||
const vector< boost::shared_ptr<Trace> > traces(get_traces());
|
||||
const vector< boost::shared_ptr<Trace> > traces(get_traces(ALL_VIEW));
|
||||
if (!traces.empty()){
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces) {
|
||||
maxNameWidth = max(fm.boundingRect(t->get_name()).width(), maxNameWidth);
|
||||
@ -593,8 +714,10 @@ int View::headerWidth()
|
||||
|
||||
void View::resizeEvent(QResizeEvent*)
|
||||
{
|
||||
setViewportMargins(headerWidth(), RulerHeight, 0, 0);
|
||||
update_margins();
|
||||
update_scroll();
|
||||
signals_changed();
|
||||
if (_session.get_device()->dev_inst()->mode == DSO)
|
||||
_scale = _session.get_device()->get_time_base() * std::pow(10.0, -9.0) * DS_CONF_DSO_HDIVS / get_view_width();
|
||||
|
||||
@ -605,10 +728,10 @@ void View::resizeEvent(QResizeEvent*)
|
||||
|
||||
_scale = min(_scale, _maxscale);
|
||||
|
||||
signals_changed();
|
||||
_ruler->update();
|
||||
_header->header_resize();
|
||||
_need_update = true;
|
||||
set_update(_time_viewport, true);
|
||||
set_update(_fft_viewport, true);
|
||||
}
|
||||
|
||||
void View::h_scroll_value_changed(int value)
|
||||
@ -631,15 +754,14 @@ void View::h_scroll_value_changed(int value)
|
||||
|
||||
if (_offset != _preOffset) {
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
}
|
||||
|
||||
void View::v_scroll_value_changed(int value)
|
||||
{
|
||||
_v_offset = value;
|
||||
_header->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
|
||||
void View::data_updated()
|
||||
@ -651,18 +773,19 @@ void View::data_updated()
|
||||
update_scroll();
|
||||
|
||||
// Repaint the view
|
||||
_need_update = true;
|
||||
_viewport->update();
|
||||
set_update(_time_viewport, true);
|
||||
set_update(_fft_viewport, true);
|
||||
viewport_update();
|
||||
}
|
||||
|
||||
void View::update_margins()
|
||||
{
|
||||
_ruler->setGeometry(_viewport->x(), 0,
|
||||
get_view_width(), _viewport->y());
|
||||
_header->setGeometry(0, _viewport->y(),
|
||||
_viewport->x(), _viewport->height());
|
||||
_ruler->setGeometry(_viewcenter->x(), 0,
|
||||
get_view_width(), _viewcenter->y());
|
||||
_header->setGeometry(0, _viewcenter->y(),
|
||||
_viewcenter->x(), _viewcenter->height());
|
||||
_devmode->setGeometry(0, 0,
|
||||
_viewport->x(), _viewport->y());
|
||||
_viewcenter->x(), _viewcenter->y());
|
||||
}
|
||||
|
||||
void View::header_updated()
|
||||
@ -673,21 +796,21 @@ void View::header_updated()
|
||||
// Update the scroll bars
|
||||
update_scroll();
|
||||
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
_header->update();
|
||||
}
|
||||
|
||||
void View::marker_time_changed()
|
||||
{
|
||||
_ruler->update();
|
||||
_viewport->update();
|
||||
viewport_update();
|
||||
}
|
||||
|
||||
void View::on_traces_moved()
|
||||
{
|
||||
update_scroll();
|
||||
_need_update = true;
|
||||
_viewport->update();
|
||||
set_update(_time_viewport, true);
|
||||
viewport_update();
|
||||
//traces_moved();
|
||||
}
|
||||
|
||||
@ -740,9 +863,18 @@ void View::set_cursor_middle(int index)
|
||||
set_scale_offset(_scale, (*i)->index() * 1.0 / _session.get_device()->get_sample_rate() - _scale * get_view_width() / 2);
|
||||
}
|
||||
|
||||
Viewport * View::get_viewport()
|
||||
void View::on_measure_updated()
|
||||
{
|
||||
return _viewport;
|
||||
_active_viewport = dynamic_cast<Viewport *>(sender());
|
||||
measure_updated();
|
||||
}
|
||||
|
||||
QString View::get_measure(QString option)
|
||||
{
|
||||
if (_active_viewport) {
|
||||
return _active_viewport->get_measure(option);
|
||||
}
|
||||
return "#####";
|
||||
}
|
||||
|
||||
QString View::get_cm_time(int index)
|
||||
@ -782,13 +914,16 @@ void View::on_cursor_moved()
|
||||
|
||||
void View::set_measure_en(int enable)
|
||||
{
|
||||
_viewport->set_measure_en(enable);
|
||||
BOOST_FOREACH(Viewport *viewport, _viewport_list)
|
||||
viewport->set_measure_en(enable);
|
||||
}
|
||||
|
||||
void View::on_state_changed(bool stop)
|
||||
{
|
||||
if (stop)
|
||||
_viewport->stop_trigger_timer();
|
||||
if (stop) {
|
||||
BOOST_FOREACH(Viewport *viewport, _viewport_list)
|
||||
viewport->stop_trigger_timer();
|
||||
}
|
||||
}
|
||||
|
||||
int View::get_view_width()
|
||||
@ -800,7 +935,7 @@ int View::get_view_width()
|
||||
view_width = max((double)view_width, s->get_view_rect().width());
|
||||
}
|
||||
} else {
|
||||
view_width = _viewport->width();
|
||||
view_width = _viewcenter->width();
|
||||
}
|
||||
|
||||
return view_width;
|
||||
@ -815,7 +950,7 @@ int View::get_view_height()
|
||||
view_height = max((double)view_height, s->get_view_rect().height());
|
||||
}
|
||||
} else {
|
||||
view_height = _viewport->width();
|
||||
view_height = _viewcenter->height();
|
||||
}
|
||||
|
||||
return view_height;
|
||||
@ -846,5 +981,19 @@ void View::show_region(uint64_t start, uint64_t end)
|
||||
set_scale_offset(new_scale, new_off);
|
||||
}
|
||||
|
||||
void View::viewport_update()
|
||||
{
|
||||
_viewcenter->update();
|
||||
BOOST_FOREACH(Viewport *viewport, _viewport_list)
|
||||
viewport->update();
|
||||
}
|
||||
|
||||
void View::splitterMoved(int pos, int index)
|
||||
{
|
||||
(void)pos;
|
||||
(void)index;
|
||||
signals_changed();
|
||||
}
|
||||
|
||||
} // namespace view
|
||||
} // namespace pv
|
||||
|
@ -32,12 +32,15 @@
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
||||
#include <QAbstractScrollArea>
|
||||
#include <QScrollArea>
|
||||
#include <QSizeF>
|
||||
#include <QDateTime>
|
||||
#include <QSplitter>
|
||||
|
||||
#include "../../extdef.h"
|
||||
#include "../toolbars/samplingbar.h"
|
||||
#include "../data/signaldata.h"
|
||||
#include "../view/viewport.h"
|
||||
#include "cursor.h"
|
||||
#include "signal.h"
|
||||
|
||||
@ -57,7 +60,7 @@ class Ruler;
|
||||
class Trace;
|
||||
class Viewport;
|
||||
|
||||
class View : public QAbstractScrollArea {
|
||||
class View : public QScrollArea {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
@ -111,7 +114,7 @@ public:
|
||||
void set_scale_offset(double scale, double offset);
|
||||
void set_preScale_preOffset();
|
||||
|
||||
std::vector< boost::shared_ptr<Trace> > get_traces() const;
|
||||
std::vector< boost::shared_ptr<Trace> > get_traces(int type);
|
||||
|
||||
/**
|
||||
* Returns true if cursors are displayed. false otherwise.
|
||||
@ -164,11 +167,10 @@ public:
|
||||
double get_minscale() const;
|
||||
double get_maxscale() const;
|
||||
|
||||
void set_need_update(bool need_update);
|
||||
bool need_update() const;
|
||||
void set_update(Viewport *viewport, bool need_update);
|
||||
void set_all_update(bool need_update);
|
||||
|
||||
uint64_t get_cursor_samples(int index);
|
||||
Viewport * get_viewport();
|
||||
QString get_cm_time(int index);
|
||||
QString get_cm_delta(int index1, int index2);
|
||||
|
||||
@ -187,6 +189,11 @@ public:
|
||||
|
||||
QString trigger_time();
|
||||
|
||||
QString get_measure(QString option);
|
||||
|
||||
void viewport_update();
|
||||
|
||||
|
||||
signals:
|
||||
void hover_point_changed();
|
||||
|
||||
@ -198,6 +205,8 @@ signals:
|
||||
|
||||
void mode_changed();
|
||||
|
||||
void measure_updated();
|
||||
|
||||
private:
|
||||
void get_scroll_layout(double &length, double &offset) const;
|
||||
|
||||
@ -236,12 +245,22 @@ private slots:
|
||||
|
||||
void set_trig_pos(quint64 trig_pos);
|
||||
|
||||
void on_measure_updated();
|
||||
|
||||
void splitterMoved(int pos, int index);
|
||||
|
||||
private:
|
||||
|
||||
SigSession &_session;
|
||||
pv::toolbars::SamplingBar *_sampling_bar;
|
||||
|
||||
Viewport *_viewport;
|
||||
QWidget *_viewcenter;
|
||||
QSplitter *_vsplitter;
|
||||
Viewport * _time_viewport;
|
||||
Viewport * _fft_viewport;
|
||||
Viewport *_active_viewport;
|
||||
std::list<Viewport *> _viewport_list;
|
||||
std::map<int, int> _trace_view_map;
|
||||
Ruler *_ruler;
|
||||
Header *_header;
|
||||
DevMode *_devmode;
|
||||
@ -259,10 +278,7 @@ private:
|
||||
int _spanY;
|
||||
int _signalHeight;
|
||||
|
||||
int _v_offset;
|
||||
bool _updating_scroll;
|
||||
|
||||
bool _need_update;
|
||||
bool _updating_scroll;
|
||||
|
||||
bool _show_cursors;
|
||||
|
||||
|
@ -21,13 +21,13 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "view.h"
|
||||
#include "viewport.h"
|
||||
#include "ruler.h"
|
||||
|
||||
#include "signal.h"
|
||||
#include "dsosignal.h"
|
||||
#include "logicsignal.h"
|
||||
#include "mathtrace.h"
|
||||
#include "../device/devinst.h"
|
||||
#include "../data/logic.h"
|
||||
#include "../data/logicsnapshot.h"
|
||||
@ -52,9 +52,11 @@ namespace view {
|
||||
const double Viewport::DragDamping = 1.05;
|
||||
const double Viewport::MinorDragRateUp = 10;
|
||||
|
||||
Viewport::Viewport(View &parent) :
|
||||
QWidget(&parent),
|
||||
_view(parent),
|
||||
Viewport::Viewport(View &parent, View_type type) :
|
||||
QWidget(&parent),
|
||||
_view(parent),
|
||||
_type(type),
|
||||
_need_update(false),
|
||||
_total_receive_len(0),
|
||||
_action_type(NO_ACTION),
|
||||
_measure_type(NO_MEASURE),
|
||||
@ -100,7 +102,7 @@ int Viewport::get_total_height() const
|
||||
{
|
||||
int h = 0;
|
||||
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view.get_traces());
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view.get_traces(_type));
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces) {
|
||||
assert(t);
|
||||
h += (int)(t->get_totalHeight());
|
||||
@ -126,11 +128,13 @@ void Viewport::paintEvent(QPaintEvent *event)
|
||||
QPainter p(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &o, &p, this);
|
||||
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view.get_traces());
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view.get_traces(_type));
|
||||
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
|
||||
{
|
||||
assert(t);
|
||||
t->paint_back(p, 0, _view.get_view_width());
|
||||
if (t->enabled() && _view.session().get_device()->dev_inst()->mode == DSO)
|
||||
break;
|
||||
}
|
||||
|
||||
p.setRenderHint(QPainter::Antialiasing, false);
|
||||
@ -145,9 +149,11 @@ void Viewport::paintEvent(QPaintEvent *event)
|
||||
break;
|
||||
|
||||
case SigSession::Running:
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
paintProgress(p);
|
||||
p.setRenderHint(QPainter::Antialiasing, false);
|
||||
if (_type == TIME_VIEW) {
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
paintProgress(p);
|
||||
p.setRenderHint(QPainter::Antialiasing, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -172,11 +178,11 @@ void Viewport::paintEvent(QPaintEvent *event)
|
||||
|
||||
void Viewport::paintSignals(QPainter &p)
|
||||
{
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view.get_traces());
|
||||
const vector< boost::shared_ptr<Trace> > traces(_view.get_traces(_type));
|
||||
if (_view.scale() != _curScale ||
|
||||
_view.offset() != _curOffset ||
|
||||
_view.get_signalHeight() != _curSignalHeight ||
|
||||
_view.need_update()) {
|
||||
_need_update) {
|
||||
_curScale = _view.scale();
|
||||
_curOffset = _view.offset();
|
||||
_curSignalHeight = _view.get_signalHeight();
|
||||
@ -190,15 +196,14 @@ void Viewport::paintSignals(QPainter &p)
|
||||
{
|
||||
assert(t);
|
||||
if (t->enabled())
|
||||
t->paint_mid(dbp, 0, _view.get_view_width());
|
||||
t->paint_mid(dbp, 0, t->get_view_rect().width());
|
||||
}
|
||||
|
||||
_view.set_need_update(false);
|
||||
_need_update = false;
|
||||
}
|
||||
p.drawPixmap(0, 0, pixmap);
|
||||
|
||||
// plot cursors
|
||||
if (_view.cursors_shown()) {
|
||||
if (_view.cursors_shown() && _type == TIME_VIEW) {
|
||||
list<Cursor*>::iterator i = _view.get_cursorList().begin();
|
||||
double cursorX;
|
||||
const double samples_per_pixel = _view.session().get_device()->get_sample_rate() * _view.scale();
|
||||
@ -212,22 +217,25 @@ void Viewport::paintSignals(QPainter &p)
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (_view.trig_cursor_shown()) {
|
||||
_view.get_trig_cursor()->paint(p, rect(), 0);
|
||||
}
|
||||
if (_view.search_cursor_shown()) {
|
||||
_view.get_search_cursor()->paint(p, rect(), 0);
|
||||
}
|
||||
|
||||
// plot zoom rect
|
||||
if (_action_type == LOGIC_ZOOM) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Trace::dsLightBlue);
|
||||
p.drawRect(QRectF(_mouse_down_point, _mouse_point));
|
||||
}
|
||||
if (_type == TIME_VIEW) {
|
||||
if (_view.trig_cursor_shown()) {
|
||||
_view.get_trig_cursor()->paint(p, rect(), 0);
|
||||
}
|
||||
if (_view.search_cursor_shown()) {
|
||||
_view.get_search_cursor()->paint(p, rect(), 0);
|
||||
}
|
||||
|
||||
//plot measure arrow
|
||||
paintMeasure(p);
|
||||
// plot zoom rect
|
||||
if (_action_type == LOGIC_ZOOM) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Trace::dsLightBlue);
|
||||
p.drawRect(QRectF(_mouse_down_point, _mouse_point));
|
||||
}
|
||||
|
||||
//plot measure arrow
|
||||
paintMeasure(p);
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::paintProgress(QPainter &p)
|
||||
@ -413,38 +421,51 @@ void Viewport::mouseMoveEvent(QMouseEvent *event)
|
||||
_hover_hit = false;
|
||||
|
||||
if (event->buttons() & Qt::LeftButton) {
|
||||
_view.set_scale_offset(_view.scale(),
|
||||
_mouse_down_offset +
|
||||
(_mouse_down_point - event->pos()).x() *
|
||||
_view.scale());
|
||||
_drag_strength = (_mouse_down_point - event->pos()).x();
|
||||
if (_type == TIME_VIEW) {
|
||||
_view.set_scale_offset(_view.scale(),
|
||||
_mouse_down_offset +
|
||||
(_mouse_down_point - event->pos()).x() *
|
||||
_view.scale());
|
||||
_drag_strength = (_mouse_down_point - event->pos()).x();
|
||||
} else if (_type == FFT_VIEW) {
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> t, _view.session().get_math_signals()) {
|
||||
assert(t);
|
||||
if(t->enabled()) {
|
||||
double delta = (_mouse_point - event->pos()).x();
|
||||
t->set_offset(delta);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(event->buttons() || Qt::NoButton)) {
|
||||
if (_action_type == DSO_TRIG_MOVE) {
|
||||
if (_drag_sig) {
|
||||
boost::shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(_drag_sig))
|
||||
dsoSig->set_trig_vpos(event->pos().y());
|
||||
if (_type == TIME_VIEW) {
|
||||
if (!(event->buttons() || Qt::NoButton)) {
|
||||
if (_action_type == DSO_TRIG_MOVE) {
|
||||
if (_drag_sig) {
|
||||
boost::shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(_drag_sig))
|
||||
dsoSig->set_trig_vpos(event->pos().y());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_action_type == CURS_MOVE) {
|
||||
uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
|
||||
TimeMarker* grabbed_marker = _view.get_ruler()->get_grabbed_cursor();
|
||||
if (_view.cursors_shown() && grabbed_marker) {
|
||||
const double cur_time = _view.offset() + _view.hover_point().x() * _view.scale();
|
||||
const double pos = cur_time * sample_rate;
|
||||
const double pos_delta = pos - (uint64_t)pos;
|
||||
if ( pos_delta < 0.5)
|
||||
grabbed_marker->set_index((uint64_t)floor(pos));
|
||||
else
|
||||
grabbed_marker->set_index((uint64_t)ceil(pos));
|
||||
if (_action_type == CURS_MOVE) {
|
||||
uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
|
||||
TimeMarker* grabbed_marker = _view.get_ruler()->get_grabbed_cursor();
|
||||
if (_view.cursors_shown() && grabbed_marker) {
|
||||
const double cur_time = _view.offset() + _view.hover_point().x() * _view.scale();
|
||||
const double pos = cur_time * sample_rate;
|
||||
const double pos_delta = pos - (uint64_t)pos;
|
||||
if ( pos_delta < 0.5)
|
||||
grabbed_marker->set_index((uint64_t)floor(pos));
|
||||
else
|
||||
grabbed_marker->set_index((uint64_t)ceil(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_action_type == DSO_YM)
|
||||
_dso_ym_end = event->pos().y();
|
||||
if (_action_type == DSO_YM)
|
||||
_dso_ym_end = event->pos().y();
|
||||
}
|
||||
}
|
||||
|
||||
_mouse_point = event->pos();
|
||||
@ -457,177 +478,178 @@ void Viewport::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
assert(event);
|
||||
|
||||
if ((_action_type == NO_ACTION) &&
|
||||
(event->button() == Qt::LeftButton)) {
|
||||
// priority 0
|
||||
if (_action_type == NO_ACTION && _view.cursors_shown()) {
|
||||
list<Cursor*>::iterator i = _view.get_cursorList().begin();
|
||||
double cursorX;
|
||||
const double samples_per_pixel = _view.session().get_device()->get_sample_rate() * _view.scale();
|
||||
while (i != _view.get_cursorList().end()) {
|
||||
cursorX = (*i)->index()/samples_per_pixel - (_view.offset() / _view.scale());
|
||||
if ((*i)->grabbed()) {
|
||||
_view.get_ruler()->rel_grabbed_cursor();
|
||||
} else if (qAbs(cursorX - event->pos().x()) <= HitCursorMargin) {
|
||||
_view.get_ruler()->set_grabbed_cursor(*i);
|
||||
_action_type = CURS_MOVE;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_view.session().get_device()->dev_inst()->mode == LOGIC &&
|
||||
_view.session().get_capture_state() == SigSession::Stopped) {
|
||||
// priority 1
|
||||
if (_action_type == NO_ACTION) {
|
||||
const double strength = _drag_strength*DragTimerInterval*1.0/_time.elapsed();
|
||||
if (_time.elapsed() < 200 &&
|
||||
abs(_drag_strength) < MinorDragOffsetUp &&
|
||||
abs(strength) > MinorDragRateUp) {
|
||||
_drag_strength = _drag_strength;
|
||||
_drag_timer.start(DragTimerInterval);
|
||||
_action_type = LOGIC_MOVE;
|
||||
} else if (_time.elapsed() < 200 &&
|
||||
abs(strength) > DragTimerInterval) {
|
||||
_drag_strength = strength * 5;
|
||||
_drag_timer.start(DragTimerInterval);
|
||||
_action_type = LOGIC_MOVE;
|
||||
if (_type == TIME_VIEW) {
|
||||
if ((_action_type == NO_ACTION) &&
|
||||
(event->button() == Qt::LeftButton)) {
|
||||
// priority 0
|
||||
if (_action_type == NO_ACTION && _view.cursors_shown()) {
|
||||
list<Cursor*>::iterator i = _view.get_cursorList().begin();
|
||||
double cursorX;
|
||||
const double samples_per_pixel = _view.session().get_device()->get_sample_rate() * _view.scale();
|
||||
while (i != _view.get_cursorList().end()) {
|
||||
cursorX = (*i)->index()/samples_per_pixel - (_view.offset() / _view.scale());
|
||||
if ((*i)->grabbed()) {
|
||||
_view.get_ruler()->rel_grabbed_cursor();
|
||||
} else if (qAbs(cursorX - event->pos().x()) <= HitCursorMargin) {
|
||||
_view.get_ruler()->set_grabbed_cursor(*i);
|
||||
_action_type = CURS_MOVE;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// priority 2
|
||||
if (_action_type == NO_ACTION) {
|
||||
if (_mouse_down_point.x() == event->pos().x()) {
|
||||
if (_view.session().get_device()->dev_inst()->mode == LOGIC &&
|
||||
_view.session().get_capture_state() == SigSession::Stopped) {
|
||||
// priority 1
|
||||
if (_action_type == NO_ACTION) {
|
||||
const double strength = _drag_strength*DragTimerInterval*1.0/_time.elapsed();
|
||||
if (_time.elapsed() < 200 &&
|
||||
abs(_drag_strength) < MinorDragOffsetUp &&
|
||||
abs(strength) > MinorDragRateUp) {
|
||||
_drag_strength = _drag_strength;
|
||||
_drag_timer.start(DragTimerInterval);
|
||||
_action_type = LOGIC_MOVE;
|
||||
} else if (_time.elapsed() < 200 &&
|
||||
abs(strength) > DragTimerInterval) {
|
||||
_drag_strength = strength * 5;
|
||||
_drag_timer.start(DragTimerInterval);
|
||||
_action_type = LOGIC_MOVE;
|
||||
}
|
||||
}
|
||||
|
||||
// priority 2
|
||||
if (_action_type == NO_ACTION) {
|
||||
if (_mouse_down_point.x() == event->pos().x()) {
|
||||
const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals());
|
||||
BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
|
||||
assert(s);
|
||||
if (abs(event->pos().y() - s->get_y()) < _view.get_signalHeight()) {
|
||||
_action_type = LOGIC_EDGE;
|
||||
_edge_start = (_view.offset() + (event->pos().x() + 0.5) * _view.scale()) * _view.session().get_device()->get_sample_rate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (_view.session().get_device()->dev_inst()->mode == DSO) {
|
||||
// priority 0
|
||||
if (_action_type == NO_ACTION && _hover_hit) {
|
||||
_action_type = DSO_YM;
|
||||
_dso_ym_valid = true;
|
||||
_dso_ym_sig_index = _hover_sig_index;
|
||||
_dso_ym_sig_value = _hover_sig_value;
|
||||
_dso_ym_index = _hover_index;
|
||||
_dso_ym_start = event->pos().y();
|
||||
}
|
||||
|
||||
// priority 1
|
||||
if (_action_type == NO_ACTION) {
|
||||
const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals());
|
||||
BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
|
||||
assert(s);
|
||||
if (abs(event->pos().y() - s->get_y()) < _view.get_signalHeight()) {
|
||||
_action_type = LOGIC_EDGE;
|
||||
_edge_start = (_view.offset() + (event->pos().x() + 0.5) * _view.scale()) * _view.session().get_device()->get_sample_rate();
|
||||
break;
|
||||
if (!s->enabled())
|
||||
continue;
|
||||
boost::shared_ptr<DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<DsoSignal>(s)) {
|
||||
if (dsoSig->get_trig_rect(0, _view.get_view_width()).contains(_mouse_point)) {
|
||||
_drag_sig = s;
|
||||
_action_type = DSO_TRIG_MOVE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (_view.session().get_device()->dev_inst()->mode == DSO) {
|
||||
// priority 0
|
||||
if (_action_type == NO_ACTION && _hover_hit) {
|
||||
_action_type = DSO_YM;
|
||||
_dso_ym_valid = true;
|
||||
_dso_ym_sig_index = _hover_sig_index;
|
||||
_dso_ym_sig_value = _hover_sig_value;
|
||||
_dso_ym_index = _hover_index;
|
||||
_dso_ym_start = event->pos().y();
|
||||
} else if (_action_type == DSO_YM) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
_dso_ym_end = event->pos().y();
|
||||
_action_type = NO_ACTION;
|
||||
} else if (event->button() == Qt::RightButton) {
|
||||
_action_type = NO_ACTION;
|
||||
_dso_ym_valid = false;
|
||||
}
|
||||
} else if (_action_type == DSO_TRIG_MOVE) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
_drag_sig.reset();
|
||||
_action_type = NO_ACTION;
|
||||
}
|
||||
} else if (_action_type == DSO_XM_STEP0) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
_action_type = DSO_XM_STEP1;
|
||||
_dso_xm_valid = true;
|
||||
}
|
||||
} else if (_action_type == DSO_XM_STEP1) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
const uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
|
||||
const double scale = _view.scale();
|
||||
const double samples_per_pixel = sample_rate * scale;
|
||||
|
||||
// priority 1
|
||||
if (_action_type == NO_ACTION) {
|
||||
const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals());
|
||||
BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
|
||||
assert(s);
|
||||
if (!s->enabled())
|
||||
continue;
|
||||
boost::shared_ptr<DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<DsoSignal>(s)) {
|
||||
if (dsoSig->get_trig_rect(0, _view.get_view_width()).contains(_mouse_point)) {
|
||||
_drag_sig = s;
|
||||
_action_type = DSO_TRIG_MOVE;
|
||||
break;
|
||||
}
|
||||
_dso_xm_index[1] = event->pos().x() * samples_per_pixel + _view.offset() * sample_rate;
|
||||
const uint64_t max_index = max(_dso_xm_index[0], _dso_xm_index[1]);
|
||||
_dso_xm_index[0] = min(_dso_xm_index[0], _dso_xm_index[1]);
|
||||
_dso_xm_index[1] = max_index;
|
||||
|
||||
_action_type = DSO_XM_STEP2;
|
||||
} else if (event->button() == Qt::RightButton) {
|
||||
_action_type = NO_ACTION;
|
||||
_dso_xm_valid = false;
|
||||
_mm_width = "#####";
|
||||
_mm_period = "#####";
|
||||
_mm_freq = "#####";
|
||||
_mm_duty = "#####";
|
||||
measure_updated();
|
||||
}
|
||||
} else if (_action_type == DSO_XM_STEP2) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
const uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
|
||||
const double scale = _view.scale();
|
||||
const double samples_per_pixel = sample_rate * scale;
|
||||
_dso_xm_index[2] = event->pos().x() * samples_per_pixel + _view.offset() * sample_rate;
|
||||
const uint64_t max_index = max(_dso_xm_index[1], _dso_xm_index[2]);
|
||||
_dso_xm_index[1] = min(_dso_xm_index[1], _dso_xm_index[2]);
|
||||
_dso_xm_index[2] = max_index;
|
||||
|
||||
_action_type = NO_ACTION;
|
||||
} else if (event->button() == Qt::RightButton) {
|
||||
_action_type = NO_ACTION;
|
||||
_dso_xm_valid = false;
|
||||
_mm_width = "#####";
|
||||
_mm_period = "#####";
|
||||
_mm_freq = "#####";
|
||||
_mm_duty = "#####";
|
||||
measure_updated();
|
||||
}
|
||||
} else if (_action_type == CURS_MOVE) {
|
||||
_action_type = NO_ACTION;
|
||||
if (_view.cursors_shown()) {
|
||||
list<Cursor*>::iterator i = _view.get_cursorList().begin();
|
||||
while (i != _view.get_cursorList().end()) {
|
||||
if ((*i)->grabbed()) {
|
||||
_view.get_ruler()->rel_grabbed_cursor();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (_action_type == DSO_YM) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
_dso_ym_end = event->pos().y();
|
||||
} else if (_action_type == LOGIC_EDGE) {
|
||||
_action_type = NO_ACTION;
|
||||
} else if (event->button() == Qt::RightButton) {
|
||||
_edge_rising = 0;
|
||||
_edge_falling = 0;
|
||||
} else if (_action_type == LOGIC_MOVE) {
|
||||
_drag_strength = 0;
|
||||
_drag_timer.stop();
|
||||
_action_type = NO_ACTION;
|
||||
_dso_ym_valid = false;
|
||||
}
|
||||
} else if (_action_type == DSO_TRIG_MOVE) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
_drag_sig.reset();
|
||||
_action_type = NO_ACTION;
|
||||
}
|
||||
} else if (_action_type == DSO_XM_STEP0) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
_action_type = DSO_XM_STEP1;
|
||||
_dso_xm_valid = true;
|
||||
}
|
||||
} else if (_action_type == DSO_XM_STEP1) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
const uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
|
||||
const double scale = _view.scale();
|
||||
const double samples_per_pixel = sample_rate * scale;
|
||||
|
||||
_dso_xm_index[1] = event->pos().x() * samples_per_pixel + _view.offset() * sample_rate;
|
||||
const uint64_t max_index = max(_dso_xm_index[0], _dso_xm_index[1]);
|
||||
_dso_xm_index[0] = min(_dso_xm_index[0], _dso_xm_index[1]);
|
||||
_dso_xm_index[1] = max_index;
|
||||
|
||||
_action_type = DSO_XM_STEP2;
|
||||
} else if (event->button() == Qt::RightButton) {
|
||||
_action_type = NO_ACTION;
|
||||
_dso_xm_valid = false;
|
||||
_mm_width = "#####";
|
||||
_mm_period = "#####";
|
||||
_mm_freq = "#####";
|
||||
_mm_duty = "#####";
|
||||
measure_updated();
|
||||
}
|
||||
} else if (_action_type == DSO_XM_STEP2) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
const uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
|
||||
const double scale = _view.scale();
|
||||
const double samples_per_pixel = sample_rate * scale;
|
||||
_dso_xm_index[2] = event->pos().x() * samples_per_pixel + _view.offset() * sample_rate;
|
||||
const uint64_t max_index = max(_dso_xm_index[1], _dso_xm_index[2]);
|
||||
_dso_xm_index[1] = min(_dso_xm_index[1], _dso_xm_index[2]);
|
||||
_dso_xm_index[2] = max_index;
|
||||
|
||||
_action_type = NO_ACTION;
|
||||
} else if (event->button() == Qt::RightButton) {
|
||||
_action_type = NO_ACTION;
|
||||
_dso_xm_valid = false;
|
||||
_mm_width = "#####";
|
||||
_mm_period = "#####";
|
||||
_mm_freq = "#####";
|
||||
_mm_duty = "#####";
|
||||
measure_updated();
|
||||
}
|
||||
} else if (_action_type == CURS_MOVE) {
|
||||
_action_type = NO_ACTION;
|
||||
if (_view.cursors_shown()) {
|
||||
list<Cursor*>::iterator i = _view.get_cursorList().begin();
|
||||
while (i != _view.get_cursorList().end()) {
|
||||
if ((*i)->grabbed()) {
|
||||
_view.get_ruler()->rel_grabbed_cursor();
|
||||
}
|
||||
i++;
|
||||
} else if (_action_type == LOGIC_ZOOM) {
|
||||
if (event->pos().x() != _mouse_down_point.x()) {
|
||||
const double newOffset = _view.offset() + (min(event->pos().x(), _mouse_down_point.x()) + 0.5) * _view.scale();
|
||||
const double newScale = max(min(_view.scale() * abs(event->pos().x() - _mouse_down_point.x()) / _view.get_view_width(),
|
||||
_view.get_maxscale()), _view.get_minscale());
|
||||
if (newScale != _view.scale())
|
||||
_view.set_scale_offset(newScale, newOffset);
|
||||
}
|
||||
_action_type = NO_ACTION;
|
||||
}
|
||||
} else if (_action_type == LOGIC_EDGE) {
|
||||
_action_type = NO_ACTION;
|
||||
_edge_rising = 0;
|
||||
_edge_falling = 0;
|
||||
} else if (_action_type == LOGIC_MOVE) {
|
||||
_drag_strength = 0;
|
||||
_drag_timer.stop();
|
||||
_action_type = NO_ACTION;
|
||||
} else if (_action_type == LOGIC_ZOOM) {
|
||||
if (event->pos().x() != _mouse_down_point.x()) {
|
||||
const double newOffset = _view.offset() + (min(event->pos().x(), _mouse_down_point.x()) + 0.5) * _view.scale();
|
||||
const double newScale = max(min(_view.scale() * abs(event->pos().x() - _mouse_down_point.x()) / _view.get_view_width(),
|
||||
_view.get_maxscale()), _view.get_minscale());
|
||||
if (newScale != _view.scale())
|
||||
_view.set_scale_offset(newScale, newOffset);
|
||||
}
|
||||
_action_type = NO_ACTION;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
@ -676,16 +698,26 @@ void Viewport::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
assert(event);
|
||||
|
||||
if (event->orientation() == Qt::Vertical) {
|
||||
// Vertical scrolling is interpreted as zooming in/out
|
||||
const double offset = event->x();
|
||||
_view.zoom(event->delta() / 80, offset);
|
||||
} else if (event->orientation() == Qt::Horizontal) {
|
||||
// Horizontal scrolling is interpreted as moving left/right
|
||||
_view.set_scale_offset(_view.scale(),
|
||||
event->delta() * _view.scale()
|
||||
+ _view.offset());
|
||||
}
|
||||
if (_type == FFT_VIEW) {
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> t, _view.session().get_math_signals()) {
|
||||
assert(t);
|
||||
if(t->enabled()) {
|
||||
t->zoom(event->delta() / 80, event->x());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_type == TIME_VIEW){
|
||||
if (event->orientation() == Qt::Vertical) {
|
||||
// Vertical scrolling is interpreted as zooming in/out
|
||||
const double offset = event->x();
|
||||
_view.zoom(event->delta() / 80, offset);
|
||||
} else if (event->orientation() == Qt::Horizontal) {
|
||||
// Horizontal scrolling is interpreted as moving left/right
|
||||
_view.set_scale_offset(_view.scale(),
|
||||
event->delta() * _view.scale()
|
||||
+ _view.offset());
|
||||
}
|
||||
}
|
||||
|
||||
measure();
|
||||
}
|
||||
@ -759,62 +791,72 @@ void Viewport::clear_measure()
|
||||
void Viewport::measure()
|
||||
{
|
||||
_measure_type = NO_MEASURE;
|
||||
const uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
|
||||
const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals());
|
||||
BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
|
||||
assert(s);
|
||||
boost::shared_ptr<view::LogicSignal> logicSig;
|
||||
boost::shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (logicSig = dynamic_pointer_cast<view::LogicSignal>(s)) {
|
||||
if (_action_type == NO_ACTION) {
|
||||
if (logicSig->measure(_mouse_point, _cur_sample, _nxt_sample, _thd_sample)) {
|
||||
_measure_type = LOGIC_FREQ;
|
||||
if (_type == TIME_VIEW) {
|
||||
const uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
|
||||
const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals());
|
||||
BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
|
||||
assert(s);
|
||||
boost::shared_ptr<view::LogicSignal> logicSig;
|
||||
boost::shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (logicSig = dynamic_pointer_cast<view::LogicSignal>(s)) {
|
||||
if (_action_type == NO_ACTION) {
|
||||
if (logicSig->measure(_mouse_point, _cur_sample, _nxt_sample, _thd_sample)) {
|
||||
_measure_type = LOGIC_FREQ;
|
||||
|
||||
_mm_width = _view.get_ruler()->format_real_time(_nxt_sample - _cur_sample, sample_rate);
|
||||
_mm_period = _thd_sample != 0 ? _view.get_ruler()->format_real_time(_thd_sample - _cur_sample, sample_rate) : "#####";
|
||||
_mm_freq = _thd_sample != 0 ? _view.get_ruler()->format_real_freq(_thd_sample - _cur_sample, sample_rate) : "#####";
|
||||
_mm_width = _view.get_ruler()->format_real_time(_nxt_sample - _cur_sample, sample_rate);
|
||||
_mm_period = _thd_sample != 0 ? _view.get_ruler()->format_real_time(_thd_sample - _cur_sample, sample_rate) : "#####";
|
||||
_mm_freq = _thd_sample != 0 ? _view.get_ruler()->format_real_freq(_thd_sample - _cur_sample, sample_rate) : "#####";
|
||||
|
||||
const double pixels_offset = _view.offset() / _view.scale();
|
||||
const double samples_per_pixel = sample_rate * _view.scale();
|
||||
_cur_preX = _cur_sample / samples_per_pixel - pixels_offset;
|
||||
_cur_aftX = _nxt_sample / samples_per_pixel - pixels_offset;
|
||||
_cur_thdX = _thd_sample / samples_per_pixel - pixels_offset;
|
||||
_cur_midY = logicSig->get_y();
|
||||
const double pixels_offset = _view.offset() / _view.scale();
|
||||
const double samples_per_pixel = sample_rate * _view.scale();
|
||||
_cur_preX = _cur_sample / samples_per_pixel - pixels_offset;
|
||||
_cur_aftX = _nxt_sample / samples_per_pixel - pixels_offset;
|
||||
_cur_thdX = _thd_sample / samples_per_pixel - pixels_offset;
|
||||
_cur_midY = logicSig->get_y();
|
||||
|
||||
_mm_duty = _thd_sample != 0 ? QString::number((_nxt_sample - _cur_sample) * 100.0 / (_thd_sample - _cur_sample), 'f', 2)+"%" :
|
||||
"#####";
|
||||
_mm_duty = _thd_sample != 0 ? QString::number((_nxt_sample - _cur_sample) * 100.0 / (_thd_sample - _cur_sample), 'f', 2)+"%" :
|
||||
"#####";
|
||||
break;
|
||||
} else {
|
||||
_measure_type = NO_MEASURE;
|
||||
_mm_width = "#####";
|
||||
_mm_period = "#####";
|
||||
_mm_freq = "#####";
|
||||
_mm_duty = "#####";
|
||||
}
|
||||
} else if (_action_type == LOGIC_EDGE) {
|
||||
if (logicSig->edges(_view.hover_point(), _edge_start, _edge_rising, _edge_falling)) {
|
||||
const double pixels_offset = _view.offset() / _view.scale();
|
||||
const double samples_per_pixel = sample_rate * _view.scale();
|
||||
_cur_preX = _edge_start / samples_per_pixel - pixels_offset;
|
||||
_cur_aftX = _view.hover_point().x();
|
||||
_cur_midY = logicSig->get_y() - logicSig->get_totalHeight()/2 - 5;
|
||||
|
||||
_em_rising = "Rising: " + QString::number(_edge_rising);
|
||||
_em_falling = "Falling: " + QString::number(_edge_falling);
|
||||
_em_edges = "Edges: " + QString::number(_edge_rising + _edge_falling);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
|
||||
if (_measure_en && dsoSig->measure(_view.hover_point())) {
|
||||
_measure_type = DSO_VALUE;
|
||||
break;
|
||||
} else {
|
||||
_measure_type = NO_MEASURE;
|
||||
_mm_width = "#####";
|
||||
_mm_period = "#####";
|
||||
_mm_freq = "#####";
|
||||
_mm_duty = "#####";
|
||||
}
|
||||
} else if (_action_type == LOGIC_EDGE) {
|
||||
if (logicSig->edges(_view.hover_point(), _edge_start, _edge_rising, _edge_falling)) {
|
||||
const double pixels_offset = _view.offset() / _view.scale();
|
||||
const double samples_per_pixel = sample_rate * _view.scale();
|
||||
_cur_preX = _edge_start / samples_per_pixel - pixels_offset;
|
||||
_cur_aftX = _view.hover_point().x();
|
||||
_cur_midY = logicSig->get_y() - logicSig->get_totalHeight()/2 - 5;
|
||||
|
||||
_em_rising = "Rising: " + QString::number(_edge_rising);
|
||||
_em_falling = "Falling: " + QString::number(_edge_falling);
|
||||
_em_edges = "Edges: " + QString::number(_edge_rising + _edge_falling);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
|
||||
if (_measure_en && dsoSig->measure(_view.hover_point())) {
|
||||
_measure_type = DSO_VALUE;
|
||||
break;
|
||||
} else {
|
||||
_measure_type = NO_MEASURE;
|
||||
}
|
||||
} else if (_type == FFT_VIEW) {
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> t, _view.session().get_math_signals()) {
|
||||
assert(t);
|
||||
if(t->enabled()) {
|
||||
t->measure(_view.hover_point());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
measure_updated();
|
||||
}
|
||||
|
||||
@ -1065,7 +1107,7 @@ void Viewport::paintMeasure(QPainter &p)
|
||||
p.drawLine(x[dso_xm_stage-1], _dso_xm_y,
|
||||
_mouse_point.x(), _dso_xm_y);
|
||||
p.drawLine(_mouse_point.x(), 0,
|
||||
_mouse_point.x(), _view.get_viewport()->height());
|
||||
_mouse_point.x(), height());
|
||||
}
|
||||
measure_updated();
|
||||
}
|
||||
@ -1179,5 +1221,11 @@ void Viewport::paintTrigTime(QPainter &p)
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::set_need_update(bool update)
|
||||
{
|
||||
_need_update = update;
|
||||
}
|
||||
|
||||
|
||||
} // namespace view
|
||||
} // namespace pv
|
||||
|
@ -30,8 +30,12 @@
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../../extdef.h"
|
||||
#include "../view/view.h"
|
||||
|
||||
class QPainter;
|
||||
class QPaintEvent;
|
||||
class SigSession;
|
||||
@ -81,7 +85,7 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Viewport(View &parent);
|
||||
explicit Viewport(View &parent, View_type type);
|
||||
|
||||
int get_total_height() const;
|
||||
|
||||
@ -96,6 +100,8 @@ public:
|
||||
|
||||
void clear_measure();
|
||||
|
||||
void set_need_update(bool update);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
|
||||
@ -125,6 +131,8 @@ signals:
|
||||
|
||||
private:
|
||||
View &_view;
|
||||
View_type _type;
|
||||
bool _need_update;
|
||||
|
||||
uint64_t _total_receive_len;
|
||||
QPoint _mouse_point;
|
||||
|
@ -247,6 +247,9 @@ static const uint64_t samplerates[] = {
|
||||
// SR_MB(4),
|
||||
// SR_MB(8),
|
||||
// SR_MB(16),
|
||||
// SR_MB(32),
|
||||
// SR_MB(64),
|
||||
// SR_MB(128),
|
||||
//};
|
||||
|
||||
static const uint64_t samplecounts[] = {
|
||||
@ -270,10 +273,10 @@ static const uint64_t samplecounts[] = {
|
||||
|
||||
/* We name the probes 0-7 on our demo driver. */
|
||||
static const char *probe_names[NUM_PROBES + 1] = {
|
||||
"Channel 0", "Channel 1", "Channel 2", "Channel 3",
|
||||
"Channel 4", "Channel 5", "Channel 6", "Channel 7",
|
||||
"Channel 8", "Channel 9", "Channel 10", "Channel 11",
|
||||
"Channel 12", "Channel 13", "Channel 14", "Channel 15",
|
||||
"CH0", "CH1", "CH2", "CH3",
|
||||
"CH4", "CH5", "CH6", "CH7",
|
||||
"CH8", "CH9", "CH10", "CH11",
|
||||
"CH12", "CH13", "CH14", "CH15",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -549,6 +549,7 @@ enum {
|
||||
SR_CHANNEL_ANALOG,
|
||||
SR_CHANNEL_GROUP,
|
||||
SR_CHANNEL_DECODER,
|
||||
SR_CHANNEL_FFT,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -560,7 +561,7 @@ enum {
|
||||
struct sr_channel {
|
||||
/* The index field will go: use g_slist_length(sdi->channels) instead. */
|
||||
uint16_t index;
|
||||
int type;
|
||||
int type;
|
||||
gboolean enabled;
|
||||
char *name;
|
||||
char *trigger;
|
||||
|