]> sigrok.org Git - pulseview.git/blob - pv/sigsession.cpp
Mutex protected SigSession::_signals
[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 {
41         // TODO: This should not be necessary
42         _session = this;
43 }
44
45 SigSession::~SigSession()
46 {
47         if(_sampling_thread.get())
48                 _sampling_thread->join();
49         _sampling_thread.reset();
50
51         // TODO: This should not be necessary
52         _session = NULL;
53 }
54
55 void SigSession::load_file(const std::string &name)
56 {
57         if (sr_session_load(name.c_str()) == SR_OK) {
58                 /* sigrok session file */
59                 sr_session_datafeed_callback_add(data_feed_in_proc);
60                 sr_session_start();
61                 sr_session_run();
62                 sr_session_stop();
63         }
64 }
65
66 void SigSession::start_capture(struct sr_dev_inst *sdi,
67         uint64_t record_length, uint64_t sample_rate)
68 {
69         // Check sampling isn't already active
70         if(_sampling_thread.get())
71                 _sampling_thread->join();
72
73         _sampling_thread.reset(new boost::thread(
74                 &SigSession::sample_thread_proc, this, sdi,
75                 record_length, sample_rate));
76 }
77
78 vector< shared_ptr<view::Signal> > SigSession::get_signals()
79 {
80         lock_guard<mutex> lock(_signals_mutex);
81         return _signals;
82 }
83
84 boost::shared_ptr<LogicData> SigSession::get_data()
85 {
86         return _logic_data;
87 }
88
89 void SigSession::sample_thread_proc(struct sr_dev_inst *sdi,
90         uint64_t record_length, uint64_t sample_rate)
91 {
92         sr_session_new();
93         sr_session_datafeed_callback_add(data_feed_in_proc);
94
95         if (sr_session_dev_add(sdi) != SR_OK) {
96                 qDebug() << "Failed to use device.";
97                 sr_session_destroy();
98                 return;
99         }
100
101         if (sr_dev_config_set(sdi, SR_HWCAP_LIMIT_SAMPLES,
102                 &record_length) != SR_OK) {
103                 qDebug() << "Failed to configure time-based sample limit.";
104                 sr_session_destroy();
105                 return;
106         }
107
108         if (sr_dev_config_set(sdi, SR_HWCAP_SAMPLERATE,
109                 &sample_rate) != SR_OK) {
110                 qDebug() << "Failed to configure samplerate.";
111                 sr_session_destroy();
112                 return;
113         }
114
115         if (sr_session_start() != SR_OK) {
116                 qDebug() << "Failed to start session.";
117                 return;
118         }
119
120         sr_session_run();
121         sr_session_destroy();
122 }
123
124 void SigSession::data_feed_in(const struct sr_dev_inst *sdi,
125         struct sr_datafeed_packet *packet)
126 {
127         using view::LogicSignal;
128
129         assert(sdi);
130         assert(packet);
131
132         switch (packet->type) {
133         case SR_DF_HEADER:
134         {
135                 lock_guard<mutex> lock(_signals_mutex);
136                 _signals.clear();
137                 break;
138         }
139
140         case SR_DF_META_LOGIC:
141         {
142                 assert(packet->payload);
143                 const sr_datafeed_meta_logic &meta_logic =
144                         *(sr_datafeed_meta_logic*)packet->payload;
145
146         {
147                 lock_guard<mutex> lock(_data_mutex);
148
149                 // Create an empty LogiData for coming data snapshots
150                 _logic_data.reset(new LogicData(meta_logic));
151                 assert(_logic_data);
152                 if(!_logic_data)
153                         break;
154         }
155
156         {
157                 lock_guard<mutex> lock(_signals_mutex);
158
159                 // Add the signals
160                 for (int i = 0; i < meta_logic.num_probes; i++)
161                 {
162                         const sr_probe *const probe =
163                                 (const sr_probe*)g_slist_nth_data(
164                                         sdi->probes, i);
165                         if(probe->enabled)
166                         {
167                                 shared_ptr<LogicSignal> signal(
168                                         new LogicSignal(probe->name,
169                                                 _logic_data,
170                                                 probe->index));
171                                 _signals.push_back(signal);
172                         }
173                 }
174
175                 signals_changed();
176                 break;
177         }
178         }
179
180         case SR_DF_LOGIC:
181         {
182                 lock_guard<mutex> lock(_data_mutex);
183                 assert(packet->payload);
184                 if(!_cur_logic_snapshot)
185                 {
186                         // Create a new data snapshot
187                         _cur_logic_snapshot = shared_ptr<LogicDataSnapshot>(
188                                 new LogicDataSnapshot(
189                                 *(sr_datafeed_logic*)packet->payload));
190                         _logic_data->push_snapshot(_cur_logic_snapshot);
191                 }
192                 else
193                 {
194                         // Append to the existing data snapshot
195                         _cur_logic_snapshot->append_payload(
196                                 *(sr_datafeed_logic*)packet->payload);
197                 }
198
199                 break;
200         }
201
202         case SR_DF_END:
203         {
204                 {
205                         lock_guard<mutex> lock(_data_mutex);
206                         _cur_logic_snapshot.reset();
207                 }
208                 data_updated();
209                 break;
210         }
211         }
212 }
213
214 void SigSession::data_feed_in_proc(const struct sr_dev_inst *sdi,
215         struct sr_datafeed_packet *packet)
216 {
217         assert(_session);
218         _session->data_feed_in(sdi, packet);
219 }
220
221 } // namespace pv