File: decodesignal.hpp

package info (click to toggle)
pulseview 0.4.2-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,064 kB
  • sloc: cpp: 25,958; xml: 215; java: 42; makefile: 2
file content (259 lines) | stat: -rw-r--r-- 7,762 bytes parent folder | download | duplicates (3)
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