2
0
forked from Ivasoft/DSView

Merge branch 'develop' for v0.97

This commit is contained in:
DreamSourceLab
2017-05-25 21:03:24 +08:00
211 changed files with 8371 additions and 5688 deletions

1
.gitignore vendored
View File

@@ -36,6 +36,7 @@ DSView/ui_*.h
DSView/DSView
DSView/install_manifest.txt
DSView/qrc_DSView.cpp
DSView/qrc_style.cpp
moc_*.cpp
moc_*.cpp_parameters

View File

@@ -34,7 +34,7 @@ project(DSView)
option(DISABLE_WERROR "Build without -Werror" TRUE)
option(ENABLE_SIGNALS "Build with UNIX signals" TRUE)
option(ENABLE_DECODE "Build with libsigrokdecode" TRUE)
option(ENABLE_DECODE "Build with libsigrokdecode4DSL" TRUE)
option(ENABLE_COTIRE "Enable cotire" FALSE)
option(ENABLE_TESTS "Enable unit tests" FALSE)
option(STATIC_PKGDEPS_LIBS "Statically link to (pkg-config) libraries" FALSE)
@@ -62,9 +62,10 @@ 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")
list(APPEND PKGDEPS "libsigrokdecode4DSL>=0.4.0")
endif()
find_package(PkgConfig)
@@ -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}
)
@@ -146,7 +148,7 @@ set(DSView_SOURCES
pv/view/header.cpp
pv/view/cursor.cpp
pv/view/analogsignal.cpp
pv/prop/binding/binding_deviceoptions.cpp
pv/prop/binding/deviceoptions.cpp
pv/toolbars/trigbar.cpp
pv/toolbars/filebar.cpp
pv/dock/protocoldock.cpp
@@ -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,17 +260,17 @@ set(DSView_HEADERS
pv/dialogs/dsmessagebox.h
pv/dialogs/shadow.h
pv/dialogs/dsdialog.h
pv/dialogs/interval.h
)
set(DSView_FORMS
)
set(DSView_RESOURCES
DSView.qrc
darkstyle/style.qrc
DSView.qrc
darkstyle/style.qrc
)
if(ENABLE_DECODE)
list(APPEND DSView_SOURCES
pv/dock/protocoldock.cpp
@@ -396,9 +399,7 @@ set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "/usr/local/lib")
# Install the executable.
install(TARGETS ${PROJECT_NAME} DESTINATION bin/)
install(DIRECTORY res DESTINATION share/${PROJECT_NAME})
install(DIRECTORY ../libsigrokdecode4DSL/decoders DESTINATION share/${PROJECT_NAME})
install(FILES icons/logo.png DESTINATION share/${PROJECT_NAME} RENAME logo.png)
install(FILES DreamSourceLab.rules DESTINATION /usr/lib/udev/rules.d/)
install(FILES DreamSourceLab.rules DESTINATION /etc/udev/rules.d/)
install(FILES DSView.desktop DESTINATION /usr/share/applications/)

0
DSView/DSView.desktop Executable file → Normal file
View File

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/add_dis.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

BIN
DSView/icons/arrow-loop.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

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

BIN
DSView/icons/del_dis.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

11
DSView/icons/logo.svg Executable file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="256pt" height="256pt" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#fefefe" d=" M 0.00 0.00 L 56.60 0.00 C 40.80 1.65 25.70 9.35 15.34 21.41 C 6.87 30.97 1.57 43.16 0.00 55.81 L 0.00 0.00 Z" />
<path fill="#1185e5" d=" M 56.60 0.00 L 199.56 0.00 C 211.49 1.39 223.17 5.87 232.53 13.47 C 245.40 23.52 253.88 38.88 256.00 55.03 L 256.00 59.75 C 246.92 44.56 235.18 29.93 218.89 22.15 C 207.31 16.63 193.56 15.92 181.57 20.55 C 168.19 25.49 157.52 35.74 149.07 46.95 C 130.45 71.90 120.91 102.02 112.47 131.60 C 106.52 151.99 98.91 172.21 86.86 189.85 C 80.68 198.41 73.35 207.32 62.85 210.49 C 54.74 212.91 46.62 208.51 40.66 203.30 C 27.83 191.53 19.81 175.66 13.16 159.82 C 7.57 147.35 4.30 134.06 0.00 121.15 L 0.00 55.81 C 1.57 43.16 6.87 30.97 15.34 21.41 C 25.70 9.35 40.80 1.65 56.60 0.00 Z" />
<path fill="#fefefe" d=" M 199.56 0.00 L 256.00 0.00 L 256.00 55.03 C 253.88 38.88 245.40 23.52 232.53 13.47 C 223.17 5.87 211.49 1.39 199.56 0.00 Z" />
<path fill="#fefefe" d=" M 181.57 20.55 C 193.56 15.92 207.31 16.63 218.89 22.15 C 235.18 29.93 246.92 44.56 256.00 59.75 L 256.00 134.53 C 248.91 111.26 241.48 87.58 227.75 67.23 C 221.49 58.65 214.38 49.63 203.96 46.08 C 197.49 43.74 190.42 46.17 184.99 49.88 C 176.43 56.07 170.05 64.70 164.67 73.68 C 158.93 83.12 154.55 93.31 150.60 103.61 C 144.34 120.03 140.44 137.22 134.67 153.81 C 128.34 172.75 120.10 191.19 108.52 207.54 C 99.57 219.91 87.97 231.30 73.24 236.31 C 58.65 241.43 41.95 238.36 29.36 229.64 C 17.06 221.07 7.44 209.08 0.00 196.16 L 0.00 121.15 C 4.30 134.06 7.57 147.35 13.16 159.82 C 19.81 175.66 27.83 191.53 40.66 203.30 C 46.62 208.51 54.74 212.91 62.85 210.49 C 73.35 207.32 80.68 198.41 86.86 189.85 C 98.91 172.21 106.52 151.99 112.47 131.60 C 120.91 102.02 130.45 71.90 149.07 46.95 C 157.52 35.74 168.19 25.49 181.57 20.55 Z" />
<path fill="#1185e5" d=" M 184.99 49.88 C 190.42 46.17 197.49 43.74 203.96 46.08 C 214.38 49.63 221.49 58.65 227.75 67.23 C 241.48 87.58 248.91 111.26 256.00 134.53 L 256.00 201.15 C 254.22 215.68 247.14 229.46 236.45 239.45 C 226.90 248.39 214.54 254.29 201.56 256.00 L 54.62 256.00 C 39.95 254.08 26.10 246.79 16.13 235.88 C 7.21 225.95 1.41 213.25 0.00 199.96 L 0.00 196.16 C 7.44 209.08 17.06 221.07 29.36 229.64 C 41.95 238.36 58.65 241.43 73.24 236.31 C 87.97 231.30 99.57 219.91 108.52 207.54 C 120.10 191.19 128.34 172.75 134.67 153.81 C 140.44 137.22 144.34 120.03 150.60 103.61 C 154.55 93.31 158.93 83.12 164.67 73.68 C 170.05 64.70 176.43 56.07 184.99 49.88 Z" />
<path fill="#fefefe" d=" M 0.00 199.96 C 1.41 213.25 7.21 225.95 16.13 235.88 C 26.10 246.79 39.95 254.08 54.62 256.00 L 0.00 256.00 L 0.00 199.96 Z" />
<path fill="#fefefe" d=" M 236.45 239.45 C 247.14 229.46 254.22 215.68 256.00 201.15 L 256.00 256.00 L 201.56 256.00 C 214.54 254.29 226.90 248.39 236.45 239.45 Z" />
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
DSView/icons/logo_128.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
DSView/icons/logo_16.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

BIN
DSView/icons/logo_256.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
DSView/icons/logo_32.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
DSView/icons/logo_48.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
DSView/icons/logo_64.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
DSView/icons/moder.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
DSView/icons/moder_dis.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
DSView/icons/modes.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
DSView/icons/modes_dis.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
DSView/icons/nav.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

BIN
DSView/icons/oneloop.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
DSView/icons/repeat.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -22,7 +22,7 @@
#ifdef ENABLE_DECODE
#include <libsigrokdecode/libsigrokdecode.h> /* First, so we avoid a _POSIX_C_SOURCE warning. */
#include <libsigrokdecode4DSL/libsigrokdecode.h> /* First, so we avoid a _POSIX_C_SOURCE warning. */
#endif
#include <stdint.h>
@@ -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)
{
uint16_t 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

@@ -20,7 +20,7 @@
*/
extern "C" {
#include <libsigrokdecode/libsigrokdecode.h>
#include <libsigrokdecode4DSL/libsigrokdecode.h>
}
#include <vector>

View File

@@ -20,12 +20,10 @@
*/
#include <libsigrok4DSL/libsigrok.h>
#include <libsigrokdecode/libsigrokdecode.h>
#include <libsigrokdecode4DSL/libsigrokdecode.h>
#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

@@ -20,7 +20,7 @@
#include "row.h"
#include <libsigrokdecode/libsigrokdecode.h>
#include <libsigrokdecode4DSL/libsigrokdecode.h>
namespace pv {
namespace data {

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

@@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <libsigrokdecode/libsigrokdecode.h>
#include <libsigrokdecode4DSL/libsigrokdecode.h>
#include <boost/foreach.hpp>
#include <boost/thread/thread.hpp>

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;
@@ -460,27 +457,13 @@ uint64_t DecoderStack::get_max_sample_count() const
return max_sample_count;
}
boost::optional<uint64_t> DecoderStack::wait_for_data() const
{
//unique_lock<mutex> input_lock(_input_mutex);
while(!boost::this_thread::interruption_requested() &&
!_frame_complete && (uint64_t)_samples_decoded >= _sample_count)
//_input_cond.wait(input_lock);
return boost::make_optional(
!boost::this_thread::interruption_requested() &&
((uint64_t)_samples_decoded < _sample_count || !_frame_complete),
_sample_count);
}
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 +484,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 +549,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 +587,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 +622,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 +750,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

@@ -21,7 +21,7 @@
#ifndef DSVIEW_PV_DATA_DECODERSTACK_H
#define DSVIEW_PV_DATA_DECODERSTACK_H
#include <libsigrokdecode/libsigrokdecode.h>
#include <libsigrokdecode4DSL/libsigrokdecode.h>
#include <list>
@@ -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,11 @@ 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 +200,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

@@ -157,12 +157,13 @@ const std::vector<double> MathStack::get_fft_spectrum() const
return empty;
}
const double MathStack::get_fft_spectrum(uint64_t index) const
double MathStack::get_fft_spectrum(uint64_t index)
{
double ret = -1;
if (_math_state == Stopped && index < _power_spectrum.size())
return _power_spectrum[index];
else
return -1;
ret = _power_spectrum[index];
return ret;
}
void MathStack::calc_fft()
@@ -193,14 +194,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

@@ -86,7 +86,7 @@ public:
void set_sample_interval(int interval);
const std::vector<double> get_fft_spectrum() const;
const double get_fft_spectrum(uint64_t index) const;
double get_fft_spectrum(uint64_t index);
void calc_fft();

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);
}
@@ -82,7 +83,7 @@ GVariant* DevInst::get_config(const sr_channel *ch, const sr_channel_group *grou
return data;
}
bool DevInst::set_config(const sr_channel *ch, const sr_channel_group *group, int key, GVariant *data)
bool DevInst::set_config(sr_channel *ch, sr_channel_group *group, int key, GVariant *data)
{
assert(_owner);
sr_dev_inst *const sdi = dev_inst();
@@ -206,5 +207,10 @@ void DevInst::run()
sr_session_run();
}
bool DevInst::is_usable() const
{
return _usable;
}
} // device
} // pv

