2
0
forked from Ivasoft/DSView

v0.97 initial update, compile pass, run error

This commit is contained in:
DreamSourceLab
2017-05-20 03:20:06 +08:00
parent 7665adeb9c
commit 2add0e3cf3
132 changed files with 7811 additions and 4722 deletions

View File

@@ -62,6 +62,7 @@ endif()
list(APPEND PKGDEPS
"libsigrok4DSL >= 0.2.0"
"libusb-1.0 >= 1.0.16"
"libzip >= 0.10"
)
if(ENABLE_DECODE)
list(APPEND PKGDEPS "libsigrokdecode>=0.3.0")
@@ -93,6 +94,7 @@ find_package(Threads)
find_package(Boost 1.42 COMPONENTS filesystem system thread REQUIRED)
find_package(libusb-1.0 REQUIRED)
find_package(libzip REQUIRED)
find_package(FFTW REQUIRED)
#===============================================================================
@@ -104,7 +106,7 @@ set(DS_DESCRIPTION "A GUI for instruments of DreamSourceLab")
set(DS_VERSION_MAJOR 0)
set(DS_VERSION_MINOR 9)
set(DS_VERSION_MICRO 6)
set(DS_VERSION_MICRO 7)
set(DS_VERSION_STRING
${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO}
)
@@ -202,6 +204,7 @@ set(DSView_SOURCES
pv/dialogs/dsmessagebox.cpp
pv/dialogs/shadow.cpp
pv/dialogs/dsdialog.cpp
pv/dialogs/interval.cpp
)
set(DSView_HEADERS
@@ -257,6 +260,7 @@ set(DSView_HEADERS
pv/dialogs/dsmessagebox.h
pv/dialogs/shadow.h
pv/dialogs/dsdialog.h
pv/dialogs/interval.h
)
set(DSView_FORMS

View File

@@ -1,9 +0,0 @@
[Desktop Entry]
Version=0.96
Exec=/usr/local/bin/DSView
Name=DSView
Comment=GUI Program for DreamSourceLab USB-based Instruments
Icon=/usr/local/share/DSView/logo.png
Type=Application
Terminal=false
Categories=Development

View File

@@ -10,8 +10,6 @@
<file>stylesheet.qss</file>
<file>icons/down-arrow.png</file>
<file>icons/slider-handle.png</file>
<file>icons/add.png</file>
<file>icons/del.png</file>
<file>icons/trigger.png</file>
<file>icons/measure.png</file>
<file>icons/search-bar.png</file>
@@ -55,5 +53,16 @@
<file>icons/maximize.png</file>
<file>icons/minimize.png</file>
<file>icons/restore.png</file>
<file>icons/nav.png</file>
<file>icons/oneloop.png</file>
<file>icons/repeat.png</file>
<file>icons/moder.png</file>
<file>icons/moder_dis.png</file>
<file>icons/modes.png</file>
<file>icons/modes_dis.png</file>
<file>icons/add.png</file>
<file>icons/del.png</file>
<file>icons/add_dis.png</file>
<file>icons/del_dis.png</file>
</qresource>
</RCC>

View File

@@ -65,7 +65,7 @@ QWidget:item:selected
QCheckBox
{
spacing: 5px;
spacing: 0px;
outline: none;
color: #bbb;
margin-bottom: 2px;
@@ -635,7 +635,7 @@ QComboBox::drop-down
{
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
width: 10px;
border-left-width: 0px;
border-left-color: darkgray;

View File

@@ -34,15 +34,15 @@ bool DSApplication::notify(QObject *receiver_, QEvent *event_)
return QApplication::notify(receiver_, event_);
} catch ( std::exception& e ) {
QMessageBox msg(NULL);
msg.setText("Application Error");
msg.setText(tr("Application Error"));
msg.setInformativeText(e.what());
msg.setStandardButtons(QMessageBox::Ok);
msg.setIcon(QMessageBox::Warning);
msg.exec();
} catch (...) {
QMessageBox msg(NULL);
msg.setText("Application Error");
msg.setInformativeText("An unexpected error occurred");
msg.setText(tr("Application Error"));
msg.setInformativeText(tr("An unexpected error occurred"));
msg.setStandardButtons(QMessageBox::Ok);
msg.setIcon(QMessageBox::Warning);
msg.exec();

BIN
DSView/icons/add.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 399 B

BIN
DSView/icons/del.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 B

After

Width:  |  Height:  |  Size: 714 B

View File

@@ -34,7 +34,7 @@
#include <QDebug>
#include <QFile>
#include <QDir>
#include <QIcon>
#include <QTranslator>
#include "dsapplication.h"
#include "pv/devicemanager.h"
@@ -143,9 +143,10 @@ int main(int argc, char *argv[])
a.setStyleSheet(qss.readAll());
qss.close();
w.show();
w.readSettings();
// Run the application
ret = a.exec();
ret = a.exec();
} catch(std::exception e) {
qDebug() << e.what();

View File

@@ -91,14 +91,20 @@ void AnalogSnapshot::clear()
init();
}
void AnalogSnapshot::first_payload(const sr_datafeed_analog &analog, uint64_t total_sample_count, unsigned int channel_num)
void AnalogSnapshot::first_payload(const sr_datafeed_analog &analog, uint64_t total_sample_count, GSList *channels)
{
_total_sample_count = total_sample_count;
_channel_num = channel_num;
_unit_size = sizeof(uint16_t)*channel_num;
_channel_num = 0;
for (const GSList *l = channels; l; l = l->next) {
sr_channel *const probe = (sr_channel*)l->data;
assert(probe);
if (probe->type == SR_CHANNEL_ANALOG && probe->enabled) {
_channel_num ++;
}
}
bool isOk = true;
uint64_t size = _total_sample_count * _unit_size + sizeof(uint64_t);
uint64_t size = _total_sample_count * _channel_num * BytesPerSample + sizeof(uint64_t);
if (size != _capacity) {
free_data();
_data = malloc(size);
@@ -125,6 +131,13 @@ void AnalogSnapshot::first_payload(const sr_datafeed_analog &analog, uint64_t to
}
if (isOk) {
for (const GSList *l = channels; l; l = l->next) {
sr_channel *const probe = (sr_channel*)l->data;
assert(probe);
if (probe->type == SR_CHANNEL_ANALOG && probe->enabled) {
_ch_index.push_back(probe->index);
}
}
_capacity = size;
_memory_failed = false;
append_payload(analog);
@@ -132,7 +145,6 @@ void AnalogSnapshot::first_payload(const sr_datafeed_analog &analog, uint64_t to
} else {
free_data();
free_envelop();
_capacity = 0;
_memory_failed = true;
}
}
@@ -147,6 +159,27 @@ void AnalogSnapshot::append_payload(
append_payload_to_envelope_levels();
}
void AnalogSnapshot::append_data(void *data, uint64_t samples)
{
int unit_bytes = BytesPerSample * _channel_num;
if (_sample_count + samples < _total_sample_count)
_sample_count += samples;
else
_sample_count = _total_sample_count;
if (_ring_sample_count + samples > _total_sample_count) {
memcpy((uint8_t*)_data + _ring_sample_count * unit_bytes,
data, (_total_sample_count - _ring_sample_count) * unit_bytes);
_ring_sample_count = (samples + _ring_sample_count - _total_sample_count) % _total_sample_count;
memcpy((uint8_t*)_data,
data, _ring_sample_count * unit_bytes);
} else {
memcpy((uint8_t*)_data + _ring_sample_count * unit_bytes,
data, samples * unit_bytes);
_ring_sample_count += samples;
}
}
const uint16_t* AnalogSnapshot::get_samples(
int64_t start_sample, int64_t end_sample) const
{
@@ -303,5 +336,20 @@ void AnalogSnapshot::append_payload_to_envelope_levels()
}
}
int AnalogSnapshot::get_ch_order(int sig_index)
{
int order = 0;
for (auto& iter:_ch_index) {
if (iter == sig_index)
break;
order++;
}
if (order >= _ch_index.size())
return -1;
else
return order;
}
} // namespace data
} // namespace pv

View File

@@ -68,6 +68,8 @@ private:
static const float LogEnvelopeScaleFactor;
static const uint64_t EnvelopeDataUnit;
static const int BytesPerSample = 2;
public:
AnalogSnapshot();
@@ -76,7 +78,8 @@ public:
void clear();
void init();
void first_payload(const sr_datafeed_analog &analog, uint64_t total_sample_count, unsigned int channel_num);
void first_payload(const sr_datafeed_analog &analog,
uint64_t total_sample_count, GSList *channels);
void append_payload(const sr_datafeed_analog &analog);
@@ -86,11 +89,16 @@ public:
void get_envelope_section(EnvelopeSection &s,
uint64_t start, uint64_t end, float min_length, int probe_index) const;
int get_ch_order(int sig_index);
private:
void append_data(void *data, uint64_t samples);
void free_envelop();
void reallocate_envelope(Envelope &l);
void append_payload_to_envelope_levels();
private:
struct Envelope _envelope_levels[2*DS_MAX_ANALOG_PROBES_NUM][ScaleStepCount];

View File

@@ -24,8 +24,6 @@
#include "decoder.h"
#include <pv/view/logicsignal.h>
using boost::shared_ptr;
using std::set;
using std::map;
@@ -44,10 +42,6 @@ Decoder::Decoder(const srd_decoder *const dec) :
Decoder::~Decoder()
{
for (map<string, GVariant*>::const_iterator i = _options.begin();
i != _options.end(); i++)
g_variant_unref((*i).second);
for (map<string, GVariant*>::const_iterator i = _options_back.begin();
i != _options_back.end(); i++)
g_variant_unref((*i).second);
@@ -68,14 +62,13 @@ void Decoder::show(bool show)
_shown = show;
}
const map<const srd_channel*, shared_ptr<view::LogicSignal> >&
const map<const srd_channel*, int>&
Decoder::channels() const
{
return _probes;
}
void Decoder::set_probes(std::map<const srd_channel*,
boost::shared_ptr<view::LogicSignal> > probes)
void Decoder::set_probes(std::map<const srd_channel *, int> probes)
{
_probes_back = probes;
_setted = true;
@@ -89,6 +82,7 @@ const std::map<std::string, GVariant*>& Decoder::options() const
void Decoder::set_option(const char *id, GVariant *value)
{
assert(value);
g_variant_unref(_options_back[id]);
g_variant_ref(value);
_options_back[id] = value;
_setted = true;
@@ -139,24 +133,8 @@ bool Decoder::have_required_probes() const
return true;
}
set< shared_ptr<pv::data::Logic> > Decoder::get_data()
srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session) const
{
set< shared_ptr<pv::data::Logic> > data;
for(map<const srd_channel*, shared_ptr<view::LogicSignal> >::
const_iterator i = _probes.begin();
i != _probes.end(); i++)
{
shared_ptr<view::LogicSignal> signal((*i).second);
assert(signal);
data.insert(signal->logic_data());
}
return data;
}
srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session, int unit_size) const
{
(void)unit_size;
GHashTable *const opt_hash = g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
@@ -180,13 +158,11 @@ srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session, int unit_si
GHashTable *const probes = g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
for(map<const srd_channel*, shared_ptr<view::LogicSignal> >::
for(map<const srd_channel*, int>::
const_iterator i = _probes.begin();
i != _probes.end(); i++)
{
shared_ptr<view::LogicSignal> signal((*i).second);
GVariant *const gvar = g_variant_new_int32(
signal->probe()->index);
GVariant *const gvar = g_variant_new_int32((*i).second);
g_variant_ref_sink(gvar);
g_hash_table_insert(probes, (*i).first->id, gvar);
}
@@ -196,6 +172,11 @@ srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session, int unit_si
return decoder_inst;
}
int Decoder::get_channel_type(const srd_channel *ch)
{
return ch->type;
}
} // decode
} // data
} // pv

View File

@@ -35,15 +35,7 @@ struct srd_channel;
struct srd_session;
namespace pv {
namespace view {
class LogicSignal;
}
namespace data {
class Logic;
namespace decode {
class Decoder
@@ -58,10 +50,8 @@ public:
bool shown() const;
void show(bool show = true);
const std::map<const srd_channel*,
boost::shared_ptr<view::LogicSignal> >& channels() const;
void set_probes(std::map<const srd_channel*,
boost::shared_ptr<view::LogicSignal> > probes);
const std::map<const srd_channel*, int>& channels() const;
void set_probes(std::map<const srd_channel*, int> probes);
const std::map<std::string, GVariant*>& options() const;
@@ -69,10 +59,7 @@ public:
bool have_required_probes() const;
srd_decoder_inst* create_decoder_inst(
srd_session *session, int unit_size) const;
std::set< boost::shared_ptr<pv::data::Logic> > get_data();
srd_decoder_inst* create_decoder_inst(srd_session *session) const;
void set_decode_region(uint64_t start, uint64_t end);
uint64_t decode_start() const;
@@ -80,17 +67,17 @@ public:
bool commit();
int get_channel_type(const srd_channel* ch);
private:
const srd_decoder *const _decoder;
bool _shown;
std::map<const srd_channel*, boost::shared_ptr<pv::view::LogicSignal> >
_probes;
std::map<const srd_channel*, int> _probes;
std::map<std::string, GVariant*> _options;
std::map<const srd_channel*, boost::shared_ptr<pv::view::LogicSignal> >
_probes_back;
std::map<const srd_channel*, int> _probes_back;
std::map<std::string, GVariant*> _options_back;
uint64_t _decode_start, _decode_end;

View File

@@ -38,6 +38,11 @@ RowData::RowData() :
}
RowData::~RowData()
{
clear();
}
void RowData::clear()
{
_annotations.clear();
}
@@ -56,7 +61,10 @@ uint64_t RowData::get_max_annotation() const
uint64_t RowData::get_min_annotation() const
{
return _min_annotation;
if (_min_annotation == UINT64_MAX)
return 10;
else
return _min_annotation;
}
void RowData::get_annotation_subset(
@@ -70,6 +78,18 @@ void RowData::get_annotation_subset(
dest.push_back(*i);
}
uint64_t RowData::get_annotation_index(uint64_t start_sample) const
{
uint64_t index = 0;
for (vector<Annotation>::const_iterator i = _annotations.begin();
i != _annotations.end(); i++) {
if ((*i).start_sample() > start_sample)
break;
index++;
}
return index;
}
bool RowData::push_annotation(const Annotation &a)
{
try {

View File

@@ -47,6 +47,8 @@ public:
std::vector<pv::data::decode::Annotation> &dest,
uint64_t start_sample, uint64_t end_sample) const;
uint64_t get_annotation_index(uint64_t start_sample) const;
bool push_annotation(const Annotation &a);
uint64_t get_annotation_size() const;
@@ -54,6 +56,8 @@ public:
bool get_annotation(pv::data::decode::Annotation &ann,
uint64_t index) const;
void clear();
private:
uint64_t _max_annotation;
uint64_t _min_annotation;

View File

@@ -35,19 +35,8 @@
#include <pv/sigsession.h>
#include <pv/view/logicsignal.h>
using boost::lock_guard;
using boost::mutex;
using boost::optional;
using boost::shared_ptr;
using boost::unique_lock;
using std::deque;
using std::make_pair;
using std::max;
using std::min;
using std::list;
using std::map;
using std::pair;
using std::vector;
using namespace boost;
using namespace std;
using namespace pv::data::decode;
@@ -70,7 +59,8 @@ DecoderStack::DecoderStack(pv::SigSession &session,
_samples_decoded(0),
_decode_state(Stopped),
_options_changed(false),
_no_memory(false)
_no_memory(false),
_mark_index(-1)
{
connect(&_session, SIGNAL(frame_began()),
this, SLOT(on_new_frame()));
@@ -79,7 +69,7 @@ DecoderStack::DecoderStack(pv::SigSession &session,
connect(&_session, SIGNAL(frame_ended()),
this, SLOT(on_frame_ended()));
_stack.push_back(shared_ptr<decode::Decoder>(
_stack.push_back(boost::shared_ptr<decode::Decoder>(
new decode::Decoder(dec)));
build_row();
@@ -116,7 +106,7 @@ void DecoderStack::push(boost::shared_ptr<decode::Decoder> decoder)
void DecoderStack::remove(boost::shared_ptr<Decoder> &decoder)
{
// Find the decoder in the stack
list< shared_ptr<Decoder> >::iterator iter = _stack.begin();
list< boost::shared_ptr<Decoder> >::iterator iter = _stack.begin();
for(unsigned int i = 0; i < _stack.size(); i++, iter++)
if ((*iter) == decoder)
break;
@@ -133,7 +123,7 @@ void DecoderStack::build_row()
{
_rows.clear();
// Add classes
BOOST_FOREACH (const shared_ptr<decode::Decoder> &dec, _stack)
BOOST_FOREACH (const boost::shared_ptr<decode::Decoder> &dec, _stack)
{
assert(dec);
const srd_decoder *const decc = dec->decoder();
@@ -206,6 +196,21 @@ void DecoderStack::get_annotation_subset(
start_sample, end_sample);
}
uint64_t DecoderStack::get_annotation_index(
const Row &row, uint64_t start_sample) const
{
//lock_guard<mutex> lock(_output_mutex);
uint64_t index = 0;
std::map<const Row, decode::RowData>::const_iterator iter =
_rows.find(row);
if (iter != _rows.end())
index = (*iter).second.get_annotation_index(start_sample);
return index;
}
uint64_t DecoderStack::get_max_annotation(const Row &row)
{
//lock_guard<mutex> lock(_output_mutex);
@@ -353,84 +358,77 @@ QString DecoderStack::error_message()
void DecoderStack::clear()
{
//lock_guard<boost::recursive_mutex> decode_lock(_output_mutex);
_sample_count = 0;
_frame_complete = false;
_samples_decoded = 0;
new_decode_data();
_error_message = QString();
for (map<const Row, RowData>::iterator i = _rows.begin();
i != _rows.end(); i++)
_rows[(*i).first] = decode::RowData();
// _rows.clear();
// _rows_gshow.clear();
// _rows_lshow.clear();
// _class_rows.clear();
_no_memory = false;
init();
}
void DecoderStack::init()
{
clear();
_sample_count = 0;
_frame_complete = false;
_samples_decoded = 0;
_error_message = QString();
_no_memory = false;
for (map<const Row, RowData>::iterator i = _rows.begin();
i != _rows.end(); i++) {
//_rows[(*i).first] = decode::RowData();
(*i).second.clear();
}
set_mark_index(-1);
}
void DecoderStack::stop_decode()
{
//_snapshot.reset();
if(_decode_state == Stopped) {
clear();
return;
if(_decode_state != Stopped) {
if (_decode_thread.get()) {
_decode_thread->interrupt();
_decode_thread->join();
_decode_state = Stopped;
}
_decode_thread.reset();
}
if (_decode_thread.get()) {
_decode_thread->interrupt();
_decode_thread->join();
_decode_state = Stopped;
}
_decode_thread.reset();
clear();
}
void DecoderStack::begin_decode()
{
shared_ptr<pv::view::LogicSignal> logic_signal;
shared_ptr<pv::data::Logic> data;
boost::shared_ptr<pv::view::LogicSignal> logic_signal;
boost::shared_ptr<pv::data::Logic> data;
if (!_options_changed)
return;
_options_changed = false;
// if (_decode_thread.joinable()) {
// _decode_thread.interrupt();
// _decode_thread.join();
// }
stop_decode();
init();
// Check that all decoders have the required channels
BOOST_FOREACH(const shared_ptr<decode::Decoder> &dec, _stack)
BOOST_FOREACH(const boost::shared_ptr<decode::Decoder> &dec, _stack)
if (!dec->have_required_probes()) {
_error_message = tr("One or more required channels "
"have not been specified");
return;
}
// // Build rows
// build_row();
// We get the logic data of the first channel in the list.
// This works because we are currently assuming all
// LogicSignals have the same data/snapshot
BOOST_FOREACH (const shared_ptr<decode::Decoder> &dec, _stack)
if (dec && !dec->channels().empty() &&
((logic_signal = (*dec->channels().begin()).second)) &&
((data = logic_signal->logic_data())))
break;
BOOST_FOREACH (const boost::shared_ptr<decode::Decoder> &dec, _stack) {
if (dec && !dec->channels().empty()) {
BOOST_FOREACH(boost::shared_ptr<view::Signal> sig, _session.get_signals()) {
if((sig->get_index() == (*dec->channels().begin()).second) &&
(logic_signal = dynamic_pointer_cast<view::LogicSignal>(sig)) &&
(data = logic_signal->logic_data()))
break;
}
if (data)
break;
}
}
if (!data)
return;
// Check we have a snapshot of data
const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots =
const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
data->get_snapshots();
if (snapshots.empty())
return;
@@ -438,8 +436,7 @@ void DecoderStack::begin_decode()
if (_snapshot->empty())
return;
// Get the samplerate and start time
_start_time = data->get_start_time();
// Get the samplerate
_samplerate = data->samplerate();
if (_samplerate == 0.0)
return;
@@ -474,13 +471,11 @@ boost::optional<uint64_t> DecoderStack::wait_for_data() const
void DecoderStack::decode_data(
const uint64_t decode_start, const uint64_t decode_end,
const unsigned int unit_size, srd_session *const session)
srd_session *const session)
{
uint8_t *chunk = NULL;
//uint8_t *chunk = NULL;
uint64_t last_cnt = 0;
uint64_t notify_cnt = (decode_end - decode_start + 1)/100;
const uint64_t chunk_sample_count =
DecodeChunkLength / _snapshot->unit_size();
srd_decoder_inst *logic_di = NULL;
// find the first level decoder instant
for (GSList *d = session->di_list; d; d = d->next) {
@@ -501,41 +496,63 @@ void DecoderStack::decode_data(
i < decode_end && !_no_memory)
{
//lock_guard<mutex> decode_lock(_global_decode_mutex);
std::vector<const uint8_t *> chunk;
std::vector<uint8_t> chunk_const;
uint64_t chunk_end = decode_end;
for (int j =0 ; j < logic_di->dec_num_channels; j++) {
int sig_index = logic_di->dec_channelmap[j];
if (sig_index == -1) {
chunk.push_back(NULL);
} else {
if (_snapshot->has_data(sig_index)) {
chunk.push_back(_snapshot->get_samples(i, chunk_end, sig_index));
chunk_const.push_back(_snapshot->get_sample(i, sig_index));
} else {
_error_message = tr("At least one of selected channels are not enabled.");
return;
}
}
}
if (chunk_end - i > MaxChunkSize)
chunk_end = i + MaxChunkSize;
const uint64_t chunk_end = min(
i + chunk_sample_count, decode_end);
chunk = _snapshot->get_samples(i, chunk_end);
if (srd_session_send(session, chunk_type, i, chunk_end, chunk,
(chunk_end - i) * unit_size, unit_size, &error) != SRD_OK) {
if (srd_session_send(session, chunk_type, i, chunk_end,
chunk.data(), chunk_const.data(), &error) != SRD_OK) {
_error_message = QString::fromLocal8Bit(error);
break;
}
if (logic_di && logic_di->logic_mask != 0) {
if (logic_di && logic_di->logic_mask != 0 && logic_di->cur_pos < decode_end) {
uint64_t cur_pos = logic_di->cur_pos;
assert(cur_pos < _snapshot->get_sample_count());
uint64_t sample = _snapshot->get_sample(cur_pos) & logic_di->logic_mask;
uint64_t sample;
if (logic_di->edge_index == -1) {
std::vector<uint64_t> pos_vector;
cur_pos++;
for (int j =0 ; j < logic_di->dec_num_channels; j++) {
int index = logic_di->dec_channelmap[j];
if (index != -1 && (logic_di->logic_mask & (1 << index))) {
bool last_sample = (sample & (1 << index)) ? 1 : 0;
if (index != -1 && (logic_di->logic_mask & (1 << j))) {
bool last_sample = _snapshot->get_sample(cur_pos - 1, index);
pos_vector.push_back(cur_pos);
_snapshot->get_nxt_edge(pos_vector.back(), last_sample, decode_end, 1, index);
}
}
cur_pos = *std::min_element(pos_vector.begin(), pos_vector.end());
} else {
bool last_sample = (sample & (1 << logic_di->edge_index)) ? 1 : 0;
bool last_sample = _snapshot->get_sample(cur_pos, logic_di->edge_index);
do {
sample = 0;
cur_pos++;
if (!_snapshot->get_nxt_edge(cur_pos, last_sample, decode_end, 1, logic_di->edge_index))
break;
sample = _snapshot->get_sample(cur_pos) & logic_di->logic_mask;
last_sample = (sample & (1 << logic_di->edge_index)) ? 1 : 0;
for (int j =0 ; j < logic_di->dec_num_channels; j++) {
if (logic_di->logic_mask & (1 << j)) {
int index = logic_di->dec_channelmap[j];
bool index_sample = _snapshot->get_sample(cur_pos, index);
sample += index_sample << j;
if (index == logic_di->edge_index)
last_sample = index_sample;
}
}
} while(sample != logic_di->exp_logic);
}
@@ -544,7 +561,7 @@ void DecoderStack::decode_data(
i = decode_end;
chunk_type = 0;
} else {
i += chunk_sample_count;
i = chunk_end + 1;
chunk_type = 1;
}
@@ -582,18 +599,16 @@ void DecoderStack::decode_proc()
_decode_state = Running;
// Create the decoders
const unsigned int unit_size = _snapshot->unit_size();
// Get the intial sample count
{
//unique_lock<mutex> input_lock(_input_mutex);
sample_count = _sample_count = _snapshot->get_sample_count();
}
BOOST_FOREACH(const shared_ptr<decode::Decoder> &dec, _stack)
// Create the decoders
BOOST_FOREACH(const boost::shared_ptr<decode::Decoder> &dec, _stack)
{
srd_decoder_inst *const di = dec->create_decoder_inst(session, unit_size);
srd_decoder_inst *const di = dec->create_decoder_inst(session);
if (!di)
{
@@ -619,7 +634,7 @@ void DecoderStack::decode_proc()
char *error = NULL;
if (srd_session_start(session, &error) == SRD_OK)
decode_data(decode_start, decode_end, unit_size, session);
decode_data(decode_start, decode_end, session);
else
_error_message = QString::fromLocal8Bit(error);
@@ -747,5 +762,15 @@ bool DecoderStack::out_of_memory() const
return _no_memory;
}
void DecoderStack::set_mark_index(int64_t index)
{
_mark_index = index;
}
int64_t DecoderStack::get_mark_index() const
{
return _mark_index;
}
} // namespace data
} // namespace pv

View File

@@ -68,6 +68,7 @@ private:
static const double DecodeThreshold;
static const int64_t DecodeChunkLength;
static const unsigned int DecodeNotifyPeriod;
static const uint64_t MaxChunkSize = 1024 * 16;
public:
enum decode_state {
@@ -96,6 +97,9 @@ public:
const decode::Row &row, uint64_t start_sample,
uint64_t end_sample) const;
uint64_t get_annotation_index(
const decode::Row &row, uint64_t start_sample) const;
uint64_t get_max_annotation(const decode::Row &row);
uint64_t get_min_annotation(const decode::Row &row); // except instant(end=start) annotation
@@ -137,14 +141,13 @@ public:
bool out_of_memory() const;
void set_mark_index(int64_t index);
int64_t get_mark_index() const;
private:
boost::optional<uint64_t> wait_for_data() const;
// void decode_data(const uint64_t sample_count,
// const unsigned int unit_size, srd_session *const session);
void decode_data(const uint64_t decode_start, const uint64_t decode_end,
const unsigned int unit_size, srd_session *const session);
void decode_data(const uint64_t decode_start, const uint64_t decode_end, srd_session *const session);
void decode_proc();
@@ -199,6 +202,8 @@ private:
bool _options_changed;
bool _no_memory;
int64_t _mark_index;
friend class DecoderStackTest::TwoDecoderStack;
};

View File

@@ -80,6 +80,7 @@ void DsoSnapshot::init()
_memory_failed = false;
_last_ended = true;
_envelope_done = false;
_ch_enable.clear();
for (unsigned int i = 0; i < _channel_num; i++) {
for (unsigned int level = 0; level < ScaleStepCount; level++) {
_envelope_levels[i][level].length = 0;
@@ -96,15 +97,29 @@ void DsoSnapshot::clear()
init();
}
void DsoSnapshot::first_payload(const sr_datafeed_dso &dso, uint64_t total_sample_count, unsigned int channel_num, bool instant)
void DsoSnapshot::first_payload(const sr_datafeed_dso &dso, uint64_t total_sample_count,
std::map<int, bool> ch_enable, bool instant)
{
bool re_alloc = false;
unsigned int channel_num = 0;
for (auto& iter:ch_enable) {
if (iter.second)
channel_num++;
}
assert(channel_num != 0);
if (total_sample_count != _total_sample_count ||
channel_num != _channel_num)
re_alloc = true;
_total_sample_count = total_sample_count;
_channel_num = channel_num;
_instant = instant;
_ch_enable = ch_enable;
bool isOk = true;
uint64_t size = _total_sample_count * _unit_size + sizeof(uint64_t);
if (size != _capacity) {
uint64_t size = _total_sample_count * _channel_num + sizeof(uint64_t);
if (re_alloc || size != _capacity) {
free_data();
_data = malloc(size);
if (_data) {
@@ -137,7 +152,6 @@ void DsoSnapshot::first_payload(const sr_datafeed_dso &dso, uint64_t total_sampl
} else {
free_data();
free_envelop();
_capacity = 0;
_memory_failed = true;
}
}
@@ -147,7 +161,7 @@ void DsoSnapshot::append_payload(const sr_datafeed_dso &dso)
boost::lock_guard<boost::recursive_mutex> lock(_mutex);
if (_channel_num > 0 && dso.num_samples != 0) {
refill_data(dso.data, dso.num_samples, _instant);
append_data(dso.data, dso.num_samples, _instant);
// Generate the first mip-map from the data
if (_envelope_en)
@@ -155,6 +169,18 @@ void DsoSnapshot::append_payload(const sr_datafeed_dso &dso)
}
}
void DsoSnapshot::append_data(void *data, uint64_t samples, bool instant)
{
if (instant) {
memcpy((uint8_t*)_data + _sample_count * _channel_num, data, samples*_channel_num);
_sample_count = (_sample_count + samples) % (_total_sample_count + 1);
} else {
memcpy((uint8_t*)_data, data, samples*_channel_num);
_sample_count = samples;
}
}
void DsoSnapshot::enable_envelope(bool enable)
{
boost::lock_guard<boost::recursive_mutex> lock(_mutex);
@@ -382,5 +408,13 @@ double DsoSnapshot::cal_vmean(int index) const
return vmean;
}
bool DsoSnapshot::has_data(int index)
{
if (_ch_enable.find(index) != _ch_enable.end())
return _ch_enable[index];
else
return false;
}
} // namespace data
} // namespace pv

View File

@@ -77,7 +77,7 @@ public:
void clear();
void init();
void first_payload(const sr_datafeed_dso &dso, uint64_t total_sample_count, unsigned int channel_num, bool instant);
void first_payload(const sr_datafeed_dso &dso, uint64_t total_sample_count, std::map<int, bool> ch_enable, bool instant);
void append_payload(const sr_datafeed_dso &dso);
@@ -92,7 +92,10 @@ public:
double cal_vrms(double zero_off, int index) const;
double cal_vmean(int index) const;
bool has_data(int index);
private:
void append_data(void *data, uint64_t samples, bool instant);
void free_envelop();
void reallocate_envelope(Envelope &l);
void append_payload_to_envelope_levels(bool header);
@@ -102,6 +105,7 @@ private:
bool _envelope_en;
bool _envelope_done;
bool _instant;
std::map<int, bool> _ch_enable;
friend class DsoSnapshotTest::Basic;
};

File diff suppressed because it is too large Load Diff

View File

@@ -26,6 +26,8 @@
#include "snapshot.h"
#include <QString>
#include <utility>
#include <vector>
@@ -43,19 +45,30 @@ namespace data {
class LogicSnapshot : public Snapshot
{
private:
struct MipMapLevel
{
uint64_t length;
uint64_t data_length;
void *data;
};
static const int ScaleLevel = 4;
static const int ScalePower = 6;
static const uint64_t Scale = 1 << ScalePower;
static const int ScaleSize = Scale / 8;
static const int RootScalePower = ScalePower;
static const uint64_t RootScale = 1 << RootScalePower;
static const uint64_t LeafBlockSpace = (Scale + Scale*Scale +
Scale*Scale*Scale + Scale*Scale*Scale*Scale) / 8;
static const uint64_t LeafBlockSamples = 1 << ScaleLevel*ScalePower;
static const uint64_t LeafBlockPower = ScaleLevel*ScalePower;
static const uint64_t RootNodeSamples = LeafBlockSamples*RootScale;
static const uint64_t RootMask = ~(~0ULL << RootScalePower) << ScaleLevel*ScalePower;
static const uint64_t LeafMask = ~(~0ULL << ScaleLevel*ScalePower);
static const uint64_t LevelMask[ScaleLevel];
static const uint64_t LevelOffset[ScaleLevel];
private:
static const unsigned int ScaleStepCount = 10;
static const int MipMapScalePower;
static const int MipMapScaleFactor;
static const float LogMipMapScaleFactor;
static const uint64_t MipMapDataUnit;
struct RootNode
{
uint64_t tog;
uint64_t value;
void *lbp[Scale];
};
public:
typedef std::pair<uint64_t, bool> EdgePair;
@@ -64,50 +77,116 @@ public:
LogicSnapshot();
virtual ~LogicSnapshot();
void free_data();
void clear();
void init();
void first_payload(const sr_datafeed_logic &logic, uint64_t total_sample_count, unsigned int channel_num);
void first_payload(const sr_datafeed_logic &logic, uint64_t total_sample_count, GSList *channels);
void append_payload(const sr_datafeed_logic &logic);
uint8_t * get_samples(int64_t start_sample, int64_t end_sample) const;
const uint8_t * get_samples(uint64_t start_sample, uint64_t& end_sample, int sig_index);
private:
void free_mipmap();
void reallocate_mipmap_level(MipMapLevel &m);
void append_payload_to_mipmap();
bool get_sample(uint64_t index, int sig_index);
public:
/**
* Parses a logic data snapshot to generate a list of transitions
* in a time interval to a given level of detail.
* @param[out] edges The vector to place the edges into.
* @param[in] start The start sample index.
* @param[in] end The end sample index.
* @param[in] min_length The minimum number of samples that
* can be resolved at this level of detail.
* @param[in] sig_index The index of the signal.
**/
void get_subsampled_edges(std::vector<EdgePair> &edges,
uint64_t start, uint64_t end,
float min_length, int sig_index);
void capture_ended();
bool get_display_edges(std::vector<std::pair<bool, bool>> &edges,
std::vector<std::pair<uint16_t, bool>> &togs,
uint64_t start, uint64_t end, uint16_t width,
uint16_t max_togs, double pixels_offset,
double min_length, uint16_t sig_index);
bool get_nxt_edge(uint64_t &index, bool last_sample, uint64_t end,
float min_length, int sig_index);
double min_length, int sig_index);
bool get_pre_edge(uint64_t &index, bool last_sample,
float min_length, int sig_index);
double min_length, int sig_index);
bool has_data(int sig_index);
int get_block_num();
uint64_t get_block_size(int block_index);
uint8_t *get_block_buf(int block_index, int sig_index, bool &sample);
bool pattern_search(int64_t start, int64_t end, bool nxt, int64_t& index,
std::map<uint16_t, QString> pattern);
private:
uint64_t get_subsample(int level, uint64_t offset) const;
int get_ch_order(int sig_index);
void calc_mipmap(unsigned int order, uint8_t index0, uint8_t index1, uint64_t samples);
static uint64_t pow2_ceil(uint64_t x, unsigned int power);
void append_cross_payload(const sr_datafeed_logic &logic);
void append_split_payload(const sr_datafeed_logic &logic);
bool block_nxt_edge(uint64_t *lbp, uint64_t &index, uint64_t block_end, bool last_sample,
unsigned int min_level);
bool block_pre_edge(uint64_t *lbp, uint64_t &index, bool last_sample,
unsigned int min_level, int sig_index);
inline uint64_t bsf_folded (uint64_t bb)
{
static const int lsb_64_table[64] = {
63, 30, 3, 32, 59, 14, 11, 33,
60, 24, 50, 9, 55, 19, 21, 34,
61, 29, 2, 53, 51, 23, 41, 18,
56, 28, 1, 43, 46, 27, 0, 35,
62, 31, 58, 4, 5, 49, 54, 6,
15, 52, 12, 40, 7, 42, 45, 16,
25, 57, 48, 13, 10, 39, 8, 44,
20, 47, 38, 22, 17, 37, 36, 26
};
unsigned int folded;
bb ^= bb - 1;
folded = (int) bb ^ (bb >> 32);
return lsb_64_table[folded * 0x78291ACF >> 26];
}
inline int bsr32(uint32_t bb)
{
static const char msb_256_table[256] = {
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4,4, 4, 4, 4,4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
};
int result = 0;
if (bb > 0xFFFF) {
bb >>= 16;
result += 16;
}
if (bb > 0xFF) {
bb >>= 8;
result += 8;
}
return (result + msb_256_table[bb]);
}
inline uint64_t bsr64(uint64_t bb)
{
const uint32_t hb = bb >> 32;
return hb ? 32 + bsr32((uint32_t)hb) : bsr32((uint32_t)bb);
}
private:
struct MipMapLevel _mip_map[ScaleStepCount];
uint64_t _last_append_sample;
std::vector<std::vector<struct RootNode>> _ch_data;
uint64_t _block_num;
uint8_t _byte_fraction;
uint16_t _ch_fraction;
void *_src_ptr;
void *_dest_ptr;
std::vector<uint64_t> _sample_cnt;
std::vector<uint64_t> _block_cnt;
std::vector<uint64_t> _ring_sample_cnt;
std::vector<uint64_t> _last_sample;
friend class LogicSnapshotTest::Pow2;
friend class LogicSnapshotTest::Basic;

View File

@@ -193,14 +193,13 @@ void MathStack::calc_fft()
if (_snapshot->get_sample_count() < _sample_num*_sample_interval)
return;
// Get the samplerate and start time
_start_time = data->get_start_time();
// Get the samplerate
_samplerate = data->samplerate();
if (_samplerate == 0.0)
_samplerate = 1.0;
// prepare _xn data
const double offset = dsoSig->get_zero_value();
const double offset = dsoSig->get_hw_offset();
const double vscale = dsoSig->get_vDialValue() * dsoSig->get_factor() * DS_CONF_DSO_VDIVS / (1000*255.0);
const uint16_t step = _snapshot->get_channel_num() * _sample_interval;
const uint8_t *const samples = _snapshot->get_samples(0, _sample_num*_sample_interval-1, _index);

View File

@@ -28,8 +28,7 @@ namespace pv {
namespace data {
SignalData::SignalData() :
_samplerate(0),
_start_time(0)
_samplerate(0)
{
}
@@ -44,10 +43,5 @@ void SignalData::set_samplerate(double samplerate)
_samplerate = samplerate;
}
double SignalData::get_start_time() const
{
return _start_time;
}
} // namespace data
} // namespace pv

View File

@@ -42,11 +42,8 @@ public:
virtual void init() = 0;
double get_start_time() const;
protected:
double _samplerate;
double _start_time;
};
} // namespace data

View File

@@ -59,7 +59,9 @@ void Snapshot::free_data()
free(_data);
_data = NULL;
_capacity = 0;
_sample_count = 0;
}
_ch_index.clear();
}
bool Snapshot::memory_failed() const
@@ -69,7 +71,7 @@ bool Snapshot::memory_failed() const
bool Snapshot::empty() const
{
if (get_sample_count() == 0 || _memory_failed || !_data)
if (get_sample_count() == 0)
return true;
else
return false;
@@ -106,46 +108,9 @@ unsigned int Snapshot::get_channel_num() const
return _channel_num;
}
uint64_t Snapshot::get_sample(uint64_t index) const
void Snapshot::capture_ended()
{
assert(_data);
assert(index < get_sample_count());
return *(uint64_t*)((uint8_t*)_data + index * _unit_size);
}
void Snapshot::append_data(void *data, uint64_t samples)
{
// _data = realloc(_data, (_sample_count + samples) * _unit_size +
// sizeof(uint64_t));
if (_sample_count + samples < _total_sample_count)
_sample_count += samples;
else
_sample_count = _total_sample_count;
if (_ring_sample_count + samples > _total_sample_count) {
memcpy((uint8_t*)_data + _ring_sample_count * _unit_size,
data, (_total_sample_count - _ring_sample_count) * _unit_size);
_ring_sample_count = (samples + _ring_sample_count - _total_sample_count) % _total_sample_count;
memcpy((uint8_t*)_data,
data, _ring_sample_count * _unit_size);
} else {
memcpy((uint8_t*)_data + _ring_sample_count * _unit_size,
data, samples * _unit_size);
_ring_sample_count += samples;
}
}
void Snapshot::refill_data(void *data, uint64_t samples, bool instant)
{
if (instant) {
memcpy((uint8_t*)_data + _sample_count * _channel_num, data, samples*_channel_num);
_sample_count = (_sample_count + samples) % (_total_sample_count + 1);
} else {
memcpy((uint8_t*)_data, data, samples*_channel_num);
_sample_count = samples;
}
set_last_ended(true);
}
} // namespace data

View File

@@ -55,17 +55,18 @@ public:
unsigned int get_channel_num() const;
uint64_t get_sample(uint64_t index) const;
virtual void capture_ended();
protected:
void append_data(void *data, uint64_t samples);
void refill_data(void *data, uint64_t samples, bool instant);
void free_data();
virtual void free_data();
protected:
mutable boost::recursive_mutex _mutex;
//std::vector<uint8_t> _data;
void* _data;
std::vector<uint16_t> _ch_index;
uint64_t _capacity;
unsigned int _channel_num;
uint64_t _sample_count;

View File

@@ -32,7 +32,7 @@ namespace pv {
namespace device {
Device::Device(sr_dev_inst *sdi) :
_sdi(sdi)
_sdi(sdi)
{
assert(_sdi);
}
@@ -50,6 +50,7 @@ void Device::use(SigSession *owner) throw(QString)
assert(_sdi);
sr_dev_open(_sdi);
_usable = (_sdi->status == SR_ST_ACTIVE);
if (sr_session_dev_add(_sdi) != SR_OK)
throw QString(tr("Failed to use device."));
}

View File

@@ -34,7 +34,7 @@ public:
sr_dev_inst* dev_inst() const;
void use(SigSession *owner) throw(QString);
void use(SigSession *owner) throw(QString);
void release();

View File

@@ -33,7 +33,8 @@ namespace pv {
namespace device {
DevInst::DevInst() :
_owner(NULL)
_owner(NULL),
_usable(true)
{
_id = malloc(1);
}
@@ -206,5 +207,10 @@ void DevInst::run()
sr_session_run();
}
bool DevInst::is_usable() const
{
return _usable;
}
} // device
} // pv

View File

@@ -118,6 +118,8 @@ public:
virtual bool is_trigger_enabled() const;
bool is_usable() const;
public:
virtual void start();
@@ -132,6 +134,7 @@ signals:
protected:
SigSession *_owner;
void *_id;
bool _usable;
};
} // device

View File

@@ -25,6 +25,8 @@
#include <QFileInfo>
#include <zip.h>
#include <boost/filesystem.hpp>
#include <libsigrok4DSL/libsigrok.h>
@@ -63,7 +65,35 @@ File* File::create(QString name)
}
}
return new InputFile(name);
return new InputFile(name);
}
QJsonArray File::get_decoders()
{
struct zip *archive;
struct zip_file *zf;
struct zip_stat zs;
int ret;
char *dec_file;
QJsonArray dec_array;
QJsonParseError error;
if (archive = zip_open(_path.toLocal8Bit().data(), 0, &ret)) {
/* read "decoders" */
if (zip_stat(archive, "decoders", 0, &zs) != -1) {
if (dec_file = (char *)g_try_malloc(zs.size)) {
zf = zip_fopen_index(archive, zs.index, 0);
zip_fread(zf, dec_file, zs.size);
zip_fclose(zf);
//QString sessionData = QString::fromUtf8(dec_file);
QJsonDocument sessionDoc = QJsonDocument::fromJson(QByteArray::fromRawData(dec_file, zs.size), &error);
dec_array = sessionDoc.array();
}
}
}
return dec_array;
}
} // device

View File

@@ -24,6 +24,9 @@
#include <string>
#include <QJsonArray>
#include <QJsonDocument>
#include "devinst.h"
namespace pv {
@@ -37,6 +40,8 @@ protected:
public:
static File* create(QString name);
QJsonArray get_decoders();
public:
QString format_device_title() const;

View File

@@ -50,13 +50,18 @@ void InputFile::use(SigSession *owner) throw(QString)
{
assert(!_input);
_input = load_input_file_format(_path, NULL);
File::use(owner);
// only *.dsl file is valid
// don't allow other types of file input
throw tr("Not a valid DSView data file.");
return;
sr_session_new();
// _input = load_input_file_format(_path, NULL);
// File::use(owner);
if (sr_session_dev_add(_input->sdi) != SR_OK)
throw tr("Failed to add session device.");
// sr_session_new();
// if (sr_session_dev_add(_input->sdi) != SR_OK)
// throw tr("Failed to add session device.");
}
void InputFile::release()
@@ -78,7 +83,7 @@ sr_input_format* InputFile::determine_input_file_format(const QString filename)
/* If there are no input formats, return NULL right away. */
sr_input_format *const *const inputs = sr_input_list();
if (!inputs) {
g_critical("No supported input formats available.");
g_critical("No supported input formats available.");
return NULL;
}
@@ -90,7 +95,7 @@ sr_input_format* InputFile::determine_input_file_format(const QString filename)
/* Return NULL if no input module wanted to touch this. */
if (!inputs[i]) {
g_critical("Error: no matching input module found.");
g_critical("Error: no matching input module found.");
return NULL;
}

View File

@@ -21,7 +21,7 @@
#include "sessionfile.h"
#include <libsigrok4DSL//libsigrok.h>
#include <libsigrok4DSL/libsigrok.h>
namespace pv {
namespace device {

View File

@@ -45,6 +45,10 @@ const QString Calibration::VOFF = QT_TR_NOOP(" VOFF");
Calibration::Calibration(QWidget *parent) :
DSDialog(parent)
{
#ifdef Q_OS_OSX
Qt::WindowFlags flags = windowFlags();
this->setWindowFlags(flags | Qt::Tool);
#endif
this->setFixedSize(400, 250);
this->setWindowOpacity(0.7);
this->setModal(false);
@@ -125,7 +129,7 @@ void Calibration::set_device(boost::shared_ptr<device::DevInst> dev_inst)
gain_slider->setRange(-vgain_range/2, vgain_range/2);
gain_slider->setValue(vgain - vgain_default);
gain_slider->setObjectName(VGAIN+probe->index);
QString gain_string = "Channel" + QString::number(probe->index) + VGAIN;
QString gain_string = tr("Channel") + QString::number(probe->index) + VGAIN;
QLabel *gain_label = new QLabel(gain_string, this);
_flayout->addRow(gain_label, gain_slider);
_slider_list.push_back(gain_slider);
@@ -147,7 +151,7 @@ void Calibration::set_device(boost::shared_ptr<device::DevInst> dev_inst)
off_slider->setRange(0, voff_range);
off_slider->setValue(voff);
off_slider->setObjectName(VOFF+probe->index);
QString off_string = "Channel" + QString::number(probe->index) + VOFF;
QString off_string = tr("Channel") + QString::number(probe->index) + VOFF;
QLabel *off_label = new QLabel(off_string, this);
_flayout->addRow(off_label, off_slider);
_slider_list.push_back(off_slider);
@@ -213,7 +217,8 @@ void Calibration::on_save()
QProgressDialog dlg(tr("Save Calibration Result... It can take a while."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;
@@ -239,7 +244,8 @@ void Calibration::on_reset()
QProgressDialog dlg(tr("Reset Calibration Result... It can take a while."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;

View File

@@ -54,7 +54,7 @@ DeviceOptions::DeviceOptions(QWidget *parent, boost::shared_ptr<pv::device::DevI
_probes_box->setLayout(&_probes_box_layout);
_layout.addWidget(_probes_box);
} else if (_dev_inst->name().contains("DSCope")){
_config_button = new QPushButton(tr("Zero Adjustment"), this);
_config_button = new QPushButton(tr("Auto Calibration"), this);
_layout.addWidget(_config_button);
connect(_config_button, SIGNAL(clicked()), this, SLOT(zero_adj()));
@@ -86,8 +86,7 @@ DeviceOptions::DeviceOptions(QWidget *parent, boost::shared_ptr<pv::device::DevI
void DeviceOptions::accept()
{
using namespace Qt;
QDialog::accept();
bool hasEnabled = false;
// Commit the properties
const vector< boost::shared_ptr<pv::prop::Property> > &properties =
@@ -103,10 +102,24 @@ void DeviceOptions::accept()
for (const GSList *l = _dev_inst->dev_inst()->channels; l; l = l->next) {
sr_channel *const probe = (sr_channel*)l->data;
assert(probe);
probe->enabled = (_probes_checkBox_list.at(index)->checkState() == Qt::Checked);
index++;
if (probe->enabled)
hasEnabled = true;
}
} else {
hasEnabled = true;
}
if (hasEnabled) {
QDialog::accept();
} else {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Attention"));
msg.mBox()->setInformativeText(tr("All channel disabled! Please enable at least one channel."));
msg.mBox()->addButton(tr("Ok"), QMessageBox::AcceptRole);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
}
}
@@ -147,6 +160,8 @@ void DeviceOptions::setup_probes()
int row0 = 0, row1 = 0, col = 0;
int index = 0;
QString ch_mode;
int vld_ch_num = 0;
int cur_ch_num = 0;
while(_probes_box_layout.count() > 0)
{
@@ -182,10 +197,22 @@ void DeviceOptions::setup_probes()
}
}
GVariant *gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_VLD_CH_NUM);
if (gvar != NULL) {
vld_ch_num = g_variant_get_int16(gvar);
g_variant_unref(gvar);
}
for (const GSList *l = _dev_inst->dev_inst()->channels; l; l = l->next) {
sr_channel *const probe = (sr_channel*)l->data;
assert(probe);
if (probe->enabled)
cur_ch_num++;
if (cur_ch_num > vld_ch_num)
probe->enabled = false;
QLabel *probe_label = new QLabel(QString::number(probe->index), this);
QCheckBox *probe_checkBox = new QCheckBox(this);
probe_checkBox->setCheckState(probe->enabled ? Qt::Checked : Qt::Unchecked);
@@ -197,6 +224,8 @@ void DeviceOptions::setup_probes()
index++;
col = index % 8;
row1 = index / 8;
connect(probe_checkBox, SIGNAL(released()), this, SLOT(channel_enable()));
}
QPushButton *_enable_all_probes = new QPushButton(tr("Enable All"), this);
@@ -220,8 +249,45 @@ void DeviceOptions::set_all_probes(bool set)
}
}
void DeviceOptions::enable_max_probes() {
int cur_ch_num = 0;
QVector<QCheckBox *>::iterator iter = _probes_checkBox_list.begin();
while(iter != _probes_checkBox_list.end()) {
if ((*iter)->isChecked())
cur_ch_num++;
iter++;
}
GVariant* gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_VLD_CH_NUM);
if (gvar == NULL)
return;
int vld_ch_num = g_variant_get_int16(gvar);
g_variant_unref(gvar);
iter = _probes_checkBox_list.begin();
while(cur_ch_num < vld_ch_num &&
iter != _probes_checkBox_list.end()) {
if (!(*iter)->isChecked()) {
(*iter)->setChecked(true);
cur_ch_num++;
}
iter++;
}
}
void DeviceOptions::enable_all_probes()
{
GVariant* gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_STREAM);
if (gvar != NULL) {
bool stream_mode = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
if (stream_mode) {
enable_max_probes();
return;
}
}
set_all_probes(true);
}
@@ -237,7 +303,7 @@ void DeviceOptions::zero_adj()
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Information"));
msg.mBox()->setInformativeText(tr("Zero adjustment program will be started. Please keep all channels out of singal input. It can take a while!"));
msg.mBox()->setInformativeText(tr("Auto Calibration program will be started. Please keep all channels out of singal input. It can take a while!"));
//msg.mBox()->setStandardButtons(QMessageBox::);
msg.mBox()->addButton(tr("Ok"), QMessageBox::AcceptRole);
msg.mBox()->addButton(tr("Cancel"), QMessageBox::RejectRole);
@@ -293,5 +359,47 @@ void DeviceOptions::channel_check()
setup_probes();
}
void DeviceOptions::channel_enable()
{
QCheckBox* sc=dynamic_cast<QCheckBox*>(sender());
if (sc == NULL || !sc->isChecked())
return;
GVariant* gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_STREAM);
if (gvar == NULL)
return;
bool stream_mode = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
if (!stream_mode)
return;
int cur_ch_num = 0;
QVector<QCheckBox *>::iterator i = _probes_checkBox_list.begin();
while(i != _probes_checkBox_list.end()) {
if ((*i)->isChecked())
cur_ch_num++;
i++;
}
gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_VLD_CH_NUM);
if (gvar == NULL)
return;
int vld_ch_num = g_variant_get_int16(gvar);
g_variant_unref(gvar);
if (cur_ch_num > vld_ch_num) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Information"));
msg.mBox()->setInformativeText(tr("Current mode only suppport max ") + QString::number(vld_ch_num) + tr(" channels!"));
msg.mBox()->addButton(tr("Ok"), QMessageBox::AcceptRole);
msg.mBox()->setIcon(QMessageBox::Information);
msg.exec();
sc->setChecked(false);
}
}
} // namespace dialogs
} // namespace pv

View File

@@ -66,6 +66,7 @@ private:
void setup_probes();
void set_all_probes(bool set);
void enable_max_probes();
private slots:
void enable_all_probes();
@@ -74,6 +75,7 @@ private slots:
void mode_check();
void channel_check();
void on_calibration();
void channel_enable();
private:
boost::shared_ptr<pv::device::DevInst> _dev_inst;

View File

@@ -36,7 +36,8 @@ DSDialog::DSDialog(QWidget *parent, bool hasClose) :
QDialog(parent),
_moving(false)
{
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
setAttribute(Qt::WA_TranslucentBackground);
build_main(hasClose);

View File

@@ -36,7 +36,8 @@ DSMessageBox::DSMessageBox(QWidget *parent) :
QDialog(parent),
_moving(false)
{
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
setAttribute(Qt::WA_TranslucentBackground);
_main = new QWidget(this);
QVBoxLayout *mlayout = new QVBoxLayout(_main);
@@ -50,7 +51,8 @@ DSMessageBox::DSMessageBox(QWidget *parent) :
_main->setGraphicsEffect(bodyShadow);
_msg = new QMessageBox(this);
_msg->setWindowFlags(Qt::FramelessWindowHint | Qt::Widget);
_msg->setWindowFlags(Qt::FramelessWindowHint | Qt::Widget | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
_titlebar = new toolbars::TitleBar(false, this);
_titlebar->setTitle(tr("Message"));

View File

@@ -152,7 +152,7 @@ void ProtocolExp::accept()
break;
}
}
out << QString("%1;%2;%3\n")
out << QString("%1,%2,%3\n")
.arg("ID")
.arg("Time[s]")
.arg(title);
@@ -180,7 +180,7 @@ void ProtocolExp::accept()
0, decoder_stack->sample_count()-1);
if (!annotations.empty()) {
BOOST_FOREACH(const Annotation &a, annotations) {
out << QString("%1;%2;%3\n")
out << QString("%1,%2,%3\n")
.arg(QString::number(exported))
.arg(QString::number(a.start_sample()*time_pre_samples))
.arg(a.annotations().at(0));
@@ -195,7 +195,8 @@ void ProtocolExp::accept()
QProgressDialog dlg(tr("Export Protocol List Result... It can take a while."),
tr("Cancel"),0,100,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
QFutureWatcher<void> watcher;
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));

View File

@@ -47,6 +47,15 @@ ProtocolList::ProtocolList(QWidget *parent, SigSession &session) :
{
pv::data::DecoderModel* decoder_model = _session.get_decoder_model();
_map_zoom_combobox = new QComboBox(this);
_map_zoom_combobox->addItem(tr("Fit to Window"));
_map_zoom_combobox->addItem(tr("Fixed"));
int cur_map_zoom = _session.get_map_zoom();
if (cur_map_zoom >= _map_zoom_combobox->count())
_map_zoom_combobox->setCurrentIndex(0);
else
_map_zoom_combobox->setCurrentIndex(cur_map_zoom);
connect(_map_zoom_combobox, SIGNAL(currentIndexChanged(int)), &_session, SLOT(set_map_zoom(int)));
_protocol_combobox = new QComboBox(this);
const std::vector< boost::shared_ptr<pv::view::DecodeTrace> > decode_sigs(
@@ -67,6 +76,7 @@ ProtocolList::ProtocolList(QWidget *parent, SigSession &session) :
_flayout->setFormAlignment(Qt::AlignLeft);
_flayout->setLabelAlignment(Qt::AlignLeft);
_flayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
_flayout->addRow(new QLabel(tr("Map Zoom: "), this), _map_zoom_combobox);
_flayout->addRow(new QLabel(tr("Decoded Protocols: "), this), _protocol_combobox);
_layout = new QVBoxLayout();
@@ -185,6 +195,5 @@ void ProtocolList::on_row_check(bool show)
_session.get_decoder_model()->setDecoderStack(decoder_stack);
}
} // namespace dialogs
} // namespace pv

View File

@@ -62,6 +62,7 @@ private:
SigSession &_session;
toolbars::TitleBar *_titlebar;
QComboBox *_map_zoom_combobox;
QComboBox *_protocol_combobox;
std::list<QCheckBox *> _show_checkbox_list;
std::list<QLabel *> _show_label_list;

View File

@@ -21,53 +21,73 @@
#include "search.h"
#include "../view/logicsignal.h"
#include <assert.h>
#include <QRegExpValidator>
#include <boost/foreach.hpp>
namespace pv {
namespace dialogs {
Search::Search(QWidget *parent, boost::shared_ptr<device::DevInst> dev_inst, QString pattern) :
Search::Search(QWidget *parent, SigSession &session, std::map<uint16_t, QString> pattern) :
DSDialog(parent),
_dev_inst(dev_inst)
_session(session)
{
assert(_dev_inst);
QFont font("Monaco");
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
//this->setMinimumWidth(350);
QRegExp value_rx("[10XRFCxrfc ]+");
QRegExp value_rx("[10XRFCxrfc]+");
QValidator *value_validator = new QRegExpValidator(value_rx, this);
search_lineEdit.setText(pattern);
search_lineEdit.setValidator(value_validator);
search_lineEdit.setMaxLength(16 * 2 - 1);
search_lineEdit.setInputMask("X X X X X X X X X X X X X X X X");
search_lineEdit.setFont(font);
QLabel *search_label = new QLabel("1 1 1 1 1 1\n5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0");
search_label->setFont(font);
search_buttonBox.addButton(QDialogButtonBox::Ok);
search_buttonBox.addButton(QDialogButtonBox::Cancel);
QGridLayout *search_layout = new QGridLayout();
search_layout->setVerticalSpacing(5);
search_layout->addWidget(search_label, 1, 1);
search_layout->addWidget(new QLabel(tr("Search Value: ")), 2,0, Qt::AlignRight);
search_layout->addWidget(&search_lineEdit, 2, 1);
search_layout->addWidget(new QLabel(" "), 3,0);
search_layout->addWidget(new QLabel(tr("X: Don't care\n0: Low level\n1: High level\nR: Rising edge\nF: Falling edge\nC: Rising/Falling edge")), 4, 0);
search_layout->addWidget(&search_buttonBox, 5, 2);
search_layout->setVerticalSpacing(0);
int index = 0;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> sig,
_session.get_signals()) {
assert(sig);
boost::shared_ptr<view::LogicSignal> logic_sig;
if (logic_sig = boost::dynamic_pointer_cast<view::LogicSignal>(sig)) {
QLineEdit *search_lineEdit = new QLineEdit(this);
if (pattern.find(index) != pattern.end())
search_lineEdit->setText(pattern[index]);
else
search_lineEdit->setText("X");
search_lineEdit->setValidator(value_validator);
search_lineEdit->setMaxLength(1);
search_lineEdit->setInputMask("X");
search_lineEdit->setFont(font);
_search_lineEdit_vec.push_back(search_lineEdit);
search_layout->addWidget(new QLabel(logic_sig->get_name()+":"), index, 0, Qt::AlignRight);
search_layout->addWidget(new QLabel(QString::number(logic_sig->get_index())), index, 1, Qt::AlignRight);
search_layout->addWidget(search_lineEdit, index, 2);
connect(search_lineEdit, SIGNAL(editingFinished()), this, SLOT(format()));
index++;
}
}
search_layout->addWidget(new QLabel(" "), index,0);
search_layout->addWidget(new QLabel(tr("X: Don't care\n0: Low level\n1: High level\nR: Rising edge\nF: Falling edge\nC: Rising/Falling edge")), 0, 3, index, 1);
search_layout->addWidget(&search_buttonBox, index+1, 3);
search_layout->setColumnStretch(3, 100);
layout()->addLayout(search_layout);
setTitle(tr("Search Options"));
connect(&search_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(&search_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
connect(_dev_inst.get(), SIGNAL(device_updated()), this, SLOT(reject()));
connect(_session.get_device().get(), SIGNAL(device_updated()), this, SLOT(reject()));
}
Search::~Search()
@@ -81,10 +101,27 @@ void Search::accept()
QDialog::accept();
}
QString Search::get_pattern()
void Search::format()
{
QString pattern = search_lineEdit.text();
//pattern.remove(QChar('/r'), Qt::CaseInsensitive);
QLineEdit *sc = qobject_cast<QLineEdit *>(sender());
sc->setText(sc->text().toUpper());
}
std::map<uint16_t, QString> Search::get_pattern()
{
std::map<uint16_t, QString> pattern;
int index = 0;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> sig,
_session.get_signals()) {
assert(sig);
boost::shared_ptr<view::LogicSignal> logic_sig;
if (logic_sig = boost::dynamic_pointer_cast<view::LogicSignal>(sig)) {
pattern[index] = _search_lineEdit_vec[index]->text();
index++;
}
}
return pattern;
}

View File

@@ -45,23 +45,25 @@ class Search : public DSDialog
public:
Search(QWidget *parent = 0, boost::shared_ptr<pv::device::DevInst> dev_inst = 0, QString pattern = "");
Search(QWidget *parent, SigSession &session, std::map<uint16_t, QString> pattern);
~Search();
QString get_pattern();
std::map<uint16_t, QString> get_pattern();
protected:
void accept();
signals:
public slots:
private slots:
void format();
private:
SigSession &_session;
toolbars::TitleBar *_titlebar;
QLineEdit search_lineEdit;
QVector<QLineEdit *> _search_lineEdit_vec;
QDialogButtonBox search_buttonBox;
boost::shared_ptr<pv::device::DevInst> _dev_inst;
};
} // namespace decoder

View File

@@ -2,6 +2,7 @@
* This file is part of the PulseView project.
*
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,62 +22,113 @@
#include "storeprogress.h"
#include "dsmessagebox.h"
#include "QVBoxLayout"
namespace pv {
namespace dialogs {
StoreProgress::StoreProgress(const QString &file_name,
SigSession &session, QWidget *parent) :
QProgressDialog(tr("Saving..."), tr("Cancel"), 0, 0, parent),
_session(file_name.toStdString(), session)
StoreProgress::StoreProgress(SigSession &session, QWidget *parent) :
DSDialog(parent),
_store_session(session),
_button_box(QDialogButtonBox::Cancel, Qt::Horizontal, this),
_done(false)
{
connect(&_session, SIGNAL(progress_updated()),
this, SLOT(on_progress_updated()));
this->setModal(true);
_info.setText("...");
_progress.setValue(0);
_progress.setMaximum(0);
QVBoxLayout* add_layout = new QVBoxLayout(this);
add_layout->addWidget(&_info, 0, Qt::AlignCenter);
add_layout->addWidget(&_progress);
add_layout->addWidget(&_button_box);
layout()->addLayout(add_layout);
connect(&_button_box, SIGNAL(rejected()), this, SLOT(reject()));
connect(&_store_session, SIGNAL(progress_updated()),
this, SLOT(on_progress_updated()), Qt::QueuedConnection);
}
StoreProgress::~StoreProgress()
{
_session.wait();
_store_session.wait();
}
void StoreProgress::run()
void StoreProgress::reject()
{
if (_session.start())
show();
else
using namespace Qt;
_store_session.cancel();
QDialog::reject();
}
void StoreProgress::timeout()
{
if (_done)
close();
else
QTimer::singleShot(100, this, SLOT(timeout()));
}
void StoreProgress::save_run()
{
_info.setText("Saving...");
if (_store_session.save_start())
show();
else
show_error();
QTimer::singleShot(100, this, SLOT(timeout()));
}
void StoreProgress::export_run()
{
_info.setText("Exporting...");
if (_store_session.export_start())
show();
else
show_error();
QTimer::singleShot(100, this, SLOT(timeout()));
}
void StoreProgress::show_error()
{
dialogs::DSMessageBox msg(parentWidget());
msg.mBox()->setText(tr("Failed to save session."));
msg.mBox()->setInformativeText(_session.error());
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
if (!_store_session.error().isEmpty()) {
dialogs::DSMessageBox msg(parentWidget());
msg.mBox()->setText(tr("Failed to save data."));
msg.mBox()->setInformativeText(_store_session.error());
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
}
}
void StoreProgress::closeEvent(QCloseEvent*)
void StoreProgress::closeEvent(QCloseEvent* e)
{
_session.cancel();
_store_session.cancel();
DSDialog::closeEvent(e);
}
void StoreProgress::on_progress_updated()
{
const std::pair<uint64_t, uint64_t> p = _session.progress();
const std::pair<uint64_t, uint64_t> p = _store_session.progress();
assert(p.first <= p.second);
setValue(p.first);
setMaximum(p.second);
_progress.setValue(p.first);
_progress.setMaximum(p.second);
const QString err = _session.error();
const QString err = _store_session.error();
if (!err.isEmpty()) {
show_error();
close();
//close();
_done = true;
}
if (p.first == p.second)
close();
if (p.first == p.second) {
//close();
_done = true;
}
}
} // dialogs

View File

@@ -2,6 +2,7 @@
* This file is part of the PulseView project.
*
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,9 +26,13 @@
#include <boost/shared_ptr.hpp>
#include <QProgressDialog>
#include <QLabel>
#include <QProgressBar>
#include <QDialogButtonBox>
#include <QTimer>
#include <pv/storesession.h>
#include "../storesession.h"
#include "../dialogs/dsdialog.h"
#include "../toolbars/titlebar.h"
namespace pv {
@@ -36,30 +41,43 @@ class SigSession;
namespace dialogs {
class StoreProgress : public QProgressDialog
class StoreProgress : public DSDialog
{
Q_OBJECT
public:
StoreProgress(const QString &file_name, SigSession &session,
StoreProgress(SigSession &session,
QWidget *parent = 0);
virtual ~StoreProgress();
void run();
protected:
void reject();
private:
void show_error();
void closeEvent(QCloseEvent* e);
void closeEvent(QCloseEvent*);
public slots:
void save_run();
void export_run();
private slots:
void on_progress_updated();
void timeout();
private:
pv::StoreSession _session;
pv::StoreSession _store_session;
QLabel _info;
QProgressBar _progress;
QDialogButtonBox _button_box;
toolbars::TitleBar *_titlebar;
bool _done;
};
} // dialogs

View File

@@ -79,7 +79,7 @@ WaitingDialog::WaitingDialog(QWidget *parent, boost::shared_ptr<pv::device::DevI
mlayout->addWidget(&_button_box);
layout()->addLayout(mlayout);
setTitle(tr("Zero Adjustment"));
setTitle(tr("Auto Calibration"));
}
void WaitingDialog::accept()
@@ -100,7 +100,8 @@ void WaitingDialog::accept()
QProgressDialog dlg(tr("Save Auto Zero Result... It can take a while."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;
@@ -130,7 +131,8 @@ void WaitingDialog::reject()
QProgressDialog dlg(tr("Load Current Setting... It can take a while."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;

View File

@@ -34,14 +34,17 @@
#include "../devicemanager.h"
#include "../device/device.h"
#include "../device/file.h"
#include "../dialogs/dsdialog.h"
#include "../dialogs/dsmessagebox.h"
#include <QObject>
#include <QPainter>
#include <QRegExpValidator>
#include <QMessageBox>
#include "libsigrok4DSL/libsigrok.h"
using boost::shared_ptr;
using namespace boost;
namespace pv {
namespace dock {
@@ -51,7 +54,11 @@ using namespace pv::view;
MeasureDock::MeasureDock(QWidget *parent, View &view, SigSession &session) :
QScrollArea(parent),
_session(session),
_view(view)
_view(view),
_icon_add(":/icons/add.png"),
_icon_add_dis(":/icons/add_dis.png"),
_icon_del(":/icons/del.png"),
_icon_del_dis(":/icons/del_dis.png")
{
_widget = new QWidget(this);
@@ -67,76 +74,74 @@ MeasureDock::MeasureDock(QWidget *parent, View &view, SigSession &session) :
_mouse_layout = new QGridLayout();
_mouse_layout->setVerticalSpacing(5);
_mouse_layout->addWidget(_fen_checkBox, 0, 0, 1, 4);
_mouse_layout->addWidget(_fen_checkBox, 0, 0, 1, 6);
_mouse_layout->addWidget(new QLabel(tr("W: "), _widget), 1, 0);
_mouse_layout->addWidget(_width_label, 1, 1);
_mouse_layout->addWidget(new QLabel(tr("P: "), _widget), 1, 2);
_mouse_layout->addWidget(_period_label, 1, 3);
_mouse_layout->addWidget(new QLabel(tr("F: "), _widget), 2, 2);
_mouse_layout->addWidget(_freq_label, 2, 3);
_mouse_layout->addWidget(new QLabel(tr("P: "), _widget), 1, 4);
_mouse_layout->addWidget(_period_label, 1, 5);
_mouse_layout->addWidget(new QLabel(tr("F: "), _widget), 2, 4);
_mouse_layout->addWidget(_freq_label, 2, 5);
_mouse_layout->addWidget(new QLabel(tr("D: "), _widget), 2, 0);
_mouse_layout->addWidget(_duty_label, 2, 1);
_mouse_layout->addWidget(new QLabel(_widget), 0, 4);
_mouse_layout->addWidget(new QLabel(_widget), 1, 4);
_mouse_layout->addWidget(new QLabel(_widget), 2, 4);
_mouse_layout->addWidget(new QLabel(_widget), 0, 6);
_mouse_layout->addWidget(new QLabel(_widget), 1, 6);
_mouse_layout->addWidget(new QLabel(_widget), 2, 6);
_mouse_layout->setColumnStretch(5, 1);
_mouse_groupBox->setLayout(_mouse_layout);
/* cursor distance group */
_dist_groupBox = new QGroupBox(tr("Cursor Distance"), _widget);
_dist_groupBox->setMinimumWidth(300);
_dist_add_btn = new QToolButton(_widget);
_dist_add_btn->setIcon(_icon_add);
connect(_dist_add_btn, SIGNAL(clicked()), this, SLOT(add_dist_measure()));
_cursor_groupBox = new QGroupBox(tr("Cursor measurement"), _widget);
_t1_comboBox = new QComboBox(_widget);
_t2_comboBox = new QComboBox(_widget);
_t3_comboBox = new QComboBox(_widget);
_delta_label_t1t2 = new QLabel("##########/##########", _widget);
_delta_label_t2t3 = new QLabel("##########/##########", _widget);
_delta_label_t1t3 = new QLabel("##########/##########", _widget);
_t1_last_index = 0;
_t2_last_index = 0;
_t3_last_index = 0;
_t1_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
_t2_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
_t3_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
_dist_layout = new QGridLayout(_widget);
_dist_layout->setVerticalSpacing(5);
_dist_layout->addWidget(_dist_add_btn, 0, 0);
_dist_layout->addWidget(new QLabel(_widget), 0, 1, 1, 3);
_dist_layout->addWidget(new QLabel(tr("Time/Samples"), _widget), 0, 4);
_dist_layout->addWidget(new QLabel(_widget), 0, 5, 1, 2);
_dist_layout->setColumnStretch(1, 50);
_dist_layout->setColumnStretch(6, 100);
add_dist_measure();
_dist_groupBox->setLayout(_dist_layout);
/* cursor edges group */
_edge_groupBox = new QGroupBox(tr("Edges"), _widget);
_edge_groupBox->setMinimumWidth(300);
_edge_add_btn = new QToolButton(_widget);
_edge_add_btn->setIcon(_icon_add);
connect(_edge_add_btn, SIGNAL(clicked()), this, SLOT(add_edge_measure()));
_edge_layout = new QGridLayout(_widget);
_edge_layout->setVerticalSpacing(5);
_edge_layout->addWidget(_edge_add_btn, 0, 0);
_edge_layout->addWidget(new QLabel(_widget), 0, 1, 1, 4);
_edge_layout->addWidget(new QLabel(tr("Channel"), _widget), 0, 5);
_edge_layout->addWidget(new QLabel(tr("Rising/Falling/Edges"), _widget), 0, 6);
_edge_layout->setColumnStretch(1, 50);
//_edge_layout->setColumnStretch(6, 100);
//add_edge_measure();
_edge_groupBox->setLayout(_edge_layout);
/* cursors group */
_cursor_groupBox = new QGroupBox(tr("Cursors"), _widget);
_cursor_layout = new QGridLayout(_widget);
_cursor_layout->setVerticalSpacing(5);
_cursor_layout->addWidget(new QLabel(tr("T1: "), _widget), 0, 0);
_cursor_layout->addWidget(_t1_comboBox, 0, 1);
_cursor_layout->addWidget(new QLabel(tr("T2: "), _widget), 1, 0);
_cursor_layout->addWidget(_t2_comboBox, 1, 1);
_cursor_layout->addWidget(new QLabel(tr("T3: "), _widget), 2, 0);
_cursor_layout->addWidget(_t3_comboBox, 2, 1);
_cursor_layout->addWidget(new QLabel(tr("Time/Samples"), _widget), 3, 1, 1, 2);
_cursor_layout->addWidget(new QLabel(tr("|T2 - T1|: "), _widget), 4, 0);
_cursor_layout->addWidget(_delta_label_t1t2, 4, 1, 1, 2);
_cursor_layout->addWidget(new QLabel(tr("|T3 - T2|: "), _widget), 5, 0);
_cursor_layout->addWidget(_delta_label_t2t3, 5, 1, 1, 2);
_cursor_layout->addWidget(new QLabel(tr("|T3 - T1|: "), _widget), 6, 0);
_cursor_layout->addWidget(_delta_label_t1t3, 6, 1, 1, 2);
_cursor_layout->addWidget(new QLabel(_widget), 7, 0);
_cursor_layout->addWidget(new QLabel(tr("Cursors"), _widget), 8, 0);
_cursor_layout->addWidget(new QLabel(tr("Time/Samples"), _widget), 8, 1, 1, 2);
_cursor_layout->addWidget(new QLabel(_widget), 0, 2);
_cursor_layout->addWidget(new QLabel(_widget), 1, 2);
_cursor_layout->addWidget(new QLabel(_widget), 2, 2);
_cursor_layout->setColumnStretch(2, 1);
_cursor_layout->addWidget(new QLabel(tr("Time/Samples"), _widget), 0, 2);
_cursor_layout->addWidget(new QLabel(_widget), 0, 3);
_cursor_layout->setColumnStretch(3, 1);
_cursor_groupBox->setLayout(_cursor_layout);
QVBoxLayout *layout = new QVBoxLayout(_widget);
layout->addWidget(_mouse_groupBox);
layout->addWidget(_dist_groupBox);
layout->addWidget(_edge_groupBox);
layout->addWidget(_cursor_groupBox);
layout->addStretch(1);
_widget->setLayout(layout);
connect(_t1_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
connect(_t2_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
connect(_t3_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
connect(_fen_checkBox, SIGNAL(stateChanged(int)), &_view, SLOT(set_measure_en(int)));
connect(&_view, SIGNAL(measure_updated()), this, SLOT(measure_updated()));
@@ -157,73 +162,70 @@ void MeasureDock::paintEvent(QPaintEvent *)
// style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
void MeasureDock::refresh()
{
}
void MeasureDock::reload()
{
for (QVector <QComboBox *>::const_iterator i = _edge_ch_cmb_vec.begin();
i != _edge_ch_cmb_vec.end(); i++) {
update_probe_selector(*i);
}
reCalc();
}
void MeasureDock::cursor_update()
{
using namespace pv::data;
int index = 1;
disconnect(_t1_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
disconnect(_t2_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
disconnect(_t3_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
_t1_comboBox->clear();
_t2_comboBox->clear();
_t3_comboBox->clear();
if (!_cursor_pushButton_list.empty()) {
for (QVector <QToolButton *>::const_iterator i = _cursor_del_btn_vec.begin();
i != _cursor_del_btn_vec.end(); i++)
delete (*i);
for (QVector<QPushButton *>::Iterator i = _cursor_pushButton_list.begin();
i != _cursor_pushButton_list.end(); i++)
delete (*i);
for (QVector<QLabel *>::Iterator i = _curpos_label_list.begin();
i != _curpos_label_list.end(); i++)
delete (*i);
for (QVector<QLabel *>::Iterator i = _space_label_list.begin();
i != _space_label_list.end(); i++)
delete (*i);
_cursor_del_btn_vec.clear();
_cursor_pushButton_list.clear();
_curpos_label_list.clear();
_space_label_list.clear();
}
update_dist();
update_edge();
int index = 1;
for(std::list<Cursor*>::iterator i = _view.get_cursorList().begin();
i != _view.get_cursorList().end(); i++) {
QString curCursor = tr("Cursor ")+QString::number(index);
_t1_comboBox->addItem(curCursor);
_t2_comboBox->addItem(curCursor);
_t3_comboBox->addItem(curCursor);
QString curCursor = QString::number(index);
QToolButton *del_btn = new QToolButton(_widget);
del_btn->setIcon(QIcon::fromTheme("measure",
QIcon(":/icons/del.png")));
del_btn->setCheckable(true);
QPushButton *_cursor_pushButton = new QPushButton(curCursor, _widget);
set_cursor_btn_color(_cursor_pushButton);
QString _cur_text = _view.get_cm_time(index - 1) + "/" + QString::number(_view.get_cursor_samples(index - 1));
QLabel *_curpos_label = new QLabel(_cur_text, _widget);
QLabel *_space_label = new QLabel(_widget);
_cursor_del_btn_vec.push_back(del_btn);
_cursor_pushButton_list.push_back(_cursor_pushButton);
_curpos_label_list.push_back(_curpos_label);
_space_label_list.push_back(_space_label);
_cursor_layout->addWidget(_cursor_pushButton, 8 + index, 0);
_cursor_layout->addWidget(_curpos_label, 8 + index, 1, 1, 2);
_cursor_layout->addWidget(del_btn, 1+index, 0);
_cursor_layout->addWidget(_cursor_pushButton, 1 + index, 1);
_cursor_layout->addWidget(_curpos_label, 1 + index, 2);
connect(del_btn, SIGNAL(clicked()), this, SLOT(del_cursor()));
connect(_cursor_pushButton, SIGNAL(clicked()), this, SLOT(goto_cursor()));
index++;
}
_t1_comboBox->setMinimumWidth(_t1_comboBox->sizeHint().width()+30);
_t2_comboBox->setMinimumWidth(_t2_comboBox->sizeHint().width()+30);
_t3_comboBox->setMinimumWidth(_t3_comboBox->sizeHint().width()+30);
if (_t1_last_index < _t1_comboBox->count())
_t1_comboBox->setCurrentIndex(_t1_last_index);
if (_t2_last_index < _t2_comboBox->count())
_t2_comboBox->setCurrentIndex(_t2_last_index);
if (_t3_last_index < _t3_comboBox->count())
_t3_comboBox->setCurrentIndex(_t3_last_index);
connect(_t1_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
connect(_t2_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
connect(_t3_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
delta_update();
update();
}
@@ -235,7 +237,7 @@ void MeasureDock::measure_updated()
_duty_label->setText(_view.get_measure("duty"));
}
void MeasureDock::cursor_moved()
void MeasureDock::cursor_moving()
{
//TimeMarker* grabbed_marker = _view.get_ruler()->get_grabbed_cursor();
if (_view.cursors_shown()) {
@@ -248,38 +250,13 @@ void MeasureDock::cursor_moved()
index++;
}
}
delta_update();
update_dist();
}
void MeasureDock::delta_update()
void MeasureDock::reCalc()
{
QString delta_text;
_t1_last_index = std::max(_t1_comboBox->currentIndex(), 0);
_t2_last_index = std::max(_t2_comboBox->currentIndex(), 0);
_t3_last_index = std::max(_t3_comboBox->currentIndex(), 0);
if (_t1_comboBox->count() != 0 && _t2_comboBox->count() != 0) {
uint64_t delta = abs(_view.get_cursor_samples(_t1_last_index) -
_view.get_cursor_samples(_t2_last_index));
delta_text = _view.get_cm_delta(_t1_last_index, _t2_last_index) +
"/" + QString::number(delta);
_delta_label_t1t2->setText(delta_text);
}
if (_t2_comboBox->count() != 0 && _t2_comboBox->count() != 0) {
uint64_t delta = abs(_view.get_cursor_samples(_t2_last_index) -
_view.get_cursor_samples(_t3_last_index));
delta_text = _view.get_cm_delta(_t2_last_index, _t3_last_index) +
"/" + QString::number(delta);
_delta_label_t2t3->setText(delta_text);
}
if (_t1_comboBox->count() != 0 && _t3_comboBox->count() != 0) {
uint64_t delta = abs(_view.get_cursor_samples(_t1_last_index) -
_view.get_cursor_samples(_t3_last_index));
delta_text = _view.get_cm_delta(_t1_last_index, _t3_last_index) +
"/" + QString::number(delta);
_delta_label_t1t3->setText(delta_text);
}
update_edge();
}
void MeasureDock::goto_cursor()
@@ -297,5 +274,387 @@ void MeasureDock::goto_cursor()
}
}
void MeasureDock::add_dist_measure()
{
if (_dist_row_widget_vec.size() > Max_Measure_Limits)
return;
QWidget *row_widget = new QWidget(_widget);
row_widget->setContentsMargins(0,0,0,0);
QHBoxLayout *row_layout = new QHBoxLayout(row_widget);
row_layout->setContentsMargins(0,0,0,0);
row_layout->setSpacing(0);
row_widget->setLayout(row_layout);
_dist_row_widget_vec.push_back(row_widget);
QToolButton *del_btn = new QToolButton(row_widget);
del_btn->setIcon(QIcon::fromTheme("measure",
QIcon(":/icons/del.png")));
del_btn->setCheckable(true);
QPushButton *s_btn = new QPushButton(tr(" "), row_widget);
s_btn->setObjectName("dist");
QPushButton *e_btn = new QPushButton(tr(" "), row_widget);
e_btn->setObjectName("dist");
QLabel *r_label = new QLabel(row_widget);
QLabel *g_label = new QLabel(tr("-"), row_widget);
g_label->setContentsMargins(0,0,0,0);
_dist_del_btn_vec.push_back(del_btn);
_dist_s_btn_vec.push_back(s_btn);
_dist_e_btn_vec.push_back(e_btn);
_dist_r_label_vec.push_back(r_label);
connect(del_btn, SIGNAL(clicked()), this, SLOT(del_dist_measure()));
connect(s_btn, SIGNAL(clicked()), this, SLOT(show_all_coursor()));
connect(e_btn, SIGNAL(clicked()), this, SLOT(show_all_coursor()));
row_layout->addWidget(del_btn);
row_layout->addSpacing(5);
row_layout->addWidget(s_btn);
row_layout->addWidget(g_label);
row_layout->addWidget(e_btn);
row_layout->addSpacing(5);
row_layout->addWidget(r_label, 100);
_dist_layout->addWidget(row_widget, _dist_row_widget_vec.size(), 0, 1, 7);
}
void MeasureDock::del_dist_measure()
{
int del_index = 0;
for (QVector <QToolButton *>::const_iterator i = _dist_del_btn_vec.begin();
i != _dist_del_btn_vec.end(); i++) {
if ((*i)->isChecked()) {
_dist_layout->removeWidget(_dist_row_widget_vec.at(del_index));
delete _dist_del_btn_vec.at(del_index);
delete _dist_s_btn_vec.at(del_index);
delete _dist_e_btn_vec.at(del_index);
delete _dist_r_label_vec.at(del_index);
delete _dist_row_widget_vec.at(del_index);
_dist_del_btn_vec.remove(del_index);
_dist_s_btn_vec.remove(del_index);
_dist_e_btn_vec.remove(del_index);
_dist_r_label_vec.remove(del_index);
_dist_row_widget_vec.remove(del_index);
break;
}
del_index++;
}
}
void MeasureDock::add_edge_measure()
{
if (_edge_row_widget_vec.size() > Max_Measure_Limits)
return;
QWidget *row_widget = new QWidget(_widget);
row_widget->setContentsMargins(0,0,0,0);
QHBoxLayout *row_layout = new QHBoxLayout(row_widget);
row_layout->setContentsMargins(0,0,0,0);
row_layout->setSpacing(0);
row_widget->setLayout(row_layout);
_edge_row_widget_vec.push_back(row_widget);
QToolButton *del_btn = new QToolButton(row_widget);
del_btn->setIcon(QIcon::fromTheme("measure",
QIcon(":/icons/del.png")));
del_btn->setCheckable(true);
QPushButton *s_btn = new QPushButton(tr(" "), row_widget);
s_btn->setObjectName("edge");
QPushButton *e_btn = new QPushButton(tr(" "), row_widget);
e_btn->setObjectName("edge");
QLabel *r_label = new QLabel(row_widget);
QLabel *g_label = new QLabel(tr("-"), row_widget);
g_label->setContentsMargins(0,0,0,0);
QLabel *a_label = new QLabel(tr("@"), row_widget);
a_label->setContentsMargins(0,0,0,0);
QComboBox *ch_cmb = create_probe_selector(row_widget);
_edge_del_btn_vec.push_back(del_btn);
_edge_s_btn_vec.push_back(s_btn);
_edge_e_btn_vec.push_back(e_btn);
_edge_ch_cmb_vec.push_back(ch_cmb);
_edge_r_label_vec.push_back(r_label);
connect(del_btn, SIGNAL(clicked()), this, SLOT(del_edge_measure()));
connect(s_btn, SIGNAL(clicked()), this, SLOT(show_all_coursor()));
connect(e_btn, SIGNAL(clicked()), this, SLOT(show_all_coursor()));
connect(ch_cmb, SIGNAL(currentIndexChanged(int)), this, SLOT(update_edge()));
row_layout->addWidget(del_btn);
row_layout->addSpacing(5);
row_layout->addWidget(s_btn);
row_layout->addWidget(g_label);
row_layout->addWidget(e_btn);
row_layout->addWidget(a_label);
row_layout->addWidget(ch_cmb);
row_layout->addSpacing(5);
row_layout->addWidget(r_label, 100);
_edge_layout->addWidget(row_widget, _edge_row_widget_vec.size(), 0, 1, 7);
}
void MeasureDock::del_edge_measure()
{
int del_index = 0;
for (QVector <QToolButton *>::const_iterator i = _edge_del_btn_vec.begin();
i != _edge_del_btn_vec.end(); i++) {
if ((*i)->isChecked()) {
_edge_layout->removeWidget(_edge_row_widget_vec.at(del_index));
delete _edge_del_btn_vec.at(del_index);
delete _edge_s_btn_vec.at(del_index);
delete _edge_e_btn_vec.at(del_index);
delete _edge_r_label_vec.at(del_index);
delete _edge_ch_cmb_vec.at(del_index);
delete _edge_row_widget_vec.at(del_index);
_edge_del_btn_vec.remove(del_index);
_edge_s_btn_vec.remove(del_index);
_edge_e_btn_vec.remove(del_index);
_edge_r_label_vec.remove(del_index);
_edge_ch_cmb_vec.remove(del_index);
_edge_row_widget_vec.remove(del_index);
break;
}
del_index++;
}
}
void MeasureDock::show_all_coursor()
{
if (_view.get_cursorList().empty()) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Information"));
msg.mBox()->setInformativeText(tr("Please insert cursor before using cursor measure."));
msg.mBox()->addButton(tr("Ok"), QMessageBox::AcceptRole);
msg.mBox()->setIcon(QMessageBox::Information);
msg.exec();
return;
}
_sel_btn = qobject_cast<QPushButton *>(sender());
//dialogs::DSDialog cursor_dlg(_widget);
QDialog cursor_dlg(_widget);
cursor_dlg.setWindowFlags(Qt::FramelessWindowHint | Qt::Popup | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
int index = 0;
QHBoxLayout *hlayout;
QVBoxLayout *vlayout = new QVBoxLayout(&cursor_dlg);
for(std::list<Cursor*>::iterator i = _view.get_cursorList().begin();
i != _view.get_cursorList().end(); i++) {
QPushButton *cursor_btn = new QPushButton(QString::number(index+1), &cursor_dlg);
set_cursor_btn_color(cursor_btn);
if ((index % 4) == 0) {
hlayout = new QHBoxLayout(&cursor_dlg);
vlayout->addLayout(hlayout);
//cursor_dlg.layout()->addLayout(hlayout);
}
hlayout->addWidget(cursor_btn);
connect(cursor_btn, SIGNAL(clicked()), &cursor_dlg, SLOT(accept()));
connect(cursor_btn, SIGNAL(clicked()), this, SLOT(set_se_cursor()));
index++;
}
while((index++ % 4) != 0)
hlayout->addWidget(new QLabel(&cursor_dlg));
cursor_dlg.setLayout(vlayout);
QRect sel_btn_rect = _sel_btn->geometry();
sel_btn_rect.moveTopLeft(_sel_btn->parentWidget()->mapToGlobal(sel_btn_rect.topLeft()));
cursor_dlg.setGeometry(sel_btn_rect.left(), sel_btn_rect.bottom()+10,
cursor_dlg.width(), cursor_dlg.height());
cursor_dlg.exec();
}
void MeasureDock::set_se_cursor()
{
QPushButton *sc = qobject_cast<QPushButton *>(sender());
if (_sel_btn)
_sel_btn->setText(sc->text());
set_cursor_btn_color(_sel_btn);
if (_sel_btn->objectName() == "dist")
update_dist();
else if (_sel_btn->objectName() == "edge")
update_edge();
}
const view::Cursor* MeasureDock::find_cousor(int index)
{
int cur_index = 1;
for(std::list<Cursor*>::iterator i = _view.get_cursorList().begin();
i != _view.get_cursorList().end(); i++) {
if (cur_index == index) {
return (*i);
}
}
return NULL;
}
void MeasureDock::update_dist()
{
int dist_index = 0;
for (QVector<QPushButton *>::Iterator i = _dist_s_btn_vec.begin();
i != _dist_s_btn_vec.end(); i++) {
bool start_ret, end_ret;
const unsigned int start = (*i)->text().toInt(&start_ret) - 1;
const unsigned int end = _dist_e_btn_vec[dist_index]->text().toInt(&end_ret) - 1;
if (start_ret) {
if (start + 1 > _view.get_cursorList().size()) {
(*i)->setText(" ");
set_cursor_btn_color((*i));
start_ret = false;
}
}
if (end_ret) {
if (end + 1 > _view.get_cursorList().size()) {
_dist_e_btn_vec[dist_index]->setText(" ");
set_cursor_btn_color(_dist_e_btn_vec[dist_index]);
end_ret = false;
}
}
if (start_ret && end_ret) {
int64_t delta = _view.get_cursor_samples(start) -
_view.get_cursor_samples(end);
QString delta_text = _view.get_cm_delta(start, end) +
"/" + QString::number(delta);
if (delta < 0)
delta_text.replace('+', '-');
_dist_r_label_vec[dist_index]->setText(delta_text);
} else {
_dist_r_label_vec[dist_index]->setText(" ");
}
dist_index++;
}
}
void MeasureDock::update_edge()
{
int edge_index = 0;
for (QVector<QPushButton *>::Iterator i = _edge_s_btn_vec.begin();
i != _edge_s_btn_vec.end(); i++) {
bool start_ret, end_ret;
const unsigned int start = (*i)->text().toInt(&start_ret) - 1;
const unsigned int end = _edge_e_btn_vec[edge_index]->text().toInt(&end_ret) - 1;
if (start_ret) {
if (start + 1 > _view.get_cursorList().size()) {
(*i)->setText(" ");
set_cursor_btn_color((*i));
start_ret = false;
}
}
if (end_ret) {
if (end + 1 > _view.get_cursorList().size()) {
_edge_e_btn_vec[edge_index]->setText(" ");
set_cursor_btn_color(_edge_e_btn_vec[edge_index]);
end_ret = false;
}
}
bool mValid = false;
if (start_ret && end_ret) {
uint64_t rising_edges;
uint64_t falling_edges;
const std::vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
for(size_t i = 0; i < sigs.size(); i++) {
const boost::shared_ptr<view::Signal> s(sigs[i]);
boost::shared_ptr<view::LogicSignal> logicSig;
assert(s);
if ((logicSig = dynamic_pointer_cast<view::LogicSignal>(s)) &&
(logicSig->enabled()) &&
(logicSig->get_index() == _edge_ch_cmb_vec[edge_index]->currentText().toInt())){
if (logicSig->edges(_view.get_cursor_samples(end), _view.get_cursor_samples(start), rising_edges, falling_edges)) {
QString delta_text = QString::number(rising_edges) + "/" +
QString::number(falling_edges) + "/" +
QString::number(rising_edges + falling_edges);
_edge_r_label_vec[edge_index]->setText(delta_text);
mValid = true;
break;
}
}
}
}
if (!mValid)
_edge_r_label_vec[edge_index]->setText("-/-/-");
edge_index++;
}
}
void MeasureDock::set_cursor_btn_color(QPushButton *btn)
{
bool ret;
const unsigned int start = btn->text().toInt(&ret) - 1;
QColor cursor_color = ret ? view::Ruler::CursorColor[start%8] : QColor("#302F2F");
QString border_width = ret ? "0px" : "1px";
QString normal = "{background-color:" + cursor_color.name() +
"; color:black" + "; border-width:" + border_width + ";}";
QString hover = "{background-color:" + cursor_color.darker().name() +
"; color:black" + "; border-width:" + border_width + ";}";
QString style = "QPushButton:hover" + hover +
"QPushButton" + normal;
btn->setStyleSheet(style);
}
QComboBox* MeasureDock::create_probe_selector(QWidget *parent)
{
QComboBox *selector = new QComboBox(parent);
update_probe_selector(selector);
return selector;
}
void MeasureDock::update_probe_selector(QComboBox *selector)
{
selector->clear();
const std::vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
for(size_t i = 0; i < sigs.size(); i++) {
const boost::shared_ptr<view::Signal> s(sigs[i]);
assert(s);
if (dynamic_pointer_cast<LogicSignal>(s) && s->enabled())
{
selector->addItem(QString::number(s->get_index()));
}
}
}
void MeasureDock::del_cursor()
{
int del_index = 0;
Cursor* cursor;
for (QVector <QToolButton *>::const_iterator i = _cursor_del_btn_vec.begin();
i != _cursor_del_btn_vec.end(); i++) {
if ((*i)->isChecked()) {
int cur_index = 0;
std::list<Cursor*>::iterator ite = _view.get_cursorList().begin();
while (cur_index++ != del_index)
ite++;
cursor = *ite;
break;
}
del_index++;
}
_view.del_cursor(cursor);
if (_view.get_cursorList().empty())
_view.show_cursors(false);
cursor_update();
_view.update();
}
} // namespace dock
} // namespace pv

View File

@@ -50,6 +50,7 @@ namespace pv {
class SigSession;
namespace view {
class Cursor;
class View;
}
@@ -59,21 +60,42 @@ class MeasureDock : public QScrollArea
{
Q_OBJECT
private:
static const int Max_Measure_Limits = 16;
public:
MeasureDock(QWidget *parent, pv::view::View &view, SigSession &session);
~MeasureDock();
void paintEvent(QPaintEvent *);
void reload();
private:
QComboBox* create_probe_selector(QWidget *parent);
void update_probe_selector(QComboBox *selector);
signals:
private slots:
void delta_update();
void goto_cursor();
void add_dist_measure();
void del_dist_measure();
void add_edge_measure();
void del_edge_measure();
void show_all_coursor();
void set_se_cursor();
const view::Cursor* find_cousor(int index);
void update_dist();
void update_edge();
void set_cursor_btn_color(QPushButton *btn);
void del_cursor();
public slots:
void cursor_update();
void cursor_moved();
void cursor_moving();
void reCalc();
void measure_updated();
void refresh();
private:
SigSession &_session;
@@ -88,24 +110,37 @@ private:
QLabel *_freq_label;
QLabel *_duty_label;
QGridLayout *_dist_layout;
QGroupBox *_dist_groupBox;
QToolButton *_dist_add_btn;
QVector<QWidget *> _dist_row_widget_vec;
QVector<QToolButton *> _dist_del_btn_vec;
QVector<QPushButton *> _dist_s_btn_vec;
QVector<QPushButton *> _dist_e_btn_vec;
QVector<QLabel *> _dist_r_label_vec;
QGridLayout *_edge_layout;
QGroupBox *_edge_groupBox;
QToolButton *_edge_add_btn;
QVector<QWidget *> _edge_row_widget_vec;
QVector<QToolButton *> _edge_del_btn_vec;
QVector<QPushButton *> _edge_s_btn_vec;
QVector<QPushButton *> _edge_e_btn_vec;
QVector<QComboBox *> _edge_ch_cmb_vec;
QVector<QLabel *> _edge_r_label_vec;
QPushButton *_sel_btn;
QGridLayout *_cursor_layout;
QGroupBox *_cursor_groupBox;
QComboBox *_t1_comboBox;
QComboBox *_t2_comboBox;
QComboBox *_t3_comboBox;
QLabel *_delta_label_t1t2;
QLabel *_cnt_label_t1t2;
QLabel *_delta_label_t2t3;
QLabel *_cnt_label_t2t3;
QLabel *_delta_label_t1t3;
QLabel *_cnt_label_t1t3;
int _t1_last_index;
int _t2_last_index;
int _t3_last_index;
QVector<QToolButton *> _cursor_del_btn_vec;
QVector <QPushButton *> _cursor_pushButton_list;
QVector <QLabel *> _curpos_label_list;
QVector <QLabel *> _space_label_list;
QIcon _icon_add;
QIcon _icon_add_dis;
QIcon _icon_del;
QIcon _icon_del_dis;
};
} // namespace dock

View File

@@ -29,6 +29,7 @@
#include "../dialogs/protocollist.h"
#include "../dialogs/protocolexp.h"
#include "../dialogs/dsmessagebox.h"
#include "../view/view.h"
#include <QObject>
#include <QHBoxLayout>
@@ -52,12 +53,14 @@
namespace pv {
namespace dock {
ProtocolDock::ProtocolDock(QWidget *parent, SigSession &session) :
ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession &session) :
QScrollArea(parent),
_session(session),
_view(view),
_cur_search_index(-1),
_search_edited(false),
_searching(false)
_searching(false),
_add_silent(false)
{
_up_widget = new QWidget(this);
@@ -125,11 +128,19 @@ ProtocolDock::ProtocolDock(QWidget *parent, SigSession &session) :
connect(_dn_save_button, SIGNAL(clicked()),
this, SLOT(export_table_view()));
_dn_nav_button = new QPushButton(_dn_widget);
_dn_nav_button->setFlat(true);
_dn_nav_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/nav.png")));
connect(_dn_nav_button, SIGNAL(clicked()),
this, SLOT(nav_table_view()));
QHBoxLayout *dn_title_layout = new QHBoxLayout();
dn_title_layout->addWidget(_dn_set_button, 0, Qt::AlignLeft);
dn_title_layout->addWidget(_dn_save_button, 0, Qt::AlignLeft);
dn_title_layout->addWidget(new QLabel(tr("Protocol List Viewer"), _dn_widget), 1, Qt::AlignLeft);
dn_title_layout->addStretch(1);
dn_title_layout->addWidget(_dn_nav_button, 0, Qt::AlignRight);
//dn_title_layout->addStretch(1);
_table_view = new QTableView(_dn_widget);
_table_view->setModel(_session.get_decoder_model());
@@ -237,7 +248,38 @@ int ProtocolDock::decoder_name_cmp(const void *a, const void *b)
((const srd_decoder*)b)->name);
}
bool ProtocolDock::sel_protocol(QString id)
{
QString name;
GSList *l = g_slist_sort(g_slist_copy(
(GSList*)srd_decoder_list()), decoder_name_cmp);
for(; l; l = l->next)
{
const srd_decoder *const d = (srd_decoder*)l->data;
assert(d);
const bool have_probes = (d->channels || d->opt_channels) != 0;
if (true == have_probes &&
QString::fromUtf8(d->id) == id) {
name = QString::fromUtf8(d->name);
break;
}
}
g_slist_free(l);
_protocol_combobox->setCurrentText(name);
if (_protocol_combobox->currentText() == name)
return true;
else
return false;
}
void ProtocolDock::add_protocol()
{
add_protocol(false);
}
void ProtocolDock::add_protocol(bool silent)
{
if (_session.get_device()->dev_inst()->mode != LOGIC) {
dialogs::DSMessageBox msg(this);
@@ -249,7 +291,7 @@ void ProtocolDock::add_protocol()
} else {
srd_decoder *const decoder =
(srd_decoder*)(_protocol_combobox->itemData(_protocol_combobox->currentIndex())).value<void*>();
if (_session.add_decoder(decoder)) {
if (_session.add_decoder(decoder, silent)) {
//std::list <int > _sel_probes = dlg.get_sel_probes();
//QMap <QString, QVariant>& _options = dlg.get_options();
//QMap <QString, int> _options_index = dlg.get_options_index();
@@ -442,6 +484,13 @@ void ProtocolDock::set_model()
resize_table_view(_session.get_decoder_model());
_model_proxy.setSourceModel(_session.get_decoder_model());
search_done();
// clear mark_index of all DecoderStacks
const std::vector< boost::shared_ptr<pv::view::DecodeTrace> > decode_sigs(
_session.get_decode_signals());
BOOST_FOREACH(boost::shared_ptr<pv::view::DecodeTrace> d, decode_sigs) {
d->decoder()->set_mark_index(-1);
}
}
void ProtocolDock::update_model()
@@ -494,7 +543,13 @@ void ProtocolDock::item_clicked(const QModelIndex &index)
if (decoder_stack) {
pv::data::decode::Annotation ann;
if (decoder_stack->list_annotation(ann, index.column(), index.row())) {
_session.show_region(ann.start_sample(), ann.end_sample());
const std::vector< boost::shared_ptr<pv::view::DecodeTrace> > decode_sigs(
_session.get_decode_signals());
BOOST_FOREACH(boost::shared_ptr<pv::view::DecodeTrace> d, decode_sigs) {
d->decoder()->set_mark_index(-1);
}
decoder_stack->set_mark_index((ann.start_sample()+ann.end_sample())/2);
_session.show_region(ann.start_sample(), ann.end_sample(), false);
}
}
_table_view->resizeRowToContents(index.row());
@@ -558,6 +613,41 @@ void ProtocolDock::export_table_view()
protocolexp_dlg->exec();
}
void ProtocolDock::nav_table_view()
{
uint64_t row_index;
pv::data::DecoderModel *decoder_model = _session.get_decoder_model();
boost::shared_ptr<pv::data::DecoderStack> decoder_stack = decoder_model->getDecoderStack();
if (decoder_stack) {
uint64_t offset = _view.offset() * (decoder_stack->samplerate() * _view.scale());
std::map<const pv::data::decode::Row, bool> rows = decoder_stack->get_rows_lshow();
int column = _model_proxy.filterKeyColumn();
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
if ((*i).second && column-- == 0) {
row_index = decoder_stack->get_annotation_index((*i).first, offset);
break;
}
}
QModelIndex index = _model_proxy.mapToSource(_model_proxy.index(row_index, _model_proxy.filterKeyColumn()));
if(index.isValid()){
_table_view->scrollTo(index);
_table_view->setCurrentIndex(index);
pv::data::decode::Annotation ann;
decoder_stack->list_annotation(ann, index.column(), index.row());
const std::vector< boost::shared_ptr<pv::view::DecodeTrace> > decode_sigs(
_session.get_decode_signals());
BOOST_FOREACH(boost::shared_ptr<pv::view::DecodeTrace> d, decode_sigs) {
d->decoder()->set_mark_index(-1);
}
decoder_stack->set_mark_index((ann.start_sample()+ann.end_sample())/2);
_view.set_all_update(true);
_view.update();
}
}
}
void ProtocolDock::search_pre()
{
search_update();
@@ -707,7 +797,8 @@ void ProtocolDock::search_update()
QProgressDialog dlg(tr("Searching..."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;

View File

@@ -52,6 +52,10 @@ namespace data {
class DecoderModel;
}
namespace view {
class View;
}
namespace dock {
class ProtocolDock : public QScrollArea
@@ -62,10 +66,12 @@ public:
static const uint64_t ProgressRows = 100000;
public:
ProtocolDock(QWidget *parent, SigSession &session);
ProtocolDock(QWidget *parent, view::View &view, SigSession &session);
~ProtocolDock();
void del_all_protocol();
bool sel_protocol(QString name);
void add_protocol(bool silent);
protected:
void paintEvent(QPaintEvent *);
@@ -82,6 +88,7 @@ private slots:
void set_model();
void update_model();
void export_table_view();
void nav_table_view();
void item_clicked(const QModelIndex &index);
void column_resize(int index, int old_size, int new_size);
void search_pre();
@@ -96,6 +103,7 @@ private:
private:
SigSession &_session;
view::View &_view;
QSortFilterProxyModel _model_proxy;
double _cur_search_index;
QStringList _str_list;
@@ -124,10 +132,13 @@ private:
QPushButton *_dn_set_button;
QPushButton *_dn_save_button;
QPushButton *_dn_nav_button;
mutable boost::mutex _search_mutex;
bool _search_edited;
bool _searching;
bool _add_silent;
};
} // namespace dock

View File

@@ -55,8 +55,6 @@ SearchDock::SearchDock(QWidget *parent, View &view, SigSession &session) :
_session(session),
_view(view)
{
_pattern = "X X X X X X X X X X X X X X X X";
connect(&_pre_button, SIGNAL(clicked()),
this, SLOT(on_previous()));
connect(&_nxt_button, SIGNAL(clicked()),
@@ -113,14 +111,25 @@ void SearchDock::paintEvent(QPaintEvent *)
void SearchDock::on_previous()
{
bool ret;
uint64_t last_pos;
uint8_t *data;
int unit_size;
uint64_t length;
QString value = _search_value->text();
search_previous(value);
int64_t last_pos;
bool last_hit;
const boost::shared_ptr<data::Snapshot> snapshot(_session.get_snapshot(SR_CHANNEL_LOGIC));
assert(snapshot);
const boost::shared_ptr<data::LogicSnapshot> logic_snapshot = boost::dynamic_pointer_cast<data::LogicSnapshot>(snapshot);
if (!logic_snapshot || logic_snapshot->empty()) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
msg.mBox()->setInformativeText(tr("No Sample data!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
return;
}
const int64_t end = logic_snapshot->get_sample_count() - 1;
last_pos = _view.get_search_pos();
last_hit = _view.get_search_hit();
if (last_pos == 0) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
@@ -130,43 +139,34 @@ void SearchDock::on_previous()
msg.exec();
return;
} else {
data = (uint8_t*)_session.get_buf(unit_size, length);
if (data == NULL) {
QFuture<void> future;
future = QtConcurrent::run([&]{
last_pos -= last_hit;
ret = logic_snapshot->pattern_search(0, end, false, last_pos, _pattern);
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Search Previous..."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
watcher.setFuture(future);
dlg.exec();
if (!ret) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
msg.mBox()->setInformativeText(tr("No Sample data!"));
msg.mBox()->setInformativeText(tr("Pattern not found!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
return;
} else {
QFuture<void> future;
future = QtConcurrent::run([&]{
ret = search_value(data, unit_size, length, last_pos, 1, value);
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Search Previous..."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
watcher.setFuture(future);
dlg.exec();
if (!ret) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
msg.mBox()->setInformativeText(tr("Pattern ") + value + tr(" not found!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
return;
} else {
_view.set_search_pos(last_pos);
}
_view.set_search_pos(last_pos, true);
}
}
}
@@ -174,15 +174,24 @@ void SearchDock::on_previous()
void SearchDock::on_next()
{
bool ret;
uint64_t last_pos;
int unit_size;
uint64_t length;
uint8_t *data = (uint8_t*)_session.get_buf(unit_size, length);
QString value = _search_value->text();
search_previous(value);
int64_t last_pos;
const boost::shared_ptr<data::Snapshot> snapshot(_session.get_snapshot(SR_CHANNEL_LOGIC));
assert(snapshot);
const boost::shared_ptr<data::LogicSnapshot> logic_snapshot = boost::dynamic_pointer_cast<data::LogicSnapshot>(snapshot);
last_pos = _view.get_search_pos();
if (last_pos == length - 1) {
if (!logic_snapshot || logic_snapshot->empty()) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
msg.mBox()->setInformativeText(tr("No Sample data!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
return;
}
const int64_t end = logic_snapshot->get_sample_count() - 1;
last_pos = _view.get_search_pos() + _view.get_search_hit();
if (last_pos >= end) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
msg.mBox()->setInformativeText(tr("Search cursor at the end position!"));
@@ -191,180 +200,58 @@ void SearchDock::on_next()
msg.exec();
return;
} else {
if (data == NULL) {
QFuture<void> future;
future = QtConcurrent::run([&]{
ret = logic_snapshot->pattern_search(0, end, true, last_pos, _pattern);
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Search Next..."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
watcher.setFuture(future);
dlg.exec();
if (!ret) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
msg.mBox()->setInformativeText(tr("No Sample data!"));
msg.mBox()->setInformativeText(tr("Pattern not found!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
return;
} else {
QFuture<void> future;
future = QtConcurrent::run([&]{
ret = search_value(data, unit_size, length, last_pos, 0, value);
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Search Next..."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
watcher.setFuture(future);
dlg.exec();
if (!ret) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
msg.mBox()->setInformativeText(tr("Pattern ") + value + tr(" not found!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
return;
} else {
_view.set_search_pos(last_pos);
}
_view.set_search_pos(last_pos, true);
}
}
}
void SearchDock::on_set()
{
dialogs::Search dlg(this, _session.get_device(), _pattern);
dialogs::Search dlg(this, _session, _pattern);
if (dlg.exec()) {
_pattern = dlg.get_pattern();
_pattern.remove(QChar(' '), Qt::CaseInsensitive);
_pattern = _pattern.toUpper();
_search_value->setText(_pattern);
QFontMetrics fm = this->fontMetrics();
_search_value->setFixedWidth(fm.width(_pattern)+_search_button->width()+20);
}
}
bool SearchDock::search_value(const uint8_t *data, int unit_size, uint64_t length, uint64_t& pos, bool left, QString value)
{
QByteArray pattern = value.toUtf8();
int i = 0;
uint64_t match_pos = left ? pos - 1 : pos + 1;
bool part_match = false;
int match_bits = unit_size * 8 - 1;
bool unmatch = false;
while(i <= match_bits) {
unmatch = false;
uint64_t pattern_mask = 1ULL << i;
if (pattern[match_bits - i] == 'X') {
part_match = true;
} else if (pattern[match_bits - i] == '0') {
//while((match_pos >= 0 && left) || (match_pos < length && !left)) {
while(left || (match_pos < length && !left)) {
if (0 == ((*(uint64_t *)(data + match_pos * unit_size) & pattern_mask) != 0)) {
part_match = true;
break;
} else if ((match_pos == 0 && left) || (match_pos == length - 1 && !left)) {
unmatch = true;
part_match = false;
break;
} else if (part_match) {
unmatch = true;
match_pos = left ? match_pos - 1 : match_pos + 1;
i = 0;
break;
} else if (!part_match) {
match_pos = left ? match_pos - 1 : match_pos + 1;
}
}
} else if (pattern[match_bits - i] == '1') {
//while((match_pos >= 0 && left) || (match_pos < length && !left)) {
while(left || (match_pos < length && !left)) {
if (1 == ((*(uint64_t *)(data + match_pos * unit_size) & pattern_mask) != 0)) {
part_match = true;
break;
} else if ((match_pos == 0 && left) || (match_pos == length - 1 && !left)) {
unmatch = true;
part_match = false;
break;
} else if (part_match) {
unmatch = true;
match_pos = left ? match_pos - 1 : match_pos + 1;
i = 0;
break;
} else if (!part_match) {
match_pos = left ? match_pos - 1 : match_pos + 1;
}
}
}else if (pattern[match_bits - i] == 'R') {
while((match_pos > 0 && left) || (match_pos < length && !left)) {
if (1 == ((*(uint64_t *)(data + match_pos * unit_size) & pattern_mask) != 0) &&
0 == ((*(uint64_t *)(data + (match_pos - 1) * unit_size) & pattern_mask) != 0)) {
part_match = true;
break;
} else if ((match_pos == 1 && left) || (match_pos == length - 1 && !left)) {
unmatch = true;
part_match = false;
break;
} else if (part_match) {
unmatch = true;
match_pos = left ? match_pos - 1 : match_pos + 1;
i = 0;
break;
} else if (!part_match) {
match_pos = left ? match_pos - 1 : match_pos + 1;
}
}
} else if (pattern[match_bits - i] == 'F') {
while((match_pos > 0 && left) || (match_pos < length && !left)) {
if (0 == ((*(uint64_t *)(data + match_pos * unit_size) & pattern_mask) != 0) &&
1 == ((*(uint64_t *)(data + (match_pos - 1) * unit_size) & pattern_mask) != 0)) {
part_match = true;
break;
} else if ((match_pos == 1 && left) || (match_pos == length - 1 && !left)) {
unmatch = true;
part_match = false;
break;
} else if (part_match) {
unmatch = true;
match_pos = left ? match_pos - 1 : match_pos + 1;
i = 0;
break;
} else if (!part_match) {
match_pos = left ? match_pos - 1 : match_pos + 1;
}
}
} else if (pattern[match_bits - i] == 'C') {
while((match_pos > 0 && left) || (match_pos < length && !left)) {
if (((*(uint64_t *)(data + match_pos * unit_size) & pattern_mask) != 0) !=
((*(uint64_t *)(data + (match_pos - 1) * unit_size) & pattern_mask) != 0)) {
part_match = true;
break;
} else if ((match_pos == 1 && left) || (match_pos == length - 1 && !left)) {
unmatch = true;
part_match = false;
break;
} else if (part_match) {
unmatch = true;
match_pos = left ? match_pos - 1 : match_pos + 1;
i = 0;
break;
} else if (!part_match) {
match_pos = left ? match_pos - 1 : match_pos + 1;
}
}
QString search_label;
for (auto& iter:_pattern) {
iter.second.remove(QChar(' '), Qt::CaseInsensitive);
iter.second = iter.second.toUpper();
search_label.push_back(iter.second);
// if (iter.second != "XXXXXXXXXXXXXXXX") {
// search_label.push_back(QString::number(iter.first));
// search_label.push_back("/");
// }
}
if (unmatch && !part_match)
break;
else if ((!unmatch && part_match) || !part_match)
i++;
_search_value->setText(search_label);
QFontMetrics fm = this->fontMetrics();
_search_value->setFixedWidth(fm.width(search_label)+_search_button->width()+20);
}
pos = match_pos;
return !unmatch;
}
} // namespace dock

View File

@@ -70,22 +70,15 @@ public:
void paintEvent(QPaintEvent *);
signals:
void search_previous(QString);
void search_next(QString);
public slots:
void on_previous();
void on_next();
void on_set();
private:
bool search_value(const uint8_t* data, int unit_size, uint64_t length,
uint64_t& pos, bool left, QString value);
private:
SigSession &_session;
view::View &_view;
QString _pattern;
std::map<uint16_t, QString> _pattern;
QPushButton _pre_button;
QPushButton _nxt_button;

View File

@@ -57,10 +57,10 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) :
position_label = new QLabel(tr("Trigger Position: "), _widget);
position_spinBox = new QSpinBox(_widget);
position_spinBox->setRange(MinTrigPosition, 99);
position_spinBox->setRange(MinTrigPosition, DS_MAX_TRIG_PERCENT);
position_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
position_slider = new QSlider(Qt::Horizontal, _widget);
position_slider->setRange(MinTrigPosition, 99);
position_slider->setRange(MinTrigPosition, DS_MAX_TRIG_PERCENT);
connect(position_slider, SIGNAL(valueChanged(int)), position_spinBox, SLOT(setValue(int)));
connect(position_spinBox, SIGNAL(valueChanged(int)), position_slider, SLOT(setValue(int)));
@@ -93,10 +93,10 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) :
_value0_lineEdit->setInputMask("X X X X X X X X X X X X X X X X");
_value0_lineEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
_value0_lineEdit_list.push_back(_value0_lineEdit);
QSpinBox *_count0_spinBox = new QSpinBox(_widget);
_count0_spinBox->setRange(1, INT32_MAX);
_count0_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
_count0_spinBox_list.push_back(_count0_spinBox);
QSpinBox *_count_spinBox = new QSpinBox(_widget);
_count_spinBox->setRange(1, INT32_MAX);
_count_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
_count_spinBox_list.push_back(_count_spinBox);
QComboBox *_inv0_comboBox = new QComboBox(_widget);
_inv0_comboBox->addItem(tr("=="));
_inv0_comboBox->addItem(tr("!="));
@@ -109,33 +109,38 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) :
_value1_lineEdit->setInputMask("X X X X X X X X X X X X X X X X");
_value1_lineEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
_value1_lineEdit_list.push_back(_value1_lineEdit);
QSpinBox *_count1_spinBox = new QSpinBox(_widget);
_count1_spinBox->setRange(1, INT32_MAX);
_count1_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
_count1_spinBox_list.push_back(_count1_spinBox);
QComboBox *_inv1_comboBox = new QComboBox(_widget);
_inv1_comboBox->addItem(tr("=="));
_inv1_comboBox->addItem(tr("!="));
_inv1_comboBox_list.push_back(_inv1_comboBox);
QCheckBox *_contiguous_checkbox = new QCheckBox(_widget);
_contiguous_checkbox_list.push_back(_contiguous_checkbox);
QLabel *value_exp_label = new QLabel("1 1 1 1 1 1\n5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ", _widget);
QLabel *inv_exp_label = new QLabel("Inv", _widget);
QLabel *count_exp_label = new QLabel("Counter", _widget);
QLabel *inv_exp_label = new QLabel(tr("Inv"), _widget);
QLabel *count_exp_label = new QLabel(tr("Counter"), _widget);
value_exp_label->setFont(font);
QVBoxLayout *stage_layout = new QVBoxLayout();
QGridLayout *stage_glayout = new QGridLayout();
stage_glayout->setVerticalSpacing(5);
stage_glayout->addWidget(value_exp_label, 1, 0);
stage_glayout->addWidget(inv_exp_label, 1, 1);
stage_glayout->addWidget(count_exp_label, 1, 2);
stage_glayout->addWidget(_value0_lineEdit, 2, 0);
stage_glayout->addWidget(_inv0_comboBox, 2, 1);
stage_glayout->addWidget(_count0_spinBox, 2, 2);
stage_glayout->addWidget(_logic_comboBox, 2, 3);
stage_glayout->addWidget(_logic_comboBox, 2, 2);
stage_glayout->addWidget(_value1_lineEdit, 3, 0);
stage_glayout->addWidget(_inv1_comboBox, 3, 1);
stage_glayout->addWidget(_count1_spinBox, 3, 2);
stage_glayout->addWidget(new QLabel(_widget), 4, 0);
stage_glayout->addWidget(new QLabel(tr("Contiguous")), 5, 1, 1, 2);
stage_glayout->addWidget(_contiguous_checkbox, 5, 0, 1, 1, Qt::AlignRight);
stage_glayout->addWidget(count_exp_label, 6, 1, 1, 2);
stage_glayout->addWidget(_count_spinBox, 6, 0);
stage_layout->addLayout(stage_glayout);
stage_layout->addSpacing(20);
stage_layout->addWidget(new QLabel(tr("X: Don't care\n0: Low level\n1: High level\nR: Rising edge\nF: Falling edge\nC: Rising/Falling edge")));
@@ -189,9 +194,9 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) :
_serial_value_lineEdit->setInputMask("X X X X X X X X X X X X X X X X");
_serial_value_lineEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
_serial_vcnt_spinBox = new QSpinBox(_widget);
_serial_vcnt_spinBox->setRange(1, INT32_MAX);
_serial_vcnt_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
_serial_bits_comboBox = new QComboBox(_widget);
for(i = 1; i <= 16; i++)
_serial_bits_comboBox->addItem(QString::number(i));
QLabel *serial_value_exp_label = new QLabel("1 1 1 1 1 1\n5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0", _widget);
serial_value_exp_label->setFont(font);
@@ -211,11 +216,11 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) :
serial_glayout->addWidget(new QLabel(_widget), 5, 0, 1, 5);
serial_glayout->addWidget(_serial_data_lable, 6, 0);
serial_glayout->addWidget(_serial_data_comboBox, 6, 1);
serial_glayout->addWidget(new QLabel(tr("counter"), _widget), 6, 4);
serial_glayout->addWidget(_serial_value_lable, 7, 0);
serial_glayout->addWidget(_serial_value_lineEdit, 7, 1, 1, 3);
serial_glayout->addWidget(_serial_vcnt_spinBox, 7, 4);
serial_glayout->addWidget(new QLabel(_widget), 7, 5);
serial_glayout->addWidget(new QLabel(tr("Data Bits"), _widget), 7, 0);
serial_glayout->addWidget(_serial_bits_comboBox, 7, 1);
serial_glayout->addWidget(_serial_value_lable, 8, 0);
serial_glayout->addWidget(_serial_value_lineEdit, 8, 1, 1, 3);
serial_layout->addLayout(serial_glayout);
serial_layout->addSpacing(20);
serial_layout->addWidget(new QLabel(tr("X: Don't care\n0: Low level\n1: High level\nR: Rising edge\nF: Falling edge\nC: Rising/Falling edge")));
@@ -343,27 +348,18 @@ void TriggerDock::value_changed()
sc->setText(sc->text().toUpper());
}
void TriggerDock::device_change()
void TriggerDock::device_updated()
{
uint64_t max_hd_depth;
uint64_t hw_depth;
bool stream = false;
uint8_t maxRange;
uint64_t sample_limits;
GVariant *gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_MAX_LOGIC_SAMPLELIMITS);
GVariant *gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_HW_DEPTH);
if (gvar != NULL) {
max_hd_depth = g_variant_get_uint64(gvar);
hw_depth = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
if (_session.get_device()->dev_inst()->mode == LOGIC) {
sample_limits = _session.get_device()->get_sample_limit();
if (max_hd_depth >= sample_limits)
maxRange = 99;
else
maxRange = max_hd_depth*70 / sample_limits;
position_spinBox->setRange(MinTrigPosition, maxRange);
position_slider->setRange(MinTrigPosition, maxRange);
gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_STREAM);
if (gvar != NULL) {
@@ -371,6 +367,16 @@ void TriggerDock::device_change()
g_variant_unref(gvar);
}
sample_limits = _session.get_device()->get_sample_limit();
if (stream)
maxRange = 1;
else if (hw_depth >= sample_limits)
maxRange = DS_MAX_TRIG_PERCENT;
else
maxRange = ceil(hw_depth * DS_MAX_TRIG_PERCENT / sample_limits);
position_spinBox->setRange(MinTrigPosition, maxRange);
position_slider->setRange(MinTrigPosition, maxRange);
if (_session.get_device()->name().contains("virtual") ||
stream) {
simple_radioButton->setChecked(true);
@@ -397,7 +403,7 @@ bool TriggerDock::commit_trigger()
ds_trigger_set_mode(SERIAL_TRIGGER);
// trigger stage update
ds_trigger_set_stage(stages_comboBox->currentText().toInt());
ds_trigger_set_stage(stages_comboBox->currentText().toInt() - 1);
int i;
// trigger value update
@@ -410,36 +416,36 @@ bool TriggerDock::commit_trigger()
} else if(_adv_tabWidget->currentIndex() == 1){
ds_trigger_stage_set_value(0, TriggerProbes,
_serial_start_lineEdit->text().toLocal8Bit().data(),
_value1_lineEdit_list.at(0)->text().toLocal8Bit().data());
_serial_stop_lineEdit->text().toLocal8Bit().data());
ds_trigger_stage_set_value(1, TriggerProbes,
_serial_stop_lineEdit->text().toLocal8Bit().data(),
_value1_lineEdit_list.at(1)->text().toLocal8Bit().data());
ds_trigger_stage_set_value(2, TriggerProbes,
_serial_edge_lineEdit->text().toLocal8Bit().data(),
_value1_lineEdit_list.at(2)->text().toLocal8Bit().data());
_value1_lineEdit_list.at(1)->text().toLocal8Bit().data());
//_serial_data_comboBox
const int data_channel = _serial_data_comboBox->currentText().toInt();
char channel[31];
for(i = 0; i < 31; i++){
if (i == (30 - 2*data_channel))
channel[i] = '1';
else if (i%2 == 0)
channel[i] = '0';
else if (i%2 == 0)
channel[i] = 'X';
else
channel[i] = ' ';
}
ds_trigger_stage_set_value(3, TriggerProbes,
ds_trigger_stage_set_value(2, TriggerProbes,
channel,
_value1_lineEdit_list.at(3)->text().toLocal8Bit().data());
ds_trigger_stage_set_value(4, TriggerProbes,
_value1_lineEdit_list.at(2)->text().toLocal8Bit().data());
ds_trigger_stage_set_value(STriggerDataStage, TriggerProbes,
_serial_value_lineEdit->text().toLocal8Bit().data(),
_value1_lineEdit_list.at(4)->text().toLocal8Bit().data());
_value1_lineEdit_list.at(3)->text().toLocal8Bit().data());
}
// trigger logic update
for (i = 0; i < stages_comboBox->currentText().toInt(); i++) {
const char logic = (_contiguous_checkbox_list.at(i)->isChecked() << 1) +
_logic_comboBox_list.at(i)->currentIndex();
ds_trigger_stage_set_logic(i, TriggerProbes,
_logic_comboBox_list.at(i)->currentIndex());
logic);
}
// trigger inv update
@@ -453,12 +459,15 @@ bool TriggerDock::commit_trigger()
if (_adv_tabWidget->currentIndex() == 0) {
for (i = 0; i < stages_comboBox->currentText().toInt(); i++) {
ds_trigger_stage_set_count(i, TriggerProbes,
_count0_spinBox_list.at(i)->value() - 1,
_count1_spinBox_list.at(i)->value() - 1);
_count_spinBox_list.at(i)->value(),
0);
}
} else if(_adv_tabWidget->currentIndex() == 1){
ds_trigger_stage_set_count(4, TriggerProbes,
_serial_vcnt_spinBox->value() - 1,
ds_trigger_stage_set_count(1, TriggerProbes,
1,
0);
ds_trigger_stage_set_count(3, TriggerProbes,
_serial_bits_comboBox->currentText().toInt() - 1,
0);
}
return 1;
@@ -475,34 +484,37 @@ void TriggerDock::init()
QJsonObject TriggerDock::get_session()
{
QJsonObject trigSes;
trigSes["triggerMode"] = adv_radioButton->isChecked() ? 1 : 0;
trigSes["advTriggerMode"] = adv_radioButton->isChecked();
trigSes["triggerPos"] = position_slider->value();
trigSes["triggerStages"] = stages_comboBox->currentIndex();
trigSes["triggerSerial"] = _adv_tabWidget->currentIndex();
trigSes["triggerTab"] = _adv_tabWidget->currentIndex();
for (int i = 0; i < stages_comboBox->count(); i++) {
QString value0_str = "triggerValue0" + QString::number(i);
QString inv0_str = "triggerInv0" + QString::number(i);
QString count0_str = "triggerCount0" + QString::number(i);
QString value1_str = "triggerValue1" + QString::number(i);
QString inv1_str = "triggerInv1" + QString::number(i);
QString count1_str = "triggerCount1" + QString::number(i);
QString logic_str = "triggerLogic" + QString::number(i);
QString value0_str = "stageTriggerValue0" + QString::number(i);
QString inv0_str = "stageTriggerInv0" + QString::number(i);
QString value1_str = "stageTriggerValue1" + QString::number(i);
QString inv1_str = "stageTriggerInv1" + QString::number(i);
QString logic_str = "stageTriggerLogic" + QString::number(i);
QString count_str = "stageTriggerCount" + QString::number(i);
QString conti_str = "stageTriggerContiguous" + QString::number(i);
trigSes[value0_str] = _value0_lineEdit_list.at(i)->text();
trigSes[value1_str] = _value1_lineEdit_list.at(i)->text();
trigSes[inv0_str] = _inv0_comboBox_list.at(i)->currentIndex();
trigSes[inv1_str] = _inv1_comboBox_list.at(i)->currentIndex();
trigSes[count0_str] = _count0_spinBox_list.at(i)->value();
trigSes[count1_str] = _count1_spinBox_list.at(i)->value();
trigSes[logic_str] = _logic_comboBox_list.at(i)->currentIndex();
trigSes[count_str] = _count_spinBox_list.at(i)->value();
trigSes[conti_str] = _contiguous_checkbox_list.at(i)->isChecked();
}
trigSes["triggerStart"] = _serial_start_lineEdit->text();
trigSes["triggerStop"] = _serial_stop_lineEdit->text();
trigSes["triggerClock"] = _serial_edge_lineEdit->text();
trigSes["triggerChannel"] = _serial_data_comboBox->currentIndex();
trigSes["triggerData"] = _serial_value_lineEdit->text();
trigSes["triggerVcnt"] = _serial_vcnt_spinBox->value();
trigSes["serialTriggerStart"] = _serial_start_lineEdit->text();
trigSes["serialTriggerStop"] = _serial_stop_lineEdit->text();
trigSes["serialTriggerClock"] = _serial_edge_lineEdit->text();
trigSes["serialTriggerChannel"] = _serial_data_comboBox->currentIndex();
trigSes["serialTriggerData"] = _serial_value_lineEdit->text();
trigSes["serialTriggerBits"] = _serial_bits_comboBox->currentIndex();
return trigSes;
}
@@ -511,35 +523,38 @@ void TriggerDock::set_session(QJsonObject ses)
{
position_slider->setValue(ses["triggerPos"].toDouble());
stages_comboBox->setCurrentIndex(ses["triggerStages"].toDouble());
_adv_tabWidget->setCurrentIndex(ses["triggerSerial"].toDouble());
if (ses["triggerMode"].toDouble() == 0)
simple_radioButton->click();
else
_adv_tabWidget->setCurrentIndex(ses["triggerTab"].toDouble());
if (ses["advTriggerMode"].toBool())
adv_radioButton->click();
else
simple_radioButton->click();
for (int i = 0; i < stages_comboBox->count(); i++) {
QString value0_str = "triggerValue0" + QString::number(i);
QString inv0_str = "triggerInv0" + QString::number(i);
QString count0_str = "triggerCount0" + QString::number(i);
QString value1_str = "triggerValue1" + QString::number(i);
QString inv1_str = "triggerInv1" + QString::number(i);
QString count1_str = "triggerCount1" + QString::number(i);
QString logic_str = "triggerLogic" + QString::number(i);
QString value0_str = "stageTriggerValue0" + QString::number(i);
QString inv0_str = "stageTriggerInv0" + QString::number(i);
QString value1_str = "stageTriggerValue1" + QString::number(i);
QString inv1_str = "stageTriggerInv1" + QString::number(i);
QString logic_str = "stageTriggerLogic" + QString::number(i);
QString count_str = "stageTriggerCount" + QString::number(i);
QString conti_str = "stageTriggerContiguous" + QString::number(i);
_value0_lineEdit_list.at(i)->setText(ses[value0_str].toString());
_value1_lineEdit_list.at(i)->setText(ses[value1_str].toString());
_inv0_comboBox_list.at(i)->setCurrentIndex(ses[inv0_str].toDouble());
_inv1_comboBox_list.at(i)->setCurrentIndex(ses[inv1_str].toDouble());
_count0_spinBox_list.at(i)->setValue(ses[count0_str].toDouble());
_count1_spinBox_list.at(i)->setValue(ses[count1_str].toDouble());
_logic_comboBox_list.at(i)->setCurrentIndex(ses[logic_str].toDouble());
_count_spinBox_list.at(i)->setValue(ses[count_str].toDouble());
_contiguous_checkbox_list.at(i)->setChecked(ses[conti_str].toBool());
}
_serial_start_lineEdit->setText(ses["triggerStart"].toString());
_serial_stop_lineEdit->setText(ses["triggerStop"].toString());
_serial_edge_lineEdit->setText(ses["triggerClock"].toString());
_serial_data_comboBox->setCurrentIndex(ses["triggerChannel"].toDouble());
_serial_value_lineEdit->setText(ses["triggerData"].toString());
_serial_vcnt_spinBox->setValue(ses["triggerVcnt"].toDouble());
_serial_start_lineEdit->setText(ses["serialTriggerStart"].toString());
_serial_stop_lineEdit->setText(ses["serialTriggerStop"].toString());
_serial_edge_lineEdit->setText(ses["serialTriggerClock"].toString());
_serial_data_comboBox->setCurrentIndex(ses["serialTriggerChannel"].toDouble());
_serial_value_lineEdit->setText(ses["serialTriggerData"].toString());
_serial_bits_comboBox->setCurrentIndex(ses["serialTriggerBits"].toDouble());
}
} // namespace dock

View File

@@ -32,6 +32,7 @@
#include <QLineEdit>
#include <QSpinBox>
#include <QGroupBox>
#include <QCheckBox>
#include <QTableWidget>
#include <QJsonObject>
@@ -84,7 +85,7 @@ public slots:
void value_changed();
void device_change();
void device_updated();
private:
@@ -109,11 +110,11 @@ private:
QVector <QLabel *> _mu_label_list;
QVector <QComboBox *> _logic_comboBox_list;
QVector <QLineEdit *> _value0_lineEdit_list;
QVector <QSpinBox *> _count0_spinBox_list;
QVector <QSpinBox *> _count_spinBox_list;
QVector <QComboBox *> _inv0_comboBox_list;
QVector <QLineEdit *> _value1_lineEdit_list;
QVector <QSpinBox *> _count1_spinBox_list;
QVector <QComboBox *> _inv1_comboBox_list;
QVector <QCheckBox *> _contiguous_checkbox_list;
QTabWidget *_adv_tabWidget;
QGroupBox *_serial_groupBox;
@@ -128,7 +129,7 @@ private:
QLabel *_serial_value_lable;
QLineEdit *_serial_value_lineEdit;
QLabel *_serial_vcnt_lable;
QSpinBox *_serial_vcnt_spinBox;
QComboBox *_serial_bits_comboBox;
};
} // namespace dock

View File

@@ -46,7 +46,8 @@ MainFrame::MainFrame(DeviceManager &device_manager,
setAttribute(Qt::WA_TranslucentBackground);
// Make this a borderless window which can't
// be resized or moved via the window system
setWindowFlags(Qt::FramelessWindowHint);
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
setMinimumHeight(680);
setMinimumWidth(800);
//resize(1024, 768);
@@ -58,6 +59,7 @@ MainFrame::MainFrame(DeviceManager &device_manager,
setWindowIcon(icon);
_moving = false;
_draging = false;
_startPos = None;
_freezing = false;
_minimized = false;
@@ -118,24 +120,24 @@ MainFrame::MainFrame(DeviceManager &device_manager,
_layout->addWidget(_bottom_right, 2, 2);
connect(&_timer, SIGNAL(timeout()), this, SLOT(unfreezing()));
readSettings();
connect(_mainWindow, SIGNAL(prgRate(int)), this, SLOT(setTaskbarProgress(int)));
//readSettings();
}
void MainFrame::changeEvent(QEvent* event)
{
QFrame::changeEvent(event);
QWindowStateChangeEvent* win_event = static_cast< QWindowStateChangeEvent* >(event);
if(win_event->type() == QEvent::WindowStateChange) {
if (win_event->oldState() & Qt::WindowMinimized) {
if (_minimized) {
readSettings();
_minimized = false;
}
QWindowStateChangeEvent* win_event = static_cast< QWindowStateChangeEvent* >(event);
if(win_event->type() == QEvent::WindowStateChange) {
if (win_event->oldState() & Qt::WindowMinimized) {
if (_minimized) {
readSettings();
_minimized = false;
}
}
}
}
void MainFrame::resizeEvent(QResizeEvent *event)
{
QFrame::resizeEvent(event);
@@ -346,6 +348,7 @@ void MainFrame::writeSettings()
QSettings settings;
settings.beginGroup("MainFrame");
settings.setValue("isMax", isMaximized());
settings.setValue("size", size());
settings.setValue("pos", pos() +
QPoint(geometry().left() - frameGeometry().left(), frameGeometry().right() - geometry().right()));
@@ -357,13 +360,28 @@ void MainFrame::readSettings()
QSettings settings;
QDesktopWidget* desktopWidget = QApplication::desktop();
QRect deskRect = desktopWidget->availableGeometry();
QPoint default_upleft = QPoint((deskRect.width() - minWidth)/2, (deskRect.height() - minHeight)/2);
QSize default_size = QSize(minWidth, minHeight);
settings.beginGroup("MainFrame");
QSize size = settings.value("size", QSize(minWidth, minHeight)).toSize();
QPoint pos = settings.value("pos", QPoint((deskRect.width() - minWidth)/2, (deskRect.height() - minHeight)/2)).toPoint();
bool isMax = settings.value("isMax", false).toBool();
QSize size = settings.value("size", default_size).toSize();
QPoint pos = settings.value("pos", default_upleft).toPoint();
settings.endGroup();
if (size == deskRect.size()) {
// check the restored position is vavlid or not
int i = 0;
for (; i < desktopWidget->screenCount(); i++) {
deskRect = desktopWidget->availableGeometry(i);
if (deskRect.contains(pos))
break;
}
if (i >= desktopWidget->screenCount())
pos = default_upleft;
if (isMax) {
resize(default_size);
move(default_upleft);
_titleBar->showMaxRestore();
} else {
resize(size);

View File

@@ -64,7 +64,7 @@ public:
MainFrame(DeviceManager &device_manager,
const char *open_file_name = NULL);
void showMaxRestore();
void readSettings();
protected:
void changeEvent(QEvent* event);
@@ -83,7 +83,6 @@ private:
void show_border();
void writeSettings();
void readSettings();
private:
toolbars::TitleBar *_titleBar;

View File

@@ -106,9 +106,6 @@ MainWindow::MainWindow(DeviceManager &device_manager,
Qt::QueuedConnection,
Q_ARG(QString, s));
}
test_timer_linked = false;
test_timer.stop();
test_timer.setSingleShot(true);
}
void MainWindow::setup_ui()
@@ -140,8 +137,10 @@ void MainWindow::setup_ui()
SLOT(on_search(bool)));
connect(_file_bar, SIGNAL(load_file(QString)), this,
SLOT(load_file(QString)));
connect(_file_bar, SIGNAL(save()), this,
connect(_file_bar, SIGNAL(on_save()), this,
SLOT(on_save()));
connect(_file_bar, SIGNAL(on_export()), this,
SLOT(on_export()));
connect(_file_bar, SIGNAL(on_screenShot()), this,
SLOT(on_screenShot()), Qt::QueuedConnection);
connect(_file_bar, SIGNAL(load_session(QString)), this,
@@ -149,17 +148,6 @@ void MainWindow::setup_ui()
connect(_file_bar, SIGNAL(store_session(QString)), this,
SLOT(store_session(QString)));
#ifdef ENABLE_DECODE
// protocol dock
_protocol_dock=new QDockWidget(tr("Protocol"),this);
_protocol_dock->setFeatures(QDockWidget::DockWidgetMovable);
_protocol_dock->setAllowedAreas(Qt::RightDockWidgetArea);
_protocol_dock->setVisible(false);
//dock::ProtocolDock *_protocol_widget = new dock::ProtocolDock(_protocol_dock, _session);
_protocol_widget = new dock::ProtocolDock(_protocol_dock, _session);
_protocol_dock->setWidget(_protocol_widget);
qDebug() << "Protocol decoder enabled!\n";
#endif
// trigger dock
_trigger_dock=new QDockWidget(tr("Trigger Setting..."),this);
_trigger_dock->setFeatures(QDockWidget::DockWidgetMovable);
@@ -189,14 +177,13 @@ void MainWindow::setup_ui()
connect(_sampling_bar, SIGNAL(instant_stop()), this,
SLOT(instant_stop()));
connect(_sampling_bar, SIGNAL(sample_count_changed()), _trigger_widget,
SLOT(device_change()));
SLOT(device_updated()));
connect(_sampling_bar, SIGNAL(show_calibration()), _view,
SLOT(show_calibration()));
connect(_sampling_bar, SIGNAL(hide_calibration()), _view,
SLOT(hide_calibration()));
connect(_dso_trigger_widget, SIGNAL(set_trig_pos(int)), _view,
SLOT(set_trig_pos(int)));
connect(_protocol_widget, SIGNAL(protocol_updated()), _view, SLOT(signals_changed()));
setIconSize(QSize(40,40));
addToolBar(_sampling_bar);
@@ -205,6 +192,19 @@ void MainWindow::setup_ui()
addToolBar(_logo_bar);
// Setup the dockWidget
#ifdef ENABLE_DECODE
// protocol dock
_protocol_dock=new QDockWidget(tr("Protocol"),this);
_protocol_dock->setFeatures(QDockWidget::DockWidgetMovable);
_protocol_dock->setAllowedAreas(Qt::RightDockWidgetArea);
_protocol_dock->setVisible(false);
//dock::ProtocolDock *_protocol_widget = new dock::ProtocolDock(_protocol_dock, _session);
_protocol_widget = new dock::ProtocolDock(_protocol_dock, *_view, _session);
_protocol_dock->setWidget(_protocol_widget);
qDebug() << "Protocol decoder enabled!\n";
connect(_protocol_widget, SIGNAL(protocol_updated()), _view, SLOT(signals_changed()));
#endif
// measure dock
_measure_dock=new QDockWidget(tr("Measurement"),this);
_measure_dock->setFeatures(QDockWidget::DockWidgetMovable);
@@ -242,19 +242,24 @@ void MainWindow::setup_ui()
SLOT(device_attach()), Qt::QueuedConnection);
connect(&_session, SIGNAL(device_detach()), this,
SLOT(device_detach()), Qt::QueuedConnection);
connect(&_session, SIGNAL(test_data_error()), this,
SLOT(test_data_error()));
connect(&_session, SIGNAL(malloc_error()), this,
SLOT(malloc_error()));
connect(&_session, SIGNAL(hardware_connect_failed()), this,
SLOT(hardware_connect_failed()));
connect(&_session, SIGNAL(on_mode_change()), this,
connect(&_session, SIGNAL(session_error()), this,
SLOT(show_error()), Qt::QueuedConnection);
connect(&_session, SIGNAL(session_save()), this,
SLOT(session_save()));
connect(&_session, SIGNAL(data_updated()), _measure_widget,
SLOT(reCalc()));
connect(&_session, SIGNAL(repeat_resume()), this,
SLOT(repeat_resume()));
connect(_view, SIGNAL(cursor_update()), _measure_widget,
SLOT(cursor_update()));
connect(_view, SIGNAL(cursor_moving()), _measure_widget,
SLOT(cursor_moving()));
connect(_view, SIGNAL(cursor_moved()), _measure_widget,
SLOT(cursor_moved()));
SLOT(reCalc()));
connect(_view, SIGNAL(prgRate(int)), this, SIGNAL(prgRate(int)));
connect(_view, SIGNAL(update_device_list()),
this, SLOT(update_device_list()), Qt::DirectConnection);
// event filter
_view->installEventFilter(this);
@@ -272,10 +277,10 @@ void MainWindow::setup_ui()
// Populate the device list and select the initially selected device
_session.set_default_device(boost::bind(&MainWindow::session_error, this,
QString("Set Default Device failed"), _1));
QString(tr("Set Default Device failed")), _1));
update_device_list();
_session.start_hotplug_proc(boost::bind(&MainWindow::session_error, this,
QString("Hotplug failed"), _1));
QString(tr("Hotplug failed")), _1));
}
void MainWindow::session_error(
@@ -292,24 +297,45 @@ void MainWindow::update_device_list()
_session.stop_capture();
_view->reload();
_trigger_widget->device_change();
_trigger_widget->device_updated();
#ifdef ENABLE_DECODE
_protocol_widget->del_all_protocol();
#endif
_trig_bar->reload();
_sampling_bar->reload();
shared_ptr<pv::device::DevInst> selected_device = _session.get_device();
_device_manager.add_device(selected_device);
_sampling_bar->set_device_list(_device_manager.devices(), selected_device);
_session.init_signals();
if(dynamic_pointer_cast<pv::device::File>(selected_device)) {
shared_ptr<pv::device::File> file_dev;
if(file_dev = dynamic_pointer_cast<pv::device::File>(selected_device)) {
#ifdef ENABLE_DECODE
// load decoders
StoreSession ss(_session);
ss.load_decoders(_protocol_widget, file_dev->get_decoders());
#endif
// check version
if (selected_device->dev_inst()->mode == LOGIC) {
GVariant* gvar = selected_device->get_config(NULL, NULL, SR_CONF_FILE_VERSION);
if (gvar != NULL) {
int16_t version = g_variant_get_int16(gvar);
g_variant_unref(gvar);
if (version == 1) {
show_session_error(tr("Attension"),
tr("Current loading file has an old format. "
"This will lead to a slow loading speed. "
"Please resave it after loaded."));
}
}
}
// load data
const QString errorMessage(
QString("Failed to capture file data!"));
const QString infoMessage;
QString(tr("Failed to capture file data!")));
_session.start_capture(true, boost::bind(&MainWindow::session_error, this,
errorMessage, infoMessage));
errorMessage, _1));
}
if (!selected_device->name().contains("virtual")) {
@@ -332,31 +358,30 @@ void MainWindow::update_device_list()
_file_bar->set_settings_en(false);
_logo_bar->dsl_connected(false);
}
_sampling_bar->reload();
_view->status_clear();
_trigger_widget->init();
_dso_trigger_widget->init();
_measure_widget->reload();
}
void MainWindow::reload()
{
_trigger_widget->device_change();
_trigger_widget->device_updated();
_session.reload();
}
void MainWindow::mode_changed()
{
update_device_list();
_measure_widget->reload();
}
void MainWindow::load_file(QString file_name)
{
try {
//_session.set_file(file_name.toStdString());
if (strncmp(_session.get_device()->name().toLocal8Bit(), "virtual", 7))
session_save();
_session.set_file(file_name);
} catch(QString e) {
show_session_error(tr("Failed to load ") + file_name, e);
_session.set_default_device(boost::bind(&MainWindow::session_error, this,
QString("Set Default Device failed"), _1));
QString(tr("Set Default Device failed")), _1));
update_device_list();
return;
}
@@ -380,8 +405,10 @@ void MainWindow::device_attach()
_session.get_device()->device_updated();
//_session.stop_hot_plug_proc();
if (_session.get_capture_state() == SigSession::Running)
_session.stop_capture();
_session.set_repeating(false);
_session.stop_capture();
_sampling_bar->set_sampling(false);
_session.capture_state_changed(SigSession::Stopped);
struct sr_dev_driver **const drivers = sr_driver_list();
struct sr_dev_driver **driver;
@@ -390,8 +417,9 @@ void MainWindow::device_attach()
_device_manager.driver_scan(*driver);
_session.set_default_device(boost::bind(&MainWindow::session_error, this,
QString("Set Default Device failed"), _1));
QString(tr("Set Default Device failed")), _1));
update_device_list();
}
void MainWindow::device_detach()
@@ -399,8 +427,10 @@ void MainWindow::device_detach()
_session.get_device()->device_updated();
//_session.stop_hot_plug_proc();
if (_session.get_capture_state() == SigSession::Running)
_session.stop_capture();
_session.set_repeating(false);
_session.stop_capture();
_sampling_bar->set_sampling(false);
_session.capture_state_changed(SigSession::Stopped);
session_save();
_view->hide_calibration();
@@ -412,120 +442,143 @@ void MainWindow::device_detach()
_device_manager.driver_scan(*driver);
_session.set_default_device(boost::bind(&MainWindow::session_error, this,
QString("Set Default Device failed"), _1));
QString(tr("Set Default Device failed")), _1));
update_device_list();
}
void MainWindow::run_stop()
{
#ifdef TEST_MODE
if (!test_timer_linked) {
connect(&test_timer, SIGNAL(timeout()),
this, SLOT(run_stop()));
test_timer_linked = true;
}
#endif
switch(_session.get_capture_state()) {
case SigSession::Init:
case SigSession::Stopped:
if (_session.get_device()->dev_inst()->mode == DSO)
_view->show_trig_cursor(true);
else
_view->show_trig_cursor(false);
_view->update_sample(false);
commit_trigger(false);
_session.start_capture(false,
boost::bind(&MainWindow::session_error, this,
QString("Capture failed"), _1));
break;
case SigSession::Running:
_session.stop_capture();
break;
}
}
void MainWindow::instant_stop()
{
#ifdef TEST_MODE
if (!test_timer_linked) {
connect(&test_timer, SIGNAL(timeout()),
this, SLOT(instant_stop()));
test_timer_linked = true;
}
#endif
switch(_session.get_capture_state()) {
case SigSession::Init:
case SigSession::Stopped:
if (_session.get_device()->dev_inst()->mode == DSO)
_view->show_trig_cursor(true);
else
_view->show_trig_cursor(false);
_view->update_sample(true);
commit_trigger(true);
_session.start_capture(true,
_view->capture_init(false);
commit_trigger(false);
_session.start_capture(false,
boost::bind(&MainWindow::session_error, this,
QString("Capture failed"), _1));
QString(tr("Capture failed")), _1));
break;
case SigSession::Running:
_session.stop_capture();
break;
}
}
void MainWindow::test_data_error()
void MainWindow::instant_stop()
{
switch(_session.get_capture_state()) {
case SigSession::Init:
case SigSession::Stopped:
_view->capture_init(true);
commit_trigger(true);
_session.start_capture(true,
boost::bind(&MainWindow::session_error, this,
QString(tr("Capture failed")), _1));
break;
case SigSession::Running:
_session.stop_capture();
break;
}
}
void MainWindow::repeat_resume()
{
while(_view->session().get_capture_state() == SigSession::Running)
QCoreApplication::processEvents();
run_stop();
}
void MainWindow::show_error()
{
QString title;
QString details;
QString ch_status = "";
uint64_t error_pattern;
switch(_session.get_error()) {
case SigSession::Hw_err:
_session.set_repeating(false);
_session.stop_capture();
title = tr("Hardware Operation Failed");
details = tr("Please replug device to refresh hardware configuration!");
break;
case SigSession::Malloc_err:
_session.set_repeating(false);
_session.stop_capture();
title = tr("Malloc Error");
details = tr("Memory is not enough for this sample!\nPlease reduce the sample depth!");
break;
case SigSession::Test_data_err:
_session.set_repeating(false);
_session.stop_capture();
_sampling_bar->set_sampling(false);
_session.capture_state_changed(SigSession::Stopped);
title = tr("Data Error");
error_pattern = _session.get_error_pattern();
for(int i = 0; i < 16; i++) {
if (error_pattern & 0x01)
ch_status += "X ";
else
ch_status += " ";
ch_status += (i > 9 ? " " : "");
error_pattern >>= 1;
}
details = tr("the received data are not consist with pre-defined test data!\n") +
tr("0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n") + ch_status;
break;
case SigSession::Pkt_data_err:
title = tr("Packet Error");
details = tr("the content of received packet are not expected!");
_session.refresh(0);
break;
case SigSession::Data_overflow:
_session.set_repeating(false);
_session.stop_capture();
title = tr("Data Overflow");
details = tr("USB bandwidth can not support current sample rate! \nPlease reduce the sample rate!");
break;
default:
title = tr("Undefined Error");
details = tr("Not expected error!");
break;
}
_session.stop_capture();
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Data Error"));
msg.mBox()->setInformativeText(tr("the receive data are not consist with pre-defined test data"));
connect(_session.get_device().get(), SIGNAL(device_updated()), &msg, SLOT(accept()));
QFont font("Monaco");
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
msg.mBox()->setFont(font);
msg.mBox()->setText(title);
msg.mBox()->setInformativeText(details);
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
}
void MainWindow::malloc_error()
{
_session.stop_capture();
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Malloc Error"));
msg.mBox()->setInformativeText(tr("Memory is not enough for this sample!\nPlease reduce the sample depth!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
}
void MainWindow::hardware_connect_failed()
{
_session.stop_capture();
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Hardware Connect Failed"));
msg.mBox()->setInformativeText(tr("Please check hardware connection!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
_session.clear_error();
}
void MainWindow::capture_state_changed(int state)
{
_file_bar->enable_toggle(state != SigSession::Running);
_sampling_bar->set_sampling(state == SigSession::Running);
_view->on_state_changed(state != SigSession::Running);
if (!_session.repeat_check()) {
_file_bar->enable_toggle(state != SigSession::Running);
_sampling_bar->set_sampling(state == SigSession::Running);
_view->on_state_changed(state != SigSession::Running);
if (_session.get_device()->dev_inst()->mode != DSO) {
_sampling_bar->enable_toggle(state != SigSession::Running);
_trig_bar->enable_toggle(state != SigSession::Running);
_measure_dock->widget()->setEnabled(state != SigSession::Running);
if (_session.get_device()->dev_inst()->mode != DSO) {
_sampling_bar->enable_toggle(state != SigSession::Running);
_trig_bar->enable_toggle(state != SigSession::Running);
//_measure_dock->widget()->setEnabled(state != SigSession::Running);
_measure_widget->refresh();
}
}
#ifdef TEST_MODE
if (state == SigSession::Stopped) {
test_timer.start(qrand()%1000);
prgRate(0);
_view->repeat_unshow();
}
#endif
}
void MainWindow::session_save()
@@ -542,8 +595,9 @@ void MainWindow::session_save()
QString mode_name = QString::number(_session.get_device()->dev_inst()->mode);
QString file_name = dir.absolutePath() + "/" + driver_name + mode_name + ".dsc";
if (strncmp(driver_name.toLocal8Bit(), "virtual", 7) &&
!file_name.isEmpty())
!file_name.isEmpty()) {
store_session(file_name);
}
}
}
@@ -629,35 +683,21 @@ void MainWindow::on_screenShot()
void MainWindow::on_save()
{
using pv::dialogs::StoreProgress;
StoreProgress *dlg = new StoreProgress(_session, this);
dlg->save_run();
}
const QString DIR_KEY("SavePath");
QSettings settings;
// Stop any currently running capture session
_session.stop_capture();
// Show the dialog
const QString file_name = QFileDialog::getSaveFileName(
this, tr("Save File"), settings.value(DIR_KEY).toString(), tr("DSView Data (*.dsl)"));
if (file_name.isEmpty())
return;
QDir CurrentDir;
settings.setValue(DIR_KEY, CurrentDir.absoluteFilePath(file_name));
StoreProgress *dlg = new StoreProgress(file_name, _session, this);
dlg->run();
void MainWindow::on_export()
{
using pv::dialogs::StoreProgress;
StoreProgress *dlg = new StoreProgress(_session, this);
dlg->export_run();
}
bool MainWindow::load_session(QString name)
{
QFile sessionFile(name);
if (!sessionFile.open(QIODevice::ReadOnly)) {
// dialogs::DSMessageBox msg(this);
// msg.mBox()->setText(tr("File Error"));
// msg.mBox()->setInformativeText(tr("Couldn't open session file!"));
// msg.mBox()->setStandardButtons(QMessageBox::Ok);
// msg.mBox()->setIcon(QMessageBox::Warning);
// msg.exec();
qDebug("Warning: Couldn't open session file!");
return false;
}
@@ -666,6 +706,11 @@ bool MainWindow::load_session(QString name)
QJsonDocument sessionDoc = QJsonDocument::fromJson(sessionData.toUtf8());
QJsonObject sessionObj = sessionDoc.object();
// check session file version
if (!sessionObj.contains("Version") ||
sessionObj["Version"].toInt() != Session_Version)
return false;
// check device and mode
const sr_dev_inst *const sdi = _session.get_device()->dev_inst();
if (strcmp(sdi->driver->name, sessionObj["Device"].toString().toLocal8Bit()) != 0 ||
@@ -729,6 +774,9 @@ bool MainWindow::load_session(QString name)
if (!isEnabled)
probe->enabled = false;
}
_sampling_bar->update_record_length();
_trigger_widget->device_updated();
//_session.init_signals();
_session.reload();
@@ -749,7 +797,7 @@ bool MainWindow::load_session(QString name)
boost::shared_ptr<view::DsoSignal> dsoSig;
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
dsoSig->load_settings();
dsoSig->set_zero_vrate(obj["zeroPos"].toDouble());
dsoSig->set_zero_vrate(obj["zeroPos"].toDouble(), true);
dsoSig->set_trig_vrate(obj["trigValue"].toDouble());
dsoSig->commit_settings();
}
@@ -763,6 +811,14 @@ bool MainWindow::load_session(QString name)
_trigger_widget->set_session(sessionObj["trigger"].toObject());
}
on_trigger(false);
#ifdef ENABLE_DECODE
// load decoders
if (sessionObj.contains("decoder")) {
StoreSession ss(_session);
ss.load_decoders(_protocol_widget, sessionObj["decoder"].toArray());
}
#endif
}
bool MainWindow::store_session(QString name)
@@ -787,8 +843,8 @@ bool MainWindow::store_session(QString name)
gsize num_opts;
const sr_dev_inst *const sdi = _session.get_device()->dev_inst();
QJsonObject sessionVar;
QJsonObject triggerVar;
QJsonArray channelVar;
sessionVar["Version"]= QJsonValue::fromVariant(Session_Version);
sessionVar["Device"] = QJsonValue::fromVariant(sdi->driver->name);
sessionVar["DeviceMode"] = QJsonValue::fromVariant(sdi->mode);
@@ -844,6 +900,10 @@ bool MainWindow::store_session(QString name)
sessionVar["trigger"] = _trigger_widget->get_session();
}
#ifdef ENABLE_DECODE
StoreSession ss(_session);
sessionVar["decoder"] = ss.json_decoders();
#endif
QJsonDocument sessionDoc(sessionVar);
//sessionFile.write(QString::fromUtf8(sessionDoc.toJson()));
@@ -888,11 +948,11 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event)
break;
case Qt::Key_PageUp:
_view->set_scale_offset(_view->scale(),
_view->offset() - _view->scale()*_view->get_view_width());
_view->offset() - _view->get_view_width());
break;
case Qt::Key_PageDown:
_view->set_scale_offset(_view->scale(),
_view->offset() + _view->scale()*_view->get_view_width());
_view->offset() + _view->get_view_width());
break;
case Qt::Key_Left:

View File

@@ -27,7 +27,6 @@
#include <list>
#include <QMainWindow>
#include <QTimer>
#include "sigsession.h"
@@ -59,10 +58,6 @@ class MeasureDock;
class SearchDock;
}
namespace dialogs{
class Calibration;
}
namespace view {
class View;
}
@@ -71,6 +66,9 @@ class MainWindow : public QMainWindow
{
Q_OBJECT
private:
static constexpr int Session_Version = 2;
public:
explicit MainWindow(DeviceManager &device_manager,
const char *open_file_name = NULL,
@@ -100,8 +98,6 @@ private slots:
*/
void update_device_list();
void mode_changed();
void reload();
void show_session_error(
@@ -111,10 +107,6 @@ private slots:
void instant_stop();
void test_data_error();
void malloc_error();
void capture_state_changed(int state);
void on_protocol(bool visible);
@@ -131,9 +123,16 @@ private slots:
void on_save();
void on_export();
bool load_session(QString name);
bool store_session(QString name);
/*
* repeat
*/
void repeat_resume();
/*
* hotplug slot function
*/
@@ -143,7 +142,9 @@ private slots:
/*
* errors
*/
void hardware_connect_failed();
void show_error();
signals:
void prgRate(int progress);
private:
DeviceManager &_device_manager;
@@ -187,9 +188,6 @@ private:
dock::MeasureDock *_measure_widget;
QDockWidget *_search_dock;
dock::SearchDock * _search_widget;
QTimer test_timer;
bool test_timer_linked;
};
} // namespace pv

View File

@@ -79,6 +79,18 @@ QWidget* Binding::get_property_form(QWidget *parent,
return form;
}
std::map< boost::shared_ptr<Property>,
GVariant* >& Binding::get_property_value() const
{
std::map < boost::shared_ptr<Property>,
GVariant* > pvalue;
BOOST_FOREACH(shared_ptr<pv::prop::Property> p, _properties)
{
assert(p);
pvalue[p] = p->get_value();
}
}
QString Binding::print_gvariant(GVariant *const gvar)
{
QString s;

View File

@@ -27,6 +27,7 @@
#include <glib.h>
#include <vector>
#include <map>
#include <boost/shared_ptr.hpp>
#include <QString>
@@ -54,6 +55,9 @@ public:
QWidget* get_property_form(QWidget *parent,
bool auto_commit = false) const;
std::map< boost::shared_ptr<Property>,
GVariant* >& get_property_value() const;
static QString print_gvariant(GVariant *const gvar);
protected:

View File

@@ -87,6 +87,7 @@ DeviceOptions::DeviceOptions(struct sr_dev_inst *sdi) :
case SR_CONF_COUPLING:
case SR_CONF_EN_CH:
case SR_CONF_OPERATION_MODE:
case SR_CONF_BUFFER_OPTIONS:
case SR_CONF_THRESHOLD:
case SR_CONF_ZERO:
case SR_CONF_STREAM:

View File

@@ -45,14 +45,16 @@ public:
DecoderOptions(boost::shared_ptr<pv::data::DecoderStack> decoder_stack,
boost::shared_ptr<pv::data::decode::Decoder> decoder);
GVariant* getter(const char *id);
void setter(const char *id, GVariant *value);
private:
static boost::shared_ptr<Property> bind_enum(const QString &name,
const srd_decoder_option *option,
Property::Getter getter, Property::Setter setter);
GVariant* getter(const char *id);
void setter(const char *id, GVariant *value);
private:
boost::shared_ptr<pv::data::DecoderStack> _decoder_stack;

View File

@@ -69,6 +69,13 @@ bool Bool::labeled_widget() const
return true;
}
GVariant* Bool::get_value() const
{
GVariant *const value = _getter ? _getter() : NULL;
return value;
}
void Bool::commit()
{
assert(_setter);

View File

@@ -42,6 +42,8 @@ public:
QWidget* get_widget(QWidget *parent, bool auto_commit);
bool labeled_widget() const;
GVariant* get_value() const;
void commit();
private slots:

View File

@@ -42,5 +42,10 @@ bool Property::labeled_widget() const
return false;
}
GVariant* Property::get_value() const
{
return NULL;
}
} // prop
} // pv

View File

@@ -53,6 +53,8 @@ public:
bool auto_commit = false) = 0;
virtual bool labeled_widget() const;
virtual GVariant* get_value() const;
virtual void commit() = 0;
protected:

View File

@@ -89,7 +89,13 @@ SigSession* SigSession::_session = NULL;
SigSession::SigSession(DeviceManager &device_manager) :
_device_manager(device_manager),
_capture_state(Init),
_instant(false)
_instant(false),
_error(No_err),
_run_mode(Single),
_repeat_intvl(1),
_repeating(false),
_repeat_hold_prg(0),
_map_zoom(0)
{
// TODO: This should not be necessary
_session = this;
@@ -99,11 +105,11 @@ SigSession::SigSession(DeviceManager &device_manager) :
register_hotplug_callback();
_view_timer.stop();
_noData_cnt = 0;
_refresh_timer.stop();
_refresh_timer.setSingleShot(true);
_data_lock = false;
_data_updated = false;
#ifdef ENABLE_DECODE
_decoder_model = new pv::data::DecoderModel(this);
#endif
// Create snapshots & data containers
_cur_logic_snapshot.reset(new data::LogicSnapshot());
@@ -119,12 +125,6 @@ SigSession::SigSession(DeviceManager &device_manager) :
_group_cnt = 0;
connect(&_view_timer, SIGNAL(timeout()), this, SLOT(check_update()));
connect(&_refresh_timer, SIGNAL(timeout()), this, SLOT(data_unlock()));
#ifdef TEST_MODE
_test_timer.setSingleShot(true);
connect(&_test_timer, SIGNAL(timeout()), this, SLOT(stop_capture()));
#endif
}
SigSession::~SigSession()
@@ -172,6 +172,11 @@ void SigSession::set_device(boost::shared_ptr<device::DevInst> dev_inst) throw(Q
_dev_inst->use(this);
_cur_samplerate = _dev_inst->get_sample_rate();
_cur_samplelimits = _dev_inst->get_sample_limit();
if (_dev_inst->dev_inst()->mode == DSO)
set_run_mode(Repetitive);
else
set_run_mode(Single);
} catch(const QString e) {
throw(e);
return;
@@ -200,222 +205,6 @@ void SigSession::set_file(QString name) throw(QString)
}
}
void SigSession::save_file(const QString name, QWidget* parent, int type){
unsigned char* data;
int unit_size;
uint64_t sample_count;
if (type == ANALOG) {
const deque< boost::shared_ptr<pv::data::AnalogSnapshot> > &snapshots =
_analog_data->get_snapshots();
if (snapshots.empty())
return;
const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot =
snapshots.front();
data = (unsigned char*)snapshot->get_data();
unit_size = snapshot->unit_size();
sample_count = snapshot->get_sample_count();
} else if (type == DSO) {
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
_dso_data->get_snapshots();
if (snapshots.empty())
return;
const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
snapshots.front();
data = (unsigned char*)snapshot->get_data();
// snapshot->unit_size() is not valid for dso, replaced by enabled channel number
unit_size = get_ch_num(SR_CHANNEL_DSO);
sample_count = snapshot->get_sample_count();
} else {
const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
_logic_data->get_snapshots();
if (snapshots.empty())
return;
const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot =
snapshots.front();
data = (unsigned char*)snapshot->get_data();
unit_size = snapshot->unit_size();
sample_count = snapshot->get_sample_count();
}
QFuture<void> future;
future = QtConcurrent::run([&]{
sr_session_save(name.toLocal8Bit().data(), _dev_inst->dev_inst(),
data, unit_size, sample_count, _trigger_time.toMSecsSinceEpoch(), _trigger_pos);
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Save Capture to File... It can take a while."),
tr("Cancel"),0,0,parent,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;
watcher.setFuture(future);
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
dlg.exec();
}
QList<QString> SigSession::getSuportedExportFormats(){
const struct sr_output_module** supportedModules = sr_output_list();
QList<QString> list;
while(*supportedModules){
if(*supportedModules == NULL)
break;
if (_dev_inst->dev_inst()->mode == DSO && strcmp((*supportedModules)->id, "csv"))
break;
QString format((*supportedModules)->desc);
format.append(" (*.");
format.append((*supportedModules)->id);
format.append(")");
list.append(format);
supportedModules++;
}
return list;
}
void SigSession::cancelSaveFile(){
saveFileThreadRunning = false;
}
void SigSession::export_file(const QString name, QWidget* parent, const QString ext){
boost::shared_ptr<pv::data::Snapshot> snapshot;
int channel_type;
if (_dev_inst->dev_inst()->mode == LOGIC) {
const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
_logic_data->get_snapshots();
if(snapshots.empty())
return;
snapshot = snapshots.front();
channel_type = SR_CHANNEL_LOGIC;
} else if (_dev_inst->dev_inst()->mode == DSO) {
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
_dso_data->get_snapshots();
if(snapshots.empty())
return;
snapshot = snapshots.front();
channel_type = SR_CHANNEL_DSO;
} else {
return;
}
const struct sr_output_module** supportedModules = sr_output_list();
const struct sr_output_module* outModule = NULL;
while(*supportedModules){
if(*supportedModules == NULL)
break;
if(!strcmp((*supportedModules)->id, ext.toLocal8Bit().data())){
outModule = *supportedModules;
break;
}
supportedModules++;
}
if(outModule == NULL)
return;
GHashTable *params = g_hash_table_new(g_str_hash, g_str_equal);
GVariant* filenameGVariant = g_variant_new_bytestring(name.toLocal8Bit().data());
g_hash_table_insert(params, (char*)"filename", filenameGVariant);
GVariant* typeGVariant = g_variant_new_int16(channel_type);
g_hash_table_insert(params, (char*)"type", typeGVariant);
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _signals) {
boost::shared_ptr<view::DsoSignal> dsoSig;
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
GVariant* timebaseGVariant = g_variant_new_uint64(dsoSig->get_hDialValue());
g_hash_table_insert(params, (char*)"timebase", timebaseGVariant);
break;
}
}
struct sr_output output;
output.module = (sr_output_module*) outModule;
output.sdi = _dev_inst->dev_inst();
output.param = NULL;
if(outModule->init)
outModule->init(&output, params);
QFile file(name);
file.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream out(&file);
out.setCodec("UTF-8");
out.setGenerateByteOrderMark(true);
QFuture<void> future;
if (_dev_inst->dev_inst()->mode == LOGIC) {
future = QtConcurrent::run([&]{
saveFileThreadRunning = true;
unsigned char* datat = (unsigned char*)snapshot->get_data();
unsigned int numsamples = snapshot->get_sample_count()*snapshot->unit_size();
GString *data_out;
unsigned int usize = 8192;
unsigned int size = usize;
struct sr_datafeed_logic lp;
struct sr_datafeed_packet p;
for(uint64_t i = 0; i < numsamples; i+=usize){
if(numsamples - i < usize)
size = numsamples - i;
lp.data = &datat[i];
lp.length = size;
lp.unitsize = snapshot->unit_size();
p.type = SR_DF_LOGIC;
p.payload = &lp;
outModule->receive(&output, &p, &data_out);
if(data_out){
out << QString::fromUtf8((char*) data_out->str);
g_string_free(data_out,TRUE);
}
emit progressSaveFileValueChanged(i*100/numsamples);
if(!saveFileThreadRunning)
break;
}
});
} else if (_dev_inst->dev_inst()->mode == DSO) {
future = QtConcurrent::run([&]{
saveFileThreadRunning = true;
unsigned char* datat = (unsigned char*)snapshot->get_data();
unsigned int numsamples = snapshot->get_sample_count();
GString *data_out;
unsigned int usize = 8192;
unsigned int size = usize;
struct sr_datafeed_dso dp;
struct sr_datafeed_packet p;
for(uint64_t i = 0; i < numsamples; i+=usize){
if(numsamples - i < usize)
size = numsamples - i;
dp.data = &datat[i*snapshot->get_channel_num()];
dp.num_samples = size;
p.type = SR_DF_DSO;
p.payload = &dp;
outModule->receive(&output, &p, &data_out);
if(data_out){
out << (char*) data_out->str;
g_string_free(data_out,TRUE);
}
emit progressSaveFileValueChanged(i*100/numsamples);
if(!saveFileThreadRunning)
break;
}
});
}
QFutureWatcher<void> watcher;
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Exporting data... It can take a while."),
tr("Cancel"),0,100,parent,flags);
dlg.setWindowModality(Qt::WindowModal);
watcher.setFuture(future);
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
connect(this,SIGNAL(progressSaveFileValueChanged(int)),&dlg,SLOT(setValue(int)));
connect(&dlg,SIGNAL(canceled()),this,SLOT(cancelSaveFile()));
dlg.exec();
future.waitForFinished();
// optional, as QFile destructor will already do it:
file.close();
outModule->cleanup(&output);
g_hash_table_destroy(params);
g_variant_unref(filenameGVariant);
}
void SigSession::set_default_device(boost::function<void (const QString)> error_handler)
{
boost::shared_ptr<pv::device::DevInst> default_device;
@@ -511,9 +300,13 @@ void SigSession::set_cur_samplelimits(uint64_t samplelimits)
void SigSession::capture_init()
{
if (!_instant)
set_repeating(get_run_mode() == Repetitive);
_cur_samplerate = _dev_inst->get_sample_rate();
_cur_samplelimits = _dev_inst->get_sample_limit();
_data_updated = false;
_trigger_flag = false;
_hw_replied = false;
if (_dev_inst->dev_inst()->mode != LOGIC)
_view_timer.start(ViewTime);
else
@@ -522,11 +315,7 @@ void SigSession::capture_init()
data_unlock();
// Init and Set sample rate for all SignalData
// Logic/Analog/Dso
if (_logic_data) {
_logic_data->init();
_logic_data->set_samplerate(_cur_samplerate);
}
// Analog/Dso
if (_analog_data) {
_analog_data->init();
_analog_data->set_samplerate(_cur_samplerate);
@@ -535,12 +324,42 @@ void SigSession::capture_init()
_dso_data->init();
_dso_data->set_samplerate(_cur_samplerate);
}
// MathStack
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> m, _math_traces)
{
assert(m);
m->get_math_stack()->init();
m->get_math_stack()->set_samplerate(_cur_samplerate);
}
// update current hw offset
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _signals)
{
assert(s);
boost::shared_ptr<view::DsoSignal> dsoSig;
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
dsoSig->set_zero_vrate(dsoSig->get_zero_vrate(), true);
}
}
}
void SigSession::logic_init()
{
// Logic
if (_logic_data) {
_logic_data->init();
_logic_data->set_samplerate(_cur_samplerate);
}
// Group
if (_group_data) {
_group_data->init();
_group_data->set_samplerate(_cur_samplerate);
}
#ifdef ENABLE_DECODE
// DecoderModel
pv::data::DecoderModel *decoder_model = get_decoder_model();
decoder_model->setDecoderStack(NULL);
// DecoderStack
BOOST_FOREACH(const boost::shared_ptr<view::DecodeTrace> d, _decode_traces)
{
@@ -549,29 +368,36 @@ void SigSession::capture_init()
d->decoder()->set_samplerate(_cur_samplerate);
}
#endif
// MathStack
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> m, _math_traces)
{
assert(m);
m->get_math_stack()->init();
m->get_math_stack()->set_samplerate(_cur_samplerate);
}
}
void SigSession::start_capture(bool instant,
boost::function<void (const QString)> error_handler)
{
stop_capture();
capture_init();
// Check that a device instance has been selected.
// Check that a device instance has been selected.
if (!_dev_inst) {
qDebug() << "No device selected";
return;
}
qDebug() << "No device selected";
capture_state_changed(SigSession::Stopped);
return;
}
assert(_dev_inst->dev_inst());
if (!_dev_inst->is_usable()) {
_error = Hw_err;
session_error();
capture_state_changed(SigSession::Stopped);
return;
}
// stop previous capture
stop_capture();
// update setting
if (_dev_inst->name() != "virtual-session")
_instant = instant;
else
_instant = true;
capture_init();
// Check that at least one probe is enabled
const GSList *l;
for (l = _dev_inst->dev_inst()->channels; l; l = l->next) {
@@ -583,16 +409,11 @@ void SigSession::start_capture(bool instant,
if (!l) {
error_handler(tr("No probes enabled."));
data_updated();
set_repeating(false);
capture_state_changed(SigSession::Stopped);
return;
}
// update setting
if (_dev_inst->name() != "virtual-session")
_instant = instant;
else
_instant = true;
// Begin the session
_sampling_thread.reset(new boost::thread(
&SigSession::sample_thread_proc, this, _dev_inst,
@@ -619,6 +440,30 @@ void SigSession::stop_capture()
_sampling_thread.reset();
}
bool SigSession::get_capture_status(bool &triggered, int &progress)
{
uint64_t sample_limits = cur_samplelimits();
sr_status status;
if (sr_status_get(_dev_inst->dev_inst(), &status, SR_STATUS_TRIG_BEGIN, SR_STATUS_TRIG_END) == SR_OK){
triggered = status.trig_hit & 0x01;
const bool captured_cnt_dec = status.trig_hit & 0x02;
uint64_t captured_cnt = status.trig_hit >> 2;
captured_cnt = ((uint64_t)status.captured_cnt0 +
((uint64_t)status.captured_cnt1 << 8) +
((uint64_t)status.captured_cnt2 << 16) +
((uint64_t)status.captured_cnt3 << 24) +
(captured_cnt << 32));
if (_dev_inst->dev_inst()->mode == DSO)
captured_cnt = captured_cnt * _signals.size() / get_ch_num(SR_CHANNEL_DSO);
if (captured_cnt_dec)
progress = (sample_limits - captured_cnt) * 100.0 / sample_limits;
else
progress = captured_cnt * 100.0 / sample_limits;
return true;
}
return false;
}
vector< boost::shared_ptr<view::Signal> > SigSession::get_signals()
{
//boost::lock_guard<boost::mutex> lock(_signals_mutex);
@@ -648,47 +493,6 @@ bool SigSession::get_instant()
return _instant;
}
const void* SigSession::get_buf(int& unit_size, uint64_t &length)
{
if (_dev_inst->dev_inst()->mode == LOGIC) {
const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
_logic_data->get_snapshots();
if (snapshots.empty())
return NULL;
const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot =
snapshots.front();
unit_size = snapshot->unit_size();
length = snapshot->get_sample_count();
return snapshot->get_data();
} else if (_dev_inst->dev_inst()->mode == DSO) {
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
_dso_data->get_snapshots();
if (snapshots.empty())
return NULL;
const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
snapshots.front();
unit_size = snapshot->unit_size();
length = snapshot->get_sample_count();
return snapshot->get_data();
} else {
const deque< boost::shared_ptr<pv::data::AnalogSnapshot> > &snapshots =
_analog_data->get_snapshots();
if (snapshots.empty())
return NULL;
const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot =
snapshots.front();
unit_size = snapshot->unit_size();
length = snapshot->get_sample_count();
return snapshot->get_data();
}
}
void SigSession::set_capture_state(capture_state state)
{
boost::lock_guard<boost::mutex> lock(_sampling_mutex);
@@ -733,10 +537,6 @@ void SigSession::check_update()
data_updated();
_data_updated = false;
_noData_cnt = 0;
#ifdef TEST_MODE
if (!_test_timer.isActive())
_test_timer.start(qrand()%5000);
#endif
} else {
if (++_noData_cnt >= (WaitShowTime/ViewTime))
nodata_timeout();
@@ -947,24 +747,26 @@ void SigSession::reload()
}
break;
case SR_CHANNEL_DSO:
signal = boost::shared_ptr<view::Signal>(
new view::DsoSignal(_dev_inst,_dso_data, probe));
break;
// case SR_CHANNEL_DSO:
// signal = boost::shared_ptr<view::Signal>(
// new view::DsoSignal(_dev_inst,_dso_data, probe));
// break;
case SR_CHANNEL_ANALOG:
if (probe->enabled)
signal = boost::shared_ptr<view::Signal>(
new view::AnalogSignal(_dev_inst, _analog_data, probe));
break;
// case SR_CHANNEL_ANALOG:
// if (probe->enabled)
// signal = boost::shared_ptr<view::Signal>(
// new view::AnalogSignal(_dev_inst, _analog_data, probe));
// break;
}
if (signal.get())
sigs.push_back(signal);
}
_signals.clear();
vector< boost::shared_ptr<view::Signal> >().swap(_signals);
_signals = sigs;
if (!sigs.empty()) {
_signals.clear();
vector< boost::shared_ptr<view::Signal> >().swap(_signals);
_signals = sigs;
}
}
mathTraces_rebuild();
@@ -975,7 +777,7 @@ void SigSession::refresh(int holdtime)
boost::lock_guard<boost::mutex> lock(_data_mutex);
_data_lock = true;
_refresh_timer.start(holdtime);
QTimer::singleShot(holdtime, this, SLOT(data_unlock()));
if (_logic_data) {
_logic_data->init();
@@ -1057,9 +859,12 @@ void SigSession::feed_in_meta(const sr_dev_inst *sdi,
void SigSession::feed_in_trigger(const ds_trigger_pos &trigger_pos)
{
_hw_replied = true;
if (_dev_inst->dev_inst()->mode != DSO) {
_trigger_pos = trigger_pos.real_pos;
receive_trigger(_trigger_pos);
if (_trigger_flag = (trigger_pos.status & 0x01)) {
_trigger_pos = trigger_pos.real_pos;
receive_trigger(_trigger_pos);
}
if (_dev_inst->name() != "virtual-session") {
const double time = trigger_pos.real_pos * 1.0 / _cur_samplerate;
_trigger_time = QDateTime::currentDateTime();
@@ -1092,15 +897,14 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic)
}
if (logic.data_error == 1) {
test_data_error();
_error = Test_data_err;
_error_pattern = logic.error_pattern;
session_error();
}
if (_cur_logic_snapshot->last_ended()) {
_cur_logic_snapshot->first_payload(logic, _dev_inst->get_sample_limit(), 1);
if (_cur_logic_snapshot->memory_failed()) {
malloc_error();
return;
}
logic_init();
_cur_logic_snapshot->first_payload(logic, _dev_inst->get_sample_limit(), _dev_inst->dev_inst()->channels);
// @todo Putting this here means that only listeners querying
// for logic will be notified. Currently the only user of
// frame_began is DecoderStack, but in future we need to signal
@@ -1111,7 +915,13 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic)
_cur_logic_snapshot->append_payload(logic);
}
emit receive_data(logic.length/logic.unitsize);
if (_cur_logic_snapshot->memory_failed()) {
_error = Malloc_err;
session_error();
return;
}
emit receive_data(logic.length * 8 / get_ch_num(SR_CHANNEL_LOGIC));
data_received();
//data_updated();
_data_updated = true;
@@ -1129,25 +939,30 @@ void SigSession::feed_in_dso(const sr_datafeed_dso &dso)
if (_cur_dso_snapshot->last_ended())
{
std::map<int, bool> sig_enable;
// reset scale of dso signal
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _signals)
{
assert(s);
boost::shared_ptr<view::DsoSignal> dsoSig;
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s))
dsoSig->set_scale(dsoSig->get_view_rect().height() / 256.0f);
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
dsoSig->set_scale(dsoSig->get_view_rect().height());
sig_enable[dsoSig->get_index()] = dsoSig->enabled();
}
}
// first payload
_cur_dso_snapshot->first_payload(dso, _dev_inst->get_sample_limit(), get_ch_num(SR_CHANNEL_DSO), _instant);
if (_cur_dso_snapshot->memory_failed()) {
malloc_error();
return;
}
_cur_dso_snapshot->first_payload(dso, _dev_inst->get_sample_limit(), sig_enable, _instant);
} else {
// Append to the existing data snapshot
_cur_dso_snapshot->append_payload(dso);
}
if (_cur_dso_snapshot->memory_failed()) {
_error = Malloc_err;
session_error();
return;
}
// calculate related math results
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> m, _math_traces)
{
@@ -1175,16 +990,18 @@ void SigSession::feed_in_analog(const sr_datafeed_analog &analog)
if (_cur_analog_snapshot->last_ended())
{
// first payload
_cur_analog_snapshot->first_payload(analog, _dev_inst->get_sample_limit(), get_ch_num(SR_CHANNEL_ANALOG));
if (_cur_analog_snapshot->memory_failed()) {
malloc_error();
return;
}
_cur_analog_snapshot->first_payload(analog, _dev_inst->get_sample_limit(), _dev_inst->dev_inst()->channels);
} else {
// Append to the existing data snapshot
_cur_analog_snapshot->append_payload(analog);
}
if (_cur_analog_snapshot->memory_failed()) {
_error = Malloc_err;
session_error();
return;
}
receive_data(analog.num_samples);
//data_updated();
_data_updated = true;
@@ -1200,6 +1017,12 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi,
if (_data_lock)
return;
if (packet->type != SR_DF_END &&
packet->status != SR_PKT_OK) {
_error = Pkt_data_err;
session_error();
return;
}
switch (packet->type) {
case SR_DF_HEADER:
@@ -1232,6 +1055,12 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi,
feed_in_analog(*(const sr_datafeed_analog*)packet->payload);
break;
case SR_DF_OVERFLOW:
{
_error = Data_overflow;
session_error();
break;
}
case SR_DF_END:
{
{
@@ -1247,14 +1076,22 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi,
_cur_group_snapshot.reset();
}
}
_cur_logic_snapshot->set_last_ended(true);
_cur_dso_snapshot->set_last_ended(true);
_cur_analog_snapshot->set_last_ended(true);
if (!_cur_logic_snapshot->last_ended())
_cur_logic_snapshot->capture_ended();
else if (get_run_mode() != SigSession::Repetitive)
logic_init();
_cur_dso_snapshot->capture_ended();
_cur_analog_snapshot->capture_ended();
#ifdef ENABLE_DECODE
BOOST_FOREACH(const boost::shared_ptr<view::DecodeTrace> d, _decode_traces)
d->frame_ended();
#endif
}
if (packet->status != SR_PKT_OK) {
_error = Pkt_data_err;
session_error();
}
frame_ended();
break;
}
@@ -1403,14 +1240,13 @@ uint16_t SigSession::get_ch_num(int type)
}
#ifdef ENABLE_DECODE
bool SigSession::add_decoder(srd_decoder *const dec)
bool SigSession::add_decoder(srd_decoder *const dec, bool silent)
{
bool ret = false;
map<const srd_channel*, boost::shared_ptr<view::LogicSignal> > probes;
map<const srd_channel*, int> probes;
boost::shared_ptr<data::DecoderStack> decoder_stack;
try
{
try {
//lock_guard<mutex> lock(_signals_mutex);
// Create the decoder
@@ -1440,13 +1276,14 @@ bool SigSession::add_decoder(srd_decoder *const dec)
break;
}
}
if (d->create_popup()) {
if (silent) {
_decode_traces.push_back(d);
ret = true;
} else if (d->create_popup()) {
_decode_traces.push_back(d);
ret = true;
}
}
catch(std::runtime_error e)
{
} catch(std::runtime_error e) {
return false;
}
@@ -1604,4 +1441,117 @@ void SigSession::nodata_timeout()
}
}
boost::shared_ptr<data::Snapshot> SigSession::get_snapshot(int type)
{
if (type == SR_CHANNEL_LOGIC)
return _cur_logic_snapshot;
else if (type == SR_CHANNEL_ANALOG)
return _cur_analog_snapshot;
else if (type == SR_CHANNEL_DSO)
return _cur_dso_snapshot;
else
return NULL;
}
SigSession::error_state SigSession::get_error() const
{
return _error;
}
void SigSession::set_error(error_state state)
{
_error = state;
}
void SigSession::clear_error()
{
_error_pattern = 0;
_error = No_err;
}
uint64_t SigSession::get_error_pattern() const
{
return _error_pattern;
}
SigSession::run_mode SigSession::get_run_mode() const
{
return _run_mode;
}
void SigSession::set_run_mode(run_mode mode)
{
_run_mode = mode;
}
int SigSession::get_repeat_intvl() const
{
return _repeat_intvl;
}
void SigSession::set_repeat_intvl(int interval)
{
_repeat_intvl = interval;
}
void SigSession::set_repeating(bool repeat)
{
_repeating = repeat;
if (!_repeating)
_repeat_hold_prg = 0;
}
bool SigSession::isRepeating() const
{
return _repeating;
}
bool SigSession::repeat_check()
{
if (get_capture_state() != Stopped ||
get_run_mode() != Repetitive ||
!isRepeating()) {
return false;
}
if (_dev_inst->dev_inst()->mode == LOGIC) {
_repeat_hold_prg = 100;
repeat_hold(_repeat_hold_prg);
QTimer::singleShot(_repeat_intvl*1000/RepeatHoldDiv, this, SLOT(repeat_update()));
return true;
} else {
return true;
}
}
void SigSession::repeat_update()
{
if (isRepeating()) {
_repeat_hold_prg -= 100/RepeatHoldDiv;
if (_repeat_hold_prg != 0)
QTimer::singleShot(_repeat_intvl*1000/RepeatHoldDiv, this, SLOT(repeat_update()));
repeat_hold(_repeat_hold_prg);
if (_repeat_hold_prg == 0)
repeat_resume();
}
}
int SigSession::get_repeat_hold() const
{
if (isRepeating())
return _repeat_hold_prg;
else
return 0;
}
void SigSession::set_map_zoom(int index)
{
_map_zoom = index;
}
int SigSession::get_map_zoom() const
{
return _map_zoom;
}
} // namespace pv

View File

@@ -59,6 +59,7 @@ class DeviceManager;
namespace data {
class SignalData;
class Snapshot;
class Analog;
class AnalogSnapshot;
class Dso;
@@ -93,7 +94,7 @@ class SigSession : public QObject
private:
static constexpr float Oversampling = 2.0f;
static const int RefreshTime = 500;
bool saveFileThreadRunning = false;
static const int RepeatHoldDiv = 20;
public:
static const int ViewTime = 50;
@@ -106,6 +107,21 @@ public:
Running
};
enum run_mode {
Single,
Repetitive
};
enum error_state {
No_err,
Hw_err,
Malloc_err,
Test_data_err,
Test_timeout_err,
Pkt_data_err,
Data_overflow
};
public:
SigSession(DeviceManager &device_manager);
@@ -122,10 +138,7 @@ public:
void set_file(QString name)
throw(QString);
void save_file(const QString name, QWidget* parent, int type);
void set_default_device(boost::function<void (const QString)> error_handler);
void export_file(const QString name, QWidget* parent, const QString ext);
void release_device(device::DevInst *dev_inst);
@@ -142,6 +155,8 @@ public:
void start_capture(bool instant,
boost::function<void (const QString)> error_handler);
void capture_init();
bool get_capture_status(bool &triggered, int &progress);
void logic_init();
std::set< boost::shared_ptr<data::SignalData> > get_data() const;
@@ -150,10 +165,9 @@ public:
std::vector< boost::shared_ptr<view::GroupSignal> >
get_group_signals();
QList<QString> getSuportedExportFormats();
#ifdef ENABLE_DECODE
bool add_decoder(srd_decoder *const dec);
bool add_decoder(srd_decoder *const dec, bool silent);
std::vector< boost::shared_ptr<view::DecodeTrace> >
get_decode_signals() const;
@@ -167,20 +181,17 @@ public:
void rst_decoder(view::DecodeTrace *signal);
pv::data::DecoderModel* get_decoder_model() const;
#endif
std::vector< boost::shared_ptr<view::MathTrace> >
get_math_signals();
#endif
void init_signals();
void add_group();
void del_group();
const void* get_buf(int& unit_size, uint64_t& length);
void start_hotplug_proc(boost::function<void (const QString)> error_handler);
void stop_hotplug_proc();
void register_hotplug_callback();
@@ -195,6 +206,23 @@ public:
bool trigd() const;
boost::shared_ptr<data::Snapshot> get_snapshot(int type);
error_state get_error() const;
void set_error(error_state state);
void clear_error();
uint64_t get_error_pattern() const;
run_mode get_run_mode() const;
void set_run_mode(run_mode mode);
int get_repeat_intvl() const;
void set_repeat_intvl(int interval);
bool isRepeating() const;
bool repeat_check();
int get_repeat_hold() const;
int get_map_zoom() const;
private:
void set_capture_state(capture_state state);
@@ -278,17 +306,23 @@ private:
QTimer _view_timer;
int _noData_cnt;
QTimer _refresh_timer;
bool _data_lock;
bool _data_updated;
#ifdef TEST_MODE
QTimer _test_timer;
#endif
QDateTime _trigger_time;
uint64_t _trigger_pos;
bool _trigger_flag;
bool _hw_replied;
error_state _error;
uint64_t _error_pattern;
run_mode _run_mode;
int _repeat_intvl;
bool _repeating;
int _repeat_hold_prg;
int _map_zoom;
signals:
void capture_state_changed(int state);
@@ -297,15 +331,11 @@ signals:
void data_updated();
void start_timer(int);
void receive_data(quint64 length);
void device_attach();
void device_detach();
void test_data_error();
void receive_trigger(quint64 trigger_pos);
void receive_header();
@@ -320,31 +350,35 @@ signals:
void device_setted();
void malloc_error();
void zero_adj();
void progressSaveFileValueChanged(int percent);
void decode_done();
void show_region(uint64_t start, uint64_t end);
void hardware_connect_failed();
void show_region(uint64_t start, uint64_t end, bool keep);
void show_wait_trigger();
void on_mode_change();
void session_save();
void session_error();
void repeat_hold(int percent);
void repeat_resume();
public slots:
void reload();
void refresh(int holdtime);
void stop_capture();
// repeat
void set_repeating(bool repeat);
void set_map_zoom(int index);
private slots:
void cancelSaveFile();
void data_unlock();
void check_update();
void nodata_timeout();
void repeat_update();
private:
// TODO: This should not be necessary. Multiple concurrent

View File

@@ -2,6 +2,7 @@
* This file is part of the PulseView project.
*
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,10 +24,22 @@
#include <pv/sigsession.h>
#include <pv/data/logic.h>
#include <pv/data/logicsnapshot.h>
#include <pv/data/dsosnapshot.h>
#include <pv/data/decoderstack.h>
#include <pv/data/decode/decoder.h>
#include <pv/data/decode/row.h>
#include <pv/view/trace.h>
#include <pv/view/signal.h>
#include <pv/view/logicsignal.h>
#include <pv/view/dsosignal.h>
#include <pv/view/decodetrace.h>
#include <pv/device/devinst.h>
#include <pv/dock/protocoldock.h>
#include <boost/foreach.hpp>
#include <QFileDialog>
using boost::dynamic_pointer_cast;
using boost::mutex;
using boost::shared_ptr;
@@ -42,14 +55,12 @@ using std::vector;
namespace pv {
const size_t StoreSession::BlockSize = 1024 * 1024;
StoreSession::StoreSession(const std::string &file_name,
SigSession &session) :
_file_name(file_name),
StoreSession::StoreSession(SigSession &session) :
_session(session),
_outModule(NULL),
_units_stored(0),
_unit_count(0)
_unit_count(0),
_has_error(false)
{
}
@@ -70,132 +81,791 @@ const QString& StoreSession::error() const
return _error;
}
bool StoreSession::start()
{
const vector< shared_ptr<view::Signal> > sigs(_session.get_signals());
set< boost::shared_ptr<data::SignalData> > data_set;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> sig, sigs) {
assert(sig);
data_set.insert(sig->data());
}
// Check we have logic data
if (data_set.empty() || sigs.empty()) {
_error = tr("No data to save.");
return false;
}
if (data_set.size() > 1) {
_error = tr("DSView currently only has support for "
"storing a single data stream.");
return false;
}
// Get the logic data
//shared_ptr<data::SignalData
shared_ptr<data::Logic> data;
if (!(data = dynamic_pointer_cast<data::Logic>(*data_set.begin()))) {
_error = tr("DSView currently only has support for "
"storing a logic data.");
return false;
}
// Get the snapshot
const deque< shared_ptr<data::LogicSnapshot> > &snapshots =
data->get_snapshots();
if (snapshots.empty()) {
_error = tr("No snapshots to save.");
return false;
}
const shared_ptr<data::LogicSnapshot> snapshot(snapshots.front());
assert(snapshot);
// Make a list of probes
char **const probes = new char*[sigs.size() + 1];
for (size_t i = 0; i < sigs.size(); i++) {
shared_ptr<view::Signal> sig(sigs[i]);
assert(sig);
probes[i] = strdup(sig->get_name().toUtf8().constData());
}
probes[sigs.size()] = NULL;
// Begin storing
if (sr_session_save_init(_file_name.c_str(),
data->samplerate(), probes) != SR_OK) {
_error = tr("Error while saving.");
return false;
}
// Delete the probes array
for (size_t i = 0; i <= sigs.size(); i++)
free(probes[i]);
delete[] probes;
_thread = boost::thread(&StoreSession::store_proc, this, snapshot);
return true;
}
void StoreSession::wait()
{
if (_thread.joinable())
_thread.join();
if (_thread.joinable())
_thread.join();
}
void StoreSession::cancel()
{
_thread.interrupt();
_thread.interrupt();
}
void StoreSession::store_proc(shared_ptr<data::LogicSnapshot> snapshot)
QList<QString> StoreSession::getSuportedExportFormats(){
const struct sr_output_module** supportedModules = sr_output_list();
QList<QString> list;
while(*supportedModules){
if(*supportedModules == NULL)
break;
if (_session.get_device()->dev_inst()->mode == DSO && strcmp((*supportedModules)->id, "csv"))
break;
QString format((*supportedModules)->desc);
format.append(" (*.");
format.append((*supportedModules)->id);
format.append(")");
list.append(format);
supportedModules++;
}
return list;
}
bool StoreSession::save_start()
{
std::set<int> type_set;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> sig, _session.get_signals()) {
assert(sig);
type_set.insert(sig->get_type());
}
if (type_set.size() > 1) {
_error = tr("DSView does not currently support"
"file saving for multiple data types.");
return false;
} else if (type_set.size() == 0) {
_error = tr("No data to save.");
return false;
}
const boost::shared_ptr<data::Snapshot> snapshot(_session.get_snapshot(*type_set.begin()));
assert(snapshot);
// Check we have data
if (snapshot->empty()) {
_error = tr("No data to save.");
return false;
}
const QString DIR_KEY("SavePath");
QSettings settings;
// Show the dialog
_file_name = QFileDialog::getSaveFileName(
NULL, tr("Save File"), settings.value(DIR_KEY).toString(),
tr("DSView Data (*.dsl)"));
if (!_file_name.isEmpty()) {
QFileInfo f(_file_name);
if(f.suffix().compare("dsl"))
_file_name.append(tr(".dsl"));
QDir CurrentDir;
settings.setValue(DIR_KEY, CurrentDir.absoluteFilePath(_file_name));
QString meta_file = meta_gen(snapshot);
#ifdef ENABLE_DECODE
QString decoders_file = decoders_gen();
#else
QString decoders_file = NULL;
#endif
if (meta_file == NULL) {
_error = tr("Generate temp file failed.");
return false;
} else {
sr_session_save_init(_file_name.toLocal8Bit().data(),
meta_file.toLocal8Bit().data(),
decoders_file.toLocal8Bit().data());
_thread = boost::thread(&StoreSession::save_proc, this, snapshot);
return !_has_error;
}
}
_error.clear();
return false;
}
void StoreSession::save_proc(shared_ptr<data::Snapshot> snapshot)
{
assert(snapshot);
uint64_t start_sample = 0;
shared_ptr<data::LogicSnapshot> logic_snapshot;
shared_ptr<data::AnalogSnapshot> analog_snapshot;
shared_ptr<data::DsoSnapshot> dso_snapshot;
/// TODO: Wrap this in a std::unique_ptr when we transition to C++11
uint8_t *data = NULL;
//uint8_t *const data = new uint8_t[BlockSize];
//assert(data);
if (logic_snapshot = boost::dynamic_pointer_cast<data::LogicSnapshot>(snapshot)) {
uint16_t to_save_probes = 0;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
if (s->enabled() && logic_snapshot->has_data(s->get_index()))
to_save_probes++;
}
_unit_count = logic_snapshot->get_sample_count() / 8 * to_save_probes;
int num = logic_snapshot->get_block_num();
bool sample;
const int unit_size = snapshot->unit_size();
assert(unit_size != 0);
{
//lock_guard<mutex> lock(_mutex);
_unit_count = snapshot->get_sample_count();
}
const unsigned int samples_per_block = BlockSize / unit_size;
while (!boost::this_thread::interruption_requested() &&
start_sample < _unit_count)
{
progress_updated();
const uint64_t end_sample = min(
start_sample + samples_per_block, _unit_count);
data = snapshot->get_samples(start_sample, end_sample);
if(sr_session_append(_file_name.c_str(), data, unit_size,
end_sample - start_sample) != SR_OK)
{
_error = tr("Error while saving.");
break;
}
start_sample = end_sample;
{
//lock_guard<mutex> lock(_mutex);
_units_stored = start_sample;
}
}
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
int ch_type = s->get_type();
if (ch_type == SR_CHANNEL_LOGIC) {
int ch_index = s->get_index();
if (!s->enabled() || !logic_snapshot->has_data(ch_index))
continue;
for (int i = 0; !boost::this_thread::interruption_requested() && i < num; i++) {
uint8_t *buf = logic_snapshot->get_block_buf(i, ch_index, sample);
uint64_t size = logic_snapshot->get_block_size(i);
bool need_malloc = (buf == NULL);
if (need_malloc) {
buf = (uint8_t *)malloc(size);
if (buf == NULL) {
_has_error = true;
_error = tr("Malloc failed.");
return;
}
memset(buf, sample ? 0xff : 0x0, size);
}
sr_session_append(_file_name.toLocal8Bit().data(), buf, size,
i, ch_index, ch_type, File_Version);
_units_stored += size;
if (need_malloc)
free(buf);
progress_updated();
}
}
}
} else {
int ch_type;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
ch_type = s->get_type();
break;
}
uint64_t size = snapshot->get_sample_count() * snapshot->get_channel_num();
uint8_t *buf = (uint8_t *)snapshot->get_data();
sr_session_append(_file_name.toLocal8Bit().data(), buf, size,
0, 0, ch_type, 1);
}
progress_updated();
}
//delete[] data;
QString StoreSession::meta_gen(boost::shared_ptr<data::Snapshot> snapshot)
{
GSList *l;
GVariant *gvar;
FILE *meta;
struct sr_channel *probe;
int probecnt;
char *s;
struct sr_status status;
QString metafile;
/* init "metadata" */
QDir dir;
#if QT_VERSION >= 0x050400
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
#else
QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
#endif
if(dir.mkpath(path)) {
dir.cd(path);
metafile = dir.absolutePath() + "/DSView-meta-XXXXXX";
} else {
return NULL;
}
const sr_dev_inst *sdi = _session.get_device()->dev_inst();
meta = fopen(metafile.toLocal8Bit().data(), "wb");
fprintf(meta, "[version]\n");
if (sdi->mode == DSO)
fprintf(meta, "version = %d\n", 1); // should be updated in next version
else
fprintf(meta, "version = %d\n", File_Version);
/* metadata */
fprintf(meta, "[header]\n");
if (sdi->driver) {
fprintf(meta, "driver = %s\n", sdi->driver->name);
fprintf(meta, "device mode = %d\n", sdi->mode);
}
/* metadata */
fprintf(meta, "capturefile = data\n");
fprintf(meta, "total samples = %llu\n", snapshot->get_sample_count());
if (sdi->mode == DSO)
fprintf(meta, "total probes = %d\n", g_slist_length(sdi->channels));
shared_ptr<data::LogicSnapshot> logic_snapshot;
if (logic_snapshot = dynamic_pointer_cast<data::LogicSnapshot>(snapshot)) {
uint16_t to_save_probes = 0;
for (l = sdi->channels; l; l = l->next) {
probe = (struct sr_channel *)l->data;
if (probe->enabled && logic_snapshot->has_data(probe->index))
to_save_probes++;
}
fprintf(meta, "total probes = %d\n", to_save_probes);
fprintf(meta, "total blocks = %d\n", logic_snapshot->get_block_num());
}
s = sr_samplerate_string(_session.cur_samplerate());
fprintf(meta, "samplerate = %s\n", s);
if (sdi->mode == DSO) {
gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_TIMEBASE);
if (gvar != NULL) {
uint64_t tmp_u64 = g_variant_get_uint64(gvar);
fprintf(meta, "hDiv = %llu\n", tmp_u64);
g_variant_unref(gvar);
}
gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_DSO_BITS);
if (gvar != NULL) {
uint8_t tmp_u8 = g_variant_get_byte(gvar);
fprintf(meta, "bits = %d\n", tmp_u8);
g_variant_unref(gvar);
}
} else if (sdi->mode == LOGIC) {
fprintf(meta, "trigger time = %lld\n", _session.get_trigger_time().toMSecsSinceEpoch());
}
fprintf(meta, "trigger pos = %llu\n", _session.get_trigger_pos());
probecnt = 1;
for (l = sdi->channels; l; l = l->next) {
probe = (struct sr_channel *)l->data;
if (probe->enabled || sdi->mode == DSO) {
if (probe->name)
fprintf(meta, "probe%d = %s\n", probe->index, probe->name);
if (probe->trigger)
fprintf(meta, " trigger%d = %s\n", probe->index, probe->trigger);
if (sdi->mode == DSO) {
fprintf(meta, " enable%d = %d\n", probe->index, probe->enabled);
fprintf(meta, " coupling%d = %d\n", probe->index, probe->coupling);
fprintf(meta, " vDiv%d = %d\n", probe->index, probe->vdiv);
fprintf(meta, " vFactor%d = %d\n", probe->index, probe->vfactor);
fprintf(meta, " vPos%d = %lf\n", probe->index, probe->vpos);
fprintf(meta, " vTrig%d = %d\n", probe->index, probe->trig_value);
if (sr_status_get(sdi, &status, 0, 0) == SR_OK) {
if (probe->index == 0) {
fprintf(meta, " period%d = %llu\n", probe->index, status.ch0_period);
fprintf(meta, " pcnt%d = %lu\n", probe->index, status.ch0_pcnt);
fprintf(meta, " max%d = %d\n", probe->index, status.ch0_max);
fprintf(meta, " min%d = %d\n", probe->index, status.ch0_min);
} else {
fprintf(meta, " period%d = %llu\n", probe->index, status.ch1_period);
fprintf(meta, " pcnt%d = %lu\n", probe->index, status.ch1_pcnt);
fprintf(meta, " max%d = %d\n", probe->index, status.ch1_max);
fprintf(meta, " min%d = %d\n", probe->index, status.ch1_min);
}
}
}
probecnt++;
}
}
fclose(meta);
return metafile;
}
bool StoreSession::export_start()
{
std::set<int> type_set;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> sig, _session.get_signals()) {
assert(sig);
type_set.insert(sig->get_type());
}
if (type_set.size() > 1) {
_error = tr("DSView does not currently support"
"file export for multiple data types.");
return false;
} else if (type_set.size() == 0) {
_error = tr("No data to save.");
return false;
}
const boost::shared_ptr<data::Snapshot> snapshot(_session.get_snapshot(*type_set.begin()));
assert(snapshot);
// Check we have data
if (snapshot->empty()) {
_error = tr("No data to save.");
return false;
}
const QString DIR_KEY("ExportPath");
QSettings settings;
// Show the dialog
QList<QString> supportedFormats = getSuportedExportFormats();
QString filter;
for(int i = 0; i < supportedFormats.count();i++){
filter.append(supportedFormats[i]);
if(i < supportedFormats.count() - 1)
filter.append(";;");
}
_file_name = QFileDialog::getSaveFileName(
NULL, tr("Export Data"), settings.value(DIR_KEY).toString(),filter,&filter);
if (!_file_name.isEmpty()) {
QFileInfo f(_file_name);
QStringList list = filter.split('.').last().split(')');
_suffix = list.first();
if(f.suffix().compare(_suffix))
_file_name += tr(".") + _suffix;
QDir CurrentDir;
settings.setValue(DIR_KEY, CurrentDir.absoluteFilePath(_file_name));
const struct sr_output_module** supportedModules = sr_output_list();
while(*supportedModules){
if(*supportedModules == NULL)
break;
if(!strcmp((*supportedModules)->id, _suffix.toLocal8Bit().data())){
_outModule = *supportedModules;
break;
}
supportedModules++;
}
if(_outModule == NULL) {
_error = tr("Invalid export format.");
} else {
_thread = boost::thread(&StoreSession::export_proc, this, snapshot);
return !_has_error;
}
}
_error.clear();
return false;
}
void StoreSession::export_proc(shared_ptr<data::Snapshot> snapshot)
{
assert(snapshot);
shared_ptr<data::LogicSnapshot> logic_snapshot;
shared_ptr<data::AnalogSnapshot> analog_snapshot;
shared_ptr<data::DsoSnapshot> dso_snapshot;
int channel_type;
if (logic_snapshot = boost::dynamic_pointer_cast<data::LogicSnapshot>(snapshot)) {
channel_type = SR_CHANNEL_LOGIC;
} else if (dso_snapshot = boost::dynamic_pointer_cast<data::DsoSnapshot>(snapshot)) {
channel_type = SR_CHANNEL_DSO;
} else {
_has_error = true;
_error = tr("data type don't support.");
return;
}
GHashTable *params = g_hash_table_new(g_str_hash, g_str_equal);
GVariant* filenameGVariant = g_variant_new_bytestring(_file_name.toLocal8Bit().data());
g_hash_table_insert(params, (char*)"filename", filenameGVariant);
GVariant* typeGVariant = g_variant_new_int16(channel_type);
g_hash_table_insert(params, (char*)"type", typeGVariant);
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
boost::shared_ptr<view::DsoSignal> dsoSig;
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
GVariant* timebaseGVariant = g_variant_new_uint64(dsoSig->get_hDialValue());
g_hash_table_insert(params, (char*)"timebase", timebaseGVariant);
break;
}
}
struct sr_output output;
output.module = (sr_output_module*) _outModule;
output.sdi = _session.get_device()->dev_inst();
output.param = NULL;
if(_outModule->init)
_outModule->init(&output, params);
QFile file(_file_name);
file.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream out(&file);
out.setCodec("UTF-8");
out.setGenerateByteOrderMark(true);
if (channel_type == SR_CHANNEL_LOGIC) {
_unit_count = logic_snapshot->get_sample_count();
int blk_num = logic_snapshot->get_block_num();
bool sample;
std::vector<uint8_t *> buf_vec;
std::vector<bool> buf_sample;
for (int blk = 0; !boost::this_thread::interruption_requested() &&
blk < blk_num; blk++) {
uint64_t buf_sample_num = logic_snapshot->get_block_size(blk) * 8;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
int ch_type = s->get_type();
if (ch_type == SR_CHANNEL_LOGIC) {
int ch_index = s->get_index();
if (!logic_snapshot->has_data(ch_index))
continue;
uint8_t *buf = logic_snapshot->get_block_buf(blk, ch_index, sample);
buf_vec.push_back(buf);
buf_sample.push_back(sample);
}
}
uint16_t unitsize = ceil(buf_vec.size() / 8.0);
GString *data_out;
unsigned int usize = 8192;
unsigned int size = usize;
struct sr_datafeed_logic lp;
struct sr_datafeed_packet p;
for(uint64_t i = 0; !boost::this_thread::interruption_requested() &&
i < buf_sample_num; i+=usize){
if(buf_sample_num - i < usize)
size = buf_sample_num - i;
uint8_t *xbuf = (uint8_t *)malloc(size * unitsize);
if (xbuf == NULL) {
_has_error = true;
_error = tr("xbuffer malloc failed.");
return;
}
memset(xbuf, 0, size * unitsize);
for (uint64_t j = 0; j < usize; j++) {
for (unsigned int k = 0; k < buf_vec.size(); k++) {
if (buf_vec[k] == NULL && buf_sample[k])
xbuf[j*unitsize+k/8] += 1 << k%8;
else if (buf_vec[k] && (buf_vec[k][(i+j)/8] & (1 << j%8)))
xbuf[j*unitsize+k/8] += 1 << k%8;
}
}
lp.data = xbuf;
lp.length = size * unitsize;
lp.unitsize = unitsize;
p.type = SR_DF_LOGIC;
p.status = SR_PKT_OK;
p.payload = &lp;
_outModule->receive(&output, &p, &data_out);
if(data_out){
out << QString::fromUtf8((char*) data_out->str);
g_string_free(data_out,TRUE);
}
_units_stored += size;
if (xbuf)
free(xbuf);
progress_updated();
}
}
} else if (channel_type = SR_CHANNEL_DSO) {
_unit_count = snapshot->get_sample_count();
unsigned char* datat = (unsigned char*)snapshot->get_data();
GString *data_out;
unsigned int usize = 8192;
unsigned int size = usize;
struct sr_datafeed_dso dp;
struct sr_datafeed_packet p;
for(uint64_t i = 0; !boost::this_thread::interruption_requested() && i < _unit_count; i+=usize){
if(_unit_count - i < usize)
size = _unit_count - i;
dp.data = &datat[i*snapshot->get_channel_num()];
dp.num_samples = size;
p.type = SR_DF_DSO;
p.status = SR_PKT_OK;
p.payload = &dp;
_outModule->receive(&output, &p, &data_out);
if(data_out){
out << (char*) data_out->str;
g_string_free(data_out,TRUE);
}
_units_stored += size;
progress_updated();
}
}
// optional, as QFile destructor will already do it:
file.close();
_outModule->cleanup(&output);
g_hash_table_destroy(params);
g_variant_unref(filenameGVariant);
progress_updated();
}
#ifdef ENABLE_DECODE
QString StoreSession::decoders_gen()
{
QDir dir;
#if QT_VERSION >= 0x050400
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
#else
QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
#endif
if(dir.mkpath(path)) {
dir.cd(path);
QString file_name = dir.absolutePath() + "/DSView-decoders-XXXXXX";
QFile sessionFile(file_name);
if (!sessionFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug("Warning: Couldn't open session file to write!");
return NULL;
}
QTextStream outStream(&sessionFile);
outStream.setCodec("UTF-8");
outStream.setGenerateByteOrderMark(true);
QJsonArray dec_array = json_decoders();
QJsonDocument sessionDoc(dec_array);
outStream << QString::fromUtf8(sessionDoc.toJson());
sessionFile.close();
return file_name;
} else {
return NULL;
}
}
QJsonArray StoreSession::json_decoders()
{
QJsonArray dec_array;
BOOST_FOREACH(boost::shared_ptr<view::DecodeTrace> t, _session.get_decode_signals()) {
QJsonObject dec_obj;
QJsonArray stack_array;
QJsonObject show_obj;
const boost::shared_ptr<data::DecoderStack>& stack = t->decoder();
const std::list< boost::shared_ptr<data::decode::Decoder> >& decoder = stack->stack();
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec, decoder) {
QJsonArray ch_array;
const srd_decoder *const d = dec->decoder();;
const bool have_probes = (d->channels || d->opt_channels) != 0;
if (have_probes) {
for(std::map<const srd_channel*, int>::const_iterator i = dec->channels().begin();
i != dec->channels().end(); i++) {
QJsonObject ch_obj;
ch_obj[(*i).first->id] = QJsonValue::fromVariant((*i).second);
ch_array.push_back(ch_obj);
}
}
QJsonObject options_obj;
boost::shared_ptr<prop::binding::DecoderOptions> dec_binding(
new prop::binding::DecoderOptions(stack, dec));
for (GSList *l = d->options; l; l = l->next)
{
const srd_decoder_option *const opt =
(srd_decoder_option*)l->data;
const std::map<string, GVariant*>& options = dec->options();
std::map<string, GVariant*>::const_iterator iter = options.find(opt->id);
if (opt->values) {
for (GSList *vl = opt->values; vl; vl = vl->next) {
GVariant *const var = (GVariant*)vl->data;
assert(var);
if (iter == options.end()) {
options_obj[opt->id] = QJsonValue::fromVariant(dec_binding->print_gvariant(opt->def));
break;
} else if (g_variant_compare((*iter).second, var) == 0) {
options_obj[opt->id] = QJsonValue::fromVariant(dec_binding->print_gvariant(var));
break;
}
}
} else if (g_variant_is_of_type(opt->def, G_VARIANT_TYPE("d"))) {
GVariant *const var = dec_binding->getter(opt->id);
options_obj[opt->id] = QJsonValue::fromVariant(g_variant_get_double(var));
g_variant_unref(var);
} else if (g_variant_is_of_type(opt->def, G_VARIANT_TYPE("x"))) {
GVariant *const var = dec_binding->getter(opt->id);
options_obj[opt->id] = QJsonValue::fromVariant(get_double(var));
g_variant_unref(var);
} else if (g_variant_is_of_type(opt->def, G_VARIANT_TYPE("s"))) {
GVariant *const var = dec_binding->getter(opt->id);
options_obj[opt->id] = QJsonValue::fromVariant(g_variant_get_string(var, NULL));
g_variant_unref(var);
}else {
continue;
}
}
if (have_probes) {
dec_obj["id"] = QJsonValue::fromVariant(d->id);
dec_obj["channel"] = ch_array;
dec_obj["options"] = options_obj;
} else {
QJsonObject stack_obj;
stack_obj["id"] = QJsonValue::fromVariant(d->id);
stack_obj["options"] = options_obj;
stack_array.push_back(stack_obj);
}
show_obj[d->id] = QJsonValue::fromVariant(dec->shown());
}
dec_obj["stacked decoders"] = stack_array;
std::map<const pv::data::decode::Row, bool> rows = stack->get_rows_gshow();
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
show_obj[(*i).first.title()] = QJsonValue::fromVariant((*i).second);
}
dec_obj["show"] = show_obj;
dec_array.push_back(dec_obj);
}
return dec_array;
}
void StoreSession::load_decoders(dock::ProtocolDock *widget, QJsonArray dec_array)
{
if (_session.get_device()->dev_inst()->mode != LOGIC ||
dec_array.empty())
return;
foreach (const QJsonValue &dec_value, dec_array) {
QJsonObject dec_obj = dec_value.toObject();
const vector< boost::shared_ptr<view::DecodeTrace> > pre_dsigs(
_session.get_decode_signals());
if (widget->sel_protocol(dec_obj["id"].toString()))
widget->add_protocol(true);
const vector< boost::shared_ptr<view::DecodeTrace> > aft_dsigs(
_session.get_decode_signals());
if (aft_dsigs.size() > pre_dsigs.size()) {
const GSList *l;
boost::shared_ptr<view::DecodeTrace> new_dsig = aft_dsigs.back();
const boost::shared_ptr<data::DecoderStack>& stack = new_dsig->decoder();
if (dec_obj.contains("stacked decoders")) {
foreach(const QJsonValue &value, dec_obj["stacked decoders"].toArray()) {
QJsonObject stacked_obj = value.toObject();
GSList *dl = g_slist_copy((GSList*)srd_decoder_list());
for(; dl; dl = dl->next) {
const srd_decoder *const d = (srd_decoder*)dl->data;
assert(d);
if (QString::fromUtf8(d->id) == stacked_obj["id"].toString()) {
stack->push(boost::shared_ptr<data::decode::Decoder>(
new data::decode::Decoder(d)));
break;
}
}
g_slist_free(dl);
}
}
const std::list< boost::shared_ptr<data::decode::Decoder> >& decoder = stack->stack();
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec, decoder) {
const srd_decoder *const d = dec->decoder();
QJsonObject options_obj;
if (dec == decoder.front()) {
std::map<const srd_channel*, int> probe_map;
// Load the mandatory channels
for(l = d->channels; l; l = l->next) {
const struct srd_channel *const pdch =
(struct srd_channel *)l->data;
foreach (const QJsonValue &value, dec_obj["channel"].toArray()) {
QJsonObject ch_obj = value.toObject();
if (ch_obj.contains(pdch->id)) {
probe_map[pdch] = ch_obj[pdch->id].toInt();
break;
}
}
}
// Load the optional channels
for(l = d->opt_channels; l; l = l->next) {
const struct srd_channel *const pdch =
(struct srd_channel *)l->data;
foreach (const QJsonValue &value, dec_obj["channel"].toArray()) {
QJsonObject ch_obj = value.toObject();
if (ch_obj.contains(pdch->id)) {
probe_map[pdch] = ch_obj[pdch->id].toInt();
break;
}
}
}
dec->set_probes(probe_map);
options_obj = dec_obj["options"].toObject();
} else {
foreach(const QJsonValue &value, dec_obj["stacked decoders"].toArray()) {
QJsonObject stacked_obj = value.toObject();
if (QString::fromUtf8(d->id) == stacked_obj["id"].toString()) {
options_obj = stacked_obj["options"].toObject();
break;
}
}
}
for (l = d->options; l; l = l->next) {
const srd_decoder_option *const opt =
(srd_decoder_option*)l->data;
if (options_obj.contains(opt->id)) {
if (opt->values) {
QString enum_option = options_obj[opt->id].toString();
for (GSList *vl = opt->values; vl; vl = vl->next) {
GVariant *const var = (GVariant*)vl->data;
assert(var);
if (enum_option == QString::fromUtf8(g_variant_get_string(var, NULL))) {
dec->set_option(opt->id, var);
break;
}
}
} else if (g_variant_is_of_type(opt->def, G_VARIANT_TYPE("d"))) {
double d_option = options_obj[opt->id].toDouble();
dec->set_option(opt->id, g_variant_new_double(d_option));
} else if (g_variant_is_of_type(opt->def, G_VARIANT_TYPE("x"))) {
int64_t d_option = options_obj[opt->id].toDouble();
GVariant *new_value = NULL;
const GVariantType *const type = g_variant_get_type(opt->def);
if (g_variant_type_equal(type, G_VARIANT_TYPE_BYTE))
new_value = g_variant_new_byte(d_option);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT16))
new_value = g_variant_new_int16(d_option);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT16))
new_value = g_variant_new_uint16(d_option);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT32))
new_value = g_variant_new_int32(d_option);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT32))
new_value = g_variant_new_int32(d_option);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT64))
new_value = g_variant_new_int64(d_option);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT64))
new_value = g_variant_new_uint64(d_option);
if (new_value != NULL)
dec->set_option(opt->id, new_value);
} else if (g_variant_is_of_type(opt->def, G_VARIANT_TYPE("s"))) {
QString s_option = options_obj[opt->id].toString();
dec->set_option(opt->id, g_variant_new_string(s_option.toLocal8Bit().data()));
}
}
}
dec->commit();
if (dec_obj.contains("show")) {
QJsonObject show_obj = dec_obj["show"].toObject();
if (show_obj.contains(d->id)) {
dec->show(show_obj[d->id].toBool());
}
}
}
if (dec_obj.contains("show")) {
QJsonObject show_obj = dec_obj["show"].toObject();
std::map<const pv::data::decode::Row, bool> rows = stack->get_rows_gshow();
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
if (show_obj.contains((*i).first.title())) {
stack->set_rows_gshow((*i).first, show_obj[(*i).first.title()].toBool());
}
}
}
}
}
}
#endif
double StoreSession::get_double(GVariant *var)
{
double val;
const GVariantType *const type = g_variant_get_type(var);
assert(type);
if (g_variant_type_equal(type, G_VARIANT_TYPE_BYTE))
val = g_variant_get_byte(var);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT16))
val = g_variant_get_int16(var);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT16))
val = g_variant_get_uint16(var);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT32))
val = g_variant_get_int32(var);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT32))
val = g_variant_get_uint32(var);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT64))
val = g_variant_get_int64(var);
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT64))
val = g_variant_get_uint64(var);
else
assert(0);
return val;
}
} // pv

View File

@@ -2,6 +2,7 @@
* This file is part of the PulseView project.
*
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,19 +23,25 @@
#define DSVIEW_PV_STORESESSION_H
#include <stdint.h>
#include <string>
#include <boost/thread.hpp>
#include <QObject>
#include <libsigrok4DSL/libsigrok.h>
#include <libsigrokdecode/libsigrokdecode.h>
namespace pv {
class SigSession;
namespace data {
class LogicSnapshot;
class Snapshot;
}
namespace dock {
class ProtocolDock;
}
class StoreSession : public QObject
@@ -42,11 +49,10 @@ class StoreSession : public QObject
Q_OBJECT
private:
static const size_t BlockSize;
const static int File_Version = 2;
public:
StoreSession(const std::string &file_name,
SigSession &session);
StoreSession(SigSession &session);
~StoreSession();
@@ -54,27 +60,48 @@ public:
const QString& error() const;
bool start();
bool save_start();
bool export_start();
void wait();
void cancel();
private:
void store_proc(boost::shared_ptr<pv::data::LogicSnapshot> snapshot);
void save_proc(boost::shared_ptr<pv::data::Snapshot> snapshot);
QString meta_gen(boost::shared_ptr<data::Snapshot> snapshot);
void export_proc(boost::shared_ptr<pv::data::Snapshot> snapshot);
#ifdef ENABLE_DECODE
QString decoders_gen();
#endif
public:
#ifdef ENABLE_DECODE
QJsonArray json_decoders();
void load_decoders(dock::ProtocolDock *widget, QJsonArray dec_array);
#endif
private:
QList<QString> getSuportedExportFormats();
double get_double(GVariant * var);
signals:
void progress_updated();
private:
const std::string _file_name;
QString _file_name;
QString _suffix;
SigSession &_session;
boost::thread _thread;
const struct sr_output_module* _outModule;
//mutable boost::mutex _mutex;
uint64_t _units_stored;
uint64_t _unit_count;
bool _has_error;
QString _error;
};

View File

@@ -91,13 +91,13 @@ FileBar::FileBar(SigSession &session, QWidget *parent) :
_action_save->setIcon(QIcon::fromTheme("file",
QIcon(":/icons/save.png")));
_action_save->setObjectName(QString::fromUtf8("actionSave"));
connect(_action_save, SIGNAL(triggered()), this, SLOT(on_actionSave_triggered()));
connect(_action_save, SIGNAL(triggered()), this, SIGNAL(on_save()));
_action_export = new QAction(this);
_action_export->setText(QApplication::translate("File", "&Export...", 0));
_action_export->setIcon(QIcon::fromTheme("file",QIcon(":/icons/export.png")));
_action_export->setObjectName(QString::fromUtf8("actionExport"));
connect(_action_export, SIGNAL(triggered()), this, SLOT(on_actionExport_triggered()));
connect(_action_export, SIGNAL(triggered()), this, SIGNAL(on_export()));
_action_capture = new QAction(this);
@@ -119,9 +119,6 @@ FileBar::FileBar(SigSession &session, QWidget *parent) :
_menu->addAction(_action_capture);
_file_button.setMenu(_menu);
addWidget(&_file_button);
_screenshot_timer.setSingleShot(true);
connect(&_screenshot_timer, SIGNAL(timeout()), this, SIGNAL(on_screenShot()));
}
void FileBar::on_actionOpen_triggered()
@@ -131,7 +128,7 @@ void FileBar::on_actionOpen_triggered()
// Show the dialog
const QString file_name = QFileDialog::getOpenFileName(
this, tr("Open File"), settings.value(DIR_KEY).toString(), tr(
"DSView Data (*.dsl);;All Files (*.*)"));
"DSView Data (*.dsl)"));
if (!file_name.isEmpty()) {
QDir CurrentDir;
settings.setValue(DIR_KEY, CurrentDir.absoluteFilePath(file_name));
@@ -158,74 +155,6 @@ void FileBar::show_session_error(
msg.exec();
}
void FileBar::on_actionExport_triggered(){
const QString DIR_KEY("ExportPath");
QSettings settings;
int unit_size;
uint64_t length;
const void* buf = _session.get_buf(unit_size, length);
if (!buf) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Data Export"));
msg.mBox()->setInformativeText(tr("No Data to Save!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
} else {
QList<QString> supportedFormats = _session.getSuportedExportFormats();
QString filter;
for(int i = 0; i < supportedFormats.count();i++){
filter.append(supportedFormats[i]);
if(i < supportedFormats.count() - 1)
filter.append(";;");
}
QString file_name = QFileDialog::getSaveFileName(
this, tr("Export Data"), settings.value(DIR_KEY).toString(),filter,&filter);
if (!file_name.isEmpty()) {
QFileInfo f(file_name);
QStringList list = filter.split('.').last().split(')');
QString ext = list.first();
if(f.suffix().compare(ext))
file_name+=tr(".")+ext;
QDir CurrentDir;
settings.setValue(DIR_KEY, CurrentDir.absoluteFilePath(file_name));
_session.export_file(file_name, this, ext);
}
}
}
void FileBar::on_actionSave_triggered()
{
const QString DIR_KEY("SavePath");
QSettings settings;
//save();
int unit_size;
uint64_t length;
const void* buf = _session.get_buf(unit_size, length);
if (!buf) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("File Save"));
msg.mBox()->setInformativeText(tr("No Data to Save!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
} else {
QString file_name = QFileDialog::getSaveFileName(
this, tr("Save File"), settings.value(DIR_KEY).toString(),
tr("DSView Data (*.dsl)"));
if (!file_name.isEmpty()) {
QFileInfo f(file_name);
if(f.suffix().compare("dsl"))
file_name.append(tr(".dsl"));
QDir CurrentDir;
settings.setValue(DIR_KEY, CurrentDir.absoluteFilePath(file_name));
_session.save_file(file_name, this, _session.get_device()->dev_inst()->mode);
}
}
}
void FileBar::on_actionLoad_triggered()
{
const QString DIR_KEY("SessionLoadPath");
@@ -282,7 +211,7 @@ void FileBar::on_actionCapture_triggered()
{
_file_button.close();
QCoreApplication::sendPostedEvents();
_screenshot_timer.start(100);
QTimer::singleShot(100, this, SIGNAL(on_screenShot()));
}
void FileBar::enable_toggle(bool enable)

View File

@@ -53,7 +53,8 @@ private:
signals:
void load_file(QString);
void save();
void on_save();
void on_export();
void on_screenShot();
void load_session(QString);
void store_session(QString);
@@ -63,9 +64,7 @@ private slots:
void on_actionStore_triggered();
void on_actionDefault_triggered();
void on_actionOpen_triggered();
void on_actionSave_triggered();
void on_actionCapture_triggered();
void on_actionExport_triggered();
private:
bool _enable;
@@ -84,9 +83,6 @@ private:
QAction *_action_save;
QAction *_action_export;
QAction *_action_capture;
QTimer _screenshot_timer;
};
} // namespace toolbars

View File

@@ -32,6 +32,7 @@
#include <QDebug>
#include <QLabel>
#include <QAbstractItemView>
#include <QApplication>
#include "samplingbar.h"
@@ -41,6 +42,7 @@
#include "../dialogs/waitingdialog.h"
#include "../dialogs/dsmessagebox.h"
#include "../view/dsosignal.h"
#include "../dialogs/interval.h"
using namespace boost;
using boost::shared_ptr;
@@ -74,12 +76,15 @@ const uint64_t SamplingBar::RecordLengths[19] = {
40000000,
};
const QString SamplingBar::RLEString = "(RLE)";
const uint64_t SamplingBar::DefaultRecordLength = 1000000;
SamplingBar::SamplingBar(SigSession &session, QWidget *parent) :
QToolBar("Sampling Bar", parent),
_session(session),
_enable(true),
_sampling(false),
_device_selector(this),
_updating_device_selector(false),
_configure_button(this),
@@ -94,6 +99,11 @@ SamplingBar::SamplingBar(SigSession &session, QWidget *parent) :
_icon_instant_dis(":/icons/instant_dis.png"),
_run_stop_button(this),
_instant_button(this),
_mode_button(this),
_icon_repeat(":/icons/moder.png"),
_icon_single(":/icons/modes.png"),
_icon_repeat_dis(":/icons/moder_dis.png"),
_icon_single_dis(":/icons/modes_dis.png"),
_instant(false)
{
setMovable(false);
@@ -112,6 +122,8 @@ SamplingBar::SamplingBar(SigSession &session, QWidget *parent) :
_configure_button.setIcon(QIcon::fromTheme("configure",
QIcon(":/icons/params.png")));
_mode_button.setPopupMode(QToolButton::InstantPopup);
_mode_button.setIcon(_session.get_run_mode() == pv::SigSession::Single ? _icon_single : _icon_repeat);
_run_stop_button.setIcon(_icon_start);
_instant_button.setIcon(_icon_instant);
@@ -138,6 +150,25 @@ SamplingBar::SamplingBar(SigSession &session, QWidget *parent) :
addWidget(&_sample_count);
addWidget(new QLabel(tr(" @ ")));
addWidget(&_sample_rate);
_action_single = new QAction(this);
_action_single->setText(QApplication::translate("Sampling", "&Single", 0));
_action_single->setIcon(QIcon::fromTheme("Sampling",
QIcon(":/icons/oneloop.png")));
connect(_action_single, SIGNAL(triggered()), this, SLOT(on_mode()));
_action_repeat = new QAction(this);
_action_repeat->setText(QApplication::translate("Sampling", "&Repetitive", 0));
_action_repeat->setIcon(QIcon::fromTheme("Sampling",
QIcon(":/icons/repeat.png")));
connect(_action_repeat, SIGNAL(triggered()), this, SLOT(on_mode()));
_mode_menu = new QMenu(this);
_mode_menu->addAction(_action_single);
_mode_menu->addAction(_action_repeat);
_mode_button.setMenu(_mode_menu);
_mode_action = addWidget(&_mode_button);
_run_stop_action = addWidget(&_run_stop_button);
_instant_action = addWidget(&_instant_button);
}
@@ -245,10 +276,8 @@ void SamplingBar::on_configure()
if (test) {
update_sample_count_selector_value();
update_sample_rate_selector_value();
#ifndef TEST_MODE
_sample_count.setDisabled(true);
_sample_rate.setDisabled(true);
#endif
} else if (dev_inst->dev_inst()->mode != DSO) {
_sample_count.setDisabled(false);
_sample_rate.setDisabled(false);
@@ -277,7 +306,7 @@ void SamplingBar::zero_adj()
}
if (_session.get_capture_state() == pv::SigSession::Running)
run_stop();
on_run_stop();
}
uint64_t SamplingBar::get_record_length() const
@@ -322,8 +351,20 @@ void SamplingBar::update_sample_rate()
this, SLOT(on_samplerate_sel(int)));
}
bool SamplingBar::get_sampling() const
{
return _sampling;
}
bool SamplingBar::get_instant() const
{
return _instant;
}
void SamplingBar::set_sampling(bool sampling)
{
lock_guard<boost::recursive_mutex> lock(_sampling_mutex);
_sampling = sampling;
if (_instant) {
_instant_button.setIcon(sampling ? _icon_stop : _icon_instant);
_run_stop_button.setIcon(sampling ? _icon_start_dis : _icon_start);
@@ -342,6 +383,9 @@ void SamplingBar::set_sampling(bool sampling)
enable_run_stop(true);
}
_mode_button.setEnabled(!sampling);
_mode_button.setIcon(sampling ? (_session.get_run_mode() == pv::SigSession::Single ? _icon_single_dis : _icon_repeat_dis) :
(_session.get_run_mode() == pv::SigSession::Single ? _icon_single : _icon_repeat));
_configure_button.setEnabled(!sampling);
_configure_button.setIcon(sampling ? QIcon(":/icons/params_dis.png") :
QIcon(":/icons/params.png"));
@@ -482,7 +526,6 @@ void SamplingBar::on_samplecount_sel(int index)
{
uint64_t sample_count = 0;
qDebug() << "index: " << index;
if (index >= 0)
sample_count = _sample_count.itemData(
index).value<uint64_t>();
@@ -509,13 +552,13 @@ void SamplingBar::on_samplerate_sel(int index)
sample_rate = _sample_rate.itemData(
index).value<uint64_t>();
boost::shared_ptr<pv::device::DevInst> _devInst = get_selected_device();
assert(_devInst);
boost::shared_ptr<pv::device::DevInst> dev_inst = get_selected_device();
assert(dev_inst);
// Get last samplerate
//last_sample_rate = get_selected_device()->get_sample_rate();
if (_devInst->name() == "DSLogic" && _devInst->dev_inst()->mode != DSO) {
if (dev_inst->name() == "DSLogic" && dev_inst->dev_inst()->mode != DSO) {
// Set the samplerate
get_selected_device()->set_config(NULL, NULL,
SR_CONF_SAMPLERATE,
@@ -529,7 +572,8 @@ void SamplingBar::update_sample_count_selector()
const uint64_t *elements = NULL;
gsize num_elements;
bool stream_mode = false;
uint64_t max_sample_count = 0;
uint64_t hw_depth;
uint64_t sw_depth;
if (_updating_sample_count)
return;
@@ -557,9 +601,9 @@ void SamplingBar::update_sample_count_selector()
stream_mode = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
}
gvar = dev_inst->get_config(NULL, NULL, SR_CONF_RLE_SAMPLELIMITS);
gvar = dev_inst->get_config(NULL, NULL, SR_CONF_HW_DEPTH);
if (gvar != NULL) {
max_sample_count = g_variant_get_uint64(gvar);
hw_depth = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
}
@@ -570,11 +614,23 @@ void SamplingBar::update_sample_count_selector()
gvar_list, &num_elements, sizeof(uint64_t));
_sample_count.clear();
#if defined(__x86_64__) || defined(_M_X64)
sw_depth = elements[num_elements - 1];
#elif defined(__i386) || defined(_M_IX86)
int ch_num = _session.get_ch_num(SR_CHANNEL_LOGIC);
if (ch_num <= 0)
sw_depth = SR_GB(8);
else
sw_depth = SR_GB(8) / ch_num;
#endif
for (unsigned int i = 0; i < num_elements; i++)
{
if (elements[i] > sw_depth)
break;
char *const s = sr_samplecount_string(elements[i]);
if (!stream_mode && (elements[i] > max_sample_count))
_sample_count.addItem(QString(s)+"(RLE)",
if (!stream_mode && (elements[i] > hw_depth))
_sample_count.addItem(QString(s)+RLEString,
qVariantFromValue(elements[i]));
else
_sample_count.addItem(QString(s),
@@ -647,81 +703,118 @@ void SamplingBar::commit_sample_count()
g_variant_new_uint64(sample_count));
}
bool rle_mode = _sample_count.currentText().contains(RLEString);
get_selected_device()->set_config(NULL, NULL,
SR_CONF_RLE,
g_variant_new_boolean(rle_mode));
_updating_sample_count = false;
}
void SamplingBar::on_run_stop()
{
enable_run_stop(false);
enable_instant(false);
commit_sample_rate();
commit_sample_count();
_instant = false;
const shared_ptr<device::DevInst> dev_inst = get_selected_device();
if (!dev_inst)
return;
if (dev_inst->dev_inst()->mode == DSO) {
GVariant* gvar = dev_inst->get_config(NULL, NULL, SR_CONF_ZERO);
if (gvar != NULL) {
bool zero = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
if (zero) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Zero Adjustment"));
msg.mBox()->setInformativeText(tr("Please adjust zero skew and save the result!"));
//msg.setStandardButtons(QMessageBox::Ok);
msg.mBox()->addButton(tr("Ok"), QMessageBox::AcceptRole);
msg.mBox()->addButton(tr("Skip"), QMessageBox::RejectRole);
msg.mBox()->setIcon(QMessageBox::Warning);
if (msg.exec()) {
zero_adj();
} else {
dev_inst->set_config(NULL, NULL, SR_CONF_ZERO, g_variant_new_boolean(false));
enable_run_stop(true);
enable_instant(true);
}
return;
if (get_sampling() || _session.isRepeating()) {
_session.set_repeating(false);
bool wait_upload = false;
if (_session.get_run_mode() != SigSession::Repetitive) {
GVariant *gvar = get_selected_device()->get_config(NULL, NULL, SR_CONF_WAIT_UPLOAD);
if (gvar != NULL) {
wait_upload = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
}
}
if (!wait_upload) {
_session.stop_capture();
_session.capture_state_changed(SigSession::Stopped);
}
} else {
enable_run_stop(false);
enable_instant(false);
commit_sample_rate();
commit_sample_count();
_instant = false;
const shared_ptr<device::DevInst> dev_inst = get_selected_device();
if (!dev_inst)
return;
if (dev_inst->dev_inst()->mode == DSO) {
GVariant* gvar = dev_inst->get_config(NULL, NULL, SR_CONF_ZERO);
if (gvar != NULL) {
bool zero = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
if (zero) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Auto Calibration"));
msg.mBox()->setInformativeText(tr("Please adjust zero skew and save the result!"));
//msg.setStandardButtons(QMessageBox::Ok);
msg.mBox()->addButton(tr("Ok"), QMessageBox::AcceptRole);
msg.mBox()->addButton(tr("Skip"), QMessageBox::RejectRole);
msg.mBox()->setIcon(QMessageBox::Warning);
if (msg.exec()) {
zero_adj();
} else {
dev_inst->set_config(NULL, NULL, SR_CONF_ZERO, g_variant_new_boolean(false));
enable_run_stop(true);
enable_instant(true);
}
return;
}
}
}
run_stop();
}
run_stop();
}
void SamplingBar::on_instant_stop()
{
enable_run_stop(false);
enable_instant(false);
commit_sample_rate();
commit_sample_count();
_instant = true;
const shared_ptr<device::DevInst> dev_inst = get_selected_device();
if (!dev_inst)
return;
if (dev_inst->dev_inst()->mode == DSO) {
GVariant* gvar = dev_inst->get_config(NULL, NULL, SR_CONF_ZERO);
if (gvar != NULL) {
bool zero = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
if (zero) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Zero Adjustment"));
msg.mBox()->setInformativeText(tr("Zero adjustment program will be started. Please keep all channels out of singal input. It can take a while!"));
//msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->addButton(tr("Ok"), QMessageBox::AcceptRole);
msg.mBox()->addButton(tr("Skip"), QMessageBox::RejectRole);
msg.mBox()->setIcon(QMessageBox::Warning);
if (msg.exec()) {
zero_adj();
} else {
dev_inst->set_config(NULL, NULL, SR_CONF_ZERO, g_variant_new_boolean(false));
enable_run_stop(true);
enable_instant(true);
}
return;
if (get_sampling()) {
_session.set_repeating(false);
bool wait_upload = false;
if (_session.get_run_mode() != SigSession::Repetitive) {
GVariant *gvar = get_selected_device()->get_config(NULL, NULL, SR_CONF_WAIT_UPLOAD);
if (gvar != NULL) {
wait_upload = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
}
}
if (!wait_upload) {
_session.stop_capture();
_session.capture_state_changed(SigSession::Stopped);
}
} else {
enable_run_stop(false);
enable_instant(false);
commit_sample_rate();
commit_sample_count();
_instant = true;
const shared_ptr<device::DevInst> dev_inst = get_selected_device();
if (!dev_inst)
return;
if (dev_inst->dev_inst()->mode == DSO) {
GVariant* gvar = dev_inst->get_config(NULL, NULL, SR_CONF_ZERO);
if (gvar != NULL) {
bool zero = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
if (zero) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Auto Calibration"));
msg.mBox()->setInformativeText(tr("Auto Calibration program will be started. Please keep all channels out of singal input. It can take a while!"));
//msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->addButton(tr("Ok"), QMessageBox::AcceptRole);
msg.mBox()->addButton(tr("Skip"), QMessageBox::RejectRole);
msg.mBox()->setIcon(QMessageBox::Warning);
if (msg.exec()) {
zero_adj();
} else {
dev_inst->set_config(NULL, NULL, SR_CONF_ZERO, g_variant_new_boolean(false));
enable_run_stop(true);
enable_instant(true);
}
return;
}
}
}
instant_stop();
}
instant_stop();
}
void SamplingBar::on_device_selected()
@@ -757,6 +850,9 @@ void SamplingBar::enable_toggle(bool enable)
if (!test) {
_sample_count.setDisabled(!enable);
_sample_rate.setDisabled(!enable);
} else {
_sample_count.setDisabled(true);
_sample_rate.setDisabled(true);
}
}
@@ -787,10 +883,17 @@ void SamplingBar::reload()
_icon_instant = QIcon(":/icons/instant.png");
_icon_instant_dis = QIcon(":/icons/instant_dis.png");
_instant_button.setIcon(_icon_instant);
if (_session.get_device()->name() == "virtual-session") {
_mode_action->setVisible(false);
} else {
_mode_button.setIcon(_session.get_run_mode() == pv::SigSession::Single ? _icon_single : _icon_repeat);
_mode_action->setVisible(true);
}
_run_stop_action->setVisible(true);
_instant_action->setVisible(true);
enable_toggle(true);
} else if (_session.get_device()->dev_inst()->mode == ANALOG) {
_mode_action->setVisible(false);
_run_stop_action->setVisible(true);
_instant_action->setVisible(false);
enable_toggle(true);
@@ -798,6 +901,7 @@ void SamplingBar::reload()
_icon_instant = QIcon(":/icons/single.png");
_icon_instant_dis = QIcon(":/icons/single_dis.png");
_instant_button.setIcon(_icon_instant);
_mode_action->setVisible(false);
_run_stop_action->setVisible(true);
_instant_action->setVisible(true);
enable_toggle(false);
@@ -805,5 +909,19 @@ void SamplingBar::reload()
update();
}
void SamplingBar::on_mode()
{
QAction *act = qobject_cast<QAction *>(sender());
if (act == _action_single) {
_mode_button.setIcon(_icon_single);
_session.set_run_mode(pv::SigSession::Single);
} else if (act == _action_repeat) {
_mode_button.setIcon(_icon_repeat);
pv::dialogs::Interval interval_dlg(_session, this);
interval_dlg.exec();
_session.set_run_mode(pv::SigSession::Repetitive);
}
}
} // namespace toolbars
} // namespace pv

View File

@@ -33,6 +33,8 @@
#include <QComboBox>
#include <QToolBar>
#include <QToolButton>
#include <QAction>
#include <QMenu>
#include <libsigrok4DSL/libsigrok.h>
@@ -64,6 +66,7 @@ private:
static const uint64_t RecordLengths[19];
static const uint64_t DefaultRecordLength;
static const int ComboBoxMaxWidth = 200;
static const QString RLEString;
public:
SamplingBar(SigSession &session, QWidget *parent);
@@ -80,6 +83,8 @@ public:
void update_sample_rate();
void set_sampling(bool sampling);
bool get_sampling() const;
bool get_instant() const;
void enable_toggle(bool enable);
@@ -110,6 +115,7 @@ private:
void setting_adj();
private slots:
void on_mode();
void on_run_stop();
void on_instant_stop();
void on_device_selected();
@@ -127,7 +133,9 @@ public slots:
private:
SigSession &_session;
mutable boost::recursive_mutex _sampling_mutex;
bool _enable;
bool _sampling;
QComboBox _device_selector;
std::map<const void*, boost::weak_ptr<device::DevInst> >
@@ -151,6 +159,17 @@ private:
QAction* _run_stop_action;
QAction* _instant_action;
QAction* _mode_action;
QToolButton _mode_button;
QMenu *_mode_menu;
QAction *_action_repeat;
QAction *_action_single;
QIcon _icon_repeat;
QIcon _icon_single;
QIcon _icon_repeat_dis;
QIcon _icon_single_dis;
bool _instant;
};

View File

@@ -85,7 +85,7 @@ void AnalogSignal::paint_mid(QPainter &p, int left, int right)
const int y = get_y() + _totalHeight * 0.5;
const double scale = _view->scale();
assert(scale > 0);
const double offset = _view->offset();
const int64_t offset = _view->offset();
const deque< boost::shared_ptr<pv::data::AnalogSnapshot> > &snapshots =
_data->get_snapshots();
@@ -98,15 +98,15 @@ void AnalogSignal::paint_mid(QPainter &p, int left, int right)
if (snapshot->empty())
return;
if (get_index() >= (int)snapshot->get_channel_num())
const int order = snapshot->get_ch_order(get_index());
if (order == -1)
return;
const double pixels_offset = offset / scale;
const double pixels_offset = offset;
const double samplerate = _data->samplerate();
const double start_time = _data->get_start_time();
const int64_t last_sample = max((int64_t)(snapshot->get_sample_count() - 1), (int64_t)0);
const double samples_per_pixel = samplerate * scale;
const double start = samplerate * (offset - start_time);
const double start = offset * samples_per_pixel;
const double end = start + samples_per_pixel * (right - left);
const int64_t start_sample = min(max((int64_t)floor(start),
@@ -117,17 +117,18 @@ void AnalogSignal::paint_mid(QPainter &p, int left, int right)
if (samples_per_pixel < EnvelopeThreshold)
paint_trace(p, snapshot, y, left,
start_sample, end_sample,
pixels_offset, samples_per_pixel);
pixels_offset, samples_per_pixel, order);
else
paint_envelope(p, snapshot, y, left,
start_sample, end_sample,
pixels_offset, samples_per_pixel);
pixels_offset, samples_per_pixel, order);
}
void AnalogSignal::paint_trace(QPainter &p,
const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot,
int y, int left, const int64_t start, const int64_t end,
const double pixels_offset, const double samples_per_pixel)
const double pixels_offset, const double samples_per_pixel,
int order)
{
const int64_t sample_count = end - start;
const int64_t channel_num = snapshot->get_channel_num();
@@ -145,7 +146,7 @@ void AnalogSignal::paint_trace(QPainter &p,
const float x = (sample / samples_per_pixel -
pixels_offset) + left;
*point++ = QPointF(x,
y - samples[(sample - start) * channel_num + get_index()] * _scale);
y - samples[(sample - start) * channel_num + order] * _scale);
}
p.drawPolyline(points, point - points);
@@ -157,13 +158,14 @@ void AnalogSignal::paint_trace(QPainter &p,
void AnalogSignal::paint_envelope(QPainter &p,
const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot,
int y, int left, const int64_t start, const int64_t end,
const double pixels_offset, const double samples_per_pixel)
const double pixels_offset, const double samples_per_pixel,
int order)
{
using namespace Qt;
using pv::data::AnalogSnapshot;
AnalogSnapshot::EnvelopeSection e;
snapshot->get_envelope_section(e, start, end, samples_per_pixel, get_index());
snapshot->get_envelope_section(e, start, end, samples_per_pixel, order);
if (e.length < 2)
return;
@@ -201,10 +203,5 @@ void AnalogSignal::paint_envelope(QPainter &p,
//delete[] e.samples;
}
const std::vector< std::pair<uint64_t, bool> > AnalogSignal::cur_edges() const
{
}
} // namespace view
} // namespace pv

View File

@@ -64,18 +64,16 @@ public:
**/
void paint_mid(QPainter &p, int left, int right);
const std::vector< std::pair<uint64_t, bool> > cur_edges() const;
private:
void paint_trace(QPainter &p,
const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot,
int y, int left, const int64_t start, const int64_t end,
const double pixels_offset, const double samples_per_pixel);
void paint_trace(QPainter &p,
const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot,
int y, int left, const int64_t start, const int64_t end,
const double pixels_offset, const double samples_per_pixel, int order);
void paint_envelope(QPainter &p,
const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot,
int y, int left, const int64_t start, const int64_t end,
const double pixels_offset, const double samples_per_pixel);
void paint_envelope(QPainter &p,
const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot,
int y, int left, const int64_t start, const int64_t end,
const double pixels_offset, const double samples_per_pixel, int order);
private:
boost::shared_ptr<pv::data::Analog> _data;

View File

@@ -58,25 +58,31 @@ Cursor::Cursor(View &view, QColor color, uint64_t index) :
{
}
QRectF Cursor::get_label_rect(const QRect &rect) const
QRect Cursor::get_label_rect(const QRect &rect, bool &visible) const
{
const double samples_per_pixel = _view.session().cur_samplerate() * _view.scale();
const double x = _index/samples_per_pixel - (_view.offset() / _view.scale());
const double cur_offset = _index / samples_per_pixel;
if (cur_offset < _view.offset() ||
cur_offset > (_view.offset() + _view.width())) {
visible = false;
return QRect(-1, -1, 0, 0);
}
const int64_t x = _index/samples_per_pixel - _view.offset();
const QSizeF label_size(
const QSize label_size(
_text_size.width() + View::LabelPadding.width() * 2,
_text_size.height() + View::LabelPadding.height() * 2);
const float top = rect.height() - label_size.height() -
const int top = rect.height() - label_size.height() -
Cursor::Offset - Cursor::ArrowSize - 0.5f;
const float height = label_size.height();
const int height = label_size.height();
return QRectF(x - label_size.width() / 2, top, label_size.width(), height);
visible = true;
return QRect(x - label_size.width() / 2, top, label_size.width(), height);
}
QRectF Cursor::get_close_rect(const QRect &rect) const
QRect Cursor::get_close_rect(const QRect &rect) const
{
const QRectF r(get_label_rect(rect));
return QRectF(r.right() - CloseSize, r.top(), CloseSize, CloseSize);
return QRect(rect.right() - CloseSize, rect.top(), CloseSize, CloseSize);
}
void Cursor::paint_label(QPainter &p, const QRect &rect,
@@ -85,10 +91,13 @@ void Cursor::paint_label(QPainter &p, const QRect &rect,
assert(index > 0);
using pv::view::Ruler;
bool visible;
compute_text_size(p, prefix);
const QRectF r(get_label_rect(rect));
const QRectF close(get_close_rect(rect));
compute_text_size(p, prefix);
const QRect r(get_label_rect(rect, visible));
if (!visible)
return;
const QRect close(get_close_rect(r));
p.setPen(Qt::transparent);
if (close.contains(QPoint(_view.hover_point().x(), _view.hover_point().y())))
@@ -99,10 +108,10 @@ void Cursor::paint_label(QPainter &p, const QRect &rect,
p.setBrush(Ruler::CursorColor[(index - 1) % 8]);
p.drawRect(r);
const QPointF points[] = {
QPointF(r.left() + r.width() / 2 - ArrowSize, r.bottom()),
QPointF(r.left() + r.width() / 2 + ArrowSize, r.bottom()),
QPointF(r.left() + r.width() / 2, rect.bottom()),
const QPoint points[] = {
QPoint(r.left() + r.width() / 2 - ArrowSize, r.bottom()),
QPoint(r.left() + r.width() / 2 + ArrowSize, r.bottom()),
QPoint(r.left() + r.width() / 2, rect.bottom()),
};
p.drawPolygon(points, countof(points));
@@ -118,7 +127,7 @@ void Cursor::paint_label(QPainter &p, const QRect &rect,
p.drawText(r, Qt::AlignCenter | Qt::AlignVCenter,
Ruler::format_real_time(_index, _view.session().cur_samplerate()));
const QRectF arrowRect = QRectF(r.bottomLeft().x(), r.bottomLeft().y(), r.width(), ArrowSize);
const QRect arrowRect = QRect(r.bottomLeft().x(), r.bottomLeft().y(), r.width(), ArrowSize);
p.drawText(arrowRect, Qt::AlignCenter | Qt::AlignVCenter, QString::number(index));
}
@@ -126,18 +135,21 @@ void Cursor::paint_fix_label(QPainter &p, const QRect &rect,
unsigned int prefix, QChar label, QColor color)
{
using pv::view::Ruler;
bool visible;
compute_text_size(p, prefix);
const QRectF r(get_label_rect(rect));
const QRect r(get_label_rect(rect, visible));
if (!visible)
return;
p.setPen(Qt::transparent);
p.setBrush(color);
p.drawRect(r);
const QPointF points[] = {
QPointF(r.left() + r.width() / 2 - ArrowSize, r.bottom()),
QPointF(r.left() + r.width() / 2 + ArrowSize, r.bottom()),
QPointF(r.left() + r.width() / 2, rect.bottom()),
const QPoint points[] = {
QPoint(r.left() + r.width() / 2 - ArrowSize, r.bottom()),
QPoint(r.left() + r.width() / 2 + ArrowSize, r.bottom()),
QPoint(r.left() + r.width() / 2, rect.bottom()),
};
p.drawPolygon(points, countof(points));
@@ -145,14 +157,14 @@ void Cursor::paint_fix_label(QPainter &p, const QRect &rect,
p.drawText(r, Qt::AlignCenter | Qt::AlignVCenter,
Ruler::format_real_time(_index, _view.session().cur_samplerate()));
const QRectF arrowRect = QRectF(r.bottomLeft().x(), r.bottomLeft().y(), r.width(), ArrowSize);
const QRect arrowRect = QRect(r.bottomLeft().x(), r.bottomLeft().y(), r.width(), ArrowSize);
p.drawText(arrowRect, Qt::AlignCenter | Qt::AlignVCenter, label);
}
void Cursor::compute_text_size(QPainter &p, unsigned int prefix)
{
(void)prefix;
_text_size = p.boundingRect(QRectF(), 0,
_text_size = p.boundingRect(QRect(), 0,
Ruler::format_real_time(_index, _view.session().cur_samplerate())).size();
}

View File

@@ -64,9 +64,9 @@ public:
* @param rect The rectangle of the ruler client area.
* @return Returns the label rectangle.
*/
QRectF get_label_rect(const QRect &rect) const;
QRect get_label_rect(const QRect &rect, bool &visible) const;
QRectF get_close_rect(const QRect &rect) const;
QRect get_close_rect(const QRect &rect) const;
/**
* Paints the cursor's label to the ruler.

View File

@@ -179,8 +179,8 @@ void DecodeTrace::paint_back(QPainter &p, int left, int right)
// --draw decode region control
const double samples_per_pixel = _session.cur_samplerate() * _view->scale();
const double startX = _decode_start/samples_per_pixel - (_view->offset() / _view->scale());
const double endX = _decode_end/samples_per_pixel - (_view->offset() / _view->scale());
const double startX = _decode_start/samples_per_pixel - _view->offset();
const double endX = _decode_end/samples_per_pixel - _view->offset();
const double regionY = get_y() - _totalHeight*0.5 - ControlRectWidth;
p.setBrush(Signal::dsBlue);
@@ -245,41 +245,42 @@ void DecodeTrace::paint_mid(QPainter &p, int left, int right)
if (!err.isEmpty())
{
draw_error(p, err, left, right);
return;
//return;
}
const double scale = _view->scale();
assert(scale > 0);
const double scale = _view->scale();
assert(scale > 0);
double samplerate = _decoder_stack->samplerate();
double samplerate = _decoder_stack->samplerate();
_cur_row_headings.clear();
_cur_row_headings.clear();
// Show sample rate as 1Hz when it is unknown
if (samplerate == 0.0)
samplerate = 1.0;
// Show sample rate as 1Hz when it is unknown
if (samplerate == 0.0)
samplerate = 1.0;
const double pixels_offset = (_view->offset() -
_decoder_stack->get_start_time()) / scale;
const double samples_per_pixel = samplerate * scale;
const int64_t pixels_offset = _view->offset();
const double samples_per_pixel = samplerate * scale;
const uint64_t start_sample = (uint64_t)max((left + pixels_offset) *
samples_per_pixel, 0.0);
uint64_t start_sample = (uint64_t)max((left + pixels_offset) *
samples_per_pixel, 0.0);
uint64_t end_sample = (uint64_t)max((right + pixels_offset) *
samples_per_pixel, 0.0);
const uint64_t samples_decoded = _decoder_stack->samples_decoded();
if (samples_decoded < start_sample)
samples_per_pixel, 0.0);
BOOST_FOREACH(const boost::shared_ptr<data::decode::Decoder> &dec, _decoder_stack->stack()) {
start_sample = max(dec->decode_start(), start_sample);
end_sample = min(dec->decode_end(), end_sample);
break;
}
if (end_sample < start_sample)
return;
if (samples_decoded < end_sample)
end_sample = samples_decoded;
const int annotation_height = _view->get_signalHeight();
// Iterate through the rows
assert(_view);
// Iterate through the rows
assert(_view);
int y = get_y() - (_totalHeight - annotation_height)*0.5;
assert(_decoder_stack);
assert(_decoder_stack);
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec,
_decoder_stack->stack()) {
@@ -299,7 +300,8 @@ void DecodeTrace::paint_mid(QPainter &p, int left, int right)
const uint64_t max_annotation =
_decoder_stack->get_max_annotation(row);
const double max_annWidth = max_annotation / samples_per_pixel;
if (max_annWidth > 5) {
if ((max_annWidth > 10 && min_annWidth > 1) ||
(max_annWidth == 0 && samples_per_pixel < 10)) {
vector<Annotation> annotations;
_decoder_stack->get_annotation_subset(annotations, row,
start_sample, end_sample);
@@ -310,13 +312,11 @@ void DecodeTrace::paint_mid(QPainter &p, int left, int right)
samples_per_pixel, pixels_offset, y,
0, min_annWidth);
}
} else if (max_annWidth != 0){
} else {
draw_nodetail(p, annotation_height, left, right, y, 0);
}
if (max_annWidth != 0) {
y += annotation_height;
_cur_row_headings.push_back(row.title());
}
y += annotation_height;
_cur_row_headings.push_back(row.title());
}
}
}
@@ -495,12 +495,50 @@ void DecodeTrace::draw_annotation(const pv::data::decode::Annotation &a,
if (start > right + DrawPadding || end < left - DrawPadding)
return;
if (_decoder_stack->get_mark_index() == (a.start_sample()+ a.end_sample())/2) {
p.setPen(Signal::dsBlue);
int xpos = (start+end)/2;
int ypos = get_y()+_totalHeight*0.5 + 1;
const QPoint triangle[] = {
QPoint(xpos, ypos),
QPoint(xpos-1, ypos + 1),
QPoint(xpos, ypos + 1),
QPoint(xpos+1, ypos + 1),
QPoint(xpos-2, ypos + 2),
QPoint(xpos-1, ypos + 2),
QPoint(xpos, ypos + 2),
QPoint(xpos+1, ypos + 2),
QPoint(xpos+2, ypos + 2),
};
p.drawPoints(triangle, 9);
}
if (a.start_sample() == a.end_sample())
draw_instant(a, p, fill, outline, text_color, h,
start, y, min_annWidth);
else
else {
draw_range(a, p, fill, outline, text_color, h,
start, end, y);
if ((a.type()/100 == 2) && (end - start > 20)) {
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec,
_decoder_stack->stack()) {
for (auto& iter: dec->channels()) {
int type = dec->get_channel_type(iter.first);
if ((type == SRD_CHANNEL_COMMON) ||
((type%100 != a.type()%100) && (type%100 != 0)))
continue;
boost::shared_ptr<LogicSignal> logic_sig;
BOOST_FOREACH(boost::shared_ptr<view::Signal> sig, _session.get_signals()) {
if((sig->get_index() == iter.second) &&
(logic_sig = dynamic_pointer_cast<view::LogicSignal>(sig))) {
logic_sig->paint_mark(p, start, end, type/100);
break;
}
}
}
}
}
}
}
void DecodeTrace::draw_nodetail(QPainter &p,
@@ -723,13 +761,12 @@ QComboBox* DecodeTrace::create_probe_selector(
const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
assert(_decoder_stack);
const map<const srd_channel*,
boost::shared_ptr<LogicSignal> >::const_iterator probe_iter =
const map<const srd_channel*, int>::const_iterator probe_iter =
dec->channels().find(pdch);
QComboBox *selector = new QComboBox(parent);
selector->addItem("-", qVariantFromValue((void*)NULL));
selector->addItem("-", qVariantFromValue(-1));
if (probe_iter == dec->channels().end())
selector->setCurrentIndex(0);
@@ -741,9 +778,9 @@ QComboBox* DecodeTrace::create_probe_selector(
if (dynamic_pointer_cast<LogicSignal>(s) && s->enabled())
{
selector->addItem(s->get_name(),
qVariantFromValue((void*)s.get()));
qVariantFromValue(s->get_index()));
if (probe_iter != dec->channels().end()) {
if ((*probe_iter).second->get_index() == s->get_index())
if ((*probe_iter).second == s->get_index())
selector->setCurrentIndex(i + 1);
}
}
@@ -756,7 +793,7 @@ void DecodeTrace::commit_decoder_probes(boost::shared_ptr<data::decode::Decoder>
{
assert(dec);
map<const srd_channel*, boost::shared_ptr<LogicSignal> > probe_map;
map<const srd_channel*, int> probe_map;
const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
_index_list.clear();
@@ -765,15 +802,13 @@ void DecodeTrace::commit_decoder_probes(boost::shared_ptr<data::decode::Decoder>
if(s._decoder != dec)
break;
const LogicSignal *const selection =
(LogicSignal*)s._combo->itemData(
s._combo->currentIndex()).value<void*>();
const int selection = s._combo->itemData(
s._combo->currentIndex()).value<int>();
BOOST_FOREACH(boost::shared_ptr<Signal> sig, sigs)
if(sig.get() == selection) {
probe_map[s._pdch] =
dynamic_pointer_cast<LogicSignal>(sig);
_index_list.push_back(sig->get_index());
if(sig->get_index() == selection) {
probe_map[s._pdch] = selection;
_index_list.push_back(selection);
break;
}
}

View File

@@ -117,7 +117,7 @@ void DevMode::on_mode_change()
if ((*i).first == button) {
if (dev_inst->dev_inst()->mode != (*i).second->mode) {
_session.stop_capture();
_session.on_mode_change();
_session.session_save();
dev_inst->set_config(NULL, NULL,
SR_CONF_DEVICE_MODE,
g_variant_new_int16((*i).second->mode));

View File

@@ -171,9 +171,9 @@ void DsoSignal::set_viewport(pv::view::Viewport *viewport)
}
void DsoSignal::set_scale(float scale)
void DsoSignal::set_scale(int height)
{
_scale = scale;
_scale = height * 1.0f / (1 << _bits);
}
float DsoSignal::get_scale()
@@ -186,48 +186,38 @@ void DsoSignal::set_enable(bool enable)
if (_dev_inst->name() == "DSLogic" &&
get_index() == 0)
return;
_view->session().refresh(INT_MAX);
/*
* avoid race condition for en_ch_num
* data lock need to lock usb event
*/
_dev_inst->set_config(_probe, NULL, SR_CONF_DATALOCK,
g_variant_new_boolean(true));
set_vDialActive(false);
_dev_inst->set_config(_probe, NULL, SR_CONF_EN_CH,
g_variant_new_boolean(enable));
int ch_num = _view->session().get_ch_num(SR_CHANNEL_DSO);
GVariant* gvar;
uint64_t max_sample_rate;
uint64_t max_sample_limit;
gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_MAX_DSO_SAMPLERATE);
bool cur_enable;
gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_EN_CH);
if (gvar != NULL) {
max_sample_rate = g_variant_get_uint64(gvar);
cur_enable = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
} else {
qDebug() << "ERROR: config_get SR_CONF_MAX_DSO_SAMPLERATE failed.";
return;
}
gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_MAX_DSO_SAMPLELIMITS);
if (gvar != NULL) {
max_sample_limit = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
} else {
qDebug() << "ERROR: config_get SR_CONF_MAX_DSO_SAMPLELIMITS failed.";
if (cur_enable == enable)
return;
bool running = false;
if (_view->session().get_capture_state() == SigSession::Running) {
running = true;
_view->session().stop_capture();
}
while(_view->session().get_capture_state() == SigSession::Running)
QCoreApplication::processEvents();
set_vDialActive(false);
_dev_inst->set_config(_probe, NULL, SR_CONF_EN_CH,
g_variant_new_boolean(enable));
int ch_num = _view->session().get_ch_num(SR_CHANNEL_DSO);
if (running) {
update_capture();
_view->session().repeat_resume();
}
uint64_t sample_limit = (uint64_t)(max_sample_limit / (ch_num ? ch_num : 1));
uint64_t sample_rate = min((uint64_t)(sample_limit * std::pow(10.0, 9.0) / (_hDial->get_value() * DS_CONF_DSO_HDIVS)),
(uint64_t)(max_sample_rate / (ch_num ? ch_num : 1)));
_view->set_sample_rate(sample_rate, true);
_view->set_sample_limit(sample_limit, true);
_dev_inst->set_config(_probe, NULL, SR_CONF_DATALOCK,
g_variant_new_boolean(false));
_view->session().refresh(RefreshLong);
_view->set_update(_viewport, true);
_view->update();
}
@@ -304,11 +294,11 @@ bool DsoSignal::go_hDialPre(bool setted)
uint64_t sample_rate = _view->session().get_device()->get_sample_rate();
const uint64_t min_div = std::pow(10.0, 9.0) / sample_rate;
if (_view->session().get_capture_state() != SigSession::Running &&
!_data->get_snapshots().empty()) {
!_data->get_snapshots().front()->empty()) {
if (_hDial->get_value() > min_div)
_hDial->set_sel(_hDial->get_sel() - 1);
} else if ((_view->session().get_capture_state() == SigSession::Running ||
_data->get_snapshots().empty()) &&
_data->get_snapshots().front()->empty()) &&
!_view->session().get_instant()) {
_view->session().refresh(RefreshShort);
_hDial->set_sel(_hDial->get_sel() - 1);
@@ -346,17 +336,16 @@ bool DsoSignal::go_hDialPre(bool setted)
}
}
bool DsoSignal::go_hDialCur()
bool DsoSignal::update_capture()
{
int ch_num = _view->session().get_ch_num(SR_CHANNEL_DSO);
if (ch_num == 0)
return false;
_view->session().refresh(RefreshShort);
uint64_t sample_limit = _view->session().get_device()->get_sample_limit();
GVariant* gvar;
uint64_t max_sample_rate;
gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_MAX_DSO_SAMPLERATE);
uint64_t max_sample_limit;
GVariant *gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_MAX_DSO_SAMPLERATE);
if (gvar != NULL) {
max_sample_rate = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
@@ -364,11 +353,19 @@ bool DsoSignal::go_hDialCur()
qDebug() << "ERROR: config_get SR_CONF_MAX_DSO_SAMPLERATE failed.";
return false;
}
gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_MAX_DSO_SAMPLELIMITS);
if (gvar != NULL) {
max_sample_limit = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
} else {
qDebug() << "ERROR: config_get SR_CONF_MAX_DSO_SAMPLELIMITS failed.";
return false;
}
uint64_t sample_limit = (uint64_t)(max_sample_limit / (ch_num ? ch_num : 1));
uint64_t sample_rate = min((uint64_t)(sample_limit * std::pow(10.0, 9.0) / (_hDial->get_value() * DS_CONF_DSO_HDIVS)),
(uint64_t)(max_sample_rate / (ch_num ? ch_num : 1)));
// _dev_inst->set_config(NULL, NULL, SR_CONF_SAMPLERATE,
// g_variant_new_uint64(sample_rate));
_view->set_sample_limit(sample_limit, true);
_view->set_sample_rate(sample_rate, true);
_dev_inst->set_config(_probe, NULL, SR_CONF_TIMEBASE,
@@ -381,10 +378,10 @@ bool DsoSignal::go_hDialNext(bool setted)
int ch_num = _view->session().get_ch_num(SR_CHANNEL_DSO);
if (ch_num != 0 && !_hDial->isMax()) {
if (_view->session().get_capture_state() != SigSession::Running &&
!_data->get_snapshots().empty()) {
!_data->get_snapshots().front()->empty()) {
_hDial->set_sel(_hDial->get_sel() + 1);
} else if ((_view->session().get_capture_state() == SigSession::Running ||
_data->get_snapshots().empty()) &&
_data->get_snapshots().front()->empty()) &&
!_view->session().get_instant()) {
_view->session().refresh(RefreshShort);
_hDial->set_sel(_hDial->get_sel() + 1);
@@ -428,15 +425,17 @@ bool DsoSignal::load_settings()
GVariant* gvar;
// -- enable
//bool enable;
//gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_EN_CH);
//if (gvar != NULL) {
// enable = g_variant_get_boolean(gvar);
// g_variant_unref(gvar);
//} else {
// qDebug() << "ERROR: config_get SR_CONF_EN_CH failed.";
// return false;
//}
bool enable;
gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_EN_CH);
if (gvar != NULL) {
enable = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
} else {
qDebug() << "ERROR: config_get SR_CONF_EN_CH failed.";
return false;
}
// dso channel bits
gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_DSO_BITS);
if (gvar != NULL) {
_bits = g_variant_get_byte(gvar);
@@ -444,7 +443,8 @@ bool DsoSignal::load_settings()
} else {
_bits = DefaultBits;
qDebug("Warning: config_get SR_CONF_DSO_BITS failed, set to %d(default).", DefaultBits);
return false;
if (strncmp(_dev_inst->name().toLocal8Bit(), "virtual", 7))
return false;
}
// -- hdiv
@@ -515,10 +515,8 @@ bool DsoSignal::load_settings()
return false;
}
_zero_vrate = min(max((0.5 - vpos / (_vDial->get_value() * DS_CONF_DSO_VDIVS)), 0.0), 1.0);
if (_dev_inst->name() == "DSCope")
_zero_value = _zero_vrate * ((1 << _bits) - 1);
else
_zero_value = 0x80;
if (_dev_inst->name().contains("virtual"))
cur_hw_offset = _zero_vrate * ((1 << _bits) - 1);
// -- trig_value
gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_TRIGGER_VALUE);
@@ -528,7 +526,8 @@ bool DsoSignal::load_settings()
g_variant_unref(gvar);
} else {
qDebug() << "ERROR: config_get SR_CONF_TRIGGER_VALUE failed.";
return false;
if (strncmp(_dev_inst->name().toLocal8Bit(), "virtual", 7))
return false;
}
if (_view) {
@@ -666,29 +665,33 @@ double DsoSignal::get_zero_vrate()
return _zero_vrate;
}
double DsoSignal::get_zero_value()
double DsoSignal::get_hw_offset()
{
return _zero_value;
return cur_hw_offset;
}
void DsoSignal::set_zero_vpos(int pos)
{
if (enabled()) {
double delta = _trig_delta* get_view_rect().height();
_zero_vrate = min(max(pos - UpMargin, 0), get_view_rect().height()) * 1.0 / get_view_rect().height();
set_zero_vrate(min(max(pos - UpMargin, 0), get_view_rect().height()) * 1.0 / get_view_rect().height(), false);
set_trig_vpos(get_zero_vpos() + delta, false);
update_offset();
}
}
void DsoSignal::set_zero_vrate(double rate)
void DsoSignal::set_zero_vrate(double rate, bool force_update)
{
_zero_vrate = rate;
if (_dev_inst->name() == "DSCope")
_zero_value = _zero_vrate * ((1 << _bits) - 1);
else
_zero_value = 0x80;
update_offset();
if (!_dev_inst->name().contains("virtual") &&
(force_update ||
_view->session().get_capture_state() == SigSession::Running)) {
if (_dev_inst->name() == "DSLogic")
cur_hw_offset = 0x80;
else
cur_hw_offset = _zero_vrate * ((1 << _bits) - 1);
}
}
void DsoSignal::set_factor(uint64_t factor)
@@ -818,8 +821,7 @@ void DsoSignal::paint_back(QPainter &p, int left, int right)
const double samplerate = _dev_inst->get_sample_rate();
const double samples_per_pixel = samplerate * _view->scale();
const double shown_rate = min(samples_per_pixel * width * 1.0 / sample_len, 1.0);
const double start_time = _data->get_start_time();
const double start = samplerate * (_view->offset() - start_time);
const double start = _view->offset() * samples_per_pixel;
const double shown_offset = min(start / sample_len, 1.0) * width;
const double shown_len = shown_rate * width;
const QPointF left_edge[] = {QPoint(shown_offset + 3, UpMargin/2 - 6),
@@ -875,7 +877,7 @@ void DsoSignal::paint_mid(QPainter &p, int left, int right)
const int y = get_zero_vpos() + height * 0.5;
const double scale = _view->scale();
assert(scale > 0);
const double offset = _view->offset();
const int64_t offset = _view->offset();
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
_data->get_snapshots();
@@ -886,18 +888,16 @@ void DsoSignal::paint_mid(QPainter &p, int left, int right)
if (snapshot->empty())
return;
const uint16_t number_channels = snapshot->get_channel_num();
if (_dev_inst->name() == "DSLogic" &&
(unsigned int)get_index() >= number_channels)
if (!snapshot->has_data(get_index()))
return;
const double pixels_offset = offset / scale;
const uint16_t number_channels = snapshot->get_channel_num();
const double pixels_offset = offset;
//const double samplerate = _data->samplerate();
const double samplerate = _dev_inst->get_sample_rate();
const double start_time = _data->get_start_time();
const int64_t last_sample = max((int64_t)(snapshot->get_sample_count() - 1), (int64_t)0);
const double samples_per_pixel = samplerate * scale;
const double start = samplerate * (offset - start_time);
const double start = offset * samples_per_pixel;
const double end = start + samples_per_pixel * width;
const int64_t start_sample = min(max((int64_t)floor(start),
@@ -923,6 +923,9 @@ void DsoSignal::paint_fore(QPainter &p, int left, int right)
{
assert(_view);
bool antialiasing = p.Antialiasing;
p.setRenderHint(QPainter::Antialiasing, false);
QPen pen(Signal::dsGray);
pen.setStyle(Qt::DotLine);
p.setPen(pen);
@@ -967,6 +970,8 @@ void DsoSignal::paint_fore(QPainter &p, int left, int right)
// Paint measure
paint_measure(p);
}
p.setRenderHint(QPainter::Antialiasing, antialiasing);
}
QRectF DsoSignal::get_trig_rect(int left, int right) const
@@ -1001,9 +1006,6 @@ void DsoSignal::paint_trace(QPainter &p,
float top = get_view_rect().top();
float bottom = get_view_rect().bottom();
float zeroP = _zero_vrate * get_view_rect().height() + top;;
if (_dev_inst->name() == "DSCope" &&
_view->session().get_capture_state() == SigSession::Running)
_zero_value = _zero_vrate * ((1 << _bits) - 1);
float x = (start / samples_per_pixel - pixels_offset) + left;
double pixels_per_sample = 1.0/samples_per_pixel;
uint8_t offset;
@@ -1014,7 +1016,7 @@ void DsoSignal::paint_trace(QPainter &p,
//offset = samples[(sample - start)*num_channels];
offset = samples[sample];
const float y = min(max(top, zeroP + (offset - _zero_value) * _scale), bottom);
const float y = min(max(top, zeroP + (offset - cur_hw_offset) * _scale), bottom);
*point++ = QPointF(x, y);
x += pixels_per_sample;
//*point++ = QPointF(x, top + offset);
@@ -1057,9 +1059,6 @@ void DsoSignal::paint_envelope(QPainter &p,
float top = get_view_rect().top();
float bottom = get_view_rect().bottom();
float zeroP = _zero_vrate * get_view_rect().height() + top;
if (_dev_inst->name() == "DSCope" &&
_view->session().get_capture_state() == SigSession::Running)
_zero_value = _zero_vrate * ((1 << _bits) - 1);
for(uint64_t sample = 0; sample < e.length-1; sample++) {
const float x = ((e.scale * sample + e.start) /
samples_per_pixel - pixels_offset) + left;
@@ -1068,8 +1067,8 @@ void DsoSignal::paint_envelope(QPainter &p,
// We overlap this sample with the next so that vertical
// gaps do not appear during steep rising or falling edges
const float b = min(max(top, ((max(s->max, (s+1)->min) - _zero_value) * _scale + zeroP)), bottom);
const float t = min(max(top, ((min(s->min, (s+1)->max) - _zero_value) * _scale + zeroP)), bottom);
const float b = min(max(top, ((max(s->max, (s+1)->min) - cur_hw_offset) * _scale + zeroP)), bottom);
const float t = min(max(top, ((min(s->min, (s+1)->max) - cur_hw_offset) * _scale + zeroP)), bottom);
float h = b - t;
if(h >= 0.0f && h <= 1.0f)
@@ -1086,11 +1085,6 @@ void DsoSignal::paint_envelope(QPainter &p,
//delete[] e.samples;
}
const std::vector< std::pair<uint64_t, bool> > DsoSignal::cur_edges() const
{
}
void DsoSignal::paint_type_options(QPainter &p, int right, const QPoint pt)
{
int y = get_y();
@@ -1328,21 +1322,21 @@ void DsoSignal::paint_measure(QPainter &p)
_min = (index == 0) ? status.ch0_min : status.ch1_min;
const uint64_t period = (index == 0) ? status.ch0_period : status.ch1_period;
const uint32_t count = (index == 0) ? status.ch0_pcnt : status.ch1_pcnt;
double value_max = (_zero_value - _min) * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
double value_min = (_zero_value - _max) * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
double value_max = (cur_hw_offset - _min) * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
double value_min = (cur_hw_offset - _max) * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
double value_p2p = value_max - value_min;
_period = (count == 0) ? period * 10.0 : period * 10.0 / count;
const int channel_count = _view->session().get_ch_num(SR_CHANNEL_DSO);
uint64_t sample_rate = _dev_inst->get_sample_rate();
_period = _period * 200.0 / (channel_count * sample_rate * 1.0 / SR_MHZ(1));
_ms_string[DSO_MS_VMAX] = "Vmax: " + (abs(value_max) > 1000 ? QString::number(value_max/1000.0, 'f', 2) + "V" : QString::number(value_max, 'f', 2) + "mV");
_ms_string[DSO_MS_VMIN] = "Vmin: " + (abs(value_min) > 1000 ? QString::number(value_min/1000.0, 'f', 2) + "V" : QString::number(value_min, 'f', 2) + "mV");
_ms_string[DSO_MS_PERD] = "Perd: " + (abs(_period) > 1000000000 ? QString::number(_period/1000000000, 'f', 2) + "S" :
_ms_string[DSO_MS_VMAX] = tr("Vmax: ") + (abs(value_max) > 1000 ? QString::number(value_max/1000.0, 'f', 2) + "V" : QString::number(value_max, 'f', 2) + "mV");
_ms_string[DSO_MS_VMIN] = tr("Vmin: ") + (abs(value_min) > 1000 ? QString::number(value_min/1000.0, 'f', 2) + "V" : QString::number(value_min, 'f', 2) + "mV");
_ms_string[DSO_MS_PERD] = tr("Perd: ") + (abs(_period) > 1000000000 ? QString::number(_period/1000000000, 'f', 2) + "S" :
abs(_period) > 1000000 ? QString::number(_period/1000000, 'f', 2) + "mS" :
abs(_period) > 1000 ? QString::number(_period/1000, 'f', 2) + "uS" : QString::number(_period, 'f', 2) + "nS");
_ms_string[DSO_MS_FREQ] = "Freq: " + (abs(_period) > 1000000 ? QString::number(1000000000/_period, 'f', 2) + "Hz" :
_ms_string[DSO_MS_FREQ] = tr("Freq: ") + (abs(_period) > 1000000 ? QString::number(1000000000/_period, 'f', 2) + "Hz" :
abs(_period) > 1000 ? QString::number(1000000/_period, 'f', 2) + "kHz" : QString::number(1000/_period, 'f', 2) + "MHz");
_ms_string[DSO_MS_VP2P] = "Vp-p: " + (abs(value_p2p) > 1000 ? QString::number(value_p2p/1000.0, 'f', 2) + "V" : QString::number(value_p2p, 'f', 2) + "mV");
_ms_string[DSO_MS_VP2P] = tr("Vp-p: ") + (abs(value_p2p) > 1000 ? QString::number(value_p2p/1000.0, 'f', 2) + "V" : QString::number(value_p2p, 'f', 2) + "mV");
if (_probe->ms_show && _probe->ms_en[DSO_MS_VRMS]) {
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
@@ -1350,9 +1344,9 @@ void DsoSignal::paint_measure(QPainter &p)
if (!snapshots.empty()) {
const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
snapshots.front();
const double vrms = snapshot->cal_vrms(_zero_value, get_index());
const double vrms = snapshot->cal_vrms(cur_hw_offset, get_index());
const double value_vrms = vrms * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
_ms_string[DSO_MS_VRMS] = "Vrms: " + (abs(value_vrms) > 1000 ? QString::number(value_vrms/1000.0, 'f', 2) + "V" : QString::number(value_vrms, 'f', 2) + "mV");
_ms_string[DSO_MS_VRMS] = tr("Vrms: ") + (abs(value_vrms) > 1000 ? QString::number(value_vrms/1000.0, 'f', 2) + "V" : QString::number(value_vrms, 'f', 2) + "mV");
}
}
@@ -1363,18 +1357,18 @@ void DsoSignal::paint_measure(QPainter &p)
const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
snapshots.front();
const double vmean = snapshot->cal_vmean(get_index());
const double value_vmean = (_zero_value - vmean) * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
_ms_string[DSO_MS_VMEA] = "Vmean: " + (abs(value_vmean) > 1000 ? QString::number(value_vmean/1000.0, 'f', 2) + "V" : QString::number(value_vmean, 'f', 2) + "mV");
const double value_vmean = (cur_hw_offset - vmean) * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
_ms_string[DSO_MS_VMEA] = tr("Vmean: ") + (abs(value_vmean) > 1000 ? QString::number(value_vmean/1000.0, 'f', 2) + "V" : QString::number(value_vmean, 'f', 2) + "mV");
}
}
} else {
_ms_string[DSO_MS_VMAX] = "Vmax: #####";
_ms_string[DSO_MS_VMIN] = "Vmin: #####";
_ms_string[DSO_MS_PERD] = "Perd: #####";
_ms_string[DSO_MS_FREQ] = "Freq: #####";
_ms_string[DSO_MS_VP2P] = "Vp-p: #####";
_ms_string[DSO_MS_VRMS] = "Vrms: #####";
_ms_string[DSO_MS_VMEA] = "Vmean: #####";
_ms_string[DSO_MS_VMAX] = tr("Vmax: #####");
_ms_string[DSO_MS_VMIN] = tr("Vmin: #####");
_ms_string[DSO_MS_PERD] = tr("Perd: #####");
_ms_string[DSO_MS_FREQ] = tr("Freq: #####");
_ms_string[DSO_MS_VP2P] = tr("Vp-p: #####");
_ms_string[DSO_MS_VRMS] = tr("Vrms: #####");
_ms_string[DSO_MS_VMEA] = tr("Vmean: #####");
}
QColor measure_colour = _colour;
@@ -1506,8 +1500,7 @@ bool DsoSignal::measure(const QPointF &p)
const double scale = _view->scale();
assert(scale > 0);
const double offset = _view->offset();
const double pixels_offset = offset / scale;
const int64_t pixels_offset = _view->offset();
const double samplerate = _dev_inst->get_sample_rate();
const double samples_per_pixel = samplerate * scale;
@@ -1529,17 +1522,17 @@ bool DsoSignal::measure(const QPointF &p)
const uint8_t cur_sample = *snapshot->get_samples(_hover_index, _hover_index, get_index());
const uint8_t nxt_sample = *snapshot->get_samples(nxt_index, nxt_index, get_index());
_hover_value = (_zero_value - cur_sample) * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
_hover_value = (cur_hw_offset - cur_sample) * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
float top = get_view_rect().top();
float bottom = get_view_rect().bottom();
float zeroP = _zero_vrate * get_view_rect().height() + top;
float pre_x = (pre_index / samples_per_pixel - pixels_offset);
const float pre_y = min(max(top, zeroP + (pre_sample - _zero_value)* _scale), bottom);
const float pre_y = min(max(top, zeroP + (pre_sample - cur_hw_offset)* _scale), bottom);
float x = (_hover_index / samples_per_pixel - pixels_offset);
const float y = min(max(top, zeroP + (cur_sample - _zero_value)* _scale), bottom);
const float y = min(max(top, zeroP + (cur_sample - cur_hw_offset)* _scale), bottom);
float nxt_x = (nxt_index / samples_per_pixel - pixels_offset);
const float nxt_y = min(max(top, zeroP + (nxt_sample - _zero_value)* _scale), bottom);
const float nxt_y = min(max(top, zeroP + (nxt_sample - cur_hw_offset)* _scale), bottom);
const QRectF slope_rect = QRectF(QPointF(pre_x - 10, pre_y - 10), QPointF(nxt_x + 10, nxt_y + 10));
if (abs(y-p.y()) < 20 || slope_rect.contains(p)) {
_hover_point = QPointF(x, y);

View File

@@ -100,7 +100,7 @@ public:
boost::shared_ptr<pv::data::Dso> dso_data() const;
void set_viewport(pv::view::Viewport *viewport);
void set_scale(float scale);
void set_scale(int height);
float get_scale();
/**
@@ -115,7 +115,7 @@ public:
bool go_vDialNext();
bool go_hDialPre(bool setted);
bool go_hDialNext(bool setted);
bool go_hDialCur();
bool update_capture();
uint64_t get_vDialValue() const;
uint64_t get_hDialValue() const;
uint16_t get_vDialSel() const;
@@ -148,12 +148,12 @@ public:
*/
int get_zero_vpos();
double get_zero_vrate();
double get_zero_value();
double get_hw_offset();
/**
* Sets the mid-Y position of this signal.
*/
void set_zero_vpos(int pos);
void set_zero_vrate(double rate);
void set_zero_vrate(double rate, bool force_update);
void update_offset();
/**
@@ -180,8 +180,6 @@ public:
**/
void paint_fore(QPainter &p, int left, int right);
const std::vector< std::pair<uint64_t, bool> > cur_edges() const;
QRect get_view_rect() const;
QRectF get_trig_rect(int left, int right) const;
@@ -234,7 +232,7 @@ private:
int _trig_value;
double _trig_delta;
double _zero_vrate;
float _zero_value;
float cur_hw_offset;
uint8_t _max;
uint8_t _min;

View File

@@ -81,7 +81,7 @@ void GroupSignal::paint_mid(QPainter &p, int left, int right)
const int y = get_y() + _totalHeight * 0.5;
const double scale = _view->scale();
assert(scale > 0);
const double offset = _view->offset();
const int64_t offset = _view->offset();
_scale = _totalHeight * 1.0f / std::pow(2.0, static_cast<int>(_index_list.size()));
@@ -93,12 +93,11 @@ void GroupSignal::paint_mid(QPainter &p, int left, int right)
const boost::shared_ptr<pv::data::GroupSnapshot> &snapshot =
snapshots.at(_sec_index);
const double pixels_offset = offset / scale;
const double pixels_offset = offset;
const double samplerate = _data->samplerate();
const double start_time = _data->get_start_time();
const int64_t last_sample = snapshot->get_sample_count() - 1;
const double samples_per_pixel = samplerate * scale;
const double start = samplerate * (offset - start_time);
const double start = offset * samples_per_pixel;
const double end = start + samples_per_pixel * (right - left);
const int64_t start_sample = min(max((int64_t)floor(start),
@@ -190,11 +189,6 @@ void GroupSignal::paint_envelope(QPainter &p,
delete[] e.samples;
}
const std::vector< std::pair<uint64_t, bool> > GroupSignal::cur_edges() const
{
}
void GroupSignal::paint_type_options(QPainter &p, int right, const QPoint pt)
{
(void)pt;

View File

@@ -76,8 +76,6 @@ public:
**/
void paint_mid(QPainter &p, int left, int right);
const std::vector< std::pair<uint64_t, bool> > cur_edges() const;
QRectF get_rect(GroupSetRegions type, int y, int right);
protected:

View File

@@ -75,9 +75,6 @@ Header::Header(View &parent) :
connect(nameEdit, SIGNAL(editingFinished()),
this, SLOT(on_action_set_name_triggered()));
connect(&_view, SIGNAL(traces_moved()),
this, SLOT(on_traces_moved()));
}
@@ -322,7 +319,6 @@ void Header::mouseMoveEvent(QMouseEvent *event)
}
}
}
//traces_moved();
}
update();
}
@@ -380,11 +376,6 @@ void Header::on_action_del_group_triggered()
_view.session().del_group();
}
void Header::on_traces_moved()
{
update();
}
void Header::header_resize()
{
//if (nameEdit->isVisible()) {

View File

@@ -77,8 +77,6 @@ private slots:
void on_action_del_group_triggered();
void on_traces_moved();
signals:
void traces_moved();
void header_updated();

View File

@@ -20,6 +20,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <libsigrokdecode/libsigrokdecode.h>
#include <extdef.h>
@@ -74,6 +75,7 @@ LogicSignal::LogicSignal(boost::shared_ptr<view::LogicSignal> s,
LogicSignal::~LogicSignal()
{
_cur_edges.clear();
_cur_pulses.clear();
}
const sr_channel* LogicSignal::probe() const
@@ -128,8 +130,6 @@ void LogicSignal::paint_mid(QPainter &p, int left, int right)
{
using pv::view::View;
QLineF *line;
assert(_data);
assert(_view);
assert(right >= left);
@@ -137,10 +137,10 @@ void LogicSignal::paint_mid(QPainter &p, int left, int right)
const int y = get_y() + _totalHeight * 0.5;
const double scale = _view->scale();
assert(scale > 0);
const double offset = _view->offset();
const int64_t offset = _view->offset();
const float high_offset = y - _totalHeight + 0.5f;
const float low_offset = y + 0.5f;
const int high_offset = y - _totalHeight + 0.5f;
const int low_offset = y + 0.5f;
const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
_data->get_snapshots();
@@ -150,47 +150,60 @@ void LogicSignal::paint_mid(QPainter &p, int left, int right)
const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot =
snapshots.front();
if (snapshot->empty())
if (snapshot->empty() || !snapshot->has_data(_probe->index))
return;
const double pixels_offset = offset / scale;
const double start_time = _data->get_start_time();
const int64_t last_sample = snapshot->get_sample_count() - 1;
const double samples_per_pixel = samplerate * scale;
const double start = samplerate * (offset - start_time);
const double end = start + samples_per_pixel * (right - left);
snapshot->get_subsampled_edges(_cur_edges,
min(max((int64_t)floor(start), (int64_t)0), last_sample),
min(max((int64_t)ceil(end), (int64_t)0), last_sample),
samples_per_pixel / Oversampling, _probe->index);
if (_cur_edges.size() < 2)
uint16_t width = right - left;
const double start = offset * samples_per_pixel;
const double end = (offset + width + 1) * samples_per_pixel;
const uint64_t end_index = min(max((int64_t)ceil(end), (int64_t)0), last_sample);
const uint64_t start_index = max((uint64_t)floor(start), (uint64_t)0);
if (start_index > end_index)
return;
width = min(width, (uint16_t)ceil((end_index + 1)/samples_per_pixel - offset));
const uint16_t max_togs = width / TogMaxScale;
// Paint the edges
const unsigned int edge_count = 2 * _cur_edges.size() - 3;
QLineF *const edge_lines = new QLineF[edge_count];
line = edge_lines;
const bool first_sample = snapshot->get_display_edges(_cur_pulses, _cur_edges,
start_index, end_index, width, max_togs,
offset,
samples_per_pixel, _probe->index);
assert(_cur_pulses.size() >= width);
double preX = ((*(_cur_edges.begin())).first / samples_per_pixel - pixels_offset) + left;
double preY = (*(_cur_edges.begin())).second ? high_offset : low_offset;
vector<pv::data::LogicSnapshot::EdgePair>::const_iterator i;
for ( i = _cur_edges.begin() + 1; i != _cur_edges.end() - 1; i++) {
const double x = ((*i).first / samples_per_pixel -
pixels_offset) + left;
const double y = (*i).second ? high_offset : low_offset;
*line++ = QLineF(preX, preY, x, preY);
*line++ = QLineF(x, high_offset, x, low_offset);
preX = x;
preY = y;
int preX = 0;
int preY = first_sample ? high_offset : low_offset;
int x = preX;
std::vector<QLine> wave_lines;
if (_cur_edges.size() < max_togs) {
std::vector<std::pair<uint16_t, bool>>::const_iterator i;
for (i = _cur_edges.begin() + 1; i != _cur_edges.end() - 1; i++) {
x = (*i).first;
wave_lines.push_back(QLine(preX, preY, x, preY));
wave_lines.push_back(QLine(x, high_offset, x, low_offset));
preX = x;
preY = (*i).second ? high_offset : low_offset;
}
x = (*i).first;
wave_lines.push_back(QLine(preX, preY, x, preY));
} else {
std::vector<std::pair<bool, bool>>::const_iterator i = _cur_pulses.begin();
while (i != _cur_pulses.end() - 1) {
if ((*i).first) {
wave_lines.push_back(QLine(preX, preY, x, preY));
wave_lines.push_back(QLine(x, high_offset, x, low_offset));
preX = x;
preY = (*i).second ? high_offset : low_offset;
}
x++;
i++;
}
wave_lines.push_back(QLine(preX, preY, x, preY));
}
const double x = ((*i).first / samples_per_pixel -
pixels_offset) + left;
*line++ = QLineF(preX, preY, x, preY);
p.setPen(_colour);
p.drawLines(edge_lines, edge_count);
delete[] edge_lines;
p.drawLines(wave_lines.data(), wave_lines.size());
}
void LogicSignal::paint_caps(QPainter &p, QLineF *const lines,
@@ -216,11 +229,6 @@ void LogicSignal::paint_caps(QPainter &p, QLineF *const lines,
p.drawLines(lines, line - lines);
}
const std::vector< std::pair<uint64_t, bool> > LogicSignal::cur_edges() const
{
return _cur_edges;
}
void LogicSignal::paint_type_options(QPainter &p, int right, const QPoint pt)
{
int y = get_y();
@@ -305,32 +313,43 @@ bool LogicSignal::measure(const QPointF &p, uint64_t &index0, uint64_t &index1,
const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot =
snapshots.front();
if (snapshot->empty())
if (snapshot->empty() || !snapshot->has_data(_probe->index))
return false;
uint64_t index = _data->samplerate() * (_view->offset() - _data->get_start_time() + p.x() * _view->scale());
if (index == 0 || index >= (snapshot->get_sample_count() - 1))
const uint64_t end = snapshot->get_sample_count() - 1;
uint64_t index = _data->samplerate() * _view->scale() * (_view->offset() + p.x());
if (index > end)
return false;
const uint64_t sig_mask = 1ULL << get_index();
bool sample = snapshot->get_sample(index) & sig_mask;
index--;
if (!snapshot->get_pre_edge(index, sample, 1, get_index()))
return false;
bool sample = snapshot->get_sample(index, get_index());
if (index == 0)
index0 = index;
else {
index--;
if (snapshot->get_pre_edge(index, sample, 1, get_index()))
index0 = index;
else
index0 = 0;
}
index0 = index;
sample = snapshot->get_sample(index) & sig_mask;
sample = snapshot->get_sample(index, get_index());
index++;
if (!snapshot->get_nxt_edge(index, sample, snapshot->get_sample_count(), 1, get_index()))
return false;
index1 = index;
sample = snapshot->get_sample(index) & sig_mask;
index++;
if (!snapshot->get_nxt_edge(index, sample, snapshot->get_sample_count(), 1, get_index()))
if (snapshot->get_nxt_edge(index, sample, end, 1, get_index()))
index1 = index;
else {
if (index0 == 0)
return false;
index1 = end + 1;
index2 = 0;
else
return true;
}
sample = snapshot->get_sample(index, get_index());
index++;
if (snapshot->get_nxt_edge(index, sample, end, 1, get_index()))
index2 = index;
else
index2 = end + 1;
return true;
}
@@ -343,44 +362,51 @@ bool LogicSignal::edges(const QPointF &p, uint64_t start, uint64_t &rising, uint
uint64_t index, end;
const float gap = abs(p.y() - get_y());
if (gap < get_totalHeight() * 0.5) {
const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
_data->get_snapshots();
if (snapshots.empty())
return false;
const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot =
snapshots.front();
if (snapshot->empty())
return false;
end = _data->samplerate() * (_view->offset() - _data->get_start_time() + p.x() * _view->scale());
index = min(start, end);
end = max(start, end);
start = index;
if (end > (snapshot->get_sample_count() - 1))
return false;
const uint64_t sig_mask = 1ULL << get_index();
bool sample = snapshot->get_sample(start) & sig_mask;
rising = 0;
falling = 0;
do {
if (snapshot->get_nxt_edge(index, sample, snapshot->get_sample_count(), 1, get_index())) {
if (index > end)
break;
rising += !sample;
falling += sample;
sample = !sample;
} else {
break;
}
} while(index <= end);
return true;
end = _data->samplerate() * _view->scale() * (_view->offset() + p.x());
return edges(end, start, rising, falling);
}
return false;
}
bool LogicSignal::edges(uint64_t end, uint64_t start, uint64_t &rising, uint64_t &falling) const
{
const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
_data->get_snapshots();
if (snapshots.empty())
return false;
const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot =
snapshots.front();
if (snapshot->empty() || !snapshot->has_data(_probe->index))
return false;
uint64_t index = min(start, end);
const uint64_t sample_count = snapshot->get_sample_count();
end = max(start, end);
start = index;
if (end > (sample_count - 1))
return false;
const int ch_index = get_index();
bool sample = snapshot->get_sample(start, ch_index);
rising = 0;
falling = 0;
do {
if (snapshot->get_nxt_edge(index, sample, sample_count, 1, ch_index)) {
if (index > end)
break;
rising += !sample;
falling += sample;
sample = !sample;
} else {
break;
}
} while(index <= end);
return true;
}
bool LogicSignal::mouse_press(int right, const QPoint pt)
{
int y = get_y();
@@ -439,5 +465,38 @@ QRectF LogicSignal::get_rect(LogicSetRegions type, int y, int right)
return QRectF(0, 0, 0, 0);
}
void LogicSignal::paint_mark(QPainter &p, int xstart, int xend, int type)
{
const int ypos = get_y();
const int msize = 3;
p.setPen(p.brush().color());
if (type == SRD_CHANNEL_SDATA) {
p.drawEllipse(QPoint(xstart, ypos), msize, msize);
} else if (type == SRD_CHANNEL_SCLK) {
const QPoint triangle[] = {
QPoint(xstart, ypos - 2),
QPoint(xstart-1, ypos - 1),
QPoint(xstart, ypos - 1),
QPoint(xstart+1, ypos - 1),
QPoint(xstart-2, ypos),
QPoint(xstart-1, ypos),
QPoint(xstart, ypos),
QPoint(xstart+1, ypos),
QPoint(xstart+2, ypos),
QPoint(xstart-3, ypos + 1),
QPoint(xstart-2, ypos + 1),
QPoint(xstart-1, ypos + 1),
QPoint(xstart, ypos + 1),
QPoint(xstart+1, ypos + 1),
QPoint(xstart+2, ypos + 1),
QPoint(xstart+3, ypos + 1),
};
p.drawPoints(triangle, 16);
} else if (type == SRD_CHANNEL_ADATA) {
p.drawEllipse(QPoint((xstart+xend)/2, ypos), msize, msize);
}
}
} // namespace view
} // namespace pv

View File

@@ -53,6 +53,8 @@ private:
static const int StateHeight;
static const int StateRound;
static const int TogMaxScale = 10;
enum LogicSetRegions{
NONTRIG = 0,
POSTRIG,
@@ -94,16 +96,18 @@ public:
**/
void paint_mid(QPainter &p, int left, int right);
const std::vector< std::pair<uint64_t, bool> > cur_edges() const;
bool measure(const QPointF &p, uint64_t &index0, uint64_t &index1, uint64_t &index2) const;
bool edges(const QPointF &p, uint64_t start, uint64_t &rising, uint64_t &falling) const;
bool edges(uint64_t end, uint64_t start, uint64_t &rising, uint64_t &falling) const;
bool mouse_press(int right, const QPoint pt);
QRectF get_rect(LogicSetRegions type, int y, int right);
void paint_mark(QPainter &p, int xstart, int xend, int type);
protected:
void paint_type_options(QPainter &p, int right, const QPoint pt);
@@ -116,7 +120,8 @@ private:
private:
boost::shared_ptr<pv::data::Logic> _data;
std::vector< std::pair<uint64_t, bool> > _cur_edges;
std::vector< std::pair<uint16_t, bool> > _cur_edges;
std::vector<std::pair<bool, bool>> _cur_pulses;
LogicSetRegions _trig;
};

View File

@@ -205,8 +205,9 @@ void Ruler::mouseMoveEvent(QMouseEvent *e)
(void)e;
if (_grabbed_marker) {
_grabbed_marker->set_index((_view.offset() +
_view.hover_point().x() * _view.scale()) * _view.session().cur_samplerate());
_grabbed_marker->set_index((_view.offset() + _view.hover_point().x()) *
_view.scale() * _view.session().cur_samplerate());
_view.cursor_moving();
}
update();
@@ -228,6 +229,7 @@ void Ruler::mousePressEvent(QMouseEvent *e)
void Ruler::mouseReleaseEvent(QMouseEvent *event)
{
bool addCursor = false;
bool visible;
if (event->button() & Qt::LeftButton) {
bool hitCursor = false;
if (!_cursor_sel_visible & !_view.get_cursorList().empty()) {
@@ -235,10 +237,12 @@ void Ruler::mouseReleaseEvent(QMouseEvent *event)
if (_grabbed_marker) {
rel_grabbed_cursor();
hitCursor = true;
_view.cursor_moved();
} else {
list<Cursor*>::iterator i = _view.get_cursorList().begin();
while (i != _view.get_cursorList().end()) {
if ((*i)->get_close_rect(rect()).contains(event->pos())) {
const QRect cursor_rect((*i)->get_label_rect(rect(), visible));
if ((*i)->get_close_rect(cursor_rect).contains(event->pos())) {
_view.del_cursor(*i);
if (_view.get_cursorList().empty()) {
_cursor_sel_visible = false;
@@ -247,7 +251,7 @@ void Ruler::mouseReleaseEvent(QMouseEvent *event)
hitCursor = true;
break;
}
if ((*i)->get_label_rect(rect()).contains(event->pos())) {
if (cursor_rect.contains(event->pos())) {
set_grabbed_cursor(*i);
_cursor_sel_visible = false;
_cursor_go_visible = false;
@@ -265,7 +269,7 @@ void Ruler::mouseReleaseEvent(QMouseEvent *event)
_cursor_sel_visible = true;
} else {
int overCursor;
uint64_t index = (_view.offset() + (_cursor_sel_x + 0.5) * _view.scale()) * _view.session().cur_samplerate();
uint64_t index = (_view.offset() + _cursor_sel_x + 0.5) * _view.scale() * _view.session().cur_samplerate();
overCursor = in_cursor_sel_rect(event->pos());
if (overCursor == 0) {
_view.add_cursor(CursorColor[_view.get_cursorList().size() % 8], index);
@@ -354,7 +358,7 @@ void Ruler::draw_tick_mark(QPainter &p)
typical_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
AlignLeft | AlignTop, format_time(_view.offset(),
AlignLeft | AlignTop, format_time(_view.offset() * _view.scale(),
prefix)).width() + MinValueSpacing;
min_width += SpacingIncrement;
@@ -369,9 +373,9 @@ void Ruler::draw_tick_mark(QPainter &p)
const double minor_tick_period = tick_period / MinorTickSubdivision;
const double first_major_division =
floor(_view.offset() / tick_period);
floor(_view.offset() * _view.scale() / tick_period);
const double first_minor_division =
ceil(_view.offset() / minor_tick_period);
ceil(_view.offset() * _view.scale() / minor_tick_period);
const double t0 = first_major_division * tick_period;
int division = (int)round(first_minor_division -
@@ -385,7 +389,7 @@ void Ruler::draw_tick_mark(QPainter &p)
do {
const double t = t0 + division * minor_tick_period;
x = (t - _view.offset()) / _view.scale();
x = t / _view.scale() - _view.offset();
if (division % MinorTickSubdivision == 0)
{
@@ -432,7 +436,7 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
double typical_width;
double tick_period = 0;
double scale = _view.scale();
double offset = _view.offset();
int64_t offset = _view.offset();
const uint64_t cur_period_scale = ceil((scale * min_width) / abs_min_period);
@@ -449,7 +453,7 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
_cur_prefix = prefix;
assert(prefix < countof(SIPrefixes));
typical_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
AlignLeft | AlignTop, format_time(offset,
AlignLeft | AlignTop, format_time(offset * scale,
prefix)).width() + MinValueSpacing;
do
{
@@ -470,9 +474,9 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
assert(minor_prefix < countof(SIPrefixes));
const double first_major_division =
floor(offset / tick_period);
floor(offset * scale / tick_period);
const double first_minor_division =
floor(offset / minor_tick_period + 1);
floor(offset * scale / minor_tick_period + 1);
const double t0 = first_major_division * tick_period;
int division = (int)round(first_minor_division -
@@ -482,7 +486,7 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
const int tick_y2 = height();
const int minor_tick_y1 = (major_tick_y1 + tick_y2) / 2;
double x;
int x;
const double inc_text_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
AlignLeft | AlignTop,
@@ -492,7 +496,7 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
const double t = t0 + division * minor_tick_period;
const double major_t = t0 + floor(division / MinPeriodScale) * tick_period;
x = (t - offset) / scale;
x = t / scale - offset;
if (division % MinPeriodScale == 0)
{
@@ -500,8 +504,8 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
p.drawText(x, 2 * ValueMargin, 0, text_height,
AlignCenter | AlignTop | TextDontClip,
format_time(t, prefix));
p.drawLine(QPointF(x, major_tick_y1),
QPointF(x, tick_y2));
p.drawLine(QPoint(x, major_tick_y1),
QPoint(x, tick_y2));
}
else
{
@@ -516,8 +520,8 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
p.drawText(x, 2 * ValueMargin, 0, minor_tick_y1 + ValueMargin,
AlignCenter | AlignTop | TextDontClip,
format_time(t - major_t, minor_prefix));
p.drawLine(QPointF(x, minor_tick_y1),
QPointF(x, tick_y2));
p.drawLine(QPoint(x, minor_tick_y1),
QPoint(x, tick_y2));
}
division++;
@@ -533,13 +537,12 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
index++;
i++;
}
_view.on_cursor_moved();
}
if (_view.trig_cursor_shown()) {
_view.get_trig_cursor()->paint_fix_label(p, rect(), prefix, 'T', Trace::dsLightRed);
_view.get_trig_cursor()->paint_fix_label(p, rect(), prefix, 'T', _view.get_trig_cursor()->colour());
}
if (_view.search_cursor_shown()) {
_view.get_search_cursor()->paint_fix_label(p, rect(), prefix, 'S', Trace::dsLightBlue);
_view.get_search_cursor()->paint_fix_label(p, rect(), prefix, 'S', _view.get_search_cursor()->colour());
}
}

View File

@@ -67,8 +67,6 @@ protected:
public:
virtual boost::shared_ptr<pv::data::SignalData> data() const = 0;
virtual const std::vector< std::pair<uint64_t, bool> > cur_edges() const = 0;
/**
* Returns true if the trace is visible and enabled.
*/

View File

@@ -24,6 +24,7 @@
#include "timemarker.h"
#include "view.h"
#include "ruler.h"
#include "../device/device.h"
#include <QPainter>
@@ -48,6 +49,16 @@ TimeMarker::TimeMarker(const TimeMarker &s) :
{
}
QColor TimeMarker::colour() const
{
return _colour;
}
void TimeMarker::set_colour(QColor color)
{
_colour = color;
}
bool TimeMarker::grabbed() const
{
return _grabbed;
@@ -68,14 +79,15 @@ void TimeMarker::set_index(uint64_t index)
time_changed();
}
void TimeMarker::paint(QPainter &p, const QRect &rect, const bool highlight)
void TimeMarker::paint(QPainter &p, const QRect &rect, const bool highlight, int order)
{
const uint64_t sample_rate = _view.session().cur_samplerate();
const double scale = _view.scale();
const double samples_per_pixel = sample_rate * scale;
const double x = _index/samples_per_pixel - (_view.offset() / scale);
p.setPen((_grabbed | highlight) ? QPen(_colour.lighter(), 2, Qt::DashLine) : QPen(_colour, 1, Qt::DashLine));
p.drawLine(QPointF(x, rect.top()), QPointF(x, rect.bottom()));
const int64_t x = _index/samples_per_pixel - _view.offset();
QColor color = (order == -1) ? _colour : Ruler::CursorColor[order%8];
p.setPen((_grabbed | highlight) ? QPen(color.lighter(), 2, Qt::DashLine) : QPen(color, 1, Qt::DashLine));
p.drawLine(QPoint(x, rect.top()), QPoint(x, rect.bottom()));
}
} // namespace view

View File

@@ -68,6 +68,12 @@ public:
*/
void set_index(uint64_t index);
/**
* Gets/Sets colour of the marker
*/
QColor colour() const;
void set_colour(QColor color);
/*
*
*/
@@ -79,14 +85,15 @@ public:
* @param p The painter to draw with.
* @param rect The rectangle of the viewport client area.
*/
virtual void paint(QPainter &p, const QRect &rect, const bool highlight);
virtual void paint(QPainter &p, const QRect &rect, const bool highlight, int order);
/**
* Gets the marker label rectangle.
* @param rect The rectangle of the ruler client area.
* @param visible is this marker in visible area
* @return Returns the label rectangle.
*/
virtual QRectF get_label_rect(const QRect &rect) const = 0;
virtual QRect get_label_rect(const QRect &rect, bool &visible) const = 0;
/**
* Paints the marker's label to the ruler.

View File

@@ -73,7 +73,7 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
QScrollArea(parent),
_session(session),
_sampling_bar(sampling_bar),
_scale(1e-5),
_scale(10),
_preScale(1e-6),
_maxscale(1e9),
_minscale(1e-15),
@@ -82,6 +82,7 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
_updating_scroll(false),
_show_cursors(false),
_hover_point(-1, -1),
_search_hit(false),
_dso_auto(true)
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
@@ -113,6 +114,7 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
_time_viewport->setMinimumHeight(100);
connect(_time_viewport, SIGNAL(measure_updated()),
this, SLOT(on_measure_updated()));
connect(_time_viewport, SIGNAL(prgRate(int)), this, SIGNAL(prgRate(int)));
_fft_viewport = new Viewport(*this, FFT_VIEW);
_fft_viewport->setVisible(false);
_fft_viewport->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
@@ -140,7 +142,7 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
layout->setContentsMargins(0,0,0,0);
_viewcenter->setLayout(layout);
layout->addWidget(_vsplitter, 0, 0);
_viewbottom = new widgets::ViewStatus(this);
_viewbottom = new widgets::ViewStatus(_session, this);
_viewbottom->setFixedHeight(StatusHeight);
layout->addWidget(_viewbottom, 1, 0);
setViewport(_viewcenter);
@@ -153,21 +155,21 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
this, SLOT(signals_changed()), Qt::DirectConnection);
connect(&_session, SIGNAL(data_updated()),
this, SLOT(data_updated()));
connect(&_session, SIGNAL(receive_header()),
this, SLOT(receive_header()));
connect(&_session, SIGNAL(receive_trigger(quint64)),
this, SLOT(receive_trigger(quint64)));
connect(&_session, SIGNAL(frame_ended()),
this, SLOT(receive_end()));
connect(&_session, SIGNAL(frame_began()),
this, SLOT(frame_began()));
connect(&_session, SIGNAL(show_region(uint64_t,uint64_t)),
this, SLOT(show_region(uint64_t, uint64_t)));
connect(&_session, SIGNAL(show_region(uint64_t, uint64_t, bool)),
this, SLOT(show_region(uint64_t, uint64_t, bool)));
connect(&_session, SIGNAL(show_wait_trigger()),
_time_viewport, SLOT(show_wait_trigger()));
connect(&_session, SIGNAL(repeat_hold(int)),
this, SLOT(repeat_show()));
connect(_devmode, SIGNAL(mode_changed()),
parent, SLOT(mode_changed()), Qt::DirectConnection);
this, SLOT(mode_changed()), Qt::DirectConnection);
connect(_header, SIGNAL(traces_moved()),
this, SLOT(on_traces_moved()));
@@ -188,7 +190,7 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
_trig_cursor = new Cursor(*this, Trace::dsLightRed, 0);
_show_search_cursor = false;
_search_pos = 0;
_search_cursor = new Cursor(*this, Trace::dsLightBlue, _search_pos);
_search_cursor = new Cursor(*this, Trace::dsGray, _search_pos);
_cali = new pv::dialogs::Calibration(this);
_cali->hide();
@@ -204,7 +206,7 @@ double View::scale() const
return _scale;
}
double View::offset() const
int64_t View::offset() const
{
return _offset;
}
@@ -219,6 +221,17 @@ double View::get_maxscale() const
return _maxscale;
}
void View::capture_init(bool instant)
{
if (_session.get_device()->dev_inst()->mode == DSO)
show_trig_cursor(true);
else if (!_session.isRepeating())
show_trig_cursor(false);
update_sample(instant);
status_clear();
}
void View::zoom(double steps)
{
zoom(steps, get_view_width() / 2);
@@ -241,7 +254,7 @@ void View::update_sample(bool instant)
BOOST_FOREACH(const boost::shared_ptr<pv::view::Signal> s, _session.get_signals()) {
boost::shared_ptr<pv::view::DsoSignal> dsoSig;
if (dsoSig = dynamic_pointer_cast<pv::view::DsoSignal>(s)) {
dsoSig->go_hDialCur();
dsoSig->update_capture();
break;
}
}
@@ -271,7 +284,6 @@ void View::zoom(double steps, int offset)
_preScale = _scale;
_preOffset = _offset;
const double cursor_offset = _offset + _scale * offset;
if (_session.get_device()->dev_inst()->mode != DSO) {
_scale *= std::pow(3.0/2.0, -steps);
_scale = max(min(_scale, _maxscale), _minscale);
@@ -292,7 +304,7 @@ void View::zoom(double steps, int offset)
}
}
_offset = cursor_offset - _scale * offset;
_offset = floor((_offset + offset) * (_preScale / _scale) - offset);
_offset = max(min(_offset, get_max_offset()), get_min_offset());
if (_scale != _preScale || _offset != _preOffset) {
@@ -305,14 +317,14 @@ void View::zoom(double steps, int offset)
}
void View::set_scale_offset(double scale, double offset)
void View::set_scale_offset(double scale, int64_t offset)
{
//if (_session.get_capture_state() == SigSession::Stopped) {
_preScale = _scale;
_preOffset = _offset;
_scale = max(min(scale, _maxscale), _minscale);
_offset = max(min(offset, get_max_offset()), get_min_offset());
_offset = floor(max(min(offset, get_max_offset()), get_min_offset()));
if (_scale != _preScale || _offset != _preOffset) {
update_scroll();
@@ -419,15 +431,18 @@ void View::status_clear()
_viewbottom->clear();
}
void View::receive_header()
void View::repeat_unshow()
{
status_clear();
_viewbottom->repeat_unshow();
}
void View::frame_began()
{
if (_session.get_device()->dev_inst()->mode == LOGIC)
_viewbottom->set_trig_time(_session.get_trigger_time());
_search_hit = false;
_search_pos = 0;
set_search_pos(_search_pos, _search_hit);
}
void View::receive_end()
@@ -460,7 +475,7 @@ void View::receive_trigger(quint64 trig_pos)
_session.get_device()->name() == "virtual-session" ||
_session.get_device()->dev_inst()->mode == DSO) {
_show_trig_cursor = true;
set_scale_offset(_scale, time - _scale * get_view_width() / 2);
set_scale_offset(_scale, (time / _scale) - (get_view_width() / 2));
}
_ruler->update();
@@ -473,16 +488,21 @@ void View::set_trig_pos(int percent)
receive_trigger(index);
}
void View::set_search_pos(uint64_t search_pos)
void View::set_search_pos(uint64_t search_pos, bool hit)
{
//assert(search_pos >= 0);
const double time = search_pos * 1.0 / _session.cur_samplerate();
_search_pos = search_pos;
_search_hit = hit;
_search_cursor->set_index(search_pos);
set_scale_offset(_scale, time - _scale * get_view_width() / 2);
_ruler->update();
viewport_update();
_search_cursor->set_colour(hit ? Trace::dsLightBlue : Trace::dsGray);
if (hit) {
set_scale_offset(_scale, (time / _scale) - (get_view_width() / 2));
_ruler->update();
viewport_update();
}
}
uint64_t View::get_search_pos()
@@ -490,6 +510,11 @@ uint64_t View::get_search_pos()
return _search_pos;
}
bool View::get_search_hit()
{
return _search_hit;
}
const QPoint& View::hover_point() const
{
return _hover_point;
@@ -522,14 +547,14 @@ int View::get_signalHeight()
return _signalHeight;
}
void View::get_scroll_layout(double &length, double &offset) const
void View::get_scroll_layout(int64_t &length, int64_t &offset) const
{
const set< boost::shared_ptr<data::SignalData> > data_set = _session.get_data();
if (data_set.empty())
return;
length = _session.get_device()->get_sample_time() / _scale;
offset = _offset / _scale;
length = ceil(_session.cur_sampletime() / _scale);
offset = _offset;
}
void View::update_scroll()
@@ -539,9 +564,10 @@ void View::update_scroll()
const QSize areaSize = _viewcenter->size();
// Set the horizontal scroll bar
double length = 0, offset = 0;
int64_t length = 0;
int64_t offset = 0;
get_scroll_layout(length, offset);
length = max(length - areaSize.width(), 0.0);
length = max(length - areaSize.width(), (int64_t)0);
horizontalScrollBar()->setPageStep(areaSize.width() / 2);
@@ -553,7 +579,7 @@ void View::update_scroll()
} else {
horizontalScrollBar()->setRange(0, MaxScrollValue);
horizontalScrollBar()->setSliderPosition(
_offset * MaxScrollValue / (_scale * length));
_offset * MaxScrollValue / length);
}
_updating_scroll = false;
@@ -569,7 +595,6 @@ void View::update_scale_offset()
assert(sample_rate > 0);
if (_session.get_device()->dev_inst()->mode != DSO) {
//_scale = (1.0 / sample_rate) / WellPixelsPerSample;
_maxscale = _session.cur_sampletime() / (get_view_width() * MaxViewRate);
_minscale = (1.0 / sample_rate) / MaxPixelsPerSample;
} else {
@@ -578,7 +603,6 @@ void View::update_scale_offset()
_minscale = 1e-15;
}
_scale = max(min(_scale, _maxscale), _minscale);
_offset = max(min(_offset, get_max_offset()), get_min_offset());
@@ -591,6 +615,18 @@ void View::update_scale_offset()
viewport_update();
}
void View::mode_changed()
{
const uint64_t sample_rate = _session.cur_samplerate();
assert(sample_rate > 0);
if (_session.get_device()->name().contains("virtual"))
_scale = WellSamplesPerPixel * 1.0 / sample_rate;
_scale = max(min(_scale, _maxscale), _minscale);
update_device_list();
}
void View::signals_changed()
{
int total_rows = 0;
@@ -624,7 +660,7 @@ void View::signals_changed()
_fft_viewport->setVisible(false);
_vsplitter->refresh();
// Find the decoder in the stack
// Find the _fft_viewport in the stack
std::list< Viewport *>::iterator iter = _viewport_list.begin();
for(unsigned int i = 0; i < _viewport_list.size(); i++, iter++)
if ((*iter) == _fft_viewport)
@@ -671,12 +707,7 @@ void View::signals_changed()
boost::shared_ptr<view::DsoSignal> dsoSig;
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(t)) {
GVariant *gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_DSO_BITS);
if (gvar != NULL) {
bits = g_variant_get_byte(gvar);
g_variant_unref(gvar);
}
dsoSig->set_scale(dsoSig->get_view_rect().height() * 1.0f / (1 << bits));
dsoSig->set_scale(dsoSig->get_view_rect().height());
}
}
_time_viewport->clear_measure();
@@ -695,10 +726,11 @@ bool View::eventFilter(QObject *object, QEvent *event)
const QMouseEvent *const mouse_event = (QMouseEvent*)event;
if (object == _ruler || object == _time_viewport || object == _fft_viewport) {
//_hover_point = QPoint(mouse_event->x(), 0);
double cur_periods = (mouse_event->pos().x() * _scale + _offset) / _ruler->get_min_period();
int integer_x = (round(cur_periods) * _ruler->get_min_period() - _offset ) / _scale;
double cur_periods = (mouse_event->pos().x() + _offset) * _scale / _ruler->get_min_period();
int integer_x = round(cur_periods) * _ruler->get_min_period() / _scale - _offset;
double cur_deviate_x = qAbs(mouse_event->pos().x() - integer_x);
if (cur_deviate_x < 10)
if (_session.get_device()->dev_inst()->mode == LOGIC &&
cur_deviate_x < 10)
_hover_point = QPoint(integer_x, mouse_event->pos().y());
else
_hover_point = mouse_event->pos();
@@ -789,11 +821,12 @@ void View::h_scroll_value_changed(int value)
const int range = horizontalScrollBar()->maximum();
if (range < MaxScrollValue)
_offset = _scale * value;
_offset = value;
else {
double length = 0, offset;
int64_t length = 0;
int64_t offset = 0;
get_scroll_layout(length, offset);
_offset = _scale * length * value / MaxScrollValue;
_offset = floor(length * value / MaxScrollValue);
}
_offset = max(min(_offset, get_max_offset()), get_min_offset());
@@ -859,7 +892,6 @@ void View::on_traces_moved()
update_scroll();
set_update(_time_viewport, true);
viewport_update();
//traces_moved();
}
/*
@@ -908,7 +940,7 @@ void View::set_cursor_middle(int index)
list<Cursor*>::iterator i = _cursorList.begin();
while (index-- != 0)
i++;
set_scale_offset(_scale, (*i)->index() * 1.0 / _session.cur_samplerate() - _scale * get_view_width() / 2);
set_scale_offset(_scale, (*i)->index() / (_session.cur_samplerate() * _scale) - (get_view_width() / 2));
}
void View::on_measure_updated()
@@ -955,11 +987,6 @@ uint64_t View::get_cursor_samples(int index)
}
}
void View::on_cursor_moved()
{
cursor_moved();
}
void View::set_measure_en(int enable)
{
BOOST_FOREACH(Viewport *viewport, _viewport_list)
@@ -1017,15 +1044,18 @@ int View::get_view_height()
return view_height;
}
double View::get_min_offset()
int64_t View::get_min_offset()
{
return -(_scale * (get_view_width() * (1 - MaxViewRate)));
if (MaxViewRate > 1)
return floor(get_view_width() * (1 - MaxViewRate));
else
return 0;
}
double View::get_max_offset()
int64_t View::get_max_offset()
{
return _session.get_device()->get_sample_time()
- _scale * (get_view_width() * MaxViewRate);
return ceil((_session.cur_sampletime() / _scale) -
(get_view_width() * MaxViewRate));
}
// -- calibration dialog
@@ -1047,13 +1077,22 @@ void View::update_calibration()
}
}
void View::show_region(uint64_t start, uint64_t end)
void View::show_region(uint64_t start, uint64_t end, bool keep)
{
assert(start <= end);
const double ideal_scale = (end-start) * 2.0 / _session.cur_samplerate() / get_view_width();
const double new_scale = max(min(ideal_scale, _maxscale), _minscale);
const double new_off = (start + end) * 0.5 / _session.cur_samplerate() - new_scale * get_view_width() / 2;
set_scale_offset(new_scale, new_off);
if (keep) {
set_all_update(true);
update();
} else if (_session.get_map_zoom() == 0) {
const double ideal_scale = (end-start) * 2.0 / _session.cur_samplerate() / get_view_width();
const double new_scale = max(min(ideal_scale, _maxscale), _minscale);
const double new_off = (start + end) * 0.5 / (_session.cur_samplerate() * new_scale) - (get_view_width() / 2);
set_scale_offset(new_scale, new_off);
} else {
const double new_scale = scale();
const double new_off = (start + end) * 0.5 / (_session.cur_samplerate() * new_scale) - (get_view_width() / 2);
set_scale_offset(new_scale, new_off);
}
}
void View::viewport_update()
@@ -1082,8 +1121,48 @@ void View::reload()
_viewbottom->setFixedHeight(StatusHeight);
else
_viewbottom->setFixedHeight(10);
}
void View::repeat_show()
{
_viewbottom->update();
}
bool View::get_capture_status(bool &triggered, int &progress)
{
uint64_t sample_limits = _session.cur_samplelimits();
sr_status status;
if (sr_status_get(_session.get_device()->dev_inst(), &status, SR_STATUS_TRIG_BEGIN, SR_STATUS_TRIG_END) == SR_OK){
triggered = status.trig_hit & 0x01;
const bool captured_cnt_dec = status.trig_hit & 0x02;
uint64_t captured_cnt = status.trig_hit >> 2;
captured_cnt = ((uint64_t)status.captured_cnt0 +
((uint64_t)status.captured_cnt1 << 8) +
((uint64_t)status.captured_cnt2 << 16) +
((uint64_t)status.captured_cnt3 << 24) +
(captured_cnt << 32));
if (_session.get_device()->dev_inst()->mode == DSO)
captured_cnt = captured_cnt * _session.get_signals().size() / _session.get_ch_num(SR_CHANNEL_DSO);
if (captured_cnt_dec)
progress = (sample_limits - captured_cnt) * 100.0 / sample_limits;
else
progress = captured_cnt * 100.0 / sample_limits;
return true;
}
return false;
}
void View::set_capture_status()
{
bool triggered;
int progress;
if (_session.get_capture_status(triggered, progress)) {
_viewbottom->set_capture_status(triggered, progress);
_viewbottom->update();
}
}
} // namespace view

View File

@@ -80,7 +80,7 @@ public:
static const QSizeF LabelPadding;
static const int WellPixelsPerSample = 10;
static const int WellSamplesPerPixel = 2048;
static constexpr double MaxViewRate = 1.0;
static const int MaxPixelsPerSample = 100;
@@ -97,14 +97,15 @@ public:
double scale() const;
/**
* Returns the time offset of the left edge of the view in
* seconds.
* Returns the pixels offset of the left edge of the view
*/
double offset() const;
int64_t offset() const;
int v_offset() const;
double get_min_offset();
double get_max_offset();
int64_t get_min_offset();
int64_t get_max_offset();
void capture_init(bool instant);
void zoom(double steps);
void zoom(double steps, int offset);
@@ -114,7 +115,7 @@ public:
* @param scale The new view scale in seconds per pixel.
* @param offset The view time offset in seconds.
*/
void set_scale_offset(double scale, double offset);
void set_scale_offset(double scale, int64_t offset);
void set_preScale_preOffset();
std::vector< boost::shared_ptr<Trace> > get_traces(int type);
@@ -157,8 +158,9 @@ public:
Cursor* get_trig_cursor();
Cursor* get_search_cursor();
bool get_search_hit();
void set_search_pos(uint64_t search_pos);
void set_search_pos(uint64_t search_pos, bool hit);
uint64_t get_search_pos();
@@ -175,8 +177,6 @@ public:
QString get_cm_time(int index);
QString get_cm_delta(int index1, int index2);
void on_cursor_moved();
void on_state_changed(bool stop);
QRect get_view_rect();
@@ -193,19 +193,25 @@ public:
void viewport_update();
bool get_capture_status(bool &triggered, int &progress);
void set_capture_status();
signals:
void hover_point_changed();
void traces_moved();
void cursor_update();
void cursor_moving();
void cursor_moved();
void measure_updated();
void prgRate(int progress);
void update_device_list();
private:
void get_scroll_layout(double &length, double &offset) const;
void get_scroll_layout(int64_t &length, int64_t &offset) const;
void update_scroll();
@@ -228,11 +234,14 @@ public slots:
void signals_changed();
void data_updated();
void update_scale_offset();
void show_region(uint64_t start, uint64_t end);
void show_region(uint64_t start, uint64_t end, bool keep);
// -- calibration
void update_calibration();
void hide_calibration();
void status_clear();
void repeat_unshow();
// -- repeat
void repeat_show();
private slots:
@@ -245,8 +254,6 @@ private slots:
void header_updated();
void receive_header();
void receive_trigger(quint64 trig_pos);
void set_trig_pos(int percent);
@@ -260,6 +267,8 @@ private slots:
void splitterMoved(int pos, int index);
void mode_changed();
private:
SigSession &_session;
@@ -279,32 +288,29 @@ private:
/// The view time scale in seconds per pixel.
double _scale;
double _preScale;
double _maxscale;
double _minscale;
double _preScale;
double _maxscale;
double _minscale;
/// The view time offset in seconds.
double _offset;
double _preOffset;
int _spanY;
int _signalHeight;
bool _updating_scroll;
/// The pixels offset of the left edge of the view
int64_t _offset;
int64_t _preOffset;
int _spanY;
int _signalHeight;
bool _updating_scroll;
bool _show_cursors;
std::list<Cursor*> _cursorList;
Cursor *_trig_cursor;
bool _show_trig_cursor;
Cursor *_search_cursor;
bool _show_search_cursor;
uint64_t _search_pos;
bool _search_hit;
std::list<Cursor*> _cursorList;
Cursor *_trig_cursor;
bool _show_trig_cursor;
Cursor *_search_cursor;
bool _show_search_cursor;
uint64_t _search_pos;
QPoint _hover_point;
dialogs::Calibration *_cali;
bool _dso_auto;
QPoint _hover_point;
dialogs::Calibration *_cali;
bool _dso_auto;
};
} // namespace view

View File

@@ -57,7 +57,7 @@ Viewport::Viewport(View &parent, View_type type) :
_view(parent),
_type(type),
_need_update(false),
_total_receive_len(0),
_sample_received(0),
_action_type(NO_ACTION),
_measure_type(NO_MEASURE),
_cur_sample(0),
@@ -81,15 +81,13 @@ Viewport::Viewport(View &parent, View_type type) :
_mm_freq = "#####";
_mm_duty = "#####";
_measure_en = true;
triggered = false;
transfer_started = false;
timer_cnt = 0;
// drag inertial
_drag_strength = 0;
_drag_timer.setSingleShot(true);
connect(&_view, SIGNAL(traces_moved()),
this, SLOT(on_traces_moved()));
connect(&trigger_timer, SIGNAL(timeout()),
this, SLOT(on_trigger_timer()));
connect(&_drag_timer, SIGNAL(timeout()),
@@ -135,7 +133,7 @@ void Viewport::paintEvent(QPaintEvent *event)
{
assert(t);
t->paint_back(p, 0, _view.get_view_width());
if (t->enabled() && _view.session().get_device()->dev_inst()->mode == DSO)
if (_view.session().get_device()->dev_inst()->mode == DSO)
break;
}
@@ -151,7 +149,12 @@ void Viewport::paintEvent(QPaintEvent *event)
break;
case SigSession::Running:
if (_type == TIME_VIEW) {
if (_view.session().isRepeating() &&
!transfer_started) {
_view.set_capture_status();
paintSignals(p);
} else if (_type == TIME_VIEW) {
_view.repeat_unshow();
p.setRenderHint(QPainter::Antialiasing);
paintProgress(p);
p.setRenderHint(QPainter::Antialiasing, false);
@@ -205,27 +208,33 @@ void Viewport::paintSignals(QPainter &p)
p.drawPixmap(0, 0, pixmap);
// plot cursors
const double samples_per_pixel = _view.session().cur_samplerate() * _view.scale();
if (_view.cursors_shown() && _type == TIME_VIEW) {
list<Cursor*>::iterator i = _view.get_cursorList().begin();
double cursorX;
const double samples_per_pixel = _view.session().cur_samplerate() * _view.scale();
int index = 0;
while (i != _view.get_cursorList().end()) {
cursorX = (*i)->index()/samples_per_pixel - (_view.offset() / _view.scale());
const int64_t cursorX = (*i)->index()/samples_per_pixel - _view.offset();
if (rect().contains(_view.hover_point().x(), _view.hover_point().y()) &&
qAbs(cursorX - _view.hover_point().x()) <= HitCursorMargin)
(*i)->paint(p, rect(), 1);
(*i)->paint(p, rect(), 1, index);
else
(*i)->paint(p, rect(), 0);
(*i)->paint(p, rect(), 0, index);
i++;
index++;
}
}
if (_type == TIME_VIEW) {
if (_view.trig_cursor_shown()) {
_view.get_trig_cursor()->paint(p, rect(), 0);
_view.get_trig_cursor()->paint(p, rect(), 0, -1);
}
if (_view.search_cursor_shown()) {
_view.get_search_cursor()->paint(p, rect(), 0);
const int64_t searchX = _view.get_search_cursor()->index()/samples_per_pixel - _view.offset();
if (rect().contains(_view.hover_point().x(), _view.hover_point().y()) &&
qAbs(searchX - _view.hover_point().x()) <= HitCursorMargin)
_view.get_search_cursor()->paint(p, rect(), 1, -1);
else
_view.get_search_cursor()->paint(p, rect(), 0, -1);
}
// plot zoom rect
@@ -276,9 +285,9 @@ void Viewport::paintProgress(QPainter &p)
{
using pv::view::Signal;
const uint64_t _total_sample_len = _view.session().cur_samplelimits();
const uint64_t sample_limits = _view.session().cur_samplelimits();
double progress = -(_total_receive_len * 1.0 / _total_sample_len * 360 * 16);
double progress = -(_sample_received * 1.0 / sample_limits * 360 * 16);
int captured_progress = 0;
p.setPen(Qt::gray);
@@ -344,7 +353,7 @@ void Viewport::paintProgress(QPainter &p)
p.drawEllipse(logoPoints[19].x() - 0.5 * logoRadius, logoPoints[19].y() - logoRadius,
logoRadius, logoRadius);
if (!triggered) {
if (!transfer_started) {
const int width = _view.get_view_width();
const QPoint cenLeftPos = QPoint(width / 2 - 0.05 * width, height() / 2);
const QPoint cenRightPos = QPoint(width / 2 + 0.05 * width, height() / 2);
@@ -359,37 +368,38 @@ void Viewport::paintProgress(QPainter &p)
p.drawEllipse(cenRightPos, trigger_radius, trigger_radius);
sr_status status;
if (sr_status_get(_view.session().get_device()->dev_inst(), &status, SR_STATUS_TRIG_BEGIN, SR_STATUS_TRIG_END) == SR_OK){
const bool triggred = status.trig_hit & 0x01;
uint32_t captured_cnt = (status.captured_cnt0 +
(status.captured_cnt1 << 8) +
(status.captured_cnt2 << 16) +
(status.captured_cnt3 << 24));
if (_view.session().get_device()->dev_inst()->mode == DSO)
captured_cnt = captured_cnt * _view.session().get_signals().size() / _view.session().get_ch_num(SR_CHANNEL_DSO);
if (triggred)
captured_progress = (_total_sample_len - captured_cnt) * 100.0 / _total_sample_len;
else
captured_progress = captured_cnt * 100.0 / _total_sample_len;
bool triggered;
if (_view.session().get_capture_status(triggered, captured_progress)){
p.setPen(Trace::dsLightBlue);
QFont font=p.font();
font.setPointSize(10);
font.setBold(true);
p.setFont(font);
QRect status_rect = QRect(cenPos.x() - radius, cenPos.y() + radius * 0.4, radius * 2, radius * 0.5);
if (triggred)
if (triggered)
p.drawText(status_rect,
Qt::AlignCenter | Qt::AlignVCenter,
"Triggered! " + QString::number(captured_progress)+"% Captured");
tr("Triggered! ") + QString::number(captured_progress) + tr("% Captured"));
else
p.drawText(status_rect,
Qt::AlignCenter | Qt::AlignVCenter,
"Waiting for Trigger! " + QString::number(captured_progress)+"% Captured");
tr("Waiting for Trigger! ") + QString::number(captured_progress) + tr("% Captured"));
prgRate(captured_progress);
}
} else {
if (_view.session().get_error() == SigSession::No_err) {
GVariant *gvar = _view.session().get_device()->get_config(NULL, NULL, SR_CONF_HW_STATUS);
if (gvar != NULL) {
uint8_t hw_info = g_variant_get_byte(gvar);
g_variant_unref(gvar);
if (hw_info & 0x10) {
_view.session().set_error(SigSession::Data_overflow);
_view.session().session_error();
}
}
}
const int progress100 = ceil(progress / -3.6 / 16);
p.setPen(Trace::dsGreen);
QFont font=p.font();
@@ -397,6 +407,7 @@ void Viewport::paintProgress(QPainter &p)
font.setBold(true);
p.setFont(font);
p.drawText(rect(), Qt::AlignCenter | Qt::AlignVCenter, QString::number(progress100)+"%");
prgRate(progress100);
}
p.setPen(QPen(Trace::dsLightBlue, 4, Qt::SolidLine));
@@ -444,7 +455,7 @@ void Viewport::mousePressEvent(QMouseEvent *event)
_action_type = LOGIC_ZOOM;
} else if (_view.session().get_device()->dev_inst()->mode == DSO) {
if (_hover_hit) {
uint64_t index = (_view.offset() + (event->pos().x() + 0.5) * _view.scale()) * _view.session().cur_samplerate();
const int64_t index = (_view.offset() + event->pos().x()) * _view.scale() * _view.session().cur_samplerate();
_view.add_cursor(view::Ruler::CursorColor[_view.get_cursorList().size() % 8], index);
_view.show_cursors(true);
}
@@ -460,9 +471,7 @@ void Viewport::mouseMoveEvent(QMouseEvent *event)
if (event->buttons() & Qt::LeftButton) {
if (_type == TIME_VIEW) {
_view.set_scale_offset(_view.scale(),
_mouse_down_offset +
(_mouse_down_point - event->pos()).x() *
_view.scale());
_mouse_down_offset + (_mouse_down_point - event->pos()).x());
_drag_strength = (_mouse_down_point - event->pos()).x();
} else if (_type == FFT_VIEW) {
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> t, _view.session().get_math_signals()) {
@@ -489,7 +498,7 @@ void Viewport::mouseMoveEvent(QMouseEvent *event)
if (_action_type == CURS_MOVE) {
uint64_t sample_rate = _view.session().cur_samplerate();
TimeMarker* grabbed_marker = _view.get_ruler()->get_grabbed_cursor();
if (_view.cursors_shown() && grabbed_marker) {
if (grabbed_marker) {
int curX = _view.hover_point().x();
uint64_t index0 = 0, index1 = 0, index2 = 0;
bool logic = false;
@@ -512,13 +521,12 @@ void Viewport::mouseMoveEvent(QMouseEvent *event)
}
}
const double cur_time = _view.offset() + curX * _view.scale();
const double cur_time = (_view.offset() + curX) * _view.scale();
const double pos = cur_time * sample_rate;
const double pos_delta = pos - (uint64_t)pos;
const double samples_per_pixel = sample_rate * _view.scale();
const double index_offset = _view.offset() / _view.scale();
const double curP = index0 / samples_per_pixel - index_offset;
const double curN = index1 / samples_per_pixel - index_offset;
const double curP = index0 / samples_per_pixel - _view.offset();
const double curN = index1 / samples_per_pixel - _view.offset();
if (logic && (curX - curP < SnapMinSpace || curN - curX < SnapMinSpace)) {
if (curX - curP < curN - curX)
grabbed_marker->set_index(index0);
@@ -529,6 +537,12 @@ void Viewport::mouseMoveEvent(QMouseEvent *event)
} else {
grabbed_marker->set_index((uint64_t)ceil(pos));
}
if (grabbed_marker == _view.get_search_cursor()) {
_view.set_search_pos(grabbed_marker->index(), false);
}
_view.cursor_moving();
}
}
@@ -563,15 +577,23 @@ void Viewport::mouseReleaseEvent(QMouseEvent *event)
assert(event);
if (_type == TIME_VIEW) {
const double samples_per_pixel = _view.session().cur_samplerate() * _view.scale();
if ((_action_type == NO_ACTION) &&
(event->button() == Qt::LeftButton)) {
// priority 0
if (_action_type == NO_ACTION && _view.search_cursor_shown()) {
const int64_t searchX = _view.get_search_cursor()->index()/samples_per_pixel - _view.offset();
if (_view.get_search_cursor()->grabbed()) {
_view.get_ruler()->rel_grabbed_cursor();
} else if (qAbs(searchX - event->pos().x()) <= HitCursorMargin) {
_view.get_ruler()->set_grabbed_cursor(_view.get_search_cursor());
_action_type = CURS_MOVE;
}
}
if (_action_type == NO_ACTION && _view.cursors_shown()) {
list<Cursor*>::iterator i = _view.get_cursorList().begin();
double cursorX;
const double samples_per_pixel = _view.session().cur_samplerate() * _view.scale();
while (i != _view.get_cursorList().end()) {
cursorX = (*i)->index()/samples_per_pixel - (_view.offset() / _view.scale());
const int64_t cursorX = (*i)->index()/samples_per_pixel - _view.offset();
if ((*i)->grabbed()) {
_view.get_ruler()->rel_grabbed_cursor();
} else if (qAbs(cursorX - event->pos().x()) <= HitCursorMargin) {
@@ -609,7 +631,7 @@ void Viewport::mouseReleaseEvent(QMouseEvent *event)
assert(s);
if (abs(event->pos().y() - s->get_y()) < _view.get_signalHeight()) {
_action_type = LOGIC_EDGE;
_edge_start = (_view.offset() + (event->pos().x() + 0.5) * _view.scale()) * _view.session().cur_samplerate();
_edge_start = (_view.offset() + event->pos().x()) * _view.scale() * _view.session().cur_samplerate();
break;
}
}
@@ -664,11 +686,7 @@ void Viewport::mouseReleaseEvent(QMouseEvent *event)
}
} else if (_action_type == DSO_XM_STEP1) {
if (event->button() == Qt::LeftButton) {
const uint64_t sample_rate = _view.session().cur_samplerate();
const double scale = _view.scale();
const double samples_per_pixel = sample_rate * scale;
_dso_xm_index[1] = event->pos().x() * samples_per_pixel + _view.offset() * sample_rate;
_dso_xm_index[1] = (event->pos().x() + _view.offset()) * samples_per_pixel;
const uint64_t max_index = max(_dso_xm_index[0], _dso_xm_index[1]);
_dso_xm_index[0] = min(_dso_xm_index[0], _dso_xm_index[1]);
_dso_xm_index[1] = max_index;
@@ -685,10 +703,7 @@ void Viewport::mouseReleaseEvent(QMouseEvent *event)
}
} else if (_action_type == DSO_XM_STEP2) {
if (event->button() == Qt::LeftButton) {
const uint64_t sample_rate = _view.session().cur_samplerate();
const double scale = _view.scale();
const double samples_per_pixel = sample_rate * scale;
_dso_xm_index[2] = event->pos().x() * samples_per_pixel + _view.offset() * sample_rate;
_dso_xm_index[2] = (event->pos().x() + _view.offset()) * samples_per_pixel;
uint64_t max_index = max(_dso_xm_index[1], _dso_xm_index[2]);
_dso_xm_index[1] = min(_dso_xm_index[1], _dso_xm_index[2]);
_dso_xm_index[2] = max_index;
@@ -709,15 +724,18 @@ void Viewport::mouseReleaseEvent(QMouseEvent *event)
}
} else if (_action_type == CURS_MOVE) {
_action_type = NO_ACTION;
if (_view.cursors_shown()) {
list<Cursor*>::iterator i = _view.get_cursorList().begin();
while (i != _view.get_cursorList().end()) {
if ((*i)->grabbed()) {
_view.get_ruler()->rel_grabbed_cursor();
}
i++;
}
}
_view.get_ruler()->rel_grabbed_cursor();
// if (_view.cursors_shown()) {
// list<Cursor*>::iterator i = _view.get_cursorList().begin();
// while (i != _view.get_cursorList().end()) {
// if ((*i)->grabbed()) {
// _view.get_ruler()->rel_grabbed_cursor();
// }
// i++;
// }
// }
_view.cursor_moved();
} else if (_action_type == LOGIC_EDGE) {
_action_type = NO_ACTION;
_edge_rising = 0;
@@ -741,9 +759,10 @@ void Viewport::mouseReleaseEvent(QMouseEvent *event)
}
} else if (_action_type == LOGIC_ZOOM) {
if (event->pos().x() != _mouse_down_point.x()) {
const double newOffset = _view.offset() + (min(event->pos().x(), _mouse_down_point.x()) + 0.5) * _view.scale();
int64_t newOffset = _view.offset() + (min(event->pos().x(), _mouse_down_point.x()));
const double newScale = max(min(_view.scale() * abs(event->pos().x() - _mouse_down_point.x()) / _view.get_view_width(),
_view.get_maxscale()), _view.get_minscale());
newOffset = floor(newOffset * (_view.scale() / newScale));
if (newScale != _view.scale())
_view.set_scale_offset(newScale, newOffset);
}
@@ -764,9 +783,37 @@ void Viewport::mouseDoubleClickEvent(QMouseEvent *event)
if (_view.scale() == _view.get_maxscale())
_view.set_preScale_preOffset();
else
_view.set_scale_offset(_view.get_maxscale(), 0);
_view.set_scale_offset(_view.get_maxscale(), _view.get_min_offset());
} else if (event->button() == Qt::LeftButton) {
uint64_t index = (_view.offset() + (event->pos().x() + 0.5) * _view.scale()) * _view.session().cur_samplerate();
bool logic = false;
uint64_t index;
uint64_t index0 = 0, index1 = 0, index2 = 0;
if (_view.session().get_device()->dev_inst()->mode == LOGIC) {
const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals());
BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
assert(s);
boost::shared_ptr<view::LogicSignal> logicSig;
if ((logicSig = dynamic_pointer_cast<view::LogicSignal>(s))) {
if (logicSig->measure(event->pos(), index0, index1, index2)) {
logic = true;
break;
}
}
}
}
const uint64_t sample_rate = _view.session().cur_samplerate();
const double curX = event->pos().x();
const double samples_per_pixel = sample_rate * _view.scale();
const double curP = index0 / samples_per_pixel - _view.offset();
const double curN = index1 / samples_per_pixel - _view.offset();
if (logic && (curX - curP < SnapMinSpace || curN - curX < SnapMinSpace)) {
if (curX - curP < curN - curX)
index = index0;
else
index = index1;
} else {
index = (_view.offset() + curX) * _view.scale() * sample_rate;;
}
_view.add_cursor(view::Ruler::CursorColor[_view.get_cursorList().size() % 8], index);
_view.show_cursors(true);
}
@@ -789,8 +836,7 @@ void Viewport::mouseDoubleClickEvent(QMouseEvent *event)
uint64_t sample_rate = _view.session().cur_samplerate();
double scale = _view.scale();
const double samples_per_pixel = sample_rate * scale;
_dso_xm_index[0] = event->pos().x() * samples_per_pixel +
_view.offset() * sample_rate;
_dso_xm_index[0] = (event->pos().x() + _view.offset()) * samples_per_pixel;
_dso_xm_y = event->pos().y();
_action_type = DSO_XM_STEP0;
}
@@ -815,13 +861,12 @@ void Viewport::wheelEvent(QWheelEvent *event)
} else if (_type == TIME_VIEW){
if (event->orientation() == Qt::Vertical) {
// Vertical scrolling is interpreted as zooming in/out
const double offset = event->x();
const int offset = event->x();
_view.zoom(event->delta() / 80, offset);
} else if (event->orientation() == Qt::Horizontal) {
// Horizontal scrolling is interpreted as moving left/right
_view.set_scale_offset(_view.scale(),
event->delta() * _view.scale()
+ _view.offset());
event->delta() + _view.offset());
}
}
@@ -857,22 +902,17 @@ void Viewport::leaveEvent(QEvent *)
update();
}
void Viewport::on_traces_moved()
{
update();
}
void Viewport::set_receive_len(quint64 length)
{
if (length == 0) {
_total_receive_len = 0;
_sample_received = 0;
start_trigger_timer(333);
} else {
stop_trigger_timer();
if (_total_receive_len + length > _view.session().cur_samplelimits())
_total_receive_len = _view.session().cur_samplelimits();
if (_sample_received + length > _view.session().cur_samplelimits())
_sample_received = _view.session().cur_samplelimits();
else
_total_receive_len += length;
_sample_received += length;
}
update();
}
@@ -904,11 +944,10 @@ void Viewport::measure()
_mm_period = _thd_sample != 0 ? _view.get_ruler()->format_real_time(_thd_sample - _cur_sample, sample_rate) : "#####";
_mm_freq = _thd_sample != 0 ? _view.get_ruler()->format_real_freq(_thd_sample - _cur_sample, sample_rate) : "#####";
const double pixels_offset = _view.offset() / _view.scale();
const double samples_per_pixel = sample_rate * _view.scale();
_cur_preX = _cur_sample / samples_per_pixel - pixels_offset;
_cur_aftX = _nxt_sample / samples_per_pixel - pixels_offset;
_cur_thdX = _thd_sample / samples_per_pixel - pixels_offset;
_cur_preX = _cur_sample / samples_per_pixel - _view.offset();
_cur_aftX = _nxt_sample / samples_per_pixel - _view.offset();
_cur_thdX = _thd_sample / samples_per_pixel - _view.offset();
_cur_midY = logicSig->get_y();
_mm_duty = _thd_sample != 0 ? QString::number((_nxt_sample - _cur_sample) * 100.0 / (_thd_sample - _cur_sample), 'f', 2)+"%" :
@@ -923,9 +962,8 @@ void Viewport::measure()
}
} else if (_action_type == LOGIC_EDGE) {
if (logicSig->edges(_view.hover_point(), _edge_start, _edge_rising, _edge_falling)) {
const double pixels_offset = _view.offset() / _view.scale();
const double samples_per_pixel = sample_rate * _view.scale();
_cur_preX = _edge_start / samples_per_pixel - pixels_offset;
_cur_preX = _edge_start / samples_per_pixel - _view.offset();
_cur_aftX = _view.hover_point().x();
_cur_midY = logicSig->get_y() - logicSig->get_totalHeight()/2 - 5;
@@ -1086,8 +1124,8 @@ void Viewport::paintMeasure(QPainter &p)
const int text_height = p.boundingRect(0, 0, INT_MAX, INT_MAX,
Qt::AlignLeft | Qt::AlignTop, "W").height();
const uint64_t sample_rate = _view.session().cur_samplerate();
const double x = (_dso_ym_index / (sample_rate * _view.scale())) -
_view.offset() /_view.scale();
const int64_t x = (_dso_ym_index / (sample_rate * _view.scale())) -
_view.offset();
p.drawLine(x-10, _dso_ym_start,
x+10, _dso_ym_start);
p.drawLine(x, _dso_ym_start,
@@ -1135,7 +1173,7 @@ void Viewport::paintMeasure(QPainter &p)
QLineF *line;
QLineF *const measure_lines = new QLineF[measure_line_count];
line = measure_lines;
double x[DsoMeasureStages];
int64_t x[DsoMeasureStages];
int dso_xm_stage = 0;
if (_action_type == DSO_XM_STEP1)
dso_xm_stage = 1;
@@ -1146,18 +1184,18 @@ void Viewport::paintMeasure(QPainter &p)
for (int i = 0; i < dso_xm_stage; i++) {
x[i] = (_dso_xm_index[i] / (sample_rate * _view.scale())) -
_view.offset() /_view.scale();
_view.offset();
}
measure_line_count = 0;
if (dso_xm_stage > 0) {
*line++ = QLineF(x[0], _dso_xm_y - 10,
*line++ = QLine(x[0], _dso_xm_y - 10,
x[0], _dso_xm_y + 10);
measure_line_count += 1;
}
if (dso_xm_stage > 1) {
*line++ = QLineF(x[1], _dso_xm_y - 10,
*line++ = QLine(x[1], _dso_xm_y - 10,
x[1], _dso_xm_y + 10);
*line++ = QLineF(x[0], _dso_xm_y,
*line++ = QLine(x[0], _dso_xm_y,
x[1], _dso_xm_y);
_mm_width = _view.get_ruler()->format_real_time(_dso_xm_index[1] - _dso_xm_index[0], sample_rate);
@@ -1274,14 +1312,14 @@ void Viewport::set_measure_en(int enable)
void Viewport::start_trigger_timer(int msec)
{
assert(msec > 0);
triggered = false;
transfer_started = false;
timer_cnt = 0;
trigger_timer.start(msec);
}
void Viewport::stop_trigger_timer()
{
triggered = true;
transfer_started = true;
timer_cnt = 0;
trigger_timer.stop();
}
@@ -1294,13 +1332,13 @@ void Viewport::on_trigger_timer()
void Viewport::on_drag_timer()
{
const double offset = _view.offset();
const int64_t offset = _view.offset();
const double scale = _view.scale();
if (_view.session().get_capture_state() == SigSession::Stopped &&
_drag_strength != 0 &&
offset < _view.get_max_offset() &&
offset > _view.get_min_offset()) {
_view.set_scale_offset(scale, offset + _drag_strength * scale);
_view.set_scale_offset(scale, offset + _drag_strength);
_drag_strength /= DragDamping;
if (_drag_strength != 0)
_drag_timer.start(DragTimerInterval);

View File

@@ -119,7 +119,6 @@ private:
void measure();
private slots:
void on_traces_moved();
void on_trigger_timer();
void on_drag_timer();
void set_receive_len(quint64 length);
@@ -130,18 +129,19 @@ public slots:
signals:
void measure_updated();
void prgRate(int progress);
private:
View &_view;
View_type _type;
bool _need_update;
uint64_t _total_receive_len;
uint64_t _sample_received;
QPoint _mouse_point;
QPoint _mouse_down_point;
double _mouse_down_offset;
int64_t _mouse_down_offset;
double _curScale;
double _curOffset;
int64_t _curOffset;
int _curSignalHeight;
QPixmap pixmap;
@@ -152,10 +152,10 @@ private:
uint64_t _cur_sample;
uint64_t _nxt_sample;
uint64_t _thd_sample;
double _cur_preX;
double _cur_aftX;
double _cur_thdX;
double _cur_midY;
int64_t _cur_preX;
int64_t _cur_aftX;
int64_t _cur_thdX;
int _cur_midY;
QString _mm_width;
QString _mm_period;
QString _mm_freq;
@@ -169,7 +169,7 @@ private:
QString _em_edges;
QTimer trigger_timer;
bool triggered;
bool transfer_started;
int timer_cnt;
boost::shared_ptr<Signal> _drag_sig;

View File

@@ -103,5 +103,10 @@ void Border::paintEvent(QPaintEvent *)
}
}
void Border::leaveEvent(QEvent*)
{
//setCursor(Qt::ArrowCursor);
}
} // namespace widgets
} // namespace pv

View File

@@ -35,6 +35,7 @@ public:
protected:
void paintEvent(QPaintEvent *);
void leaveEvent(QEvent *);
private:
int _type;

View File

@@ -26,11 +26,14 @@
#include <QStyleOption>
#include "../view/trace.h"
#include "../sigsession.h"
namespace pv {
namespace widgets {
ViewStatus::ViewStatus(QWidget *parent) : QWidget(parent)
ViewStatus::ViewStatus(SigSession &session, QWidget *parent) :
_session(session),
QWidget(parent)
{
}
@@ -44,12 +47,28 @@ void ViewStatus::paintEvent(QPaintEvent *)
p.setPen(pv::view::Trace::DARK_FORE);
p.drawText(this->rect(), Qt::AlignLeft | Qt::AlignVCenter, _rle_depth);
p.drawText(this->rect(), Qt::AlignRight | Qt::AlignVCenter, _trig_time);
p.setPen(Qt::NoPen);
p.setBrush(pv::view::Trace::dsLightBlue);
p.drawRect(this->rect().left(), this->rect().bottom() - 3,
_session.get_repeat_hold() * this->rect().width() / 100, 3);
p.setPen(pv::view::Trace::dsLightBlue);
p.drawText(this->rect(), Qt::AlignCenter | Qt::AlignVCenter, _capture_status);
}
void ViewStatus::clear()
{
_trig_time.clear();
_rle_depth.clear();
_capture_status.clear();
update();
}
void ViewStatus::repeat_unshow()
{
_capture_status.clear();
update();
}
void ViewStatus::set_trig_time(QDateTime time)
@@ -59,7 +78,15 @@ void ViewStatus::set_trig_time(QDateTime time)
void ViewStatus::set_rle_depth(uint64_t depth)
{
_rle_depth = tr("RLE FULL: ") + QString::number(depth) + tr(" Samples Captured!");
_rle_depth = QString::number(depth) + tr(" Samples Captured!");
}
void ViewStatus::set_capture_status(bool triggered, int progess)
{
if (triggered)
_capture_status = tr("Triggered! ") + QString::number(progess) + tr("% Captured");
else
_capture_status = tr("Waiting for Trigger! ") + QString::number(progess) + tr("% Captured");
}
} // namespace widgets

View File

@@ -24,7 +24,7 @@
#include <QWidget>
#include <QLabel>
#include "QDateTime"
#include <QDateTime>
namespace pv {
@@ -36,7 +36,7 @@ class ViewStatus : public QWidget
{
Q_OBJECT
public:
explicit ViewStatus(QWidget *parent = 0);
explicit ViewStatus(SigSession &session, QWidget *parent = 0);
void paintEvent(QPaintEvent *);
@@ -44,12 +44,17 @@ signals:
public slots:
void clear();
void repeat_unshow();
void set_trig_time(QDateTime time);
void set_rle_depth(uint64_t depth);
void set_capture_status(bool triggered, int progess);
private:
SigSession &_session;
QString _trig_time;
QString _rle_depth;
QString _capture_status;
};
} // namespace widgets

Some files were not shown because too many files have changed in this diff Show More