X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fdata%2Fdecodesignal.cpp;h=a57a9a1a9624556d5658dc3d6d3877f160194095;hp=49b76f2aa9cedd87533031cadd512d50e1589ab2;hb=762ab7a4b20928a784b2b3400ce748d901e32d2d;hpb=8b5ea5a149b3686694de47058983e0f5fb6d7bfb diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp index 49b76f2a..a57a9a1a 100644 --- a/pv/data/decodesignal.cpp +++ b/pv/data/decodesignal.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include using std::lock_guard; @@ -48,8 +49,6 @@ const double DecodeSignal::DecodeMargin = 1.0; const double DecodeSignal::DecodeThreshold = 0.2; const int64_t DecodeSignal::DecodeChunkLength = 256 * 1024; -mutex DecodeSignal::global_srd_mutex_; - DecodeSignal::DecodeSignal(pv::Session &session) : SignalBase(nullptr, SignalBase::DecodeChannel), @@ -80,7 +79,9 @@ const vector< shared_ptr >& DecodeSignal::decoder_stack() const void DecodeSignal::stack_decoder(const srd_decoder *decoder) { assert(decoder); - stack_.push_back(make_shared(decoder)); + const shared_ptr dec = make_shared(decoder); + + stack_.push_back(dec); // Set name if this decoder is the first in the list if (stack_.size() == 1) @@ -89,7 +90,7 @@ void DecodeSignal::stack_decoder(const srd_decoder *decoder) // Include the newly created decode channels in the channel lists update_channel_list(); - auto_assign_signals(); + auto_assign_signals(dec); commit_decoder_channels(); begin_decode(); } @@ -264,12 +265,16 @@ const vector DecodeSignal::get_channels() const return channels_; } -void DecodeSignal::auto_assign_signals() +void DecodeSignal::auto_assign_signals(const shared_ptr dec) { bool new_assignment = false; // Try to auto-select channels that don't have signals assigned yet for (data::DecodeChannel &ch : channels_) { + // If a decoder is given, auto-assign only its channels + if (dec && (ch.decoder_ != dec)) + continue; + if (ch.assigned_signal) continue; @@ -422,6 +427,22 @@ void DecodeSignal::save_settings(QSettings &settings) const settings.setValue("id", decoder->decoder()->id); + // Save decoder options + const map& options = decoder->options(); + + settings.setValue("options", (int)options.size()); + + // Note: decode::Decoder::options() returns only the options + // that differ from the default. See binding::Decoder::getter() + int i = 0; + for (auto option : options) { + settings.beginGroup("option" + QString::number(i)); + settings.setValue("name", QString::fromStdString(option.first)); + GlobalSettings::store_gvariant(settings, option.second); + settings.endGroup(); + i++; + } + settings.endGroup(); } @@ -447,8 +468,6 @@ void DecodeSignal::save_settings(QSettings &settings) const settings.endGroup(); } - - // TODO Save decoder options } void DecodeSignal::restore_settings(QSettings &settings) @@ -471,7 +490,21 @@ void DecodeSignal::restore_settings(QSettings &settings) continue; if (QString::fromUtf8(dec->id) == id) { - stack_.push_back(make_shared(dec)); + shared_ptr decoder = + make_shared(dec); + + stack_.push_back(decoder); + + // Restore decoder options that differ from their default + int options = settings.value("options").toInt(); + + for (int i = 0; i < options; i++) { + settings.beginGroup("option" + QString::number(i)); + QString name = settings.value("name").toString(); + GVariant *value = GlobalSettings::restore_gvariant(settings); + decoder->set_option(name.toUtf8(), value); + settings.endGroup(); + } // Include the newly created decode channels in the channel lists update_channel_list(); @@ -511,8 +544,6 @@ void DecodeSignal::restore_settings(QSettings &settings) } begin_decode(); - - // TODO Restore decoder options } void DecodeSignal::update_channel_list() @@ -628,7 +659,10 @@ void DecodeSignal::mux_logic_samples(const int64_t start, const int64_t end) const shared_ptr logic_data = ch.assigned_signal->logic_data(); const shared_ptr segment = logic_data->logic_segments().front(); segments.push_back(segment); - signal_data.push_back(segment->get_samples(start, end)); + + uint8_t* data = new uint8_t[(end - start) * segment->unit_size()]; + segment->get_samples(start, end, data); + signal_data.push_back(data); const int bitpos = ch.assigned_signal->logic_bit_index(); signal_in_bytepos.push_back(bitpos / 8); @@ -721,12 +755,24 @@ void DecodeSignal::query_input_metadata() // TODO Currently we assume all channels have the same sample rate // and start time bool samplerate_valid = false; + data::DecodeChannel *any_channel; + shared_ptr logic_data; - auto any_channel = find_if(channels_.begin(), channels_.end(), - [](data::DecodeChannel ch) { return ch.assigned_signal; }); + do { + any_channel = &(*find_if(channels_.begin(), channels_.end(), + [](data::DecodeChannel ch) { return ch.assigned_signal; })); - shared_ptr logic_data = - any_channel->assigned_signal->logic_data(); + logic_data = any_channel->assigned_signal->logic_data(); + + if (!logic_data) { + // Wait until input data is available or an interrupt was requested + unique_lock input_wait_lock(input_mutex_); + decode_input_cond_.wait(input_wait_lock); + } + } while (!logic_data && !decode_interrupt_); + + if (decode_interrupt_) + return; do { if (!logic_data->logic_segments().empty()) { @@ -759,10 +805,12 @@ void DecodeSignal::decode_data( const int64_t chunk_end = min(i + chunk_sample_count, abs_start_samplenum + sample_count); - const uint8_t* chunk = segment_->get_samples(i, chunk_end); + int64_t data_size = (chunk_end - i) * unit_size; + uint8_t* chunk = new uint8_t[data_size]; + segment_->get_samples(i, chunk_end, chunk); if (srd_session_send(srd_session_, i, chunk_end, chunk, - (chunk_end - i) * unit_size, unit_size) != SRD_OK) { + data_size, unit_size) != SRD_OK) { error_message_ = tr("Decoder reported an error"); delete[] chunk; break; @@ -795,13 +843,8 @@ void DecodeSignal::decode_proc() do { // Keep processing new samples until we exhaust the input data do { - // Prevent any other decode threads from accessing libsigrokdecode - lock_guard srd_lock(global_srd_mutex_); - - { - lock_guard input_lock(input_mutex_); - sample_count = segment_->get_sample_count() - abs_start_samplenum; - } + lock_guard input_lock(input_mutex_); + sample_count = segment_->get_sample_count() - abs_start_samplenum; if (sample_count > 0) { decode_data(abs_start_samplenum, sample_count);