27 #include <QApplication> 28 #include <QFormLayout> 42 #include <libsigrokcxx/libsigrokcxx.hpp> 49 using std::out_of_range;
51 using std::shared_ptr;
54 using sigrok::ConfigKey;
55 using sigrok::Capability;
56 using sigrok::Trigger;
57 using sigrok::TriggerMatch;
58 using sigrok::TriggerMatchType;
77 ":/icons/trigger-marker-low.svg",
78 ":/icons/trigger-marker-high.svg",
79 ":/icons/trigger-marker-rising.svg",
80 ":/icons/trigger-marker-falling.svg",
81 ":/icons/trigger-marker-change.svg",
91 trigger_types_(get_trigger_types()),
92 trigger_none_(nullptr),
93 trigger_rising_(nullptr),
94 trigger_high_(nullptr),
95 trigger_falling_(nullptr),
96 trigger_low_(nullptr),
97 trigger_change_(nullptr)
114 for (
auto stage : trigger->stages())
115 for (
auto match : stage->matches())
116 if (match->channel() ==
base_->channel())
122 std::map<QString, QVariant> result;
131 auto entry = settings.find(
"trace_height");
132 if (entry != settings.end()) {
148 const int signal_margin =
149 QFontMetrics(QApplication::font()).height() / 2;
157 vector< pair<int64_t, bool> > edges;
164 if (!
base_->enabled())
169 const float fill_height = low_offset - high_offset;
172 if (!segment || (segment->get_sample_count() == 0))
175 double samplerate = segment->samplerate();
178 if (samplerate == 0.0)
183 const int64_t last_sample = (int64_t)segment->get_sample_count() - 1;
184 const double samples_per_pixel = samplerate * pp.
scale();
185 const double pixels_per_sample = 1 / samples_per_pixel;
189 const int64_t start_sample =
min(
max(floor(start).convert_to<int64_t>(),
190 (int64_t)0), last_sample);
191 const uint64_t end_sample =
min(
max(ceil(end).convert_to<int64_t>(),
192 (int64_t)0), last_sample);
194 segment->get_subsampled_edges(edges, start_sample, end_sample,
196 assert(edges.size() >= 2);
198 const float first_sample_x =
199 pp.
left() + (edges.front().first / samples_per_pixel - pixels_offset);
200 const float last_sample_x =
201 pp.
left() + (edges.back().first / samples_per_pixel - pixels_offset);
205 vector<QRectF> sampling_points;
206 float sampling_point_x = first_sample_x;
207 int64_t sampling_point_sample = start_sample;
210 if (show_sampling_points)
211 sampling_points.reserve(end_sample - start_sample + 1);
213 vector<QRectF> high_rects;
215 bool rising_edge_seen =
false;
218 const unsigned int edge_count = edges.size() - 2;
219 QLineF *
const edge_lines =
new QLineF[edge_count];
222 if (edges.front().second) {
224 rising_edge_x = first_sample_x;
225 rising_edge_seen =
true;
228 for (
auto i = edges.cbegin() + 1; i != edges.cend() - 1; i++) {
234 const float x = pp.
left() + ((*i).first / samples_per_pixel - pixels_offset);
235 *line++ = QLineF(x, high_offset, x, low_offset);
239 if (rising_edge_seen) {
240 const int width = x - rising_edge_x;
242 high_rects.emplace_back(rising_edge_x, high_offset, width, fill_height);
243 rising_edge_seen =
false;
249 rising_edge_seen =
true;
253 if (show_sampling_points)
254 while (sampling_point_sample < (*i).first) {
255 const float y = (*i).second ? low_offset : high_offset;
256 sampling_points.emplace_back(
257 QRectF(sampling_point_x - (w / 2), y - (w / 2), w, w));
258 sampling_point_sample++;
259 sampling_point_x += pixels_per_sample;
264 if (show_sampling_points)
265 while ((uint64_t)sampling_point_sample <= end_sample) {
267 const float y = (edges.cend() - 1)->second ? high_offset : low_offset;
268 sampling_points.emplace_back(
269 QRectF(sampling_point_x - (w / 2), y - (w / 2), w, w));
270 sampling_point_sample++;
271 sampling_point_x += pixels_per_sample;
276 if (rising_edge_seen && (edges.cend() - 1)->second)
277 high_rects.emplace_back(rising_edge_x, high_offset,
282 p.drawRects((
const QRectF*)(high_rects.data()), high_rects.size());
286 p.drawLines(edge_lines, edge_count);
290 const unsigned int max_cap_line_count = edges.size();
291 QLineF *
const cap_lines =
new QLineF[max_cap_line_count];
294 paint_caps(p, cap_lines, edges,
true, samples_per_pixel,
295 pixels_offset, pp.
left(), high_offset);
297 paint_caps(p, cap_lines, edges,
false, samples_per_pixel,
298 pixels_offset, pp.
left(), low_offset);
303 if (show_sampling_points) {
305 p.drawRects(sampling_points.data(), sampling_points.size());
311 if (
base_->enabled()) {
317 const TriggerMatchType *
const type =
318 TriggerMatchType::get(type_id);
330 const QSize size = pixmap->size();
332 pp.
right() - size.width() - pad * 2,
337 p.drawRoundedRect(QRectF(point, size).adjusted(
338 -pad, -pad, pad, pad), pad, pad);
339 p.drawPixmap(point, *pixmap);
356 return vector<LogicSegment::EdgePair>();
359 if (!segment || (segment->get_sample_count() == 0))
360 return vector<LogicSegment::EdgePair>();
364 const double samples_per_pixel =
base_->get_samplerate() * view->scale();
366 vector<LogicSegment::EdgePair> edges;
368 segment->get_surrounding_edges(edges, sample_pos,
372 return vector<LogicSegment::EdgePair>();
378 vector< pair<int64_t, bool> > &edges,
bool level,
379 double samples_per_pixel,
double pixels_offset,
float x_offset,
382 QLineF *line = lines;
384 for (
auto i = edges.begin(); i != (edges.end() - 1); i++)
385 if ((*i).second == level) {
387 ((*i).first / samples_per_pixel -
388 pixels_offset) + x_offset, y_offset,
389 ((*(i+1)).first / samples_per_pixel -
390 pixels_offset) + x_offset, y_offset);
393 p.drawLines(lines, line - lines);
398 shared_ptr<pv::data::LogicSegment> segment;
400 const deque< shared_ptr<pv::data::LogicSegment> > &segments =
401 base_->logic_data()->logic_segments();
403 if (!segments.empty()) {
405 segment = segments.back();
411 }
catch (out_of_range&) {
412 qDebug() <<
"Current logic segment out of range for signal" <<
base_->name() <<
":" <<
current_segment_;
423 tr(
"No trigger"), parent);
428 tr(
"Trigger on rising edge"), parent);
433 tr(
"Trigger on high level"), parent);
438 tr(
"Trigger on falling edge"), parent);
443 tr(
"Trigger on low level"), parent);
448 tr(
"Trigger on rising or falling edge"), parent);
457 return vector<int32_t>();
460 if (sr_dev->config_check(ConfigKey::TRIGGER_MATCH, Capability::LIST)) {
461 const Glib::VariantContainerBase gvar =
462 sr_dev->config_list(ConfigKey::TRIGGER_MATCH);
464 vector<int32_t> ttypes;
466 for (
unsigned int i = 0; i < gvar.get_n_children(); i++) {
467 Glib::VariantBase tmp_vb;
468 gvar.get_child(tmp_vb, i);
470 Glib::Variant<int32_t> tmp_v =
471 Glib::VariantBase::cast_dynamic< Glib::Variant<int32_t> >(tmp_vb);
473 ttypes.push_back(tmp_v.get());
478 return vector<int32_t>();
488 switch (type->id()) {
489 case SR_TRIGGER_ZERO:
495 case SR_TRIGGER_RISING:
498 case SR_TRIGGER_FALLING:
501 case SR_TRIGGER_EDGE:
515 return TriggerMatchType::ZERO;
517 return TriggerMatchType::ONE;
519 return TriggerMatchType::RISING;
521 return TriggerMatchType::FALLING;
523 return TriggerMatchType::EDGE;
544 if (!trig_types.empty()) {
550 for (
auto type_id : trig_types) {
551 const TriggerMatchType *
const type =
552 TriggerMatchType::get(type_id);
560 for (QAction* action :
trigger_bar_->findChildren<QAction*>())
561 action->setEnabled(
false);
573 for (
auto stage : trigger->stages()) {
574 const auto &matches = stage->matches();
575 if (none_of(matches.begin(), matches.end(),
576 [&](shared_ptr<TriggerMatch> match) {
577 return match->channel() !=
base_->channel(); }))
580 auto new_stage = new_trigger->add_stage();
581 for (
auto match : stage->matches()) {
582 if (match->channel() ==
base_->channel())
584 new_stage->add_match(match->channel(), match->type());
593 if (new_trigger->stages().empty())
594 new_trigger->add_stage();
596 new_trigger->stages().back()->add_match(
base_->channel(),
601 new_trigger->stages().empty() ?
nullptr : new_trigger);
610 const QIcon *icon =
new QIcon(path);
620 const QPixmap *pixmap =
new QPixmap(path);
653 action = (QAction *)sender();
654 action->setChecked(
true);
static QColor TriggerMarkerBackgroundColor
static const QIcon * get_icon(const char *path)
virtual std::map< QString, QVariant > save_settings() const
void on_setting_changed(const QString &key, const QVariant &value)
QAction * action_from_trigger_type(const sigrok::TriggerMatchType *type)
double pixels_offset() const
const sigrok::TriggerMatchType * trigger_match_
TraceTreeItemOwner * owner_
bool show_sampling_points_
const vector< int32_t > get_trigger_types() const
virtual void extents_changed(bool horz, bool vert)=0
void init_trigger_actions(QWidget *parent)
const shared_ptr< sigrok::Context > & context() const
static const QString Key_View_FillSignalHighAreaColor
shared_ptr< sigrok::Session > session() const
virtual void paint_fore(QPainter &p, ViewItemPaintParams &pp)
T value(details::expression_node< T > *n)
virtual void restore_settings(std::map< QString, QVariant > settings)
int current_segment_
The ID of the currently displayed segment.
QAction * trigger_change_
static const QString Key_View_DefaultLogicHeight
static const QColor HighColor
static QCache< QString, const QPixmap > pixmap_cache_
shared_ptr< data::SignalBase > base_
static const float Oversampling
QAction * trigger_rising_
T max(const T v0, const T v1)
virtual void paint_mid(QPainter &p, ViewItemPaintParams &pp)
shared_ptr< devices::Device > device() const
void populate_popup_form(QWidget *parent, QFormLayout *form)
DeviceManager & device_manager()
void paint_caps(QPainter &p, QLineF *const lines, vector< pair< int64_t, bool > > &edges, bool level, double samples_per_pixel, double pixels_offset, float x_offset, float y_offset)
const pv::util::Timestamp & offset() const
const vector< int32_t > trigger_types_
const sigrok::TriggerMatchType * trigger_type_from_action(QAction *action)
shared_ptr< pv::data::LogicSegment > get_logic_segment_to_paint() const
T min(const T v0, const T v1)
QAction * trigger_falling_
capture_state get_capture_state() const
virtual void populate_popup_form(QWidget *parent, QFormLayout *form)
static const int TriggerMarkerPadding
QSpinBox * signal_height_sb_
SegmentDisplayMode segment_display_mode_
LogicSignal(pv::Session &session, shared_ptr< data::SignalBase > base)
static const QString Key_View_ShowSamplingPoints
static const QString Key_View_FillSignalHighAreas
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t x(y+z)
static const QColor SamplingPointColor
static QCache< QString, const QIcon > icon_cache_
static const QColor EdgeColor
boost::multiprecision::number< boost::multiprecision::cpp_dec_float< 24 >, boost::multiprecision::et_off > Timestamp
Timestamp type providing yoctosecond resolution.
static const char * TriggerMarkerIcons[8]
virtual void update_logic_level_offsets()
static const QPixmap * get_pixmap(const char *path)
static const QColor LowColor
virtual vector< data::LogicSegment::EdgePair > get_nearest_level_changes(uint64_t sample_pos)
virtual pair< int, int > v_extents() const
virtual void row_item_appearance_changed(bool label, bool content)=0
virtual void on_setting_changed(const QString &key, const QVariant &value)
void on_signal_height_changed(int height)
void paint_hover_marker(QPainter &p)