diff --git a/DSView/pv/data/logicsnapshot.cpp b/DSView/pv/data/logicsnapshot.cpp index b78b9a9f..2b53292e 100644 --- a/DSView/pv/data/logicsnapshot.cpp +++ b/DSView/pv/data/logicsnapshot.cpp @@ -252,7 +252,7 @@ bool LogicSnapshot::get_nxt_edge( unsigned int level; bool fast_forward; - assert(index > 0); + //assert(index > 0); const unsigned int min_level = max((int)floorf(logf(min_length) / LogMipMapScaleFactor) - 1, 0); diff --git a/DSView/pv/view/logicsignal.cpp b/DSView/pv/view/logicsignal.cpp index 3b2527d6..f52282ce 100644 --- a/DSView/pv/view/logicsignal.cpp +++ b/DSView/pv/view/logicsignal.cpp @@ -324,5 +324,49 @@ bool LogicSignal::measure(const QPointF &p, uint64_t &index0, uint64_t &index1, return false; } + +bool LogicSignal::edges(const QPointF &p, uint64_t start, uint64_t &rising, uint64_t &falling) const +{ + uint64_t index, end; + const float gap = abs(p.y() - get_y()); + if (gap < get_signalHeight() * 0.5) { + const deque< boost::shared_ptr > &snapshots = + _data->get_snapshots(); + if (snapshots.empty()) + return false; + + const boost::shared_ptr &snapshot = + snapshots.front(); + if (snapshot->buf_null()) + return false; + + end = _data->samplerate() * (_view->offset() - _data->get_start_time() + p.x() * _view->scale()); + index = min(start, end); + end = max(start, end); + start = index; + if (end > (snapshot->get_sample_count() - 1)) + return false; + + const uint64_t sig_mask = 1ULL << get_index(); + bool sample = snapshot->get_sample(start) & sig_mask; + + rising = 0; + falling = 0; + do { + if (snapshot->get_nxt_edge(index, sample, snapshot->get_sample_count(), 1, get_index())) { + if (index > end) + break; + rising += !sample; + falling += sample; + sample = !sample; + } else { + break; + } + } while(index <= end); + return true; + } + return false; +} + } // namespace view } // namespace pv diff --git a/DSView/pv/view/logicsignal.h b/DSView/pv/view/logicsignal.h index 9a03464f..5a3a444e 100644 --- a/DSView/pv/view/logicsignal.h +++ b/DSView/pv/view/logicsignal.h @@ -82,6 +82,8 @@ public: bool measure(const QPointF &p, uint64_t &index0, uint64_t &index1, uint64_t &index2) const; + bool edges(const QPointF &p, uint64_t start, uint64_t &rising, uint64_t &falling) const; + protected: void paint_type_options(QPainter &p, int right, bool hover, int action); diff --git a/DSView/pv/view/viewport.cpp b/DSView/pv/view/viewport.cpp index 6e3bc1b1..bc781a61 100644 --- a/DSView/pv/view/viewport.cpp +++ b/DSView/pv/view/viewport.cpp @@ -511,16 +511,34 @@ void Viewport::mouseReleaseEvent(QMouseEvent *event) if(_drag_sig) _drag_sig.reset(); - const double strength = _drag_strength*DragTimerInterval*1.0/_time.elapsed(); - if (abs(_drag_strength) < MinorDragOffsetUp && abs(strength) > MinorDragRateUp) { - _drag_strength = _drag_strength; - _drag_timer.start(DragTimerInterval); - } else if (abs(strength) > DragTimerInterval) { - _drag_strength = strength * 5; - _drag_timer.start(DragTimerInterval); - } else { - _drag_strength = 0; - _drag_timer.stop(); + if (_mouse_down_point.x() == event->pos().x() && + event->button() & Qt::LeftButton) { + if (_measure_type == LOGIC_EDGE) { + _measure_type = NO_MEASURE; + _measure_shown = false; + _edge_rising = 0; + _edge_falling = 0; + } else if (_measure_type != LOGIC_MOVE) { + _measure_type = LOGIC_EDGE; + _edge_start = (_view.offset() + (event->pos().x() + 0.5) * _view.scale()) * _view.session().get_device()->get_sample_rate(); + } + } + + if (_measure_type != LOGIC_EDGE) { + const double strength = _drag_strength*DragTimerInterval*1.0/_time.elapsed(); + if (abs(_drag_strength) < MinorDragOffsetUp && abs(strength) > MinorDragRateUp) { + _drag_strength = _drag_strength; + _drag_timer.start(DragTimerInterval); + _measure_type = LOGIC_MOVE; + } else if (abs(strength) > DragTimerInterval) { + _drag_strength = strength * 5; + _drag_timer.start(DragTimerInterval); + _measure_type = LOGIC_MOVE; + } else { + _drag_strength = 0; + _drag_timer.stop(); + _measure_type = NO_MEASURE; + } } update(); @@ -593,6 +611,10 @@ void Viewport::leaveEvent(QEvent *) _measure_shown = _dso_xm || _dso_ym; _mouse_point = QPoint(-1, -1); //_view.show_cursors(false); + if (_measure_type == LOGIC_EDGE) { + _measure_type = NO_MEASURE; + _measure_shown = false; + } update(); } @@ -622,46 +644,62 @@ void Viewport::measure() _view.session().get_capture_state() == SigSession::Running) || _drag_strength != 0) return; - _measure_shown = _dso_xm || _dso_ym; - const uint64_t sample_rate = _view.session().get_device()->get_sample_rate(); - const vector< boost::shared_ptr > sigs(_view.session().get_signals()); - BOOST_FOREACH(const boost::shared_ptr s, sigs) { - assert(s); - boost::shared_ptr logicSig; - boost::shared_ptr dsoSig; - if (logicSig = dynamic_pointer_cast(s)) { - if (logicSig->measure(_view.hover_point(), _cur_sample, _nxt_sample, _thd_sample)) { - _measure_shown = true; - _measure_type = LOGIC_FREQ; + _measure_shown = _dso_xm || _dso_ym; + const uint64_t sample_rate = _view.session().get_device()->get_sample_rate(); + const vector< boost::shared_ptr > sigs(_view.session().get_signals()); + BOOST_FOREACH(const boost::shared_ptr s, sigs) { + assert(s); + boost::shared_ptr logicSig; + boost::shared_ptr dsoSig; + if (logicSig = dynamic_pointer_cast(s)) { + if (_measure_type != LOGIC_EDGE && + logicSig->measure(_view.hover_point(), _cur_sample, _nxt_sample, _thd_sample)) { + _measure_shown = true; + _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)+"%" : "#####"; - mouse_measure(); - break; - } else { - _mm_width = "#####"; - _mm_period = "#####"; - _mm_freq = "#####"; - _mm_duty = "#####"; - } - mouse_measure(); - } else if (dsoSig = dynamic_pointer_cast(s)) { - if (_measure_en && dsoSig->measure(_view.hover_point())) { - _measure_shown = true; - _measure_type = DSO_FREQ; - } - } + mouse_measure(); + break; + } else if (_measure_type == LOGIC_EDGE && + logicSig->edges(_view.hover_point(), _edge_start, _edge_rising, _edge_falling)) { + _measure_shown = true; + + 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_signalHeight()/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 { + _mm_width = "#####"; + _mm_period = "#####"; + _mm_freq = "#####"; + _mm_duty = "#####"; + } + mouse_measure(); + } else if (dsoSig = dynamic_pointer_cast(s)) { + if (_measure_en && dsoSig->measure(_view.hover_point())) { + _measure_shown = true; + _measure_type = DSO_FREQ; + } + } } } @@ -721,6 +759,43 @@ void Viewport::paintMeasure(QPainter &p) p.drawText(measure4_rect, Qt::AlignRight | Qt::AlignVCenter, tr("Duty Cycle: ") + _mm_duty); } + } else if (_measure_type == LOGIC_EDGE) { + p.setPen(QColor(17, 133, 209, 255)); + + p.drawLine(QLineF(_cur_preX, _cur_midY-5, _cur_preX, _cur_midY+5)); + p.drawLine(QLineF(_cur_aftX, _cur_midY-5, _cur_aftX, _cur_midY+5)); + p.drawLine(QLineF(_cur_preX, _cur_midY, _cur_aftX, _cur_midY)); + + int typical_width = p.boundingRect(0, 0, INT_MAX, INT_MAX, + Qt::AlignLeft | Qt::AlignTop, _em_edges).width(); + typical_width = max(typical_width, p.boundingRect(0, 0, INT_MAX, INT_MAX, + Qt::AlignLeft | Qt::AlignTop, _em_rising).width()); + typical_width = max(typical_width, p.boundingRect(0, 0, INT_MAX, INT_MAX, + Qt::AlignLeft | Qt::AlignTop, _em_falling).width()); + + typical_width = typical_width + 30; + + const double width = _view.get_view_width(); + const double height = _view.viewport()->height(); + const double left = _view.hover_point().x(); + const double top = _view.hover_point().y(); + const double right = left + typical_width; + const double bottom = top + 60; + QPointF org_pos = QPointF(right > width ? left - typical_width : left, bottom > height ? top - 80 : top); + QRectF measure_rect = QRectF(org_pos.x(), org_pos.y(), (double)typical_width, 60.0); + QRectF measure1_rect = QRectF(org_pos.x(), org_pos.y(), (double)typical_width, 20.0); + QRectF measure2_rect = QRectF(org_pos.x(), org_pos.y()+20, (double)typical_width, 20.0); + QRectF measure3_rect = QRectF(org_pos.x(), org_pos.y()+40, (double)typical_width, 20.0); + + p.setPen(Qt::NoPen); + p.setBrush(QColor(17, 133, 209, 150)); + p.drawRect(measure_rect); + + p.setPen(Qt::black); + p.drawText(measure1_rect, Qt::AlignRight | Qt::AlignVCenter, _em_edges); + p.drawText(measure2_rect, Qt::AlignRight | Qt::AlignVCenter, _em_rising); + p.drawText(measure3_rect, Qt::AlignRight | Qt::AlignVCenter, _em_falling); + } else if (_measure_type == DSO_FREQ) { const vector< boost::shared_ptr > sigs(_view.session().get_signals()); BOOST_FOREACH(const boost::shared_ptr s, sigs) { diff --git a/DSView/pv/view/viewport.h b/DSView/pv/view/viewport.h index 6a0f8909..9c0da6be 100644 --- a/DSView/pv/view/viewport.h +++ b/DSView/pv/view/viewport.h @@ -57,6 +57,8 @@ public: enum MeasureType { NO_MEASURE, LOGIC_FREQ, + LOGIC_EDGE, + LOGIC_MOVE, DSO_FREQ }; @@ -118,7 +120,7 @@ private: bool _measure_en; bool _measure_shown; - int _measure_type; + MeasureType _measure_type; uint64_t _cur_sample; uint64_t _nxt_sample; uint64_t _thd_sample; @@ -131,6 +133,13 @@ private: QString _mm_freq; QString _mm_duty; + uint64_t _edge_rising; + uint64_t _edge_falling; + uint64_t _edge_start; + QString _em_rising; + QString _em_falling; + QString _em_edges; + QTimer trigger_timer; bool triggered; int timer_cnt;