1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
|
/*
* This file is part of the PulseView project.
*
* Copyright (C) 2017 Soeren Apel <soeren@apelpie.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PULSEVIEW_PV_DATA_DECODESIGNAL_HPP
#define PULSEVIEW_PV_DATA_DECODESIGNAL_HPP
#include <atomic>
#include <deque>
#include <condition_variable>
#include <unordered_set>
#include <vector>
#include <QSettings>
#include <QString>
#include <libsigrokdecode/libsigrokdecode.h>
#include <pv/data/decode/decoder.hpp>
#include <pv/data/decode/row.hpp>
#include <pv/data/decode/rowdata.hpp>
#include <pv/data/signalbase.hpp>
#include <pv/util.hpp>
using std::atomic;
using std::condition_variable;
using std::deque;
using std::map;
using std::mutex;
using std::vector;
using std::shared_ptr;
using pv::data::decode::Annotation;
using pv::data::decode::DecodeBinaryClassInfo;
using pv::data::decode::DecodeChannel;
using pv::data::decode::Decoder;
using pv::data::decode::Row;
using pv::data::decode::RowData;
namespace pv {
class Session;
namespace data {
class Logic;
class LogicSegment;
class SignalBase;
class SignalData;
struct DecodeBinaryDataChunk
{
vector<uint8_t> data;
uint64_t sample; ///< Number of the sample where this data was provided by the PD
};
struct DecodeBinaryClass
{
const Decoder* decoder;
const DecodeBinaryClassInfo* info;
deque<DecodeBinaryDataChunk> chunks;
};
struct DecodeSegment
{
map<const Row*, RowData> annotation_rows;
pv::util::Timestamp start_time;
double samplerate;
int64_t samples_decoded_incl, samples_decoded_excl;
vector<DecodeBinaryClass> binary_classes;
};
class DecodeSignal : public SignalBase
{
Q_OBJECT
private:
static const double DecodeMargin;
static const double DecodeThreshold;
static const int64_t DecodeChunkLength;
public:
DecodeSignal(pv::Session &session);
virtual ~DecodeSignal();
bool is_decode_signal() const;
const vector< shared_ptr<Decoder> >& decoder_stack() const;
void stack_decoder(const srd_decoder *decoder, bool restart_decode=true);
void remove_decoder(int index);
bool toggle_decoder_visibility(int index);
void reset_decode(bool shutting_down = false);
void begin_decode();
void pause_decode();
void resume_decode();
bool is_paused() const;
QString error_message() const;
const vector<decode::DecodeChannel> get_channels() const;
void auto_assign_signals(const shared_ptr<Decoder> dec);
void assign_signal(const uint16_t channel_id, const SignalBase *signal);
int get_assigned_signal_count() const;
void set_initial_pin_state(const uint16_t channel_id, const int init_state);
double samplerate() const;
const pv::util::Timestamp start_time() const;
/**
* Returns the number of samples that can be worked on,
* i.e. the number of samples where samples are available
* for all connected channels.
*/
int64_t get_working_sample_count(uint32_t segment_id) const;
/**
* Returns the number of processed samples. Newly generated annotations will
* have sample numbers greater than this.
*
* If include_processing is true, this number will include the ones being
* currently processed (in case the decoder stack is running). In this case,
* newly generated annotations will have sample numbers smaller than this.
*/
int64_t get_decoded_sample_count(uint32_t segment_id,
bool include_processing) const;
vector<Row*> get_rows(bool visible_only=false);
vector<const Row*> get_rows(bool visible_only=false) const;
uint64_t get_annotation_count(const Row* row, uint32_t segment_id) const;
/**
* Extracts annotations from a single row into a vector.
* Note: The annotations may be unsorted and only annotations that fully
* fit into the sample range are considered.
*/
void get_annotation_subset(deque<const Annotation*> &dest, const Row* row,
uint32_t segment_id, uint64_t start_sample, uint64_t end_sample) const;
/**
* Extracts annotations from all rows into a vector.
* Note: The annotations may be unsorted and only annotations that fully
* fit into the sample range are considered.
*/
void get_annotation_subset(deque<const Annotation*> &dest, uint32_t segment_id,
uint64_t start_sample, uint64_t end_sample) const;
uint32_t get_binary_data_chunk_count(uint32_t segment_id,
const Decoder* dec, uint32_t bin_class_id) const;
void get_binary_data_chunk(uint32_t segment_id, const Decoder* dec,
uint32_t bin_class_id, uint32_t chunk_id, const vector<uint8_t> **dest,
uint64_t *size);
void get_merged_binary_data_chunks_by_sample(uint32_t segment_id,
const Decoder* dec, uint32_t bin_class_id,
uint64_t start_sample, uint64_t end_sample,
vector<uint8_t> *dest) const;
void get_merged_binary_data_chunks_by_offset(uint32_t segment_id,
const Decoder* dec, uint32_t bin_class_id,
uint64_t start, uint64_t end,
vector<uint8_t> *dest) const;
const DecodeBinaryClass* get_binary_data_class(uint32_t segment_id,
const Decoder* dec, uint32_t bin_class_id) const;
virtual void save_settings(QSettings &settings) const;
virtual void restore_settings(QSettings &settings);
private:
void set_error_message(QString msg);
uint32_t get_input_segment_count() const;
uint32_t get_input_samplerate(uint32_t segment_id) const;
Decoder* get_decoder_by_instance(const srd_decoder *const srd_dec);
void update_channel_list();
void commit_decoder_channels();
void mux_logic_samples(uint32_t segment_id, const int64_t start, const int64_t end);
void logic_mux_proc();
void decode_data(const int64_t abs_start_samplenum, const int64_t sample_count,
const shared_ptr<LogicSegment> input_segment);
void decode_proc();
void start_srd_session();
void terminate_srd_session();
void stop_srd_session();
void connect_input_notifiers();
void create_decode_segment();
static void annotation_callback(srd_proto_data *pdata, void *decode_signal);
static void binary_callback(srd_proto_data *pdata, void *decode_signal);
Q_SIGNALS:
void decoder_stacked(void* decoder); ///< decoder is of type decode::Decoder*
void decoder_removed(void* decoder); ///< decoder is of type decode::Decoder*
void new_annotations(); // TODO Supply segment for which they belong to
void new_binary_data(unsigned int segment_id, void* decoder, unsigned int bin_class_id);
void decode_reset();
void decode_finished();
void channels_updated();
private Q_SLOTS:
void on_capture_state_changed(int state);
void on_data_cleared();
void on_data_received();
private:
pv::Session &session_;
vector<decode::DecodeChannel> channels_;
struct srd_session *srd_session_;
shared_ptr<Logic> logic_mux_data_;
uint32_t logic_mux_unit_size_;
bool logic_mux_data_invalid_;
vector< shared_ptr<Decoder> > stack_;
bool stack_config_changed_;
vector<DecodeSegment> segments_;
uint32_t current_segment_id_;
mutable mutex input_mutex_, output_mutex_, decode_pause_mutex_, logic_mux_mutex_;
mutable condition_variable decode_input_cond_, decode_pause_cond_,
logic_mux_cond_;
std::thread decode_thread_, logic_mux_thread_;
atomic<bool> decode_interrupt_, logic_mux_interrupt_;
bool decode_paused_;
QString error_message_;
};
} // namespace data
} // namespace pv
#endif // PULSEVIEW_PV_DATA_DECODESIGNAL_HPP
|