const double DecodeSignal::DecodeMargin = 1.0;
const double DecodeSignal::DecodeThreshold = 0.2;
-const int64_t DecodeSignal::DecodeChunkLength = 10 * 1024 * 1024;
-const unsigned int DecodeSignal::DecodeNotifyPeriod = 1024;
+const int64_t DecodeSignal::DecodeChunkLength = 256 * 1024;
mutex DecodeSignal::global_srd_mutex_;
logic_mux_data_invalid_(false),
start_time_(0),
samplerate_(0),
- annotation_count_(0),
samples_decoded_(0),
frame_complete_(false)
{
DecodeSignal::~DecodeSignal()
{
- if (decode_thread_.joinable()) {
- decode_interrupt_ = true;
- decode_input_cond_.notify_one();
- decode_thread_.join();
- }
-
- if (logic_mux_thread_.joinable()) {
- logic_mux_interrupt_ = true;
- logic_mux_cond_.notify_one();
- logic_mux_thread_.join();
- }
-
- stop_srd_session();
+ reset_decode();
}
const vector< shared_ptr<Decoder> >& DecodeSignal::decoder_stack() const
return stack_;
}
-void DecodeSignal::stack_decoder(srd_decoder *decoder)
+void DecodeSignal::stack_decoder(const srd_decoder *decoder)
{
assert(decoder);
stack_.push_back(make_shared<decode::Decoder>(decoder));
void DecodeSignal::reset_decode()
{
+ if (decode_thread_.joinable()) {
+ decode_interrupt_ = true;
+ decode_input_cond_.notify_one();
+ decode_thread_.join();
+ }
+
+ if (logic_mux_thread_.joinable()) {
+ logic_mux_interrupt_ = true;
+ logic_mux_cond_.notify_one();
+ logic_mux_thread_.join();
+ }
+
stop_srd_session();
- annotation_count_ = 0;
frame_complete_ = false;
samples_decoded_ = 0;
error_message_ = QString();
+
rows_.clear();
class_rows_.clear();
+
+ logic_mux_data_.reset();
+ logic_mux_data_invalid_ = true;
}
void DecodeSignal::begin_decode()
return;
}
+ // Make sure that all assigned channels still provide logic data
+ // (can happen when a converted signal was assigned but the
+ // conversion removed in the meanwhile)
+ for (data::DecodeChannel &ch : channels_)
+ if (ch.assigned_signal && !(ch.assigned_signal->logic_data() != nullptr))
+ ch.assigned_signal = nullptr;
+
// Check that all decoders have the required channels
for (const shared_ptr<decode::Decoder> &dec : stack_)
if (!dec->have_required_channels()) {
{
SignalBase::save_settings(settings);
- // TODO Save decoder stack, channel mapping and decoder options
+ settings.setValue("decoders", (int)(stack_.size()));
+
+ int decoder_idx = 0;
+ for (shared_ptr<decode::Decoder> decoder : stack_) {
+ settings.beginGroup("decoder" + QString::number(decoder_idx++));
+
+ settings.setValue("id", decoder->decoder()->id);
+
+ settings.endGroup();
+ }
+
+ // TODO Save channel mapping and decoder options
}
void DecodeSignal::restore_settings(QSettings &settings)
{
SignalBase::restore_settings(settings);
- // TODO Restore decoder stack, channel mapping and decoder options
-}
+ GSList *dec_list = g_slist_copy((GSList*)srd_decoder_list());
-uint64_t DecodeSignal::inc_annotation_count()
-{
- return (annotation_count_++);
+ int decoders = settings.value("decoders").toInt();
+
+ for (int decoder_idx = 0; decoder_idx < decoders; decoder_idx++) {
+ settings.beginGroup("decoder" + QString::number(decoder_idx));
+
+ QString id = settings.value("id").toString();
+
+ for (GSList *entry = dec_list; entry; entry = entry->next) {
+ const srd_decoder *dec = (srd_decoder*)entry->data;
+ if (!dec)
+ continue;
+
+ if (QString::fromUtf8(dec->id) == id) {
+ stack_.push_back(make_shared<decode::Decoder>(dec));
+
+ // Include the newly created decode channels in the channel lists
+ update_channel_list();
+ break;
+ }
+ }
+
+ settings.endGroup();
+ }
+
+ // TODO Restore channel mapping and decoder options
}
void DecodeSignal::update_channel_list()
lock_guard<mutex> lock(output_mutex_);
samples_decoded_ = chunk_end;
}
+
+ // Notify the frontend that we processed some data and
+ // possibly have new annotations as well
+ new_annotations();
}
}
decode_data(abs_start_samplenum, sample_count);
abs_start_samplenum += sample_count;
}
- } while (error_message_.isEmpty() && (sample_count > 0));
+ } while (error_message_.isEmpty() && (sample_count > 0) && !decode_interrupt_);
- if (error_message_.isEmpty()) {
- // Make sure all annotations are known to the frontend
- new_annotations();
+ if (error_message_.isEmpty() && !decode_interrupt_) {
+ if (sample_count == 0)
+ decode_finished();
// Wait for new input data or an interrupt was requested
unique_lock<mutex> input_wait_lock(input_mutex_);
void DecodeSignal::connect_input_notifiers()
{
// Disconnect the notification slot from the previous set of signals
+ disconnect(this, SLOT(on_data_cleared()));
disconnect(this, SLOT(on_data_received()));
// Connect the currently used signals to our slot
if (!ch.assigned_signal)
continue;
- shared_ptr<Logic> logic_data = ch.assigned_signal->logic_data();
- connect(logic_data.get(), SIGNAL(samples_added(QObject*, uint64_t, uint64_t)),
+ const data::SignalBase *signal = ch.assigned_signal;
+ connect(signal, SIGNAL(samples_cleared()),
+ this, SLOT(on_data_cleared()));
+ connect(signal, SIGNAL(samples_added(QObject*, uint64_t, uint64_t)),
this, SLOT(on_data_received()));
}
}
// Add the annotation
(*row_iter).second.push_annotation(a);
-
- // Notify the frontend every DecodeNotifyPeriod annotations
- if (ds->inc_annotation_count() % DecodeNotifyPeriod == 0)
- ds->new_annotations();
}
void DecodeSignal::on_capture_state_changed(int state)
begin_decode();
}
+void DecodeSignal::on_data_cleared()
+{
+ reset_decode();
+}
+
void DecodeSignal::on_data_received()
{
- logic_mux_cond_.notify_one();
+ if (!logic_mux_thread_.joinable())
+ begin_decode();
+ else
+ logic_mux_cond_.notify_one();
}
} // namespace data