* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <QDebug>
#include <QFileInfo>
#include <cassert>
#include "data/analog.hpp"
#include "data/analogsegment.hpp"
#include "data/decode/decoder.hpp"
-#include "data/decoderstack.hpp"
#include "data/logic.hpp"
#include "data/logicsegment.hpp"
#include "data/signalbase.hpp"
#ifdef ENABLE_DECODE
#include <libsigrokdecode/libsigrokdecode.h>
+#include "data/decodesignal.hpp"
#endif
using std::bad_alloc;
using Glib::VariantBase;
namespace pv {
+
+shared_ptr<sigrok::Context> Session::sr_context;
+
Session::Session(DeviceManager &device_manager, QString name) :
device_manager_(device_manager),
default_name_(name),
{
map<string, string> dev_info;
list<string> key_list;
- int stacks = 0, views = 0;
+ int decode_signals = 0, views = 0;
if (device_) {
shared_ptr<devices::HardwareDevice> hw_device =
for (shared_ptr<data::SignalBase> base : signalbases_) {
#ifdef ENABLE_DECODE
if (base->is_decode_signal()) {
- shared_ptr<pv::data::DecoderStack> decoder_stack =
- base->decoder_stack();
- shared_ptr<data::decode::Decoder> top_decoder =
- decoder_stack->stack().front();
-
- settings.beginGroup("decoder_stack" + QString::number(stacks++));
- settings.setValue("id", top_decoder->decoder()->id);
- settings.setValue("name", top_decoder->decoder()->name);
+ settings.beginGroup("decode_signal" + QString::number(decode_signals++));
+ base->save_settings(settings);
settings.endGroup();
} else
#endif
}
}
- settings.setValue("decoder_stacks", stacks);
+ settings.setValue("decode_signals", decode_signals);
// Save view states and their signal settings
// Note: main_view must be saved as view0
// Restore decoders
#ifdef ENABLE_DECODE
- int stacks = settings.value("decoder_stacks").toInt();
-
- for (int i = 0; i < stacks; i++) {
- settings.beginGroup("decoder_stack" + QString::number(i++));
-
- QString id = settings.value("id").toString();
- add_decoder(srd_decoder_get_by_id(id.toStdString().c_str()));
+ int decode_signals = settings.value("decode_signals").toInt();
+ for (int i = 0; i < decode_signals; i++) {
+ settings.beginGroup("decode_signal" + QString::number(i));
+ shared_ptr<data::DecodeSignal> signal = add_decode_signal();
+ signal->restore_settings(settings);
settings.endGroup();
}
#endif
views_.push_back(view);
+ // Add all device signals
update_signals();
+
+ // Add all other signals
+ unordered_set< shared_ptr<data::SignalBase> > view_signalbases =
+ view->signalbases();
+
+ views::trace::View *trace_view =
+ qobject_cast<views::trace::View*>(view.get());
+
+ if (trace_view) {
+ for (shared_ptr<data::SignalBase> signalbase : signalbases_) {
+ const int sb_exists = count_if(
+ view_signalbases.cbegin(), view_signalbases.cend(),
+ [&](const shared_ptr<data::SignalBase> &sb) {
+ return sb == signalbase;
+ });
+ // Add the signal to the view as it doesn't have it yet
+ if (!sb_exists)
+ switch (signalbase->type()) {
+ case data::SignalBase::AnalogChannel:
+ case data::SignalBase::LogicChannel:
+ case data::SignalBase::DecodeChannel:
+#ifdef ENABLE_DECODE
+ trace_view->add_decode_signal(
+ dynamic_pointer_cast<data::DecodeSignal>(signalbase));
+#endif
+ break;
+ case data::SignalBase::MathChannel:
+ // TBD
+ break;
+ }
+ }
+ }
+
+ signals_changed();
}
void Session::deregister_view(shared_ptr<views::ViewBase> view)
return samplerate;
}
+int Session::get_segment_count() const
+{
+ int min_val = INT_MAX;
+
+ for (shared_ptr<data::SignalData> data : all_signal_data_)
+ if (data->get_segment_count() < min_val)
+ min_val = data->get_segment_count();
+
+ return min_val;
+}
+
const unordered_set< shared_ptr<data::SignalBase> > Session::signalbases() const
{
return signalbases_;
}
#ifdef ENABLE_DECODE
-bool Session::add_decoder(srd_decoder *const dec)
+shared_ptr<data::DecodeSignal> Session::add_decode_signal()
{
- if (!dec)
- return false;
-
- map<const srd_channel*, shared_ptr<data::SignalBase> > channels;
- shared_ptr<data::DecoderStack> decoder_stack;
+ shared_ptr<data::DecodeSignal> signal;
try {
- // Create the decoder
- decoder_stack = make_shared<data::DecoderStack>(*this, dec);
-
- // Make a list of all the channels
- vector<const srd_channel*> all_channels;
- 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)
- all_channels.push_back((const srd_channel*)i->data);
-
- // Auto select the initial channels
- for (const srd_channel *pdch : all_channels)
- for (shared_ptr<data::SignalBase> b : signalbases_) {
- if (b->logic_data()) {
- if (QString::fromUtf8(pdch->name).toLower().
- contains(b->name().toLower()))
- channels[pdch] = b;
- }
- }
-
- assert(decoder_stack);
- assert(!decoder_stack->stack().empty());
- assert(decoder_stack->stack().front());
- decoder_stack->stack().front()->set_channels(channels);
-
// Create the decode signal
- shared_ptr<data::SignalBase> signalbase =
- make_shared<data::SignalBase>(nullptr, data::SignalBase::DecodeChannel);
+ signal = make_shared<data::DecodeSignal>(*this);
- signalbase->set_decoder_stack(decoder_stack);
- signalbases_.insert(signalbase);
+ signalbases_.insert(signal);
+ // Add the decode signal to all views
for (shared_ptr<views::ViewBase> view : views_)
- view->add_decode_signal(signalbase);
+ view->add_decode_signal(signal);
} catch (runtime_error e) {
- return false;
+ remove_decode_signal(signal);
+ return nullptr;
}
signals_changed();
- // Do an initial decode
- decoder_stack->begin_decode();
-
- return true;
+ return signal;
}
-void Session::remove_decode_signal(shared_ptr<data::SignalBase> signalbase)
+void Session::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
{
- signalbases_.erase(signalbase);
+ signalbases_.erase(signal);
for (shared_ptr<views::ViewBase> view : views_)
- view->remove_decode_signal(signalbase);
+ view->remove_decode_signal(signal);
signals_changed();
}
void Session::feed_in_header()
{
- cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
+ // Nothing to do here for now
}
void Session::feed_in_meta(shared_ptr<Meta> meta)
void Session::feed_in_frame_begin()
{
+ frame_began_ = true;
+
if (cur_logic_segment_ || !cur_analog_segments_.empty())
frame_began();
}
+void Session::feed_in_frame_end()
+{
+ {
+ lock_guard<recursive_mutex> lock(data_mutex_);
+ cur_logic_segment_.reset();
+ cur_analog_segments_.clear();
+ }
+
+ if (frame_began_) {
+ frame_began_ = false;
+ frame_ended();
+ }
+}
+
void Session::feed_in_logic(shared_ptr<Logic> logic)
{
+ if (!cur_samplerate_)
+ cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
+
lock_guard<recursive_mutex> lock(data_mutex_);
if (!logic_data_) {
void Session::feed_in_analog(shared_ptr<Analog> analog)
{
+ if (!cur_samplerate_)
+ cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
+
lock_guard<recursive_mutex> lock(data_mutex_);
const vector<shared_ptr<Channel>> channels = analog->channels();
void Session::data_feed_in(shared_ptr<sigrok::Device> device,
shared_ptr<Packet> packet)
{
- static bool frame_began = false;
-
(void)device;
assert(device);
feed_in_trigger();
break;
- case SR_DF_FRAME_BEGIN:
- feed_in_frame_begin();
- frame_began = true;
- break;
-
case SR_DF_LOGIC:
try {
feed_in_logic(dynamic_pointer_cast<Logic>(packet->payload()));
}
break;
+ case SR_DF_FRAME_BEGIN:
+ feed_in_frame_begin();
+ break;
+
case SR_DF_FRAME_END:
+ feed_in_frame_end();
+ break;
+
case SR_DF_END:
- {
+ // Strictly speaking, this is performed when a frame end marker was
+ // received, so there's no point doing this again. However, not all
+ // devices use frames, and for those devices, we need to do it here.
{
lock_guard<recursive_mutex> lock(data_mutex_);
cur_logic_segment_.reset();
cur_analog_segments_.clear();
}
- if (frame_began) {
- frame_began = false;
- frame_ended();
- }
break;
- }
+
default:
break;
}