View File

@@ -63,7 +63,7 @@ public:
GVariant* get_config(const sr_channel *ch, const sr_channel_group *group, int key);
bool set_config(const sr_channel *ch, const sr_channel_group *group, int key, GVariant *data);
bool set_config(sr_channel *ch, sr_channel_group *group, int key, GVariant *data);
GVariant* list_config(const sr_channel_group *group, int key);
@@ -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,37 @@ 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;
archive = zip_open(_path.toLocal8Bit().data(), 0, &ret);
if (archive) {
/* read "decoders" */
if (zip_stat(archive, "decoders", 0, &zs) != -1) {
dec_file = (char *)g_try_malloc(zs.size);
if (dec_file) {
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

@@ -48,15 +48,21 @@ sr_dev_inst* InputFile::dev_inst() const
void InputFile::use(SigSession *owner) throw(QString)
{
(void)owner;
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 +84,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 +96,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

@@ -224,7 +224,7 @@ void FftOptions::accept()
mathTrace->get_math_stack()->set_sample_num(_len_combobox->currentData().toULongLong());
mathTrace->get_math_stack()->set_sample_interval(_interval_combobox->currentData().toInt());
mathTrace->get_math_stack()->set_windows_index(_window_combobox->currentData().toInt());
mathTrace->set_view_mode(_view_combobox->currentData().toInt());
mathTrace->set_view_mode(_view_combobox->currentData().toUInt());
//mathTrace->init_zoom();
mathTrace->set_dbv_range(_dbv_combobox->currentData().toInt());
mathTrace->set_enable(_en_checkbox->isChecked());

75
DSView/pv/dialogs/interval.cpp Executable file
View File

@@ -0,0 +1,75 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "interval.h"
#include <QGridLayout>
namespace pv {
namespace dialogs {
Interval::Interval(SigSession &session, QWidget *parent) :
DSDialog(parent),
_session(session),
_button_box(QDialogButtonBox::Ok,
Qt::Horizontal, this)
{
setMinimumWidth(300);
_interval_label = new QLabel(tr("Interval(s): "), this);
_interval_spinBox = new QSpinBox(this);
_interval_spinBox->setRange(1, 10);
_interval_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
_interval_slider = new QSlider(Qt::Horizontal, this);
_interval_slider->setRange(1, 10);
connect(_interval_slider, SIGNAL(valueChanged(int)), _interval_spinBox, SLOT(setValue(int)));
connect(_interval_spinBox, SIGNAL(valueChanged(int)), _interval_slider, SLOT(setValue(int)));
_interval_slider->setValue(_session.get_repeat_intvl());
QGridLayout *glayout = new QGridLayout(this);
glayout->addWidget(_interval_label, 0, 0);
glayout->addWidget(_interval_spinBox, 0, 1);
glayout->addWidget(_interval_slider, 1, 0, 1, 3);
glayout->addWidget(&_button_box, 2, 2);
layout()->addLayout(glayout);
setTitle(tr("Repetitive Interval"));
connect(&_button_box, SIGNAL(accepted()), this, SLOT(accept()));
}
void Interval::accept()
{
using namespace Qt;
_session.set_repeat_intvl(_interval_slider->value());
QDialog::accept();
}
void Interval::reject()
{
using namespace Qt;
QDialog::reject();
}
} // namespace dialogs
} // namespace pv

62
DSView/pv/dialogs/interval.h Executable file
View File

@@ -0,0 +1,62 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DSVIEW_PV_INTERVAL_H
#define DSVIEW_PV_INTERVAL_H
#include <QLabel>
#include <QSpinBox>
#include <QSlider>
#include <QDialogButtonBox>
#include "../sigsession.h"
#include "../toolbars/titlebar.h"
#include "dsdialog.h"
namespace pv {
namespace dialogs {
class Interval : public DSDialog
{
Q_OBJECT
public:
Interval(SigSession &session, QWidget *parent);
protected:
void accept();
void reject();
private:
SigSession &_session;
QLabel *_interval_label;
QSpinBox *_interval_spinBox;
QSlider *_interval_slider;
QDialogButtonBox _button_box;
};
} // namespace dialogs
} // namespace pv
#endif // DSVIEW_PV_INTERVAL_H

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,388 @@ 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 = NULL;
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 = NULL;
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++;
}
if (cursor)
_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 = 0;
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

@@ -23,7 +23,7 @@
#ifndef DSVIEW_PV_PROTOCOLDOCK_H
#define DSVIEW_PV_PROTOCOLDOCK_H
#include <libsigrokdecode/libsigrokdecode.h>
#include <libsigrokdecode4DSL/libsigrokdecode.h>
#include <QDockWidget>
#include <QPushButton>
@@ -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,23 @@ MainFrame::MainFrame(DeviceManager &device_manager,
_layout->addWidget(_bottom_right, 2, 2);
connect(&_timer, SIGNAL(timeout()), this, SLOT(unfreezing()));
readSettings();
//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 +347,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 +359,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

@@ -22,7 +22,7 @@
#ifdef ENABLE_DECODE
#include <libsigrokdecode/libsigrokdecode.h>
#include <libsigrokdecode4DSL/libsigrokdecode.h>
#include "dock/protocoldock.h"
#endif
@@ -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 received data is not consistent 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("Not enough memory 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,16 @@ 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
return true;
}
bool MainWindow::store_session(QString name)
@@ -787,8 +845,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 +902,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 +950,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,20 @@ 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();
}
return pvalue;
}
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

@@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <libsigrokdecode/libsigrokdecode.h>
#include <libsigrokdecode4DSL/libsigrokdecode.h>
#include "decoderoptions.h"

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

@@ -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:
@@ -141,7 +142,7 @@ GVariant* DeviceOptions::config_getter(
}
void DeviceOptions::config_setter(
const struct sr_dev_inst *sdi, int key, GVariant* value)
struct sr_dev_inst *sdi, int key, GVariant* value)
{
if (sr_config_set(sdi, NULL, NULL, key, value) != SR_OK)
qDebug() << "WARNING: Failed to set value of sample rate";

View File

@@ -47,7 +47,7 @@ private:
static GVariant* config_getter(
const struct sr_dev_inst *sdi, int key);
static void config_setter(
const struct sr_dev_inst *sdi, int key, GVariant* value);
struct sr_dev_inst *sdi, int key, GVariant* value);
void bind_bool(const QString &name, int key);
void bind_enum(const QString &name, int key,

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

@@ -21,7 +21,7 @@
*/
#ifdef ENABLE_DECODE
#include <libsigrokdecode/libsigrokdecode.h>
#include <libsigrokdecode4DSL/libsigrokdecode.h>
#endif
#include "sigsession.h"
@@ -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("Saving capture to file... this 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... this 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,13 @@ 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);
_trigger_flag = (trigger_pos.status & 0x01);
if (_trigger_flag) {
_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 +898,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 +916,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 +940,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 +991,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 +1018,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 +1056,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 +1077,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 +1241,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 +1277,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 +1442,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,793 @@ 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 = -1;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
ch_type = s->get_type();
break;
}
if (ch_type != -1) {
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 = %" PRIu64 "\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 = %" PRIu64 "\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 = %" PRIu64 "\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 = %" PRIu64 "\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 = %" PRIu64 "\n", probe->index, status.ch0_period);
fprintf(meta, " pcnt%d = %" PRIu32 "\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 = %" PRIu64 "\n", probe->index, status.ch1_period);
fprintf(meta, " pcnt%d = %" PRIu32 "\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 = 0;
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 <libsigrokdecode4DSL/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 = 0;
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 signal input. This 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

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