diff --git a/.gitignore b/.gitignore
index 2b0f916e..c889fc34 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/DSView/CMakeLists.txt b/DSView/CMakeLists.txt
index bc91cc8d..a52c36c8 100644
--- a/DSView/CMakeLists.txt
+++ b/DSView/CMakeLists.txt
@@ -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/)
diff --git a/DSView/DSView.desktop b/DSView/DSView.desktop
old mode 100755
new mode 100644
diff --git a/DSView/DSView.qrc b/DSView/DSView.qrc
index f58808ff..f560529f 100644
--- a/DSView/DSView.qrc
+++ b/DSView/DSView.qrc
@@ -10,8 +10,6 @@
stylesheet.qss
icons/down-arrow.png
icons/slider-handle.png
- icons/add.png
- icons/del.png
icons/trigger.png
icons/measure.png
icons/search-bar.png
@@ -55,5 +53,16 @@
icons/maximize.png
icons/minimize.png
icons/restore.png
+ icons/nav.png
+ icons/oneloop.png
+ icons/repeat.png
+ icons/moder.png
+ icons/moder_dis.png
+ icons/modes.png
+ icons/modes_dis.png
+ icons/add.png
+ icons/del.png
+ icons/add_dis.png
+ icons/del_dis.png
diff --git a/DSView/darkstyle/style.qss b/DSView/darkstyle/style.qss
index 21455512..f23c1ea1 100755
--- a/DSView/darkstyle/style.qss
+++ b/DSView/darkstyle/style.qss
@@ -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;
diff --git a/DSView/dsapplication.cpp b/DSView/dsapplication.cpp
index 9facc855..98cb6897 100644
--- a/DSView/dsapplication.cpp
+++ b/DSView/dsapplication.cpp
@@ -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();
diff --git a/DSView/icons/add.png b/DSView/icons/add.png
old mode 100644
new mode 100755
index efe2e387..24c81886
Binary files a/DSView/icons/add.png and b/DSView/icons/add.png differ
diff --git a/DSView/icons/add_dis.png b/DSView/icons/add_dis.png
new file mode 100755
index 00000000..b0349001
Binary files /dev/null and b/DSView/icons/add_dis.png differ
diff --git a/DSView/icons/arrow-loop.png b/DSView/icons/arrow-loop.png
new file mode 100755
index 00000000..d3df3243
Binary files /dev/null and b/DSView/icons/arrow-loop.png differ
diff --git a/DSView/icons/del.png b/DSView/icons/del.png
old mode 100644
new mode 100755
index ff04e887..527534b4
Binary files a/DSView/icons/del.png and b/DSView/icons/del.png differ
diff --git a/DSView/icons/del_dis.png b/DSView/icons/del_dis.png
new file mode 100755
index 00000000..d4f418c3
Binary files /dev/null and b/DSView/icons/del_dis.png differ
diff --git a/DSView/icons/logo.svg b/DSView/icons/logo.svg
new file mode 100755
index 00000000..b713c304
--- /dev/null
+++ b/DSView/icons/logo.svg
@@ -0,0 +1,11 @@
+
+
+
diff --git a/DSView/icons/logo_128.png b/DSView/icons/logo_128.png
new file mode 100755
index 00000000..0d46a075
Binary files /dev/null and b/DSView/icons/logo_128.png differ
diff --git a/DSView/icons/logo_16.png b/DSView/icons/logo_16.png
new file mode 100755
index 00000000..67042eb3
Binary files /dev/null and b/DSView/icons/logo_16.png differ
diff --git a/DSView/icons/logo_256.png b/DSView/icons/logo_256.png
new file mode 100755
index 00000000..ca65932d
Binary files /dev/null and b/DSView/icons/logo_256.png differ
diff --git a/DSView/icons/logo_32.png b/DSView/icons/logo_32.png
new file mode 100755
index 00000000..ed7b1a4e
Binary files /dev/null and b/DSView/icons/logo_32.png differ
diff --git a/DSView/icons/logo_48.png b/DSView/icons/logo_48.png
new file mode 100755
index 00000000..eb8b4162
Binary files /dev/null and b/DSView/icons/logo_48.png differ
diff --git a/DSView/icons/logo_64.png b/DSView/icons/logo_64.png
new file mode 100755
index 00000000..8691e890
Binary files /dev/null and b/DSView/icons/logo_64.png differ
diff --git a/DSView/icons/moder.png b/DSView/icons/moder.png
new file mode 100755
index 00000000..d94f826a
Binary files /dev/null and b/DSView/icons/moder.png differ
diff --git a/DSView/icons/moder_dis.png b/DSView/icons/moder_dis.png
new file mode 100755
index 00000000..8bc44721
Binary files /dev/null and b/DSView/icons/moder_dis.png differ
diff --git a/DSView/icons/modes.png b/DSView/icons/modes.png
new file mode 100755
index 00000000..c8e465ce
Binary files /dev/null and b/DSView/icons/modes.png differ
diff --git a/DSView/icons/modes_dis.png b/DSView/icons/modes_dis.png
new file mode 100755
index 00000000..375a2a50
Binary files /dev/null and b/DSView/icons/modes_dis.png differ
diff --git a/DSView/icons/nav.png b/DSView/icons/nav.png
new file mode 100755
index 00000000..03f1f605
Binary files /dev/null and b/DSView/icons/nav.png differ
diff --git a/DSView/icons/oneloop.png b/DSView/icons/oneloop.png
new file mode 100755
index 00000000..9a03ebb3
Binary files /dev/null and b/DSView/icons/oneloop.png differ
diff --git a/DSView/icons/repeat.png b/DSView/icons/repeat.png
new file mode 100755
index 00000000..d68d4edb
Binary files /dev/null and b/DSView/icons/repeat.png differ
diff --git a/DSView/main.cpp b/DSView/main.cpp
index d63b2e7f..ba9f38d0 100644
--- a/DSView/main.cpp
+++ b/DSView/main.cpp
@@ -22,7 +22,7 @@
#ifdef ENABLE_DECODE
-#include /* First, so we avoid a _POSIX_C_SOURCE warning. */
+#include /* First, so we avoid a _POSIX_C_SOURCE warning. */
#endif
#include
@@ -34,7 +34,7 @@
#include
#include
#include
-#include
+#include
#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();
diff --git a/DSView/pv/data/analogsnapshot.cpp b/DSView/pv/data/analogsnapshot.cpp
index 005885c7..cfc22080 100644
--- a/DSView/pv/data/analogsnapshot.cpp
+++ b/DSView/pv/data/analogsnapshot.cpp
@@ -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
diff --git a/DSView/pv/data/analogsnapshot.h b/DSView/pv/data/analogsnapshot.h
index 3f2b015a..8767f6c3 100644
--- a/DSView/pv/data/analogsnapshot.h
+++ b/DSView/pv/data/analogsnapshot.h
@@ -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];
diff --git a/DSView/pv/data/decode/annotation.cpp b/DSView/pv/data/decode/annotation.cpp
index f2d30df5..3581817d 100644
--- a/DSView/pv/data/decode/annotation.cpp
+++ b/DSView/pv/data/decode/annotation.cpp
@@ -20,7 +20,7 @@
*/
extern "C" {
-#include
+#include
}
#include
diff --git a/DSView/pv/data/decode/decoder.cpp b/DSView/pv/data/decode/decoder.cpp
index 8d54d7f6..1c8d2a9d 100644
--- a/DSView/pv/data/decode/decoder.cpp
+++ b/DSView/pv/data/decode/decoder.cpp
@@ -20,12 +20,10 @@
*/
#include
-#include
+#include
#include "decoder.h"
-#include
-
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::const_iterator i = _options.begin();
- i != _options.end(); i++)
- g_variant_unref((*i).second);
-
for (map::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 map&
Decoder::channels() const
{
return _probes;
}
-void Decoder::set_probes(std::map > probes)
+void Decoder::set_probes(std::map probes)
{
_probes_back = probes;
_setted = true;
@@ -89,6 +82,7 @@ const std::map& 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 > Decoder::get_data()
+srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session) const
{
- set< shared_ptr > data;
- for(map >::
- const_iterator i = _probes.begin();
- i != _probes.end(); i++)
- {
- shared_ptr 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 >::
+ for(map::
const_iterator i = _probes.begin();
i != _probes.end(); i++)
{
- shared_ptr 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
diff --git a/DSView/pv/data/decode/decoder.h b/DSView/pv/data/decode/decoder.h
index 40fde4e6..4f9d40ad 100644
--- a/DSView/pv/data/decode/decoder.h
+++ b/DSView/pv/data/decode/decoder.h
@@ -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 >& channels() const;
- void set_probes(std::map > probes);
+ const std::map& channels() const;
+ void set_probes(std::map probes);
const std::map& 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 > 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 >
- _probes;
+ std::map _probes;
std::map _options;
- std::map >
- _probes_back;
+ std::map _probes_back;
std::map _options_back;
uint64_t _decode_start, _decode_end;
diff --git a/DSView/pv/data/decode/row.cpp b/DSView/pv/data/decode/row.cpp
index 46fb337f..fd798eb7 100644
--- a/DSView/pv/data/decode/row.cpp
+++ b/DSView/pv/data/decode/row.cpp
@@ -20,7 +20,7 @@
#include "row.h"
-#include
+#include
namespace pv {
namespace data {
diff --git a/DSView/pv/data/decode/rowdata.cpp b/DSView/pv/data/decode/rowdata.cpp
index 8d3e41e0..c80cbfbd 100644
--- a/DSView/pv/data/decode/rowdata.cpp
+++ b/DSView/pv/data/decode/rowdata.cpp
@@ -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::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 {
diff --git a/DSView/pv/data/decode/rowdata.h b/DSView/pv/data/decode/rowdata.h
index 40792cb7..72d33456 100644
--- a/DSView/pv/data/decode/rowdata.h
+++ b/DSView/pv/data/decode/rowdata.h
@@ -47,6 +47,8 @@ public:
std::vector &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;
diff --git a/DSView/pv/data/decodermodel.cpp b/DSView/pv/data/decodermodel.cpp
index 078111a4..614f67ff 100644
--- a/DSView/pv/data/decodermodel.cpp
+++ b/DSView/pv/data/decodermodel.cpp
@@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include
+#include
#include
#include
diff --git a/DSView/pv/data/decoderstack.cpp b/DSView/pv/data/decoderstack.cpp
index 233dcc4d..2ad6a532 100644
--- a/DSView/pv/data/decoderstack.cpp
+++ b/DSView/pv/data/decoderstack.cpp
@@ -35,19 +35,8 @@
#include
#include
-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(
+ _stack.push_back(boost::shared_ptr(
new decode::Decoder(dec)));
build_row();
@@ -116,7 +106,7 @@ void DecoderStack::push(boost::shared_ptr decoder)
void DecoderStack::remove(boost::shared_ptr &decoder)
{
// Find the decoder in the stack
- list< shared_ptr >::iterator iter = _stack.begin();
+ list< boost::shared_ptr >::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 &dec, _stack)
+ BOOST_FOREACH (const boost::shared_ptr &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 lock(_output_mutex);
+
+ uint64_t index = 0;
+ std::map::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 lock(_output_mutex);
@@ -353,84 +358,77 @@ QString DecoderStack::error_message()
void DecoderStack::clear()
{
- //lock_guard decode_lock(_output_mutex);
- _sample_count = 0;
- _frame_complete = false;
- _samples_decoded = 0;
- new_decode_data();
- _error_message = QString();
- for (map::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::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 logic_signal;
- shared_ptr data;
+ boost::shared_ptr logic_signal;
+ boost::shared_ptr 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 &dec, _stack)
+ BOOST_FOREACH(const boost::shared_ptr &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 &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 &dec, _stack) {
+ if (dec && !dec->channels().empty()) {
+ BOOST_FOREACH(boost::shared_ptr sig, _session.get_signals()) {
+ if((sig->get_index() == (*dec->channels().begin()).second) &&
+ (logic_signal = dynamic_pointer_cast(sig)) &&
+ (data = logic_signal->logic_data()))
+ break;
+ }
+ if (data)
+ break;
+ }
+ }
if (!data)
return;
// Check we have a snapshot of data
- const deque< shared_ptr > &snapshots =
+ const deque< boost::shared_ptr > &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 DecoderStack::wait_for_data() const
-{
- //unique_lock 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 decode_lock(_global_decode_mutex);
+ std::vector chunk;
+ std::vector 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 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 input_lock(_input_mutex);
sample_count = _sample_count = _snapshot->get_sample_count();
}
- BOOST_FOREACH(const shared_ptr &dec, _stack)
+ // Create the decoders
+ BOOST_FOREACH(const boost::shared_ptr &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
diff --git a/DSView/pv/data/decoderstack.h b/DSView/pv/data/decoderstack.h
index 281a5428..c7baf7cc 100644
--- a/DSView/pv/data/decoderstack.h
+++ b/DSView/pv/data/decoderstack.h
@@ -21,7 +21,7 @@
#ifndef DSVIEW_PV_DATA_DECODERSTACK_H
#define DSVIEW_PV_DATA_DECODERSTACK_H
-#include
+#include
#include
@@ -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 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;
};
diff --git a/DSView/pv/data/dsosnapshot.cpp b/DSView/pv/data/dsosnapshot.cpp
index 665c0dbe..b3e06955 100644
--- a/DSView/pv/data/dsosnapshot.cpp
+++ b/DSView/pv/data/dsosnapshot.cpp
@@ -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 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 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 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
diff --git a/DSView/pv/data/dsosnapshot.h b/DSView/pv/data/dsosnapshot.h
index df6376e0..e34ca502 100644
--- a/DSView/pv/data/dsosnapshot.h
+++ b/DSView/pv/data/dsosnapshot.h
@@ -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 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 _ch_enable;
friend class DsoSnapshotTest::Basic;
};
diff --git a/DSView/pv/data/logicsnapshot.cpp b/DSView/pv/data/logicsnapshot.cpp
index 40ee3087..199f47bc 100644
--- a/DSView/pv/data/logicsnapshot.cpp
+++ b/DSView/pv/data/logicsnapshot.cpp
@@ -40,30 +40,43 @@ using namespace std;
namespace pv {
namespace data {
-const int LogicSnapshot::MipMapScalePower = 4;
-const int LogicSnapshot::MipMapScaleFactor = 1 << MipMapScalePower;
-const float LogicSnapshot::LogMipMapScaleFactor = logf(MipMapScaleFactor);
-const uint64_t LogicSnapshot::MipMapDataUnit = 64*1024; // bytes
+const uint64_t LogicSnapshot::LevelMask[LogicSnapshot::ScaleLevel] = {
+ ~(~0ULL << ScalePower) << 0 * ScalePower,
+ ~(~0ULL << ScalePower) << 1 * ScalePower,
+ ~(~0ULL << ScalePower) << 2 * ScalePower,
+ ~(~0ULL << ScalePower) << 3 * ScalePower,
+};
+const uint64_t LogicSnapshot::LevelOffset[LogicSnapshot::ScaleLevel] = {
+ 0,
+ (uint64_t)pow(Scale, 3),
+ (uint64_t)pow(Scale, 3) + (uint64_t)pow(Scale, 2),
+ (uint64_t)pow(Scale, 3) + (uint64_t)pow(Scale, 2) + (uint64_t)pow(Scale, 1),
+};
LogicSnapshot::LogicSnapshot() :
- Snapshot(1, 1, 1),
- _last_append_sample(0)
+ Snapshot(1, 0, 0),
+ _block_num(0)
{
- memset(_mip_map, 0, sizeof(_mip_map));
}
LogicSnapshot::~LogicSnapshot()
{
- free_mipmap();
}
-void LogicSnapshot::free_mipmap()
+void LogicSnapshot::free_data()
{
- BOOST_FOREACH(MipMapLevel &l, _mip_map) {
- if (l.data)
- free(l.data);
+ Snapshot::free_data();
+ for(auto& iter:_ch_data) {
+ for(auto& iter_rn:iter) {
+ for (unsigned int k = 0; k < Scale; k++)
+ if (iter_rn.lbp[k] != NULL)
+ free(iter_rn.lbp[k]);
+ }
+ std::vector void_vector;
+ iter.swap(void_vector);
}
- memset(_mip_map, 0, sizeof(_mip_map));
+ _ch_data.clear();
+ _sample_count = 0;
}
void LogicSnapshot::init()
@@ -71,308 +84,602 @@ void LogicSnapshot::init()
boost::lock_guard lock(_mutex);
_sample_count = 0;
_ring_sample_count = 0;
+ _block_num = 0;
+ _byte_fraction = 0;
+ _ch_fraction = 0;
+ _src_ptr = NULL;
+ _dest_ptr = NULL;
+ _data = NULL;
_memory_failed = false;
_last_ended = true;
- for (unsigned int level = 0; level < ScaleStepCount; level++) {
- _mip_map[level].length = 0;
- _mip_map[level].data_length = 0;
- }
}
void LogicSnapshot::clear()
{
boost::lock_guard lock(_mutex);
free_data();
- free_mipmap();
init();
}
-void LogicSnapshot::first_payload(const sr_datafeed_logic &logic, uint64_t total_sample_count, unsigned int channel_num)
+void LogicSnapshot::capture_ended()
{
- _total_sample_count = total_sample_count;
- _channel_num = channel_num;
- _unit_size = logic.unitsize;
+ Snapshot::capture_ended();
- bool isOk = true;
- uint64_t size = _total_sample_count * _unit_size + sizeof(uint64_t);
- if (size != _capacity) {
- free_data();
- _data = malloc(size);
- if (_data) {
- free_mipmap();
- uint64_t mipmap_count = _total_sample_count / MipMapScaleFactor;
- for (unsigned int level = 0; level < ScaleStepCount; level++) {
- mipmap_count = ((mipmap_count + MipMapDataUnit - 1) /
- MipMapDataUnit) * MipMapDataUnit;
- _mip_map[level].data = malloc(mipmap_count * _unit_size + sizeof(uint64_t));
- if (!_mip_map[level].data) {
- isOk = false;
- break;
- }
- mipmap_count = mipmap_count / MipMapScaleFactor;
+ //assert(_ch_fraction == 0);
+ //assert(_byte_fraction == 0);
+ uint64_t block_index = _ring_sample_count / LeafBlockSamples;
+ uint64_t block_offset = (_ring_sample_count % LeafBlockSamples) / Scale;
+ if (block_offset != 0) {
+ uint64_t index0 = block_index / RootScale;
+ uint64_t index1 = block_index % RootScale;
+ int order = 0;
+ for(auto& iter:_ch_data) {
+ const uint64_t *end_ptr = (uint64_t *)iter[index0].lbp[index1] + (LeafBlockSamples / Scale);
+ uint64_t *ptr = (uint64_t *)iter[index0].lbp[index1] + block_offset;
+ while (ptr < end_ptr)
+ *ptr++ = 0;
+
+ // calc mipmap of current block
+ calc_mipmap(order, index0, index1, block_offset * Scale);
+
+ // calc root of current block
+ if (*((uint64_t *)iter[index0].lbp[index1]) != 0)
+ iter[index0].value += 1ULL << index1;
+ if (*((uint64_t *)iter[index0].lbp[index1] + LeafBlockSpace / sizeof(uint64_t) - 1) != 0) {
+ iter[index0].tog += 1ULL << index1;
+ } else {
+ // trim leaf to free space
+ free(iter[index0].lbp[index1]);
+ iter[index0].lbp[index1] = NULL;
+ }
+
+ order++;
+ }
+ }
+ _sample_count = _ring_sample_count;
+}
+
+void LogicSnapshot::first_payload(const sr_datafeed_logic &logic, uint64_t total_sample_count, GSList *channels)
+{
+ bool channel_changed = false;
+ uint16_t 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_LOGIC) {
+ channel_num += probe->enabled;
+ if (!channel_changed && probe->enabled) {
+ channel_changed = !has_data(probe->index);
}
- } else {
- isOk = false;
}
}
- if (isOk) {
- _capacity = size;
- _memory_failed = false;
- append_payload(logic);
- _last_ended = false;
- } else {
+ if (total_sample_count != _total_sample_count ||
+ channel_num != _channel_num ||
+ channel_changed) {
free_data();
- free_mipmap();
- _capacity = 0;
- _memory_failed = true;
+ _total_sample_count = total_sample_count;
+ _channel_num = channel_num;
+ uint64_t rootnode_size = (_total_sample_count + RootNodeSamples - 1) / RootNodeSamples;
+ for (const GSList *l = channels; l; l = l->next) {
+ sr_channel *const probe = (sr_channel*)l->data;
+ if (probe->type == SR_CHANNEL_LOGIC && probe->enabled) {
+ std::vector root_vector;
+ for (uint64_t j = 0; j < rootnode_size; j++) {
+ struct RootNode rn;
+ rn.tog = 0;
+ rn.value = 0;
+ memset(rn.lbp, 0, sizeof(rn.lbp));
+ root_vector.push_back(rn);
+ }
+ _ch_data.push_back(root_vector);
+ _ch_index.push_back(probe->index);
+ }
+ }
+ } else {
+ for(auto& iter:_ch_data) {
+ for(auto& iter_rn:iter) {
+ iter_rn.tog = 0;
+ iter_rn.value = 0;
+ }
+ }
}
+
+ _sample_count = 0;
+ _last_sample.clear();
+ _sample_cnt.clear();
+ _block_cnt.clear();
+ _ring_sample_cnt.clear();
+ for (unsigned int i = 0; i < _channel_num; i++) {
+ _last_sample.push_back(0);
+ _sample_cnt.push_back(0);
+ _block_cnt.push_back(0);
+ _ring_sample_cnt.push_back(0);
+ }
+
+ append_payload(logic);
+ _last_ended = false;
}
void LogicSnapshot::append_payload(
const sr_datafeed_logic &logic)
{
- assert(_unit_size == logic.unitsize);
- assert((logic.length % _unit_size) == 0);
-
boost::lock_guard lock(_mutex);
- append_data(logic.data, logic.length / _unit_size);
-
- // Generate the first mip-map from the data
- append_payload_to_mipmap();
+ if (logic.format == LA_CROSS_DATA)
+ append_cross_payload(logic);
+ else if (logic.format == LA_SPLIT_DATA)
+ append_split_payload(logic);
}
-uint8_t * LogicSnapshot::get_samples(int64_t start_sample, int64_t end_sample) const
+void LogicSnapshot::append_cross_payload(
+ const sr_datafeed_logic &logic)
+{
+ assert(logic.format == LA_CROSS_DATA);
+ assert(logic.length >= ScaleSize * _channel_num);
+
+ if (_sample_count >= _total_sample_count)
+ return;
+
+ uint64_t samples = ceil(logic.length * 8.0 / _channel_num);
+
+ if (_sample_count + samples < _total_sample_count)
+ _sample_count += samples;
+ else
+ _sample_count = _total_sample_count;
+
+ while (_sample_count > _block_num * LeafBlockSamples) {
+ uint8_t index0 = _block_num / RootScale;
+ uint8_t index1 = _block_num % RootScale;
+ for(auto& iter:_ch_data) {
+ if (iter[index0].lbp[index1] == NULL)
+ iter[index0].lbp[index1] = malloc(LeafBlockSpace);
+ if (iter[index0].lbp[index1] == NULL) {
+ _memory_failed = true;
+ return;
+ }
+ uint64_t *mipmap_ptr = (uint64_t *)iter[index0].lbp[index1] +
+ (LeafBlockSamples / Scale);
+ memset(mipmap_ptr, 0, LeafBlockSpace - (LeafBlockSamples / 8));
+ }
+ _block_num++;
+ }
+
+ _src_ptr = logic.data;
+ uint64_t len = logic.length;
+
+ // bit align
+ while (((_ch_fraction != 0) || (_byte_fraction != 0)) && (len != 0)) {
+ uint8_t *dp_tmp = (uint8_t *)_dest_ptr;
+ uint8_t *sp_tmp = (uint8_t *)_src_ptr;
+ do {
+ //*(uint8_t *)_dest_ptr++ = *(uint8_t *)_src_ptr++;
+ *dp_tmp++ = *sp_tmp++;
+ _byte_fraction = (_byte_fraction + 1) % ScaleSize;
+ len--;
+ } while ((_byte_fraction != 0) && (len != 0));
+ _dest_ptr = dp_tmp;
+ _src_ptr = sp_tmp;
+ if (_byte_fraction == 0) {
+ const uint64_t index0 = _ring_sample_count / RootNodeSamples;
+ const uint64_t index1 = (_ring_sample_count >> LeafBlockPower) % RootScale;
+ const uint64_t offset = (_ring_sample_count % LeafBlockSamples) / Scale;
+
+// _dest_ptr = (uint64_t *)_ch_data[i][index0].lbp[index1] + offset;
+// uint64_t mipmap_index = offset / 8 / Scale;
+// uint64_t mipmap_offset = (offset / 8) % Scale;
+// uint64_t *l1_mipmap = (uint64_t *)_ch_data[i][index0].lbp[index1] +
+// (LeafBlockSamples / Scale) + mipmap_index;
+// *l1_mipmap += ((_last_sample[i] ^ *(uint64_t *)_dest_ptr) != 0 ? 1ULL : 0ULL) << mipmap_offset;
+// _last_sample[i] = *(uint64_t *)_dest_ptr & (1ULL << (Scale - 1)) ? ~0ULL : 0ULL;
+
+ _ch_fraction = (_ch_fraction + 1) % _channel_num;
+ if (_ch_fraction == 0)
+ _ring_sample_count += Scale;
+ _dest_ptr = (uint8_t *)_ch_data[_ch_fraction][index0].lbp[index1] + (offset * ScaleSize);
+ }
+ }
+
+ // align data append
+ {
+ assert(_ch_fraction == 0);
+ assert(_byte_fraction == 0);
+ assert(_ring_sample_count % Scale == 0);
+ uint64_t pre_index0 = _ring_sample_count / RootNodeSamples;
+ uint64_t pre_index1 = (_ring_sample_count >> LeafBlockPower) % RootScale;
+ uint64_t pre_offset = (_ring_sample_count % LeafBlockSamples) / Scale;
+ uint64_t *src_ptr = NULL;
+ uint64_t *dest_ptr;
+ int order = 0;
+ const uint64_t align_size = len / ScaleSize / _channel_num;
+ _ring_sample_count += align_size * Scale;
+
+// uint64_t mipmap_index = pre_offset / Scale;
+// uint64_t mipmap_offset = pre_offset % Scale;
+// uint64_t *l1_mipmap;
+ for(auto& iter:_ch_data) {
+ uint64_t index0 = pre_index0;
+ uint64_t index1 = pre_index1;
+ src_ptr = (uint64_t *)_src_ptr + order;
+ _dest_ptr = iter[index0].lbp[index1];
+ dest_ptr = (uint64_t *)_dest_ptr + pre_offset;
+// l1_mipmap = (uint64_t *)_dest_ptr + (LeafBlockSamples / Scale) + mipmap_index;
+ while (src_ptr < (uint64_t *)_src_ptr + (align_size * _channel_num)) {
+ const uint64_t tmp_u64 = *src_ptr;
+ *dest_ptr++ = tmp_u64;
+// *l1_mipmap += ((_last_sample[i] ^ tmp_u64) != 0 ? 1ULL : 0ULL) << mipmap_offset;
+// mipmap_offset = (mipmap_offset + 1) % Scale;
+// l1_mipmap += (mipmap_offset == 0);
+// _last_sample[i] = tmp_u64 & (1ULL << (Scale - 1)) ? ~0ULL : 0ULL;
+ src_ptr += _channel_num;
+ //mipmap
+ if (dest_ptr == (uint64_t *)_dest_ptr + (LeafBlockSamples / Scale)) {
+ // calc mipmap of current block
+ calc_mipmap(order, index0, index1, LeafBlockSamples);
+
+ // calc root of current block
+ if (*((uint64_t *)iter[index0].lbp[index1]) != 0)
+ iter[index0].value += 1ULL<< index1;
+ if (*((uint64_t *)iter[index0].lbp[index1] + LeafBlockSpace / sizeof(uint64_t) - 1) != 0) {
+ iter[index0].tog += 1ULL << index1;
+ } else {
+ // trim leaf to free space
+ free(iter[index0].lbp[index1]);
+ iter[index0].lbp[index1] = NULL;
+ }
+
+ index1++;
+ if (index1 == RootScale) {
+ index0++;
+ index1 = 0;
+ }
+ _dest_ptr = iter[index0].lbp[index1];
+ dest_ptr = (uint64_t *)_dest_ptr;
+ }
+ }
+ order++;
+ }
+ len -= align_size * _channel_num * ScaleSize;
+ _src_ptr = src_ptr - _channel_num + 1;
+ }
+
+ // fraction data append
+ {
+ uint64_t index0 = _ring_sample_count / RootNodeSamples;
+ uint64_t index1 = (_ring_sample_count >> LeafBlockPower) % RootScale;
+ uint64_t offset = (_ring_sample_count % LeafBlockSamples) / 8;
+ _dest_ptr = (uint8_t *)_ch_data[_ch_fraction][index0].lbp[index1] + offset;
+
+ uint8_t *dp_tmp = (uint8_t *)_dest_ptr;
+ uint8_t *sp_tmp = (uint8_t *)_src_ptr;
+ while(len-- != 0) {
+ //*(uint8_t *)_dest_ptr++ = *(uint8_t *)_src_ptr++;
+ *dp_tmp++ = *sp_tmp++;
+ if (++_byte_fraction == ScaleSize) {
+ _ch_fraction = (_ch_fraction + 1) % _channel_num;
+ _byte_fraction = 0;
+ //_dest_ptr = (uint8_t *)_ch_data[_ch_fraction][index0].lbp[index1] + offset;
+ dp_tmp = (uint8_t *)_ch_data[_ch_fraction][index0].lbp[index1] + offset;
+ }
+ }
+ //_dest_ptr = (uint8_t *)_dest_ptr + _byte_fraction;
+ _dest_ptr = dp_tmp + _byte_fraction;
+ }
+}
+
+void LogicSnapshot::append_split_payload(
+ const sr_datafeed_logic &logic)
+{
+ assert(logic.format == LA_SPLIT_DATA);
+
+ uint64_t samples = logic.length * 8;
+ uint16_t order = logic.order;
+ assert(order < _ch_data.size());
+
+ if (_sample_cnt[order] >= _total_sample_count)
+ return;
+
+ if (_sample_cnt[order] + samples < _total_sample_count)
+ _sample_cnt[order] += samples;
+ else
+ _sample_cnt[order] = _total_sample_count;
+
+ while (_sample_cnt[order] > _block_cnt[order] * LeafBlockSamples) {
+ uint8_t index0 = _block_cnt[order] / RootScale;
+ uint8_t index1 = _block_cnt[order] % RootScale;
+ if (_ch_data[order][index0].lbp[index1] == NULL)
+ _ch_data[order][index0].lbp[index1] = malloc(LeafBlockSpace);
+ if (_ch_data[order][index0].lbp[index1] == NULL) {
+ _memory_failed = true;
+ return;
+ }
+ memset(_ch_data[order][index0].lbp[index1], 0, LeafBlockSpace);
+ _block_cnt[order]++;
+ }
+
+ while(samples > 0) {
+ const uint64_t index0 = _ring_sample_cnt[order] / RootNodeSamples;
+ const uint64_t index1 = (_ring_sample_cnt[order] >> LeafBlockPower) % RootScale;
+ const uint64_t offset = (_ring_sample_cnt[order] % LeafBlockSamples) / 8;
+ _dest_ptr = (uint8_t *)_ch_data[order][index0].lbp[index1] + offset;
+
+ uint64_t bblank = (LeafBlockSamples - (_ring_sample_cnt[order] & LeafMask));
+ if (samples >= bblank) {
+ memcpy((uint8_t*)_dest_ptr, (uint8_t *)logic.data, bblank/8);
+ _ring_sample_cnt[order] += bblank;
+ samples -= bblank;
+
+ // calc mipmap of current block
+ calc_mipmap(order, index0, index1, LeafBlockSamples);
+
+ // calc root of current block
+ if (*((uint64_t *)_ch_data[order][index0].lbp[index1]) != 0)
+ _ch_data[order][index0].value += 1ULL<< index1;
+ if (*((uint64_t *)_ch_data[order][index0].lbp[index1] + LeafBlockSpace / sizeof(uint64_t) - 1) != 0) {
+ _ch_data[order][index0].tog += 1ULL << index1;
+ } else {
+ // trim leaf to free space
+ free(_ch_data[order][index0].lbp[index1]);
+ _ch_data[order][index0].lbp[index1] = NULL;
+ }
+ } else {
+ memcpy((uint8_t*)_dest_ptr, (uint8_t *)logic.data, samples/8);
+ _ring_sample_cnt[order] += samples;
+ samples = 0;
+ }
+ }
+
+ _sample_count = *min_element(_sample_cnt.begin(), _sample_cnt.end());
+ _ring_sample_count = *min_element(_ring_sample_cnt.begin(), _ring_sample_cnt.end());
+}
+
+void LogicSnapshot::calc_mipmap(unsigned int order, uint8_t index0, uint8_t index1, uint64_t samples)
+{
+ uint8_t offset;
+ uint64_t *src_ptr;
+ uint64_t *dest_ptr;
+ unsigned int i;
+
+ // level 1
+ src_ptr = (uint64_t *)_ch_data[order][index0].lbp[index1];
+ dest_ptr = src_ptr + (LeafBlockSamples / Scale) - 1;
+ const uint64_t mask = 1ULL << (Scale - 1);
+ for(i = 0; i < samples / Scale; i++) {
+ offset = i % Scale;
+ if (offset == 0)
+ dest_ptr++;
+ *dest_ptr += ((_last_sample[order] ^ *src_ptr) != 0 ? 1ULL : 0ULL) << offset;
+ _last_sample[order] = *src_ptr & mask ? ~0ULL : 0ULL;
+ src_ptr++;
+ }
+
+ // level 2/3
+ src_ptr = (uint64_t *)_ch_data[order][index0].lbp[index1] + (LeafBlockSamples / Scale);
+ dest_ptr = src_ptr + (LeafBlockSamples / Scale / Scale) - 1;
+ for(i = LeafBlockSamples / Scale; i < LeafBlockSpace / sizeof(uint64_t) - 1; i++) {
+ offset = i % Scale;
+ if (offset == 0)
+ dest_ptr++;
+ *dest_ptr += (*src_ptr != 0 ? 1ULL : 0ULL) << offset;
+ src_ptr++;
+ }
+}
+
+const uint8_t *LogicSnapshot::get_samples(uint64_t start_sample, uint64_t &end_sample,
+ int sig_index)
{
//assert(data);
- assert(start_sample >= 0);
- assert(start_sample <= (int64_t)get_sample_count());
- assert(end_sample >= 0);
- assert(end_sample <= (int64_t)get_sample_count());
+ assert(start_sample < get_sample_count());
+ assert(end_sample < get_sample_count());
assert(start_sample <= end_sample);
- (void)end_sample;
+ int order = get_ch_order(sig_index);
+ uint64_t root_index = start_sample >> (LeafBlockPower + RootScalePower);
+ uint8_t root_pos = (start_sample & RootMask) >> LeafBlockPower;
+ uint64_t block_offset = (start_sample & LeafMask) / 8;
+ end_sample = (root_index << (LeafBlockPower + RootScalePower)) +
+ (root_pos << LeafBlockPower) +
+ ~(~0ULL << LeafBlockPower);
+ end_sample = min(end_sample, get_sample_count() - 1);
- //const size_t size = (end_sample - start_sample) * _unit_size;
- //memcpy(data, (const uint8_t*)_data + start_sample * _unit_size, size);
- return (uint8_t*)_data + start_sample * _unit_size;
+ if (order == -1 ||
+ _ch_data[order][root_index].lbp[root_pos] == NULL)
+ return NULL;
+ else
+ return (uint8_t *)_ch_data[order][root_index].lbp[root_pos] + block_offset;
}
-void LogicSnapshot::reallocate_mipmap_level(MipMapLevel &m)
+bool LogicSnapshot::get_sample(uint64_t index, int sig_index)
{
- const uint64_t new_data_length = ((m.length + MipMapDataUnit - 1) /
- MipMapDataUnit) * MipMapDataUnit;
- if (new_data_length > m.data_length)
- {
- m.data_length = new_data_length;
+ int order = get_ch_order(sig_index);
+ assert(order != -1);
+ assert(_ch_data[order].size() != 0);
+ assert(index < get_sample_count());
- // Padding is added to allow for the uint64_t write word
-// m.data = realloc(m.data, new_data_length * _unit_size +
-// sizeof(uint64_t));
- }
+ uint64_t index_mask = 1ULL << (index & LevelMask[0]);
+ uint64_t root_index = index >> (LeafBlockPower + RootScalePower);
+ uint8_t root_pos = (index & RootMask) >> LeafBlockPower;
+ uint64_t root_pos_mask = 1ULL << root_pos;
+
+ if ((_ch_data[order][root_index].tog & root_pos_mask) == 0) {
+ return (_ch_data[order][root_index].value & root_pos_mask) != 0;
+ } else {
+ uint64_t *lbp = (uint64_t *)_ch_data[order][root_index].lbp[root_pos];
+ return *(lbp + ((index & LeafMask) >> ScalePower)) & index_mask;
+ }
}
-void LogicSnapshot::append_payload_to_mipmap()
-{
- MipMapLevel &m0 = _mip_map[0];
- uint64_t prev_length;
- const uint8_t *src_ptr;
- uint8_t *dest_ptr;
- uint64_t accumulator;
- unsigned int diff_counter;
-
- // Expand the data buffer to fit the new samples
- prev_length = m0.length;
- m0.length = _sample_count / MipMapScaleFactor;
-
- // Break off if there are no new samples to compute
- if (m0.length == prev_length)
- return;
-
- reallocate_mipmap_level(m0);
-
- dest_ptr = (uint8_t*)m0.data + prev_length * _unit_size;
-
- // Iterate through the samples to populate the first level mipmap
- const uint8_t *const end_src_ptr = (uint8_t*)_data +
- m0.length * _unit_size * MipMapScaleFactor;
- for (src_ptr = (uint8_t*)_data +
- prev_length * _unit_size * MipMapScaleFactor;
- src_ptr < end_src_ptr;)
- {
- // Accumulate transitions which have occurred in this sample
- accumulator = 0;
- diff_counter = MipMapScaleFactor;
- while (diff_counter-- > 0)
- {
- const uint64_t sample = *(uint64_t*)src_ptr;
- accumulator |= _last_append_sample ^ sample;
- _last_append_sample = sample;
- src_ptr += _unit_size;
- }
-
- *(uint64_t*)dest_ptr = accumulator;
- dest_ptr += _unit_size;
- }
-
- // Compute higher level mipmaps
- for (unsigned int level = 1; level < ScaleStepCount; level++)
- {
- MipMapLevel &m = _mip_map[level];
- const MipMapLevel &ml = _mip_map[level-1];
-
- // Expand the data buffer to fit the new samples
- prev_length = m.length;
- m.length = ml.length / MipMapScaleFactor;
-
- // Break off if there are no more samples to computed
- if (m.length == prev_length)
- break;
-
- reallocate_mipmap_level(m);
-
- // Subsample the level lower level
- src_ptr = (uint8_t*)ml.data +
- _unit_size * prev_length * MipMapScaleFactor;
- const uint8_t *const end_dest_ptr =
- (uint8_t*)m.data + _unit_size * m.length;
- for (dest_ptr = (uint8_t*)m.data +
- _unit_size * prev_length;
- dest_ptr < end_dest_ptr;
- dest_ptr += _unit_size)
- {
- accumulator = 0;
- diff_counter = MipMapScaleFactor;
- while (diff_counter-- > 0)
- {
- accumulator |= *(uint64_t*)src_ptr;
- src_ptr += _unit_size;
- }
-
- *(uint64_t*)dest_ptr = accumulator;
- }
- }
-}
-
-void LogicSnapshot::get_subsampled_edges(
- std::vector &edges,
- uint64_t start, uint64_t end,
- float min_length, int sig_index)
+bool LogicSnapshot::get_display_edges(std::vector > &edges,
+ std::vector > &togs,
+ uint64_t start, uint64_t end, uint16_t width, uint16_t max_togs,
+ double pixels_offset, double min_length, uint16_t sig_index)
{
if (!edges.empty())
edges.clear();
+ if (!togs.empty())
+ togs.clear();
if (get_sample_count() == 0)
- return;
+ return false;
assert(end < get_sample_count());
- assert(start <= end);
- assert(min_length > 0);
- assert(sig_index >= 0);
- assert(sig_index < 64);
+ assert(start <= end);
+ assert(min_length > 0);
uint64_t index = start;
bool last_sample;
- const uint64_t block_length = (uint64_t)max(min_length, 1.0f);
- const uint64_t sig_mask = 1ULL << sig_index;
+ bool start_sample;
-
- // Store the initial state
- last_sample = (get_sample(start) & sig_mask) != 0;
- edges.push_back(pair(index++, last_sample));
-
- while (index + block_length <= end)
- {
+ // Get the initial state
+ start_sample = last_sample = get_sample(index++, sig_index);
+ togs.push_back(pair(0, last_sample));
+ while(edges.size() < width) {
// search next edge
- get_nxt_edge(index, last_sample, end, min_length, sig_index);
+ bool has_edge = get_nxt_edge(index, last_sample, end, 0, sig_index);
- //----- Store the edge -----//
+ // calc the edge position
+ int64_t gap = (index / min_length) - pixels_offset;
+ index = max((uint64_t)ceil((floor(index/min_length) + 1) * min_length), index + 1);
+ while(gap > (int64_t)edges.size() && edges.size() < width)
+ edges.push_back(pair(false, last_sample));
- // Take the last sample of the quanization block
- const int64_t final_index = index + block_length;
- if (index + block_length > end)
- break;
+ if (index > end)
+ last_sample = get_sample(end, sig_index);
+ else
+ last_sample = get_sample(index - 1, sig_index);
- // Store the final state
- const bool final_sample =
- (get_sample(final_index - 1) & sig_mask) != 0;
- edges.push_back(pair(index, final_sample));
+ if (has_edge) {
+ edges.push_back(pair(true, last_sample));
+ if (togs.size() < max_togs)
+ togs.push_back(pair(edges.size() - 1, last_sample));
+ }
- index = final_index;
- last_sample = final_sample;
- }
+ while(index > end && edges.size() < width)
+ edges.push_back(pair(false, last_sample));
+ }
- // Add the final state
- const bool end_sample = ((get_sample(end) & sig_mask) != 0);
- if ((end != get_sample_count() - 1) ||
- ((end == get_sample_count() - 1) && end_sample != last_sample))
- edges.push_back(pair(end, end_sample));
+ if (togs.size() < max_togs) {
+ last_sample = get_sample(end, sig_index);
+ togs.push_back(pair(edges.size() - 1, last_sample));
+ }
- if (end == get_sample_count() - 1)
- edges.push_back(pair(end + 1, ~last_sample));
+ return start_sample;
}
bool LogicSnapshot::get_nxt_edge(
uint64_t &index, bool last_sample, uint64_t end,
- float min_length, int sig_index)
+ double min_length, int sig_index)
{
- unsigned int level;
- bool fast_forward;
-
- //assert(index > 0);
-
- const unsigned int min_level = max((int)floorf(logf(min_length) /
- LogMipMapScaleFactor) - 1, 0);
- const uint64_t sig_mask = 1ULL << sig_index;
-
- if (index >= end)
+ if (index > end)
return false;
- //----- Continue to search -----//
- level = min_level;
+ int order = get_ch_order(sig_index);
+ if (order == -1)
+ return false;
- // We cannot fast-forward if there is no mip-map data at
- // at the minimum level.
- fast_forward = (_mip_map[level].data != NULL);
+ //const unsigned int min_level = max((int)floorf(logf(min_length) / logf(Scale)) - 1, 0);
+ const unsigned int min_level = max((int)(log2f(min_length) - 1) / ScalePower, 0);
+ uint64_t root_index = index >> (LeafBlockPower + RootScalePower);
+ uint8_t root_pos = (index & RootMask) >> LeafBlockPower;
+ bool edge_hit = false;
- if (min_length < MipMapScaleFactor)
+ // linear search for the next transition on the root level
+ for (int64_t i = root_index; !edge_hit && (index <= end) && i < (int64_t)_ch_data[order].size(); i++) {
+ uint64_t cur_mask = (~0ULL << root_pos);
+ do {
+ uint64_t cur_tog = _ch_data[order][i].tog & cur_mask;
+ if (cur_tog != 0) {
+ uint64_t first_edge_pos = bsf_folded(cur_tog);
+ uint64_t *lbp = (uint64_t *)_ch_data[order][i].lbp[first_edge_pos];
+ uint64_t blk_start = (i << (LeafBlockPower + RootScalePower)) + (first_edge_pos << LeafBlockPower);
+ index = max(blk_start, index);
+ if (min_level < ScaleLevel) {
+ uint64_t block_end = min(index | LeafMask, end);
+ edge_hit = block_nxt_edge(lbp, index, block_end, last_sample, min_level);
+ } else {
+ edge_hit = true;
+ }
+ if (first_edge_pos == RootScale - 1)
+ break;
+ cur_mask = (~0ULL << (first_edge_pos + 1));
+ } else {
+ index = (index + (1 << (LeafBlockPower + RootScalePower))) &
+ (~0ULL << (LeafBlockPower + RootScalePower));
+ break;
+ }
+ } while (!edge_hit && index < end);
+ root_pos = 0;
+ }
+ return edge_hit;
+}
+
+bool LogicSnapshot::get_pre_edge(uint64_t &index, bool last_sample,
+ double min_length, int sig_index)
+{
+ assert(index < get_sample_count());
+
+ int order = get_ch_order(sig_index);
+ if (order == -1)
+ return false;
+
+ //const unsigned int min_level = max((int)floorf(logf(min_length) / logf(Scale)) - 1, 1);
+ const unsigned int min_level = max((int)(log2f(min_length) - 1) / ScalePower, 0);
+ int root_index = index >> (LeafBlockPower + RootScalePower);
+ uint8_t root_pos = (index & RootMask) >> LeafBlockPower;
+ bool edge_hit = false;
+
+ // linear search for the previous transition on the root level
+ for (int64_t i = root_index; !edge_hit && i >= 0; i--) {
+ uint64_t cur_mask = (~0ULL >> (RootScale - root_pos - 1));
+ do {
+ uint64_t cur_tog = _ch_data[order][i].tog & cur_mask;
+ if (cur_tog != 0) {
+ uint64_t first_edge_pos = bsr64(cur_tog);
+ uint64_t *lbp = (uint64_t *)_ch_data[order][i].lbp[first_edge_pos];
+ uint64_t blk_end = ((i << (LeafBlockPower + RootScalePower)) +
+ (first_edge_pos << LeafBlockPower)) | LeafMask;
+ index = min(blk_end, index);
+ if (min_level < ScaleLevel) {
+ edge_hit = block_pre_edge(lbp, index, last_sample, min_level, sig_index);
+ } else {
+ edge_hit = true;
+ }
+ if (first_edge_pos == 0)
+ break;
+ cur_mask = (~0ULL >> (RootScale - first_edge_pos));
+ } else {
+ break;
+ }
+ } while (!edge_hit);
+ root_pos = RootScale - 1;
+ }
+
+ return edge_hit;
+}
+
+bool LogicSnapshot::block_nxt_edge(uint64_t *lbp, uint64_t &index, uint64_t block_end, bool last_sample,
+ unsigned int min_level)
+{
+ unsigned int level = min_level;
+ bool fast_forward = true;
+ const uint64_t last = last_sample ? ~0ULL : 0;
+
+ //----- Search Next Edge Within Current LeafBlock -----//
+ if (level == 0)
{
// Search individual samples up to the beginning of
// the next first level mip map block
- const uint64_t final_index = min(end,
- pow2_ceil(index, MipMapScalePower));
-
- for (; index < final_index &&
- (index & ~(~0 << MipMapScalePower)) != 0;
- index++)
- {
- const bool sample =
- (get_sample(index) & sig_mask) != 0;
-
- // If there was a change we cannot fast forward
- if (sample != last_sample) {
- fast_forward = false;
- break;
- }
- }
- }
- else
- {
- // If resolution is less than a mip map block,
- // round up to the beginning of the mip-map block
- // for this level of detail
- const int min_level_scale_power =
- (level + 1) * MipMapScalePower;
- index = pow2_ceil(index, min_level_scale_power);
- if (index >= end)
- return false;
-
- // We can fast forward only if there was no change
- const bool sample =
- (get_sample(index) & sig_mask) != 0;
- if (last_sample != sample)
+ const uint64_t offset = (index & ~(~0ULL << LeafBlockPower)) >> ScalePower;
+ const uint64_t mask = last_sample ? ~(~0ULL << (index & LevelMask[0])) : ~0ULL << (index & LevelMask[0]);
+ uint64_t sample = last_sample ? *(lbp + offset) | mask : *(lbp + offset) & mask;
+ if (sample ^ last) {
+ index = (index & ~LevelMask[0]) + bsf_folded(last_sample ? ~sample : sample);
fast_forward = false;
+ } else {
+ index = ((index >> ScalePower) + 1) << ScalePower;
+ }
+ } else {
+ index = ((index >> level*ScalePower) + 1) << level*ScalePower;
}
if (fast_forward) {
@@ -382,155 +689,94 @@ bool LogicSnapshot::get_nxt_edge(
// zooming in on them to find the point where the edge
// begins.
- // Slide right and zoom out at the beginnings of mip-map
+ // Zoom out at the beginnings of mip-map
// blocks until we encounter a change
- while (1) {
- const int level_scale_power =
- (level + 1) * MipMapScalePower;
- const uint64_t offset =
- index >> level_scale_power;
-
- // Check if we reached the last block at this
- // level, or if there was a change in this block
- if (offset >= _mip_map[level].length ||
- (get_subsample(level, offset) &
- sig_mask))
- break;
-
- if ((offset & ~(~0 << MipMapScalePower)) == 0) {
- // If we are now at the beginning of a
- // higher level mip-map block ascend one
- // level
- if (level + 1 >= ScaleStepCount ||
- !_mip_map[level + 1].data)
- break;
-
+ while (index <= block_end) {
+ // continue only within current block
+ if (level == 0)
level++;
- } else {
- // Slide right to the beginning of the
- // next mip map block
- index = pow2_ceil(index + 1,
- level_scale_power);
- }
- }
-
- // Zoom in, and slide right until we encounter a change,
- // and repeat until we reach min_level
- while (1) {
- assert(_mip_map[level].data);
-
const int level_scale_power =
- (level + 1) * MipMapScalePower;
+ (level + 1) * ScalePower;
const uint64_t offset =
- index >> level_scale_power;
+ (index & ~(~0ULL << LeafBlockPower)) >> level_scale_power;
+ const uint64_t mask = ~0ULL << ((index & LevelMask[level]) >> (level*ScalePower));
+ uint64_t sample = *(lbp + LevelOffset[level] + offset) & mask;
- // Check if we reached the last block at this
- // level, or if there was a change in this block
- if (offset >= _mip_map[level].length ||
- (get_subsample(level, offset) &
- sig_mask)) {
- // Zoom in unless we reached the minimum
- // zoom
- if (level == min_level)
- break;
-
- level--;
+ // Check if there was a change in this block
+ if (sample) {
+ index = (index & (~0 << (level + 1)*ScalePower)) + (bsf_folded(sample) << level*ScalePower);
+ break;
} else {
- // Slide right to the beginning of the
- // next mip map block
- index = pow2_ceil(index + 1,
- level_scale_power);
+ index = ((index >> (level + 1)*ScalePower) + 1) << (level + 1)*ScalePower;
+ ++level;
}
}
- // If individual samples within the limit of resolution,
- // do a linear search for the next transition within the
- // block
- if (min_length < MipMapScaleFactor) {
- for (; index < end; index++) {
- const bool sample = (get_sample(index) &
- sig_mask) != 0;
- if (sample != last_sample)
+ // Zoom in until we encounter a change,
+ // and repeat until we reach min_level
+ while ((index <= block_end) && (level > min_level)) {
+ // continue only within current block
+ level--;
+ const int level_scale_power =
+ (level + 1) * ScalePower;
+ const uint64_t offset =
+ (index & ~(~0ULL << LeafBlockPower)) >> level_scale_power;
+ const uint64_t mask = (level == 0 && last_sample) ?
+ ~(~0ULL << ((index & LevelMask[level]) >> (level*ScalePower))) :
+ ~0ULL << ((index & LevelMask[level]) >> (level*ScalePower));
+ uint64_t sample = (level == 0 && last_sample) ?
+ *(lbp + LevelOffset[level] + offset) | mask :
+ *(lbp + LevelOffset[level] + offset) & mask;
+
+ // Update the low level position of the change in this block
+ if (level == 0 ? sample ^ last : sample) {
+ index = (index & (~0 << (level + 1)*ScalePower)) + (bsf_folded(level == 0 ? sample ^ last : sample) << level*ScalePower);
+ if (level == min_level)
break;
}
}
}
- if (index >= end)
- return false;
- else
- return true;
+ return (index <= block_end);
}
-bool LogicSnapshot::get_pre_edge(
- uint64_t &index, bool last_sample,
- float min_length, int sig_index)
+bool LogicSnapshot::block_pre_edge(uint64_t *lbp, uint64_t &index, bool last_sample,
+ unsigned int min_level, int sig_index)
{
- unsigned int level;
- bool fast_forward;
+ assert(min_level == 0);
- assert(index < get_sample_count());
+ unsigned int level = min_level;
+ bool fast_forward = true;
+ const uint64_t last = last_sample ? ~0ULL : 0;
+ uint64_t block_start = index & ~LeafMask;
- const unsigned int min_level = max((int)floorf(logf(min_length) /
- LogMipMapScaleFactor) - 1, 0);
- const uint64_t sig_mask = 1ULL << sig_index;
-
- //----- Continue to search -----//
- level = min_level;
-
- // We cannot fast-forward if there is no mip-map data at
- // at the minimum level.
- fast_forward = (_mip_map[level].data != NULL);
-
- if (min_length < MipMapScaleFactor)
+ //----- Search Next Edge Within Current LeafBlock -----//
+ if (level == 0)
{
- // Search individual samples down to the ending of
+ // Search individual samples down to the beginning of
// the previous first level mip map block
- uint64_t final_index;
- if (index < (1 << MipMapScalePower))
- final_index = 0;
- else
- final_index = pow2_ceil(index + 1, MipMapScalePower) - (1 << MipMapScalePower) - 1;
-
- for (; index >= final_index; index--)
- {
- const bool sample =
- (get_sample(index) & sig_mask) != 0;
-
- // If there was a change we cannot fast forward
- if (sample != last_sample) {
- fast_forward = false;
- index++;
- return true;
- }
-
+ const uint64_t offset = (index & ~(~0ULL << LeafBlockPower)) >> ScalePower;
+ const uint64_t mask = last_sample ? ~(~0ULL >> (Scale - (index & LevelMask[0]) - 1)) : ~0ULL >> (Scale - (index & LevelMask[0]) - 1);
+ uint64_t sample = last_sample ? *(lbp + offset) | mask : *(lbp + offset) & mask;
+ if (sample ^ last) {
+ index = (index & ~LevelMask[0]) + bsr64(last_sample ? ~sample : sample) + 1;
+ return true;
+ } else {
+ index &= ~LevelMask[0];
if (index == 0)
return false;
- }
- }
- else
- {
- // If resolution is less than a mip map block,
- // round up to the beginning of the mip-map block
- // for this level of detail
- const unsigned int min_level_scale_power =
- (level + 1) * MipMapScalePower;
- if (index < (uint64_t)(1 << min_level_scale_power))
- index = 0;
- else
- index = pow2_ceil(index, min_level_scale_power) - (1 << min_level_scale_power) - 1;
+ else
+ index--;
- // We can fast forward only if there was no change
- const bool sample =
- (get_sample(index) & sig_mask) != 0;
- if (last_sample != sample) {
- fast_forward = false;
- index++;
- return true;
+ // using get_sample() to avoid out of block case
+ bool sample = get_sample(index, sig_index);
+ if (sample ^ last_sample) {
+ index++;
+ return true;
+ } else if (index < block_start) {
+ return false;
+ }
}
-
- if (index == 0)
- return false;
}
if (fast_forward) {
@@ -540,96 +786,305 @@ bool LogicSnapshot::get_pre_edge(
// zooming in on them to find the point where the edge
// begins.
- // Slide left and zoom out at the endings of mip-map
+ // Zoom out at the beginnings of mip-map
// blocks until we encounter a change
- while (1) {
- const int level_scale_power =
- (level + 1) * MipMapScalePower;
- const uint64_t offset =
- index >> level_scale_power;
-
- // Check if we reached the first block at this
- // level, or if there was a change in this block
- if (offset == 0 ||
- (get_subsample(level, offset) &
- sig_mask))
- break;
-
- if (((offset+1) & ~(~0 << MipMapScalePower)) == 0) {
- // If we are now at the ending of a
- // higher level mip-map block ascend one
- // level
- if (level + 1 >= ScaleStepCount ||
- !_mip_map[level + 1].data)
- break;
-
+ while (index > block_start) {
+ // continue only within current block
+ if (level == 0)
level++;
- } else {
- // Slide left to the beginning of the
- // previous mip map block
- index = pow2_ceil(index + 1,
- level_scale_power) - (1 << level_scale_power) - 1;
- }
- }
-
- // Zoom in, and slide left until we encounter a change,
- // and repeat until we reach min_level
- while (1) {
- assert(_mip_map[level].data);
-
const int level_scale_power =
- (level + 1) * MipMapScalePower;
+ (level + 1) * ScalePower;
const uint64_t offset =
- index >> level_scale_power;
+ (index & ~(~0ULL << LeafBlockPower)) >> level_scale_power;
+ const uint64_t mask = ~0ULL >> (Scale - ((index & LevelMask[level]) >> (level*ScalePower)) - 1);
+ uint64_t sample = *(lbp + LevelOffset[level] + offset) & mask;
- // Check if we reached the first block at this
- // level, or if there was a change in this block
- if (offset == 0 ||
- (get_subsample(level, offset) &
- sig_mask)) {
- // Zoom in unless we reached the minimum
- // zoom
- if (level == min_level)
- break;
-
- level--;
+ // Check if there was a change in this block
+ if (sample) {
+ index = (index & (~0 << (level + 1)*ScalePower)) +
+ (bsr64(sample) << level*ScalePower) +
+ ~(~0ULL << level*ScalePower);
+ break;
} else {
- // Slide left to the ending of the
- // previous mip map block
- index = pow2_ceil(index + 1,
- level_scale_power) - (1 << level_scale_power) - 1;
+ index = (index >> (level + 1)*ScalePower) << (level + 1)*ScalePower;
+ if (index == 0)
+ return false;
+ else
+ index--;
}
}
- // If individual samples within the limit of resolution,
- // do a linear search for the next transition within the
- // block
- if (min_length < MipMapScaleFactor) {
- for (; index > 0; index--) {
- const bool sample = (get_sample(index) &
- sig_mask) != 0;
- if (sample != last_sample) {
+ // Zoom in until we encounter a change,
+ // and repeat until we reach min_level
+ while ((index >= block_start) && (level > min_level)) {
+ // continue only within current block
+ level--;
+ const int level_scale_power =
+ (level + 1) * ScalePower;
+ const uint64_t offset =
+ (index & ~(~0ULL << LeafBlockPower)) >> level_scale_power;
+ const uint64_t mask = (level == 0 && last_sample) ?
+ ~(~0ULL >> (Scale - ((index & LevelMask[level]) >> (level*ScalePower)) - 1)) :
+ ~0ULL >> (Scale - ((index & LevelMask[level]) >> (level*ScalePower)) - 1);
+ uint64_t sample = (level == 0 && last_sample) ?
+ *(lbp + LevelOffset[level] + offset) | mask :
+ *(lbp + LevelOffset[level] + offset) & mask;
+
+ // Update the low level position of the change in this block
+ if (level == 0 ? sample ^ last : sample) {
+ index = (index & (~0 << (level + 1)*ScalePower)) +
+ (bsr64(level == 0 ? sample ^ last : sample) << level*ScalePower) +
+ ~(~0ULL << level*ScalePower);
+ if (level == min_level) {
index++;
- return true;
+ break;
}
+ } else {
+ index = (index & (~0 << (level + 1)*ScalePower));
+ }
+ }
+ }
+
+ return (index >= block_start) && (index != 0);
+}
+
+bool LogicSnapshot::pattern_search(int64_t start, int64_t end, bool nxt, int64_t &index,
+ std::map pattern)
+{
+ int start_match_pos = pattern.size() - 1;
+ int end_match_pos = 0;
+ if (pattern.empty()) {
+ return true;
+ } else {
+ for (auto& iter:pattern) {
+ int char_index = 0;
+ for (auto& iter_char:iter.second) {
+ if (iter_char != 'X') {
+ start_match_pos = min(start_match_pos, char_index);
+ end_match_pos = max(end_match_pos, char_index);
+ }
+ char_index++;
+ }
+ }
+ }
+
+ if (start_match_pos > end_match_pos)
+ return true;
+
+ std::map cur_sample;
+ std::map exp_sample;
+ std::map cur_edge;
+ std::map exp_edge;
+ int nxt_match_pos = nxt ? start_match_pos : end_match_pos;
+ int cur_match_pos = nxt ? nxt_match_pos - 1 : nxt_match_pos + 1;
+ std::vector exp_index;
+ bool find_edge;
+ typedef std::map::iterator it_type;
+ while(nxt ? index <= end : index >= start) {
+ // get expacted and current pattern
+ exp_index.clear();
+ for(it_type iterator = pattern.begin();
+ iterator != pattern.end(); iterator++) {
+ uint16_t ch_index = iterator->first;
+ if (!has_data(ch_index))
+ continue;
+ exp_index.push_back(index);
+ cur_sample[ch_index] = get_sample(index, ch_index);
+
+ if (iterator->second[nxt_match_pos] == '0') {
+ exp_sample[ch_index] = false;
+ } else if (iterator->second[nxt_match_pos] == '1') {
+ exp_sample[ch_index] = true;
+ } else if (iterator->second[nxt_match_pos] == 'X') {
+ exp_sample[ch_index] = cur_sample[ch_index];
+ } else if (iterator->second[nxt_match_pos] == 'F') {
+ exp_sample[ch_index] = false;
+ exp_edge[ch_index] = true;
+ } else if (iterator->second[nxt_match_pos] == 'R') {
+ exp_sample[ch_index] = true;
+ exp_edge[ch_index] = true;
+ } else if (iterator->second[nxt_match_pos] == 'C') {
+ exp_sample[ch_index] = cur_sample[ch_index];
+ exp_edge[ch_index] = true;
+ }
+
+ if (exp_edge.find(ch_index) != exp_edge.end()) {
+ if (index > start) {
+ bool sample = get_sample(index - 1, ch_index);
+ if (sample != cur_sample[ch_index])
+ cur_edge[ch_index] = true;
+ }
+ }
+ }
+ cur_match_pos = nxt_match_pos;
+
+ // pattern compare
+ if (cur_edge == exp_edge &&
+ cur_sample == exp_sample)
+ nxt_match_pos += nxt ? 1 : -1;
+
+ if (nxt ? nxt_match_pos > end_match_pos :
+ nxt_match_pos < start_match_pos) {
+ // all matched
+ return true;
+ } else if (nxt ? nxt_match_pos > cur_match_pos :
+ nxt_match_pos < cur_match_pos) {
+ // one stage matched
+ int64_t sub_index = nxt ? index + 1 : index - 1;
+ while((nxt ? cur_match_pos++ < end_match_pos : cur_match_pos-- > start_match_pos) &&
+ (nxt ? sub_index <= end : sub_index >= start)) {
+ // get expacted and current pattern
+ exp_index.clear();
+ for(it_type iterator = pattern.begin();
+ iterator != pattern.end(); iterator++) {
+ uint16_t ch_index = iterator->first;
+ if (!has_data(ch_index))
+ continue;
+ exp_index.push_back(sub_index);
+ cur_sample[ch_index] = get_sample(sub_index, ch_index);
+
+ if (iterator->second[cur_match_pos] == '0') {
+ exp_sample[ch_index] = false;
+ } else if (iterator->second[cur_match_pos] == '1') {
+ exp_sample[ch_index] = true;
+ } else if (iterator->second[cur_match_pos] == 'X') {
+ exp_sample[ch_index] = cur_sample[ch_index];
+ } else if (iterator->second[cur_match_pos] == 'F') {
+ exp_sample[ch_index] = false;
+ exp_edge[ch_index] = true;
+ } else if (iterator->second[cur_match_pos] == 'R') {
+ exp_sample[ch_index] = true;
+ exp_edge[ch_index] = true;
+ } else if (iterator->second[cur_match_pos] == 'C') {
+ exp_sample[ch_index] = cur_sample[ch_index];
+ exp_edge[ch_index] = true;
+ }
+
+ if (exp_edge.find(ch_index) != exp_edge.end()) {
+ if (sub_index > start) {
+ bool sample = get_sample(sub_index - 1, ch_index);
+ if (sample != cur_sample[ch_index])
+ cur_edge[ch_index] = true;
+ }
+ }
+ }
+
+ // pattern compare
+ if (cur_edge != exp_edge ||
+ cur_sample != exp_sample) {
+ cur_match_pos = nxt_match_pos - 1;
+ index += nxt ? 1 : -1;
+ break;
+ } else {
+ sub_index += nxt ? 1 : -1;
+ }
+ }
+
+ if (nxt ? cur_match_pos > end_match_pos :
+ cur_match_pos < start_match_pos) {
+ index = nxt ? sub_index - 1 : index;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ // not matched, find the next index for pattern compare
+ find_edge = true;
+ int seq = 0;
+ for(it_type iterator = pattern.begin();
+ iterator != pattern.end(); iterator++) {
+ uint16_t ch_index = iterator->first;
+ if (!has_data(ch_index))
+ continue;
+ if (exp_edge.find(ch_index) != exp_edge.end() ||
+ cur_sample[ch_index] != exp_sample[ch_index]) {
+ do {
+ if (nxt) {
+ exp_index[seq] += 1;
+ find_edge = get_nxt_edge(exp_index[seq], cur_sample[ch_index], end, 1, ch_index);
+ } else {
+ exp_index[seq] -= 1;
+ cur_sample[ch_index] = get_sample(exp_index[seq], ch_index);
+ find_edge = get_pre_edge(exp_index[seq], cur_sample[ch_index], 1, ch_index);
+ }
+ if (find_edge)
+ cur_sample[ch_index] = get_sample(exp_index[seq], ch_index);
+ else
+ break;
+ }while(cur_sample[ch_index] != exp_sample[ch_index]);
+ }
+ seq++;
+ }
+ if (find_edge) {
+ if (nxt)
+ index = *max_element(exp_index.begin(), exp_index.end());
+ else
+ index = *min_element(exp_index.begin(), exp_index.end());
+ } else {
+ break;
}
}
}
return false;
}
-uint64_t LogicSnapshot::get_subsample(int level, uint64_t offset) const
+bool LogicSnapshot::has_data(int sig_index)
{
- assert(level >= 0);
- assert(_mip_map[level].data);
- return *(uint64_t*)((uint8_t*)_mip_map[level].data +
- _unit_size * offset);
+ return get_ch_order(sig_index) != -1;
}
-uint64_t LogicSnapshot::pow2_ceil(uint64_t x, unsigned int power)
+int LogicSnapshot::get_block_num()
{
- const uint64_t p = 1 << power;
- return (x + p - 1) / p * p;
+ return (_ring_sample_count >> LeafBlockPower) +
+ ((_ring_sample_count & LeafMask) != 0);
+}
+
+uint64_t LogicSnapshot::get_block_size(int block_index)
+{
+ assert(block_index < get_block_num());
+
+ if (block_index < get_block_num() - 1) {
+ return LeafBlockSamples / 8;
+ } else {
+ if (_ring_sample_count % LeafBlockSamples == 0)
+ return LeafBlockSamples / 8;
+ else
+ return (_ring_sample_count % LeafBlockSamples) / 8;
+ }
+}
+
+uint8_t *LogicSnapshot::get_block_buf(int block_index, int sig_index, bool &sample)
+{
+ assert(block_index < get_block_num());
+
+ int order = get_ch_order(sig_index);
+ if (order == -1) {
+ sample = 0;
+ return NULL;
+ }
+ uint64_t index = block_index / RootScale;
+ uint8_t pos = block_index % RootScale;
+ uint8_t *lbp = (uint8_t *)_ch_data[order][index].lbp[pos];
+
+ if (lbp == NULL)
+ sample = (_ch_data[order][index].value & 1ULL << pos) != 0;
+
+ return lbp;
+}
+
+int LogicSnapshot::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
diff --git a/DSView/pv/data/logicsnapshot.h b/DSView/pv/data/logicsnapshot.h
index d1f70635..10656051 100644
--- a/DSView/pv/data/logicsnapshot.h
+++ b/DSView/pv/data/logicsnapshot.h
@@ -26,6 +26,8 @@
#include "snapshot.h"
+#include
+
#include
#include
@@ -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 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 &edges,
- uint64_t start, uint64_t end,
- float min_length, int sig_index);
+ void capture_ended();
+
+ bool get_display_edges(std::vector> &edges,
+ std::vector> &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 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> _ch_data;
+ uint64_t _block_num;
+ uint8_t _byte_fraction;
+ uint16_t _ch_fraction;
+ void *_src_ptr;
+ void *_dest_ptr;
+
+ std::vector _sample_cnt;
+ std::vector _block_cnt;
+ std::vector _ring_sample_cnt;
+ std::vector _last_sample;
friend class LogicSnapshotTest::Pow2;
friend class LogicSnapshotTest::Basic;
diff --git a/DSView/pv/data/mathstack.cpp b/DSView/pv/data/mathstack.cpp
index 0bec7874..9f76cb8a 100644
--- a/DSView/pv/data/mathstack.cpp
+++ b/DSView/pv/data/mathstack.cpp
@@ -157,12 +157,13 @@ const std::vector 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);
diff --git a/DSView/pv/data/mathstack.h b/DSView/pv/data/mathstack.h
index d9e32423..88c5fca3 100644
--- a/DSView/pv/data/mathstack.h
+++ b/DSView/pv/data/mathstack.h
@@ -86,7 +86,7 @@ public:
void set_sample_interval(int interval);
const std::vector get_fft_spectrum() const;
- const double get_fft_spectrum(uint64_t index) const;
+ double get_fft_spectrum(uint64_t index);
void calc_fft();
diff --git a/DSView/pv/data/signaldata.cpp b/DSView/pv/data/signaldata.cpp
index 00c7e5ef..a4cd3af3 100644
--- a/DSView/pv/data/signaldata.cpp
+++ b/DSView/pv/data/signaldata.cpp
@@ -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
diff --git a/DSView/pv/data/signaldata.h b/DSView/pv/data/signaldata.h
index 7f96312e..c74898d1 100644
--- a/DSView/pv/data/signaldata.h
+++ b/DSView/pv/data/signaldata.h
@@ -42,11 +42,8 @@ public:
virtual void init() = 0;
- double get_start_time() const;
-
protected:
double _samplerate;
- double _start_time;
};
} // namespace data
diff --git a/DSView/pv/data/snapshot.cpp b/DSView/pv/data/snapshot.cpp
index df2c8011..d49fac6e 100644
--- a/DSView/pv/data/snapshot.cpp
+++ b/DSView/pv/data/snapshot.cpp
@@ -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
diff --git a/DSView/pv/data/snapshot.h b/DSView/pv/data/snapshot.h
index 5fa3e440..36b935af 100644
--- a/DSView/pv/data/snapshot.h
+++ b/DSView/pv/data/snapshot.h
@@ -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 _data;
void* _data;
+ std::vector _ch_index;
+
uint64_t _capacity;
unsigned int _channel_num;
uint64_t _sample_count;
diff --git a/DSView/pv/device/device.cpp b/DSView/pv/device/device.cpp
index 74b021f8..56870acf 100644
--- a/DSView/pv/device/device.cpp
+++ b/DSView/pv/device/device.cpp
@@ -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."));
}
diff --git a/DSView/pv/device/device.h b/DSView/pv/device/device.h
index 435bb4bd..a98ffc0d 100644
--- a/DSView/pv/device/device.h
+++ b/DSView/pv/device/device.h
@@ -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();
diff --git a/DSView/pv/device/devinst.cpp b/DSView/pv/device/devinst.cpp
index 347ce869..652c548e 100644
--- a/DSView/pv/device/devinst.cpp
+++ b/DSView/pv/device/devinst.cpp
@@ -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
diff --git a/DSView/pv/device/devinst.h b/DSView/pv/device/devinst.h
index dec1b525..b45f515e 100644
--- a/DSView/pv/device/devinst.h
+++ b/DSView/pv/device/devinst.h
@@ -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
diff --git a/DSView/pv/device/file.cpp b/DSView/pv/device/file.cpp
index fdc1bd15..d0de5e0c 100644
--- a/DSView/pv/device/file.cpp
+++ b/DSView/pv/device/file.cpp
@@ -25,6 +25,8 @@
#include
+#include
+
#include
#include
@@ -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
diff --git a/DSView/pv/device/file.h b/DSView/pv/device/file.h
index 89a7ddf3..000b950b 100644
--- a/DSView/pv/device/file.h
+++ b/DSView/pv/device/file.h
@@ -24,6 +24,9 @@
#include
+#include
+#include
+
#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;
diff --git a/DSView/pv/device/inputfile.cpp b/DSView/pv/device/inputfile.cpp
index 967d6f7b..69de8f80 100644
--- a/DSView/pv/device/inputfile.cpp
+++ b/DSView/pv/device/inputfile.cpp
@@ -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;
}
diff --git a/DSView/pv/device/sessionfile.cpp b/DSView/pv/device/sessionfile.cpp
index c1902c15..ada63fc3 100644
--- a/DSView/pv/device/sessionfile.cpp
+++ b/DSView/pv/device/sessionfile.cpp
@@ -21,7 +21,7 @@
#include "sessionfile.h"
-#include
+#include
namespace pv {
namespace device {
diff --git a/DSView/pv/dialogs/calibration.cpp b/DSView/pv/dialogs/calibration.cpp
index f9e7995e..32d754ad 100755
--- a/DSView/pv/dialogs/calibration.cpp
+++ b/DSView/pv/dialogs/calibration.cpp
@@ -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 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 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 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 watcher;
diff --git a/DSView/pv/dialogs/deviceoptions.cpp b/DSView/pv/dialogs/deviceoptions.cpp
index 74f8f557..0824716d 100644
--- a/DSView/pv/dialogs/deviceoptions.cpp
+++ b/DSView/pv/dialogs/deviceoptions.cpp
@@ -54,7 +54,7 @@ DeviceOptions::DeviceOptions(QWidget *parent, boost::shared_ptrsetLayout(&_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 > &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::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(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::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
diff --git a/DSView/pv/dialogs/deviceoptions.h b/DSView/pv/dialogs/deviceoptions.h
index 6de30d94..52b314ae 100644
--- a/DSView/pv/dialogs/deviceoptions.h
+++ b/DSView/pv/dialogs/deviceoptions.h
@@ -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 _dev_inst;
diff --git a/DSView/pv/dialogs/dsdialog.cpp b/DSView/pv/dialogs/dsdialog.cpp
index 01f4a685..29986d3a 100755
--- a/DSView/pv/dialogs/dsdialog.cpp
+++ b/DSView/pv/dialogs/dsdialog.cpp
@@ -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);
diff --git a/DSView/pv/dialogs/dsmessagebox.cpp b/DSView/pv/dialogs/dsmessagebox.cpp
index 0491ba3d..4ef58fc5 100755
--- a/DSView/pv/dialogs/dsmessagebox.cpp
+++ b/DSView/pv/dialogs/dsmessagebox.cpp
@@ -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"));
diff --git a/DSView/pv/dialogs/fftoptions.cpp b/DSView/pv/dialogs/fftoptions.cpp
index d1df974f..6c928a0f 100644
--- a/DSView/pv/dialogs/fftoptions.cpp
+++ b/DSView/pv/dialogs/fftoptions.cpp
@@ -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());
diff --git a/DSView/pv/dialogs/interval.cpp b/DSView/pv/dialogs/interval.cpp
new file mode 100755
index 00000000..e2ff752b
--- /dev/null
+++ b/DSView/pv/dialogs/interval.cpp
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the DSView project.
+ * DSView is based on PulseView.
+ *
+ * Copyright (C) 2016 DreamSourceLab
+ *
+ * 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
+
+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
diff --git a/DSView/pv/dialogs/interval.h b/DSView/pv/dialogs/interval.h
new file mode 100755
index 00000000..86e42ade
--- /dev/null
+++ b/DSView/pv/dialogs/interval.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the DSView project.
+ * DSView is based on PulseView.
+ *
+ * Copyright (C) 2016 DreamSourceLab
+ *
+ * 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
+#include
+#include
+#include
+
+#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
diff --git a/DSView/pv/dialogs/protocolexp.cpp b/DSView/pv/dialogs/protocolexp.cpp
index 11f24355..860138e2 100644
--- a/DSView/pv/dialogs/protocolexp.cpp
+++ b/DSView/pv/dialogs/protocolexp.cpp
@@ -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 watcher;
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
diff --git a/DSView/pv/dialogs/protocollist.cpp b/DSView/pv/dialogs/protocollist.cpp
index fbc51379..78fa327c 100644
--- a/DSView/pv/dialogs/protocollist.cpp
+++ b/DSView/pv/dialogs/protocollist.cpp
@@ -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 > 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
diff --git a/DSView/pv/dialogs/protocollist.h b/DSView/pv/dialogs/protocollist.h
index 8c4524fd..bc6a9891 100644
--- a/DSView/pv/dialogs/protocollist.h
+++ b/DSView/pv/dialogs/protocollist.h
@@ -62,6 +62,7 @@ private:
SigSession &_session;
toolbars::TitleBar *_titlebar;
+ QComboBox *_map_zoom_combobox;
QComboBox *_protocol_combobox;
std::list _show_checkbox_list;
std::list _show_label_list;
diff --git a/DSView/pv/dialogs/search.cpp b/DSView/pv/dialogs/search.cpp
index 1469df78..cede9607 100644
--- a/DSView/pv/dialogs/search.cpp
+++ b/DSView/pv/dialogs/search.cpp
@@ -21,53 +21,73 @@
#include "search.h"
+#include "../view/logicsignal.h"
+
#include
#include
+#include
+
namespace pv {
namespace dialogs {
-Search::Search(QWidget *parent, boost::shared_ptr dev_inst, QString pattern) :
+Search::Search(QWidget *parent, SigSession &session, std::map 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 sig,
+ _session.get_signals()) {
+ assert(sig);
+ boost::shared_ptr logic_sig;
+ if (logic_sig = boost::dynamic_pointer_cast(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(sender());
+ sc->setText(sc->text().toUpper());
+}
+
+std::map Search::get_pattern()
+{
+ std::map pattern;
+
+ int index = 0;
+ BOOST_FOREACH(const boost::shared_ptr sig,
+ _session.get_signals()) {
+ assert(sig);
+ boost::shared_ptr logic_sig;
+ if (logic_sig = boost::dynamic_pointer_cast(sig)) {
+ pattern[index] = _search_lineEdit_vec[index]->text();
+ index++;
+ }
+ }
+
return pattern;
}
diff --git a/DSView/pv/dialogs/search.h b/DSView/pv/dialogs/search.h
index 7a9d15ac..f4105fb6 100644
--- a/DSView/pv/dialogs/search.h
+++ b/DSView/pv/dialogs/search.h
@@ -45,23 +45,25 @@ class Search : public DSDialog
public:
- Search(QWidget *parent = 0, boost::shared_ptr dev_inst = 0, QString pattern = "");
+ Search(QWidget *parent, SigSession &session, std::map pattern);
~Search();
- QString get_pattern();
+ std::map get_pattern();
protected:
void accept();
signals:
-public slots:
+private slots:
+ void format();
private:
+ SigSession &_session;
+
toolbars::TitleBar *_titlebar;
- QLineEdit search_lineEdit;
+ QVector _search_lineEdit_vec;
QDialogButtonBox search_buttonBox;
- boost::shared_ptr _dev_inst;
};
} // namespace decoder
diff --git a/DSView/pv/dialogs/storeprogress.cpp b/DSView/pv/dialogs/storeprogress.cpp
index cbd57200..aa2f2916 100644
--- a/DSView/pv/dialogs/storeprogress.cpp
+++ b/DSView/pv/dialogs/storeprogress.cpp
@@ -2,6 +2,7 @@
* This file is part of the PulseView project.
*
* Copyright (C) 2014 Joel Holdsworth
+ * Copyright (C) 2016 DreamSourceLab
*
* 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 p = _session.progress();
+ const std::pair 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
diff --git a/DSView/pv/dialogs/storeprogress.h b/DSView/pv/dialogs/storeprogress.h
index c582e3e1..30cfc841 100644
--- a/DSView/pv/dialogs/storeprogress.h
+++ b/DSView/pv/dialogs/storeprogress.h
@@ -2,6 +2,7 @@
* This file is part of the PulseView project.
*
* Copyright (C) 2014 Joel Holdsworth
+ * Copyright (C) 2016 DreamSourceLab
*
* 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
-#include
+#include
+#include
+#include
+#include
-#include
+#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
diff --git a/DSView/pv/dialogs/waitingdialog.cpp b/DSView/pv/dialogs/waitingdialog.cpp
index c069c61f..bb8ddf36 100644
--- a/DSView/pv/dialogs/waitingdialog.cpp
+++ b/DSView/pv/dialogs/waitingdialog.cpp
@@ -79,7 +79,7 @@ WaitingDialog::WaitingDialog(QWidget *parent, boost::shared_ptraddWidget(&_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 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 watcher;
diff --git a/DSView/pv/dock/measuredock.cpp b/DSView/pv/dock/measuredock.cpp
index 27fe3842..fb116eea 100644
--- a/DSView/pv/dock/measuredock.cpp
+++ b/DSView/pv/dock/measuredock.cpp
@@ -34,14 +34,17 @@
#include "../devicemanager.h"
#include "../device/device.h"
#include "../device/file.h"
+#include "../dialogs/dsdialog.h"
+#include "../dialogs/dsmessagebox.h"
#include
#include
#include
+#include
#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 ::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 ::const_iterator i = _cursor_del_btn_vec.begin();
+ i != _cursor_del_btn_vec.end(); i++)
+ delete (*i);
for (QVector::Iterator i = _cursor_pushButton_list.begin();
i != _cursor_pushButton_list.end(); i++)
delete (*i);
for (QVector::Iterator i = _curpos_label_list.begin();
i != _curpos_label_list.end(); i++)
delete (*i);
- for (QVector::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::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 ::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 ::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(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::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(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::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::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::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 > sigs(_session.get_signals());
+ for(size_t i = 0; i < sigs.size(); i++) {
+ const boost::shared_ptr s(sigs[i]);
+ boost::shared_ptr logicSig;
+ assert(s);
+ if ((logicSig = dynamic_pointer_cast(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 > sigs(_session.get_signals());
+ for(size_t i = 0; i < sigs.size(); i++) {
+ const boost::shared_ptr s(sigs[i]);
+ assert(s);
+
+ if (dynamic_pointer_cast(s) && s->enabled())
+ {
+ selector->addItem(QString::number(s->get_index()));
+ }
+ }
+}
+
+void MeasureDock::del_cursor()
+{
+ int del_index = 0;
+ Cursor* cursor = NULL;
+ for (QVector ::const_iterator i = _cursor_del_btn_vec.begin();
+ i != _cursor_del_btn_vec.end(); i++) {
+ if ((*i)->isChecked()) {
+ int cur_index = 0;
+ std::list::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
diff --git a/DSView/pv/dock/measuredock.h b/DSView/pv/dock/measuredock.h
index bb941b0c..d049782d 100644
--- a/DSView/pv/dock/measuredock.h
+++ b/DSView/pv/dock/measuredock.h
@@ -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 _dist_row_widget_vec;
+ QVector _dist_del_btn_vec;
+ QVector _dist_s_btn_vec;
+ QVector _dist_e_btn_vec;
+ QVector _dist_r_label_vec;
+
+ QGridLayout *_edge_layout;
+ QGroupBox *_edge_groupBox;
+ QToolButton *_edge_add_btn;
+ QVector _edge_row_widget_vec;
+ QVector _edge_del_btn_vec;
+ QVector _edge_s_btn_vec;
+ QVector _edge_e_btn_vec;
+ QVector _edge_ch_cmb_vec;
+ QVector _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 _cursor_del_btn_vec;
QVector _cursor_pushButton_list;
QVector _curpos_label_list;
- QVector _space_label_list;
+
+ QIcon _icon_add;
+ QIcon _icon_add_dis;
+ QIcon _icon_del;
+ QIcon _icon_del_dis;
};
} // namespace dock
diff --git a/DSView/pv/dock/protocoldock.cpp b/DSView/pv/dock/protocoldock.cpp
index 7a32761b..8311c5a5 100644
--- a/DSView/pv/dock/protocoldock.cpp
+++ b/DSView/pv/dock/protocoldock.cpp
@@ -29,6 +29,7 @@
#include "../dialogs/protocollist.h"
#include "../dialogs/protocolexp.h"
#include "../dialogs/dsmessagebox.h"
+#include "../view/view.h"
#include
#include
@@ -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();
- if (_session.add_decoder(decoder)) {
+ if (_session.add_decoder(decoder, silent)) {
//std::list _sel_probes = dlg.get_sel_probes();
//QMap & _options = dlg.get_options();
//QMap _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 > decode_sigs(
+ _session.get_decode_signals());
+ BOOST_FOREACH(boost::shared_ptr 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 > decode_sigs(
+ _session.get_decode_signals());
+ BOOST_FOREACH(boost::shared_ptr 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