diff options
Diffstat (limited to 'DSLogic-gui')
78 files changed, 4748 insertions, 692 deletions
diff --git a/DSLogic-gui/CMakeLists.txt b/DSLogic-gui/CMakeLists.txt index 5a4fb8f..539ab0d 100644 --- a/DSLogic-gui/CMakeLists.txt +++ b/DSLogic-gui/CMakeLists.txt @@ -3,6 +3,7 @@ ## ## Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk> ## Copyright (C) 2012-2013 Alexandru Gagniuc <mr.nuke.me@gmail.com> +## Copyright (C) 2013-2014 DreamSourceLab <support@dreamsourcelab.com> ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -22,13 +23,13 @@ cmake_minimum_required(VERSION 2.6) include(FindPkgConfig) include(GNUInstallDirs) -project(DSLogic-gui) +project(DSLogic) #=============================================================================== #= User Options #------------------------------------------------------------------------------- -option(DISABLE_WERROR "Build without -Werror" FALSE) +option(DISABLE_WERROR "Build without -Werror" TRUE) option(ENABLE_SIGNALS "Build with UNIX signals" TRUE) option(ENABLE_TESTS "Enable unit tests" FALSE) option(STATIC_PKGDEPS_LIBS "Statically link to (pkgconfig) libraries" FALSE) @@ -52,8 +53,11 @@ endif() list(APPEND PKGDEPS libsigrok4DSLogic>=0.2.0 + libusb-1.0>=1.0.16 ) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/") + find_package(PkgConfig) pkg_check_modules(PKGDEPS REQUIRED ${PKGDEPS}) @@ -71,6 +75,8 @@ else() find_package(Boost 1.42 COMPONENTS system thread REQUIRED) endif() +find_package(libusb-1.0 REQUIRED) + #=============================================================================== #= Config Header #------------------------------------------------------------------------------- @@ -79,7 +85,7 @@ set(DS_TITLE DSLogic) set(DS_DESCRIPTION "A GUI for DSLogic") set(DS_VERSION_MAJOR 0) -set(DS_VERSION_MINOR 1) +set(DS_VERSION_MINOR 3) set(DS_VERSION_MICRO 0) set(DS_VERSION_STRING ${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO} @@ -107,6 +113,8 @@ set(DSLogic_SOURCES pv/data/logicsnapshot.cpp pv/data/signaldata.cpp pv/data/snapshot.cpp + pv/data/dso.cpp + pv/data/dsosnapshot.cpp pv/decoder/decoder.cpp pv/decoder/decoderfactory.cpp pv/decoder/democonfig.cpp @@ -147,6 +155,9 @@ set(DSLogic_SOURCES pv/view/timemarker.cpp pv/view/view.cpp pv/view/viewport.cpp + pv/view/dsosignal.cpp + pv/view/dsldial.cpp + pv/dock/dsotriggerdock.cpp ) set(DSLogic_HEADERS @@ -167,6 +178,8 @@ set(DSLogic_HEADERS pv/toolbars/filebar.h pv/toolbars/logobar.h pv/toolbars/trigbar.h + pv/data/dso.h + pv/data/dsosnapshot.h pv/view/cursor.h pv/view/header.h pv/view/ruler.h @@ -174,12 +187,14 @@ set(DSLogic_HEADERS pv/view/groupsignal.h pv/view/protocolsignal.h pv/view/view.h + pv/view/dsosignal.h pv/view/viewport.h + pv/view/dsldial.h + pv/dock/dsotriggerdock.h ) set(DSLogic_FORMS pv/dialogs/about.ui - pv/dialogs/search.ui pv/decoder/dmx512config.ui pv/decoder/i2cconfig.ui pv/decoder/serialconfig.ui @@ -234,6 +249,7 @@ set(DSLOGIC_LINK_LIBS ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${QT_LIBRARIES} + ${LIBUSB_1_LIBRARIES} ) if(STATIC_PKGDEPS_LIBS) @@ -257,6 +273,7 @@ if(WIN32) # Pass -mwindows so that no "DOS box" will open when PulseView is started. set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-mwindows") endif() +set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "/usr/local/lib") #=============================================================================== #= Installation @@ -264,9 +281,8 @@ endif() # Install the executable. install(TARGETS ${PROJECT_NAME} DESTINATION bin/) - -# Install the manpage. -install(FILES doc/DSLogic.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 COMPONENT doc) +install(FILES res/DSLogic.fw DESTINATION bin/res/) +install(FILES res/DSLogic.bin DESTINATION bin/res/) #=============================================================================== #= Packaging (handled by CPack) diff --git a/DSLogic-gui/DSLogic.qrc b/DSLogic-gui/DSLogic.qrc index 8162e2d..d7b5e8a 100644 --- a/DSLogic-gui/DSLogic.qrc +++ b/DSLogic-gui/DSLogic.qrc @@ -27,5 +27,7 @@ <file>icons/start.png</file> <file>icons/dsl_logo.png</file> <file>icons/logo.png</file> + <file>icons/checkbox.png</file> + <file>icons/radiobutton.png</file> </qresource> </RCC> diff --git a/DSLogic-gui/INSTALL b/DSLogic-gui/INSTALL index 4032ead..126579b 100644 --- a/DSLogic-gui/INSTALL +++ b/DSLogic-gui/INSTALL @@ -1,49 +1,49 @@ -------------------------------------------------------------------------------- -INSTALL -------------------------------------------------------------------------------- - -Requirements ------------- - - - git - - g++ - - make - - libtool - - pkg-config >= 0.22 - - cmake >= 2.6 - - libglib >= 2.28.0 - - Qt >= 4.5 - - libboost >= 1.42 (including the following libs): - - libboost-system - - libboost-thread - - libsigrok4DSLogic >= 0.2.0 - - -Building and installing ------------------------ -Get the DSLogic-gui source code from: www.dreamsourcelab.com/download.html -In order to build it, run: - - $ cd DSLogic-gui - $ cmake . - $ make - -For installing PulseView: - - $ make install - -See the following wiki page for more (OS-specific) instructions: - - http://sigrok.org/wiki/Building - - -Creating a source distribution package --------------------------------------- - -In order to build a source package begin with an unconfigured source tree. - - $ mkdir dist - $ cd dist - $ cmake .. - $ make package_source - +-------------------------------------------------------------------------------
+INSTALL
+-------------------------------------------------------------------------------
+
+Requirements
+------------
+
+ - git
+ - g++
+ - make
+ - libtool
+ - pkg-config >= 0.22
+ - cmake >= 2.6
+ - libglib >= 2.28.0
+ - Qt >= 4.5
+ - libboost >= 1.42 (including the following libs):
+ - libboost-system
+ - libboost-thread
+ - libsigrok4DSLogic >= 0.2.0
+
+
+Building and installing
+-----------------------
+Get the DSLogic-gui source code from: www.dreamsourcelab.com/download.html
+In order to build it, run:
+
+ $ cd DSLogic-gui
+ $ cmake .
+ $ make
+
+For installing PulseView:
+
+ $ make install
+
+See the following wiki page for more (OS-specific) instructions:
+
+ http://sigrok.org/wiki/Building
+
+
+Creating a source distribution package
+--------------------------------------
+
+In order to build a source package begin with an unconfigured source tree.
+
+ $ mkdir dist
+ $ cd dist
+ $ cmake ..
+ $ make package_source
+
diff --git a/DSLogic-gui/NEWS b/DSLogic-gui/NEWS index dbbe970..e7c2c79 100644 --- a/DSLogic-gui/NEWS +++ b/DSLogic-gui/NEWS @@ -1,5 +1,5 @@ -0.1.0 (2013-12-15) ------------------- - - * Initial release. - +0.1.0 (2013-12-15)
+------------------
+
+ * Initial release.
+
diff --git a/DSLogic-gui/extdef.h b/DSLogic-gui/extdef.h index 29ea8f5..467b561 100644 --- a/DSLogic-gui/extdef.h +++ b/DSLogic-gui/extdef.h @@ -1,7 +1,9 @@ /* - * This file is part of the PulseView project. + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. * * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk> + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +20,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + #ifndef DSLOGIC_EXTDEF_H #define DSLOGIC_EXTDEF_H diff --git a/DSLogic-gui/icons/checkbox.png b/DSLogic-gui/icons/checkbox.png Binary files differnew file mode 100644 index 0000000..8ca5395 --- /dev/null +++ b/DSLogic-gui/icons/checkbox.png diff --git a/DSLogic-gui/icons/radiobutton.png b/DSLogic-gui/icons/radiobutton.png Binary files differnew file mode 100644 index 0000000..85fe185 --- /dev/null +++ b/DSLogic-gui/icons/radiobutton.png diff --git a/DSLogic-gui/icons/©¦+¦ down-arrow.png b/DSLogic-gui/icons/ββ€ββ down-arrow.png Binary files differindex 602c191..602c191 100644 --- a/DSLogic-gui/icons/©¦+¦ down-arrow.png +++ b/DSLogic-gui/icons/ββ€ββ down-arrow.png diff --git a/DSLogic-gui/icons/©¦+¦ params.png b/DSLogic-gui/icons/ββ€ββ params.png Binary files differindex 8c4b2c8..8c4b2c8 100644 --- a/DSLogic-gui/icons/©¦+¦ params.png +++ b/DSLogic-gui/icons/ββ€ββ params.png diff --git a/DSLogic-gui/main.cpp b/DSLogic-gui/main.cpp index 04772d4..807f3ce 100644 --- a/DSLogic-gui/main.cpp +++ b/DSLogic-gui/main.cpp @@ -1,7 +1,9 @@ /* - * This file is part of the PulseView project. + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. * * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk> + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +20,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + #ifdef ENABLE_SIGROKDECODE #include <libsigrokdecode/libsigrokdecode.h> /* First, so we avoid a _POSIX_C_SOURCE warning. */ #endif @@ -58,9 +61,9 @@ int main(int argc, char *argv[]) QApplication a(argc, argv); // Set some application metadata - QApplication::setApplicationVersion(DS_VERSION_STRING); - QApplication::setApplicationName("DSLogic"); - QApplication::setOrganizationDomain("http://www.DreamSourceLab.com"); + QApplication::setApplicationVersion(DS_VERSION_STRING); + QApplication::setApplicationName("DSLogic(Beta)"); + QApplication::setOrganizationDomain("http://www.DreamSourceLab.com"); // Parse arguments while (1) { @@ -131,12 +134,11 @@ int main(int argc, char *argv[]) pv::DeviceManager device_manager(sr_ctx); // Initialise the main window - pv::MainWindow w(device_manager, open_file); - //QFile qss(":/levelfour.qss"); - QFile qss(":/stylesheet.qss"); - qss.open(QFile::ReadOnly); - a.setStyleSheet(qss.readAll()); - qss.close(); + pv::MainWindow w(device_manager, open_file); + QFile qss(":/stylesheet.qss"); + qss.open(QFile::ReadOnly); + a.setStyleSheet(qss.readAll()); + qss.close(); w.show(); // Run the application diff --git a/DSLogic-gui/pv/data/analog.cpp b/DSLogic-gui/pv/data/analog.cpp index a62e288..d4e6304 100644 --- a/DSLogic-gui/pv/data/analog.cpp +++ b/DSLogic-gui/pv/data/analog.cpp @@ -35,12 +35,12 @@ Analog::Analog(unsigned int num_probes, uint64_t samplerate) : { } -void Analog::push_snapshot(shared_ptr<AnalogSnapshot> &snapshot) +void Analog::push_snapshot(boost::shared_ptr<AnalogSnapshot> &snapshot) { _snapshots.push_front(snapshot); } -deque< shared_ptr<AnalogSnapshot> >& Analog::get_snapshots() +deque< boost::shared_ptr<AnalogSnapshot> >& Analog::get_snapshots() { return _snapshots; } diff --git a/DSLogic-gui/pv/data/analogsnapshot.cpp b/DSLogic-gui/pv/data/analogsnapshot.cpp index 3ff8e80..f613983 100644 --- a/DSLogic-gui/pv/data/analogsnapshot.cpp +++ b/DSLogic-gui/pv/data/analogsnapshot.cpp @@ -49,7 +49,7 @@ const uint64_t AnalogSnapshot::EnvelopeDataUnit = 64*1024; // bytes AnalogSnapshot::AnalogSnapshot(const sr_datafeed_analog &analog, uint64_t _total_sample_len, unsigned int channel_num) : Snapshot(sizeof(uint16_t), _total_sample_len, channel_num) { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); memset(_envelope_levels, 0, sizeof(_envelope_levels)); init(_total_sample_len * channel_num); append_payload(analog); @@ -57,7 +57,7 @@ AnalogSnapshot::AnalogSnapshot(const sr_datafeed_analog &analog, uint64_t _total AnalogSnapshot::~AnalogSnapshot() { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); BOOST_FOREACH(Envelope &e, _envelope_levels[0]) free(e.samples); } @@ -65,7 +65,7 @@ AnalogSnapshot::~AnalogSnapshot() void AnalogSnapshot::append_payload( const sr_datafeed_analog &analog) { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); append_data(analog.data, analog.num_samples); // Generate the first mip-map from the data @@ -81,7 +81,7 @@ const uint16_t* AnalogSnapshot::get_samples( assert(end_sample < (int64_t)get_sample_count()); assert(start_sample <= end_sample); - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); // uint16_t *const data = new uint16_t[end_sample - start_sample]; // memcpy(data, (uint16_t*)_data + start_sample, sizeof(uint16_t) * @@ -97,7 +97,7 @@ void AnalogSnapshot::get_envelope_section(EnvelopeSection &s, assert(start <= end); assert(min_length > 0); - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); const unsigned int min_level = max((int)floorf(logf(min_length) / LogEnvelopeScaleFactor) - 1, 0); diff --git a/DSLogic-gui/pv/data/dso.cpp b/DSLogic-gui/pv/data/dso.cpp new file mode 100644 index 0000000..fc967ff --- /dev/null +++ b/DSLogic-gui/pv/data/dso.cpp @@ -0,0 +1,48 @@ +/* + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. + * + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "dso.h" +#include "dsosnapshot.h" + +using namespace boost; +using namespace std; + +namespace pv { +namespace data { + +Dso::Dso(unsigned int num_probes, uint64_t samplerate) : + SignalData(num_probes, samplerate) +{ +} + +void Dso::push_snapshot(boost::shared_ptr<DsoSnapshot> &snapshot) +{ + _snapshots.push_front(snapshot); +} + +deque< boost::shared_ptr<DsoSnapshot> >& Dso::get_snapshots() +{ + return _snapshots; +} + +} // namespace data +} // namespace pv diff --git a/DSLogic-gui/pv/data/dso.h b/DSLogic-gui/pv/data/dso.h new file mode 100644 index 0000000..591fa27 --- /dev/null +++ b/DSLogic-gui/pv/data/dso.h @@ -0,0 +1,54 @@ +/* + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. + * + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef DSLOGIC_PV_DATA_DSO_H +#define DSLOGIC_PV_DATA_DSO_H + +#include "signaldata.h" + +#include <boost/shared_ptr.hpp> +#include <deque> + +namespace pv { +namespace data { + +class DsoSnapshot; + +class Dso : public SignalData +{ +public: + Dso(unsigned int num_probes, uint64_t samplerate); + + void push_snapshot( + boost::shared_ptr<DsoSnapshot> &snapshot); + + std::deque< boost::shared_ptr<DsoSnapshot> >& + get_snapshots(); + +private: + std::deque< boost::shared_ptr<DsoSnapshot> > _snapshots; +}; + +} // namespace data +} // namespace pv + +#endif // DSLOGIC_PV_DATA_DSO_H diff --git a/DSLogic-gui/pv/data/dsosnapshot.cpp b/DSLogic-gui/pv/data/dsosnapshot.cpp new file mode 100644 index 0000000..fb05e5d --- /dev/null +++ b/DSLogic-gui/pv/data/dsosnapshot.cpp @@ -0,0 +1,232 @@ +/* + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. + * + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include <extdef.h> + +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include <math.h> + +#include <algorithm> + +#include <boost/foreach.hpp> + +#include "dsosnapshot.h" + +using namespace boost; +using namespace std; + +namespace pv { +namespace data { + +const int DsoSnapshot::EnvelopeScalePower = 4; +const int DsoSnapshot::EnvelopeScaleFactor = 1 << EnvelopeScalePower; +const float DsoSnapshot::LogEnvelopeScaleFactor = + logf(EnvelopeScaleFactor); +const uint64_t DsoSnapshot::EnvelopeDataUnit = 64*1024; // bytes + +DsoSnapshot::DsoSnapshot(const sr_datafeed_dso &dso, uint64_t _total_sample_len, unsigned int channel_num) : + Snapshot(sizeof(uint16_t), _total_sample_len, channel_num) +{ + boost::lock_guard<boost::recursive_mutex> lock(_mutex); + memset(_envelope_levels, 0, sizeof(_envelope_levels)); + init(_total_sample_len * channel_num); + append_payload(dso); +} + +DsoSnapshot::~DsoSnapshot() +{ + boost::lock_guard<boost::recursive_mutex> lock(_mutex); + BOOST_FOREACH(Envelope &e, _envelope_levels[0]) + free(e.samples); +} + +void DsoSnapshot::append_payload(const sr_datafeed_dso &dso) +{ + boost::lock_guard<boost::recursive_mutex> lock(_mutex); + append_data(dso.data, dso.num_samples); + + // Generate the first mip-map from the data + append_payload_to_envelope_levels(); +} + +const uint8_t *DsoSnapshot::get_samples( + int64_t start_sample, int64_t end_sample, uint16_t index) const +{ + 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 <= end_sample); + + boost::lock_guard<boost::recursive_mutex> lock(_mutex); + +// uint16_t *const data = new uint16_t[end_sample - start_sample]; +// memcpy(data, (uint16_t*)_data + start_sample, sizeof(uint16_t) * +// (end_sample - start_sample)); +// return data; + return (uint8_t*)_data + start_sample * _channel_num + index; +} + +void DsoSnapshot::get_envelope_section(EnvelopeSection &s, + uint64_t start, uint64_t end, float min_length, int probe_index) const +{ + assert(end <= get_sample_count()); + assert(start <= end); + assert(min_length > 0); + + boost::lock_guard<boost::recursive_mutex> lock(_mutex); + + const unsigned int min_level = max((int)floorf(logf(min_length) / + LogEnvelopeScaleFactor) - 1, 0); + const unsigned int scale_power = (min_level + 1) * + EnvelopeScalePower; + start >>= scale_power; + end >>= scale_power; + + s.start = start << scale_power; + s.scale = 1 << scale_power; + s.length = end - start; +// s.samples = new EnvelopeSample[s.length]; +// memcpy(s.samples, _envelope_levels[min_level].samples + start, +// s.length * sizeof(EnvelopeSample)); + s.samples = _envelope_levels[probe_index][min_level].samples + start; +} + +void DsoSnapshot::reallocate_envelope(Envelope &e) +{ + const uint64_t new_data_length = ((e.length + EnvelopeDataUnit - 1) / + EnvelopeDataUnit) * EnvelopeDataUnit; + if (new_data_length > e.data_length) + { + e.data_length = new_data_length; + e.samples = (EnvelopeSample*)realloc(e.samples, + new_data_length * sizeof(EnvelopeSample)); + } +} + +void DsoSnapshot::append_payload_to_envelope_levels() +{ + unsigned int i; + for (i = 0; i < _channel_num; i++) { + Envelope &e0 = _envelope_levels[i][0]; + uint64_t prev_length; + EnvelopeSample *dest_ptr; + + // Expand the data buffer to fit the new samples + prev_length = e0.length; + e0.length = get_sample_count() / EnvelopeScaleFactor; + + // Break off if there are no new samples to compute + // if (e0.length == prev_length) + // return; + if (e0.length == 0) + return; + if (e0.length == prev_length) + prev_length = 0; + + reallocate_envelope(e0); + + dest_ptr = e0.samples + prev_length; + + // Iterate through the samples to populate the first level mipmap + const uint8_t *const stop_src_ptr = (uint8_t*)_data + + e0.length * EnvelopeScaleFactor * _channel_num; +// for (const uint16_t *src_ptr = (uint16_t*)_data + +// prev_length * EnvelopeScaleFactor; +// src_ptr < end_src_ptr; src_ptr += EnvelopeScaleFactor) +// { +// const EnvelopeSample sub_sample = { +// *min_element(src_ptr, src_ptr + EnvelopeScaleFactor), +// *max_element(src_ptr, src_ptr + EnvelopeScaleFactor), +// }; + +// *dest_ptr++ = sub_sample; +// } + for (const uint8_t *src_ptr = (uint8_t*)_data + + prev_length * EnvelopeScaleFactor * _channel_num + i; + src_ptr < stop_src_ptr; src_ptr += EnvelopeScaleFactor * _channel_num) + { + const uint8_t * begin_src_ptr = + src_ptr; + const uint8_t *const end_src_ptr = + src_ptr + EnvelopeScaleFactor * _channel_num; + + EnvelopeSample sub_sample; + sub_sample.min = *begin_src_ptr; + sub_sample.max = *begin_src_ptr; + begin_src_ptr += _channel_num; + while (begin_src_ptr < end_src_ptr) + { + sub_sample.min = min(sub_sample.min, *begin_src_ptr); + sub_sample.max = max(sub_sample.max, *begin_src_ptr); + begin_src_ptr += _channel_num; + } + + *dest_ptr++ = sub_sample; + } + + // Compute higher level mipmaps + for (unsigned int level = 1; level < ScaleStepCount; level++) + { + Envelope &e = _envelope_levels[i][level]; + const Envelope &el = _envelope_levels[i][level-1]; + + // Expand the data buffer to fit the new samples + prev_length = e.length; + e.length = el.length / EnvelopeScaleFactor; + + // Break off if there are no more samples to computed + // if (e.length == prev_length) + // break; + if (e.length == prev_length) + prev_length = 0; + + reallocate_envelope(e); + + // Subsample the level lower level + const EnvelopeSample *src_ptr = + el.samples + prev_length * EnvelopeScaleFactor; + const EnvelopeSample *const end_dest_ptr = e.samples + e.length; + for (dest_ptr = e.samples + prev_length; + dest_ptr < end_dest_ptr; dest_ptr++) + { + const EnvelopeSample *const end_src_ptr = + src_ptr + EnvelopeScaleFactor; + + EnvelopeSample sub_sample = *src_ptr++; + while (src_ptr < end_src_ptr) + { + sub_sample.min = min(sub_sample.min, src_ptr->min); + sub_sample.max = max(sub_sample.max, src_ptr->max); + src_ptr++; + } + + *dest_ptr = sub_sample; + } + } + } +} + +} // namespace data +} // namespace pv diff --git a/DSLogic-gui/pv/data/dsosnapshot.h b/DSLogic-gui/pv/data/dsosnapshot.h new file mode 100644 index 0000000..155dd72 --- /dev/null +++ b/DSLogic-gui/pv/data/dsosnapshot.h @@ -0,0 +1,97 @@ +/* + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. + * + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef DSLOGIC_PV_DATA_DSOSNAPSHOT_H +#define DSLOGIC_PV_DATA_DSOSNAPSHOT_H + +#include "snapshot.h" + +#include <utility> +#include <vector> + +namespace DsoSnapshotTest { +class Basic; +} + +namespace pv { +namespace data { + +class DsoSnapshot : public Snapshot +{ +public: + struct EnvelopeSample + { + uint8_t min; + uint8_t max; + }; + + struct EnvelopeSection + { + uint64_t start; + unsigned int scale; + uint64_t length; + EnvelopeSample *samples; + }; + +private: + struct Envelope + { + uint64_t length; + uint64_t data_length; + EnvelopeSample *samples; + }; + +private: + static const unsigned int ScaleStepCount = 10; + static const int EnvelopeScalePower; + static const int EnvelopeScaleFactor; + static const float LogEnvelopeScaleFactor; + static const uint64_t EnvelopeDataUnit; + +public: + DsoSnapshot(const sr_datafeed_dso &dso, uint64_t _total_sample_len, unsigned int channel_num); + + virtual ~DsoSnapshot(); + + void append_payload(const sr_datafeed_dso &dso); + + const uint8_t* get_samples(int64_t start_sample, + int64_t end_sample, uint16_t index) const; + + void get_envelope_section(EnvelopeSection &s, + uint64_t start, uint64_t end, float min_length, int probe_index) const; + +private: + void reallocate_envelope(Envelope &l); + + void append_payload_to_envelope_levels(); + +private: + struct Envelope _envelope_levels[2*DS_MAX_DSO_PROBES_NUM][ScaleStepCount]; + + friend class DsoSnapshotTest::Basic; +}; + +} // namespace data +} // namespace pv + +#endif // DSLOGIC_PV_DATA_DSOSNAPSHOT_H diff --git a/DSLogic-gui/pv/data/group.cpp b/DSLogic-gui/pv/data/group.cpp index 26cccd7..6df3ee8 100644 --- a/DSLogic-gui/pv/data/group.cpp +++ b/DSLogic-gui/pv/data/group.cpp @@ -35,12 +35,12 @@ Group::Group(unsigned int num_probes, uint64_t samplerate) : { } -void Group::push_snapshot(shared_ptr<GroupSnapshot> &snapshot) +void Group::push_snapshot(boost::shared_ptr<GroupSnapshot> &snapshot) { _snapshots.push_back(snapshot); } -deque< shared_ptr<GroupSnapshot> >& Group::get_snapshots() +deque< boost::shared_ptr<GroupSnapshot> >& Group::get_snapshots() { return _snapshots; } diff --git a/DSLogic-gui/pv/data/groupsnapshot.cpp b/DSLogic-gui/pv/data/groupsnapshot.cpp index d46da5b..939ffca 100644 --- a/DSLogic-gui/pv/data/groupsnapshot.cpp +++ b/DSLogic-gui/pv/data/groupsnapshot.cpp @@ -51,11 +51,11 @@ const uint16_t GroupSnapshot::value_mask[16] = {0x1, 0x2, 0x4, 0x8, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000}; -GroupSnapshot::GroupSnapshot(const shared_ptr<LogicSnapshot> &_logic_snapshot, std::list<int> index_list) +GroupSnapshot::GroupSnapshot(const boost::shared_ptr<LogicSnapshot> &_logic_snapshot, std::list<int> index_list) { assert(_logic_snapshot); - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); memset(_envelope_levels, 0, sizeof(_envelope_levels)); _data = _logic_snapshot->get_data(); _sample_count = _logic_snapshot->get_sample_count(); @@ -66,20 +66,20 @@ GroupSnapshot::GroupSnapshot(const shared_ptr<LogicSnapshot> &_logic_snapshot, s GroupSnapshot::~GroupSnapshot() { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); BOOST_FOREACH(Envelope &e, _envelope_levels) free(e.samples); } uint64_t GroupSnapshot::get_sample_count() const { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); return _sample_count; } void GroupSnapshot::append_payload() { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); // Generate the first mip-map from the data append_payload_to_envelope_levels(); @@ -96,7 +96,7 @@ const uint16_t* GroupSnapshot::get_samples( int64_t i; uint64_t pow; - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); uint16_t *const data = new uint16_t[end_sample - start_sample]; // memcpy(data, (uint16_t*)_data + start_sample, sizeof(uint16_t) * @@ -121,7 +121,7 @@ void GroupSnapshot::get_envelope_section(EnvelopeSection &s, assert(start <= end); assert(min_length > 0); - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); const unsigned int min_level = max((int)floorf(logf(min_length) / LogEnvelopeScaleFactor) - 1, 0); diff --git a/DSLogic-gui/pv/data/logic.cpp b/DSLogic-gui/pv/data/logic.cpp index 036cc54..4cdfe2a 100644 --- a/DSLogic-gui/pv/data/logic.cpp +++ b/DSLogic-gui/pv/data/logic.cpp @@ -37,12 +37,12 @@ Logic::Logic(unsigned int num_probes, uint64_t samplerate) : } void Logic::push_snapshot( - shared_ptr<LogicSnapshot> &snapshot) + boost::shared_ptr<LogicSnapshot> &snapshot) { _snapshots.push_front(snapshot); } -deque< shared_ptr<LogicSnapshot> >& Logic::get_snapshots() +deque< boost::shared_ptr<LogicSnapshot> >& Logic::get_snapshots() { return _snapshots; } diff --git a/DSLogic-gui/pv/data/logicsnapshot.cpp b/DSLogic-gui/pv/data/logicsnapshot.cpp index e01386a..9a6b2d2 100644 --- a/DSLogic-gui/pv/data/logicsnapshot.cpp +++ b/DSLogic-gui/pv/data/logicsnapshot.cpp @@ -47,7 +47,7 @@ LogicSnapshot::LogicSnapshot(const sr_datafeed_logic &logic, uint64_t _total_sam Snapshot(logic.unitsize, _total_sample_len, channel_num), _last_append_sample(0) { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); memset(_mip_map, 0, sizeof(_mip_map)); if (init(_total_sample_len * channel_num) == SR_OK) append_payload(logic); @@ -55,7 +55,7 @@ LogicSnapshot::LogicSnapshot(const sr_datafeed_logic &logic, uint64_t _total_sam LogicSnapshot::~LogicSnapshot() { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); BOOST_FOREACH(MipMapLevel &l, _mip_map) free(l.data); } @@ -66,7 +66,7 @@ void LogicSnapshot::append_payload( assert(_unit_size == logic.unitsize); assert((logic.length % _unit_size) == 0); - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); append_data(logic.data, logic.length / _unit_size); @@ -194,7 +194,7 @@ void LogicSnapshot::get_subsampled_edges( assert(sig_index >= 0); assert(sig_index < 64); - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); const uint64_t block_length = (uint64_t)max(min_length, 1.0f); const unsigned int min_level = max((int)floorf(logf(min_length) / @@ -378,7 +378,7 @@ int LogicSnapshot::get_first_edge( assert(sig_index >= 0); assert(sig_index < 64); - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); const uint64_t block_length = 1; const unsigned int min_level = 0; @@ -550,7 +550,7 @@ void LogicSnapshot::get_edges( assert(sig_index >= 0); assert(sig_index < 64); - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); const uint64_t block_length = 1; const unsigned int min_level = 0; @@ -706,7 +706,7 @@ uint64_t LogicSnapshot::get_min_pulse(uint64_t start, uint64_t end, int sig_inde assert(sig_index >= 0); assert(sig_index < 64); - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); const uint64_t block_length = 1; const unsigned int min_level = 0; diff --git a/DSLogic-gui/pv/data/snapshot.cpp b/DSLogic-gui/pv/data/snapshot.cpp index 8cf4b6f..f05452a 100644 --- a/DSLogic-gui/pv/data/snapshot.cpp +++ b/DSLogic-gui/pv/data/snapshot.cpp @@ -40,13 +40,13 @@ Snapshot::Snapshot(int unit_size, uint64_t total_sample_count, unsigned int chan _ring_sample_count(0), _unit_size(unit_size) { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); assert(_unit_size > 0); } Snapshot::~Snapshot() { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); if (_data != NULL) free(_data); _data = NULL; @@ -73,31 +73,31 @@ bool Snapshot::buf_null() const uint64_t Snapshot::get_sample_count() const { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); return _sample_count / _channel_num; } void* Snapshot::get_data() const { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); return _data; } int Snapshot::get_unit_size() const { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); return _unit_size; } unsigned int Snapshot::get_channel_num() const { - lock_guard<recursive_mutex> lock(_mutex); + boost::lock_guard<boost::recursive_mutex> lock(_mutex); return _channel_num; } void Snapshot::append_data(void *data, uint64_t samples) { -// lock_guard<recursive_mutex> lock(_mutex); +// boost::lock_guard<boost::recursive_mutex> lock(_mutex); // _data = realloc(_data, (_sample_count + samples) * _unit_size + // sizeof(uint64_t)); if (_sample_count + samples < _total_sample_count) diff --git a/DSLogic-gui/pv/decoder/ds1wire.cpp b/DSLogic-gui/pv/decoder/ds1wire.cpp index 1f8d759..04d3ec3 100644 --- a/DSLogic-gui/pv/decoder/ds1wire.cpp +++ b/DSLogic-gui/pv/decoder/ds1wire.cpp @@ -53,7 +53,7 @@ const QString ds1Wire::StateTable[TableSize] = { "DATA" }; -ds1Wire::ds1Wire(shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : +ds1Wire::ds1Wire(boost::shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : Decoder(data, _sel_probes, _options_index) { (void)_options; @@ -91,12 +91,12 @@ void ds1Wire::decode() _max_width = 0; uint8_t cur_state = Unknown; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); uint64_t flag_index1; @@ -336,11 +336,11 @@ void ds1Wire::get_subsampled_states(std::vector<struct ds_view_state> &states, { ds_view_state view_state; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); assert(end <= snapshot->get_sample_count()); diff --git a/DSLogic-gui/pv/decoder/dsdmx512.cpp b/DSLogic-gui/pv/decoder/dsdmx512.cpp index 19894ec..846f283 100644 --- a/DSLogic-gui/pv/decoder/dsdmx512.cpp +++ b/DSLogic-gui/pv/decoder/dsdmx512.cpp @@ -53,7 +53,7 @@ const QString dsDmx512::StateTable[TableSize] = { "SLOT" }; -dsDmx512::dsDmx512(shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : +dsDmx512::dsDmx512(boost::shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : Decoder(data, _sel_probes, _options_index) { (void)_options; @@ -91,12 +91,12 @@ void dsDmx512::decode() _max_width = 0; uint8_t cur_state = Unknown; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); //uint64_t flag_index; @@ -261,11 +261,11 @@ void dsDmx512::get_subsampled_states(std::vector<struct ds_view_state> &states, { ds_view_state view_state; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); assert(end <= snapshot->get_sample_count()); diff --git a/DSLogic-gui/pv/decoder/dsi2c.cpp b/DSLogic-gui/pv/decoder/dsi2c.cpp index 9f61b86..b2bc440 100644 --- a/DSLogic-gui/pv/decoder/dsi2c.cpp +++ b/DSLogic-gui/pv/decoder/dsi2c.cpp @@ -52,7 +52,7 @@ const QString dsI2c::StateTable[TableSize] = { "DATA" }; -dsI2c::dsI2c(shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : +dsI2c::dsI2c(boost::shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : Decoder(data, _sel_probes, _options_index) { (void)_options; @@ -91,12 +91,12 @@ void dsI2c::decode() _max_width = 0; uint8_t cur_state = Unknown; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); uint64_t flag_index; @@ -185,7 +185,7 @@ void dsI2c::cmd_decode(const boost::shared_ptr<data::LogicSnapshot> &snapshot) } } -void dsI2c::data_decode(const shared_ptr<data::LogicSnapshot> &snapshot) +void dsI2c::data_decode(const boost::shared_ptr<data::LogicSnapshot> &snapshot) { uint8_t cur_state; const uint8_t *src_ptr; @@ -246,11 +246,11 @@ void dsI2c::get_subsampled_states(std::vector<struct ds_view_state> &states, { ds_view_state view_state; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); assert(end <= snapshot->get_sample_count()); diff --git a/DSLogic-gui/pv/decoder/dsserial.cpp b/DSLogic-gui/pv/decoder/dsserial.cpp index 5b23186..aee9a4c 100644 --- a/DSLogic-gui/pv/decoder/dsserial.cpp +++ b/DSLogic-gui/pv/decoder/dsserial.cpp @@ -53,7 +53,7 @@ const QString dsSerial::StateTable[TableSize] = { "DATA" }; -dsSerial::dsSerial(shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : +dsSerial::dsSerial(boost::shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : Decoder(data, _sel_probes, _options_index) { assert(_sel_probes.size() == 1); @@ -102,12 +102,12 @@ void dsSerial::decode() assert(_data); uint8_t cur_state = Unknown; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); uint64_t flag_index; @@ -117,7 +117,7 @@ void dsSerial::decode() uint64_t left = 0; uint64_t right = snapshot->get_sample_count() - 1; float samplesPerBit; - int sampleOffset; + //int sampleOffset; int i; _max_width = 0; _min_width = right; @@ -127,7 +127,7 @@ void dsSerial::decode() samplesPerBit = _data->get_samplerate() * 1.0f / _baudrate; else samplesPerBit = snapshot->get_min_pulse(left, right, _serial_index); - sampleOffset = samplesPerBit / 2; + //sampleOffset = samplesPerBit / 2; if (!_state_index.empty()) _state_index.clear(); @@ -174,7 +174,7 @@ void dsSerial::decode() } -void dsSerial::data_decode(const shared_ptr<data::LogicSnapshot> &snapshot, uint64_t start, uint64_t stop, float samplesPerBit) +void dsSerial::data_decode(const boost::shared_ptr<data::LogicSnapshot> &snapshot, uint64_t start, uint64_t stop, float samplesPerBit) { (void)stop; @@ -238,11 +238,11 @@ void dsSerial::get_subsampled_states(std::vector<struct ds_view_state> &states, { ds_view_state view_state; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); assert(end <= snapshot->get_sample_count()); diff --git a/DSLogic-gui/pv/decoder/dsspi.cpp b/DSLogic-gui/pv/decoder/dsspi.cpp index 88ff8db..3b95507 100644 --- a/DSLogic-gui/pv/decoder/dsspi.cpp +++ b/DSLogic-gui/pv/decoder/dsspi.cpp @@ -45,7 +45,7 @@ const QString dsSpi::StateTable[TableSize] = { "DATA" }; -dsSpi::dsSpi(shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : +dsSpi::dsSpi(boost::shared_ptr<data::Logic> data, std::list <int > _sel_probes, QMap<QString, QVariant> &_options, QMap<QString, int> _options_index) : Decoder(data, _sel_probes, _options_index) { _cpol = _options.value("cpol").toBool(); @@ -125,12 +125,12 @@ void dsSpi::decode() _max_width = 0; uint8_t cur_state = Unknown; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); const uint64_t ssn_mask = 1ULL << _ssn_index; @@ -191,7 +191,7 @@ void dsSpi::decode() } } -void dsSpi::data_decode(const shared_ptr<data::LogicSnapshot> &snapshot) +void dsSpi::data_decode(const boost::shared_ptr<data::LogicSnapshot> &snapshot) { uint8_t cur_state; const uint8_t *src_ptr; @@ -256,11 +256,11 @@ void dsSpi::get_subsampled_states(std::vector<struct ds_view_state> &states, { ds_view_state view_state; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); assert(end <= snapshot->get_sample_count()); diff --git a/DSLogic-gui/pv/devicemanager.cpp b/DSLogic-gui/pv/devicemanager.cpp index 4a17ca9..66e3500 100644 --- a/DSLogic-gui/pv/devicemanager.cpp +++ b/DSLogic-gui/pv/devicemanager.cpp @@ -29,12 +29,15 @@ #include <stdexcept> #include <string> +#include <QtGui/QApplication> #include <QObject> #include <QDebug> +#include <QDir> #include <libsigrok4DSLogic/libsigrok.h> using namespace std; +char config_path[256]; namespace pv { @@ -98,6 +101,15 @@ list<sr_dev_inst*> DeviceManager::driver_scan( // Release this driver and all it's attached devices release_driver(driver); + // Check If DSLogic driver + if (strcmp(driver->name, "DSLogic") == 0) { + QDir dir(QApplication::applicationDirPath()); + if (!dir.cd("res")) + return driver_devices; + std::string str = dir.absolutePath().toStdString() + "/"; + strcpy(config_path, str.c_str()); + } + // Do the scan GSList *const devices = sr_driver_scan(driver, drvopts); for (GSList *l = devices; l; l = l->next) diff --git a/DSLogic-gui/pv/dialogs/deviceoptions.cpp b/DSLogic-gui/pv/dialogs/deviceoptions.cpp index 75023c3..726fc92 100644 --- a/DSLogic-gui/pv/dialogs/deviceoptions.cpp +++ b/DSLogic-gui/pv/dialogs/deviceoptions.cpp @@ -50,7 +50,9 @@ DeviceOptions::DeviceOptions(QWidget *parent, struct sr_dev_inst *sdi) : setWindowTitle(tr("Configure Device")); setLayout(&_layout); + _last_mode = sdi->mode; _mode_comboBox.addItem(mode_strings[LOGIC]); + _mode_comboBox.addItem(mode_strings[DSO]); _mode_comboBox.addItem(mode_strings[ANALOG]); _mode_comboBox.setCurrentIndex(_sdi->mode); _props_box.setLayout(&_props_box_layout); @@ -77,10 +79,11 @@ void DeviceOptions::accept() QDialog::accept(); + _last_mode = _sdi->mode; // Commit the properties - const vector< shared_ptr<pv::prop::Property> > &properties = + const vector< boost::shared_ptr<pv::prop::Property> > &properties = _device_options_binding.properties(); - BOOST_FOREACH(shared_ptr<pv::prop::Property> p, properties) { + BOOST_FOREACH(boost::shared_ptr<pv::prop::Property> p, properties) { assert(p); p->commit(); } @@ -96,6 +99,15 @@ void DeviceOptions::accept() } } +void DeviceOptions::reject() +{ + using namespace Qt; + QDialog::reject(); + + // Mode Recovery + sr_config_set(_sdi, SR_CONF_DEVICE_MODE, g_variant_new_string(_mode_comboBox.itemText(_last_mode).toLocal8Bit())); +} + QWidget* DeviceOptions::get_property_form() { QWidget *const form = new QWidget(this); @@ -103,9 +115,9 @@ QWidget* DeviceOptions::get_property_form() form->setLayout(layout); layout->addRow("Device Mode", &_mode_comboBox); - const vector< shared_ptr<pv::prop::Property> > &properties = + const vector< boost::shared_ptr<pv::prop::Property> > &properties = _device_options_binding.properties(); - BOOST_FOREACH(shared_ptr<pv::prop::Property> p, properties) + BOOST_FOREACH(boost::shared_ptr<pv::prop::Property> p, properties) { assert(p); const QString label = p->labeled_widget() ? QString() : p->name(); @@ -182,7 +194,9 @@ void DeviceOptions::disable_all_probes() void DeviceOptions::mode_changed(QString mode) { - sr_config_set(_sdi, SR_CONF_DEVICE_MODE, g_variant_new_string(mode.toLocal8Bit())); + (void)mode; + // Commit mode + sr_config_set(_sdi, SR_CONF_DEVICE_MODE, g_variant_new_string(_mode_comboBox.currentText().toLocal8Bit())); setup_probes(); } diff --git a/DSLogic-gui/pv/dialogs/deviceoptions.h b/DSLogic-gui/pv/dialogs/deviceoptions.h index 2ee2534..ad804d2 100644 --- a/DSLogic-gui/pv/dialogs/deviceoptions.h +++ b/DSLogic-gui/pv/dialogs/deviceoptions.h @@ -51,6 +51,7 @@ public: protected: void accept(); + void reject(); private: @@ -67,6 +68,7 @@ private slots: private: struct sr_dev_inst *const _sdi; + int _last_mode; QVBoxLayout _layout; diff --git a/DSLogic-gui/pv/dialogs/search.cpp b/DSLogic-gui/pv/dialogs/search.cpp index 50c15c9..5945491 100644 --- a/DSLogic-gui/pv/dialogs/search.cpp +++ b/DSLogic-gui/pv/dialogs/search.cpp @@ -22,33 +22,55 @@ #include "search.h"
-#include "ui_search.h"
#include <assert.h>
+#include <QRegExpValidator>
namespace pv {
namespace dialogs {
Search::Search(QWidget *parent, struct sr_dev_inst *sdi, QString pattern) :
QDialog(parent),
- ui(new Ui::Search),
_sdi(sdi)
{
assert(_sdi);
- ui->setupUi(this);
+
+ QFont font("Monaco");
+ font.setStyleHint(QFont::Monospace);
+ font.setFixedPitch(true);
QRegExp value_rx("[10XRFCxrfc ]+");
QValidator *value_validator = new QRegExpValidator(value_rx, this);
- //ui->_value_lineEdit->setText("X X X X X X X X X X X X X X X X");
- ui->_value_lineEdit->setText(pattern);
- ui->_value_lineEdit->setValidator(value_validator);
- ui->_value_lineEdit->setMaxLength(16 * 2 - 1);
- ui->_value_lineEdit->setInputMask("X X X X X X X X X X X X X X X X");
+
+ 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\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->addWidget(search_label, 0, 1);
+ search_layout->addWidget(new QLabel("Search Value: "), 1,0, Qt::AlignRight);
+ search_layout->addWidget(&search_lineEdit, 1, 1);
+ search_layout->addWidget(new QLabel(" "), 2,0);
+ search_layout->addWidget(new QLabel("X: Don't care\n0: Low level\n1: High level\nR: Rising edge\nF: Falling edge\nC: Rising/Falling edge"), 3, 0);
+ search_layout->addWidget(&search_buttonBox, 4, 2);
+ //search_layout->addStretch(1);
+
+ setLayout(search_layout);
+
+ connect(&search_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(&search_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
}
Search::~Search()
{
- delete ui;
}
void Search::accept()
@@ -60,7 +82,7 @@ void Search::accept() QString Search::get_pattern()
{
- QString pattern = ui->_value_lineEdit->text();
+ QString pattern = search_lineEdit.text();
//pattern.remove(QChar('/r'), Qt::CaseInsensitive);
return pattern;
}
diff --git a/DSLogic-gui/pv/dialogs/search.h b/DSLogic-gui/pv/dialogs/search.h index a4dea4c..07c3312 100644 --- a/DSLogic-gui/pv/dialogs/search.h +++ b/DSLogic-gui/pv/dialogs/search.h @@ -27,13 +27,12 @@ #include <QDialog>
#include <QLabel>
#include <QLineEdit>
+#include <QVBoxLayout>
+#include <QGridLayout>
+#include <QDialogButtonBox>
#include "../sigsession.h"
#include <libsigrok4DSLogic/libsigrok.h>
-namespace Ui {
-class Search;
-}
-
namespace pv {
namespace dialogs {
@@ -56,7 +55,8 @@ signals: public slots:
private:
- Ui::Search *ui;
+ QLineEdit search_lineEdit;
+ QDialogButtonBox search_buttonBox;
sr_dev_inst *_sdi;
};
diff --git a/DSLogic-gui/pv/dock/dsotriggerdock.cpp b/DSLogic-gui/pv/dock/dsotriggerdock.cpp new file mode 100644 index 0000000..d8f8277 --- /dev/null +++ b/DSLogic-gui/pv/dock/dsotriggerdock.cpp @@ -0,0 +1,196 @@ +/*
+ * This file is part of the DSLogic-gui project.
+ * DSLogic-gui is based on PulseView.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "dsotriggerdock.h"
+#include "../sigsession.h"
+
+#include <QObject>
+#include <QLabel>
+#include <QRadioButton>
+#include <QPainter>
+#include <QStyleOption>
+#include <QMessageBox>
+
+#include <QVector>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+
+#include "libsigrok4DSLogic/libsigrok.h"
+
+namespace pv {
+namespace dock {
+
+DsoTriggerDock::DsoTriggerDock(QWidget *parent, SigSession &session) :
+ QWidget(parent),
+ _session(session)
+{
+ QLabel *position_label = new QLabel("Trigger Position: ", this);
+ position_spinBox = new QSpinBox(this);
+ position_spinBox->setRange(0, 99);
+ position_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+ position_slider = new QSlider(Qt::Horizontal, this);
+ position_slider->setRange(0, 99);
+ connect(position_slider, SIGNAL(valueChanged(int)), position_spinBox, SLOT(setValue(int)));
+ connect(position_spinBox, SIGNAL(valueChanged(int)), position_slider, SLOT(setValue(int)));
+ connect(position_slider, SIGNAL(valueChanged(int)), this, SLOT(pos_changed(int)));
+
+ QLabel *tSource_labe = new QLabel("Trigger Sources: ", this);
+ QRadioButton *auto_radioButton = new QRadioButton("Auto");
+ auto_radioButton->setChecked(true);
+ QRadioButton *ch0_radioButton = new QRadioButton("Channel 0");
+ QRadioButton *ch1_radioButton = new QRadioButton("Channel 1");
+ QRadioButton *ch0a1_radioButton = new QRadioButton("Channel 0 && Channel 1");
+ QRadioButton *ch0o1_radioButton = new QRadioButton("Channel 0 | Channel 1");
+ connect(auto_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
+ connect(ch0_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
+ connect(ch1_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
+ connect(ch0a1_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
+ connect(ch0o1_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
+
+ QLabel *tType_labe = new QLabel("Trigger Types: ", this);
+ QRadioButton *rising_radioButton = new QRadioButton("Rising Edge");
+ rising_radioButton->setChecked(true);
+ QRadioButton *falling_radioButton = new QRadioButton("Falling Edge");
+ connect(rising_radioButton, SIGNAL(clicked()), this, SLOT(type_changed()));
+ connect(falling_radioButton, SIGNAL(clicked()), this, SLOT(type_changed()));
+
+ source_group=new QButtonGroup(this);
+ type_group=new QButtonGroup(this);
+
+ source_group->addButton(auto_radioButton);
+ source_group->addButton(ch0_radioButton);
+ source_group->addButton(ch1_radioButton);
+ source_group->addButton(ch0a1_radioButton);
+ source_group->addButton(ch0o1_radioButton);
+ source_group->setId(auto_radioButton, DSO_TRIGGER_AUTO);
+ source_group->setId(ch0_radioButton, DSO_TRIGGER_CH0);
+ source_group->setId(ch1_radioButton, DSO_TRIGGER_CH1);
+ source_group->setId(ch0a1_radioButton, DSO_TRIGGER_CH0A1);
+ source_group->setId(ch0o1_radioButton, DSO_TRIGGER_CH0O1);
+
+ type_group->addButton(rising_radioButton);
+ type_group->addButton(falling_radioButton);
+ type_group->setId(rising_radioButton, DSO_TRIGGER_RISING);
+ type_group->setId(falling_radioButton, DSO_TRIGGER_FALLING);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ QGridLayout *gLayout = new QGridLayout();
+ gLayout->addWidget(position_label, 0, 0);
+ gLayout->addWidget(position_spinBox, 0, 1);
+ gLayout->addWidget(new QLabel(this), 0, 2);
+ gLayout->addWidget(position_slider, 1, 0, 1, 3);
+
+ gLayout->addWidget(new QLabel(this), 2, 0);
+ gLayout->addWidget(tSource_labe, 3, 0);
+ gLayout->addWidget(auto_radioButton, 4, 0);
+ gLayout->addWidget(ch0_radioButton, 5, 0);
+ gLayout->addWidget(ch1_radioButton, 5, 1);
+ gLayout->addWidget(ch0a1_radioButton, 6, 0);
+ gLayout->addWidget(ch0o1_radioButton, 6, 1);
+
+ gLayout->addWidget(new QLabel(this), 7, 0);
+ gLayout->addWidget(tType_labe, 8, 0);
+ gLayout->addWidget(rising_radioButton, 9, 0);
+ gLayout->addWidget(falling_radioButton, 10, 0);
+
+ gLayout->setColumnStretch(3, 1);
+
+ layout->addLayout(gLayout);
+ layout->addStretch(1);
+ setLayout(layout);
+}
+
+DsoTriggerDock::~DsoTriggerDock()
+{
+}
+
+void DsoTriggerDock::paintEvent(QPaintEvent *)
+{
+ QStyleOption opt;
+ opt.init(this);
+ QPainter p(this);
+ style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+}
+
+void DsoTriggerDock::pos_changed(int pos)
+{
+ int ret;
+ quint32 real_pos;
+ real_pos = pos*_session.get_total_sample_len()/100.0f;
+ real_pos = (_session.get_last_sample_rate() > SR_MHZ(100)) ? real_pos/2 : real_pos;
+ ret = sr_config_set(_session.get_device(), SR_CONF_HORIZ_TRIGGERPOS, g_variant_new_uint32(real_pos));
+ if (ret != SR_OK) {
+ QMessageBox msg(this);
+ msg.setText("Trigger Setting Issue");
+ msg.setInformativeText("Change horiz trigger position failed!");
+ msg.setStandardButtons(QMessageBox::Ok);
+ msg.setIcon(QMessageBox::Warning);
+ msg.exec();
+ }
+}
+
+void DsoTriggerDock::source_changed()
+{
+ int id = source_group->checkedId();
+ int ret;
+
+ ret = sr_config_set(_session.get_device(), SR_CONF_TRIGGER_SOURCE, g_variant_new_byte(id));
+ if (ret != SR_OK) {
+ QMessageBox msg(this);
+ msg.setText("Trigger Setting Issue");
+ msg.setInformativeText("Change trigger source failed!");
+ msg.setStandardButtons(QMessageBox::Ok);
+ msg.setIcon(QMessageBox::Warning);
+ msg.exec();
+ }
+}
+
+void DsoTriggerDock::type_changed()
+{
+ int id = type_group->checkedId();
+ int ret;
+
+ ret = sr_config_set(_session.get_device(), SR_CONF_TRIGGER_SLOPE, g_variant_new_byte(id));
+ if (ret != SR_OK) {
+ QMessageBox msg(this);
+ msg.setText("Trigger Setting Issue");
+ msg.setInformativeText("Change trigger type failed!");
+ msg.setStandardButtons(QMessageBox::Ok);
+ msg.setIcon(QMessageBox::Warning);
+ msg.exec();
+ }
+}
+
+void DsoTriggerDock::device_change()
+{
+ if (strcmp(_session.get_device()->driver->name, "DSLogic") != 0) {
+ position_spinBox->setDisabled(true);
+ position_slider->setDisabled(true);
+ } else {
+ position_spinBox->setDisabled(false);
+ position_slider->setDisabled(false);
+ }
+}
+
+} // namespace dock
+} // namespace pv
diff --git a/DSLogic-gui/pv/dock/dsotriggerdock.h b/DSLogic-gui/pv/dock/dsotriggerdock.h new file mode 100644 index 0000000..5c135c4 --- /dev/null +++ b/DSLogic-gui/pv/dock/dsotriggerdock.h @@ -0,0 +1,76 @@ +/*
+ * This file is part of the DSLogic-gui project.
+ * DSLogic-gui is based on PulseView.
+ *
+ * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
+ * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef DSLOGIC_PV_DSOTRIGGERDOCK_H
+#define DSLOGIC_PV_DSOTRIGGERDOCK_H
+
+#include <QDockWidget>
+#include <QSlider>
+#include <QSpinBox>
+#include <QButtonGroup>
+
+#include <vector>
+
+#include <libsigrok4DSLogic/libsigrok.h>
+
+namespace pv {
+
+class SigSession;
+
+namespace dock {
+
+class DsoTriggerDock : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DsoTriggerDock(QWidget *parent, SigSession &session);
+ ~DsoTriggerDock();
+
+ void paintEvent(QPaintEvent *);
+
+ void device_change();
+
+signals:
+
+private slots:
+ void pos_changed(int pos);
+ void source_changed();
+ void type_changed();
+
+private:
+
+private:
+ SigSession &_session;
+
+ QSpinBox *position_spinBox;
+ QSlider *position_slider;
+
+ QButtonGroup *source_group;
+ QButtonGroup *type_group;
+};
+
+} // namespace dock
+} // namespace pv
+
+#endif // DSLOGIC_PV_DSOTRIGGERDOCK_H
diff --git a/DSLogic-gui/pv/dock/measuredock.cpp b/DSLogic-gui/pv/dock/measuredock.cpp index e2ab59d..43c43cf 100644 --- a/DSLogic-gui/pv/dock/measuredock.cpp +++ b/DSLogic-gui/pv/dock/measuredock.cpp @@ -32,6 +32,8 @@ #include <QPainter>
#include <QRegExpValidator>
+#include "libsigrok4DSLogic/libsigrok.h"
+
namespace pv {
namespace dock {
diff --git a/DSLogic-gui/pv/dock/triggerdock.cpp b/DSLogic-gui/pv/dock/triggerdock.cpp index 38e89b8..d5fc890 100644 --- a/DSLogic-gui/pv/dock/triggerdock.cpp +++ b/DSLogic-gui/pv/dock/triggerdock.cpp @@ -31,6 +31,8 @@ #include <QRegExpValidator>
#include <QMessageBox>
+#include "libsigrok4DSLogic/libsigrok.h"
+
namespace pv {
namespace dock {
@@ -40,6 +42,10 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) : {
int i;
+ QFont font("Monaco");
+ font.setStyleHint(QFont::Monospace);
+ font.setFixedPitch(true);
+
simple_radioButton = new QRadioButton("Simple Trigger", this);
simple_radioButton->setChecked(true);
adv_radioButton = new QRadioButton("Advanced Trigger", this);
@@ -75,6 +81,7 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) : _logic_comboBox_list.push_back(_logic_comboBox);
QLineEdit *_value0_lineEdit = new QLineEdit("X X X X X X X X X X X X X X X X", this);
+ _value0_lineEdit->setFont(font);
_value0_lineEdit->setValidator(value_validator);
_value0_lineEdit->setMaxLength(TriggerProbes * 2 - 1);
_value0_lineEdit->setInputMask("X X X X X X X X X X X X X X X X");
@@ -89,6 +96,7 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) : _inv0_comboBox_list.push_back(_inv0_comboBox);
QLineEdit *_value1_lineEdit = new QLineEdit("X X X X X X X X X X X X X X X X", this);
+ _value1_lineEdit->setFont(font);
_value1_lineEdit->setValidator(value_validator);
_value1_lineEdit->setMaxLength(TriggerProbes * 2 - 1);
_value1_lineEdit->setInputMask("X X X X X X X X X X X X X X X X");
@@ -102,15 +110,14 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) : _inv1_comboBox->addItem(tr("!="));
_inv1_comboBox_list.push_back(_inv1_comboBox);
- QLabel *value_exp0_label = new QLabel("1 1 1 1 1 1", this);
- QLabel *value_exp1_label = new QLabel("5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0", this);
+ QLabel *value_exp_label = new QLabel("1 1 1 1 1 1\n5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0", this);
QLabel *inv_exp_label = new QLabel("Inv", this);
QLabel *count_exp_label = new QLabel("Counter", this);
+ value_exp_label->setFont(font);
QVBoxLayout *stage_layout = new QVBoxLayout();
QGridLayout *stage_glayout = new QGridLayout();
- stage_glayout->addWidget(value_exp0_label, 0, 0);
- stage_glayout->addWidget(value_exp1_label, 1, 0);
+ stage_glayout->addWidget(value_exp_label, 1, 0);
stage_glayout->addWidget(inv_exp_label, 1, 1);
stage_glayout->addWidget(count_exp_label, 1, 2);
stage_glayout->addWidget(_value0_lineEdit, 2, 0);
@@ -121,13 +128,8 @@ TriggerDock::TriggerDock(QWidget *parent, SigSession &session) : stage_glayout->addWidget(_inv1_comboBox, 3, 1);
stage_glayout->addWidget(_count1_spinBox, 3, 2);
stage_layout->addLayout(stage_glayout);
- stage_layout->addSpacing(124);
- stage_layout->addWidget(new QLabel("X: Don't care"));
- stage_layout->addWidget(new QLabel("0: Low level"));
- stage_layout->addWidget(new QLabel("1: High level"));
- stage_layout->addWidget(new QLabel("R: Rising edge"));
- stage_layout->addWidget(new QLabel("F: Falling edge"));
- stage_layout->addWidget(new QLabel("C: Rising/Falling edge"));
+ stage_layout->addSpacing(160);
+ stage_layout->addWidget(new QLabel("X: Don't care\n0: Low level\n1: High level\nR: Rising edge\nF: Falling edge\nC: Rising/Falling edge"));
stage_layout->addStretch(1);
QGroupBox *_stage_groupBox = new QGroupBox("Stage"+QString::number(i), this);
diff --git a/DSLogic-gui/pv/mainwindow.cpp b/DSLogic-gui/pv/mainwindow.cpp index 32c7a94..9a7bb84 100644 --- a/DSLogic-gui/pv/mainwindow.cpp +++ b/DSLogic-gui/pv/mainwindow.cpp @@ -57,6 +57,7 @@ #include "dock/protocoldock.h" #include "dock/triggerdock.h" +#include "dock/dsotriggerdock.h" #include "dock/measuredock.h" #include "dock/searchdock.h" @@ -235,6 +236,14 @@ void MainWindow::setup_ui() _trigger_widget = new dock::TriggerDock(_trigger_dock, _session); _trigger_dock->setWidget(_trigger_widget); + _dso_trigger_dock=new QDockWidget(tr("Trigger Setting..."),this); + _dso_trigger_dock->setFeatures(QDockWidget::NoDockWidgetFeatures); + _dso_trigger_dock->setAllowedAreas(Qt::RightDockWidgetArea); + _dso_trigger_dock->setVisible(false); + _dso_trigger_widget = new dock::DsoTriggerDock(_dso_trigger_dock, _session); + _dso_trigger_dock->setWidget(_dso_trigger_widget); + + // Setup _view widget _view = new pv::view::View(_session, this); _vertical_layout->addWidget(_view); @@ -242,15 +251,17 @@ void MainWindow::setup_ui() // Populate the device list and select the initially selected device update_device_list(); -// connect(_device_bar, SIGNAL(device_selected()), this, -// SLOT(device_selected())); connect(_device_bar, SIGNAL(device_selected()), this, - SLOT(init())); + SLOT(device_selected())); +// connect(_device_bar, SIGNAL(device_selected()), this, +// SLOT(init())); connect(_device_bar, SIGNAL(device_updated()), this, SLOT(update())); - connect(_sampling_bar, SIGNAL(run_stop()), this, - SLOT(run_stop())); - addToolBar(_sampling_bar); + connect(_sampling_bar, SIGNAL(device_reload()), this, + SLOT(init())); + connect(_sampling_bar, SIGNAL(run_stop()), this, + SLOT(run_stop())); + addToolBar(_sampling_bar); addToolBar(_trig_bar); addToolBar(_device_bar); addToolBar(_file_bar); @@ -294,11 +305,12 @@ void MainWindow::setup_ui() _trigger_dock->setObjectName(tr("triggerDock")); addDockWidget(Qt::RightDockWidgetArea,_protocol_dock); addDockWidget(Qt::RightDockWidgetArea,_trigger_dock); + addDockWidget(Qt::RightDockWidgetArea,_dso_trigger_dock); addDockWidget(Qt::RightDockWidgetArea, _measure_dock); addDockWidget(Qt::BottomDockWidgetArea, _search_dock); // Set the title - setWindowTitle(QApplication::translate("MainWindow", "DSLogic", 0, + setWindowTitle(QApplication::translate("MainWindow", "DSLogic(Beta)", 0, QApplication::UnicodeUTF8)); // Setup _session events @@ -310,6 +322,8 @@ void MainWindow::setup_ui() SLOT(device_detach())); connect(&_session, SIGNAL(test_data_error()), this, SLOT(test_data_error())); + connect(&_session, SIGNAL(dso_ch_changed(uint16_t)), this, + SLOT(dso_ch_changed(uint16_t))); connect(_view, SIGNAL(cursor_update()), _measure_widget, SLOT(cursor_update())); @@ -325,6 +339,14 @@ void MainWindow::init() _trigger_widget->device_change(); if (_session.get_device()) _session.init_signals(_session.get_device()); + if (_session.get_device()->mode == DSO) { + _sampling_bar->set_record_length(DefaultDSODepth*2); + _sampling_bar->set_sample_rate(DefaultDSORate*2); + _sampling_bar->enable_toggle(false); + _view->hDial_changed(0); + } else if(_session.get_device()->mode == LOGIC) { + _sampling_bar->enable_toggle(true); + } } void MainWindow::update() @@ -372,10 +394,12 @@ void MainWindow::update_device_list(struct sr_dev_inst *selected_device) } } - #ifdef HAVE_LA_DSLOGIC - _session.start_hot_plug_proc(boost::bind(&MainWindow::session_error, this, +// #ifdef HAVE_LA_DSLOGIC + _session.start_hotplug_proc(boost::bind(&MainWindow::session_error, this, QString("Hotplug failed"), _1)); - #endif + _session.start_dso_ctrl_proc(boost::bind(&MainWindow::session_error, this, + QString("Hotplug failed"), _1)); +// #endif } void MainWindow::device_change() @@ -408,11 +432,11 @@ void MainWindow::device_change() device_detach(); } - #ifdef HAVE_LA_DSLOGIC - _session.stop_hot_plug_proc(); - _session.start_hot_plug_proc(boost::bind(&MainWindow::session_error, this, +// #ifdef HAVE_LA_DSLOGIC + _session.stop_hotplug_proc(); + _session.start_hotplug_proc(boost::bind(&MainWindow::session_error, this, QString("Hotplug failed"), _1)); - #endif +// #endif } @@ -444,16 +468,44 @@ void MainWindow::device_selected() _sampling_bar->set_device(_device_bar->get_selected_device()); _sampling_bar->update_sample_rate_selector(); _view->show_trig_cursor(false); + _trigger_dock->setVisible(false); + _dso_trigger_dock->setVisible(false); + _protocol_dock->setVisible(false); + _measure_dock->setVisible(false); + _search_dock->setVisible(false); init(); } else { show_session_error("Open Device Failed", "the selected device can't be opened!"); } + + if (_device_bar->get_selected_device()->mode == DSO) { + QMessageBox msg(this); + msg.setText("Zero Adjustment"); + msg.setInformativeText("Please left both of channels unconnect for zero adjustment!"); + msg.setStandardButtons(QMessageBox::Ok); + msg.setIcon(QMessageBox::Warning); + msg.exec(); + + int ret = sr_config_set(_device_bar->get_selected_device(), SR_CONF_ZERO, g_variant_new_boolean(TRUE)); + if (ret != SR_OK) { + QMessageBox msg(this); + msg.setText("Zero Adjustment Issue"); + msg.setInformativeText("Can't send out the command of zero adjustment!"); + msg.setStandardButtons(QMessageBox::Ok); + msg.setIcon(QMessageBox::Warning); + msg.exec(); + } else { + run_stop(); + g_usleep(100000); + run_stop(); + } + } } void MainWindow::device_attach() { - _session.stop_hot_plug_proc(); + _session.stop_hotplug_proc(); if (_session.get_capture_state() == SigSession::Running) _session.stop_capture(); @@ -470,7 +522,7 @@ void MainWindow::device_attach() void MainWindow::device_detach() { - _session.stop_hot_plug_proc(); + _session.stop_hotplug_proc(); if (_session.get_capture_state() == SigSession::Running) _session.stop_capture(); @@ -506,8 +558,34 @@ void MainWindow::run_stop() _sampling_bar->enable_run_stop(true); } +void MainWindow::dso_ch_changed(uint16_t num) +{ + if(num == 1) { + _sampling_bar->set_record_length(DefaultDSODepth*2); + _sampling_bar->set_sample_rate(DefaultDSORate*2); + _session.set_total_sample_len(_sampling_bar->get_record_length()); + if (_session.get_capture_state() == SigSession::Running) { + _session.stop_capture(); + _session.start_capture(_sampling_bar->get_record_length(), + boost::bind(&MainWindow::session_error, this, + QString("Capture failed"), _1)); + } + } else { + _sampling_bar->set_record_length(DefaultDSODepth); + _sampling_bar->set_sample_rate(DefaultDSORate); + _session.set_total_sample_len(_sampling_bar->get_record_length()); + if (_session.get_capture_state() == SigSession::Running) { + _session.stop_capture(); + _session.start_capture(_sampling_bar->get_record_length(), + boost::bind(&MainWindow::session_error, this, + QString("Capture failed"), _1)); + } + } +} + void MainWindow::test_data_error() { + _session.stop_capture(); QMessageBox msg(this); msg.setText("Data Error"); msg.setInformativeText("the receive data are not consist with pre-defined test data"); @@ -518,12 +596,14 @@ void MainWindow::test_data_error() void MainWindow::capture_state_changed(int state) { - _sampling_bar->enable_toggle(state != SigSession::Running); - _trig_bar->enable_toggle(state != SigSession::Running); + if (_session.get_device()->mode != DSO) { + _sampling_bar->enable_toggle(state != SigSession::Running); + _trig_bar->enable_toggle(state != SigSession::Running); + _measure_dock->widget()->setEnabled(state != SigSession::Running); + } _device_bar->enable_toggle(state != SigSession::Running); _file_bar->enable_toggle(state != SigSession::Running); _sampling_bar->set_sampling(state == SigSession::Running); - _measure_dock->widget()->setEnabled(state != SigSession::Running); _view->on_state_changed(state != SigSession::Running); } @@ -534,7 +614,10 @@ void MainWindow::on_protocol(bool visible) void MainWindow::on_trigger(bool visible) { - _trigger_dock->setVisible(visible); + if (_session.get_device()->mode != DSO) + _trigger_dock->setVisible(visible); + else + _dso_trigger_dock->setVisible(visible); } void MainWindow::on_measure(bool visible) diff --git a/DSLogic-gui/pv/mainwindow.h b/DSLogic-gui/pv/mainwindow.h index b89aee9..9be748a 100644 --- a/DSLogic-gui/pv/mainwindow.h +++ b/DSLogic-gui/pv/mainwindow.h @@ -54,6 +54,7 @@ class LogoBar; namespace dock{ class ProtocolDock; class TriggerDock; +class DsoTriggerDock; class MeasureDock; class SearchDock; } @@ -66,6 +67,10 @@ class MainWindow : public QMainWindow { Q_OBJECT +private: + static const int DefaultDSODepth = 8192; + static const int DefaultDSORate = 100000000; + public: explicit MainWindow(DeviceManager &device_manager, const char *open_file_name = NULL, @@ -122,6 +127,9 @@ private slots: void device_attach(); void device_detach(); + /* */ + void dso_ch_changed(uint16_t num); + private: DeviceManager &_device_manager; @@ -155,7 +163,9 @@ private: QDockWidget *_protocol_dock; dock::ProtocolDock *_protocol_widget; QDockWidget *_trigger_dock; + QDockWidget *_dso_trigger_dock; dock::TriggerDock *_trigger_widget; + dock::DsoTriggerDock *_dso_trigger_widget; QDockWidget *_measure_dock; QDockWidget *_search_dock; dock::SearchDock * _search_widget; diff --git a/DSLogic-gui/pv/prop/binding/binding_deviceoptions.cpp b/DSLogic-gui/pv/prop/binding/binding_deviceoptions.cpp index 189afcc..05b488e 100644 --- a/DSLogic-gui/pv/prop/binding/binding_deviceoptions.cpp +++ b/DSLogic-gui/pv/prop/binding/binding_deviceoptions.cpp @@ -83,7 +83,12 @@ DeviceOptions::DeviceOptions(struct sr_dev_inst *sdi) : case SR_CONF_BUFFERSIZE: case SR_CONF_TRIGGER_SOURCE: case SR_CONF_FILTER: - case SR_CONF_COUPLING: + case SR_CONF_COUPLING0: + case SR_CONF_COUPLING1: + case SR_CONF_EN_CH0: + case SR_CONF_EN_CH1: + case SR_CONF_OPERATION_MODE: + case SR_CONF_ZERO: bind_enum(name, key, gvar_list); break; @@ -99,9 +104,12 @@ DeviceOptions::DeviceOptions(struct sr_dev_inst *sdi) : bind_enum(name, key, gvar_list, print_timebase); break; - case SR_CONF_VDIV: + case SR_CONF_VDIV0: + case SR_CONF_VDIV1: bind_enum(name, key, gvar_list, print_vdiv); - break; + break; + default: + gvar_list = NULL; } if (gvar_list) @@ -131,13 +139,13 @@ void DeviceOptions::config_setter( void DeviceOptions::bind_bool(const QString &name, int key) { - _properties.push_back(shared_ptr<Property>( + _properties.push_back(boost::shared_ptr<Property>( new Bool(name, bind(config_getter, _sdi, key), bind(config_setter, _sdi, key, _1)))); } void DeviceOptions::bind_enum(const QString &name, int key, - GVariant *const gvar_list, function<QString (GVariant*)> printer) + GVariant *const gvar_list, boost::function<QString (GVariant*)> printer) { GVariant *gvar; GVariantIter iter; @@ -149,7 +157,7 @@ void DeviceOptions::bind_enum(const QString &name, int key, while ((gvar = g_variant_iter_next_value (&iter))) values.push_back(make_pair(gvar, printer(gvar))); - _properties.push_back(shared_ptr<Property>( + _properties.push_back(boost::shared_ptr<Property>( new Enum(name, values, bind(config_getter, _sdi, key), bind(config_setter, _sdi, key, _1)))); @@ -158,7 +166,7 @@ void DeviceOptions::bind_enum(const QString &name, int key, void DeviceOptions::bind_int(const QString &name, int key, QString suffix, optional< std::pair<int64_t, int64_t> > range) { - _properties.push_back(shared_ptr<Property>( + _properties.push_back(boost::shared_ptr<Property>( new Int(name, suffix, range, bind(config_getter, _sdi, key), bind(config_setter, _sdi, key, _1)))); @@ -197,7 +205,7 @@ void DeviceOptions::bind_samplerate(const QString &name, assert(num_elements == 3); - _properties.push_back(shared_ptr<Property>( + _properties.push_back(boost::shared_ptr<Property>( new Double(name, 0, QObject::tr("Hz"), make_pair((double)elements[0], (double)elements[1]), (double)elements[2], diff --git a/DSLogic-gui/pv/sigsession.cpp b/DSLogic-gui/pv/sigsession.cpp index 684f346..27d7946 100644 --- a/DSLogic-gui/pv/sigsession.cpp +++ b/DSLogic-gui/pv/sigsession.cpp @@ -26,11 +26,14 @@ #include "devicemanager.h" #include "data/analog.h" #include "data/analogsnapshot.h" +#include "data/dso.h" +#include "data/dsosnapshot.h" #include "data/logic.h" #include "data/logicsnapshot.h" #include "data/group.h" #include "data/groupsnapshot.h" #include "view/analogsignal.h" +#include "view/dsosignal.h" #include "view/logicsignal.h" #include "view/groupsignal.h" #include "view/protocolsignal.h" @@ -59,8 +62,7 @@ SigSession::SigSession(DeviceManager &device_manager) : _sdi(NULL), _capture_state(Init), _last_sample_rate(1), - _total_sample_len(1), - _hot_plug_handle(NULL) + _total_sample_len(1) { // TODO: This should not be necessary _session = this; @@ -71,20 +73,28 @@ SigSession::SigSession(DeviceManager &device_manager) : _protocol_cnt = 0; _decoderFactory = new decoder::DecoderFactory(); ds_trigger_init(); + + _vDial_changed = false; + _hDial_changed = false; + _dso_ctrl_channel = 0; + register_hotplug_callback(); } SigSession::~SigSession() { - stop_capture(); + stop_capture(); - if (_sampling_thread.get()) - _sampling_thread->join(); - _sampling_thread.reset(); + if (_sampling_thread.get()) + _sampling_thread->join(); + _sampling_thread.reset(); - if (_hot_plug_handle) - stop_hot_plug_proc(); + if (_hotplug_handle) { + stop_hotplug_proc(); + deregister_hotplug_callback(); + } ds_trigger_destroy(); + stop_dso_ctrl_proc(); // TODO: This should not be necessary _session = NULL; @@ -114,15 +124,18 @@ int SigSession::set_device(struct sr_dev_inst *sdi) { int ret = SR_ERR; - if (sdi) + if (_sdi == NULL) { ret = _device_manager.use_device(sdi, this); - if (ret == SR_OK && (sdi != _sdi) && _sdi) { - _device_manager.release_device(_sdi); - } - if (ret == SR_OK) _sdi = sdi; - - set_capture_state(Init); + set_capture_state(Init); + } else if (sdi != _sdi) { + ret = _device_manager.use_device(sdi, this); + _device_manager.release_device(_sdi); + _sdi = sdi; + set_capture_state(Init); + } else { + ret = SR_OK; + } return ret; } @@ -137,12 +150,25 @@ void SigSession::release_device(struct sr_dev_inst *sdi) void SigSession::save_file(const std::string &name){ if (_sdi->mode == LOGIC) { - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _logic_data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = + snapshots.front(); + + sr_session_save(name.c_str(), _sdi, + (unsigned char*)snapshot->get_data(), + snapshot->get_unit_size(), + snapshot->get_sample_count()); + } else if (_sdi->mode == DSO){ + const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots = + _dso_data->get_snapshots(); + if (snapshots.empty()) + return; + + const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot = snapshots.front(); sr_session_save(name.c_str(), _sdi, @@ -150,12 +176,12 @@ void SigSession::save_file(const std::string &name){ snapshot->get_unit_size(), snapshot->get_sample_count()); } else { - const deque< shared_ptr<pv::data::AnalogSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::AnalogSnapshot> > &snapshots = _analog_data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::AnalogSnapshot> &snapshot = + const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot = snapshots.front(); sr_session_save(name.c_str(), _sdi, @@ -166,7 +192,7 @@ void SigSession::save_file(const std::string &name){ } void SigSession::load_file(const string &name, - function<void (const QString)> error_handler) + boost::function<void (const QString)> error_handler) { stop_capture(); _sampling_thread.reset(new boost::thread( @@ -176,12 +202,12 @@ void SigSession::load_file(const string &name, SigSession::capture_state SigSession::get_capture_state() const { - lock_guard<mutex> lock(_sampling_mutex); + boost::lock_guard<boost::mutex> lock(_sampling_mutex); return _capture_state; } void SigSession::start_capture(uint64_t record_length, - function<void (const QString)> error_handler) + boost::function<void (const QString)> error_handler) { stop_capture(); @@ -199,12 +225,28 @@ void SigSession::start_capture(uint64_t record_length, if (probe->enabled) break; } - if (!l) { error_handler(tr("No probes enabled.")); return; } + // Check that at least one signal channel is active under DSO mode + if (_sdi->mode == DSO) { + bool active = false; + BOOST_FOREACH(const shared_ptr<view::Signal> s, _signals) + { + assert(s); + if (s->get_active()) { + active = true; + break; + } + } + if (!active) { + error_handler(tr("No channels enabled.")); + return; + } + } + // Begin the session _sampling_thread.reset(new boost::thread( &SigSession::sample_thread_proc, this, _sdi, @@ -215,7 +257,6 @@ void SigSession::stop_capture() { if (get_capture_state() == Stopped) return; - sr_session_stop(); // Check that sampling stopped @@ -224,15 +265,15 @@ void SigSession::stop_capture() _sampling_thread.reset(); } -vector< shared_ptr<view::Signal> > SigSession::get_signals() +vector< boost::shared_ptr<view::Signal> > SigSession::get_signals() { - lock_guard<mutex> lock(_signals_mutex); + boost::lock_guard<boost::mutex> lock(_signals_mutex); return _signals; } -vector< shared_ptr<view::Signal> > SigSession::get_pro_signals() +vector< boost::shared_ptr<view::Signal> > SigSession::get_pro_signals() { - lock_guard<mutex> lock(_signals_mutex); + boost::lock_guard<boost::mutex> lock(_signals_mutex); return _protocol_signals; } @@ -255,6 +296,24 @@ int SigSession::get_logic_probe_cnt(const sr_dev_inst *sdi) return logic_probe_cnt; } +int SigSession::get_dso_probe_cnt(const sr_dev_inst *sdi) +{ + unsigned int dso_probe_cnt = 0; + for (const GSList *l = sdi->probes; l; l = l->next) { + const sr_probe *const probe = (const sr_probe *)l->data; + if (!probe->enabled) + continue; + + switch(probe->type) { + case SR_PROBE_DSO: + dso_probe_cnt++; + break; + } + } + + return dso_probe_cnt; +} + int SigSession::get_analog_probe_cnt(const sr_dev_inst *sdi) { unsigned int analog_probe_cnt = 0; @@ -281,24 +340,36 @@ boost::shared_ptr<data::Logic> SigSession::get_data() void* SigSession::get_buf(int& unit_size, uint64_t &length) { if (_sdi->mode == LOGIC) { - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _logic_data->get_snapshots(); if (snapshots.empty()) return NULL; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = + snapshots.front(); + + unit_size = snapshot->get_unit_size(); + length = snapshot->get_sample_count(); + return snapshot->get_data(); + } else if (_sdi->mode == DSO) { + const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots = + _dso_data->get_snapshots(); + if (snapshots.empty()) + return NULL; + + const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot = snapshots.front(); unit_size = snapshot->get_unit_size(); length = snapshot->get_sample_count(); return snapshot->get_data(); } else { - const deque< shared_ptr<pv::data::AnalogSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::AnalogSnapshot> > &snapshots = _analog_data->get_snapshots(); if (snapshots.empty()) return NULL; - const shared_ptr<pv::data::AnalogSnapshot> &snapshot = + const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot = snapshots.front(); unit_size = snapshot->get_unit_size(); @@ -309,14 +380,14 @@ void* SigSession::get_buf(int& unit_size, uint64_t &length) void SigSession::set_capture_state(capture_state state) { - lock_guard<mutex> lock(_sampling_mutex); + boost::lock_guard<boost::mutex> lock(_sampling_mutex); _capture_state = state; data_updated(); capture_state_changed(state); } void SigSession::load_thread_proc(const string name, - function<void (const QString)> error_handler) + boost::function<void (const QString)> error_handler) { if (sr_session_load(name.c_str()) != SR_OK) { error_handler(tr("Failed to load file.")); @@ -339,79 +410,79 @@ void SigSession::load_thread_proc(const string name, // Confirm that SR_DF_END was received assert(!_cur_logic_snapshot); + assert(!_cur_dso_snapshot); assert(!_cur_analog_snapshot); } void SigSession::sample_thread_proc(struct sr_dev_inst *sdi, uint64_t record_length, - function<void (const QString)> error_handler) + boost::function<void (const QString)> error_handler) { -// while(1) { - assert(sdi); - assert(error_handler); - - if (!_adv_trigger) { - /* simple trigger check trigger_enable */ - ds_trigger_set_en(false); - BOOST_FOREACH(const shared_ptr<view::Signal> s, _signals) - { - assert(s); - if (s->get_trig() != 0) { - ds_trigger_set_en(true); - s->set_trig(s->get_trig()); - } - } - } else { - /* advanced trigger check trigger_enable */ - ds_trigger_set_en(true); - } + assert(sdi); + assert(error_handler); - sr_session_new(); - sr_session_datafeed_callback_add(data_feed_in_proc, NULL); - - if (sr_session_dev_add(sdi) != SR_OK) { - error_handler(tr("Failed to use device.")); - sr_session_destroy(); - return; - } - - // Set the sample limit - if (sr_config_set(sdi, SR_CONF_LIMIT_SAMPLES, - g_variant_new_uint64(record_length)) != SR_OK) { - error_handler(tr("Failed to configure " - "time-based sample limit.")); - sr_session_destroy(); - return; + if (!_adv_trigger) { + /* simple trigger check trigger_enable */ + ds_trigger_set_en(false); + BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _signals) + { + assert(s); + if (s->get_trig() != 0) { + ds_trigger_set_en(true); + s->set_trig(s->get_trig()); + } } + } else { + /* advanced trigger check trigger_enable */ + ds_trigger_set_en(true); + } - receive_data(0); - set_capture_state(Running); + sr_session_new(); + sr_session_datafeed_callback_add(data_feed_in_proc, NULL); - if (sr_session_start() != SR_OK) { - error_handler(tr("Failed to start session.")); - set_capture_state(Stopped); - return; - } + if (sr_session_dev_add(sdi) != SR_OK) { + error_handler(tr("Failed to use device.")); + sr_session_destroy(); + return; + } - sr_session_run(); + // Set the sample limit + if (sr_config_set(sdi, SR_CONF_LIMIT_SAMPLES, + g_variant_new_uint64(record_length)) != SR_OK) { + error_handler(tr("Failed to configure " + "time-based sample limit.")); sr_session_destroy(); + return; + } + + receive_data(0); + set_capture_state(Running); + if (sr_session_start() != SR_OK) { + error_handler(tr("Failed to start session.")); set_capture_state(Stopped); + return; + } - // Confirm that SR_DF_END was received - assert(!_cur_logic_snapshot); - assert(!_cur_analog_snapshot); + sr_session_run(); + sr_session_destroy(); -// g_usleep(3000*1000); -// } + set_capture_state(Stopped); + + // Confirm that SR_DF_END was received + assert(!_cur_logic_snapshot); + assert(!_cur_dso_snapshot); + assert(!_cur_analog_snapshot); } void SigSession::feed_in_header(const sr_dev_inst *sdi) { - shared_ptr<view::Signal> signal; + boost::shared_ptr<view::Signal> signal; GVariant *gvar; uint64_t sample_rate = 0; unsigned int logic_probe_count = 0; + unsigned int dso_probe_count = 0; + unsigned int dso_channel_count = 0; unsigned int analog_probe_count = 0; // Detect what data types we will receive @@ -425,6 +496,10 @@ void SigSession::feed_in_header(const sr_dev_inst *sdi) logic_probe_count++; break; + case SR_PROBE_DSO: + dso_probe_count++; + break; + case SR_PROBE_ANALOG: analog_probe_count++; break; @@ -443,24 +518,39 @@ void SigSession::feed_in_header(const sr_dev_inst *sdi) sample_rate = g_variant_get_uint64(gvar); g_variant_unref(gvar); - ret = sr_config_get(sdi->driver, SR_CONF_LIMIT_SAMPLES, - &gvar, sdi); - if (ret != SR_OK) { - qDebug("Failed to get total samples"); - return; - } - if (g_variant_get_uint64(gvar) != 0) - _total_sample_len = g_variant_get_uint64(gvar); - g_variant_unref(gvar); +// ret = sr_config_get(sdi->driver, SR_CONF_LIMIT_SAMPLES, +// &gvar, sdi); +// if (ret != SR_OK) { +// qDebug("Failed to get total samples"); +// return; +// } +// if (g_variant_get_uint64(gvar) != 0) +// _total_sample_len = g_variant_get_uint64(gvar); +// g_variant_unref(gvar); if (sample_rate != _last_sample_rate) { _last_sample_rate = sample_rate; sample_rate_changed(sample_rate); } + ret = sr_config_get(sdi->driver, SR_CONF_EN_CH0, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get ENABLE of DSO channel 0\n"); + return; + } + dso_channel_count += g_variant_get_boolean(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_EN_CH1, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get ENABLE of DSO channel 1\n"); + return; + } + dso_channel_count += g_variant_get_boolean(gvar); + // Create data containers for the coming data snapshots { - lock_guard<mutex> data_lock(_data_mutex); + boost::lock_guard<boost::mutex> data_lock(_data_mutex); if (logic_probe_count != 0) { _logic_data.reset(new data::Logic( @@ -471,6 +561,11 @@ void SigSession::feed_in_header(const sr_dev_inst *sdi) assert(_group_data); } + if (dso_probe_count != 0) { + _dso_data.reset(new data::Dso(dso_channel_count, sample_rate)); + assert(_dso_data); + } + if (analog_probe_count != 0) { _analog_data.reset(new data::Analog(analog_probe_count, sample_rate)); assert(_analog_data); @@ -479,10 +574,10 @@ void SigSession::feed_in_header(const sr_dev_inst *sdi) // Set Signal data { - BOOST_FOREACH(const shared_ptr<view::Signal> s, _signals) + BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _signals) { assert(s); - s->set_data(_logic_data, _analog_data, _group_data); + s->set_data(_logic_data, _dso_data, _analog_data, _group_data); } receive_data(0); @@ -503,7 +598,7 @@ void SigSession::add_group() if (probe_index_list.size() > 1) { //_group_data.reset(new data::Group(_last_sample_rate)); - const shared_ptr<view::Signal> signal = shared_ptr<view::Signal>( + const boost::shared_ptr<view::Signal> signal = boost::shared_ptr<view::Signal>( new view::GroupSignal("New Group", _group_data, probe_index_list, _signals.size(), _group_cnt)); _signals.push_back(signal); @@ -513,7 +608,7 @@ void SigSession::add_group() if (!_cur_group_snapshot) { // Create a new data snapshot - _cur_group_snapshot = shared_ptr<data::GroupSnapshot>( + _cur_group_snapshot = boost::shared_ptr<data::GroupSnapshot>( new data::GroupSnapshot(_logic_data->get_snapshots().front(), signal->get_index_list())); //_cur_group_snapshot->append_payload(); _group_data->push_snapshot(_cur_group_snapshot); @@ -572,7 +667,7 @@ void SigSession::add_protocol(std::list<int> probe_index_list, decoder::Decoder if (probe_index_list.size() > 0) { //_group_data.reset(new data::Group(_last_sample_rate)); - const shared_ptr<view::Signal> signal = shared_ptr<view::Signal>( + const boost::shared_ptr<view::Signal> signal = boost::shared_ptr<view::Signal>( new view::ProtocolSignal(decoder->get_decode_name(), _logic_data, decoder, probe_index_list, 0, _protocol_cnt)); _signals.push_back(signal); @@ -627,11 +722,18 @@ void SigSession::del_signal(std::vector< boost::shared_ptr<view::Signal> >::iter void SigSession::init_signals(const sr_dev_inst *sdi) { - shared_ptr<view::Signal> signal; + boost::shared_ptr<view::Signal> signal; GVariant *gvar; uint64_t sample_rate = 0; unsigned int logic_probe_count = 0; + unsigned int dso_probe_count = 0; + unsigned int dso_channel_count = 0; unsigned int analog_probe_count = 0; + uint64_t vdiv; + uint64_t timebase; + bool coupling; + bool active; + int ret; // Detect what data types we will receive for (const GSList *l = sdi->probes; l; l = l->next) { @@ -644,6 +746,10 @@ void SigSession::init_signals(const sr_dev_inst *sdi) logic_probe_count++; break; + case SR_PROBE_DSO: + dso_probe_count++; + break; + case SR_PROBE_ANALOG: analog_probe_count++; break; @@ -653,21 +759,34 @@ void SigSession::init_signals(const sr_dev_inst *sdi) // Read out the sample rate assert(sdi->driver); - const int ret = sr_config_get(sdi->driver, SR_CONF_SAMPLERATE, + ret = sr_config_get(sdi->driver, SR_CONF_SAMPLERATE, &gvar, sdi); if (ret != SR_OK) { qDebug("Failed to get samplerate\n"); return; } - sample_rate = g_variant_get_uint64(gvar); - g_variant_unref(gvar); if (sample_rate != _last_sample_rate) { _last_sample_rate = sample_rate; sample_rate_changed(sample_rate); } + ret = sr_config_get(sdi->driver, SR_CONF_EN_CH0, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get ENABLE of DSO channel 0\n"); + return; + } + dso_channel_count += g_variant_get_boolean(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_EN_CH1, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get ENABLE of DSO channel 1\n"); + return; + } + dso_channel_count += g_variant_get_boolean(gvar); + // Create data containers for the coming data snapshots { if (logic_probe_count != 0) { @@ -680,6 +799,11 @@ void SigSession::init_signals(const sr_dev_inst *sdi) _group_cnt = 0; } + if (dso_probe_count != 0) { + _dso_data.reset(new data::Dso(dso_channel_count, sample_rate)); + assert(_dso_data); + } + if (analog_probe_count != 0) { _analog_data.reset(new data::Analog(analog_probe_count, sample_rate)); assert(_analog_data); @@ -699,13 +823,78 @@ void SigSession::init_signals(const sr_dev_inst *sdi) switch(probe->type) { case SR_PROBE_LOGIC: - signal = shared_ptr<view::Signal>( + signal = boost::shared_ptr<view::Signal>( new view::LogicSignal(probe->name, _logic_data, probe->index, _signals.size())); break; + case SR_PROBE_DSO: + if (probe->index == 0) { + ret = sr_config_get(sdi->driver, SR_CONF_VDIV0, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get VDIV of channel 0\n"); + return; + } + vdiv = g_variant_get_uint64(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_TIMEBASE, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get TIMEBASE\n"); + return; + } + timebase = g_variant_get_uint64(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_COUPLING0, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get AC COUPLING of channel 0\n"); + return; + } + coupling = g_variant_get_boolean(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_EN_CH0, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get ENABLE of channel 0\n"); + return; + } + active = g_variant_get_boolean(gvar); + } else if (probe->index == 1) { + ret = sr_config_get(sdi->driver, SR_CONF_VDIV1, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get VDIV of channel 1\n"); + return; + } + vdiv = g_variant_get_uint64(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_TIMEBASE, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get TIMEBASE\n"); + return; + } + timebase = g_variant_get_uint64(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_COUPLING1, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get AC COUPLING of channel 1\n"); + return; + } + coupling = g_variant_get_boolean(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_EN_CH1, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get ENABLE of channel 1\n"); + return; + } + active = g_variant_get_boolean(gvar); + } + signal = boost::shared_ptr<view::Signal>( + new view::DsoSignal(probe->name, + _dso_data, probe->index, _signals.size(), vdiv, timebase, coupling, active)); + break; + case SR_PROBE_ANALOG: - signal = shared_ptr<view::Signal>( + signal = boost::shared_ptr<view::Signal>( new view::AnalogSignal(probe->name, _analog_data, probe->index, _signals.size())); break; @@ -716,19 +905,27 @@ void SigSession::init_signals(const sr_dev_inst *sdi) signals_changed(); data_updated(); } + g_variant_unref(gvar); } void SigSession::update_signals(const sr_dev_inst *sdi) { - shared_ptr<view::Signal> signal; + boost::shared_ptr<view::Signal> signal; QMap<int, bool> probes_en_table; QMap<int, bool> signals_en_table; int index = 0; + GVariant *gvar; + uint64_t vdiv; + uint64_t timebase; + bool coupling; + bool active; + int ret; std::vector< boost::shared_ptr<view::Signal> >::iterator i = _signals.begin(); while (i != _signals.end()) { if (((*i)->get_type() == view::Signal::DS_LOGIC || - (*i)->get_type() == view::Signal::DS_ANALOG)) + (*i)->get_type() == view::Signal::DS_DSO || + (*i)->get_type() == view::Signal::DS_ANALOG)) signals_en_table.insert((*i)->get_index(), 1); i++; } @@ -748,13 +945,78 @@ void SigSession::update_signals(const sr_dev_inst *sdi) switch(probe->type) { case SR_PROBE_LOGIC: - signal = shared_ptr<view::Signal>( + signal = boost::shared_ptr<view::Signal>( new view::LogicSignal(probe->name, _logic_data, probe->index, 0)); break; + case SR_PROBE_DSO: + if (probe->index == 0) { + ret = sr_config_get(sdi->driver, SR_CONF_VDIV0, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get VDIV of channel 0\n"); + return; + } + vdiv = g_variant_get_uint64(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_TIMEBASE, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get TIMEBASE\n"); + return; + } + timebase = g_variant_get_uint64(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_COUPLING0, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get AC COUPLING of channel 0\n"); + return; + } + coupling = g_variant_get_boolean(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_EN_CH0, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get ENABLE of channel 0\n"); + return; + } + active = g_variant_get_boolean(gvar); + } else if (probe->index == 1) { + ret = sr_config_get(sdi->driver, SR_CONF_VDIV1, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get VDIV of channel 1\n"); + return; + } + vdiv = g_variant_get_uint64(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_TIMEBASE, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get TIMEBASE\n"); + return; + } + timebase = g_variant_get_uint64(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_COUPLING1, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get AC COUPLING of channel 1\n"); + return; + } + coupling = g_variant_get_boolean(gvar); + ret = sr_config_get(sdi->driver, SR_CONF_EN_CH1, + &gvar, sdi); + if (ret != SR_OK) { + qDebug("Failed to get ENABLE of channel 1\n"); + return; + } + active = g_variant_get_boolean(gvar); + } + signal = boost::shared_ptr<view::Signal>( + new view::DsoSignal(probe->name, + _dso_data, probe->index, _signals.size(), vdiv, timebase, coupling, active)); + break; + case SR_PROBE_ANALOG: - signal = shared_ptr<view::Signal>( + signal = boost::shared_ptr<view::Signal>( new view::AnalogSignal(probe->name, _analog_data, probe->index, 0)); break; @@ -767,7 +1029,8 @@ void SigSession::update_signals(const sr_dev_inst *sdi) i = _signals.begin(); while (i != _signals.end()) { if (((*i)->get_type() == view::Signal::DS_LOGIC || - (*i)->get_type() == view::Signal::DS_ANALOG) && + (*i)->get_type() == view::Signal::DS_DSO || + (*i)->get_type() == view::Signal::DS_ANALOG) && probes_en_table.value((*i)->get_index()) == false) { std::vector< boost::shared_ptr<view::Signal> >::iterator j = _signals.begin(); while(j != _signals.end()) { @@ -813,7 +1076,7 @@ void SigSession::feed_in_trigger(const ds_trigger_pos &trigger_pos) void SigSession::feed_in_logic(const sr_datafeed_logic &logic) { - lock_guard<mutex> lock(_data_mutex); + boost::lock_guard<boost::mutex> lock(_data_mutex); if (!_logic_data) { @@ -828,7 +1091,7 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic) if (!_cur_logic_snapshot) { // Create a new data snapshot - _cur_logic_snapshot = shared_ptr<data::LogicSnapshot>( + _cur_logic_snapshot = boost::shared_ptr<data::LogicSnapshot>( new data::LogicSnapshot(logic, _total_sample_len, 1)); if (_cur_logic_snapshot->buf_null()) stop_capture(); @@ -845,9 +1108,39 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic) //data_updated(); } +void SigSession::feed_in_dso(const sr_datafeed_dso &dso) +{ + boost::lock_guard<boost::mutex> lock(_data_mutex); + + if(!_dso_data) + { + qDebug() << "Unexpected dso packet"; + return; // This dso packet was not expected. + } + + if (!_cur_dso_snapshot) + { + // Create a new data snapshot + _cur_dso_snapshot = boost::shared_ptr<data::DsoSnapshot>( + new data::DsoSnapshot(dso, _total_sample_len, _dso_data->get_num_probes())); + if (_cur_dso_snapshot->buf_null()) + stop_capture(); + else + _dso_data->push_snapshot(_cur_dso_snapshot); + } + else + { + // Append to the existing data snapshot + _cur_dso_snapshot->append_payload(dso); + } + + receive_data(dso.num_samples); + data_updated(); +} + void SigSession::feed_in_analog(const sr_datafeed_analog &analog) { - lock_guard<mutex> lock(_data_mutex); + boost::lock_guard<boost::mutex> lock(_data_mutex); if(!_analog_data) { @@ -858,7 +1151,7 @@ void SigSession::feed_in_analog(const sr_datafeed_analog &analog) if (!_cur_analog_snapshot) { // Create a new data snapshot - _cur_analog_snapshot = shared_ptr<data::AnalogSnapshot>( + _cur_analog_snapshot = boost::shared_ptr<data::AnalogSnapshot>( new data::AnalogSnapshot(analog, _total_sample_len, _analog_data->get_num_probes())); if (_cur_analog_snapshot->buf_null()) stop_capture(); @@ -902,6 +1195,11 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi, feed_in_logic(*(const sr_datafeed_logic*)packet->payload); break; + case SR_DF_DSO: + assert(packet->payload); + feed_in_dso(*(const sr_datafeed_dso*)packet->payload); + break; + case SR_DF_ANALOG: assert(packet->payload); feed_in_analog(*(const sr_datafeed_analog*)packet->payload); @@ -910,12 +1208,12 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi, case SR_DF_END: { { - lock_guard<mutex> lock(_data_mutex); - BOOST_FOREACH(const shared_ptr<view::Signal> s, _signals) + boost::lock_guard<boost::mutex> lock(_data_mutex); + BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _signals) { assert(s); if (s->get_type() == view::Signal::DS_GROUP) { - _cur_group_snapshot = shared_ptr<data::GroupSnapshot>( + _cur_group_snapshot = boost::shared_ptr<data::GroupSnapshot>( new data::GroupSnapshot(_logic_data->get_snapshots().front(), s->get_index_list())); //_cur_group_snapshot->append_payload(); _group_data->push_snapshot(_cur_group_snapshot); @@ -926,6 +1224,7 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi, } } _cur_logic_snapshot.reset(); + _cur_dso_snapshot.reset(); _cur_analog_snapshot.reset(); } break; @@ -975,7 +1274,7 @@ void SigSession::rst_protocol_analyzer(int rst_index, std::list <int > _sel_prob if (_logic_data) _decoders.at(rst_index).first->recode(_sel_probes, _options, _options_index); - BOOST_FOREACH(const shared_ptr<view::Signal> s, _signals) + BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _signals) { assert(s); if (s->get_decoder() == _decoders.at(rst_index).first) { @@ -992,7 +1291,7 @@ void SigSession::rst_protocol_analyzer(int rst_index, std::list <int > _sel_prob void SigSession::del_protocol_analyzer(int protocol_index) { assert(protocol_index < _decoders.size()); - delete (_decoders.at(protocol_index)).first; + //delete (_decoders.at(protocol_index)).first; // BOOST_FOREACH(const int _index, (_decoders.at(protocol_index)).second) { // _signals.at(_index)->del_decoder(); @@ -1019,64 +1318,50 @@ QMap<QString, int> SigSession::get_decode_options_index(int decode_index) /* * hotplug function */ -void SigSession::start_hot_plug_proc(boost::function<void (const QString)> error_handler) -{ -#ifdef HAVE_LA_DSLOGIC - if (_hot_plug_handle) { - error_handler("Hotplug proc have started!"); - return; - } +int SigSession::hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, + libusb_hotplug_event event, void *user_data) { - int ret = libusbhp_init(&_hot_plug_handle); - if(ret != 0) { - error_handler("Could not initialize hotplug handle."); - return; - } + (void)ctx; + (void)dev; + (void)user_data; - libusbhp_register_hotplug_listeners(_hot_plug_handle, - dev_attach_callback, - dev_detach_callback, - NULL); + if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) { + _session->_hot_attach = true; + qDebug("DSLogic attaced!\n"); + }else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { + _session->_hot_detach = true; + qDebug("DSLogic dettaced!\n"); + }else{ + qDebug("Unhandled event %d\n", event); + } - // Begin the session - _hot_plug.reset(new boost::thread( - &SigSession::hot_plug_proc, this, error_handler)); -#else - error_handler("No hotplug device."); -#endif + return 0; } -void SigSession::stop_hot_plug_proc() +void SigSession::hotplug_proc(boost::function<void (const QString)> error_handler) { -#ifdef HAVE_LA_DSLOGIC - if (_hot_plug.get()) { - _hot_plug->interrupt(); - _hot_plug->join(); - } - _hot_plug.reset(); + struct timeval tv; - if(_hot_plug_handle) { - libusbhp_exit(_hot_plug_handle); - _hot_plug_handle = NULL; - } -#endif -} + (void)error_handler; -void SigSession::hot_plug_proc(boost::function<void (const QString)> error_handler) -{ if (!_sdi) return; + tv.tv_sec = tv.tv_usec = 0; try { while(_session) { + libusb_handle_events_timeout(NULL, &tv); if (_hot_attach) { + qDebug("DSLogic hardware attached!"); device_attach(); _hot_attach = false; break; } if (_hot_detach) { + qDebug("DSLogic hardware detached!"); device_detach(); _logic_data.reset(); + _dso_data.reset(); _analog_data.reset(); _hot_detach = false; break; @@ -1085,39 +1370,51 @@ void SigSession::hot_plug_proc(boost::function<void (const QString)> error_handl } } catch(...) { qDebug("Interrupt exception for hotplug thread was thrown."); - error_handler("Interrupt exception for hotplug thread was thrown."); } qDebug("Hotplug thread exit!"); } -void SigSession::dev_attach_callback(struct libusbhp_device_t *device, void *user_data) +void SigSession::register_hotplug_callback() { - (void)user_data; - - if (device) - qDebug("Attach: (%04x/%04x)", device->idVendor, device->idProduct); + int ret; + + ret = libusb_hotplug_register_callback(NULL, (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), + (libusb_hotplug_flag)LIBUSB_HOTPLUG_ENUMERATE, 0x2A0E, 0x0001, + LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL, + &_hotplug_handle); + if (LIBUSB_SUCCESS != ret){ + qDebug() << "Error creating a hotplug callback\n"; + } +} - _session->_hot_attach = true; +void SigSession::deregister_hotplug_callback() +{ + libusb_hotplug_deregister_callback(NULL, _hotplug_handle); } -void SigSession::dev_detach_callback(struct libusbhp_device_t *device, void *user_data) +void SigSession::start_hotplug_proc(boost::function<void (const QString)> error_handler) { - (void)user_data; - if (device) - qDebug("Detach: (%04x/%04x)", device->idVendor, device->idProduct); + // Begin the session + qDebug() << "Starting a hotplug thread...\n"; + _hot_attach = false; + _hot_detach = false; + _hotplug.reset(new boost::thread( + &SigSession::hotplug_proc, this, error_handler)); - _session->_hot_detach = true; } -int SigSession::hot_plug_active() +void SigSession::stop_hotplug_proc() { - if (_hot_plug_handle) - return 1; - else - return 0; + if (_hotplug.get()) { + _hotplug->interrupt(); + _hotplug->join(); + } + _hotplug.reset(); } + /* * Tigger */ @@ -1126,4 +1423,92 @@ void SigSession::set_adv_trigger(bool adv_trigger) _adv_trigger = adv_trigger; } + +/* + * oscilloscope control + */ +void SigSession::start_dso_ctrl_proc(boost::function<void (const QString)> error_handler) +{ + + // Begin the dso control thread + _dso_ctrl_thread.reset(new boost::thread( + &SigSession::dso_ctrl_proc, this, error_handler)); + +} + +void SigSession::stop_dso_ctrl_proc() +{ + + if (_dso_ctrl_thread.get()) { + _dso_ctrl_thread->interrupt(); + _dso_ctrl_thread->join(); + } + _dso_ctrl_thread.reset(); +} + +int SigSession::set_dso_ctrl(int key) +{ + int ret; + + if (key== SR_CONF_TIMEBASE) { + uint64_t timebase = _signals.at(0)->get_hDialValue(); + ret = sr_config_set(_sdi, key, g_variant_new_uint64(timebase)); + } else if (key == SR_CONF_VDIV0) { + uint64_t vdiv = _signals.at(0)->get_vDialValue(); + ret = sr_config_set(_sdi, key, g_variant_new_uint64(vdiv)); + } else if (key == SR_CONF_VDIV1) { + uint64_t vdiv = _signals.at(1)->get_vDialValue(); + ret = sr_config_set(_sdi, key, g_variant_new_uint64(vdiv)); + } else if (key == SR_CONF_COUPLING0) { + bool acdc = _signals.at(0)->get_acCoupling(); + ret = sr_config_set(_sdi, key, g_variant_new_boolean(acdc)); + } else if (key == SR_CONF_COUPLING1) { + bool acdc = _signals.at(1)->get_acCoupling(); + ret = sr_config_set(_sdi, key, g_variant_new_boolean(acdc)); + } else if (key == SR_CONF_EN_CH0) { + bool enable = _signals.at(0)->get_active(); + ret = sr_config_set(_sdi, key, g_variant_new_boolean(enable)); + dso_ch_changed(get_dso_ch_num()); + } else if (key == SR_CONF_EN_CH1) { + bool enable = _signals.at(1)->get_active(); + ret = sr_config_set(_sdi, key, g_variant_new_boolean(enable)); + dso_ch_changed(get_dso_ch_num()); + } + + return ret; +} + +uint16_t SigSession::get_dso_ch_num() +{ + uint16_t num_channels = 0; + BOOST_FOREACH(const shared_ptr<view::Signal> s, _signals) + { + assert(s); + if (s->get_active()) { + num_channels++; + } + } + return num_channels; +} + +void SigSession::dso_ctrl_proc(boost::function<void (const QString)> error_handler) +{ + (void)error_handler; + try { + while(_session) { + if (!_sdi) { + // do nothing + } else if (strcmp(_sdi->driver->name, "Demo") == 0) { + + } else if (strcmp(_sdi->driver->name, "DSLogic") == 0) { + + } + boost::this_thread::sleep(boost::posix_time::millisec(100)); + } + } catch(...) { + qDebug("Interrupt exception for oscilloscope control thread was thrown."); + } + qDebug("Oscilloscope control thread exit!"); +} + } // namespace pv diff --git a/DSLogic-gui/pv/sigsession.h b/DSLogic-gui/pv/sigsession.h index 9debdea..a8d8cfb 100644 --- a/DSLogic-gui/pv/sigsession.h +++ b/DSLogic-gui/pv/sigsession.h @@ -41,6 +41,7 @@ #include <QVariant> #include <libsigrok4DSLogic/libsigrok.h> +#include <libusb.h> namespace pv { @@ -49,6 +50,8 @@ class DeviceManager; namespace data { class Analog; class AnalogSnapshot; +class Dso; +class DsoSnapshot; class Logic; class LogicSnapshot; class Group; @@ -110,7 +113,7 @@ public: get_pro_signals(); int get_logic_probe_cnt(const struct sr_dev_inst *sdi); - + int get_dso_probe_cnt(const struct sr_dev_inst *sdi); int get_analog_probe_cnt(const struct sr_dev_inst *sdi); void init_signals(const struct sr_dev_inst *sdi); @@ -147,45 +150,47 @@ public: std::list<int> get_decode_probes(int decode_index); QMap<QString, int> get_decode_options_index(int decode_index); - void start_hot_plug_proc(boost::function<void (const QString)> error_handler); - void stop_hot_plug_proc(); - int hot_plug_active(); + void start_hotplug_proc(boost::function<void (const QString)> error_handler); + void stop_hotplug_proc(); + void register_hotplug_callback(); + void deregister_hotplug_callback(); void set_adv_trigger(bool adv_trigger); + void start_dso_ctrl_proc(boost::function<void (const QString)> error_handler); + void stop_dso_ctrl_proc(); + int set_dso_ctrl(int key); + uint16_t get_dso_ch_num(); + private: void set_capture_state(capture_state state); private: + // thread for sample/load void load_thread_proc(const std::string name, boost::function<void (const QString)> error_handler); - void sample_thread_proc(struct sr_dev_inst *sdi, uint64_t record_length, boost::function<void (const QString)> error_handler); + // data feed void feed_in_header(const sr_dev_inst *sdi); - void feed_in_meta(const sr_dev_inst *sdi, const sr_datafeed_meta &meta); - void feed_in_trigger(const ds_trigger_pos &trigger_pos); - void feed_in_logic(const sr_datafeed_logic &logic); - + void feed_in_dso(const sr_datafeed_dso &dso); void feed_in_analog(const sr_datafeed_analog &analog); - void data_feed_in(const struct sr_dev_inst *sdi, const struct sr_datafeed_packet *packet); - static void data_feed_in_proc(const struct sr_dev_inst *sdi, const struct sr_datafeed_packet *packet, void *cb_data); - void hot_plug_proc(boost::function<void (const QString)> error_handler); + void hotplug_proc(boost::function<void (const QString)> error_handler); + static int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, + libusb_hotplug_event event, void *user_data); - static void dev_attach_callback(struct libusbhp_device_t *device, void *user_data); - - static void dev_detach_callback(struct libusbhp_device_t *device, void *user_data); + void dso_ctrl_proc(boost::function<void (const QString)> error_handler); private: DeviceManager &_device_manager; @@ -208,6 +213,8 @@ private: mutable boost::mutex _data_mutex; boost::shared_ptr<data::Logic> _logic_data; boost::shared_ptr<data::LogicSnapshot> _cur_logic_snapshot; + boost::shared_ptr<data::Dso> _dso_data; + boost::shared_ptr<data::DsoSnapshot> _cur_dso_snapshot; boost::shared_ptr<data::Analog> _analog_data; boost::shared_ptr<data::AnalogSnapshot> _cur_analog_snapshot; boost::shared_ptr<data::Group> _group_data; @@ -221,13 +228,18 @@ private: quint64 _total_sample_len; - struct libusbhp_t *_hot_plug_handle; - std::auto_ptr<boost::thread> _hot_plug; + libusb_hotplug_callback_handle _hotplug_handle; + std::auto_ptr<boost::thread> _hotplug; bool _hot_attach; bool _hot_detach; bool _adv_trigger; + bool _vDial_changed; + bool _hDial_changed; + uint16_t _dso_ctrl_channel; + std::auto_ptr<boost::thread> _dso_ctrl_thread; + signals: void capture_state_changed(int state); @@ -246,6 +258,8 @@ signals: void receive_trigger(quint64 trigger_pos); + void dso_ch_changed(uint16_t num); + public slots: diff --git a/DSLogic-gui/pv/toolbars/devicebar.cpp b/DSLogic-gui/pv/toolbars/devicebar.cpp index 1c49f86..3d38a31 100644 --- a/DSLogic-gui/pv/toolbars/devicebar.cpp +++ b/DSLogic-gui/pv/toolbars/devicebar.cpp @@ -31,6 +31,7 @@ #include <QAction>
#include <QDebug>
+#include <QMessageBox>
#include "devicebar.h"
@@ -114,20 +115,20 @@ void DeviceBar::on_device_selected() void DeviceBar::on_configure()
{
- int dev_mode;
+ int dev_mode, ret;
sr_dev_inst *const sdi = get_selected_device();
assert(sdi);
dev_mode = sdi->mode;
pv::dialogs::DeviceOptions dlg(this, sdi);
- //ret = dlg.exec();
- //if (ret == QDialog::Accepted) {
- if (dlg.exec()) {
- if (dev_mode != sdi->mode)
- device_selected();
- else
- device_updated();
+ ret = dlg.exec();
+ if (ret == QDialog::Accepted) {
+ if (dev_mode != sdi->mode) {
+ device_selected();
+ } else {
+ device_updated();
+ }
}
}
diff --git a/DSLogic-gui/pv/toolbars/devicebar.h b/DSLogic-gui/pv/toolbars/devicebar.h index 68b555d..c977fb4 100644 --- a/DSLogic-gui/pv/toolbars/devicebar.h +++ b/DSLogic-gui/pv/toolbars/devicebar.h @@ -54,7 +54,6 @@ public: signals:
void device_selected();
-
void device_updated();
private slots:
diff --git a/DSLogic-gui/pv/toolbars/samplingbar.cpp b/DSLogic-gui/pv/toolbars/samplingbar.cpp index 9c5c2bb..0283939 100644 --- a/DSLogic-gui/pv/toolbars/samplingbar.cpp +++ b/DSLogic-gui/pv/toolbars/samplingbar.cpp @@ -27,6 +27,8 @@ #include <boost/foreach.hpp> +#include <libsigrok4DSLogic/libsigrok.h> + #include <QAction> #include <QDebug> #include <QLabel> @@ -63,24 +65,24 @@ const uint64_t SamplingBar::RecordLengths[19] = { const uint64_t SamplingBar::DefaultRecordLength = 1000000; const uint64_t SamplingBar::DSLogic_RecordLengths[15] = { - 1000, - 2000, - 5000, - 10000, - 20000, - 50000, - 100000, - 200000, - 500000, - 1000000, - 2000000, - 5000000, - 10000000, - 16000000, - 100000000, + 1024, + 2048, + 4096, + 8192, + 16384, + 32768, + 65536, + 131072, + 262144, + 524288, + 1048576, + 2097152, + 4194304, + 8388608, + 16777216, }; -const uint64_t SamplingBar::DSLogic_DefaultRecordLength = 16000000; +const uint64_t SamplingBar::DSLogic_DefaultRecordLength = 16777216; SamplingBar::SamplingBar(QWidget *parent) : QToolBar("Sampling Bar", parent), @@ -106,7 +108,7 @@ SamplingBar::SamplingBar(QWidget *parent) : // if (l == DefaultRecordLength) // _record_length_selector.setCurrentIndex(i); // } - + _record_length_selector.setSizeAdjustPolicy(QComboBox::AdjustToContents); set_sampling(false); //_run_stop_button.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -131,7 +133,7 @@ void SamplingBar::set_device(struct sr_dev_inst *sdi) for (size_t i = 0; i < countof(DSLogic_RecordLengths); i++) { const uint64_t &l = DSLogic_RecordLengths[i]; - char *const text = sr_si_string_u64(l, " samples"); + char *const text = sr_iec_string_u64(l, " samples"); _record_length_selector.addItem(QString(text), qVariantFromValue(l)); g_free(text); @@ -163,18 +165,47 @@ uint64_t SamplingBar::get_record_length() const return _record_length_selector.itemData(index).value<uint64_t>(); } +void SamplingBar::set_record_length(uint64_t length) +{ + for (int i = 0; i < _record_length_selector.count(); i++) { + if (length == _record_length_selector.itemData( + i).value<uint64_t>()) { + _record_length_selector.setCurrentIndex(i); + break; + } + } +} + void SamplingBar::set_sampling(bool sampling) { _run_stop_button.setIcon(sampling ? _icon_stop : _icon_start); //_run_stop_button.setText(sampling ? " Stop" : "Start"); } +void SamplingBar::set_sample_rate(uint64_t sample_rate) +{ + for (int i = 0; i < _sample_rate_list.count(); i++) { + if (sample_rate == _sample_rate_list.itemData( + i).value<uint64_t>()) { + _sample_rate_list.setCurrentIndex(i); + // Set the samplerate + if (sr_config_set(_sdi, SR_CONF_SAMPLERATE, + g_variant_new_uint64(sample_rate)) != SR_OK) { + qDebug() << "Failed to configure samplerate."; + return; + } + break; + } + } + +} + void SamplingBar::update_sample_rate_selector() { GVariant *gvar_dict, *gvar_list; const uint64_t *elements = NULL; gsize num_elements; - QAction *selector_action = NULL; + //QAction *selector_action = NULL; assert(_sample_rate_list_action); @@ -205,7 +236,7 @@ void SamplingBar::update_sample_rate_selector() _sample_rate_list.show(); g_variant_unref(gvar_list); - selector_action = _sample_rate_list_action; + //selector_action = _sample_rate_list_action; } g_variant_unref(gvar_dict); @@ -242,7 +273,9 @@ void SamplingBar::update_sample_rate_selector_value() void SamplingBar::commit_sample_rate() { + GVariant *gvar; uint64_t sample_rate = 0; + uint64_t last_sample_rate = 0; assert(_sdi); @@ -259,12 +292,30 @@ void SamplingBar::commit_sample_rate() if (sample_rate == 0) return; + // Get last samplerate + if (sr_config_get(_sdi->driver, SR_CONF_SAMPLERATE, + &gvar, _sdi) != SR_OK) { + qDebug() << + "WARNING: Failed to get value of sample rate"; + return; + } + last_sample_rate = g_variant_get_uint64(gvar); + g_variant_unref(gvar); + // Set the samplerate if (sr_config_set(_sdi, SR_CONF_SAMPLERATE, g_variant_new_uint64(sample_rate)) != SR_OK) { qDebug() << "Failed to configure samplerate."; return; } + + if (strcmp(_sdi->driver->name, "DSLogic") == 0 && _sdi->mode != DSO) { + if ((last_sample_rate == SR_MHZ(200)&& sample_rate != SR_MHZ(200)) || + (last_sample_rate != SR_MHZ(200) && sample_rate == SR_MHZ(200)) || + (last_sample_rate == SR_MHZ(400)&& sample_rate != SR_MHZ(400)) || + (last_sample_rate != SR_MHZ(400) && sample_rate == SR_MHZ(400))) + device_reload(); + } } void SamplingBar::on_sample_rate_changed() diff --git a/DSLogic-gui/pv/toolbars/samplingbar.h b/DSLogic-gui/pv/toolbars/samplingbar.h index ddd6c16..d02b8e2 100644 --- a/DSLogic-gui/pv/toolbars/samplingbar.h +++ b/DSLogic-gui/pv/toolbars/samplingbar.h @@ -54,9 +54,11 @@ public: SamplingBar(QWidget *parent); uint64_t get_record_length() const; + void set_record_length(uint64_t length); void set_sampling(bool sampling); void update_sample_rate_selector(); + void set_sample_rate(uint64_t sample_rate); void set_device(struct sr_dev_inst *sdi); @@ -66,6 +68,7 @@ public: signals: void run_stop(); + void device_reload(); private: void update_sample_rate_selector_value(); diff --git a/DSLogic-gui/pv/view/analogsignal.cpp b/DSLogic-gui/pv/view/analogsignal.cpp index 1d86310..2e62bfa 100644 --- a/DSLogic-gui/pv/view/analogsignal.cpp +++ b/DSLogic-gui/pv/view/analogsignal.cpp @@ -50,7 +50,7 @@ const QColor AnalogSignal::SignalColours[4] = { const float AnalogSignal::EnvelopeThreshold = 256.0f; -AnalogSignal::AnalogSignal(QString name, shared_ptr<data::Analog> data, +AnalogSignal::AnalogSignal(QString name, boost::shared_ptr<data::Analog> data, int probe_index, int order) : Signal(name, probe_index, DS_ANALOG, order), _data(data) @@ -64,9 +64,11 @@ AnalogSignal::~AnalogSignal() } void AnalogSignal::set_data(boost::shared_ptr<data::Logic> _logic_data, + boost::shared_ptr<data::Dso> _dso_data, boost::shared_ptr<pv::data::Analog> _analog_data, boost::shared_ptr<data::Group> _group_data) { + (void)_dso_data; (void)_logic_data; (void)_group_data; @@ -89,13 +91,13 @@ void AnalogSignal::paint(QPainter &p, int y, int left, int right, double scale, //paint_axis(p, y, left, right); - const deque< shared_ptr<pv::data::AnalogSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::AnalogSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; _scale = _signalHeight * 1.0f / 65536; - const shared_ptr<pv::data::AnalogSnapshot> &snapshot = + const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot = snapshots.front(); if (get_index() >= (int)snapshot->get_channel_num()) @@ -125,7 +127,7 @@ void AnalogSignal::paint(QPainter &p, int y, int left, int right, double scale, } void AnalogSignal::paint_trace(QPainter &p, - const shared_ptr<pv::data::AnalogSnapshot> &snapshot, + const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot, int y, int left, const int64_t start, const int64_t end, const double pixels_offset, const double samples_per_pixel) { @@ -157,7 +159,7 @@ void AnalogSignal::paint_trace(QPainter &p, } void AnalogSignal::paint_envelope(QPainter &p, - const shared_ptr<pv::data::AnalogSnapshot> &snapshot, + const boost::shared_ptr<pv::data::AnalogSnapshot> &snapshot, int y, int left, const int64_t start, const int64_t end, const double pixels_offset, const double samples_per_pixel) { diff --git a/DSLogic-gui/pv/view/analogsignal.h b/DSLogic-gui/pv/view/analogsignal.h index fc38a2e..b954487 100644 --- a/DSLogic-gui/pv/view/analogsignal.h +++ b/DSLogic-gui/pv/view/analogsignal.h @@ -75,6 +75,7 @@ public: void del_decoder(); void set_data(boost::shared_ptr<pv::data::Logic> _logic_data, + boost::shared_ptr<pv::data::Dso> _dso_data, boost::shared_ptr<pv::data::Analog> _analog_data, boost::shared_ptr<pv::data::Group> _group_data); diff --git a/DSLogic-gui/pv/view/dsldial.cpp b/DSLogic-gui/pv/view/dsldial.cpp new file mode 100644 index 0000000..ccdec2e --- /dev/null +++ b/DSLogic-gui/pv/view/dsldial.cpp @@ -0,0 +1,110 @@ +#include "dsldial.h"
+
+#include <assert.h>
+
+namespace pv {
+namespace view {
+
+dslDial::dslDial(quint64 div, quint64 step,
+ QVector<quint64> value, QVector<QString> unit)
+{
+ assert(div > 0);
+ assert(step > 0);
+ assert((quint64)value.count() == div);
+ assert(unit.count() > 0);
+
+ _div = div;
+ _step = step;
+ _value = value;
+ _unit = unit;
+ _sel = 0;
+}
+
+dslDial::~dslDial()
+{
+}
+
+void dslDial::paint(QPainter &p, QRectF dialRect, QColor dialColor)
+{
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(dialColor);
+ p.setBrush(dialColor);
+
+ int dialStartAngle = 225 * 16;
+ int dialSpanAngle = -270 * 16;
+
+ // draw dial arc
+ p.drawArc(dialRect, dialStartAngle, dialSpanAngle);
+ // draw ticks
+ p.save();
+ p.translate(dialRect.center());
+ p.rotate(45);
+ for (quint64 i = 0; i < _div; i++) {
+ // draw major ticks
+ p.drawLine(0, dialRect.width()/2+3, 0, dialRect.width()/2+8);
+ // draw minor ticks
+ for (quint64 j = 0; (j < 5) && (i < _div - 1); j++) {
+ p.drawLine(0, dialRect.width()/2+3, 0, dialRect.width()/2+5);
+ p.rotate(54.0/(_div-1));
+ }
+ }
+ // draw pointer
+ p.rotate(90+270.0/(_div-1)*_sel);
+ p.drawEllipse(-3, -3, 6, 6);
+ p.drawLine(3, 0, 0, dialRect.width()/2-3);
+ p.drawLine(-3, 0, 0, dialRect.width()/2-3);
+ p.restore();
+ // draw value
+ quint64 displayValue = _value[_sel];
+ quint64 displayIndex = 0;
+ while(displayValue / _step >= 1) {
+ displayValue = displayValue / _step;
+ displayIndex++;
+ }
+ QString pText = QString::number(displayValue) + _unit[displayIndex] + "/div";
+ QFontMetrics fm(p.font());
+ p.drawText(QRectF(dialRect.left(), dialRect.bottom()-dialRect.width()*0.3+fm.height()*0.5, dialRect.width(), fm.height()), Qt::AlignCenter, pText);
+
+}
+
+void dslDial::set_sel(quint64 sel)
+{
+ assert(sel < _div);
+
+ _sel = sel;
+}
+
+quint64 dslDial::get_sel()
+{
+ return _sel;
+}
+
+bool dslDial::isMin()
+{
+ if(_sel == 0)
+ return true;
+ else
+ return false;
+}
+
+bool dslDial::isMax()
+{
+ if(_sel == _div - 1)
+ return true;
+ else
+ return false;
+}
+
+quint64 dslDial::get_value()
+{
+ return _value[_sel];
+}
+
+bool dslDial::set_value(quint64 value)
+{
+ assert(_value.contains(value));
+ _sel = _value.indexOf(value, 0);
+}
+
+} // namespace view
+} // namespace pv
diff --git a/DSLogic-gui/pv/view/dsldial.h b/DSLogic-gui/pv/view/dsldial.h new file mode 100644 index 0000000..6925309 --- /dev/null +++ b/DSLogic-gui/pv/view/dsldial.h @@ -0,0 +1,48 @@ +#ifndef DSLOGIC_PV_VIEW_DSLDIAL_H
+#define DSLOGIC_PV_VIEW_DSLDIAL_H
+
+#include <QRect>
+#include <QPainter>
+
+namespace pv {
+namespace view {
+
+class dslDial
+{
+public:
+ dslDial(quint64 div, quint64 step,
+ QVector<quint64> value, QVector<QString> unit);
+ virtual ~dslDial();
+
+public:
+ /**
+ * Paints the dial with a QPainter
+ * @param p the QPainter to paint into.
+ * @param dialRect the rectangle to draw the dial at.
+ **/
+ void paint(QPainter &p, QRectF dialRect, QColor dialColor);
+
+ // set/get current select
+ void set_sel(quint64 sel);
+ quint64 get_sel();
+
+ // boundary detection
+ bool isMin();
+ bool isMax();
+
+ // get current value
+ quint64 get_value();
+ bool set_value(quint64 value);
+
+private:
+ quint64 _div;
+ quint64 _step;
+ QVector<quint64> _value;
+ QVector<QString> _unit;
+ quint64 _sel;
+};
+
+} // namespace view
+} // namespace pv
+
+#endif // DSLOGIC_PV_VIEW_DSLDIAL_H
diff --git a/DSLogic-gui/pv/view/dsosignal.cpp b/DSLogic-gui/pv/view/dsosignal.cpp new file mode 100644 index 0000000..d11108b --- /dev/null +++ b/DSLogic-gui/pv/view/dsosignal.cpp @@ -0,0 +1,224 @@ +/* + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. + * + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include <extdef.h> + +#include <math.h> + +#include "dsosignal.h" +#include "pv/data/dso.h" +#include "pv/data/dsosnapshot.h" + +using namespace boost; +using namespace std; + +namespace pv { +namespace view { + +const QColor DsoSignal::SignalColours[4] = { + QColor(238, 178, 17, 200), // dsYellow + QColor(0, 153, 37, 200), // dsGreen + QColor(213, 15, 37, 200), // dsRed + QColor(17, 133, 209, 200) // dsBlue + +}; + +const float DsoSignal::EnvelopeThreshold = 256.0f; + +DsoSignal::DsoSignal(QString name, boost::shared_ptr<data::Dso> data, + int probe_index, int order, uint64_t vdiv, uint64_t timebase, bool coupling, bool active) : + Signal(name, probe_index, DS_DSO, order), + _data(data) +{ + _colour = SignalColours[probe_index % countof(SignalColours)]; + _scale = _windowHeight * 1.0f / 256; + _vDial->set_value(vdiv); + _hDial->set_value(timebase); + _acCoupling = coupling; + _active = active; +} + +DsoSignal::~DsoSignal() +{ +} + +void DsoSignal::set_data(boost::shared_ptr<data::Logic> _logic_data, + boost::shared_ptr<data::Dso> _dso_data, + boost::shared_ptr<pv::data::Analog> _analog_data, + boost::shared_ptr<data::Group> _group_data) +{ + (void)_analog_data; + (void)_logic_data; + (void)_group_data; + + assert(_dso_data); + + _data = _dso_data; +} + +void DsoSignal::set_scale(float scale) +{ + _scale = scale; +} + +void DsoSignal::paint(QPainter &p, int y, int left, int right, double scale, + double offset) +{ + assert(scale > 0); + assert(_data); + assert(right >= left); + + const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots = + _data->get_snapshots(); + if (snapshots.empty()) + return; + + _scale = _windowHeight * 1.0f / 256; + const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot = + snapshots.front(); + + const uint16_t number_channels = snapshot->get_channel_num(); + if ((unsigned int)get_index() >= number_channels) + return; + + const double pixels_offset = offset / scale; + const double samplerate = _data->get_samplerate(); + const double start_time = _data->get_start_time(); + const int64_t last_sample = max((int64_t)(snapshot->get_sample_count() - 1), (int64_t)0); + const double samples_per_pixel = samplerate * scale; + const double start = samplerate * (offset - start_time); + const double end = start + samples_per_pixel * (right - left); + + const int64_t start_sample = min(max((int64_t)floor(start), + (int64_t)0), last_sample); + const int64_t end_sample = min(max((int64_t)ceil(end) + 1, + (int64_t)0), last_sample); + + if (samples_per_pixel < EnvelopeThreshold) + paint_trace(p, snapshot, y, left, + start_sample, end_sample, + pixels_offset, samples_per_pixel, number_channels); + else + paint_envelope(p, snapshot, y, left, + start_sample, end_sample, + pixels_offset, samples_per_pixel); +} + +void DsoSignal::paint_trace(QPainter &p, + const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot, + int y, int left, const int64_t start, const int64_t end, + const double pixels_offset, const double samples_per_pixel, uint64_t num_channels) +{ + const int64_t sample_count = end - start; + + if (sample_count > 0) { + const uint8_t *const samples = snapshot->get_samples(start, end, get_index()); + assert(samples); + + p.setPen(_colour); + //p.setPen(QPen(_colour, 3, Qt::SolidLine)); + + QPointF *points = new QPointF[sample_count]; + QPointF *point = points; + + for (int64_t sample = start; sample < end; sample++) { + const float x = (sample / samples_per_pixel - pixels_offset) + left; + uint8_t offset = samples[(sample - start)*num_channels]; + *point++ = QPointF(x, + y - offset * _scale); + } + + p.drawPolyline(points, point - points); + + //delete[] samples; + delete[] points; + } +} + +void DsoSignal::paint_envelope(QPainter &p, + const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot, + int y, int left, const int64_t start, const int64_t end, + const double pixels_offset, const double samples_per_pixel) +{ + using namespace Qt; + using pv::data::DsoSnapshot; + + DsoSnapshot::EnvelopeSection e; + snapshot->get_envelope_section(e, start, end, samples_per_pixel, get_index()); + + if (e.length < 2) + return; + + p.setPen(QPen(NoPen)); + //p.setPen(QPen(_colour, 2, Qt::SolidLine)); + p.setBrush(_colour); + + QRectF *const rects = new QRectF[e.length]; + QRectF *rect = rects; + + for(uint64_t sample = 0; sample < e.length-1; sample++) { + const float x = ((e.scale * sample + e.start) / + samples_per_pixel - pixels_offset) + left; + const DsoSnapshot::EnvelopeSample *const s = + e.samples + sample; + + // We overlap this sample with the next so that vertical + // gaps do not appear during steep rising or falling edges + const float b = y - max(s->max, (s+1)->min) * _scale; + const float t = y - min(s->min, (s+1)->max) * _scale; + + float h = b - t; + if(h >= 0.0f && h <= 1.0f) + h = 1.0f; + if(h <= 0.0f && h >= -1.0f) + h = -1.0f; + + *rect++ = QRectF(x, t, 1.0f, h); + } + + p.drawRects(rects, e.length); + + delete[] rects; + //delete[] e.samples; +} + +const std::vector< std::pair<uint64_t, bool> > DsoSignal::cur_edges() const +{ + +} + +void DsoSignal::set_decoder(pv::decoder::Decoder *decoder) +{ + (void)decoder; +} + +decoder::Decoder *DsoSignal::get_decoder() +{ + return NULL; +} + +void DsoSignal::del_decoder() +{ +} + +} // namespace view +} // namespace pv diff --git a/DSLogic-gui/pv/view/dsosignal.h b/DSLogic-gui/pv/view/dsosignal.h new file mode 100644 index 0000000..e22680a --- /dev/null +++ b/DSLogic-gui/pv/view/dsosignal.h @@ -0,0 +1,103 @@ +/* + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. + * + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef DSLOGIC_PV_DSOSIGNAL_H +#define DSLOGIC_PV_DSOSIGNAL_H + +#include "signal.h" + +#include <boost/shared_ptr.hpp> + +namespace pv { + +namespace data { +class Logic; +class Dso; +class Analog; +class DsoSnapshot; +} + +namespace view { + +class DsoSignal : public Signal +{ +private: + static const QColor SignalColours[4]; + + static const float EnvelopeThreshold; + +public: + DsoSignal(QString name, + boost::shared_ptr<pv::data::Dso> data, int probe_index, int order, + uint64_t vdiv, uint64_t timebase, bool coupling, bool active); + + virtual ~DsoSignal(); + + void set_scale(float scale); + + /** + * Paints the signal with a QPainter + * @param p the QPainter to paint into. + * @param y the y-coordinate to draw the signal at. + * @param left the x-coordinate of the left edge of the signal. + * @param right the x-coordinate of the right edge of the signal. + * @param scale the scale in seconds per pixel. + * @param offset the time to show at the left hand edge of + * the view in seconds. + **/ + void paint(QPainter &p, int y, int left, int right, double scale, + double offset); + + const std::vector< std::pair<uint64_t, bool> > cur_edges() const; + + void set_decoder(pv::decoder::Decoder *decoder); + + pv::decoder::Decoder* get_decoder(); + + void del_decoder(); + + void set_data(boost::shared_ptr<pv::data::Logic> _logic_data, + boost::shared_ptr<pv::data::Dso> _dso_data, + boost::shared_ptr<pv::data::Analog> _analog_data, + boost::shared_ptr<pv::data::Group> _group_data); + +private: + void paint_trace(QPainter &p, + const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot, + int y, int left, const int64_t start, const int64_t end, + const double pixels_offset, const double samples_per_pixel, + uint64_t num_channels); + + void paint_envelope(QPainter &p, + const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot, + int y, int left, const int64_t start, const int64_t end, + const double pixels_offset, const double samples_per_pixel); + +private: + boost::shared_ptr<pv::data::Dso> _data; + float _scale; +}; + +} // namespace view +} // namespace pv + +#endif // DSLOGIC_PV_DSOSIGNAL_H diff --git a/DSLogic-gui/pv/view/groupsignal.cpp b/DSLogic-gui/pv/view/groupsignal.cpp index 391779c..5330c06 100644 --- a/DSLogic-gui/pv/view/groupsignal.cpp +++ b/DSLogic-gui/pv/view/groupsignal.cpp @@ -58,10 +58,12 @@ GroupSignal::~GroupSignal() } void GroupSignal::set_data(boost::shared_ptr<data::Logic> _logic_data, + boost::shared_ptr<data::Dso> _dso_data, boost::shared_ptr<pv::data::Analog> _analog_data, boost::shared_ptr<data::Group> _group_data) { (void)_logic_data; + (void)_dso_data; (void)_analog_data; assert(_group_data); @@ -75,7 +77,7 @@ void GroupSignal::set_scale(float scale) } void GroupSignal::paint(QPainter &p, int y, int left, int right, double scale, - double offset) + double offset) { assert(scale > 0); assert(_data); @@ -84,12 +86,12 @@ void GroupSignal::paint(QPainter &p, int y, int left, int right, double scale, _scale = _signalHeight * 1.0f / pow(2, _index_list.size()); paint_axis(p, y, left, right); - const deque< shared_ptr<pv::data::GroupSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::GroupSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::GroupSnapshot> &snapshot = + const boost::shared_ptr<pv::data::GroupSnapshot> &snapshot = snapshots.at(_sec_index); const double pixels_offset = offset / scale; @@ -116,7 +118,7 @@ void GroupSignal::paint(QPainter &p, int y, int left, int right, double scale, } void GroupSignal::paint_trace(QPainter &p, - const shared_ptr<pv::data::GroupSnapshot> &snapshot, + const boost::shared_ptr<pv::data::GroupSnapshot> &snapshot, int y, int left, const int64_t start, const int64_t end, const double pixels_offset, const double samples_per_pixel) { @@ -144,7 +146,7 @@ void GroupSignal::paint_trace(QPainter &p, } void GroupSignal::paint_envelope(QPainter &p, - const shared_ptr<pv::data::GroupSnapshot> &snapshot, + const boost::shared_ptr<pv::data::GroupSnapshot> &snapshot, int y, int left, const int64_t start, const int64_t end, const double pixels_offset, const double samples_per_pixel) { diff --git a/DSLogic-gui/pv/view/groupsignal.h b/DSLogic-gui/pv/view/groupsignal.h index 43f858d..d38d1be 100644 --- a/DSLogic-gui/pv/view/groupsignal.h +++ b/DSLogic-gui/pv/view/groupsignal.h @@ -79,6 +79,7 @@ public: void del_decoder(); void set_data(boost::shared_ptr<pv::data::Logic> _logic_data, + boost::shared_ptr<pv::data::Dso> _dso_data, boost::shared_ptr<pv::data::Analog> _analog_data, boost::shared_ptr<pv::data::Group> _group_data); diff --git a/DSLogic-gui/pv/view/header.cpp b/DSLogic-gui/pv/view/header.cpp index 9bbea0b..6803e3a 100644 --- a/DSLogic-gui/pv/view/header.cpp +++ b/DSLogic-gui/pv/view/header.cpp @@ -39,6 +39,7 @@ #include <QPainter> #include <QRect> #include <QStyleOption> +#include <QMessageBox> using namespace boost; using namespace std; @@ -46,14 +47,6 @@ using namespace std; namespace pv { namespace view { -const int Header::COLOR = 1; -const int Header::NAME = 2; -const int Header::POSTRIG = 3; -const int Header::HIGTRIG = 4; -const int Header::NEGTRIG = 5; -const int Header::LOWTRIG = 6; -const int Header::LABEL = 7; - Header::Header(View &parent) : QWidget(&parent), _view(parent), @@ -90,16 +83,16 @@ int Header::get_nameEditWidth() return 0; } -boost::shared_ptr<pv::view::Signal> Header::get_mouse_over_signal( +boost::shared_ptr<pv::view::Signal> Header::get_mSig( int &action, const QPoint &pt) { const int w = width(); - const vector< shared_ptr<Signal> > sigs( + const vector< boost::shared_ptr<Signal> > sigs( _view.session().get_signals()); const int v_offset = _view.v_offset(); - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) { assert(s); @@ -108,7 +101,7 @@ boost::shared_ptr<pv::view::Signal> Header::get_mouse_over_signal( return s; } - return shared_ptr<Signal>(); + return boost::shared_ptr<Signal>(); } void Header::paintEvent(QPaintEvent*) @@ -122,7 +115,7 @@ void Header::paintEvent(QPaintEvent*) const int w = width(); int action; - const vector< shared_ptr<Signal> > sigs( + const vector< boost::shared_ptr<Signal> > sigs( _view.session().get_signals()); //QPainter painter(this); @@ -130,7 +123,7 @@ void Header::paintEvent(QPaintEvent*) const int v_offset = _view.v_offset(); const bool dragging = !_drag_sigs.empty(); - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) { assert(s); @@ -147,7 +140,7 @@ void Header::paintEvent(QPaintEvent*) w, s->get_old_v_offset() - v_offset - s->get_signalHeight()); painter.drawLine(0, s->get_old_v_offset() - v_offset, w, s->get_old_v_offset() - v_offset); - } else { + } else if (s->get_type() == Signal::DS_LOGIC){ painter.drawLine(0, s->get_old_v_offset() - v_offset + 10, w, s->get_old_v_offset() - v_offset + 10); } @@ -157,7 +150,7 @@ void Header::paintEvent(QPaintEvent*) w, s->get_v_offset() - v_offset); painter.drawLine(0, s->get_v_offset() - v_offset - s->get_signalHeight(), w, s->get_v_offset() - v_offset - s->get_signalHeight()); - } else { + } else if (s->get_type() == Signal::DS_LOGIC) { painter.drawLine(0, s->get_v_offset() - v_offset + 10, w, s->get_v_offset() - v_offset + 10); } @@ -171,7 +164,7 @@ void Header::mousePressEvent(QMouseEvent *event) { assert(event); - const vector< shared_ptr<Signal> > sigs( + const vector< boost::shared_ptr<Signal> > sigs( _view.session().get_signals()); int action; @@ -179,23 +172,24 @@ void Header::mousePressEvent(QMouseEvent *event) _mouse_down_point = event->pos(); // Save the offsets of any signals which will be dragged - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) if (s->selected()) _drag_sigs.push_back( make_pair(s, s->get_v_offset())); // Select the signal if it has been clicked - const shared_ptr<Signal> mouse_over_signal = - get_mouse_over_signal(action, event->pos()); - if (action == COLOR && mouse_over_signal) { + const boost::shared_ptr<Signal> mSig = + get_mSig(action, event->pos()); + if (action == Signal::COLOR && mSig) { _colorFlag = true; - } else if (action == NAME && mouse_over_signal) { + } else if (action == Signal::NAME && mSig) { _nameFlag = true; - } else if (action == LABEL && mouse_over_signal) { - if (mouse_over_signal->selected()) - mouse_over_signal->select(false); + } else if (action == Signal::LABEL && mSig) { + if (mSig->selected()) + mSig->select(false); else { - mouse_over_signal->select(true); + if (mSig->get_type() != Signal::DS_DSO) + mSig->select(true); if (~QApplication::keyboardModifiers() & Qt::ControlModifier) @@ -204,37 +198,91 @@ void Header::mousePressEvent(QMouseEvent *event) // Add the signal to the drag list if (event->button() & Qt::LeftButton) _drag_sigs.push_back( - make_pair(mouse_over_signal, - mouse_over_signal->get_v_offset())); + make_pair(mSig, + (mSig->get_type() == Signal::DS_DSO) ? mSig->get_zeroPos() : mSig->get_v_offset())); } - mouse_over_signal->set_old_v_offset(mouse_over_signal->get_v_offset()); - } else if (action == POSTRIG && mouse_over_signal) { - if (mouse_over_signal->get_trig() == POSTRIG) - mouse_over_signal->set_trig(0); + mSig->set_old_v_offset(mSig->get_v_offset()); + } else if (action == Signal::POSTRIG && mSig) { + if (mSig->get_trig() == Signal::POSTRIG) + mSig->set_trig(0); else - mouse_over_signal->set_trig(POSTRIG); - } else if (action == HIGTRIG && mouse_over_signal) { - if (mouse_over_signal->get_trig() == HIGTRIG) - mouse_over_signal->set_trig(0); + mSig->set_trig(Signal::POSTRIG); + } else if (action == Signal::HIGTRIG && mSig) { + if (mSig->get_trig() == Signal::HIGTRIG) + mSig->set_trig(0); else - mouse_over_signal->set_trig(HIGTRIG); - } else if (action == NEGTRIG && mouse_over_signal) { - if (mouse_over_signal->get_trig() == NEGTRIG) - mouse_over_signal->set_trig(0); + mSig->set_trig(Signal::HIGTRIG); + } else if (action == Signal::NEGTRIG && mSig) { + if (mSig->get_trig() == Signal::NEGTRIG) + mSig->set_trig(0); else - mouse_over_signal->set_trig(NEGTRIG); - } else if (action == LOWTRIG && mouse_over_signal) { - if (mouse_over_signal->get_trig() == LOWTRIG) - mouse_over_signal->set_trig(0); + mSig->set_trig(Signal::NEGTRIG); + } else if (action == Signal::LOWTRIG && mSig) { + if (mSig->get_trig() == Signal::LOWTRIG) + mSig->set_trig(0); else - mouse_over_signal->set_trig(LOWTRIG); + mSig->set_trig(Signal::LOWTRIG); + } else if (action == Signal::EDGETRIG && mSig) { + if (mSig->get_trig() == Signal::EDGETRIG) + mSig->set_trig(0); + else + mSig->set_trig(Signal::EDGETRIG); + } else if (action == Signal::VDIAL && mSig) { + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + s->set_hDialActive(false); + if (s != mSig) { + s->set_vDialActive(false); + } + } + mSig->set_vDialActive(!mSig->get_vDialActive()); + } else if (action == Signal::HDIAL && mSig) { + if (mSig->get_hDialActive()) { + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + s->set_vDialActive(false); + s->set_hDialActive(false); + } + } else { + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + s->set_vDialActive(false); + s->set_hDialActive(true); + } + } + } else if (action == Signal::CHEN && mSig) { + int channel; + if (mSig->get_index() == 0) { + bool last = 1; + channel = 0; + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + if (s->get_index() != 0 && s->get_active()) { + QMessageBox msg(this); + msg.setText("Tips"); + msg.setInformativeText("If only one channel want, Channel0 has a higher maximum sample rate!"); + msg.setStandardButtons(QMessageBox::Ok); + msg.setIcon(QMessageBox::Information); + msg.exec(); + s->set_active(!s->get_active()); + last = 0; + channel = s->get_index(); + break; + } + } + if (last) + mSig->set_active(!mSig->get_active()); + } else { + mSig->set_active(!mSig->get_active()); + channel = mSig->get_index(); + } + ch_changed(channel); + } else if (action == Signal::ACDC && mSig) { + mSig->set_acCoupling(!mSig->get_acCoupling()); + acdc_changed(mSig->get_index()); } if (~QApplication::keyboardModifiers() & Qt::ControlModifier) { // Unselect all other signals because the Ctrl is not // pressed - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) - if (s != mouse_over_signal) + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) + if (s != mSig) s->select(false); } update(); @@ -247,15 +295,15 @@ void Header::mouseReleaseEvent(QMouseEvent *event) // judge for color / name / trigger / move int action; - const shared_ptr<Signal> mouse_over_signal = - get_mouse_over_signal(action, event->pos()); - if (mouse_over_signal){ - if (action == COLOR && _colorFlag) { - _context_signal = mouse_over_signal; + const boost::shared_ptr<Signal> mSig = + get_mSig(action, event->pos()); + if (mSig){ + if (action == Signal::COLOR && _colorFlag) { + _context_signal = mSig; changeColor(event); _view.set_need_update(true); - } else if (action == NAME && _nameFlag) { - _context_signal = mouse_over_signal; + } else if (action == Signal::NAME && _nameFlag) { + _context_signal = mSig; changeName(event); } } @@ -270,12 +318,48 @@ void Header::mouseReleaseEvent(QMouseEvent *event) _view.normalize_layout(); } +void Header::wheelEvent(QWheelEvent *event) +{ + assert(event); + + if (event->orientation() == Qt::Vertical) { + const vector< shared_ptr<Signal> > sigs( + _view.session().get_signals()); + // Vertical scrolling + double shift = event->delta() / 20.0; + if (shift > 1.0) { + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + if (s->get_vDialActive()) { + if(s->go_vDialNext()) + vDial_changed(s->get_index()); + break; + } else if (s->get_hDialActive()) { + if(s->go_hDialNext()) + hDial_changed(0); + } + } + } else if (shift < -1.0) { + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + if (s->get_vDialActive()) { + if(s->go_vDialPre()) + vDial_changed(s->get_index()); + break; + } else if (s->get_hDialActive()) { + if(s->go_hDialPre()) + hDial_changed(0); + } + } + } + update(); + } +} + void Header::move(QMouseEvent *event) { bool _moveValid = false; bool _moveUp = false; bool firstCheck = true; - const vector< shared_ptr<Signal> > sigs( + const vector< boost::shared_ptr<Signal> > sigs( _view.session().get_signals()); boost::shared_ptr<Signal> minDragSig; boost::shared_ptr<Signal> maxDragSig; @@ -323,7 +407,7 @@ void Header::move(QMouseEvent *event) } if (!_moveValid && firstCheck){ firstCheck = false; - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) { if (_moveUp) { if (s->selected()) { if ((minOffset <= s->get_old_v_offset()) && (minOffset > (s->get_old_v_offset() - _view.get_spanY()))) { @@ -360,7 +444,7 @@ void Header::move(QMouseEvent *event) } } if (_moveValid) { - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) { if (_moveUp) { if (s->selected() && s == minDragSig) { s->set_v_offset(targetOffset); @@ -393,7 +477,7 @@ void Header::move(QMouseEvent *event) if (_moveValid) { signals_moved(); } else { - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) { if (s->selected()) { s->set_v_offset(s->get_old_v_offset()); s->select(false); @@ -439,24 +523,31 @@ void Header::mouseMoveEvent(QMouseEvent *event) i != _drag_sigs.end(); i++) { const boost::shared_ptr<Signal> sig((*i).first); if (sig) { - const int y = (*i).second + delta; - const int y_snap = - ((y + View::SignalSnapGridSize / 2) / - View::SignalSnapGridSize) * - View::SignalSnapGridSize; - if (y_snap != sig->get_v_offset()) { - _moveFlag = true; - sig->set_v_offset(y_snap); + int y = (*i).second + delta; + if (sig->get_type() != Signal::DS_DSO) { + const int y_snap = + ((y + View::SignalSnapGridSize / 2) / + View::SignalSnapGridSize) * + View::SignalSnapGridSize; + if (y_snap != sig->get_v_offset()) { + _moveFlag = true; + sig->set_v_offset(y_snap); + } + // Ensure the signal is selected + sig->select(true); + } else { + if (y < 0) + y = 0; + else if (y > height()) + y = height(); + sig->set_zeroPos(y); + sig->select(false); + signals_moved(); } - // Ensure the signal is selected - sig->select(true); } - } - //signals_moved(); } - update(); } @@ -470,10 +561,9 @@ void Header::contextMenuEvent(QContextMenuEvent *event) { int action; - const shared_ptr<Signal> s = get_mouse_over_signal(action, _mouse_point); + const boost::shared_ptr<Signal> s = get_mSig(action, _mouse_point); - //if (!s || action != LABEL) - if (!s || !s->selected() || action != LABEL) + if (!s || !s->selected() || action != Signal::LABEL) return; QMenu menu(this); @@ -489,7 +579,7 @@ void Header::contextMenuEvent(QContextMenuEvent *event) void Header::on_action_set_name_triggered() { - shared_ptr<view::Signal> context_signal = _context_signal; + boost::shared_ptr<view::Signal> context_signal = _context_signal; if (!context_signal) return; diff --git a/DSLogic-gui/pv/view/header.h b/DSLogic-gui/pv/view/header.h index 1756278..3e16f27 100644 --- a/DSLogic-gui/pv/view/header.h +++ b/DSLogic-gui/pv/view/header.h @@ -47,16 +47,7 @@ public: Header(View &parent); private: - static const int COLOR; - static const int NAME; - static const int POSTRIG; - static const int HIGTRIG; - static const int NEGTRIG; - static const int LOWTRIG; - static const int LABEL; - -private: - boost::shared_ptr<pv::view::Signal> get_mouse_over_signal( + boost::shared_ptr<pv::view::Signal> get_mSig( int &action, const QPoint &pt); @@ -65,13 +56,10 @@ private: private: void mousePressEvent(QMouseEvent * event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void leaveEvent(QEvent *event); - + void wheelEvent(QWheelEvent *event); void contextMenuEvent(QContextMenuEvent *event); void move(QMouseEvent *event); @@ -93,8 +81,11 @@ private slots: signals: void signals_moved(); - void header_updated(); + void vDial_changed(quint16); + void hDial_changed(quint16); + void acdc_changed(quint16); + void ch_changed(quint16); private: View &_view; diff --git a/DSLogic-gui/pv/view/logicsignal.cpp b/DSLogic-gui/pv/view/logicsignal.cpp index 5e66bb7..f9fae10 100644 --- a/DSLogic-gui/pv/view/logicsignal.cpp +++ b/DSLogic-gui/pv/view/logicsignal.cpp @@ -65,7 +65,7 @@ const QColor LogicSignal::SignalColours[8] = { const int LogicSignal::StateHeight = 12; const int LogicSignal::StateRound = 5; -LogicSignal::LogicSignal(QString name, shared_ptr<data::Logic> data, +LogicSignal::LogicSignal(QString name, boost::shared_ptr<data::Logic> data, int probe_index, int order) : Signal(name, probe_index, DS_LOGIC, order), _probe_index(probe_index), @@ -82,9 +82,11 @@ LogicSignal::~LogicSignal() } void LogicSignal::set_data(boost::shared_ptr<data::Logic> _logic_data, + boost::shared_ptr<data::Dso> _dso_data, boost::shared_ptr<pv::data::Analog> _analog_data, boost::shared_ptr<data::Group> _group_data) { + (void)_dso_data; (void)_analog_data; (void)_group_data; @@ -110,12 +112,12 @@ void LogicSignal::paint(QPainter &p, int y, int left, int right, const float high_offset = y - _signalHeight + 0.5f; const float low_offset = y + 0.5f; - const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots = + const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots = _data->get_snapshots(); if (snapshots.empty()) return; - const shared_ptr<pv::data::LogicSnapshot> &snapshot = + const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot = snapshots.front(); double samplerate = _data->get_samplerate(); diff --git a/DSLogic-gui/pv/view/logicsignal.h b/DSLogic-gui/pv/view/logicsignal.h index 39dd388..fa407f2 100644 --- a/DSLogic-gui/pv/view/logicsignal.h +++ b/DSLogic-gui/pv/view/logicsignal.h @@ -62,6 +62,7 @@ public: virtual ~LogicSignal(); void set_data(boost::shared_ptr<pv::data::Logic> _logic_data, + boost::shared_ptr<pv::data::Dso> _dso_data, boost::shared_ptr<pv::data::Analog> _analog_data, boost::shared_ptr<pv::data::Group> _group_data); /** diff --git a/DSLogic-gui/pv/view/protocolsignal.cpp b/DSLogic-gui/pv/view/protocolsignal.cpp index 91834d3..9ad3830 100644 --- a/DSLogic-gui/pv/view/protocolsignal.cpp +++ b/DSLogic-gui/pv/view/protocolsignal.cpp @@ -41,7 +41,7 @@ namespace view { const int ProtocolSignal::StateHeight = 16;
const int ProtocolSignal::StateRound = 3;
-ProtocolSignal::ProtocolSignal(QString name, shared_ptr<data::Logic> data,
+ProtocolSignal::ProtocolSignal(QString name, boost::shared_ptr<data::Logic> data,
pv::decoder::Decoder *decoder, std::list<int> probe_index_list, int order, int protocol_index) :
Signal(name, probe_index_list, DS_PROTOCOL, order, protocol_index),
_probe_index_list(probe_index_list),
@@ -55,10 +55,11 @@ ProtocolSignal::~ProtocolSignal() {
}
-void ProtocolSignal::set_data(boost::shared_ptr<data::Logic> _logic_data,
+void ProtocolSignal::set_data(boost::shared_ptr<data::Logic> _logic_data, boost::shared_ptr<data::Dso> _dso_data,
boost::shared_ptr<pv::data::Analog> _analog_data,
boost::shared_ptr<data::Group> _group_data)
{
+ (void)_dso_data;
(void)_analog_data;
(void)_group_data;
@@ -86,12 +87,12 @@ void ProtocolSignal::paint(QPainter &p, int y, int left, int right, double scale const float middle_offset = y - _signalHeight / 2 + 0.5f;
//const float low_offset = y + 0.5f;
- const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots =
+ const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
_data->get_snapshots();
if (snapshots.empty())
return;
- const shared_ptr<pv::data::LogicSnapshot> &snapshot =
+ const boost::shared_ptr<pv::data::LogicSnapshot> &snapshot =
snapshots.front();
double samplerate = _data->get_samplerate();
diff --git a/DSLogic-gui/pv/view/protocolsignal.h b/DSLogic-gui/pv/view/protocolsignal.h index e608be4..2e37ab8 100644 --- a/DSLogic-gui/pv/view/protocolsignal.h +++ b/DSLogic-gui/pv/view/protocolsignal.h @@ -57,6 +57,7 @@ public: virtual ~ProtocolSignal();
void set_data(boost::shared_ptr<pv::data::Logic> _logic_data,
+ boost::shared_ptr<pv::data::Dso> _dso_data,
boost::shared_ptr<pv::data::Analog> _analog_data,
boost::shared_ptr<pv::data::Group> _group_data);
diff --git a/DSLogic-gui/pv/view/ruler.cpp b/DSLogic-gui/pv/view/ruler.cpp index 1441318..f049beb 100644 --- a/DSLogic-gui/pv/view/ruler.cpp +++ b/DSLogic-gui/pv/view/ruler.cpp @@ -99,7 +99,7 @@ QString Ruler::format_freq(double period, unsigned precision) assert(order >= FirstSIPrefixPower); const unsigned int prefix = ceil((order - FirstSIPrefixPower) / 3.0f); const double multiplier = pow(10.0, - - prefix * 3 - FirstSIPrefixPower); + static_cast<double>(- prefix * 3 - FirstSIPrefixPower)); QString s; QTextStream ts(&s); @@ -114,7 +114,7 @@ QString Ruler::format_time(double t, unsigned int prefix, unsigned int precision) { const double multiplier = pow(10.0, - - prefix * 3 - FirstSIPrefixPower); + static_cast<double>(- prefix * 3 - FirstSIPrefixPower)); QString s; QTextStream ts(&s); @@ -318,7 +318,7 @@ void Ruler::draw_tick_mark(QPainter &p) //const int order = (int)floorf(log10f(_min_period)); const int order = ceil(log10f(_min_period)); - const double order_decimal = pow(10, order); + const double order_decimal = pow(10.0, static_cast<double>(order)); unsigned int unit = 0; diff --git a/DSLogic-gui/pv/view/signal.cpp b/DSLogic-gui/pv/view/signal.cpp index 2ac4e92..11ef319 100644 --- a/DSLogic-gui/pv/view/signal.cpp +++ b/DSLogic-gui/pv/view/signal.cpp @@ -33,26 +33,67 @@ namespace pv { namespace view { -const int Signal::SquareWidth = 20; -const int Signal::Margin = 5; - -const int Signal::COLOR = 1; -const int Signal::NAME = 2; -const int Signal::POSTRIG = 3; -const int Signal::HIGTRIG = 4; -const int Signal::NEGTRIG = 5; -const int Signal::LOWTRIG = 6; -const int Signal::LABEL = 7; - const QColor Signal::dsBlue = QColor(17, 133, 209, 255); const QColor Signal::dsYellow = QColor(238, 178, 17, 255); const QColor Signal::dsRed = QColor(213, 15, 37, 255); const QColor Signal::dsGreen = QColor(0, 153, 37, 255); const QColor Signal::dsGray = QColor(0x88, 0x8A, 0x85, 100); +const QColor Signal::dsDisable = QColor(0x88, 0x8A, 0x85, 200); +const QColor Signal::dsActive = QColor(17, 133, 209, 255); const QColor Signal::dsLightBlue = QColor(17, 133, 209, 150); const QColor Signal::dsLightRed = QColor(213, 15, 37, 150); - -const QPen Signal::SignalAxisPen(QColor(128, 128, 128, 64)); +const QPen Signal::SignalAxisPen = QColor(128, 128, 128, 64); + +const quint64 Signal::vDialValue[Signal::vDialValueCount] = { + 5, + 10, + 20, + 50, + 100, + 200, + 500, + 1000, + 2000, + 5000, +}; +const QString Signal::vDialUnit[Signal::vDialUnitCount] = { + "mv", + "v", +}; + +const quint64 Signal::hDialValue[Signal::hDialValueCount] = { + 10, + 20, + 50, + 100, + 200, + 500, + 1000, + 2000, + 5000, + 10000, + 20000, + 50000, + 100000, + 200000, + 500000, + 1000000, + 2000000, + 5000000, + 10000000, + 20000000, + 50000000, + 100000000, + 200000000, + 500000000, + 1000000000, +}; +const QString Signal::hDialUnit[Signal::hDialUnitCount] = { + "ns", + "us", + "ms", + "s", +}; Signal::Signal(QString name, int index, int type, int order) : _type(type), @@ -62,9 +103,37 @@ Signal::Signal(QString name, int index, int type, int order) : _v_offset(0), _signalHeight(30), _selected(false), - _trig(0) + _trig(0), + _vDialActive(false), + _hDialActive(false), + _acCoupling(false), + _active(true), + _windowHeight(0) { _index_list.push_back(index); + if (_type == DS_DSO) { + QVector<quint64> vValue; + QVector<QString> vUnit; + QVector<quint64> hValue; + QVector<QString> hUnit; + for(quint64 i = 0; i < Signal::vDialValueCount; i++) + vValue.append(Signal::vDialValue[i]); + for(quint64 i = 0; i < Signal::vDialUnitCount; i++) + vUnit.append(Signal::vDialUnit[i]); + + for(quint64 i = 0; i < Signal::hDialValueCount; i++) + hValue.append(Signal::hDialValue[i]); + for(quint64 i = 0; i < Signal::hDialUnitCount; i++) + hUnit.append(Signal::hDialUnit[i]); + + _vDial = new dslDial(vDialValueCount, vDialValueStep, vValue, vUnit); + _hDial = new dslDial(hDialValueCount, hDialValueStep, hValue, hUnit); + _vDial->set_sel(0); + _hDial->set_sel(0); + + _trig_vpos = 0; + _trig_en = true; + } } Signal::Signal(QString name, std::list<int> index_list, int type, int order, int sec_index) : @@ -76,8 +145,32 @@ Signal::Signal(QString name, std::list<int> index_list, int type, int order, int _v_offset(0), _signalHeight(30), _selected(false), - _trig(0) -{ + _trig(0), + _vDialActive(false), + _hDialActive(false), + _acCoupling(false), + _active(true) +{ + if (_type == DS_DSO) { + QVector<quint64> vValue; + QVector<QString> vUnit; + QVector<quint64> hValue; + QVector<QString> hUnit; + for(quint64 i = 0; i < Signal::vDialValueCount; i++) + vValue.append(Signal::vDialValue[i]); + for(quint64 i = 0; i < Signal::vDialUnitCount; i++) + vUnit.append(Signal::vDialUnit[i]); + + for(quint64 i = 0; i < Signal::hDialValueCount; i++) + hValue.append(Signal::hDialValue[i]); + for(quint64 i = 0; i < Signal::hDialUnitCount; i++) + hUnit.append(Signal::hDialUnit[i]); + + _vDial = new dslDial(Signal::vDialValueCount, Signal::vDialValueStep, vValue, vUnit); + _hDial = new dslDial(Signal::hDialValueCount, Signal::hDialValueStep, hValue, hUnit); + _vDial->set_sel(0); + _hDial->set_sel(0); + } } int Signal::get_type() const @@ -104,7 +197,7 @@ int Signal::get_leftWidth() const int Signal::get_rightWidth() const { - return 2 * Margin + 4 * SquareWidth + 1.5 * SquareWidth; + return 2 * Margin + SquareNum * SquareWidth + 1.5 * SquareWidth; } int Signal::get_headerHeight() const @@ -217,31 +310,174 @@ void Signal::set_trig(int trig) ds_trigger_probe_set(_index_list.front(), 'F', 'X'); else if (trig == LOWTRIG) ds_trigger_probe_set(_index_list.front(), '0', 'X'); + else if (trig == EDGETRIG) + ds_trigger_probe_set(_index_list.front(), 'C', 'X'); +} + +bool Signal::get_vDialActive() const +{ + return _vDialActive; +} + +void Signal::set_vDialActive(bool active) +{ + _vDialActive = active; +} + +bool Signal::go_vDialPre() +{ + assert(_type == DS_DSO); + + if (!_vDial->isMin()) { + _vDial->set_sel(_vDial->get_sel() - 1); + return true; + } else { + return false; + } +} + +bool Signal::go_vDialNext() +{ + assert(_type == DS_DSO); + + if (!_vDial->isMax()) { + _vDial->set_sel(_vDial->get_sel() + 1); + return true; + } else { + return false; + } +} + +bool Signal::get_hDialActive() const +{ + return _hDialActive; +} + +void Signal::set_hDialActive(bool active) +{ + _hDialActive = active; +} + +bool Signal::go_hDialPre() +{ + assert(_type == DS_DSO); + + if (!_hDial->isMin()) { + _hDial->set_sel(_hDial->get_sel() - 1); + return true; + } else { + return false; + } +} + +bool Signal::go_hDialNext() +{ + assert(_type == DS_DSO); + + if (!_hDial->isMax()) { + _hDial->set_sel(_hDial->get_sel() + 1); + return true; + } else { + return false; + } +} + +quint64 Signal::get_vDialValue() const +{ + return _vDial->get_value(); +} + +quint64 Signal::get_hDialValue() const +{ + return _hDial->get_value(); +} + +uint16_t Signal::get_vDialSel() const +{ + return _vDial->get_sel(); +} + +uint16_t Signal::get_hDialSel() const +{ + return _hDial->get_sel(); +} + +bool Signal::get_acCoupling() const +{ + return _acCoupling; +} + +void Signal::set_acCoupling(bool coupling) +{ + _acCoupling = coupling; +} + +bool Signal::get_active() const +{ + return _active; +} + +void Signal::set_active(bool active) +{ + _active = active; +} + +int Signal::get_zeroPos() const +{ + return _zeroPos; +} + +void Signal::set_zeroPos(int pos) +{ + _zeroPos = pos; +} + +int Signal::get_windowHeight() const +{ + return _windowHeight; +} + +void Signal::set_windowHeight(int height) +{ + _windowHeight = height; +} + +int Signal::get_trig_vpos() const +{ + return _trig_vpos; +} + +void Signal::set_trig_vpos(int value) +{ + _trig_vpos = value; } void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action) { compute_text_size(p); + const QRectF color_rect = get_rect("color", y, right); const QRectF name_rect = get_rect("name", y, right); - const QRectF posTrig_rect = get_rect("posTrig", y, right); - const QRectF higTrig_rect = get_rect("higTrig", y, right); - const QRectF negTrig_rect = get_rect("negTrig", y, right); - const QRectF lowTrig_rect = get_rect("lowTrig", y, right); - const QRectF label_rect = get_rect("label", y, right); + const QRectF label_rect = get_rect("label", (_type == DS_DSO) ? _zeroPos : y, right); p.setRenderHint(QPainter::Antialiasing); // Paint the ColorButton p.setPen(Qt::transparent); - p.setBrush(_colour); + p.setBrush(_active ? _colour : dsDisable); p.drawRect(color_rect); // Paint the signal name - p.setPen(Qt::black); + p.setPen(_active ? Qt::black : dsDisable); p.drawText(name_rect, Qt::AlignLeft | Qt::AlignVCenter, _name); // Paint the trigButton - if (_type == DS_LOGIC) { + if (_type == DS_LOGIC) { + const QRectF posTrig_rect = get_rect("posTrig", y, right); + const QRectF higTrig_rect = get_rect("higTrig", y, right); + const QRectF negTrig_rect = get_rect("negTrig", y, right); + const QRectF lowTrig_rect = get_rect("lowTrig", y, right); + const QRectF edgeTrig_rect = get_rect("edgeTrig", y, right); + p.setPen(Qt::transparent); p.setBrush(((hover && action == POSTRIG) || (_trig == POSTRIG)) ? dsYellow : @@ -259,6 +495,10 @@ void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action) dsYellow : dsBlue); p.drawRect(lowTrig_rect); + p.setBrush(((hover && action == EDGETRIG) || (_trig == EDGETRIG)) ? + dsYellow : + dsBlue); + p.drawRect(edgeTrig_rect); p.setPen(QPen(Qt::blue, 1, Qt::DotLine)); p.setBrush(Qt::transparent); @@ -268,6 +508,8 @@ void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action) higTrig_rect.right(), higTrig_rect.bottom() - 3); p.drawLine(negTrig_rect.right(), negTrig_rect.top() + 3, negTrig_rect.right(), negTrig_rect.bottom() - 3); + p.drawLine(lowTrig_rect.right(), lowTrig_rect.top() + 3, + lowTrig_rect.right(), lowTrig_rect.bottom() - 3); p.setPen(QPen(Qt::white, 2, Qt::SolidLine)); p.setBrush(Qt::transparent); @@ -290,6 +532,17 @@ void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action) p.drawLine(lowTrig_rect.left() + 5, lowTrig_rect.bottom() - 5, lowTrig_rect.right() - 5, lowTrig_rect.bottom() - 5); + + p.drawLine(edgeTrig_rect.left() + 5, edgeTrig_rect.top() + 5, + edgeTrig_rect.center().x() - 2, edgeTrig_rect.top() + 5); + p.drawLine(edgeTrig_rect.center().x() + 2 , edgeTrig_rect.top() + 5, + edgeTrig_rect.right() - 5, edgeTrig_rect.top() + 5); + p.drawLine(edgeTrig_rect.center().x(), edgeTrig_rect.top() + 7, + edgeTrig_rect.center().x(), edgeTrig_rect.bottom() - 7); + p.drawLine(edgeTrig_rect.left() + 5, edgeTrig_rect.bottom() - 5, + edgeTrig_rect.center().x() - 2, edgeTrig_rect.bottom() - 5); + p.drawLine(edgeTrig_rect.center().x() + 2, edgeTrig_rect.bottom() - 5, + edgeTrig_rect.right() - 5, edgeTrig_rect.bottom() - 5); } else if (_type == DS_GROUP || _type == DS_PROTOCOL) { const QRectF group_index_rect = get_rect("groupIndex", y, right); QString index_string; @@ -311,40 +564,92 @@ void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action) } p.setPen(Qt::white); p.drawText(group_index_rect, Qt::AlignRight | Qt::AlignVCenter, index_string); + } else if (_type == DS_DSO) { + const QRectF vDial_rect = get_rect("vDial", y, right); + const QRectF hDial_rect = get_rect("hDial", y, right); + const QRectF acdc_rect = get_rect("acdc", y, right); + const QRectF chEn_rect = get_rect("chEn", y, right); + + QColor vDial_color = _vDialActive ? dsActive : dsDisable; + QColor hDial_color = _hDialActive ? dsActive : dsDisable; + _vDial->paint(p, vDial_rect, vDial_color); + _hDial->paint(p, hDial_rect, hDial_color); + + p.setPen(Qt::transparent); + p.setBrush((hover && action == CHEN) ? _colour.darker() : _colour); + p.drawRect(chEn_rect); + p.setPen(Qt::white); + p.drawText(chEn_rect, Qt::AlignCenter | Qt::AlignVCenter, _active ? "EN" : "DIS"); + + p.setPen(Qt::transparent); + p.setBrush(_active ? ((hover && action == ACDC) ? _colour.darker() : _colour) : dsDisable); + p.drawRect(acdc_rect); + p.setPen(Qt::white); + p.drawText(acdc_rect, Qt::AlignCenter | Qt::AlignVCenter, _acCoupling ? "AC" : "DC"); } // Paint the label - const QPointF points[] = { - label_rect.topLeft(), - label_rect.topRight(), - QPointF(right, y), - label_rect.bottomRight(), - label_rect.bottomLeft() - }; - - p.setPen(Qt::transparent); - p.setBrush(((hover && action == LABEL) || _selected) ? dsYellow : dsBlue); - p.drawPolygon(points, countof(points)); - - if ((hover && action == LABEL) || _selected) { - p.setPen(QPen(dsBlue, 2, Qt::DotLine)); + if (_active) { + const QPointF points[] = { + label_rect.topLeft(), + label_rect.topRight(), + QPointF(right, (_type == DS_DSO) ? _zeroPos : y), + label_rect.bottomRight(), + label_rect.bottomLeft() + }; + + p.setPen(Qt::transparent); + if (_type == DS_DSO) + p.setBrush(((hover && action == LABEL) || _selected) ? _colour.darker() : _colour); + else + p.setBrush(((hover && action == LABEL) || _selected) ? dsYellow : dsBlue); + p.drawPolygon(points, countof(points)); + + p.setPen(QPen(Qt::blue, 1, Qt::DotLine)); p.setBrush(Qt::transparent); - p.drawPoint(label_rect.right(), label_rect.top() + 4); - p.drawPoint(label_rect.right(), label_rect.top() + 8); - p.drawPoint(label_rect.right(), label_rect.top() + 12); - p.drawPoint(label_rect.right(), label_rect.top() + 16); + p.drawLine(label_rect.right(), label_rect.top() + 3, + label_rect.right(), label_rect.bottom() - 3); + + // Paint the text + p.setPen(Qt::white); + if (_type == DS_GROUP) + p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "G"); + else if (_type == DS_ANALOG) + p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "A"); + else if (_type == DS_PROTOCOL) + p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "D"); + else + p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, QString::number(_index_list.front())); } +} - // Paint the text - p.setPen(Qt::white); - if (_type == DS_GROUP) - p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "G"); - else if (_type == DS_ANALOG) - p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "A"); - else if (_type == DS_PROTOCOL) - p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "D"); - else - p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, QString::number(_index_list.front())); +void Signal::paint_trig(QPainter &p, int left, int right, bool hover) +{ + if (_type == DS_DSO) { + const QRectF label_rect = get_rect("dsoTrig", -1, right); + // Paint the trig line + if (_trig_en) { + const QPointF points[] = { + QPointF(right - label_rect.width()*1.5, _trig_vpos), + label_rect.topLeft(), + label_rect.topRight(), + label_rect.bottomRight(), + label_rect.bottomLeft() + }; + + p.setPen(Qt::transparent); + p.setBrush(_colour); + p.drawPolygon(points, countof(points)); + + // paint the _trig_vpos line + p.setPen(QPen(_colour, hover ? 2 : 1, Qt::DashLine)); + p.drawLine(left, _trig_vpos, right - label_rect.width()*1.5, _trig_vpos); + + // Paint the text + p.setPen(Qt::white); + p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "T"); + } + } } int Signal::pt_in_rect(int y, int right, const QPoint &point) @@ -355,11 +660,17 @@ int Signal::pt_in_rect(int y, int right, const QPoint &point) const QRectF higTrig = get_rect("higTrig", y, right); const QRectF negTrig = get_rect("negTrig", y, right); const QRectF lowTrig = get_rect("lowTrig", y, right); - const QRectF label = get_rect("label", y, right); - - if (color.contains(point)) + const QRectF edgeTrig = get_rect("edgeTrig", y, right); + const QRectF label = get_rect("label", (_type == DS_DSO) ? _zeroPos : y, right); + const QRectF vDial = get_rect("vDial", y, right); + const QRectF hDial = get_rect("hDial", y, right); + const QRectF chEn = get_rect("chEn", y, right); + const QRectF acdc = get_rect("acdc", y, right); + const QRectF dsoTrig = get_rect("dsoTrig", 0, right); + + if (color.contains(point) && _active) return COLOR; - else if (name.contains(point)) + else if (name.contains(point) && _active) return NAME; else if (posTrig.contains(point) && _type == DS_LOGIC) return POSTRIG; @@ -369,8 +680,20 @@ int Signal::pt_in_rect(int y, int right, const QPoint &point) return NEGTRIG; else if (lowTrig.contains(point) && _type == DS_LOGIC) return LOWTRIG; - else if (label.contains(point)) + else if (edgeTrig.contains(point) && _type == DS_LOGIC) + return EDGETRIG; + else if (label.contains(point) && _active) return LABEL; + else if (vDial.contains(point) && _type == DS_DSO && _active) + return VDIAL; + else if (hDial.contains(point) && _type == DS_DSO && _active) + return HDIAL; + else if (chEn.contains(point) && _type == DS_DSO) + return CHEN; + else if (acdc.contains(point) && _type == DS_DSO && _active) + return ACDC; + else if (dsoTrig.contains(point) && _type == DS_DSO && _active) + return DSOTRIG; else return 0; } @@ -392,7 +715,8 @@ QRectF Signal::get_rect(const char *s, int y, int right) { const QSizeF color_size(SquareWidth, SquareWidth); const QSizeF name_size(right - get_leftWidth() - get_rightWidth(), SquareWidth); - const QSizeF label_size(_text_size.width() + Margin, SquareWidth); + //const QSizeF label_size(_text_size.width() + Margin, SquareWidth); + const QSizeF label_size(SquareWidth, SquareWidth); if (!strcmp(s, "name")) return QRectF( @@ -402,38 +726,68 @@ QRectF Signal::get_rect(const char *s, int y, int right) else if (!strcmp(s, "label")) return QRectF( right - 1.5f * label_size.width(), - y - label_size.height() / 2, + y - SquareWidth / 2, label_size.width(), label_size.height()); else if (!strcmp(s, "posTrig")) return QRectF( get_leftWidth() + name_size.width() + Margin, - y - color_size.height() / 2, - color_size.width(), color_size.height()); + y - SquareWidth / 2, + SquareWidth, SquareWidth); else if (!strcmp(s, "higTrig")) return QRectF( get_leftWidth() + name_size.width() + SquareWidth + Margin, - y - color_size.height() / 2, - color_size.width(), color_size.height()); + y - SquareWidth / 2, + SquareWidth, SquareWidth); else if (!strcmp(s, "negTrig")) return QRectF( get_leftWidth() + name_size.width() + 2 * SquareWidth + Margin, - y - color_size.height() / 2, - color_size.width(), color_size.height()); + y - SquareWidth / 2, + SquareWidth, SquareWidth); else if (!strcmp(s, "lowTrig")) return QRectF( get_leftWidth() + name_size.width() + 3 * SquareWidth + Margin, - y - color_size.height() / 2, - color_size.width(), color_size.height()); + y - SquareWidth / 2, + SquareWidth, SquareWidth); + else if (!strcmp(s, "edgeTrig")) + return QRectF( + get_leftWidth() + name_size.width() + 4 * SquareWidth + Margin, + y - SquareWidth / 2, + SquareWidth, SquareWidth); else if (!strcmp(s, "groupIndex")) return QRectF( get_leftWidth() + name_size.width() + Margin, - y - color_size.height() / 2, - color_size.width() * 4, color_size.height()); + y - SquareWidth / 2, + SquareWidth * SquareNum, SquareWidth); + else if (!strcmp(s, "vDial")) + return QRectF( + get_leftWidth() + name_size.width() + SquareWidth*0.5 + Margin, + y - SquareWidth * SquareNum, + SquareWidth * (SquareNum-1), SquareWidth * (SquareNum-1)); + else if (!strcmp(s, "hDial")) + return QRectF( + get_leftWidth() + name_size.width() + SquareWidth*0.5 + Margin, + y + SquareWidth * 1.5, + SquareWidth * (SquareNum-1), SquareWidth * (SquareNum-1)); + else if (!strcmp(s, "chEn")) + return QRectF( + get_leftWidth() + name_size.width() + SquareWidth*0.75 + Margin, + y - SquareWidth / 2, + SquareWidth * 1.5, SquareWidth); + else if (!strcmp(s, "acdc")) + return QRectF( + get_leftWidth() + name_size.width() + SquareWidth*2.75 + Margin, + y - SquareWidth / 2, + SquareWidth * 1.5, SquareWidth); + else if (!strcmp(s, "dsoTrig")) + return QRectF( + right - label_size.width(), + _trig_vpos - SquareWidth / 2, + label_size.width(), label_size.height()); else return QRectF( 2, - y - color_size.height() / 2, - color_size.width(), color_size.height()); + y - SquareWidth / 2, + SquareWidth, SquareWidth); } } // namespace view diff --git a/DSLogic-gui/pv/view/signal.h b/DSLogic-gui/pv/view/signal.h index f6f8242..8420314 100644 --- a/DSLogic-gui/pv/view/signal.h +++ b/DSLogic-gui/pv/view/signal.h @@ -36,12 +36,14 @@ #include <list> #include "libsigrok4DSLogic/libsigrok.h" +#include "dsldial.h" namespace pv { namespace data { class SignalData; class Logic; +class Dso; class Analog; class Group; } @@ -55,28 +57,49 @@ namespace view { class Signal { private: - static const int SquareWidth; - static const int Margin; - - static const int COLOR; - static const int NAME; - static const int POSTRIG; - static const int HIGTRIG; - static const int NEGTRIG; - static const int LOWTRIG; - static const int LABEL; + static const int SquareWidth = 20; + static const int Margin = 3; + static const int SquareNum = 5; + + static const quint64 vDialValueCount = 10; + static const quint64 vDialValueStep = 1000; + static const quint64 vDialUnitCount = 2; + static const quint64 hDialValueCount = 25; + static const quint64 hDialValueStep = 1000; + static const quint64 hDialUnitCount = 4; + static const quint64 vDialValue[vDialValueCount]; + static const QString vDialUnit[vDialUnitCount]; + + static const quint64 hDialValue[hDialValueCount]; + static const QString hDialUnit[hDialUnitCount]; public: + static const int COLOR = 1; + static const int NAME = 2; + static const int POSTRIG = 3; + static const int HIGTRIG = 4; + static const int NEGTRIG = 5; + static const int LOWTRIG = 6; + static const int EDGETRIG = 7; + static const int LABEL = 8; + static const int VDIAL = 9; + static const int HDIAL = 10; + static const int CHEN = 11; + static const int ACDC = 12; + static const int DSOTRIG = 13; + static const QColor dsBlue; static const QColor dsYellow; static const QColor dsRed; static const QColor dsGreen; static const QColor dsGray; + static const QColor dsDisable; + static const QColor dsActive; static const QColor dsLightBlue; static const QColor dsLightRed; - static const QPen SignalAxisPen; + static const QPen SignalAxisPen; - enum {DS_LOGIC = 0, DS_ANALOG, DS_GROUP, DS_PROTOCOL}; + enum {DS_LOGIC = 0, DS_ANALOG, DS_GROUP, DS_PROTOCOL, DS_DSO}; protected: Signal(QString name, int index, int type, int order); @@ -165,6 +188,32 @@ public: int get_trig() const; void set_trig(int trig); + /* + * + */ + bool get_vDialActive() const; + void set_vDialActive(bool active); + bool get_hDialActive() const; + void set_hDialActive(bool active); + bool go_vDialPre(); + bool go_vDialNext(); + bool go_hDialPre(); + bool go_hDialNext(); + quint64 get_vDialValue() const; + quint64 get_hDialValue() const; + uint16_t get_vDialSel() const; + uint16_t get_hDialSel() const; + bool get_acCoupling() const; + void set_acCoupling(bool coupling); + bool get_active() const; + void set_active(bool active); + int get_zeroPos() const; + void set_zeroPos(int pos); + int get_windowHeight() const; + void set_windowHeight(int height); + void set_trig_vpos(int value); + int get_trig_vpos() const; + /** * Paints the signal with a QPainter * @param p the QPainter to paint into. @@ -176,7 +225,7 @@ public: * the view in seconds. **/ virtual void paint(QPainter &p, int y, int left, int right, - double scale, double offset) = 0; + double scale, double offset) = 0; virtual const std::vector< std::pair<uint64_t, bool> > cur_edges() const = 0; @@ -187,6 +236,7 @@ public: virtual void del_decoder() = 0; virtual void set_data(boost::shared_ptr<pv::data::Logic> _logic_data, + boost::shared_ptr<pv::data::Dso> _dso_data, boost::shared_ptr<pv::data::Analog> _analog_data, boost::shared_ptr<pv::data::Group> _group_data) = 0; @@ -198,9 +248,12 @@ public: * area. * @param hover true if the label is being hovered over by the mouse. */ - virtual void paint_label(QPainter &p, int y, int right, + virtual void paint_label(QPainter &p, int y, int right, bool hover, int action); + virtual void paint_trig(QPainter &p, int left, int right, + bool hover); + /** * Determines if a point is in the header rect. * 1 - in color rect @@ -219,6 +272,16 @@ public: int pt_in_rect(int y, int right, const QPoint &point); + /** + * Computes the outline rectangle of a label. + * @param p the QPainter to lay out text with. + * @param y the y-coordinate of the signal. + * @param right the x-coordinate of the right edge of the header + * area. + * @return Returns the rectangle of the signal label. + */ + QRectF get_rect(const char *s, int y, int right); + protected: /** @@ -237,16 +300,6 @@ private: */ void compute_text_size(QPainter &p); - /** - * Computes the outline rectangle of a label. - * @param p the QPainter to lay out text with. - * @param y the y-coordinate of the signal. - * @param right the x-coordinate of the right edge of the header - * area. - * @return Returns the rectangle of the signal label. - */ - QRectF get_rect(const char *s, int y, int right); - protected: int _type; std::list<int> _index_list; @@ -264,6 +317,17 @@ protected: int _trig; QSizeF _text_size; + dslDial *_vDial; + dslDial *_hDial; + bool _vDialActive; + bool _hDialActive; + bool _acCoupling; + bool _active; + int _zeroPos; + int _windowHeight; + + int _trig_vpos; + bool _trig_en; }; } // namespace view diff --git a/DSLogic-gui/pv/view/view.cpp b/DSLogic-gui/pv/view/view.cpp index 7d9d8bd..fdd8624 100644 --- a/DSLogic-gui/pv/view/view.cpp +++ b/DSLogic-gui/pv/view/view.cpp @@ -27,6 +27,7 @@ #include <boost/foreach.hpp> +#include <QtGui/QApplication> #include <QEvent> #include <QMouseEvent> #include <QScrollBar> @@ -104,6 +105,14 @@ View::View(SigSession &session, QWidget *parent) : this, SLOT(on_signals_moved())); connect(_header, SIGNAL(header_updated()), this, SLOT(header_updated())); + connect(_header, SIGNAL(vDial_changed(quint16)), + this, SLOT(vDial_changed(quint16))); + connect(_header, SIGNAL(hDial_changed(quint16)), + this, SLOT(hDial_changed(quint16))); + connect(_header, SIGNAL(acdc_changed(quint16)), + this, SLOT(acdc_changed(quint16))); + connect(_header, SIGNAL(ch_changed(quint16)), + this, SLOT(ch_changed(quint16))); setViewportMargins(headerWidth(), RulerHeight, 0, 0); setViewport(_viewport); @@ -175,8 +184,20 @@ void View::zoom(double steps, int offset) _preOffset = _offset; const double cursor_offset = _offset + _scale * offset; - _scale *= pow(3.0/2.0, -steps); - _scale = max(min(_scale, _maxscale), _minscale); + if (_session.get_device()->mode != DSO) { + _scale *= pow(3.0/2.0, -steps); + _scale = max(min(_scale, _maxscale), _minscale); + } else { + const vector< shared_ptr<Signal> > sigs(_session.get_signals()); + if (steps > 0.5) { + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) + s->go_hDialNext(); + } else if(steps < -0.5) { + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) + s->go_hDialPre(); + } + _scale = sigs.at(0)->get_hDialValue() * pow(10, -9) * Viewport::NumSpanX / _viewport->width(); + } _offset = cursor_offset - _scale * offset; const double MinOffset = -(_scale * (_viewport->width() * (1 - MaxViewRate))); const double MaxOffset = _data_length * 1.0f / _session.get_last_sample_rate() - @@ -184,6 +205,7 @@ void View::zoom(double steps, int offset) _offset = max(min(_offset, MaxOffset), MinOffset); if (_scale != _preScale || _offset != _preOffset) { + _header->update(); _ruler->update(); _viewport->update(); update_scroll(); @@ -198,7 +220,9 @@ void View::set_scale_offset(double scale, double offset) _preScale = _scale; _preOffset = _offset; - _scale = max(min(scale, _maxscale), _minscale); + if (_session.get_device()->mode != DSO) + _scale = max(min(scale, _maxscale), _minscale); + const double MinOffset = -(_scale * (_viewport->width() * (1 - MaxViewRate))); const double MaxOffset = _data_length * 1.0f / _session.get_last_sample_rate() - _scale * (_viewport->width() * MaxViewRate); @@ -297,14 +321,14 @@ const QPointF& View::hover_point() const void View::normalize_layout() { - const vector< shared_ptr<Signal> > sigs(_session.get_signals()); + const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals()); int v_min = INT_MAX; - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) v_min = min(s->get_v_offset(), v_min); const int delta = -min(v_min, 0); - BOOST_FOREACH(shared_ptr<Signal> s, sigs) + BOOST_FOREACH(boost::shared_ptr<Signal> s, sigs) s->set_v_offset(s->get_v_offset() + delta); verticalScrollBar()->setSliderPosition(_v_offset + delta); @@ -324,7 +348,7 @@ int View::get_signalHeight() void View::get_scroll_layout(double &length, double &offset) const { - const shared_ptr<data::SignalData> sig_data = _session.get_data(); + const boost::shared_ptr<data::SignalData> sig_data = _session.get_data(); if (!sig_data) return; @@ -376,12 +400,14 @@ void View::reset_signal_layout() int offset = SignalMargin + SignalHeight; _spanY = SignalHeight + 2 * SignalMargin; - const vector< shared_ptr<Signal> > sigs(_session.get_signals()); - BOOST_FOREACH(shared_ptr<Signal> s, sigs) { + const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals()); + BOOST_FOREACH(boost::shared_ptr<Signal> s, sigs) { s->set_signalHeight(SignalHeight); + s->set_windowHeight(_viewport->height()); //s->set_v_offset(offset); //offset += SignalHeight + 2 * SignalMargin; s->set_v_offset(offset + s->get_order() * _spanY); + s->set_zeroPos(_viewport->height()*0.5); } normalize_layout(); } @@ -438,10 +464,15 @@ int View::headerWidth() int maxNameWidth = 0; int maxLeftWidth = 0; int maxRightWidth = 0; + + QFont font = QApplication::font(); + QFontMetrics fm(font); + int fontWidth=fm.width("A"); + const vector< shared_ptr<Signal> > sigs(_session.get_signals()); if (!sigs.empty()){ BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { - maxNameWidth = max(s->get_name().length() * 6, maxNameWidth); + maxNameWidth = max(s->get_name().length() * fontWidth, maxNameWidth); maxLeftWidth = max(s->get_leftWidth(), maxLeftWidth); maxRightWidth = max(s->get_rightWidth(), maxRightWidth); } @@ -512,7 +543,8 @@ void View::data_updated() // Get the new data length _data_length = max(_session.get_total_sample_len(), (quint64)1000); _maxscale = (_data_length * 1.0f / _session.get_last_sample_rate()) / (_viewport->width() * MaxViewRate); - _scale = min(_scale, _maxscale); + if(_session.get_device()->mode != DSO) + _scale = min(_scale, _maxscale); setViewportMargins(headerWidth(), RulerHeight, 0, 0); update_margins(); @@ -549,7 +581,9 @@ void View::sample_rate_changed(quint64 sample_rate) { assert(sample_rate > 0); - _scale = (1.0f / sample_rate) / WellPixelsPerSample; + if (_session.get_device()->mode != DSO) + _scale = (1.0f / sample_rate) / WellPixelsPerSample; + _minscale = (1.0f / sample_rate) / (_viewport->width() * MaxViewRate); _offset = 0; _preScale = _scale; @@ -568,7 +602,8 @@ void View::marker_time_changed() void View::on_signals_moved() { update_scroll(); - signals_moved(); + _viewport->update(); + //signals_moved(); } /* @@ -698,5 +733,39 @@ void View::on_state_changed(bool stop) _viewport->stop_trigger_timer(); } +void View::vDial_changed(uint16_t channel) +{ + if (channel == 0) + _session.set_dso_ctrl(SR_CONF_VDIV0); + else + _session.set_dso_ctrl(SR_CONF_VDIV1); +} + +void View::hDial_changed(uint16_t channel) +{ + const vector< shared_ptr<Signal> > sigs(_session.get_signals()); + _session.set_dso_ctrl(SR_CONF_TIMEBASE); + _scale = sigs.at(channel)->get_hDialValue() * pow(10, -9) * Viewport::NumSpanX / _viewport->width(); + _ruler->update(); + _viewport->update(); + update_scroll(); +} + +void View::acdc_changed(uint16_t channel) +{ + if (channel == 0) + _session.set_dso_ctrl(SR_CONF_COUPLING0); + else + _session.set_dso_ctrl(SR_CONF_COUPLING1); +} + +void View::ch_changed(uint16_t channel) +{ + if (channel == 0) + _session.set_dso_ctrl(SR_CONF_EN_CH0); + else + _session.set_dso_ctrl(SR_CONF_EN_CH1); +} + } // namespace view } // namespace pv diff --git a/DSLogic-gui/pv/view/view.h b/DSLogic-gui/pv/view/view.h index 346e298..61a3eea 100644 --- a/DSLogic-gui/pv/view/view.h +++ b/DSLogic-gui/pv/view/view.h @@ -187,7 +187,8 @@ private: void resizeEvent(QResizeEvent *e); public slots: - void set_measure_en(int enable); + void set_measure_en(int enable); + void hDial_changed(quint16 channel); private slots: @@ -209,6 +210,10 @@ private slots: void set_trig_pos(quint64 trig_pos); + void vDial_changed(quint16 channel); + void acdc_changed(quint16 channel); + void ch_changed(quint16 channel); + private: SigSession &_session; diff --git a/DSLogic-gui/pv/view/viewport.cpp b/DSLogic-gui/pv/view/viewport.cpp index e0b7e45..9a59aa8 100644 --- a/DSLogic-gui/pv/view/viewport.cpp +++ b/DSLogic-gui/pv/view/viewport.cpp @@ -79,9 +79,9 @@ Viewport::Viewport(View &parent) : int Viewport::get_total_height() const { int h = 0; - const vector< shared_ptr<Signal> > sigs( + const vector< boost::shared_ptr<Signal> > sigs( _view.session().get_signals()); - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) { assert(s); //h = max(s->get_v_offset() + _view.get_signalHeight(), h); h = max(s->get_v_offset(), h); @@ -95,7 +95,7 @@ void Viewport::paintEvent(QPaintEvent *event) (void)event; using pv::view::Signal; - + int i, j; QStyleOption o; o.initFrom(this); QPainter p(this); @@ -105,36 +105,35 @@ void Viewport::paintEvent(QPaintEvent *event) p.setRenderHint(QPainter::Antialiasing); if (_view.session().get_device()->mode == LOGIC) { - switch(_view.session().get_capture_state()) { - case SigSession::Init: - break; + switch(_view.session().get_capture_state()) { + case SigSession::Init: + break; - case SigSession::Stopped: - paintSignals(p); - break; + case SigSession::Stopped: + paintSignals(p); + break; - case SigSession::Running: - //p.setRenderHint(QPainter::Antialiasing); - paintProgress(p); - break; - } - } else if (_view.session().get_device()->mode == ANALOG) { + case SigSession::Running: + //p.setRenderHint(QPainter::Antialiasing); + paintProgress(p); + break; + } + } else { paintSignals(p); } p.setRenderHint(QPainter::Antialiasing, false); if (_view.get_signalHeight() != _curSignalHeight) _curSignalHeight = _view.get_signalHeight(); - const vector< shared_ptr<Signal> > sigs( + const vector< boost::shared_ptr<Signal> > sigs( _view.session().get_signals()); - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) { assert(s); //paint_axis(p, y, left, right); p.setPen(Signal::dsGray); const double sigY = s->get_v_offset() - _view.v_offset(); - int i, j; if (s->get_type() == Signal::DS_ANALOG) { p.drawLine(0, sigY, width(), sigY); const double spanY = (s->get_signalHeight()) * 1.0f / NumSpanY; @@ -152,19 +151,47 @@ void Viewport::paintEvent(QPaintEvent *event) p.drawLine(0 + spanX * i, sigY, 0 + spanX * i, sigY - s->get_signalHeight()); } - } else { + } else if (s->get_type() == Signal::DS_LOGIC) { p.drawLine(0, sigY + 10, width(), sigY + 10); } } + if (_view.session().get_device()->mode == DSO) { + + p.setPen(Signal::dsGray); + p.setPen(Qt::DotLine); + + const double spanY =height() * 1.0f / 10; + for (i = 1; i < 11; i++) { + const double posY = spanY * i; + p.drawLine(0, posY, width(), posY); + const double miniSpanY = spanY / 5; + for (j = 1; j < 5; j++) { + p.drawLine(width() / 2.0f - 10, posY - miniSpanY * j, + width() / 2.0f + 10, posY - miniSpanY * j); + } + } + const double spanX = width() * 1.0f / 10; + for (i = 1; i < 11; i++) { + const double posX = spanX * i; + p.drawLine(posX, 0, + posX, height()); + const double miniSpanX = spanX / 5; + for (j = 1; j < 5; j++) { + p.drawLine(posX - miniSpanX * j, height() / 2.0f - 10, + posX - miniSpanX * j, height() / 2.0f + 10); + } + } + } + p.end(); } void Viewport::paintSignals(QPainter &p) { - const vector< shared_ptr<Signal> > sigs( + const vector< boost::shared_ptr<Signal> > sigs( _view.session().get_signals()); -// const vector< shared_ptr<Signal> > pro_sigs( +// const vector< boost::shared_ptr<Signal> > pro_sigs( // _view.session().get_pro_signals()); // Plot the signal const int v_offset = _view.v_offset(); @@ -181,13 +208,14 @@ void Viewport::paintSignals(QPainter &p) QPainter dbp(&pixmap); dbp.initFrom(this); p.setRenderHint(QPainter::Antialiasing, false); - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) { assert(s); - s->paint(dbp, s->get_v_offset() - v_offset, 0, width(), - _view.scale(), _view.offset()); + if (s->get_active()) + s->paint(dbp, ((s->get_type() == Signal::DS_DSO) ? s->get_zeroPos() + height()*0.5 : s->get_v_offset() - v_offset), 0, width(), + _view.scale(), _view.offset()); } // p.setRenderHint(QPainter::Antialiasing); -// BOOST_FOREACH(const shared_ptr<Signal> s, pro_sigs) { +// BOOST_FOREACH(const boost::shared_ptr<Signal> s, pro_sigs) { // assert(s); // s->paint(dbp, s->get_v_offset() - v_offset, 0, width(), // _view.scale(), _view.offset()); @@ -196,6 +224,13 @@ void Viewport::paintSignals(QPainter &p) } p.drawPixmap(0, 0, pixmap); + // plot trig line in DSO mode + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + assert(s); + if (s->get_active() && s->get_type() == Signal::DS_DSO) + s->paint_trig(p, 0, width(), qAbs(_mouse_point.y() - s->get_trig_vpos()) <= HitCursorMargin ); + } + // plot cursors if (_view.cursors_shown()) { list<Cursor*>::iterator i = _view.get_cursorList().begin(); @@ -364,6 +399,20 @@ void Viewport::mousePressEvent(QMouseEvent *event) // if (!_view.get_ruler()->get_grabbed_cursor()) { // _zoom_rect_visible = true; // } + + const vector< shared_ptr<Signal> > sigs(_view.session().get_signals()); + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + assert(s); + if (s->get_active() && + s->get_type() == Signal::DS_DSO && + qAbs(_mouse_point.y() - s->get_trig_vpos()) <= HitCursorMargin) { + if (_drag_sig) + _drag_sig.reset(); + else + _drag_sig = s; + break; + } + } update(); } } @@ -371,7 +420,7 @@ void Viewport::mousePressEvent(QMouseEvent *event) void Viewport::mouseMoveEvent(QMouseEvent *event) { assert(event); - + _mouse_point = event->pos(); if (event->buttons() & Qt::RightButton) { _zoom_rect = QRectF(_mouse_down_point, event->pos()); _zoom_rect_visible = true; @@ -382,16 +431,35 @@ void Viewport::mouseMoveEvent(QMouseEvent *event) _mouse_down_offset + (_mouse_down_point - event->pos()).x() * _view.scale()); - measure(); } if (!(event->buttons() || Qt::NoButton)) { + if (_drag_sig) { + uint16_t trig_value = 0; + int vpos = _mouse_point.y(); + if (vpos < 0) + vpos = 0; + else if (vpos > height()) + vpos = height(); + _drag_sig->set_trig_vpos(vpos); + + const vector< shared_ptr<Signal> > sigs(_view.session().get_signals()); + BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + assert(s); + if (s->get_active() && + s->get_type() == Signal::DS_DSO) { + trig_value += (((uint16_t)(255 - s->get_trig_vpos()*1.0/height()*255)) << 8*s->get_index()); + } + } + sr_config_set(_view.session().get_device(), + SR_CONF_TRIGGER_VALUE, g_variant_new_uint16(trig_value)); + } + TimeMarker* grabbed_marker = _view.get_ruler()->get_grabbed_cursor(); if (_view.cursors_shown() && grabbed_marker) { grabbed_marker->set_time(_view.offset() + _view.hover_point().x() * _view.scale()); } - measure(); } @@ -445,6 +513,7 @@ void Viewport::wheelEvent(QWheelEvent *event) void Viewport::leaveEvent(QEvent *) { _measure_shown = false; + _mouse_point = QPoint(-1, -1); //_view.show_cursors(false); update(); } @@ -471,8 +540,8 @@ void Viewport::set_receive_len(quint64 length) void Viewport::measure() { - const vector< shared_ptr<Signal> > sigs(_view.session().get_signals()); - BOOST_FOREACH(const shared_ptr<Signal> s, sigs) { + const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals()); + BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) { assert(s); const int curY = _view.hover_point().y(); const double curX = _view.hover_point().x(); diff --git a/DSLogic-gui/pv/view/viewport.h b/DSLogic-gui/pv/view/viewport.h index 0ecb0c7..c373c78 100644 --- a/DSLogic-gui/pv/view/viewport.h +++ b/DSLogic-gui/pv/view/viewport.h @@ -24,6 +24,9 @@ #ifndef DSLOGIC_PV_VIEW_VIEWPORT_H #define DSLOGIC_PV_VIEW_VIEWPORT_H +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + #include <QTimer> #include <QWidget> #include <stdint.h> @@ -35,13 +38,14 @@ class SigSession; namespace pv { namespace view { +class Signal; class View; class Viewport : public QWidget { Q_OBJECT -private: +public: static const int HitCursorMargin; static const int NumSpanY; static const int NumMiniSpanY; @@ -88,6 +92,7 @@ private: View &_view; quint64 _total_receive_len; + QPoint _mouse_point; QPoint _mouse_down_point; double _mouse_down_offset; double _curScale; @@ -115,6 +120,8 @@ private: QTimer trigger_timer; bool triggered; int timer_cnt; + + boost::shared_ptr<Signal> _drag_sig; }; } // namespace view diff --git a/DSLogic-gui/res/DSLogic.bin b/DSLogic-gui/res/DSLogic.bin Binary files differnew file mode 100644 index 0000000..9755839 --- /dev/null +++ b/DSLogic-gui/res/DSLogic.bin diff --git a/DSLogic-gui/res/DSLogic.fw b/DSLogic-gui/res/DSLogic.fw Binary files differnew file mode 100644 index 0000000..813f8fe --- /dev/null +++ b/DSLogic-gui/res/DSLogic.fw diff --git a/DSLogic-gui/stylesheet.qss b/DSLogic-gui/stylesheet.qss index ad91277..7245f27 100644 --- a/DSLogic-gui/stylesheet.qss +++ b/DSLogic-gui/stylesheet.qss @@ -1,6 +1,6 @@ palette {
background: rgb(17, 133, 209, 255);
- disabled: rgb(232, 232, 230, 255);
+ disabled: rgb(200, 200, 200, 255);
}
QMainWindow {
@@ -77,7 +77,7 @@ QSpinBox { QLineEdit:disabled,
QComboBox:disabled,
QSpinBox:disabled {
- background-color: rgb(232, 232, 230, 255);
+ background-color: rgb(200, 200, 200, 255);
}
QComboBox:!editable {
@@ -99,7 +99,7 @@ QComboBox:on { /* shift the text when the popup opens */ QComboBox::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
- width: 15px;
+ width: 20px;
border-left-width: 0px;
border-top-right-radius: 4px; /* same radius as the QComboBox */
@@ -163,7 +163,7 @@ QGroupBox::title }
QGroupBox:disabled
{
- color: rgb(232, 232, 230, 255);
+ color: rgb(200, 200, 200, 255);
}
QDockWidget > QWidget > QTabWidget::pane{
@@ -175,7 +175,7 @@ QDockWidget > QWidget > QTabWidget::pane{ }
QDockWidget > QWidget > QTabWidget::pane:disabled{
- border: 1px solid rgb(232, 232, 230, 255);
+ border: 1px solid rgb(200, 200, 200, 255);
border-right-color: rgb(17, 133, 209, 255); /* same as the pane color */
}
@@ -203,7 +203,7 @@ QDockWidget > QWidget > QTabWidget > QTabBar::tab:selected }
QDockWidget > QWidget > QTabWidget > QTabBar::tab:disabled
{
- color: rgb(232, 232, 230, 50);
+ color: rgb(200, 200, 200, 50);
border: 1px solid rgb(232, 232, 230, 255);
background: transparent;
border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
@@ -213,18 +213,29 @@ QCheckBox, QRadioButton,
QLabel {
border: none;
- color: white;
min-height: 20px;
}
+QCheckBox::checked,
+QRadioButton::checked {
+ color: black;
+}
+
+QLabel,
+QCheckBox::unchecked,
+QRadioButton::unchecked {
+ color: white;
+}
+
QCheckBox,
QLabel {
padding: 1px 1px 1px 1px;
margin: 0px;
}
+
QLabel:disabled {
- color: rgb(232, 232, 230, 255);
+ color: rgb(200, 200, 200, 255);
}
QSlider::groove:horizontal {
diff --git a/DSLogic-gui/test/CMakeLists.txt b/DSLogic-gui/test/CMakeLists.txt index c283171..539ab0d 100644 --- a/DSLogic-gui/test/CMakeLists.txt +++ b/DSLogic-gui/test/CMakeLists.txt @@ -2,7 +2,8 @@ ## This file is part of the PulseView project. ## ## Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk> -## Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com> +## Copyright (C) 2012-2013 Alexandru Gagniuc <mr.nuke.me@gmail.com> +## Copyright (C) 2013-2014 DreamSourceLab <support@dreamsourcelab.com> ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -18,35 +19,293 @@ ## along with this program. If not, see <http://www.gnu.org/licenses/>. ## +cmake_minimum_required(VERSION 2.6) +include(FindPkgConfig) +include(GNUInstallDirs) + +project(DSLogic) + +#=============================================================================== +#= User Options +#------------------------------------------------------------------------------- + +option(DISABLE_WERROR "Build without -Werror" TRUE) +option(ENABLE_SIGNALS "Build with UNIX signals" TRUE) +option(ENABLE_TESTS "Enable unit tests" FALSE) +option(STATIC_PKGDEPS_LIBS "Statically link to (pkgconfig) libraries" FALSE) + +if(WIN32) + # On Windows/MinGW we need to statically link to libraries. + # This option is user configurable, but enable it by default on win32. + set(STATIC_PKGDEPS_LIBS TRUE) + + # For boost-thread we need two additional settings on win32: + set(Boost_USE_STATIC_LIBS on) + add_definitions(-DBOOST_THREAD_USE_LIB) + + # Windsws does not support UNIX signals + set(ENABLE_SIGNALS FALSE) +endif() + +#=============================================================================== +#= Dependencies +#------------------------------------------------------------------------------- + +list(APPEND PKGDEPS + libsigrok4DSLogic>=0.2.0 + libusb-1.0>=1.0.16 +) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/") + +find_package(PkgConfig) +pkg_check_modules(PKGDEPS REQUIRED ${PKGDEPS}) + +find_package(Qt4 REQUIRED) + # Find the platform's thread library (needed for boost-thread). # This will set ${CMAKE_THREAD_LIBS_INIT} to the correct, OS-specific value. find_package(Threads) -find_package(Boost 1.46 COMPONENTS unit_test_framework REQUIRED) +if(WIN32) +# On Windows/MinGW the we need to use 'thread_win32' instead of 'thread'. +# The library is named libboost_thread_win32* (not libboost_thread*). +find_package(Boost 1.42 COMPONENTS system thread_win32 REQUIRED) +else() +find_package(Boost 1.42 COMPONENTS system thread REQUIRED) +endif() + +find_package(libusb-1.0 REQUIRED) + +#=============================================================================== +#= Config Header +#------------------------------------------------------------------------------- + +set(DS_TITLE DSLogic) +set(DS_DESCRIPTION "A GUI for DSLogic") + +set(DS_VERSION_MAJOR 0) +set(DS_VERSION_MINOR 3) +set(DS_VERSION_MICRO 0) +set(DS_VERSION_STRING + ${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO} +) + +configure_file ( + ${PROJECT_SOURCE_DIR}/config.h.in + ${PROJECT_BINARY_DIR}/config.h +) + +#=============================================================================== +#= Sources +#------------------------------------------------------------------------------- + +set(DSLogic_SOURCES + main.cpp + pv/devicemanager.cpp + pv/mainwindow.cpp + pv/sigsession.cpp + pv/data/analog.cpp + pv/data/analogsnapshot.cpp + pv/data/group.cpp + pv/data/groupsnapshot.cpp + pv/data/logic.cpp + pv/data/logicsnapshot.cpp + pv/data/signaldata.cpp + pv/data/snapshot.cpp + pv/data/dso.cpp + pv/data/dsosnapshot.cpp + pv/decoder/decoder.cpp + pv/decoder/decoderfactory.cpp + pv/decoder/democonfig.cpp + pv/decoder/ds1wire.cpp + pv/decoder/dsdmx512.cpp + pv/decoder/dsi2c.cpp + pv/decoder/dsserial.cpp + pv/decoder/dsspi.cpp + pv/dialogs/about.cpp + pv/dialogs/connect.cpp + pv/dialogs/deviceoptions.cpp + pv/dialogs/search.cpp + pv/dock/fakelineedit.cpp + pv/dock/measuredock.cpp + pv/dock/protocoldock.cpp + pv/dock/searchdock.cpp + pv/dock/triggerdock.cpp + pv/prop/bool.cpp + pv/prop/double.cpp + pv/prop/enum.cpp + pv/prop/int.cpp + pv/prop/property.cpp + pv/prop/binding/binding.cpp + pv/prop/binding/binding_deviceoptions.cpp + pv/toolbars/devicebar.cpp + pv/toolbars/filebar.cpp + pv/toolbars/logobar.cpp + pv/toolbars/samplingbar.cpp + pv/toolbars/trigbar.cpp + pv/view/analogsignal.cpp + pv/view/cursor.cpp + pv/view/groupsignal.cpp + pv/view/header.cpp + pv/view/logicsignal.cpp + pv/view/protocolsignal.cpp + pv/view/ruler.cpp + pv/view/signal.cpp + pv/view/timemarker.cpp + pv/view/view.cpp + pv/view/viewport.cpp + pv/view/dsosignal.cpp + pv/view/dsldial.cpp + pv/dock/dsotriggerdock.cpp +) + +set(DSLogic_HEADERS + pv/sigsession.h + pv/mainwindow.h + pv/decoder/democonfig.h + pv/dock/fakelineedit.h + pv/dock/measuredock.h + pv/dock/protocoldock.h + pv/dock/searchdock.h + pv/dock/triggerdock.h + pv/dialogs/about.h + pv/dialogs/connect.h + pv/dialogs/deviceoptions.h + pv/dialogs/search.h + pv/toolbars/samplingbar.h + pv/toolbars/devicebar.h + pv/toolbars/filebar.h + pv/toolbars/logobar.h + pv/toolbars/trigbar.h + pv/data/dso.h + pv/data/dsosnapshot.h + pv/view/cursor.h + pv/view/header.h + pv/view/ruler.h + pv/view/timemarker.h + pv/view/groupsignal.h + pv/view/protocolsignal.h + pv/view/view.h + pv/view/dsosignal.h + pv/view/viewport.h + pv/view/dsldial.h + pv/dock/dsotriggerdock.h +) -set(pulseview_TEST_SOURCES - ${PROJECT_SOURCE_DIR}/pv/data/analogsnapshot.cpp - ${PROJECT_SOURCE_DIR}/pv/data/snapshot.cpp - ${PROJECT_SOURCE_DIR}/pv/data/logicsnapshot.cpp - data/analogsnapshot.cpp - data/logicsnapshot.cpp - test.cpp +set(DSLogic_FORMS + pv/dialogs/about.ui + pv/decoder/dmx512config.ui + pv/decoder/i2cconfig.ui + pv/decoder/serialconfig.ui + pv/decoder/spiconfig.ui + pv/decoder/wire1config.ui ) -add_definitions(-DBOOST_TEST_DYN_LINK) +set(DSLogic_RESOURCES + DSLogic.qrc +) + +qt4_wrap_cpp(DSLogic_HEADERS_MOC ${DSLogic_HEADERS}) +qt4_wrap_ui(DSLogic_FORMS_HEADERS ${DSLogic_FORMS}) +qt4_add_resources(DSLogic_RESOURCES_RCC ${DSLogic_RESOURCES}) + +include(${QT_USE_FILE}) + +#=============================================================================== +#= Global Definitions +#------------------------------------------------------------------------------- + +add_definitions(${QT_DEFINITIONS}) +add_definitions(-Wall -Wextra -Wno-return-type -Wno-ignored-qualifiers) + +if(NOT DISABLE_WERROR) + add_definitions(-Werror) +endif() + +#=============================================================================== +#= Global Include Directories +#------------------------------------------------------------------------------- include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} ${Boost_INCLUDE_DIRS} ) -set(PULSEVIEW_LINK_LIBS +if(STATIC_PKGDEPS_LIBS) + include_directories(${PKGDEPS_STATIC_INCLUDE_DIRS}) +else() + include_directories(${PKGDEPS_INCLUDE_DIRS}) +endif() + +#=============================================================================== +#= Linker Configuration +#------------------------------------------------------------------------------- + +link_directories(${Boost_LIBRARY_DIRS}) + +set(DSLOGIC_LINK_LIBS ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} + ${QT_LIBRARIES} + ${LIBUSB_1_LIBRARIES} ) -add_executable(pulseview-test - ${pulseview_TEST_SOURCES} +if(STATIC_PKGDEPS_LIBS) + link_directories(${PKGDEPS_STATIC_LIBRARY_DIRS}) + list(APPEND DSLOGIC_LINK_LIBS ${PKGDEPS_STATIC_LIBRARIES}) +else() + link_directories(${PKGDEPS_LIBRARY_DIRS}) + list(APPEND DSLOGIC_LINK_LIBS ${PKGDEPS_LIBRARIES}) +endif() + +add_executable(${PROJECT_NAME} + ${DSLogic_SOURCES} + ${DSLogic_HEADERS_MOC} + ${DSLogic_FORMS_HEADERS} + ${DSLogic_RESOURCES_RCC} ) -target_link_libraries(pulseview-test ${PULSEVIEW_LINK_LIBS}) +target_link_libraries(${PROJECT_NAME} ${DSLOGIC_LINK_LIBS}) + +if(WIN32) +# Pass -mwindows so that no "DOS box" will open when PulseView is started. +set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-mwindows") +endif() +set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "/usr/local/lib") + +#=============================================================================== +#= Installation +#------------------------------------------------------------------------------- + +# Install the executable. +install(TARGETS ${PROJECT_NAME} DESTINATION bin/) +install(FILES res/DSLogic.fw DESTINATION bin/res/) +install(FILES res/DSLogic.bin DESTINATION bin/res/) + +#=============================================================================== +#= Packaging (handled by CPack) +#------------------------------------------------------------------------------- + +set(CPACK_PACKAGE_VERSION_MAJOR ${DS_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${DS_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${DS_VERSION_MICRO}) +set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README) +set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/COPYING) +set(CPACK_SOURCE_IGNORE_FILES ${CMAKE_CURRENT_BINARY_DIR} ".gitignore" ".git") +set(CPACK_SOURCE_PACKAGE_FILE_NAME + "${CMAKE_PROJECT_NAME}-${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO}") +set(CPACK_SOURCE_GENERATOR "TGZ") + +include(CPack) + +#=============================================================================== +#= Tests +#------------------------------------------------------------------------------- +if(ENABLE_TESTS) + add_subdirectory(test) + enable_testing() + add_test(test ${CMAKE_CURRENT_BINARY_DIR}/test/DSLogic-test) +endif(ENABLE_TESTS) diff --git a/DSLogic-gui/test/COPYING b/DSLogic-gui/test/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/DSLogic-gui/test/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 3 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, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/DSLogic-gui/test/DSLogic.qrc b/DSLogic-gui/test/DSLogic.qrc new file mode 100644 index 0000000..d7b5e8a --- /dev/null +++ b/DSLogic-gui/test/DSLogic.qrc @@ -0,0 +1,33 @@ +<RCC> + <qresource prefix="/"> + <file>icons/search.png</file> + <file>icons/next.png</file> + <file>icons/pre.png</file> + <file>icons/file.png</file> + <file>icons/photo.png</file> + <file>icons/save.png</file> + <file>icons/open.png</file> + <file>icons/params.png</file> + <file>stylesheet.qss</file> + <file>icons/down-arrow.png</file> + <file>icons/slider-handle.png</file> + <file>icons/set.png</file> + <file>icons/add.png</file> + <file>icons/del.png</file> + <file>icons/trigger.png</file> + <file>icons/measure.png</file> + <file>icons/search-bar.png</file> + <file>icons/protocol.png</file> + <file>icons/logo_noColor.png</file> + <file>icons/logo_color.png</file> + <file>icons/logo_muColor.png</file> + <file>icons/about.png</file> + <file>icons/capture.png</file> + <file>icons/stop.png</file> + <file>icons/start.png</file> + <file>icons/dsl_logo.png</file> + <file>icons/logo.png</file> + <file>icons/checkbox.png</file> + <file>icons/radiobutton.png</file> + </qresource> +</RCC> diff --git a/DSLogic-gui/test/INSTALL b/DSLogic-gui/test/INSTALL new file mode 100644 index 0000000..126579b --- /dev/null +++ b/DSLogic-gui/test/INSTALL @@ -0,0 +1,49 @@ +-------------------------------------------------------------------------------
+INSTALL
+-------------------------------------------------------------------------------
+
+Requirements
+------------
+
+ - git
+ - g++
+ - make
+ - libtool
+ - pkg-config >= 0.22
+ - cmake >= 2.6
+ - libglib >= 2.28.0
+ - Qt >= 4.5
+ - libboost >= 1.42 (including the following libs):
+ - libboost-system
+ - libboost-thread
+ - libsigrok4DSLogic >= 0.2.0
+
+
+Building and installing
+-----------------------
+Get the DSLogic-gui source code from: www.dreamsourcelab.com/download.html
+In order to build it, run:
+
+ $ cd DSLogic-gui
+ $ cmake .
+ $ make
+
+For installing PulseView:
+
+ $ make install
+
+See the following wiki page for more (OS-specific) instructions:
+
+ http://sigrok.org/wiki/Building
+
+
+Creating a source distribution package
+--------------------------------------
+
+In order to build a source package begin with an unconfigured source tree.
+
+ $ mkdir dist
+ $ cd dist
+ $ cmake ..
+ $ make package_source
+
diff --git a/DSLogic-gui/test/NEWS b/DSLogic-gui/test/NEWS new file mode 100644 index 0000000..e7c2c79 --- /dev/null +++ b/DSLogic-gui/test/NEWS @@ -0,0 +1,5 @@ +0.1.0 (2013-12-15)
+------------------
+
+ * Initial release.
+
diff --git a/DSLogic-gui/test/README b/DSLogic-gui/test/README new file mode 100644 index 0000000..7452797 --- /dev/null +++ b/DSLogic-gui/test/README @@ -0,0 +1,72 @@ +------------------------------------------------------------------------------- +README +------------------------------------------------------------------------------- +DSLogic-gui is GUI for DSLogic software, it's based on PulseView +from the sigrok project. + +The sigrok project aims at creating a portable, cross-platform, +Free/Libre/Open-Source signal analysis software suite that supports various +device types (such as logic analyzers, oscilloscopes, multimeters, and more). + +PulseView is a Qt-based LA/scope/MSO GUI for sigrok. + + +Status +------ + +DSLogic-gui is in a usable state and has had official tarball releases. + +However, it is still work in progress. Some basic functionality +is available and working, but other things are still on the TODO list. + + +Copyright and license +--------------------- + +DSLogic-gui is licensed under the terms of the GNU General Public License +(GPL), version 3 or later. + +While some individual source code files are licensed under the GPLv2+, and +some files are licensed under the GPLv3+, this doesn't change the fact that +the program as a whole is licensed under the terms of the GPLv3+ (e.g. also +due to the fact that it links against GPLv3+ libraries). + +Please see the individual source files for the full list of copyright holders. + + +Copyright notices +----------------- + +A copyright notice indicating a range of years, must be interpreted as having +had copyrightable material added in each of those years. + +Example: + + Copyright (C) 2010-2013 Contributor Name + +is to be interpreted as + + Copyright (C) 2010,2011,2012,2013 Contributor Name + + +Mailing lists +------------- + +There are two mailing lists for sigrok/PulseView: + + https://lists.sourceforge.net/lists/listinfo/sigrok-devel + https://lists.sourceforge.net/lists/listinfo/sigrok-commits + + +IRC +--- + +You can find the sigrok developers in the #sigrok IRC channel on Freenode. + + +Website +------- + + http://sigrok.org/wiki/PulseView + http://dreamsourcelab.com + diff --git a/DSLogic-gui/config.h b/DSLogic-gui/test/config.h.in index f6afda9..89868e3 100644 --- a/DSLogic-gui/config.h +++ b/DSLogic-gui/test/config.h.in @@ -21,14 +21,14 @@ #define _DSLOGIC_CONFIG_H /* Application details */ -#define DS_TITLE "DSLogic" -#define DS_DESCRIPTION "A GUI for DSLogic" -#define DS_BIN_NAME "DSLogic-gui" +#define DS_TITLE "@DS_TITLE@" +#define DS_DESCRIPTION "@DS_DESCRIPTION@" +#define DS_BIN_NAME "@PROJECT_NAME@" /* DSLogic version information */ -#define DS_VERSION_MAJOR 0 -#define DS_VERSION_MINOR 1 -#define DS_VERSION_MICRO 0 -#define DS_VERSION_STRING "0.1.0" +#define DS_VERSION_MAJOR @DS_VERSION_MAJOR@ +#define DS_VERSION_MINOR @DS_VERSION_MINOR@ +#define DS_VERSION_MICRO @DS_VERSION_MICRO@ +#define DS_VERSION_STRING "@DS_VERSION_STRING@" #endif diff --git a/DSLogic-gui/test/extdef.h b/DSLogic-gui/test/extdef.h new file mode 100644 index 0000000..467b561 --- /dev/null +++ b/DSLogic-gui/test/extdef.h @@ -0,0 +1,32 @@ +/* + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. + * + * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk> + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef DSLOGIC_EXTDEF_H +#define DSLOGIC_EXTDEF_H + +#define countof(x) (sizeof(x)/sizeof(x[0])) + +#define begin_element(x) (&x[0]) +#define end_element(x) (&x[countof(x)]) + +#endif // DSLOGIC_EXTDEF_H diff --git a/DSLogic-gui/test/main.cpp b/DSLogic-gui/test/main.cpp new file mode 100644 index 0000000..807f3ce --- /dev/null +++ b/DSLogic-gui/test/main.cpp @@ -0,0 +1,163 @@ +/* + * This file is part of the DSLogic-gui project. + * DSLogic-gui is based on PulseView. + * + * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk> + * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifdef ENABLE_SIGROKDECODE +#include <libsigrokdecode/libsigrokdecode.h> /* First, so we avoid a _POSIX_C_SOURCE warning. */ +#endif + +#include <stdint.h> +#include <libsigrok4DSLogic/libsigrok.h> + +#include <getopt.h> + +#include <QtGui/QApplication> +#include <QDebug> +#include <QFile> + +#include "pv/devicemanager.h" +#include "pv/mainwindow.h" + +#include "config.h" + +void usage() +{ + fprintf(stdout, + "Usage:\n" + " %s [OPTIONβ¦] [FILE] β %s\n" + "\n" + "Help Options:\n" + " -l, --loglevel Set libsigrok/libsigrokdecode loglevel\n" + " -V, --version Show release version\n" + " -h, -?, --help Show help option\n" + "\n", DS_BIN_NAME, DS_DESCRIPTION); +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + struct sr_context *sr_ctx = NULL; + const char *open_file = NULL; + + QApplication a(argc, argv); + + // Set some application metadata + QApplication::setApplicationVersion(DS_VERSION_STRING); + QApplication::setApplicationName("DSLogic(Beta)"); + QApplication::setOrganizationDomain("http://www.DreamSourceLab.com"); + + // Parse arguments + while (1) { + static const struct option long_options[] = { + {"loglevel", required_argument, 0, 'l'}, + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + const int c = getopt_long(argc, argv, + "l:Vh?", long_options, NULL); + if (c == -1) + break; + + switch (c) { + case 'l': + { + const int loglevel = atoi(optarg); + sr_log_loglevel_set(loglevel); + +#ifdef ENABLE_SIGROKDECODE + srd_log_loglevel_set(loglevel); +#endif + + break; + } + + case 'V': + // Print version info + fprintf(stdout, "%s %s\n", DS_TITLE, DS_VERSION_STRING); + return 0; + + case 'h': + case '?': + usage(); + return 0; + } + } + + if (argc - optind > 1) { + fprintf(stderr, "Only one file can be openened.\n"); + return 1; + } else if (argc - optind == 1) + open_file = argv[argc - 1]; + + // Initialise libsigrok + if (sr_init(&sr_ctx) != SR_OK) { + qDebug() << "ERROR: libsigrok init failed."; + return 1; + } + + do { + +#ifdef ENABLE_SIGROKDECODE + // Initialise libsigrokdecode + if (srd_init(NULL) != SRD_OK) { + qDebug() << "ERROR: libsigrokdecode init failed."; + break; + } + + // Load the protocol decoders + srd_decoder_load_all(); +#endif + + try { + // Create the device manager, initialise the drivers + pv::DeviceManager device_manager(sr_ctx); + + // Initialise the main window + pv::MainWindow w(device_manager, open_file); + QFile qss(":/stylesheet.qss"); + qss.open(QFile::ReadOnly); + a.setStyleSheet(qss.readAll()); + qss.close(); + w.show(); + + // Run the application + ret = a.exec(); + + } catch(std::exception e) { + qDebug() << e.what(); + } + +#ifdef ENABLE_SIGROKDECODE + // Destroy libsigrokdecode + srd_exit(); +#endif + + } while (0); + + // Destroy libsigrok + if (sr_ctx) + sr_exit(sr_ctx); + + return ret; +} diff --git a/DSLogic-gui/test/stylesheet.qss b/DSLogic-gui/test/stylesheet.qss new file mode 100644 index 0000000..7245f27 --- /dev/null +++ b/DSLogic-gui/test/stylesheet.qss @@ -0,0 +1,279 @@ +palette {
+ background: rgb(17, 133, 209, 255);
+ disabled: rgb(200, 200, 200, 255);
+}
+
+QMainWindow {
+ icon-size: 48px, 48px;
+}
+
+QDialog {
+ border: none;
+ background: rgb(17, 133, 209, 255);
+}
+
+QToolBar {
+ border: none;
+ /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0 rgb(0, 75, 165, 255),
+ stop: 0.05 rgb(31, 164, 227, 255),
+ stop: 0.5 rgb(17, 133, 209, 255),
+ stop: 0.95 rgb(0, 102, 185, 255),
+ stop: 1 rgb(0, 75, 165, 255));*/
+ background: rgb(17, 133, 209, 255);
+ min-height: 50px;
+}
+
+pv--view--View,
+pv--view--Viewport{
+ margin: 0px;
+ border: none;
+ background-color: rgb(255, 255, 255);
+ padding: 0px;
+}
+
+QToolButton {
+ border: none;
+ border-style: flat;
+ color: white;
+ font: bold 10ft;
+ min-height: 50px;
+ min-width: 50px;
+}
+
+QPushButton:hover,
+QToolButton:hover {
+ background-color: rgb(238, 178, 17, 200);
+}
+
+QPushButton:pressed,
+QToolButton:pressed {
+ background-color: rgb(238, 178, 17, 255);
+}
+
+QPushButton {
+ padding: 3px;
+ border: none;
+ border-style: flat;
+ border-radius: 4px;
+ color: white;
+ background-color: rgb(255, 255, 255, 50);
+ font: bold 10ft;
+ min-height: 20px;
+ min-width: 20px;
+}
+
+/* >>> QToolBar: QLineEdit/QComboBox */
+QLineEdit,
+QComboBox:!editable,
+QSpinBox {
+ border: none;
+ border-radius: 4px;
+ background-color: white;
+ padding: 3px;
+ min-height: 20px;
+}
+
+QLineEdit:disabled,
+QComboBox:disabled,
+QSpinBox:disabled {
+ background-color: rgb(200, 200, 200, 255);
+}
+
+QComboBox:!editable {
+ padding-right: 5px;
+}
+
+/* QComboBox gets the "on" state when the popup is open */
+QComboBox:!editable:on, QToolBar > QComboBox::drop-down:editable:on {
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0 #D3D3D3, stop: 0.4 #D8D8D8,
+ stop: 0.5 #DDDDDD, stop: 1.0 #E1E1E1);
+}
+
+QComboBox:on { /* shift the text when the popup opens */
+ padding-top: 3px;
+ padding-left: 4px;
+}
+
+QComboBox::drop-down {
+ subcontrol-origin: padding;
+ subcontrol-position: top right;
+ width: 20px;
+
+ border-left-width: 0px;
+ border-top-right-radius: 4px; /* same radius as the QComboBox */
+ border-bottom-right-radius: 4px;
+}
+
+QComboBox::down-arrow {
+ image: url(:/icons/down-arrow.png);
+}
+QComboBox::down-arrow:disabled {
+ image: none;
+}
+
+QComboBox::down-arrow:on { /* shift the arrow when popup is open */
+ top: 1px;
+ left: 1px;
+}
+/* <<< QToolBar: QLineEdit/QComboBox */
+
+/* >>> QDockWidget */
+QDockWidget {
+ margin: 0px;
+ background-color: rgb(17, 133, 209, 255);
+ border: 0px;
+ padding: 0px;
+ color: rgb(17, 133, 209, 255);
+ font-size: 16px;
+ font-weight: bold;
+}
+
+QDockWidget::title {
+ margin: 0px;
+ text-align: left center;
+ background-color: rgb(255, 255, 255, 255);
+ border: 0px;
+ color: white;
+ padding: 8px;
+}
+QDockWidget > QWidget{
+ margin: 0px;
+ background-color: rgb(17, 133, 209, 255);
+ border: 0px;
+ padding: 0px;
+}
+
+QGroupBox {
+ margin: 0px;
+ background-color: rgb(17, 133, 209, 255);
+ border: 0px;
+ padding: 40px, 10px, 10px, 10px;
+ color: white;
+ font-size: 20px;
+ font-weight: bold;
+}
+
+QGroupBox::title
+{
+ subcontrol-origin: margin;
+ subcontrol-position: top center;
+ padding: 5 20px;
+}
+QGroupBox:disabled
+{
+ color: rgb(200, 200, 200, 255);
+}
+
+QDockWidget > QWidget > QTabWidget::pane{
+ margin: 0px;
+ background-color: rgb(17, 133, 209, 255);
+ border: 1px solid rgb(255, 255, 255);
+ border-right-color: rgb(17, 133, 209, 255); /* same as the pane color */
+ padding: 0px;
+}
+
+QDockWidget > QWidget > QTabWidget::pane:disabled{
+ border: 1px solid rgb(200, 200, 200, 255);
+ border-right-color: rgb(17, 133, 209, 255); /* same as the pane color */
+}
+
+QDockWidget > QWidget > QTabWidget > QTabBar::tab
+{
+ background: transparent;
+ color: white;
+ border: 2px solid rgb(238, 178, 17, 255);
+ border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
+ border-bottom-right-radius: 4px;
+ border-top-right-radius: 4px;
+ min-height: 8ex;
+ padding: 2px;
+}
+QDockWidget > QWidget > QTabWidget > QTabBar::tab:hover
+{
+ border: 3px solid rgb(238, 178, 17, 255);
+ border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
+}
+QDockWidget > QWidget > QTabWidget > QTabBar::tab:selected
+{
+ color: white;
+ background: rgb(238, 178, 17, 255);
+ border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
+}
+QDockWidget > QWidget > QTabWidget > QTabBar::tab:disabled
+{
+ color: rgb(200, 200, 200, 50);
+ border: 1px solid rgb(232, 232, 230, 255);
+ background: transparent;
+ border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
+}
+
+QCheckBox,
+QRadioButton,
+QLabel {
+ border: none;
+ min-height: 20px;
+}
+
+QCheckBox::checked,
+QRadioButton::checked {
+ color: black;
+}
+
+QLabel,
+QCheckBox::unchecked,
+QRadioButton::unchecked {
+ color: white;
+}
+
+QCheckBox,
+QLabel {
+ padding: 1px 1px 1px 1px;
+ margin: 0px;
+}
+
+
+QLabel:disabled {
+ color: rgb(200, 200, 200, 255);
+}
+
+QSlider::groove:horizontal {
+ border: 1px solid #999999;
+ height: 2px;
+ margin: 0px 0;
+ left: 10px; right: 10px;
+ border-radius: 4px;
+}
+
+QSlider::handle:horizontal {
+ border-image:url(:/icons/slider-handle.png);
+ margin-left: -12px;
+ margin-right: -12px;
+ margin-top: -11px;
+ margin-bottom: -11px;
+}
+
+QSlider::sub-page:horizontal{
+ background: qlineargradient(spread:pad,
+ x1:0, y1:1, x2:0, y2:0,
+ stop:0 rgba(17, 133, 209, 255),
+ stop:0.25 rgba(238, 178, 17, 255),
+ stop:0.75 rgba(238, 178, 17, 255),
+ stop:1 rgba(17, 133, 209, 255));
+ height: 2px;
+ border-radius: 4px;
+}
+
+QSlider::add-page:horizontal{
+ background: qlineargradient(spread:pad,
+ x1:0, y1:1, x2:0, y2:0,
+ stop:0 rgba(17, 133, 209, 255),
+ stop:0.25 rgba(255, 255, 255, 255),
+ stop:0.75 rgba(255, 255, 255, 255),
+ stop:1 rgba(17, 133, 209, 255));
+ height: 2px;
+ border-radius: 4px;
+}
+
+/* <<< QDockWidget */
|