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