#include "devicemanager.hpp"
#include "data/analog.hpp"
-#include "data/analogsnapshot.hpp"
+#include "data/analogsegment.hpp"
#include "data/decoderstack.hpp"
#include "data/logic.hpp"
-#include "data/logicsnapshot.hpp"
+#include "data/logicsegment.hpp"
#include "data/decode/decoder.hpp"
+#include "devices/hardwaredevice.hpp"
+#include "devices/sessionfile.hpp"
+
#include "view/analogsignal.hpp"
#include "view/decodetrace.hpp"
#include "view/logicsignal.hpp"
#include <QDebug>
-#include <libsigrok/libsigrok.hpp>
+#include <libsigrokcxx/libsigrokcxx.hpp>
using boost::shared_lock;
using boost::shared_mutex;
using std::list;
using std::map;
using std::mutex;
+using std::recursive_mutex;
using std::set;
using std::shared_ptr;
using std::string;
+using std::unordered_set;
using std::vector;
using sigrok::Analog;
using sigrok::ChannelType;
using sigrok::ConfigKey;
using sigrok::DatafeedCallbackFunction;
-using sigrok::Device;
using sigrok::Error;
-using sigrok::HardwareDevice;
using sigrok::Header;
using sigrok::Logic;
using sigrok::Meta;
namespace pv {
Session::Session(DeviceManager &device_manager) :
device_manager_(device_manager),
- session_(device_manager.context()->create_session()),
capture_state_(Stopped),
cur_samplerate_(0)
{
- set_default_device();
}
Session::~Session()
return device_manager_;
}
-const shared_ptr<sigrok::Session>& Session::session() const
+shared_ptr<sigrok::Session> Session::session() const
{
- return session_;
+ if (!device_)
+ return shared_ptr<sigrok::Session>();
+ return device_->session();
}
-shared_ptr<Device> Session::device() const
+shared_ptr<devices::Device> Session::device() const
{
return device_;
}
-void Session::set_device(shared_ptr<Device> device)
+void Session::set_device(shared_ptr<devices::Device> device)
{
+ assert(device);
+
// Ensure we are not capturing before setting the device
stop_capture();
- // Are we setting a session device?
- auto session_device = dynamic_pointer_cast<SessionDevice>(device);
- // Did we have a session device selected previously?
- auto prev_session_device = dynamic_pointer_cast<SessionDevice>(device_);
-
- if (device_) {
- session_->remove_datafeed_callbacks();
- if (!prev_session_device) {
- device_->close();
- session_->remove_devices();
- }
- }
-
- if (session_device)
- session_ = session_device->parent();
+ device_ = std::move(device);
+ device_->create();
+ device_->session()->add_datafeed_callback([=]
+ (shared_ptr<sigrok::Device> device, shared_ptr<Packet> packet) {
+ data_feed_in(device, packet);
+ });
+ update_signals();
decode_traces_.clear();
- if (device) {
- if (!session_device)
- {
- session_ = device_manager_.context()->create_session();
-
- try {
- device->open();
- } catch(const sigrok::Error &e) {
- throw QString(e.what());
- }
-
- session_->add_device(device);
- }
-
- device_ = device;
- session_->add_datafeed_callback([=]
- (shared_ptr<Device> device, shared_ptr<Packet> packet) {
- data_feed_in(device, packet);
- });
- update_signals(device);
- } else
- device_ = nullptr;
-
- device_selected();
-}
-
-void Session::set_file(const string &name)
-{
- session_ = device_manager_.context()->load_session(name);
- device_ = session_->devices()[0];
- decode_traces_.clear();
- session_->add_datafeed_callback([=]
- (shared_ptr<Device> device, shared_ptr<Packet> packet) {
- data_feed_in(device, packet);
- });
- device_manager_.update_display_name(device_);
- update_signals(device_);
device_selected();
}
void Session::set_default_device()
{
- shared_ptr<HardwareDevice> default_device;
- const list< shared_ptr<HardwareDevice> > &devices =
+ const list< shared_ptr<devices::HardwareDevice> > &devices =
device_manager_.devices();
- if (!devices.empty()) {
- // Fall back to the first device in the list.
- default_device = devices.front();
-
- // Try and find the demo device and select that by default
- for (shared_ptr<HardwareDevice> dev : devices)
- if (dev->driver()->name().compare("demo") == 0) {
- default_device = dev;
- break;
- }
+ if (devices.empty())
+ return;
- set_device(default_device);
- }
+ // Try and find the demo device and select that by default
+ const auto iter = std::find_if(devices.begin(), devices.end(),
+ [] (const shared_ptr<devices::HardwareDevice> &d) {
+ return d->hardware_device()->driver()->name() ==
+ "demo"; });
+ set_device((iter == devices.end()) ? devices.front() : *iter);
}
Session::capture_state Session::get_capture_state() const
{
stop_capture();
- // Check that a device instance has been selected.
- if (!device_) {
- qDebug() << "No device selected";
- return;
- }
-
// Check that at least one channel is enabled
- auto channels = device_->channels();
- bool enabled = std::any_of(channels.begin(), channels.end(),
- [](shared_ptr<Channel> channel) { return channel->enabled(); });
-
- if (!enabled) {
- error_handler(tr("No channels enabled."));
- return;
+ assert(device_);
+ const shared_ptr<sigrok::Device> sr_dev = device_->device();
+ if (sr_dev) {
+ const auto channels = sr_dev->channels();
+ if (!std::any_of(channels.begin(), channels.end(),
+ [](shared_ptr<Channel> channel) {
+ return channel->enabled(); })) {
+ error_handler(tr("No channels enabled."));
+ return;
+ }
}
+ // Clear signal data
+ for (const shared_ptr<data::SignalData> d : get_data())
+ d->clear();
+
// Begin the session
sampling_thread_ = std::thread(
&Session::sample_thread_proc, this, device_,
void Session::stop_capture()
{
if (get_capture_state() != Stopped)
- session_->stop();
+ device_->stop();
// Check that sampling stopped
if (sampling_thread_.joinable())
return signals_mutex_;
}
-const vector< shared_ptr<view::Signal> >& Session::signals() const
+const unordered_set< shared_ptr<view::Signal> >& Session::signals() const
{
return signals_;
}
// Make a list of all the channels
std::vector<const srd_channel*> all_channels;
- for(const GSList *i = dec->channels; i; i = i->next)
+ for (const GSList *i = dec->channels; i; i = i->next)
all_channels.push_back((const srd_channel*)i->data);
- for(const GSList *i = dec->opt_channels; i; i = i->next)
+ for (const GSList *i = dec->opt_channels; i; i = i->next)
all_channels.push_back((const srd_channel*)i->data);
// Auto select the initial channels
lock_guard<mutex> lock(sampling_mutex_);
const bool changed = capture_state_ != state;
capture_state_ = state;
- if(changed)
+ if (changed)
capture_state_changed(state);
}
-void Session::update_signals(shared_ptr<Device> device)
+void Session::update_signals()
{
- assert(device);
- assert(capture_state_ == Stopped);
+ assert(device_);
- // Clear the decode traces
- decode_traces_.clear();
+ lock_guard<recursive_mutex> lock(data_mutex_);
+
+ const shared_ptr<sigrok::Device> sr_dev = device_->device();
+ if (!sr_dev) {
+ signals_.clear();
+ logic_data_.reset();
+ return;
+ }
// Detect what data types we will receive
- auto channels = device->channels();
+ auto channels = sr_dev->channels();
unsigned int logic_channel_count = std::count_if(
channels.begin(), channels.end(),
[] (shared_ptr<Channel> channel) {
return channel->type() == ChannelType::LOGIC; });
- // Create data containers for the logic data snapshots
+ // Create data containers for the logic data segments
{
- lock_guard<mutex> data_lock(data_mutex_);
+ lock_guard<recursive_mutex> data_lock(data_mutex_);
- logic_data_.reset();
- if (logic_channel_count != 0) {
+ if (logic_channel_count == 0) {
+ logic_data_.reset();
+ } else if (!logic_data_ ||
+ logic_data_->num_channels() != logic_channel_count) {
logic_data_.reset(new data::Logic(
logic_channel_count));
assert(logic_data_);
{
unique_lock<shared_mutex> lock(signals_mutex_);
+ unordered_set< shared_ptr<view::Signal> > prev_sigs(signals_);
signals_.clear();
- for (auto channel : device->channels()) {
+ for (auto channel : sr_dev->channels()) {
shared_ptr<view::Signal> signal;
- switch(channel->type()->id()) {
- case SR_CHANNEL_LOGIC:
- signal = shared_ptr<view::Signal>(
- new view::LogicSignal(*this, device,
- channel, logic_data_));
- break;
-
- case SR_CHANNEL_ANALOG:
- {
- shared_ptr<data::Analog> data(
- new data::Analog());
- signal = shared_ptr<view::Signal>(
- new view::AnalogSignal(
- *this, channel, data));
- break;
- }
-
- default:
- assert(0);
- break;
+ // Find the channel in the old signals
+ const auto iter = std::find_if(
+ prev_sigs.cbegin(), prev_sigs.cend(),
+ [&](const shared_ptr<view::Signal> &s) {
+ return s->channel() == channel;
+ });
+ if (iter != prev_sigs.end()) {
+ // Copy the signal from the old set to the new
+ signal = *iter;
+ auto logic_signal = dynamic_pointer_cast<
+ view::LogicSignal>(signal);
+ if (logic_signal)
+ logic_signal->set_logic_data(
+ logic_data_);
+ } else {
+ // Create a new signal
+ switch(channel->type()->id()) {
+ case SR_CHANNEL_LOGIC:
+ signal = shared_ptr<view::Signal>(
+ new view::LogicSignal(*this,
+ device_, channel,
+ logic_data_));
+ break;
+
+ case SR_CHANNEL_ANALOG:
+ {
+ shared_ptr<data::Analog> data(
+ new data::Analog());
+ signal = shared_ptr<view::Signal>(
+ new view::AnalogSignal(
+ *this, channel, data));
+ break;
+ }
+
+ default:
+ assert(0);
+ break;
+ }
}
assert(signal);
- signals_.push_back(signal);
+ signals_.insert(signal);
}
-
}
signals_changed();
return shared_ptr<view::Signal>();
}
-void Session::read_sample_rate(shared_ptr<Device> device)
-{
- const auto keys = device_->config_keys(ConfigKey::DEVICE_OPTIONS);
- const auto iter = keys.find(ConfigKey::SAMPLERATE);
- cur_samplerate_ = (iter != keys.end() &&
- (*iter).second.find(sigrok::GET) != (*iter).second.end()) ?
- VariantBase::cast_dynamic<Variant<guint64>>(
- device->config_get(ConfigKey::SAMPLERATE)).get() : 0;
-}
-
-void Session::sample_thread_proc(shared_ptr<Device> device,
+void Session::sample_thread_proc(shared_ptr<devices::Device> device,
function<void (const QString)> error_handler)
{
assert(device);
assert(error_handler);
- read_sample_rate(device);
+ (void)device;
+
+ cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
try {
- session_->start();
+ device_->start();
} catch(Error e) {
error_handler(e.what());
return;
}
- set_capture_state(session_->trigger() ?
+ set_capture_state(device_->session()->trigger() ?
AwaitingTrigger : Running);
- session_->run();
+ device_->run();
set_capture_state(Stopped);
// Confirm that SR_DF_END was received
- if (cur_logic_snapshot_)
+ if (cur_logic_segment_)
{
qDebug("SR_DF_END was not received.");
assert(0);
}
}
-void Session::feed_in_header(shared_ptr<Device> device)
+void Session::feed_in_header()
{
- read_sample_rate(device);
+ cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
}
-void Session::feed_in_meta(shared_ptr<Device> device,
- shared_ptr<Meta> meta)
+void Session::feed_in_meta(shared_ptr<Meta> meta)
{
- (void)device;
-
for (auto entry : meta->config()) {
switch (entry.first->id()) {
case SR_CONF_SAMPLERATE:
void Session::feed_in_frame_begin()
{
- if (cur_logic_snapshot_ || !cur_analog_snapshots_.empty())
+ if (cur_logic_segment_ || !cur_analog_segments_.empty())
frame_began();
}
void Session::feed_in_logic(shared_ptr<Logic> logic)
{
- lock_guard<mutex> lock(data_mutex_);
+ lock_guard<recursive_mutex> lock(data_mutex_);
if (!logic_data_)
{
- qDebug() << "Unexpected logic packet";
- return;
+ // The only reason logic_data_ would not have been created is
+ // if it was not possible to determine the signals when the
+ // device was created.
+ update_signals();
}
- if (!cur_logic_snapshot_)
+ if (!cur_logic_segment_)
{
// This could be the first packet after a trigger
set_capture_state(Running);
// Get sample limit.
- const auto keys = device_->config_keys(
- ConfigKey::DEVICE_OPTIONS);
- const auto iter = keys.find(ConfigKey::LIMIT_SAMPLES);
- const uint64_t sample_limit = (iter != keys.end() &&
- (*iter).second.find(sigrok::GET) !=
- (*iter).second.end()) ?
- VariantBase::cast_dynamic<Variant<guint64>>(
- device_->config_get(ConfigKey::LIMIT_SAMPLES)).get() : 0;
-
- // Create a new data snapshot
- cur_logic_snapshot_ = shared_ptr<data::LogicSnapshot>(
- new data::LogicSnapshot(
+ const uint64_t sample_limit = device_->read_config<uint64_t>(
+ ConfigKey::LIMIT_SAMPLES);
+
+ // Create a new data segment
+ cur_logic_segment_ = shared_ptr<data::LogicSegment>(
+ new data::LogicSegment(
logic, cur_samplerate_, sample_limit));
- logic_data_->push_snapshot(cur_logic_snapshot_);
+ logic_data_->push_segment(cur_logic_segment_);
// @todo Putting this here means that only listeners querying
// for logic will be notified. Currently the only user of
}
else
{
- // Append to the existing data snapshot
- cur_logic_snapshot_->append_payload(logic);
+ // Append to the existing data segment
+ cur_logic_segment_->append_payload(logic);
}
data_received();
void Session::feed_in_analog(shared_ptr<Analog> analog)
{
- lock_guard<mutex> lock(data_mutex_);
+ lock_guard<recursive_mutex> lock(data_mutex_);
const vector<shared_ptr<Channel>> channels = analog->channels();
const unsigned int channel_count = channels.size();
for (auto channel : channels)
{
- shared_ptr<data::AnalogSnapshot> snapshot;
+ shared_ptr<data::AnalogSegment> segment;
- // Try to get the snapshot of the channel
- const map< shared_ptr<Channel>, shared_ptr<data::AnalogSnapshot> >::
- iterator iter = cur_analog_snapshots_.find(channel);
- if (iter != cur_analog_snapshots_.end())
- snapshot = (*iter).second;
+ // Try to get the segment of the channel
+ const map< shared_ptr<Channel>, shared_ptr<data::AnalogSegment> >::
+ iterator iter = cur_analog_segments_.find(channel);
+ if (iter != cur_analog_segments_.end())
+ segment = (*iter).second;
else
{
- // If no snapshot was found, this means we havn't
+ // If no segment was found, this means we havn't
// created one yet. i.e. this is the first packet
- // in the sweep containing this snapshot.
+ // in the sweep containing this segment.
sweep_beginning = true;
// Get sample limit.
uint64_t sample_limit;
try {
+ assert(device_);
+ const std::shared_ptr<sigrok::Device> device =
+ device_->device();
+ assert(device);
sample_limit = VariantBase::cast_dynamic<Variant<guint64>>(
- device_->config_get(ConfigKey::LIMIT_SAMPLES)).get();
+ device->config_get(ConfigKey::LIMIT_SAMPLES)).get();
} catch (Error) {
sample_limit = 0;
}
- // Create a snapshot, keep it in the maps of channels
- snapshot = shared_ptr<data::AnalogSnapshot>(
- new data::AnalogSnapshot(
+ // Create a segment, keep it in the maps of channels
+ segment = shared_ptr<data::AnalogSegment>(
+ new data::AnalogSegment(
cur_samplerate_, sample_limit));
- cur_analog_snapshots_[channel] = snapshot;
+ cur_analog_segments_[channel] = segment;
// Find the annalog data associated with the channel
shared_ptr<view::AnalogSignal> sig =
shared_ptr<data::Analog> data(sig->analog_data());
assert(data);
- // Push the snapshot into the analog data.
- data->push_snapshot(snapshot);
+ // Push the segment into the analog data.
+ data->push_segment(segment);
}
- assert(snapshot);
+ assert(segment);
- // Append the samples in the snapshot
- snapshot->append_interleaved_samples(data++, sample_count,
+ // Append the samples in the segment
+ segment->append_interleaved_samples(data++, sample_count,
channel_count);
}
data_received();
}
-void Session::data_feed_in(shared_ptr<Device> device, shared_ptr<Packet> packet)
+void Session::data_feed_in(shared_ptr<sigrok::Device> device,
+ shared_ptr<Packet> packet)
{
+ (void)device;
+
assert(device);
+ assert(device == device_->device());
assert(packet);
switch (packet->type()->id()) {
case SR_DF_HEADER:
- feed_in_header(device);
+ feed_in_header();
break;
case SR_DF_META:
- feed_in_meta(device, dynamic_pointer_cast<Meta>(packet->payload()));
+ feed_in_meta(dynamic_pointer_cast<Meta>(packet->payload()));
break;
case SR_DF_FRAME_BEGIN:
case SR_DF_END:
{
{
- lock_guard<mutex> lock(data_mutex_);
- cur_logic_snapshot_.reset();
- cur_analog_snapshots_.clear();
+ lock_guard<recursive_mutex> lock(data_mutex_);
+ cur_logic_segment_.reset();
+ cur_analog_segments_.clear();
}
frame_ended();
break;