Commit f8b2d1e4 authored by DreamSourceLab's avatar DreamSourceLab
Browse files

Add FFT function @ DSO mode

parent ced33961
......@@ -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)
{
......
#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
#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;
......
This diff is collapsed.
......@@ -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;
......
This diff is collapsed.
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment