]> sigrok.org Git - pulseview.git/blob - pv/sigsession.cpp
b9ccc2b613d9d06f84a4ebab7caa2aa2eb8d0ab0
[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::feed_in_logic(const sr_datafeed_logic &logic)
210 {
211         lock_guard<mutex> lock(_data_mutex);
212         if (!_cur_logic_snapshot)
213         {
214                 // Create a new data snapshot
215                 _cur_logic_snapshot = shared_ptr<LogicDataSnapshot>(
216                         new LogicDataSnapshot(logic));
217                 _logic_data->push_snapshot(_cur_logic_snapshot);
218         }
219         else
220         {
221                 // Append to the existing data snapshot
222                 _cur_logic_snapshot->append_payload(logic);
223         }
224
225         data_updated();
226 }
227
228
229 void SigSession::data_feed_in(const struct sr_dev_inst *sdi,
230         const struct sr_datafeed_packet *packet)
231 {
232         assert(sdi);
233         assert(packet);
234
235         switch (packet->type) {
236         case SR_DF_HEADER:
237         {
238                 lock_guard<mutex> lock(_signals_mutex);
239                 _signals.clear();
240                 break;
241         }
242
243         case SR_DF_META_LOGIC:
244                 assert(packet->payload);
245                 feed_in_meta_logic(sdi,
246                         *(const sr_datafeed_meta_logic*)packet->payload);
247                 break;
248
249         case SR_DF_LOGIC:
250                 assert(packet->payload);
251                 feed_in_logic(*(const sr_datafeed_logic*)packet->payload);
252                 break;
253
254         case SR_DF_END:
255         {
256                 {
257                         lock_guard<mutex> lock(_data_mutex);
258                         _cur_logic_snapshot.reset();
259                 }
260                 data_updated();
261                 break;
262         }
263         }
264 }
265
266 void SigSession::data_feed_in_proc(const struct sr_dev_inst *sdi,
267         const struct sr_datafeed_packet *packet)
268 {
269         assert(_session);
270         _session->data_feed_in(sdi, packet);
271 }
272
273 } // namespace pv