]> sigrok.org Git - pulseview.git/blob - pv/sigsession.cpp
Factored out feed_in_meta_logic
[pulseview.git] / pv / sigsession.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
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, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include "sigsession.h"
22
23 #include "logicdata.h"
24 #include "logicdatasnapshot.h"
25 #include "view/logicsignal.h"
26
27 #include <QDebug>
28
29 #include <assert.h>
30
31 using namespace boost;
32 using namespace std;
33
34 namespace pv {
35
36 // TODO: This should not be necessary
37 SigSession* SigSession::_session = NULL;
38
39 SigSession::SigSession() :
40         _capture_state(Stopped)
41 {
42         // TODO: This should not be necessary
43         _session = this;
44 }
45
46 SigSession::~SigSession()
47 {
48         stop_capture();
49
50         if (_sampling_thread.get())
51                 _sampling_thread->join();
52         _sampling_thread.reset();
53
54         // TODO: This should not be necessary
55         _session = NULL;
56 }
57
58 void SigSession::load_file(const string &name)
59 {
60         stop_capture();
61         _sampling_thread.reset(new boost::thread(
62                 &SigSession::load_thread_proc, this, name));
63 }
64
65 SigSession::capture_state SigSession::get_capture_state() const
66 {
67         lock_guard<mutex> lock(_state_mutex);
68         return _capture_state;
69 }
70
71 void SigSession::start_capture(struct sr_dev_inst *sdi,
72         uint64_t record_length, uint64_t sample_rate)
73 {
74         stop_capture();
75
76
77         _sampling_thread.reset(new boost::thread(
78                 &SigSession::sample_thread_proc, this, sdi,
79                 record_length, sample_rate));
80 }
81
82 void SigSession::stop_capture()
83 {
84         if (get_capture_state() == Stopped)
85                 return;
86
87         sr_session_stop();
88
89         // Check that sampling stopped
90         if (_sampling_thread.get())
91                 _sampling_thread->join();
92         _sampling_thread.reset();
93 }
94
95 vector< shared_ptr<view::Signal> > SigSession::get_signals()
96 {
97         lock_guard<mutex> lock(_signals_mutex);
98         return _signals;
99 }
100
101 boost::shared_ptr<LogicData> SigSession::get_data()
102 {
103         return _logic_data;
104 }
105
106 void SigSession::set_capture_state(capture_state state)
107 {
108         lock_guard<mutex> lock(_state_mutex);
109         _capture_state = state;
110         capture_state_changed(state);
111 }
112
113 void SigSession::load_thread_proc(const string name)
114 {
115         if (sr_session_load(name.c_str()) != SR_OK) {
116                 qDebug() << "Failed to load file.";
117                 return;
118         }
119
120         sr_session_datafeed_callback_add(data_feed_in_proc);
121
122         if (sr_session_start() != SR_OK) {
123                 qDebug() << "Failed to start session.";
124                 return;
125         }
126
127         set_capture_state(Running);
128
129         sr_session_run();
130         sr_session_stop();
131
132         set_capture_state(Stopped);
133 }
134
135 void SigSession::sample_thread_proc(struct sr_dev_inst *sdi,
136         uint64_t record_length, uint64_t sample_rate)
137 {
138         sr_session_new();
139         sr_session_datafeed_callback_add(data_feed_in_proc);
140
141         if (sr_session_dev_add(sdi) != SR_OK) {
142                 qDebug() << "Failed to use device.";
143                 sr_session_destroy();
144                 return;
145         }
146
147         if (sr_dev_config_set(sdi, SR_HWCAP_LIMIT_SAMPLES,
148                 &record_length) != SR_OK) {
149                 qDebug() << "Failed to configure time-based sample limit.";
150                 sr_session_destroy();
151                 return;
152         }
153
154         if (sr_dev_config_set(sdi, SR_HWCAP_SAMPLERATE,
155                 &sample_rate) != SR_OK) {
156                 qDebug() << "Failed to configure samplerate.";
157                 sr_session_destroy();
158                 return;
159         }
160
161         if (sr_session_start() != SR_OK) {
162                 qDebug() << "Failed to start session.";
163                 return;
164         }
165
166         set_capture_state(Running);
167
168         sr_session_run();
169         sr_session_destroy();
170
171         set_capture_state(Stopped);
172 }
173
174 void SigSession::feed_in_meta_logic(const struct sr_dev_inst *sdi,
175         const sr_datafeed_meta_logic &meta_logic)
176 {
177         using view::LogicSignal;
178
179         {
180                 lock_guard<mutex> lock(_data_mutex);
181
182                 // Create an empty LogicData for coming data snapshots
183                 _logic_data.reset(new LogicData(meta_logic));
184                 assert(_logic_data);
185                 if (!_logic_data)
186                         return;
187         }
188
189         {
190                 lock_guard<mutex> lock(_signals_mutex);
191
192                 // Add the signals
193                 for (int i = 0; i < meta_logic.num_probes; i++) {
194                         const sr_probe *const probe =
195                                 (const sr_probe*)g_slist_nth_data(
196                                         sdi->probes, i);
197                         if (probe->enabled) {
198                                 shared_ptr<LogicSignal> signal(
199                                         new LogicSignal(probe->name,
200                                                 _logic_data, probe->index));
201                                 _signals.push_back(signal);
202                         }
203                 }
204
205                 signals_changed();
206         }
207 }
208
209 void SigSession::data_feed_in(const struct sr_dev_inst *sdi,
210         const struct sr_datafeed_packet *packet)
211 {
212         assert(sdi);
213         assert(packet);
214
215         switch (packet->type) {
216         case SR_DF_HEADER:
217         {
218                 lock_guard<mutex> lock(_signals_mutex);
219                 _signals.clear();
220                 break;
221         }
222
223         case SR_DF_META_LOGIC:
224                 assert(packet->payload);
225                 feed_in_meta_logic(sdi,
226                         *(const sr_datafeed_meta_logic*)packet->payload);
227                 break;
228
229         case SR_DF_LOGIC:
230         {
231                 lock_guard<mutex> lock(_data_mutex);
232                 assert(packet->payload);
233                 if (!_cur_logic_snapshot)
234                 {
235                         // Create a new data snapshot
236                         _cur_logic_snapshot = shared_ptr<LogicDataSnapshot>(
237                                 new LogicDataSnapshot(
238                                 *(sr_datafeed_logic*)packet->payload));
239                         _logic_data->push_snapshot(_cur_logic_snapshot);
240                 }
241                 else
242                 {
243                         // Append to the existing data snapshot
244                         _cur_logic_snapshot->append_payload(
245                                 *(sr_datafeed_logic*)packet->payload);
246                 }
247
248                 data_updated();
249                 break;
250         }
251
252         case SR_DF_END:
253         {
254                 {
255                         lock_guard<mutex> lock(_data_mutex);
256                         _cur_logic_snapshot.reset();
257                 }
258                 data_updated();
259                 break;
260         }
261         }
262 }
263
264 void SigSession::data_feed_in_proc(const struct sr_dev_inst *sdi,
265         const struct sr_datafeed_packet *packet)
266 {
267         assert(_session);
268         _session->data_feed_in(sdi, packet);
269 }
270
271 } // namespace pv