]> sigrok.org Git - pulseview.git/blob - pv/sigsession.cpp
42d8e5520a379b1de3c024daa144bb6c5649892a
[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::data_feed_in(const struct sr_dev_inst *sdi,
175         const struct sr_datafeed_packet *packet)
176 {
177         using view::LogicSignal;
178
179         assert(sdi);
180         assert(packet);
181
182         switch (packet->type) {
183         case SR_DF_HEADER:
184         {
185                 lock_guard<mutex> lock(_signals_mutex);
186                 _signals.clear();
187                 break;
188         }
189
190         case SR_DF_META_LOGIC:
191         {
192                 assert(packet->payload);
193                 const sr_datafeed_meta_logic &meta_logic =
194                         *(sr_datafeed_meta_logic*)packet->payload;
195
196         {
197                 lock_guard<mutex> lock(_data_mutex);
198
199                 // Create an empty LogiData for coming data snapshots
200                 _logic_data.reset(new LogicData(meta_logic));
201                 assert(_logic_data);
202                 if (!_logic_data)
203                         break;
204         }
205
206         {
207                 lock_guard<mutex> lock(_signals_mutex);
208
209                 // Add the signals
210                 for (int i = 0; i < meta_logic.num_probes; i++)
211                 {
212                         const sr_probe *const probe =
213                                 (const sr_probe*)g_slist_nth_data(
214                                         sdi->probes, i);
215                         if (probe->enabled)
216                         {
217                                 shared_ptr<LogicSignal> signal(
218                                         new LogicSignal(probe->name,
219                                                 _logic_data,
220                                                 probe->index));
221                                 _signals.push_back(signal);
222                         }
223                 }
224
225                 signals_changed();
226                 break;
227         }
228         }
229
230         case SR_DF_LOGIC:
231         {
232                 lock_guard<mutex> lock(_data_mutex);
233                 assert(packet->payload);
234                 if (!_cur_logic_snapshot)
235                 {
236                         // Create a new data snapshot
237                         _cur_logic_snapshot = shared_ptr<LogicDataSnapshot>(
238                                 new LogicDataSnapshot(
239                                 *(sr_datafeed_logic*)packet->payload));
240                         _logic_data->push_snapshot(_cur_logic_snapshot);
241                 }
242                 else
243                 {
244                         // Append to the existing data snapshot
245                         _cur_logic_snapshot->append_payload(
246                                 *(sr_datafeed_logic*)packet->payload);
247                 }
248
249                 data_updated();
250                 break;
251         }
252
253         case SR_DF_END:
254         {
255                 {
256                         lock_guard<mutex> lock(_data_mutex);
257                         _cur_logic_snapshot.reset();
258                 }
259                 data_updated();
260                 break;
261         }
262         }
263 }
264
265 void SigSession::data_feed_in_proc(const struct sr_dev_inst *sdi,
266         const struct sr_datafeed_packet *packet)
267 {
268         assert(_session);
269         _session->data_feed_in(sdi, packet);
270 }
271
272 } // namespace pv