X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fviews%2Ftrace%2Fdecodetrace.cpp;h=ee9b0ee211472c47347deb84d7b01241db0a056d;hp=d151a92dad5fee2def16d1b7f582204c25b92f33;hb=946b52e1f0e0520415c3653cc6ea9d083718f76d;hpb=ad908057e13224eee9f983685e0ccc7db1ded0e9 diff --git a/pv/views/trace/decodetrace.cpp b/pv/views/trace/decodetrace.cpp index d151a92d..ee9b0ee2 100644 --- a/pv/views/trace/decodetrace.cpp +++ b/pv/views/trace/decodetrace.cpp @@ -48,7 +48,6 @@ extern "C" { #include #include #include -#include #include #include #include @@ -69,6 +68,11 @@ using std::tie; using std::unordered_set; using std::vector; +using pv::data::decode::Annotation; +using pv::data::decode::Row; +using pv::data::DecodeChannel; +using pv::data::DecodeSignal; + namespace pv { namespace views { namespace trace { @@ -145,6 +149,9 @@ DecodeTrace::DecodeTrace(pv::Session &session, connect(decode_signal_.get(), SIGNAL(new_annotations()), this, SLOT(on_new_annotations())); + connect(decode_signal_.get(), SIGNAL(channels_updated()), + this, SLOT(on_channels_updated())); + connect(&delete_mapper_, SIGNAL(mapped(int)), this, SLOT(on_delete_decoder(int))); connect(&show_hide_mapper_, SIGNAL(mapped(int)), @@ -179,16 +186,11 @@ void DecodeTrace::paint_back(QPainter &p, ViewItemPaintParams &pp) void DecodeTrace::paint_mid(QPainter &p, ViewItemPaintParams &pp) { - using namespace pv::data::decode; - - shared_ptr decoder_stack = base_->decoder_stack(); - const int text_height = ViewItemPaintParams::text_height(); row_height_ = (text_height * 6) / 4; const int annotation_height = (text_height * 5) / 4; - assert(decoder_stack); - const QString err = decoder_stack->error_message(); + const QString err = decode_signal_->error_message(); if (!err.isEmpty()) { draw_unresolved_period( p, annotation_height, pp.left(), pp.right()); @@ -204,7 +206,7 @@ void DecodeTrace::paint_mid(QPainter &p, ViewItemPaintParams &pp) pair sample_range = get_sample_range( pp.left(), pp.right()); - const vector rows(decoder_stack->get_visible_rows()); + const vector rows = decode_signal_->visible_rows(); visible_rows_.clear(); for (const Row& row : rows) { @@ -227,7 +229,7 @@ void DecodeTrace::paint_mid(QPainter &p, ViewItemPaintParams &pp) base_colour >>= 16; vector annotations; - decoder_stack->get_annotation_subset(annotations, row, + decode_signal_->get_annotation_subset(annotations, row, sample_range.first, sample_range.second); if (!annotations.empty()) { draw_annotations(annotations, p, annotation_height, pp, y, @@ -251,8 +253,6 @@ void DecodeTrace::paint_mid(QPainter &p, ViewItemPaintParams &pp) void DecodeTrace::paint_fore(QPainter &p, ViewItemPaintParams &pp) { - using namespace pv::data::decode; - assert(row_height_); for (size_t i = 0; i < visible_rows_.size(); i++) { @@ -293,21 +293,19 @@ void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form) { using pv::data::decode::Decoder; - shared_ptr decoder_stack = base_->decoder_stack(); - assert(form); - assert(parent); - assert(decoder_stack); // Add the standard options Trace::populate_popup_form(parent, form); // Add the decoder options bindings_.clear(); - channel_selectors_.clear(); + channel_id_map_.clear(); + init_state_map_.clear(); decoder_forms_.clear(); - const list< shared_ptr >& stack = decoder_stack->stack(); + const list< shared_ptr > &stack = + decode_signal_->decoder_stack_list(); if (stack.empty()) { QLabel *const l = new QLabel( @@ -595,49 +593,24 @@ void DecodeTrace::draw_error(QPainter &p, const QString &message, p.drawText(text_rect, message); } -void DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left, - int right) const +void DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left, int right) const { using namespace pv::data; using pv::data::decode::Decoder; double samples_per_pixel, pixels_offset; - shared_ptr decoder_stack = base_->decoder_stack(); - - assert(decoder_stack); - - shared_ptr data; - shared_ptr signalbase; - - const list< shared_ptr > &stack = decoder_stack->stack(); - - // We get the logic data of the first channel in the list. - // This works because we are currently assuming all - // LogicSignals have the same data/segment - for (const shared_ptr &dec : stack) - if (dec && !dec->channels().empty() && - ((signalbase = (*dec->channels().begin()).second)) && - ((data = signalbase->logic_data()))) - break; - - if (!data || data->logic_segments().empty()) - return; - - const shared_ptr segment = data->logic_segments().front(); - assert(segment); - const int64_t sample_count = (int64_t)segment->get_sample_count(); + const int64_t sample_count = decode_signal_->sample_count(); if (sample_count == 0) return; - const int64_t samples_decoded = decoder_stack->samples_decoded(); + const int64_t samples_decoded = decode_signal_->samples_decoded(); if (sample_count == samples_decoded) return; const int y = get_visual_y(); - tie(pixels_offset, samples_per_pixel) = - get_pixels_offset_samples_per_pixel(); + tie(pixels_offset, samples_per_pixel) = get_pixels_offset_samples_per_pixel(); const double start = max(samples_decoded / samples_per_pixel - pixels_offset, left - 1.0); @@ -656,10 +629,7 @@ void DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left, pair DecodeTrace::get_pixels_offset_samples_per_pixel() const { - shared_ptr decoder_stack = base_->decoder_stack(); - assert(owner_); - assert(decoder_stack); const View *view = owner_->view(); assert(view); @@ -668,9 +638,9 @@ pair DecodeTrace::get_pixels_offset_samples_per_pixel() const assert(scale > 0); const double pixels_offset = - ((view->offset() - decoder_stack->start_time()) / scale).convert_to(); + ((view->offset() - decode_signal_->start_time()) / scale).convert_to(); - double samplerate = decoder_stack->samplerate(); + double samplerate = decode_signal_->samplerate(); // Show sample rate as 1Hz when it is unknown if (samplerate == 0.0) @@ -728,10 +698,7 @@ const QString DecodeTrace::get_annotation_at_point(const QPoint &point) vector annotations; - shared_ptr decoder_stack = base_->decoder_stack(); - - assert(decoder_stack); - decoder_stack->get_annotation_subset(annotations, visible_rows_[row], + decode_signal_->get_annotation_subset(annotations, visible_rows_[row], sample_range.first, sample_range.second); return (annotations.empty()) ? @@ -781,7 +748,6 @@ void DecodeTrace::create_decoder_form(int index, shared_ptr &dec, QWidget *parent, QFormLayout *form) { - const GSList *l; GlobalSettings settings; assert(dec); @@ -810,67 +776,40 @@ void DecodeTrace::create_decoder_form(int index, QFormLayout *const decoder_form = new QFormLayout; group->add_layout(decoder_form); - // Add the mandatory channels - for (l = decoder->channels; l; l = l->next) { - const struct srd_channel *const pdch = - (struct srd_channel *)l->data; - - QComboBox *const combo = create_channel_selector(parent, dec, pdch); - QComboBox *const combo_initial_pin = create_channel_selector_initial_pin(parent, dec, pdch); - - connect(combo, SIGNAL(currentIndexChanged(int)), - this, SLOT(on_channel_selected(int))); - connect(combo_initial_pin, SIGNAL(currentIndexChanged(int)), - this, SLOT(on_initial_pin_selected(int))); - - QHBoxLayout *const hlayout = new QHBoxLayout; - hlayout->addWidget(combo); - hlayout->addWidget(combo_initial_pin); - - if (!settings.value(GlobalSettings::Key_Dec_InitialStateConfigurable).toBool()) - combo_initial_pin->hide(); - - decoder_form->addRow(tr("%1 (%2) *") - .arg(QString::fromUtf8(pdch->name), - QString::fromUtf8(pdch->desc)), hlayout); + const list channels = decode_signal_->get_channels(); - const ChannelSelector s = {combo, combo_initial_pin, dec, pdch}; - channel_selectors_.push_back(s); - } + // Add the channels + for (DecodeChannel ch : channels) { + // Ignore channels not part of the decoder we create the form for + if (ch.decoder_ != dec) + continue; - // Add the optional channels - for (l = decoder->opt_channels; l; l = l->next) { - const struct srd_channel *const pdch = - (struct srd_channel *)l->data; + QComboBox *const combo = create_channel_selector(parent, &ch); + QComboBox *const combo_init_state = create_channel_selector_init_state(parent, &ch); - QComboBox *const combo = create_channel_selector(parent, dec, pdch); - QComboBox *const combo_initial_pin = create_channel_selector_initial_pin(parent, dec, pdch); + channel_id_map_[combo] = ch.id; + init_state_map_[combo_init_state] = ch.id; connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(on_channel_selected(int))); - connect(combo_initial_pin, SIGNAL(currentIndexChanged(int)), - this, SLOT(on_initial_pin_selected(int))); + connect(combo_init_state, SIGNAL(currentIndexChanged(int)), + this, SLOT(on_init_state_changed(int))); QHBoxLayout *const hlayout = new QHBoxLayout; hlayout->addWidget(combo); - hlayout->addWidget(combo_initial_pin); + hlayout->addWidget(combo_init_state); if (!settings.value(GlobalSettings::Key_Dec_InitialStateConfigurable).toBool()) - combo_initial_pin->hide(); - - decoder_form->addRow(tr("%1 (%2)") - .arg(QString::fromUtf8(pdch->name), - QString::fromUtf8(pdch->desc)), hlayout); + combo_init_state->hide(); - const ChannelSelector s = {combo, combo_initial_pin, dec, pdch}; - channel_selectors_.push_back(s); + const QString required_flag = ch.is_optional ? QString() : QString("*"); + decoder_form->addRow(tr("%1 (%2) %3") + .arg(ch.name, ch.desc, required_flag), hlayout); } - shared_ptr decoder_stack = base_->decoder_stack(); - // Add the options shared_ptr binding( - new binding::Decoder(decoder_stack, dec)); + new binding::Decoder(decode_signal_, dec)); binding->add_properties_to_form(decoder_form, true); bindings_.push_back(binding); @@ -879,14 +818,11 @@ void DecodeTrace::create_decoder_form(int index, decoder_forms_.push_back(group); } -QComboBox* DecodeTrace::create_channel_selector( - QWidget *parent, const shared_ptr &dec, - const srd_channel *const pdch) +QComboBox* DecodeTrace::create_channel_selector(QWidget *parent, const DecodeChannel *ch) { - assert(dec); - const auto sigs(session_.signalbases()); + // Sort signals in natural order vector< shared_ptr > sig_list(sigs.begin(), sigs.end()); sort(sig_list.begin(), sig_list.end(), [](const shared_ptr &a, @@ -894,13 +830,11 @@ QComboBox* DecodeTrace::create_channel_selector( return strnatcasecmp(a->name().toStdString(), b->name().toStdString()) < 0; }); - const auto channel_iter = dec->channels().find(pdch); - QComboBox *selector = new QComboBox(parent); selector->addItem("-", qVariantFromValue((void*)nullptr)); - if (channel_iter == dec->channels().end()) + if (!ch->assigned_signal) selector->setCurrentIndex(0); for (const shared_ptr &b : sig_list) { @@ -909,18 +843,16 @@ QComboBox* DecodeTrace::create_channel_selector( selector->addItem(b->name(), qVariantFromValue((void*)b.get())); - if (channel_iter != dec->channels().end() && - (*channel_iter).second == b) - selector->setCurrentIndex( - selector->count() - 1); + if (ch->assigned_signal == b.get()) + selector->setCurrentIndex(selector->count() - 1); } } return selector; } -QComboBox* DecodeTrace::create_channel_selector_initial_pin(QWidget *parent, - const shared_ptr &dec, const srd_channel *const pdch) +QComboBox* DecodeTrace::create_channel_selector_init_state(QWidget *parent, + const DecodeChannel *ch) { QComboBox *selector = new QComboBox(parent); @@ -928,63 +860,13 @@ QComboBox* DecodeTrace::create_channel_selector_initial_pin(QWidget *parent, selector->addItem("1", qVariantFromValue((int)SRD_INITIAL_PIN_HIGH)); selector->addItem("X", qVariantFromValue((int)SRD_INITIAL_PIN_SAME_AS_SAMPLE0)); - // Default to index 2 (SRD_INITIAL_PIN_SAME_AS_SAMPLE0). - const int idx = (!dec->initial_pins()) ? 2 : dec->initial_pins()->data[pdch->order]; - selector->setCurrentIndex(idx); + selector->setCurrentIndex(ch->initial_pin_state); selector->setToolTip("Initial (assumed) pin value before the first sample"); return selector; } -void DecodeTrace::commit_decoder_channels(shared_ptr &dec) -{ - assert(dec); - - map > channel_map; - - const unordered_set< shared_ptr > - sigs(session_.signalbases()); - - GArray *const initial_pins = g_array_sized_new(FALSE, TRUE, - sizeof(uint8_t), channel_selectors_.size()); - g_array_set_size(initial_pins, channel_selectors_.size()); - - for (const ChannelSelector &s : channel_selectors_) { - if (s.decoder_ != dec) - break; - - const data::SignalBase *const selection = - (data::SignalBase*)s.combo_->itemData( - s.combo_->currentIndex()).value(); - - for (shared_ptr sig : sigs) - if (sig.get() == selection) { - channel_map[s.pdch_] = sig; - break; - } - - int selection_initial_pin = s.combo_initial_pin_->itemData( - s.combo_initial_pin_->currentIndex()).value(); - - initial_pins->data[s.pdch_->order] = selection_initial_pin; - } - - dec->set_channels(channel_map); - dec->set_initial_pins(initial_pins); -} - -void DecodeTrace::commit_channels() -{ - shared_ptr decoder_stack = base_->decoder_stack(); - - assert(decoder_stack); - for (shared_ptr dec : decoder_stack->stack()) - commit_decoder_channels(dec); - - decoder_stack->begin_decode(); -} - void DecodeTrace::on_new_annotations() { if (owner_) @@ -1003,12 +885,35 @@ void DecodeTrace::on_delete() void DecodeTrace::on_channel_selected(int) { - commit_channels(); + QComboBox *cb = qobject_cast(QObject::sender()); + + // Determine signal that was selected + const data::SignalBase *signal = + (data::SignalBase*)cb->itemData(cb->currentIndex()).value(); + + // Determine decode channel ID this combo box is the channel selector for + const uint16_t id = channel_id_map_.at(cb); + + decode_signal_->assign_signal(id, signal); +} + +void DecodeTrace::on_channels_updated() +{ + if (owner_) + owner_->row_item_appearance_changed(false, true); } -void DecodeTrace::on_initial_pin_selected(int) +void DecodeTrace::on_init_state_changed(int) { - commit_channels(); + QComboBox *cb = qobject_cast(QObject::sender()); + + // Determine inital pin state that was selected + int init_state = cb->itemData(cb->currentIndex()).value(); + + // Determine decode channel ID this combo box is the channel selector for + const uint16_t id = init_state_map_.at(cb); + + decode_signal_->set_initial_pin_state(id, init_state); } void DecodeTrace::on_stack_decoder(srd_decoder *decoder)