X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fdata%2Fdecoder.cpp;h=9e7145f34fe4ffd2c715f141d9701dfb4b0b7a38;hp=ea0fed6bd47a0faf9f506a43053060c9f2889363;hb=f00fc2a9e1cc85888a732de9f981f50ce957e5f1;hpb=119aff65d8ad0c4cdaff32d9b68cee00d90a5f35 diff --git a/pv/data/decoder.cpp b/pv/data/decoder.cpp index ea0fed6b..9e7145f3 100644 --- a/pv/data/decoder.cpp +++ b/pv/data/decoder.cpp @@ -18,14 +18,52 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + +#include + +#include + +#include + #include "decoder.h" +#include +#include +#include +#include + +using namespace boost; +using namespace std; + namespace pv { namespace data { -Decoder::Decoder(const srd_decoder *const dec) : - _decoder(dec) +const double Decoder::DecodeMargin = 1.0; +const double Decoder::DecodeThreshold = 0.2; +const int64_t Decoder::DecodeChunkLength = 4096; + +mutex Decoder::_global_decode_mutex; + +Decoder::Decoder(const srd_decoder *const dec, + std::map > probes, + GHashTable *options) : + _decoder(dec), + _probes(probes), + _options(options) { + init_decoder(); + + begin_decode(); +} + +Decoder::~Decoder() +{ + _decode_thread.interrupt(); + _decode_thread.join(); + + g_hash_table_destroy(_options); } const srd_decoder* Decoder::get_decoder() const @@ -33,9 +71,154 @@ const srd_decoder* Decoder::get_decoder() const return _decoder; } +const vector< shared_ptr > + Decoder::annotations() const +{ + lock_guard lock(_mutex); + return _annotations; +} + +QString Decoder::error_message() +{ + lock_guard lock(_mutex); + return _error_message; +} + +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 sig = (*_probes.begin()).second; + assert(sig); + shared_ptr data = sig->data(); + + _decode_thread = boost::thread(&Decoder::decode_proc, this, + data); +} + void Decoder::clear_snapshots() { } +void Decoder::init_decoder() +{ + if (!_probes.empty()) + { + shared_ptr logic_signal = + dynamic_pointer_cast( + (*_probes.begin()).second); + if (logic_signal) { + shared_ptr data( + logic_signal->data()); + if (data) { + _start_time = data->get_start_time(); + _samplerate = data->get_samplerate(); + if (_samplerate == 0.0) + _samplerate = 1.0; + } + } + } +} + +void Decoder::decode_proc(shared_ptr data) +{ + srd_session *session; + uint8_t chunk[DecodeChunkLength]; + + assert(data); + + _annotations.clear(); + + const deque< shared_ptr > &snapshots = + data->get_snapshots(); + if (snapshots.empty()) + return; + + const shared_ptr &snapshot = + snapshots.front(); + const int64_t sample_count = snapshot->get_sample_count() - 1; + + // Create the session + srd_session_new(&session); + assert(session); + + srd_session_metadata_set(session, SRD_CONF_SAMPLERATE, + g_variant_new_uint64((uint64_t)_samplerate)); + + srd_pd_output_callback_add(session, SRD_OUTPUT_ANN, + Decoder::annotation_callback, this); + + // Create the decoder instance + srd_decoder_inst *const decoder_inst = srd_inst_new( + session, _decoder->id, _options); + if(!decoder_inst) { + _error_message = tr("Failed to initialise decoder"); + return; + } + + // Setup the probes + GHashTable *const probes = g_hash_table_new_full(g_str_hash, + g_str_equal, g_free, (GDestroyNotify)g_variant_unref); + + for(map >:: + const_iterator i = _probes.begin(); + i != _probes.end(); i++) + { + shared_ptr signal((*i).second); + GVariant *const gvar = g_variant_new_int32( + signal->probe()->index); + g_variant_ref_sink(gvar); + g_hash_table_insert(probes, (*i).first->id, gvar); + } + + srd_inst_probe_set_all(decoder_inst, probes); + + // Start the session + srd_session_start(session); + + for (int64_t i = 0; + !this_thread::interruption_requested() && i < sample_count; + i += DecodeChunkLength) + { + lock_guard decode_lock(_global_decode_mutex); + + const int64_t chunk_end = min( + i + DecodeChunkLength, sample_count); + snapshot->get_samples(chunk, i, chunk_end); + + if (srd_session_send(session, i, i + sample_count, + chunk, chunk_end - i) != SRD_OK) { + _error_message = tr("Failed to initialise decoder"); + break; + } + } + + // Destroy the session + srd_session_destroy(session); +} + +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 a(new Annotation(pdata)); + lock_guard lock(d->_mutex); + d->_annotations.push_back(a); + + d->new_decode_data(); +} + } // namespace data } // namespace pv