]> sigrok.org Git - pulseview.git/commitdiff
Integrated decode
authorJoel Holdsworth <redacted>
Mon, 26 Aug 2013 16:16:27 +0000 (17:16 +0100)
committerJoel Holdsworth <redacted>
Sun, 29 Sep 2013 02:14:08 +0000 (11:14 +0900)
12 files changed:
CMakeLists.txt
pv/data/decoder.cpp
pv/data/decoder.h
pv/data/signaldata.h
pv/sigsession.cpp
pv/view/decodesignal.cpp
pv/view/decodesignal.h
pv/view/logicsignal.cpp
pv/view/logicsignal.h
pv/view/trace.h
pv/view/view.cpp
pv/view/view.h

index 5d268e71340db4334d66387247bd838ffcede020..4d1e9190119bc60bb0d0b4eb0a69062165e45cdd 100644 (file)
@@ -146,12 +146,14 @@ set(pulseview_SOURCES
 set(pulseview_HEADERS
        pv/mainwindow.h
        pv/sigsession.h
+       pv/data/decoder.h
        pv/dialogs/about.h
        pv/dialogs/connect.h
        pv/dialogs/deviceoptions.h
        pv/toolbars/contextbar.h
        pv/toolbars/samplingbar.h
        pv/view/cursor.h
+       pv/view/decodesignal.h
        pv/view/header.h
        pv/view/logicsignal.h
        pv/view/marginwidget.h
index e1be16e3ea14898fcea05f0f9f34b48d101e04c0..2848d16ca4dffd166697b2517193acaec7030592 100644 (file)
 
 #include <libsigrokdecode/libsigrokdecode.h>
 
+#include <boost/thread/thread.hpp>
+
 #include "decoder.h"
 
-#include <pv/view/signal.h>
+#include <pv/data/logic.h>
+#include <pv/data/logicsnapshot.h>
+#include <pv/view/logicsignal.h>
+#include <pv/view/decode/annotation.h>
 
 using namespace boost;
 using namespace std;
@@ -30,6 +35,10 @@ using namespace std;
 namespace pv {
 namespace data {
 
+const double Decoder::DecodeMargin = 1.0;
+const double Decoder::DecodeThreshold = 0.2;
+const int64_t Decoder::DecodeChunkLength = 4096;
+
 Decoder::Decoder(const srd_decoder *const dec,
        std::map<const srd_probe*,
                boost::shared_ptr<pv::view::Signal> > probes) :
@@ -38,6 +47,7 @@ Decoder::Decoder(const srd_decoder *const dec,
        _decoder_inst(NULL)
 {
        init_decoder();
+       begin_decode();
 }
 
 Decoder::~Decoder()
@@ -51,13 +61,33 @@ const srd_decoder* Decoder::get_decoder() const
        return _decoder;
 }
 
+const vector< shared_ptr<view::decode::Annotation> >
+       Decoder::annotations() const
+{
+       lock_guard<mutex> lock(_annotations_mutex);
+       return _annotations;
+}
+
 void Decoder::begin_decode()
 {
        _decode_thread.interrupt();
        _decode_thread.join();
 
+       if (_probes.empty())
+               return;
+
+       // We get the logic data of the first probe in the list.
+       // This works because we are currently assuming all
+       // LogicSignals have the same data/snapshot
+       shared_ptr<pv::view::Signal> sig = (*_probes.begin()).second;
+       assert(sig);
+       const pv::view::LogicSignal *const l =
+               dynamic_cast<pv::view::LogicSignal*>(sig.get());
+       assert(l);
+       shared_ptr<data::Logic> data = l->data();
+
        _decode_thread = boost::thread(&Decoder::decode_proc, this,
-               shared_ptr<data::Logic>());
+               data);
 }
 
 void Decoder::clear_snapshots()
@@ -66,9 +96,26 @@ void Decoder::clear_snapshots()
 
 void Decoder::init_decoder()
 {
+       if (!_probes.empty())
+       {
+               shared_ptr<pv::view::LogicSignal> logic_signal =
+                       dynamic_pointer_cast<pv::view::LogicSignal>(
+                               (*_probes.begin()).second);
+               if (logic_signal) {
+                       shared_ptr<pv::data::Logic> data(
+                               logic_signal->data());
+                       if (data) {
+                               _samplerate = data->get_samplerate();
+                               _start_time = data->get_start_time();
+                       }
+               }
+       }
+
        _decoder_inst = srd_inst_new(_decoder->id, NULL);
        assert(_decoder_inst);
 
+       _decoder_inst->data_samplerate = _samplerate;
+
        GHashTable *probes = g_hash_table_new_full(g_str_hash,
                g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
 
@@ -88,7 +135,56 @@ void Decoder::init_decoder()
 
 void Decoder::decode_proc(shared_ptr<data::Logic> data)
 {
-       (void)data;
+       uint8_t chunk[DecodeChunkLength];
+
+       assert(data);
+
+       _annotations.clear();
+
+       const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots =
+               data->get_snapshots();
+       if (snapshots.empty())
+               return;
+
+       const shared_ptr<pv::data::LogicSnapshot> &snapshot =
+               snapshots.front();
+       const int64_t sample_count = snapshot->get_sample_count() - 1;
+       double samplerate = data->get_samplerate();
+
+       // Show sample rate as 1Hz when it is unknown
+       if (samplerate == 0.0)
+               samplerate = 1.0;
+
+       srd_session_start(_probes.size(), snapshot->unit_size(), samplerate);
+
+       srd_pd_output_callback_add(SRD_OUTPUT_ANN,
+               Decoder::annotation_callback, this);
+
+       for (int64_t i = 0;
+               !this_thread::interruption_requested() && i < sample_count;
+               i += DecodeChunkLength)
+       {
+               const int64_t chunk_end = min(
+                       i + DecodeChunkLength, sample_count);
+               snapshot->get_samples(chunk, i, chunk_end);
+
+               if (srd_session_send(i, chunk, chunk_end - i) != SRD_OK)
+                       break;
+       }
+}
+
+void Decoder::annotation_callback(srd_proto_data *pdata, void *decoder)
+{
+       using namespace pv::view::decode;
+
+       assert(pdata);
+       assert(decoder);
+
+       Decoder *const d = (Decoder*)decoder;
+
+       shared_ptr<Annotation> a(new Annotation(pdata));
+       lock_guard<mutex> lock(d->_annotations_mutex);
+       d->_annotations.push_back(a);
 }
 
 } // namespace data
index dcf12fe1d4b5d2b8c6696442682bc9f5217ea2e6..4cae427ea95813e842be6aaa25fb93641ee0de1d 100644 (file)
@@ -28,6 +28,8 @@
 #include <boost/shared_ptr.hpp>
 #include <boost/thread.hpp>
 
+#include <QObject>
+
 struct srd_decoder;
 struct srd_decoder_inst;
 struct srd_probe;
@@ -36,14 +38,26 @@ namespace pv {
 
 namespace view {
 class Signal;
+
+namespace decode {
+class Annotation;
+}
+
 }
 
 namespace data {
 
 class Logic;
 
-class Decoder : public SignalData
+class Decoder : public QObject, public SignalData
 {
+       Q_OBJECT
+
+private:
+       static const double DecodeMargin;
+       static const double DecodeThreshold;
+       static const int64_t DecodeChunkLength;
+
 public:
        Decoder(const srd_decoder *const decoder,
                std::map<const srd_probe*,
@@ -53,15 +67,21 @@ public:
 
        const srd_decoder* get_decoder() const;
 
-       void begin_decode();
+       const std::vector< boost::shared_ptr<pv::view::decode::Annotation> >
+               annotations() const;
 
        void clear_snapshots();
 
 private:
+       void begin_decode();
+
        void init_decoder();
 
        void decode_proc(boost::shared_ptr<data::Logic> data);
 
+       static void annotation_callback(srd_proto_data *pdata,
+               void *decoder);
+
 private:
        const srd_decoder *const _decoder;
        std::map<const srd_probe*, boost::shared_ptr<view::Signal> >
@@ -69,6 +89,10 @@ private:
 
        srd_decoder_inst *_decoder_inst;
 
+       mutable boost::mutex _annotations_mutex;
+       std::vector< boost::shared_ptr<pv::view::decode::Annotation> >
+               _annotations;
+
        boost::thread _decode_thread;
 };
 
index c43b7a37e7e3e1934858ffd438ee0a80a95968e0..c5ed6bd3fa97967bd675cc0928ae6e53e3bb8219 100644 (file)
@@ -40,8 +40,7 @@ public:
        virtual void clear_snapshots() = 0;
 
 protected:
-       const double _start_time;
-
+       double _start_time;
        double _samplerate;
 };
 
index cad702d810c923f818c363940c69a78f83c099ab..ffe37d2008e2ac626aa6c686434b284033872c25 100644 (file)
@@ -199,6 +199,13 @@ void SigSession::add_decoder(srd_decoder *const dec,
 {
        {
                lock_guard<mutex> lock(_signals_mutex);
+
+               if (!_decode_traces.empty()) {
+                       qDebug("Currently only one decode trace can be added "
+                               "at once");
+                       _decode_traces.clear();
+               }
+
                shared_ptr<data::Decoder> decoder(
                        new data::Decoder(dec, probes));
                shared_ptr<view::DecodeSignal> d(
index 556631c6cc059e5a8bb850fdce91cee7aaa29f2a..44144d1b8b8e31a37648e6d44fb03221e20e94bb 100644 (file)
@@ -25,6 +25,7 @@ extern "C" {
 #include "decodesignal.h"
 
 #include <pv/data/decoder.h>
+#include <pv/view/view.h>
 
 using namespace boost;
 using namespace std;
@@ -37,6 +38,8 @@ DecodeSignal::DecodeSignal(pv::SigSession &session,
        Trace(session, QString(decoder->get_decoder()->name)),
        _decoder(decoder)
 {
+       assert(_decoder);
+
        _colour = Qt::red;
 }
 
@@ -50,6 +53,12 @@ bool DecodeSignal::enabled() const
        return true;
 }
 
+void DecodeSignal::set_view(pv::view::View *view)
+{
+       assert(view);
+       Trace::set_view(view);
+}
+
 void DecodeSignal::paint(QPainter &p, int left, int right)
 {
        (void)p;
index 31804589cc8f7041862dc9f2b22a69cbab319f04..95459d68fd7da43faa97474610f94a6a89d0aa7b 100644 (file)
@@ -35,6 +35,8 @@ namespace view {
 
 class DecodeSignal : public Trace
 {
+       Q_OBJECT
+
 public:
        DecodeSignal(pv::SigSession &session,
                boost::shared_ptr<pv::data::Decoder> decoder);
@@ -43,6 +45,8 @@ public:
 
        bool enabled() const;
 
+       void set_view(pv::view::View *view);
+
        /**
         * Paints the trace with a QPainter
         * @param p the QPainter to paint into.
@@ -63,6 +67,8 @@ private:
 
 private:
        boost::shared_ptr<pv::data::Decoder> _decoder;
+
+       uint64_t _decode_start, _decode_end;
 };
 
 } // namespace view
index 3624ccf0f26b2df1dce6624c95a78d974d69b5bd..bc4f5311b1fecb6200b85f7773ea0df3245c4090 100644 (file)
@@ -118,6 +118,11 @@ void LogicSignal::init_context_bar_actions(QWidget *parent)
                this, SLOT(on_trigger_change()));
 }
 
+boost::shared_ptr<pv::data::Logic> LogicSignal::data() const
+{
+       return _data;
+}
+
 const list<QAction*> LogicSignal::get_context_bar_actions()
 {
        GVariant *gvar;
index b0a328c1fc662e195bf66de423aa0f69b7bdd35b..023787573c243ad334008f1a18481999ebdb3fa9 100644 (file)
@@ -54,6 +54,8 @@ public:
 
        void init_context_bar_actions(QWidget *parent);
 
+       boost::shared_ptr<pv::data::Logic> data() const;
+
        const std::list<QAction*> get_context_bar_actions();
 
        /**
index 4d6b49be0c4a551e5a9b942903c7502f8ecf0aab..ffd87fa45524feae6e5d2cade3d3ef86cdb368da 100644 (file)
@@ -84,7 +84,7 @@ public:
         */
        virtual bool enabled() const = 0;
 
-       void set_view(pv::view::View *view);
+       virtual void set_view(pv::view::View *view);
 
        /**
         * Paints the trace with a QPainter
index e6ce6621f99d06786f230ede9714f82a6730f235..54ab4ff9e2beb1d5892dd5d46e3bb4028474bc72 100644 (file)
@@ -159,6 +159,7 @@ void View::set_scale_offset(double scale, double offset)
        update_scroll();
        _ruler->update();
        _viewport->update();
+       scale_offset_changed();
 }
 
 vector< shared_ptr<Trace> > View::get_traces() const
index dce8c252aff968f2c110eaa9e39de5eed16e7672..25e43b8a36c17b7feedf914c8fc2dd95e4c9cbac 100644 (file)
@@ -133,6 +133,8 @@ signals:
 
        void selection_changed();
 
+       void scale_offset_changed();
+
 private:
        void get_scroll_layout(double &length, double &offset) const;