v0.4 release
@ -19,10 +19,13 @@
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_minimum_required(VERSION 2.8.6)
|
||||
|
||||
include(FindPkgConfig)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake")
|
||||
|
||||
project(DSLogic)
|
||||
|
||||
#===============================================================================
|
||||
@ -31,22 +34,27 @@ project(DSLogic)
|
||||
|
||||
option(DISABLE_WERROR "Build without -Werror" TRUE)
|
||||
option(ENABLE_SIGNALS "Build with UNIX signals" TRUE)
|
||||
option(ENABLE_DECODE "Build with libsigrokdecode" TRUE)
|
||||
option(ENABLE_COTIRE "Enable cotire" FALSE)
|
||||
option(ENABLE_TESTS "Enable unit tests" FALSE)
|
||||
option(STATIC_PKGDEPS_LIBS "Statically link to (pkgconfig) libraries" FALSE)
|
||||
option(STATIC_PKGDEPS_LIBS "Statically link to (pkg-config) libraries" FALSE)
|
||||
option(FORCE_QT4 "Force use of Qt4 even if Qt5 is available" 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
|
||||
# Windows does not support UNIX signals.
|
||||
set(ENABLE_SIGNALS FALSE)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
|
||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE)
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
#= Dependencies
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -55,26 +63,35 @@ list(APPEND PKGDEPS
|
||||
"libsigrok4DSLogic >= 0.2.0"
|
||||
"libusb-1.0 >= 1.0.16"
|
||||
)
|
||||
if(ENABLE_DECODE)
|
||||
list(APPEND PKGDEPS "libsigrokdecode>=0.3.0")
|
||||
endif()
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
if(FORCE_QT4)
|
||||
set(Qt5Core_FOUND FALSE)
|
||||
else()
|
||||
find_package(Boost 1.42 COMPONENTS system thread REQUIRED)
|
||||
find_package(Qt5Core QUIET)
|
||||
endif()
|
||||
|
||||
if(Qt5Core_FOUND)
|
||||
message("-- Using Qt5")
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Gui REQUIRED)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
|
||||
set(QT_INCLUDE_DIRS ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS})
|
||||
set(QT_LIBRARIES Qt5::Gui Qt5::Widgets)
|
||||
add_definitions(${Qt5Gui_DEFINITIONS} ${Qt5Widgets_DEFINITIONS})
|
||||
else()
|
||||
find_program(QT_QMAKE_EXECUTABLE NAMES qmake4 qmake-qt4 qmake-mac)
|
||||
find_package(Qt4 REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
find_package(Boost 1.42 COMPONENTS filesystem system thread REQUIRED)
|
||||
find_package(libusb-1.0 REQUIRED)
|
||||
|
||||
#===============================================================================
|
||||
@ -85,7 +102,7 @@ set(DS_TITLE DSLogic)
|
||||
set(DS_DESCRIPTION "A GUI for DSLogic")
|
||||
|
||||
set(DS_VERSION_MAJOR 0)
|
||||
set(DS_VERSION_MINOR 3)
|
||||
set(DS_VERSION_MINOR 4)
|
||||
set(DS_VERSION_MICRO 0)
|
||||
set(DS_VERSION_STRING
|
||||
${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO}
|
||||
@ -105,31 +122,28 @@ set(DSLogic_SOURCES
|
||||
pv/devicemanager.cpp
|
||||
pv/mainwindow.cpp
|
||||
pv/sigsession.cpp
|
||||
pv/storesession.cpp
|
||||
pv/data/analog.cpp
|
||||
pv/data/analogsnapshot.cpp
|
||||
pv/data/dso.cpp
|
||||
pv/data/dsosnapshot.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/device/devinst.cpp
|
||||
pv/device/device.cpp
|
||||
pv/device/file.cpp
|
||||
pv/device/inputfile.cpp
|
||||
pv/device/sessionfile.cpp
|
||||
pv/dialogs/about.cpp
|
||||
pv/dialogs/connect.cpp
|
||||
pv/dialogs/deviceoptions.cpp
|
||||
pv/dialogs/search.cpp
|
||||
pv/dock/fakelineedit.cpp
|
||||
pv/dialogs/storeprogress.cpp
|
||||
pv/dock/dsotriggerdock.cpp
|
||||
pv/dock/measuredock.cpp
|
||||
pv/dock/protocoldock.cpp
|
||||
pv/dock/searchdock.cpp
|
||||
pv/dock/triggerdock.cpp
|
||||
pv/prop/bool.cpp
|
||||
@ -137,80 +151,116 @@ set(DSLogic_SOURCES
|
||||
pv/prop/enum.cpp
|
||||
pv/prop/int.cpp
|
||||
pv/prop/property.cpp
|
||||
pv/prop/string.cpp
|
||||
pv/prop/binding/binding.cpp
|
||||
pv/prop/binding/binding_deviceoptions.cpp
|
||||
pv/toolbars/devicebar.cpp
|
||||
pv/prop/binding/deviceoptions.cpp
|
||||
pv/prop/binding/decoderoptions.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/devmode.cpp
|
||||
pv/view/dsldial.cpp
|
||||
pv/view/dsosignal.cpp
|
||||
pv/view/groupsignal.cpp
|
||||
pv/view/header.cpp
|
||||
pv/view/logicsignal.cpp
|
||||
pv/view/protocolsignal.cpp
|
||||
pv/view/ruler.cpp
|
||||
pv/view/selectableitem.cpp
|
||||
pv/view/signal.cpp
|
||||
pv/view/timemarker.cpp
|
||||
pv/view/trace.cpp
|
||||
pv/view/view.cpp
|
||||
pv/view/viewport.cpp
|
||||
pv/view/dsosignal.cpp
|
||||
pv/view/dsldial.cpp
|
||||
pv/dock/dsotriggerdock.cpp
|
||||
pv/widgets/fakelineedit.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/sigsession.h
|
||||
pv/storesession.h
|
||||
pv/device/devinst.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/dialogs/storeprogress.h
|
||||
pv/dock/dsotriggerdock.h
|
||||
pv/dock/measuredock.h
|
||||
pv/dock/searchdock.h
|
||||
pv/dock/triggerdock.h
|
||||
pv/prop/bool.h
|
||||
pv/prop/double.h
|
||||
pv/prop/enum.h
|
||||
pv/prop/int.h
|
||||
pv/prop/property.h
|
||||
pv/prop/string.h
|
||||
pv/toolbars/filebar.h
|
||||
pv/toolbars/logobar.h
|
||||
pv/toolbars/samplingbar.h
|
||||
pv/toolbars/trigbar.h
|
||||
pv/data/dso.h
|
||||
pv/data/dsosnapshot.h
|
||||
pv/view/cursor.h
|
||||
pv/view/devmode.h
|
||||
pv/view/header.h
|
||||
pv/view/ruler.h
|
||||
pv/view/selectableitem.h
|
||||
pv/view/timemarker.h
|
||||
pv/view/groupsignal.h
|
||||
pv/view/protocolsignal.h
|
||||
pv/view/trace.h
|
||||
pv/view/view.h
|
||||
pv/view/dsosignal.h
|
||||
pv/view/viewport.h
|
||||
pv/view/dsldial.h
|
||||
pv/dock/dsotriggerdock.h
|
||||
pv/widgets/fakelineedit.h
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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})
|
||||
if(ENABLE_DECODE)
|
||||
list(APPEND DSLogic_SOURCES
|
||||
pv/dock/protocoldock.cpp
|
||||
pv/data/decoderstack.cpp
|
||||
pv/data/decode/annotation.cpp
|
||||
pv/data/decode/decoder.cpp
|
||||
pv/data/decode/row.cpp
|
||||
pv/data/decode/rowdata.cpp
|
||||
pv/prop/binding/decoderoptions.cpp
|
||||
pv/view/decodetrace.cpp
|
||||
pv/widgets/decodergroupbox.cpp
|
||||
pv/widgets/decodermenu.cpp
|
||||
)
|
||||
|
||||
list(APPEND DSLogic_HEADERS
|
||||
pv/dock/protocoldock.h
|
||||
pv/data/decoderstack.h
|
||||
pv/view/decodetrace.h
|
||||
pv/widgets/decodergroupbox.h
|
||||
pv/widgets/decodermenu.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# Use the DSLogic icon for the DSLogic.exe executable.
|
||||
set(CMAKE_RC_COMPILE_OBJECT "${CMAKE_RC_COMPILER} -O coff -I${CMAKE_CURRENT_SOURCE_DIR} <SOURCE> <OBJECT>")
|
||||
enable_language(RC)
|
||||
list(APPEND DSLogic_SOURCES DSLogic.rc)
|
||||
endif()
|
||||
|
||||
if(Qt5Core_FOUND)
|
||||
qt5_wrap_cpp(DSLogic_HEADERS_MOC ${DSLogic_HEADERS})
|
||||
qt5_wrap_ui(DSLogic_FORMS_HEADERS ${DSLogic_FORMS})
|
||||
qt5_add_resources(DSLogic_RESOURCES_RCC ${DSLogic_RESOURCES})
|
||||
else()
|
||||
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})
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
#= Global Definitions
|
||||
@ -219,8 +269,12 @@ include(${QT_USE_FILE})
|
||||
add_definitions(${QT_DEFINITIONS})
|
||||
add_definitions(-Wall -Wextra -Wno-return-type -Wno-ignored-qualifiers)
|
||||
|
||||
if(ENABLE_DECODE)
|
||||
add_definitions(-DENABLE_DECODE)
|
||||
endif()
|
||||
|
||||
if(NOT DISABLE_WERROR)
|
||||
add_definitions(-Werror)
|
||||
add_definitions(-Werror)
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
@ -231,6 +285,7 @@ include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${QT_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(STATIC_PKGDEPS_LIBS)
|
||||
@ -255,11 +310,16 @@ set(DSLOGIC_LINK_LIBS
|
||||
if(STATIC_PKGDEPS_LIBS)
|
||||
link_directories(${PKGDEPS_STATIC_LIBRARY_DIRS})
|
||||
list(APPEND DSLOGIC_LINK_LIBS ${PKGDEPS_STATIC_LIBRARIES})
|
||||
if(WIN32)
|
||||
# Workaround for a MinGW linking issue.
|
||||
list(APPEND PULSEVIEW_LINK_LIBS "-llzma -llcms2")
|
||||
endif()
|
||||
else()
|
||||
link_directories(${PKGDEPS_LIBRARY_DIRS})
|
||||
list(APPEND DSLOGIC_LINK_LIBS ${PKGDEPS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
${DSLogic_SOURCES}
|
||||
${DSLogic_HEADERS_MOC}
|
||||
@ -273,6 +333,12 @@ 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()
|
||||
|
||||
|
||||
if(ENABLE_COTIRE)
|
||||
include(cotire)
|
||||
cotire(${PROJECT_NAME})
|
||||
endif()
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "/usr/local/lib")
|
||||
|
||||
#===============================================================================
|
||||
@ -282,7 +348,8 @@ set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "/usr/local/lib")
|
||||
# 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/)
|
||||
install(FILES res/DSLogic33.bin DESTINATION bin/res/)
|
||||
install(FILES res/DSLogic50.bin DESTINATION bin/res/)
|
||||
|
||||
#===============================================================================
|
||||
#= Packaging (handled by CPack)
|
||||
|
@ -4,14 +4,12 @@
|
||||
<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>
|
||||
@ -20,14 +18,22 @@
|
||||
<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>
|
||||
<file>icons/decoder-hidden.png</file>
|
||||
<file>icons/decoder-shown.png</file>
|
||||
<file>icons/instant.png</file>
|
||||
<file>icons/trigger_dis.png</file>
|
||||
<file>icons/file_dis.png</file>
|
||||
<file>icons/measure_dis.png</file>
|
||||
<file>icons/protocol_dis.png</file>
|
||||
<file>icons/search-bar_dis.png</file>
|
||||
<file>icons/params_dis.png</file>
|
||||
<file>icons/gear.png</file>
|
||||
<file>icons/wiki.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 5.9 KiB |
BIN
DSLogic-gui/icons/decoder-hidden.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
DSLogic-gui/icons/decoder-shown.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 1.2 KiB |
BIN
DSLogic-gui/icons/file_dis.png
Normal file
After Width: | Height: | Size: 811 B |
BIN
DSLogic-gui/icons/gear.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
DSLogic-gui/icons/instant.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 364 B After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 364 B After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
DSLogic-gui/icons/measure_dis.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 632 B After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
DSLogic-gui/icons/params_dis.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 648 B After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
DSLogic-gui/icons/protocol_dis.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
DSLogic-gui/icons/search-bar_dis.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 789 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 1007 B |
BIN
DSLogic-gui/icons/trigger_dis.png
Normal file
After Width: | Height: | Size: 978 B |
BIN
DSLogic-gui/icons/wiki.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifdef ENABLE_SIGROKDECODE
|
||||
#ifdef ENABLE_DECODE
|
||||
#include <libsigrokdecode/libsigrokdecode.h> /* First, so we avoid a _POSIX_C_SOURCE warning. */
|
||||
#endif
|
||||
|
||||
@ -33,12 +33,15 @@
|
||||
#include <QtGui/QApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
#include "pv/devicemanager.h"
|
||||
#include "pv/mainwindow.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
char decoders_path[256];
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf(stdout,
|
||||
@ -85,7 +88,7 @@ int main(int argc, char *argv[])
|
||||
const int loglevel = atoi(optarg);
|
||||
sr_log_loglevel_set(loglevel);
|
||||
|
||||
#ifdef ENABLE_SIGROKDECODE
|
||||
#ifdef ENABLE_DECODE
|
||||
srd_log_loglevel_set(loglevel);
|
||||
#endif
|
||||
|
||||
@ -118,7 +121,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
do {
|
||||
|
||||
#ifdef ENABLE_SIGROKDECODE
|
||||
#ifdef ENABLE_DECODE
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
assert(dir.cd("decoders"));
|
||||
std::string str = dir.absolutePath().toStdString() + "/";
|
||||
strcpy(decoders_path, str.c_str());
|
||||
|
||||
// Initialise libsigrokdecode
|
||||
if (srd_init(NULL) != SRD_OK) {
|
||||
qDebug() << "ERROR: libsigrokdecode init failed.";
|
||||
@ -148,7 +156,7 @@ int main(int argc, char *argv[])
|
||||
qDebug() << e.what();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SIGROKDECODE
|
||||
#ifdef ENABLE_DECODE
|
||||
// Destroy libsigrokdecode
|
||||
srd_exit();
|
||||
#endif
|
||||
|
@ -30,11 +30,17 @@ using namespace std;
|
||||
namespace pv {
|
||||
namespace data {
|
||||
|
||||
Analog::Analog(unsigned int num_probes, uint64_t samplerate) :
|
||||
SignalData(num_probes, samplerate)
|
||||
Analog::Analog(unsigned int num_probes) :
|
||||
SignalData(),
|
||||
_num_probes(num_probes)
|
||||
{
|
||||
}
|
||||
|
||||
int Analog::get_num_probes() const
|
||||
{
|
||||
return _num_probes;
|
||||
}
|
||||
|
||||
void Analog::push_snapshot(boost::shared_ptr<AnalogSnapshot> &snapshot)
|
||||
{
|
||||
_snapshots.push_front(snapshot);
|
||||
@ -45,5 +51,10 @@ deque< boost::shared_ptr<AnalogSnapshot> >& Analog::get_snapshots()
|
||||
return _snapshots;
|
||||
}
|
||||
|
||||
void Analog::clear()
|
||||
{
|
||||
_snapshots.clear();
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
@ -37,7 +37,9 @@ class AnalogSnapshot;
|
||||
class Analog : public SignalData
|
||||
{
|
||||
public:
|
||||
Analog(unsigned int num_probes, uint64_t samplerate);
|
||||
Analog(unsigned int num_probes);
|
||||
|
||||
int get_num_probes() const;
|
||||
|
||||
void push_snapshot(
|
||||
boost::shared_ptr<AnalogSnapshot> &snapshot);
|
||||
@ -45,7 +47,10 @@ public:
|
||||
std::deque< boost::shared_ptr<AnalogSnapshot> >&
|
||||
get_snapshots();
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
const unsigned int _num_probes;
|
||||
std::deque< boost::shared_ptr<AnalogSnapshot> > _snapshots;
|
||||
};
|
||||
|
||||
|
@ -75,6 +75,8 @@ void AnalogSnapshot::append_payload(
|
||||
const uint16_t* AnalogSnapshot::get_samples(
|
||||
int64_t start_sample, int64_t end_sample) const
|
||||
{
|
||||
(void)end_sample;
|
||||
|
||||
assert(start_sample >= 0);
|
||||
assert(start_sample < (int64_t)get_sample_count());
|
||||
assert(end_sample >= 0);
|
||||
|
74
DSLogic-gui/pv/data/decode/annotation.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include <libsigrokdecode/libsigrokdecode.h>
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
|
||||
#include "annotation.h"
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
namespace decode {
|
||||
|
||||
Annotation::Annotation(const srd_proto_data *const pdata) :
|
||||
_start_sample(pdata->start_sample),
|
||||
_end_sample(pdata->end_sample)
|
||||
{
|
||||
assert(pdata);
|
||||
const srd_proto_data_annotation *const pda =
|
||||
(const srd_proto_data_annotation*)pdata->data;
|
||||
assert(pda);
|
||||
|
||||
_format = pda->ann_format;
|
||||
|
||||
const char *const *annotations = (char**)pda->ann_text;
|
||||
while(*annotations) {
|
||||
_annotations.push_back(QString::fromUtf8(*annotations));
|
||||
annotations++;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Annotation::start_sample() const
|
||||
{
|
||||
return _start_sample;
|
||||
}
|
||||
|
||||
uint64_t Annotation::end_sample() const
|
||||
{
|
||||
return _end_sample;
|
||||
}
|
||||
|
||||
int Annotation::format() const
|
||||
{
|
||||
return _format;
|
||||
}
|
||||
|
||||
const std::vector<QString>& Annotation::annotations() const
|
||||
{
|
||||
return _annotations;
|
||||
}
|
||||
|
||||
} // namespace decode
|
||||
} // namespace data
|
||||
} // namespace pv
|
55
DSLogic-gui/pv/data/decode/annotation.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_VIEW_DECODE_ANNOTATION_H
|
||||
#define DSLOGIC_PV_VIEW_DECODE_ANNOTATION_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
struct srd_proto_data;
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
namespace decode {
|
||||
|
||||
class Annotation
|
||||
{
|
||||
public:
|
||||
Annotation(const srd_proto_data *const pdata);
|
||||
|
||||
uint64_t start_sample() const;
|
||||
uint64_t end_sample() const;
|
||||
int format() const;
|
||||
const std::vector<QString>& annotations() const;
|
||||
|
||||
private:
|
||||
uint64_t _start_sample;
|
||||
uint64_t _end_sample;
|
||||
int _format;
|
||||
std::vector<QString> _annotations;
|
||||
};
|
||||
|
||||
} // namespace decode
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
||||
#endif // DSLOGIC_PV_VIEW_DECODE_ANNOTATION_H
|
185
DSLogic-gui/pv/data/decode/decoder.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 <libsigrok4DSLogic/libsigrok.h>
|
||||
#include <libsigrokdecode/libsigrokdecode.h>
|
||||
|
||||
#include "decoder.h"
|
||||
|
||||
#include <pv/view/logicsignal.h>
|
||||
|
||||
using boost::shared_ptr;
|
||||
using std::set;
|
||||
using std::map;
|
||||
using std::string;
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
namespace decode {
|
||||
|
||||
Decoder::Decoder(const srd_decoder *const dec) :
|
||||
_decoder(dec),
|
||||
_shown(true),
|
||||
_shown_back(true),
|
||||
_shown_setted(false),
|
||||
_setted(true)
|
||||
{
|
||||
}
|
||||
|
||||
Decoder::~Decoder()
|
||||
{
|
||||
for (map<string, GVariant*>::const_iterator i = _options.begin();
|
||||
i != _options.end(); i++)
|
||||
g_variant_unref((*i).second);
|
||||
}
|
||||
|
||||
const srd_decoder* Decoder::decoder() const
|
||||
{
|
||||
return _decoder;
|
||||
}
|
||||
|
||||
bool Decoder::shown() const
|
||||
{
|
||||
return _shown;
|
||||
}
|
||||
|
||||
void Decoder::show(bool show)
|
||||
{
|
||||
_shown_back = show;
|
||||
_shown_setted = true;
|
||||
}
|
||||
|
||||
void Decoder::commit_show()
|
||||
{
|
||||
if (_shown_setted) {
|
||||
_shown = _shown_back;
|
||||
_shown_setted = false;
|
||||
}
|
||||
}
|
||||
|
||||
const map<const srd_channel*, shared_ptr<view::LogicSignal> >&
|
||||
Decoder::channels() const
|
||||
{
|
||||
return _probes;
|
||||
}
|
||||
|
||||
void Decoder::set_probes(std::map<const srd_channel*,
|
||||
boost::shared_ptr<view::LogicSignal> > probes)
|
||||
{
|
||||
_probes_back = probes;
|
||||
_setted = true;
|
||||
}
|
||||
|
||||
const std::map<std::string, GVariant*>& Decoder::options() const
|
||||
{
|
||||
return _options;
|
||||
}
|
||||
|
||||
void Decoder::set_option(const char *id, GVariant *value)
|
||||
{
|
||||
assert(value);
|
||||
g_variant_ref(value);
|
||||
_options_back[id] = value;
|
||||
_setted = true;
|
||||
}
|
||||
|
||||
bool Decoder::commit()
|
||||
{
|
||||
if (_setted) {
|
||||
_probes = _probes_back;
|
||||
_options = _options_back;
|
||||
_setted = false;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Decoder::have_required_probes() const
|
||||
{
|
||||
for (GSList *l = _decoder->channels; l; l = l->next) {
|
||||
const srd_channel *const pdch = (const srd_channel*)l->data;
|
||||
assert(pdch);
|
||||
if (_probes.find(pdch) == _probes.end())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
set< shared_ptr<pv::data::Logic> > Decoder::get_data()
|
||||
{
|
||||
set< shared_ptr<pv::data::Logic> > data;
|
||||
for(map<const srd_channel*, shared_ptr<view::LogicSignal> >::
|
||||
const_iterator i = _probes.begin();
|
||||
i != _probes.end(); i++)
|
||||
{
|
||||
shared_ptr<view::LogicSignal> signal((*i).second);
|
||||
assert(signal);
|
||||
data.insert(signal->logic_data());
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session, int unit_size) const
|
||||
{
|
||||
GHashTable *const opt_hash = g_hash_table_new_full(g_str_hash,
|
||||
g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
|
||||
|
||||
for (map<string, GVariant*>::const_iterator i = _options.begin();
|
||||
i != _options.end(); i++)
|
||||
{
|
||||
GVariant *const value = (*i).second;
|
||||
g_variant_ref(value);
|
||||
g_hash_table_replace(opt_hash, (void*)g_strdup(
|
||||
(*i).first.c_str()), value);
|
||||
}
|
||||
|
||||
srd_decoder_inst *const decoder_inst = srd_inst_new(
|
||||
session, _decoder->id, opt_hash);
|
||||
g_hash_table_destroy(opt_hash);
|
||||
|
||||
if(!decoder_inst)
|
||||
return NULL;
|
||||
|
||||
// Setup the probes
|
||||
GHashTable *const probes = g_hash_table_new_full(g_str_hash,
|
||||
g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
|
||||
|
||||
for(map<const srd_channel*, shared_ptr<view::LogicSignal> >::
|
||||
const_iterator i = _probes.begin();
|
||||
i != _probes.end(); i++)
|
||||
{
|
||||
shared_ptr<view::LogicSignal> signal((*i).second);
|
||||
GVariant *const gvar = g_variant_new_int32(
|
||||
signal->probe()->index);
|
||||
g_variant_ref_sink(gvar);
|
||||
g_hash_table_insert(probes, (*i).first->id, gvar);
|
||||
}
|
||||
|
||||
srd_inst_channel_set_all(decoder_inst, probes, unit_size);
|
||||
|
||||
return decoder_inst;
|
||||
}
|
||||
|
||||
} // decode
|
||||
} // data
|
||||
} // pv
|
101
DSLogic-gui/pv/data/decode/decoder.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DECODE_DECODER_H
|
||||
#define DSLOGIC_PV_DATA_DECODE_DECODER_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
struct srd_decoder;
|
||||
struct srd_decoder_inst;
|
||||
struct srd_channel;
|
||||
struct srd_session;
|
||||
|
||||
namespace pv {
|
||||
|
||||
namespace view {
|
||||
class LogicSignal;
|
||||
}
|
||||
|
||||
namespace data {
|
||||
|
||||
class Logic;
|
||||
|
||||
namespace decode {
|
||||
|
||||
class Decoder
|
||||
{
|
||||
public:
|
||||
Decoder(const srd_decoder *const decoder);
|
||||
|
||||
virtual ~Decoder();
|
||||
|
||||
const srd_decoder* decoder() const;
|
||||
|
||||
bool shown() const;
|
||||
void show(bool show = true);
|
||||
void commit_show();
|
||||
|
||||
const std::map<const srd_channel*,
|
||||
boost::shared_ptr<view::LogicSignal> >& channels() const;
|
||||
void set_probes(std::map<const srd_channel*,
|
||||
boost::shared_ptr<view::LogicSignal> > probes);
|
||||
|
||||
const std::map<std::string, GVariant*>& options() const;
|
||||
|
||||
void set_option(const char *id, GVariant *value);
|
||||
|
||||
bool have_required_probes() const;
|
||||
|
||||
srd_decoder_inst* create_decoder_inst(
|
||||
srd_session *session, int unit_size) const;
|
||||
|
||||
std::set< boost::shared_ptr<pv::data::Logic> > get_data();
|
||||
|
||||
bool commit();
|
||||
|
||||
private:
|
||||
const srd_decoder *const _decoder;
|
||||
|
||||
bool _shown;
|
||||
bool _shown_back;
|
||||
bool _shown_setted;
|
||||
|
||||
std::map<const srd_channel*, boost::shared_ptr<pv::view::LogicSignal> >
|
||||
_probes;
|
||||
std::map<std::string, GVariant*> _options;
|
||||
|
||||
std::map<const srd_channel*, boost::shared_ptr<pv::view::LogicSignal> >
|
||||
_probes_back;
|
||||
std::map<std::string, GVariant*> _options_back;
|
||||
|
||||
bool _setted;
|
||||
};
|
||||
|
||||
} // namespace decode
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
||||
#endif // DSLOGIC_PV_DATA_DECODE_DECODER_H
|
72
DSLogic-gui/pv/data/decode/row.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 "row.h"
|
||||
|
||||
#include <libsigrokdecode/libsigrokdecode.h>
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
namespace decode {
|
||||
|
||||
Row::Row() :
|
||||
_decoder(NULL),
|
||||
_row(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Row::Row(const srd_decoder *decoder, const srd_decoder_annotation_row *row) :
|
||||
_decoder(decoder),
|
||||
_row(row)
|
||||
{
|
||||
}
|
||||
|
||||
const srd_decoder* Row::decoder() const
|
||||
{
|
||||
return _decoder;
|
||||
}
|
||||
|
||||
const srd_decoder_annotation_row* Row::row() const
|
||||
{
|
||||
return _row;
|
||||
}
|
||||
|
||||
const QString Row::title() const
|
||||
{
|
||||
if (_decoder && _decoder->name && _row && _row->desc)
|
||||
return QString("%1: %2")
|
||||
.arg(QString::fromUtf8(_decoder->name))
|
||||
.arg(QString::fromUtf8(_row->desc));
|
||||
if (_decoder && _decoder->name)
|
||||
return QString::fromUtf8(_decoder->name);
|
||||
if (_row && _row->desc)
|
||||
return QString::fromUtf8(_row->desc);
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool Row::operator<(const Row &other) const
|
||||
{
|
||||
return (_decoder < other._decoder) ||
|
||||
(_decoder == other._decoder && _row < other._row);
|
||||
}
|
||||
|
||||
} // decode
|
||||
} // data
|
||||
} // pv
|
59
DSLogic-gui/pv/data/decode/row.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DECODE_ROW_H
|
||||
#define DSLOGIC_PV_DATA_DECODE_ROW_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "annotation.h"
|
||||
|
||||
struct srd_decoder;
|
||||
struct srd_decoder_annotation_row;
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
namespace decode {
|
||||
|
||||
class Row
|
||||
{
|
||||
public:
|
||||
Row();
|
||||
|
||||
Row(const srd_decoder *decoder,
|
||||
const srd_decoder_annotation_row *row = NULL);
|
||||
|
||||
const srd_decoder* decoder() const;
|
||||
const srd_decoder_annotation_row* row() const;
|
||||
|
||||
const QString title() const;
|
||||
|
||||
bool operator<(const Row &other) const;
|
||||
|
||||
private:
|
||||
const srd_decoder *_decoder;
|
||||
const srd_decoder_annotation_row *_row;
|
||||
};
|
||||
|
||||
} // decode
|
||||
} // data
|
||||
} // pv
|
||||
|
||||
#endif // DSLOGIC_PV_DATA_DECODE_ROW_H
|
68
DSLogic-gui/pv/data/decode/rowdata.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 <math.h>
|
||||
|
||||
#include "rowdata.h"
|
||||
|
||||
using std::max;
|
||||
using std::vector;
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
namespace decode {
|
||||
|
||||
RowData::RowData() :
|
||||
_max_annotation(0)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t RowData::get_max_sample() const
|
||||
{
|
||||
if (_annotations.empty())
|
||||
return 0;
|
||||
return _annotations.back().end_sample();
|
||||
}
|
||||
|
||||
uint64_t RowData::get_max_annotation() const
|
||||
{
|
||||
return _max_annotation;
|
||||
}
|
||||
|
||||
void RowData::get_annotation_subset(
|
||||
vector<pv::data::decode::Annotation> &dest,
|
||||
uint64_t start_sample, uint64_t end_sample) const
|
||||
{
|
||||
for (vector<Annotation>::const_iterator i = _annotations.begin();
|
||||
i != _annotations.end(); i++)
|
||||
if ((*i).end_sample() > start_sample &&
|
||||
(*i).start_sample() <= end_sample)
|
||||
dest.push_back(*i);
|
||||
}
|
||||
|
||||
void RowData::push_annotation(const Annotation &a)
|
||||
{
|
||||
_annotations.push_back(a);
|
||||
_max_annotation = max(_max_annotation, a.end_sample() - a.start_sample());
|
||||
}
|
||||
|
||||
} // decode
|
||||
} // data
|
||||
} // pv
|
59
DSLogic-gui/pv/data/decode/rowdata.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DECODE_ROWDATA_H
|
||||
#define DSLOGIC_PV_DATA_DECODE_ROWDATA_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "annotation.h"
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
namespace decode {
|
||||
|
||||
class RowData
|
||||
{
|
||||
public:
|
||||
RowData();
|
||||
|
||||
public:
|
||||
uint64_t get_max_sample() const;
|
||||
|
||||
uint64_t get_max_annotation() const;
|
||||
/**
|
||||
* Extracts sorted annotations between two period into a vector.
|
||||
*/
|
||||
void get_annotation_subset(
|
||||
std::vector<pv::data::decode::Annotation> &dest,
|
||||
uint64_t start_sample, uint64_t end_sample) const;
|
||||
|
||||
void push_annotation(const Annotation &a);
|
||||
|
||||
private:
|
||||
uint64_t _max_annotation;
|
||||
std::vector<Annotation> _annotations;
|
||||
};
|
||||
|
||||
}
|
||||
} // data
|
||||
} // pv
|
||||
|
||||
#endif // DSLOGIC_PV_DATA_DECODE_ROWDATA_H
|
526
DSLogic-gui/pv/data/decoderstack.cpp
Normal file
@ -0,0 +1,526 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 <libsigrokdecode/libsigrokdecode.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "decoderstack.h"
|
||||
|
||||
#include <pv/data/logic.h>
|
||||
#include <pv/data/logicsnapshot.h>
|
||||
#include <pv/data/decode/decoder.h>
|
||||
#include <pv/data/decode/annotation.h>
|
||||
#include <pv/sigsession.h>
|
||||
#include <pv/view/logicsignal.h>
|
||||
|
||||
using boost::lock_guard;
|
||||
using boost::mutex;
|
||||
using boost::optional;
|
||||
using boost::shared_ptr;
|
||||
using boost::unique_lock;
|
||||
using std::deque;
|
||||
using std::make_pair;
|
||||
using std::max;
|
||||
using std::min;
|
||||
using std::list;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::vector;
|
||||
|
||||
using namespace pv::data::decode;
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
|
||||
const double DecoderStack::DecodeMargin = 1.0;
|
||||
const double DecoderStack::DecodeThreshold = 0.2;
|
||||
const int64_t DecoderStack::DecodeChunkLength = 1024 * 1024;
|
||||
const unsigned int DecoderStack::DecodeNotifyPeriod = 1;
|
||||
|
||||
mutex DecoderStack::_global_decode_mutex;
|
||||
|
||||
DecoderStack::DecoderStack(pv::SigSession &session,
|
||||
const srd_decoder *const dec) :
|
||||
_session(session),
|
||||
_sample_count(0),
|
||||
_frame_complete(false),
|
||||
_samples_decoded(0),
|
||||
_decode_state(Stopped),
|
||||
_options_changed(false)
|
||||
{
|
||||
connect(&_session, SIGNAL(frame_began()),
|
||||
this, SLOT(on_new_frame()));
|
||||
connect(&_session, SIGNAL(data_received()),
|
||||
this, SLOT(on_data_received()));
|
||||
connect(&_session, SIGNAL(frame_ended()),
|
||||
this, SLOT(on_frame_ended()));
|
||||
|
||||
_stack.push_back(shared_ptr<decode::Decoder>(
|
||||
new decode::Decoder(dec)));
|
||||
}
|
||||
|
||||
DecoderStack::~DecoderStack()
|
||||
{
|
||||
// if (_decode_thread.joinable()) {
|
||||
// _decode_thread.interrupt();
|
||||
// _decode_thread.join();
|
||||
// }
|
||||
stop_decode();
|
||||
}
|
||||
|
||||
const std::list< boost::shared_ptr<decode::Decoder> >&
|
||||
DecoderStack::stack() const
|
||||
{
|
||||
return _stack;
|
||||
}
|
||||
|
||||
void DecoderStack::push(boost::shared_ptr<decode::Decoder> decoder)
|
||||
{
|
||||
assert(decoder);
|
||||
_stack.push_back(decoder);
|
||||
}
|
||||
|
||||
void DecoderStack::remove(int index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < (int)_stack.size());
|
||||
|
||||
// Find the decoder in the stack
|
||||
list< shared_ptr<Decoder> >::iterator iter = _stack.begin();
|
||||
for(int i = 0; i < index; i++, iter++)
|
||||
assert(iter != _stack.end());
|
||||
|
||||
// Delete the element
|
||||
_stack.erase(iter);
|
||||
}
|
||||
|
||||
int64_t DecoderStack::samples_decoded() const
|
||||
{
|
||||
lock_guard<mutex> decode_lock(_output_mutex);
|
||||
return _samples_decoded;
|
||||
}
|
||||
|
||||
std::vector< std::pair<decode::Row, bool> > DecoderStack::get_visible_rows() const
|
||||
{
|
||||
lock_guard<mutex> lock(_output_mutex);
|
||||
|
||||
std::vector< std::pair<decode::Row, bool> > rows;
|
||||
|
||||
BOOST_FOREACH (const shared_ptr<decode::Decoder> &dec, _stack)
|
||||
{
|
||||
assert(dec);
|
||||
|
||||
const srd_decoder *const decc = dec->decoder();
|
||||
assert(dec->decoder());
|
||||
|
||||
// Add a row for the decoder if it doesn't have a row list
|
||||
if (!decc->annotation_rows)
|
||||
rows.push_back(make_pair(Row(decc), dec->shown()));
|
||||
|
||||
// Add the decoder rows
|
||||
for (const GSList *l = decc->annotation_rows; l; l = l->next)
|
||||
{
|
||||
const srd_decoder_annotation_row *const ann_row =
|
||||
(srd_decoder_annotation_row *)l->data;
|
||||
assert(ann_row);
|
||||
rows.push_back(make_pair(Row(decc, ann_row), dec->shown()));
|
||||
}
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
void DecoderStack::get_annotation_subset(
|
||||
std::vector<pv::data::decode::Annotation> &dest,
|
||||
const Row &row, uint64_t start_sample,
|
||||
uint64_t end_sample) const
|
||||
{
|
||||
lock_guard<mutex> lock(_output_mutex);
|
||||
|
||||
std::map<const Row, decode::RowData>::const_iterator iter =
|
||||
_rows.find(row);
|
||||
if (iter != _rows.end())
|
||||
(*iter).second.get_annotation_subset(dest,
|
||||
start_sample, end_sample);
|
||||
}
|
||||
|
||||
uint64_t DecoderStack::get_max_annotation(const Row &row)
|
||||
{
|
||||
lock_guard<mutex> lock(_output_mutex);
|
||||
|
||||
std::map<const Row, decode::RowData>::const_iterator iter =
|
||||
_rows.find(row);
|
||||
if (iter != _rows.end())
|
||||
return (*iter).second.get_max_annotation();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DecoderStack::has_annotations(const Row &row) const
|
||||
{
|
||||
lock_guard<mutex> lock(_output_mutex);
|
||||
|
||||
std::map<const Row, decode::RowData>::const_iterator iter =
|
||||
_rows.find(row);
|
||||
if (iter != _rows.end())
|
||||
if(0 == (*iter).second.get_max_sample())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
QString DecoderStack::error_message()
|
||||
{
|
||||
lock_guard<mutex> lock(_output_mutex);
|
||||
return _error_message;
|
||||
}
|
||||
|
||||
void DecoderStack::clear()
|
||||
{
|
||||
_sample_count = 0;
|
||||
_frame_complete = false;
|
||||
_samples_decoded = 0;
|
||||
_error_message = QString();
|
||||
_rows.clear();
|
||||
_class_rows.clear();
|
||||
}
|
||||
|
||||
void DecoderStack::stop_decode()
|
||||
{
|
||||
if(_decode_state == Stopped)
|
||||
return;
|
||||
|
||||
if (_decode_thread.get()) {
|
||||
_decode_thread->interrupt();
|
||||
_decode_thread->join();
|
||||
_decode_state = Stopped;
|
||||
}
|
||||
_decode_thread.reset();
|
||||
}
|
||||
|
||||
void DecoderStack::begin_decode()
|
||||
{
|
||||
shared_ptr<pv::view::LogicSignal> logic_signal;
|
||||
shared_ptr<pv::data::Logic> data;
|
||||
|
||||
if (!_options_changed)
|
||||
return;
|
||||
// if (_decode_thread.joinable()) {
|
||||
// _decode_thread.interrupt();
|
||||
// _decode_thread.join();
|
||||
// }
|
||||
stop_decode();
|
||||
|
||||
clear();
|
||||
|
||||
// Check that all decoders have the required channels
|
||||
BOOST_FOREACH(const shared_ptr<decode::Decoder> &dec, _stack)
|
||||
if (!dec->have_required_probes()) {
|
||||
_error_message = tr("One or more required channels "
|
||||
"have not been specified");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add classes
|
||||
BOOST_FOREACH (const shared_ptr<decode::Decoder> &dec, _stack)
|
||||
{
|
||||
assert(dec);
|
||||
const srd_decoder *const decc = dec->decoder();
|
||||
assert(dec->decoder());
|
||||
|
||||
// Add a row for the decoder if it doesn't have a row list
|
||||
if (!decc->annotation_rows)
|
||||
_rows[Row(decc)] = decode::RowData();
|
||||
|
||||
// Add the decoder rows
|
||||
for (const GSList *l = decc->annotation_rows; l; l = l->next)
|
||||
{
|
||||
const srd_decoder_annotation_row *const ann_row =
|
||||
(srd_decoder_annotation_row *)l->data;
|
||||
assert(ann_row);
|
||||
|
||||
const Row row(decc, ann_row);
|
||||
|
||||
// Add a new empty row data object
|
||||
_rows[row] = decode::RowData();
|
||||
|
||||
// Map out all the classes
|
||||
for (const GSList *ll = ann_row->ann_classes;
|
||||
ll; ll = ll->next)
|
||||
_class_rows[make_pair(decc,
|
||||
GPOINTER_TO_INT(ll->data))] = row;
|
||||
}
|
||||
}
|
||||
|
||||
// We get the logic data of the first channel in the list.
|
||||
// This works because we are currently assuming all
|
||||
// LogicSignals have the same data/snapshot
|
||||
BOOST_FOREACH (const shared_ptr<decode::Decoder> &dec, _stack)
|
||||
if (dec && !dec->channels().empty() &&
|
||||
((logic_signal = (*dec->channels().begin()).second)) &&
|
||||
((data = logic_signal->logic_data())))
|
||||
break;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
// Check we have a snapshot of data
|
||||
const deque< shared_ptr<pv::data::LogicSnapshot> > &snapshots =
|
||||
data->get_snapshots();
|
||||
if (snapshots.empty())
|
||||
return;
|
||||
_snapshot = snapshots.front();
|
||||
|
||||
// Get the samplerate and start time
|
||||
_start_time = data->get_start_time();
|
||||
_samplerate = data->samplerate();
|
||||
if (_samplerate == 0.0)
|
||||
_samplerate = 1.0;
|
||||
|
||||
//_decode_thread = boost::thread(&DecoderStack::decode_proc, this);
|
||||
_decode_thread.reset(new boost::thread(&DecoderStack::decode_proc, this));
|
||||
}
|
||||
|
||||
uint64_t DecoderStack::get_max_sample_count() const
|
||||
{
|
||||
uint64_t max_sample_count = 0;
|
||||
|
||||
for (map<const Row, RowData>::const_iterator i = _rows.begin();
|
||||
i != _rows.end(); i++)
|
||||
max_sample_count = max(max_sample_count,
|
||||
(*i).second.get_max_sample());
|
||||
|
||||
return max_sample_count;
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> DecoderStack::wait_for_data() const
|
||||
{
|
||||
unique_lock<mutex> input_lock(_input_mutex);
|
||||
while(!boost::this_thread::interruption_requested() &&
|
||||
!_frame_complete && (uint64_t)_samples_decoded >= _sample_count)
|
||||
_input_cond.wait(input_lock);
|
||||
return boost::make_optional(
|
||||
!boost::this_thread::interruption_requested() &&
|
||||
((uint64_t)_samples_decoded < _sample_count || !_frame_complete),
|
||||
_sample_count);
|
||||
}
|
||||
|
||||
void DecoderStack::decode_data(
|
||||
const uint64_t sample_count, const unsigned int unit_size,
|
||||
srd_session *const session)
|
||||
{
|
||||
//uint8_t chunk[DecodeChunkLength];
|
||||
uint8_t *chunk = NULL;
|
||||
chunk = (uint8_t *)realloc(chunk, DecodeChunkLength);
|
||||
|
||||
const uint64_t chunk_sample_count =
|
||||
DecodeChunkLength / _snapshot->unit_size();
|
||||
|
||||
for (uint64_t i = 0;
|
||||
!boost::this_thread::interruption_requested() &&
|
||||
i < sample_count;
|
||||
i += chunk_sample_count)
|
||||
{
|
||||
//lock_guard<mutex> decode_lock(_global_decode_mutex);
|
||||
|
||||
const uint64_t chunk_end = min(
|
||||
i + chunk_sample_count, sample_count);
|
||||
_snapshot->get_samples(chunk, i, chunk_end);
|
||||
|
||||
if (srd_session_send(session, i, i + sample_count, chunk,
|
||||
(chunk_end - i) * unit_size) != SRD_OK) {
|
||||
_error_message = tr("Decoder reported an error");
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
lock_guard<mutex> lock(_output_mutex);
|
||||
_samples_decoded = chunk_end;
|
||||
}
|
||||
|
||||
if (i % DecodeNotifyPeriod == 0)
|
||||
new_decode_data();
|
||||
|
||||
}
|
||||
_options_changed = false;
|
||||
decode_done();
|
||||
//new_decode_data();
|
||||
}
|
||||
|
||||
void DecoderStack::decode_proc()
|
||||
{
|
||||
lock_guard<mutex> decode_lock(_global_decode_mutex);
|
||||
|
||||
optional<uint64_t> sample_count;
|
||||
srd_session *session;
|
||||
srd_decoder_inst *prev_di = NULL;
|
||||
|
||||
assert(_snapshot);
|
||||
|
||||
// Create the session
|
||||
srd_session_new(&session);
|
||||
assert(session);
|
||||
|
||||
_decode_state = Running;
|
||||
|
||||
// Create the decoders
|
||||
const unsigned int unit_size = _snapshot->unit_size();
|
||||
|
||||
BOOST_FOREACH(const shared_ptr<decode::Decoder> &dec, _stack)
|
||||
{
|
||||
srd_decoder_inst *const di = dec->create_decoder_inst(session, unit_size);
|
||||
|
||||
if (!di)
|
||||
{
|
||||
_error_message = tr("Failed to create decoder instance");
|
||||
srd_session_destroy(session);
|
||||
return;
|
||||
}
|
||||
|
||||
if (prev_di)
|
||||
srd_inst_stack (session, prev_di, di);
|
||||
|
||||
prev_di = di;
|
||||
}
|
||||
|
||||
// Get the intial sample count
|
||||
{
|
||||
unique_lock<mutex> input_lock(_input_mutex);
|
||||
sample_count = _sample_count = _snapshot->get_sample_count();
|
||||
}
|
||||
|
||||
// Start the session
|
||||
srd_session_metadata_set(session, SRD_CONF_SAMPLERATE,
|
||||
g_variant_new_uint64((uint64_t)_samplerate));
|
||||
|
||||
srd_pd_output_callback_add(session, SRD_OUTPUT_ANN,
|
||||
DecoderStack::annotation_callback, this);
|
||||
|
||||
srd_session_start(session);
|
||||
|
||||
// do {
|
||||
// decode_data(*sample_count, unit_size, session);
|
||||
// } while(_error_message.isEmpty() && (sample_count = wait_for_data()));
|
||||
decode_data(*sample_count, unit_size, session);
|
||||
|
||||
// Destroy the session
|
||||
srd_session_destroy(session);
|
||||
|
||||
_decode_state = Stopped;
|
||||
}
|
||||
|
||||
void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
|
||||
{
|
||||
assert(pdata);
|
||||
assert(decoder);
|
||||
|
||||
DecoderStack *const d = (DecoderStack*)decoder;
|
||||
assert(d);
|
||||
|
||||
lock_guard<mutex> lock(d->_output_mutex);
|
||||
|
||||
const Annotation a(pdata);
|
||||
|
||||
// Find the row
|
||||
assert(pdata->pdo);
|
||||
assert(pdata->pdo->di);
|
||||
const srd_decoder *const decc = pdata->pdo->di->decoder;
|
||||
assert(decc);
|
||||
|
||||
map<const Row, decode::RowData>::iterator row_iter = d->_rows.end();
|
||||
|
||||
// Try looking up the sub-row of this class
|
||||
const map<pair<const srd_decoder*, int>, Row>::const_iterator r =
|
||||
d->_class_rows.find(make_pair(decc, a.format()));
|
||||
if (r != d->_class_rows.end())
|
||||
row_iter = d->_rows.find((*r).second);
|
||||
else
|
||||
{
|
||||
// Failing that, use the decoder as a key
|
||||
row_iter = d->_rows.find(Row(decc));
|
||||
}
|
||||
|
||||
assert(row_iter != d->_rows.end());
|
||||
if (row_iter == d->_rows.end()) {
|
||||
qDebug() << "Unexpected annotation: decoder = " << decc <<
|
||||
", format = " << a.format();
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the annotation
|
||||
(*row_iter).second.push_annotation(a);
|
||||
}
|
||||
|
||||
void DecoderStack::on_new_frame()
|
||||
{
|
||||
//begin_decode();
|
||||
}
|
||||
|
||||
void DecoderStack::on_data_received()
|
||||
{
|
||||
// {
|
||||
// unique_lock<mutex> lock(_input_mutex);
|
||||
// if (_snapshot)
|
||||
// _sample_count = _snapshot->get_sample_count();
|
||||
// }
|
||||
// _input_cond.notify_one();
|
||||
}
|
||||
|
||||
void DecoderStack::on_frame_ended()
|
||||
{
|
||||
// {
|
||||
// unique_lock<mutex> lock(_input_mutex);
|
||||
// if (_snapshot)
|
||||
// _frame_complete = true;
|
||||
// }
|
||||
// _input_cond.notify_one();
|
||||
_options_changed = true;
|
||||
begin_decode();
|
||||
}
|
||||
|
||||
int DecoderStack::cur_rows_size()
|
||||
{
|
||||
int rows_size = 0;
|
||||
for (map<const Row, RowData>::const_iterator i = _rows.begin();
|
||||
i != _rows.end(); i++)
|
||||
if ((*i).second.get_max_sample() != 0)
|
||||
rows_size++;
|
||||
|
||||
if (rows_size == 0)
|
||||
return 1;
|
||||
else
|
||||
return rows_size;
|
||||
}
|
||||
|
||||
void DecoderStack::options_changed(bool changed)
|
||||
{
|
||||
_options_changed = changed;
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace pv
|
185
DSLogic-gui/pv/data/decoderstack.h
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DECODERSTACK_H
|
||||
#define DSLOGIC_PV_DATA_DECODERSTACK_H
|
||||
|
||||
#include "signaldata.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include <pv/data/decode/row.h>
|
||||
#include <pv/data/decode/rowdata.h>
|
||||
|
||||
struct srd_decoder;
|
||||
struct srd_decoder_annotation_row;
|
||||
struct srd_channel;
|
||||
struct srd_proto_data;
|
||||
struct srd_session;
|
||||
|
||||
namespace DecoderStackTest {
|
||||
class TwoDecoderStack;
|
||||
}
|
||||
|
||||
namespace pv {
|
||||
|
||||
class SigSession;
|
||||
|
||||
namespace view {
|
||||
class LogicSignal;
|
||||
}
|
||||
|
||||
namespace data {
|
||||
|
||||
class LogicSnapshot;
|
||||
|
||||
namespace decode {
|
||||
class Annotation;
|
||||
class Decoder;
|
||||
}
|
||||
|
||||
class Logic;
|
||||
|
||||
class DecoderStack : public QObject, public SignalData
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
static const double DecodeMargin;
|
||||
static const double DecodeThreshold;
|
||||
static const int64_t DecodeChunkLength;
|
||||
static const unsigned int DecodeNotifyPeriod;
|
||||
|
||||
public:
|
||||
enum decode_state {
|
||||
Stopped,
|
||||
Running
|
||||
};
|
||||
|
||||
public:
|
||||
DecoderStack(pv::SigSession &_session,
|
||||
const srd_decoder *const decoder);
|
||||
|
||||
virtual ~DecoderStack();
|
||||
|
||||
const std::list< boost::shared_ptr<decode::Decoder> >& stack() const;
|
||||
void push(boost::shared_ptr<decode::Decoder> decoder);
|
||||
void remove(int index);
|
||||
|
||||
int64_t samples_decoded() const;
|
||||
|
||||
std::vector< std::pair<decode::Row, bool> > get_visible_rows() const;
|
||||
|
||||
/**
|
||||
* Extracts sorted annotations between two period into a vector.
|
||||
*/
|
||||
void get_annotation_subset(
|
||||
std::vector<pv::data::decode::Annotation> &dest,
|
||||
const decode::Row &row, uint64_t start_sample,
|
||||
uint64_t end_sample) const;
|
||||
|
||||
uint64_t get_max_annotation(const decode::Row &row);
|
||||
|
||||
bool has_annotations(const decode::Row &row) const;
|
||||
|
||||
QString error_message();
|
||||
|
||||
void clear();
|
||||
|
||||
uint64_t get_max_sample_count() const;
|
||||
|
||||
void begin_decode();
|
||||
|
||||
void stop_decode();
|
||||
|
||||
int cur_rows_size();
|
||||
|
||||
void options_changed(bool changed);
|
||||
|
||||
private:
|
||||
boost::optional<uint64_t> wait_for_data() const;
|
||||
|
||||
void decode_data(const uint64_t sample_count,
|
||||
const unsigned int unit_size, srd_session *const session);
|
||||
|
||||
void decode_proc();
|
||||
|
||||
static void annotation_callback(srd_proto_data *pdata,
|
||||
void *decoder);
|
||||
|
||||
private slots:
|
||||
void on_new_frame();
|
||||
|
||||
void on_data_received();
|
||||
|
||||
void on_frame_ended();
|
||||
|
||||
signals:
|
||||
void new_decode_data();
|
||||
void decode_done();
|
||||
|
||||
private:
|
||||
pv::SigSession &_session;
|
||||
|
||||
/**
|
||||
* This mutex prevents more than one decode operation occuring
|
||||
* concurrently.
|
||||
* @todo A proper solution should be implemented to allow multiple
|
||||
* decode operations.
|
||||
*/
|
||||
static boost::mutex _global_decode_mutex;
|
||||
|
||||
std::list< boost::shared_ptr<decode::Decoder> > _stack;
|
||||
|
||||
boost::shared_ptr<pv::data::LogicSnapshot> _snapshot;
|
||||
|
||||
mutable boost::mutex _input_mutex;
|
||||
mutable boost::condition_variable _input_cond;
|
||||
uint64_t _sample_count;
|
||||
bool _frame_complete;
|
||||
|
||||
mutable boost::mutex _output_mutex;
|
||||
int64_t _samples_decoded;
|
||||
|
||||
std::map<const decode::Row, decode::RowData> _rows;
|
||||
|
||||
std::map<std::pair<const srd_decoder*, int>, decode::Row> _class_rows;
|
||||
|
||||
QString _error_message;
|
||||
|
||||
std::auto_ptr<boost::thread> _decode_thread;
|
||||
decode_state _decode_state;
|
||||
|
||||
bool _options_changed;
|
||||
|
||||
friend class DecoderStackTest::TwoDecoderStack;
|
||||
};
|
||||
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
||||
#endif // DSLOGIC_PV_DATA_DECODERSTACK_H
|
@ -29,8 +29,8 @@ using namespace std;
|
||||
namespace pv {
|
||||
namespace data {
|
||||
|
||||
Dso::Dso(unsigned int num_probes, uint64_t samplerate) :
|
||||
SignalData(num_probes, samplerate)
|
||||
Dso::Dso(int num_probes) :
|
||||
SignalData(num_probes)
|
||||
{
|
||||
}
|
||||
|
||||
@ -44,5 +44,10 @@ deque< boost::shared_ptr<DsoSnapshot> >& Dso::get_snapshots()
|
||||
return _snapshots;
|
||||
}
|
||||
|
||||
void Dso::clear()
|
||||
{
|
||||
_snapshots.clear();
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
@ -36,7 +36,7 @@ class DsoSnapshot;
|
||||
class Dso : public SignalData
|
||||
{
|
||||
public:
|
||||
Dso(unsigned int num_probes, uint64_t samplerate);
|
||||
Dso(int num_probes);
|
||||
|
||||
void push_snapshot(
|
||||
boost::shared_ptr<DsoSnapshot> &snapshot);
|
||||
@ -44,6 +44,8 @@ public:
|
||||
std::deque< boost::shared_ptr<DsoSnapshot> >&
|
||||
get_snapshots();
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::deque< boost::shared_ptr<DsoSnapshot> > _snapshots;
|
||||
};
|
||||
|
@ -73,6 +73,8 @@ void DsoSnapshot::append_payload(const sr_datafeed_dso &dso)
|
||||
const uint8_t *DsoSnapshot::get_samples(
|
||||
int64_t start_sample, int64_t end_sample, uint16_t index) const
|
||||
{
|
||||
(void)end_sample;
|
||||
|
||||
assert(start_sample >= 0);
|
||||
assert(start_sample < (int64_t)get_sample_count());
|
||||
assert(end_sample >= 0);
|
||||
|
@ -30,8 +30,8 @@ using namespace std;
|
||||
namespace pv {
|
||||
namespace data {
|
||||
|
||||
Group::Group(unsigned int num_probes, uint64_t samplerate) :
|
||||
SignalData(num_probes, samplerate)
|
||||
Group::Group() :
|
||||
SignalData()
|
||||
{
|
||||
}
|
||||
|
||||
@ -45,5 +45,10 @@ deque< boost::shared_ptr<GroupSnapshot> >& Group::get_snapshots()
|
||||
return _snapshots;
|
||||
}
|
||||
|
||||
void Group::clear()
|
||||
{
|
||||
_snapshots.clear();
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
@ -37,7 +37,7 @@ class GroupSnapshot;
|
||||
class Group : public SignalData
|
||||
{
|
||||
public:
|
||||
Group(unsigned int num_probes, uint64_t samplerate);
|
||||
Group();
|
||||
|
||||
void push_snapshot(
|
||||
boost::shared_ptr<GroupSnapshot> &snapshot);
|
||||
@ -45,6 +45,8 @@ public:
|
||||
std::deque< boost::shared_ptr<GroupSnapshot> >&
|
||||
get_snapshots();
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::deque< boost::shared_ptr<GroupSnapshot> > _snapshots;
|
||||
};
|
||||
|
@ -59,7 +59,7 @@ GroupSnapshot::GroupSnapshot(const boost::shared_ptr<LogicSnapshot> &_logic_snap
|
||||
memset(_envelope_levels, 0, sizeof(_envelope_levels));
|
||||
_data = _logic_snapshot->get_data();
|
||||
_sample_count = _logic_snapshot->get_sample_count();
|
||||
_unit_size = _logic_snapshot->get_unit_size();
|
||||
_unit_size = _logic_snapshot->unit_size();
|
||||
_index_list = index_list;
|
||||
append_payload();
|
||||
}
|
||||
|
@ -30,10 +30,9 @@ using namespace std;
|
||||
namespace pv {
|
||||
namespace data {
|
||||
|
||||
Logic::Logic(unsigned int num_probes, uint64_t samplerate) :
|
||||
SignalData(num_probes, samplerate)
|
||||
Logic::Logic(int num_probes) :
|
||||
SignalData(num_probes)
|
||||
{
|
||||
assert(_num_probes > 0);
|
||||
}
|
||||
|
||||
void Logic::push_snapshot(
|
||||
@ -47,5 +46,10 @@ deque< boost::shared_ptr<LogicSnapshot> >& Logic::get_snapshots()
|
||||
return _snapshots;
|
||||
}
|
||||
|
||||
void Logic::clear()
|
||||
{
|
||||
_snapshots.clear();
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
@ -37,7 +37,9 @@ class LogicSnapshot;
|
||||
class Logic : public SignalData
|
||||
{
|
||||
public:
|
||||
Logic(unsigned int num_probes, uint64_t samplerate);
|
||||
Logic(int num_probes);
|
||||
|
||||
int get_num_probes() const;
|
||||
|
||||
void push_snapshot(
|
||||
boost::shared_ptr<LogicSnapshot> &snapshot);
|
||||
@ -45,6 +47,8 @@ public:
|
||||
std::deque< boost::shared_ptr<LogicSnapshot> >&
|
||||
get_snapshots();
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::deque< boost::shared_ptr<LogicSnapshot> > _snapshots;
|
||||
};
|
||||
|
@ -74,6 +74,22 @@ void LogicSnapshot::append_payload(
|
||||
append_payload_to_mipmap();
|
||||
}
|
||||
|
||||
void LogicSnapshot::get_samples(uint8_t *const data,
|
||||
int64_t start_sample, int64_t end_sample) const
|
||||
{
|
||||
assert(data);
|
||||
assert(start_sample >= 0);
|
||||
assert(start_sample <= (int64_t)_sample_count);
|
||||
assert(end_sample >= 0);
|
||||
assert(end_sample <= (int64_t)_sample_count);
|
||||
assert(start_sample <= end_sample);
|
||||
|
||||
//lock_guard<recursive_mutex> lock(_mutex);
|
||||
|
||||
const size_t size = (end_sample - start_sample) * _unit_size;
|
||||
memcpy(data, (const uint8_t*)_data + start_sample * _unit_size, size);
|
||||
}
|
||||
|
||||
void LogicSnapshot::reallocate_mipmap_level(MipMapLevel &m)
|
||||
{
|
||||
const uint64_t new_data_length = ((m.length + MipMapDataUnit - 1) /
|
||||
@ -170,14 +186,6 @@ void LogicSnapshot::append_payload_to_mipmap()
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t LogicSnapshot::get_sample(uint64_t index) const
|
||||
{
|
||||
assert(_data);
|
||||
assert(index < _sample_count);
|
||||
|
||||
return *(uint64_t*)((uint8_t*)_data + index * _unit_size);
|
||||
}
|
||||
|
||||
void LogicSnapshot::get_subsampled_edges(
|
||||
std::vector<EdgePair> &edges,
|
||||
uint64_t start, uint64_t end,
|
||||
@ -194,6 +202,9 @@ void LogicSnapshot::get_subsampled_edges(
|
||||
assert(sig_index >= 0);
|
||||
assert(sig_index < 64);
|
||||
|
||||
if (!_data)
|
||||
return;
|
||||
|
||||
boost::lock_guard<boost::recursive_mutex> lock(_mutex);
|
||||
|
||||
const uint64_t block_length = (uint64_t)max(min_length, 1.0f);
|
||||
|
@ -67,7 +67,8 @@ public:
|
||||
|
||||
void append_payload(const sr_datafeed_logic &logic);
|
||||
|
||||
uint64_t get_sample(uint64_t index) const;
|
||||
void get_samples(uint8_t *const data,
|
||||
int64_t start_sample, int64_t end_sample) const;
|
||||
|
||||
private:
|
||||
void reallocate_mipmap_level(MipMapLevel &m);
|
||||
|
@ -20,33 +20,48 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "signaldata.h"
|
||||
|
||||
namespace pv {
|
||||
namespace data {
|
||||
|
||||
SignalData::SignalData(unsigned int num_probes, double samplerate) :
|
||||
_num_probes(num_probes),
|
||||
_samplerate(samplerate),
|
||||
_start_time(0)
|
||||
SignalData::SignalData(int num_probes) :
|
||||
_samplerate(0),
|
||||
_start_time(0),
|
||||
_num_probes(num_probes)
|
||||
{
|
||||
assert(num_probes >= 0);
|
||||
}
|
||||
|
||||
int SignalData::get_num_probes() const
|
||||
{
|
||||
return _num_probes;
|
||||
}
|
||||
|
||||
double SignalData::get_samplerate() const
|
||||
double SignalData::samplerate() const
|
||||
{
|
||||
return _samplerate;
|
||||
}
|
||||
|
||||
void SignalData::set_samplerate(double samplerate)
|
||||
{
|
||||
assert(samplerate > 0);
|
||||
_samplerate = samplerate;
|
||||
clear();
|
||||
}
|
||||
|
||||
double SignalData::get_start_time() const
|
||||
{
|
||||
return _start_time;
|
||||
}
|
||||
|
||||
int SignalData::get_num_probes() const
|
||||
{
|
||||
return _num_probes;
|
||||
}
|
||||
|
||||
void SignalData::set_num_probes(int num)
|
||||
{
|
||||
assert(num >= 0);
|
||||
_num_probes = num;
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace pv
|
||||
|
@ -32,17 +32,24 @@ namespace data {
|
||||
class SignalData
|
||||
{
|
||||
public:
|
||||
SignalData(unsigned int num_probes, double samplerate);
|
||||
SignalData(int num_probes = 1);
|
||||
|
||||
public:
|
||||
double get_samplerate() const;
|
||||
double samplerate() const;
|
||||
void set_samplerate(double samplerate);
|
||||
|
||||
virtual void clear() = 0;
|
||||
|
||||
double get_start_time() const;
|
||||
|
||||
int get_num_probes() const;
|
||||
|
||||
void set_num_probes(int num);
|
||||
|
||||
protected:
|
||||
const unsigned int _num_probes;
|
||||
const double _samplerate;
|
||||
const double _start_time;
|
||||
double _samplerate;
|
||||
double _start_time;
|
||||
int _num_probes;
|
||||
};
|
||||
|
||||
} // namespace data
|
||||
|
@ -54,6 +54,7 @@ Snapshot::~Snapshot()
|
||||
|
||||
int Snapshot::init(uint64_t _total_sample_len)
|
||||
{
|
||||
boost::lock_guard<boost::recursive_mutex> lock(_mutex);
|
||||
_data = malloc(_total_sample_len * _unit_size +
|
||||
sizeof(uint64_t));
|
||||
|
||||
@ -83,7 +84,7 @@ void* Snapshot::get_data() const
|
||||
return _data;
|
||||
}
|
||||
|
||||
int Snapshot::get_unit_size() const
|
||||
int Snapshot::unit_size() const
|
||||
{
|
||||
boost::lock_guard<boost::recursive_mutex> lock(_mutex);
|
||||
return _unit_size;
|
||||
@ -95,6 +96,16 @@ unsigned int Snapshot::get_channel_num() const
|
||||
return _channel_num;
|
||||
}
|
||||
|
||||
uint64_t Snapshot::get_sample(uint64_t index) const
|
||||
{
|
||||
boost::lock_guard<boost::recursive_mutex> lock(_mutex);
|
||||
|
||||
assert(_data);
|
||||
assert(index < _sample_count);
|
||||
|
||||
return *(uint64_t*)((uint8_t*)_data + index * _unit_size);
|
||||
}
|
||||
|
||||
void Snapshot::append_data(void *data, uint64_t samples)
|
||||
{
|
||||
// boost::lock_guard<boost::recursive_mutex> lock(_mutex);
|
||||
|
@ -44,12 +44,14 @@ public:
|
||||
|
||||
void * get_data() const;
|
||||
|
||||
int get_unit_size() const;
|
||||
int unit_size() const;
|
||||
|
||||
bool buf_null() const;
|
||||
|
||||
unsigned int get_channel_num() const;
|
||||
|
||||
uint64_t get_sample(uint64_t index) const;
|
||||
|
||||
protected:
|
||||
void append_data(void *data, uint64_t samples);
|
||||
|
||||
|
105
DSLogic-gui/pv/device/device.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 <sstream>
|
||||
|
||||
#include <libsigrok4DSLogic/libsigrok.h>
|
||||
|
||||
#include "device.h"
|
||||
|
||||
using std::ostringstream;
|
||||
using std::string;
|
||||
|
||||
namespace pv {
|
||||
namespace device {
|
||||
|
||||
Device::Device(sr_dev_inst *sdi) :
|
||||
_sdi(sdi)
|
||||
{
|
||||
assert(_sdi);
|
||||
}
|
||||
|
||||
sr_dev_inst* Device::dev_inst() const
|
||||
{
|
||||
return _sdi;
|
||||
}
|
||||
|
||||
void Device::use(SigSession *owner) throw(QString)
|
||||
{
|
||||
DevInst::use(owner);
|
||||
|
||||
sr_session_new();
|
||||
|
||||
assert(_sdi);
|
||||
sr_dev_open(_sdi);
|
||||
if (sr_session_dev_add(_sdi) != SR_OK)
|
||||
throw QString(tr("Failed to use device."));
|
||||
}
|
||||
|
||||
void Device::release()
|
||||
{
|
||||
if (_owner) {
|
||||
DevInst::release();
|
||||
sr_session_destroy();
|
||||
}
|
||||
|
||||
sr_dev_close(_sdi);
|
||||
}
|
||||
|
||||
std::string Device::format_device_title() const
|
||||
{
|
||||
ostringstream s;
|
||||
|
||||
assert(_sdi);
|
||||
|
||||
if (_sdi->vendor && _sdi->vendor[0]) {
|
||||
s << _sdi->vendor;
|
||||
if ((_sdi->model && _sdi->model[0]) ||
|
||||
(_sdi->version && _sdi->version[0]))
|
||||
s << ' ';
|
||||
}
|
||||
|
||||
if (_sdi->model && _sdi->model[0]) {
|
||||
s << _sdi->model;
|
||||
if (_sdi->version && _sdi->version[0])
|
||||
s << ' ';
|
||||
}
|
||||
|
||||
if (_sdi->version && _sdi->version[0])
|
||||
s << _sdi->version;
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
bool Device::is_trigger_enabled() const
|
||||
{
|
||||
assert(_sdi);
|
||||
for (const GSList *l = _sdi->channels; l; l = l->next) {
|
||||
const sr_channel *const p = (const sr_channel *)l->data;
|
||||
assert(p);
|
||||
if (p->trigger && p->trigger[0] != '\0')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // device
|
||||
} // pv
|
52
DSLogic-gui/pv/device/device.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DEVICE_DEVICE_H
|
||||
#define DSLOGIC_PV_DEVICE_DEVICE_H
|
||||
|
||||
#include "devinst.h"
|
||||
|
||||
namespace pv {
|
||||
namespace device {
|
||||
|
||||
class Device : public DevInst
|
||||
{
|
||||
public:
|
||||
Device(sr_dev_inst *dev_inst);
|
||||
|
||||
sr_dev_inst* dev_inst() const;
|
||||
|
||||
void use(SigSession *owner) throw(QString);
|
||||
|
||||
void release();
|
||||
|
||||
std::string format_device_title() const;
|
||||
|
||||
bool is_trigger_enabled() const;
|
||||
|
||||
private:
|
||||
sr_dev_inst *const _sdi;
|
||||
};
|
||||
|
||||
} // device
|
||||
} // pv
|
||||
|
||||
#endif // DSLOGIC_PV_DEVICE_DEVICE_H
|
203
DSLogic-gui/pv/device/devinst.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 <cassert>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <libsigrok4DSLogic/libsigrok.h>
|
||||
|
||||
#include "devinst.h"
|
||||
|
||||
#include <pv/sigsession.h>
|
||||
|
||||
namespace pv {
|
||||
namespace device {
|
||||
|
||||
DevInst::DevInst() :
|
||||
_owner(NULL)
|
||||
{
|
||||
_id = malloc(1);
|
||||
}
|
||||
|
||||
DevInst::~DevInst()
|
||||
{
|
||||
assert(_id);
|
||||
free(_id);
|
||||
}
|
||||
|
||||
void* DevInst::get_id() const
|
||||
{
|
||||
assert(_id);
|
||||
|
||||
return _id;
|
||||
}
|
||||
|
||||
void DevInst::use(SigSession *owner) throw(QString)
|
||||
{
|
||||
assert(owner);
|
||||
assert(!_owner);
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
void DevInst::release()
|
||||
{
|
||||
if (_owner) {
|
||||
_owner->release_device(this);
|
||||
_owner = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SigSession* DevInst::owner() const
|
||||
{
|
||||
return _owner;
|
||||
}
|
||||
|
||||
GVariant* DevInst::get_config(const sr_channel *ch, const sr_channel_group *group, int key)
|
||||
{
|
||||
GVariant *data = NULL;
|
||||
assert(_owner);
|
||||
sr_dev_inst *const sdi = dev_inst();
|
||||
assert(sdi);
|
||||
if (sr_config_get(sdi->driver, sdi, ch, group, key, &data) != SR_OK)
|
||||
return NULL;
|
||||
return data;
|
||||
}
|
||||
|
||||
bool DevInst::set_config(const sr_channel *ch, const sr_channel_group *group, int key, GVariant *data)
|
||||
{
|
||||
assert(_owner);
|
||||
sr_dev_inst *const sdi = dev_inst();
|
||||
assert(sdi);
|
||||
if(sr_config_set(sdi, ch, group, key, data) == SR_OK) {
|
||||
config_changed();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
GVariant* DevInst::list_config(const sr_channel_group *group, int key)
|
||||
{
|
||||
GVariant *data = NULL;
|
||||
assert(_owner);
|
||||
sr_dev_inst *const sdi = dev_inst();
|
||||
assert(sdi);
|
||||
if (sr_config_list(sdi->driver, sdi, group, key, &data) != SR_OK)
|
||||
return NULL;
|
||||
return data;
|
||||
}
|
||||
|
||||
void DevInst::enable_probe(const sr_channel *probe, bool enable)
|
||||
{
|
||||
assert(_owner);
|
||||
sr_dev_inst *const sdi = dev_inst();
|
||||
assert(sdi);
|
||||
for (const GSList *p = sdi->channels; p; p = p->next)
|
||||
if (probe == p->data) {
|
||||
const_cast<sr_channel*>(probe)->enabled = enable;
|
||||
config_changed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Probe was not found in the device
|
||||
assert(0);
|
||||
}
|
||||
|
||||
uint64_t DevInst::get_sample_limit()
|
||||
{
|
||||
uint64_t sample_limit;
|
||||
GVariant* gvar = get_config(NULL, NULL, SR_CONF_LIMIT_SAMPLES);
|
||||
if (gvar != NULL) {
|
||||
sample_limit = g_variant_get_uint64(gvar);
|
||||
g_variant_unref(gvar);
|
||||
} else {
|
||||
sample_limit = 0U;
|
||||
}
|
||||
return sample_limit;
|
||||
}
|
||||
|
||||
uint64_t DevInst::get_sample_rate()
|
||||
{
|
||||
uint64_t sample_rate;
|
||||
GVariant* gvar = get_config(NULL, NULL, SR_CONF_SAMPLERATE);
|
||||
if (gvar != NULL) {
|
||||
sample_rate = g_variant_get_uint64(gvar);
|
||||
g_variant_unref(gvar);
|
||||
} else {
|
||||
sample_rate = 0U;
|
||||
}
|
||||
return sample_rate;
|
||||
}
|
||||
|
||||
uint64_t DevInst::get_time_base()
|
||||
{
|
||||
uint64_t time_base;
|
||||
GVariant* gvar = get_config(NULL, NULL, SR_CONF_TIMEBASE);
|
||||
if (gvar != NULL) {
|
||||
time_base = g_variant_get_uint64(gvar);
|
||||
g_variant_unref(gvar);
|
||||
} else {
|
||||
time_base = 0U;
|
||||
}
|
||||
return time_base;
|
||||
}
|
||||
|
||||
|
||||
double DevInst::get_sample_time()
|
||||
{
|
||||
uint64_t sample_rate = get_sample_rate();
|
||||
uint64_t sample_limit = get_sample_limit();
|
||||
double sample_time;
|
||||
|
||||
if (sample_rate == 0)
|
||||
sample_time = 0;
|
||||
else
|
||||
sample_time = sample_limit * 1.0f / sample_rate;
|
||||
|
||||
return sample_time;
|
||||
}
|
||||
|
||||
GSList* DevInst::get_dev_mode_list()
|
||||
{
|
||||
assert(_owner);
|
||||
sr_dev_inst *const sdi = dev_inst();
|
||||
assert(sdi);
|
||||
return sr_dev_mode_list(sdi->driver);
|
||||
}
|
||||
|
||||
bool DevInst::is_trigger_enabled() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void DevInst::start()
|
||||
{
|
||||
if (sr_session_start() != SR_OK)
|
||||
throw tr("Failed to start session.");
|
||||
}
|
||||
|
||||
void DevInst::run()
|
||||
{
|
||||
sr_session_run();
|
||||
}
|
||||
|
||||
} // device
|
||||
} // pv
|
132
DSLogic-gui/pv/device/devinst.h
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DEVICE_DEVINST_H
|
||||
#define DSLOGIC_PV_DEVICE_DEVINST_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct sr_dev_inst;
|
||||
struct sr_channel;
|
||||
struct sr_channel_group;
|
||||
|
||||
namespace pv {
|
||||
|
||||
class SigSession;
|
||||
|
||||
namespace device {
|
||||
|
||||
class DevInst : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
DevInst();
|
||||
~DevInst();
|
||||
|
||||
public:
|
||||
virtual sr_dev_inst* dev_inst() const = 0;
|
||||
|
||||
virtual void use(SigSession *owner) throw(QString);
|
||||
|
||||
virtual void release();
|
||||
|
||||
SigSession* owner() const;
|
||||
|
||||
virtual std::string format_device_title() const = 0;
|
||||
|
||||
GVariant* get_config(const sr_channel *ch, const sr_channel_group *group, int key);
|
||||
|
||||
bool set_config(const sr_channel *ch, const sr_channel_group *group, int key, GVariant *data);
|
||||
|
||||
GVariant* list_config(const sr_channel_group *group, int key);
|
||||
|
||||
void enable_probe(const sr_channel *probe, bool enable = true);
|
||||
|
||||
/**
|
||||
* @brief Gets the sample limit from the driver.
|
||||
*
|
||||
* @return The returned sample limit from the driver, or 0 if the
|
||||
* sample limit could not be read.
|
||||
*/
|
||||
uint64_t get_sample_limit();
|
||||
|
||||
/**
|
||||
* @brief Gets the sample rate from the driver.
|
||||
*
|
||||
* @return The returned sample rate from the driver, or 0 if the
|
||||
* sample rate could not be read.
|
||||
*/
|
||||
uint64_t get_sample_rate();
|
||||
|
||||
/**
|
||||
* @brief Gets the sample time from the driver.
|
||||
*
|
||||
* @return The returned sample time from the driver, or 0 if the
|
||||
* sample time could not be read.
|
||||
*/
|
||||
double get_sample_time();
|
||||
|
||||
/**
|
||||
* @brief Gets the time base from the driver.
|
||||
*
|
||||
* @return The returned time base from the driver, or 0 if the
|
||||
* time base could not be read.
|
||||
*/
|
||||
uint64_t get_time_base();
|
||||
|
||||
/**
|
||||
* @brief Gets the device mode list from the driver.
|
||||
*
|
||||
* @return The returned device mode list from the driver, or NULL if the
|
||||
* mode list could not be read.
|
||||
*/
|
||||
GSList* get_dev_mode_list();
|
||||
|
||||
virtual bool is_trigger_enabled() const;
|
||||
|
||||
public:
|
||||
virtual void start();
|
||||
|
||||
virtual void run();
|
||||
|
||||
virtual void* get_id() const;
|
||||
|
||||
signals:
|
||||
void config_changed();
|
||||
|
||||
protected:
|
||||
SigSession *_owner;
|
||||
void *_id;
|
||||
};
|
||||
|
||||
} // device
|
||||
} // pv
|
||||
|
||||
#endif // DSLOGIC_PV_DEVICE_DEVINST_H
|
67
DSLogic-gui/pv/device/file.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 "file.h"
|
||||
#include "inputfile.h"
|
||||
#include "sessionfile.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <libsigrok4DSLogic/libsigrok.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace pv {
|
||||
namespace device {
|
||||
|
||||
File::File(const std::string path) :
|
||||
_path(path)
|
||||
{
|
||||
}
|
||||
|
||||
std::string File::format_device_title() const
|
||||
{
|
||||
return boost::filesystem::path(_path).filename().string();
|
||||
}
|
||||
|
||||
File* File::create(const string &name)
|
||||
{
|
||||
if (sr_session_load(name.c_str()) == SR_OK) {
|
||||
GSList *devlist = NULL;
|
||||
sr_session_dev_list(&devlist);
|
||||
sr_session_destroy();
|
||||
|
||||
if (devlist) {
|
||||
sr_dev_inst *const sdi = (sr_dev_inst*)devlist->data;
|
||||
g_slist_free(devlist);
|
||||
if (sdi) {
|
||||
sr_dev_close(sdi);
|
||||
sr_dev_clear(sdi->driver);
|
||||
return new SessionFile(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new InputFile(name);
|
||||
}
|
||||
|
||||
} // device
|
||||
} // pv
|
50
DSLogic-gui/pv/device/file.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DEVICE_FILE_H
|
||||
#define DSLOGIC_PV_DEVICE_FILE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "devinst.h"
|
||||
|
||||
namespace pv {
|
||||
namespace device {
|
||||
|
||||
class File : public DevInst
|
||||
{
|
||||
protected:
|
||||
File(const std::string path);
|
||||
|
||||
public:
|
||||
static File* create(const std::string &name);
|
||||
|
||||
public:
|
||||
std::string format_device_title() const;
|
||||
|
||||
protected:
|
||||
const std::string _path;
|
||||
};
|
||||
|
||||
} // device
|
||||
} // pv
|
||||
|
||||
#endif // DSLOGIC_PV_DEVICE_FILE_H
|
144
DSLogic-gui/pv/device/inputfile.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 <cassert>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "inputfile.h"
|
||||
|
||||
#include <libsigrok4DSLogic/libsigrok.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace pv {
|
||||
namespace device {
|
||||
|
||||
InputFile::InputFile(const std::string &path) :
|
||||
File(path),
|
||||
_input(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
sr_dev_inst* InputFile::dev_inst() const
|
||||
{
|
||||
assert(_input);
|
||||
return _input->sdi;
|
||||
}
|
||||
|
||||
void InputFile::use(SigSession *owner) throw(QString)
|
||||
{
|
||||
assert(!_input);
|
||||
|
||||
_input = load_input_file_format(_path, NULL);
|
||||
File::use(owner);
|
||||
|
||||
sr_session_new();
|
||||
|
||||
if (sr_session_dev_add(_input->sdi) != SR_OK)
|
||||
throw tr("Failed to add session device.");
|
||||
}
|
||||
|
||||
void InputFile::release()
|
||||
{
|
||||
if (!_owner)
|
||||
return;
|
||||
|
||||
assert(_input);
|
||||
File::release();
|
||||
sr_dev_close(_input->sdi);
|
||||
sr_session_destroy();
|
||||
_input = NULL;
|
||||
}
|
||||
|
||||
sr_input_format* InputFile::determine_input_file_format(
|
||||
const string &filename)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* If there are no input formats, return NULL right away. */
|
||||
sr_input_format *const *const inputs = sr_input_list();
|
||||
if (!inputs) {
|
||||
g_critical("No supported input formats available.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Otherwise, try to find an input module that can handle this file. */
|
||||
for (i = 0; inputs[i]; i++) {
|
||||
if (inputs[i]->format_match(filename.c_str()))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return NULL if no input module wanted to touch this. */
|
||||
if (!inputs[i]) {
|
||||
g_critical("Error: no matching input module found.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return inputs[i];
|
||||
}
|
||||
|
||||
sr_input* InputFile::load_input_file_format(const string &filename,
|
||||
sr_input_format *format)
|
||||
{
|
||||
struct stat st;
|
||||
sr_input *in;
|
||||
|
||||
if (!format && !(format =
|
||||
determine_input_file_format(filename.c_str()))) {
|
||||
/* The exact cause was already logged. */
|
||||
throw tr("Failed to load file");
|
||||
}
|
||||
|
||||
if (stat(filename.c_str(), &st) == -1)
|
||||
throw tr("Failed to load file");
|
||||
|
||||
/* Initialize the input module. */
|
||||
if (!(in = new sr_input)) {
|
||||
throw tr("Failed to allocate input module.");
|
||||
}
|
||||
|
||||
in->format = format;
|
||||
in->param = NULL;
|
||||
if (in->format->init &&
|
||||
in->format->init(in, filename.c_str()) != SR_OK) {
|
||||
throw tr("Failed to load file");
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
void InputFile::start()
|
||||
{
|
||||
}
|
||||
|
||||
void InputFile::run()
|
||||
{
|
||||
assert(_input);
|
||||
assert(_input->format);
|
||||
assert(_input->format->loadfile);
|
||||
_input->format->loadfile(_input, _path.c_str());
|
||||
}
|
||||
|
||||
} // device
|
||||
} // pv
|
69
DSLogic-gui/pv/device/inputfile.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DEVICE_INPUTFILE_H
|
||||
#define DSLOGIC_PV_DEVICE_INPUTFILE_H
|
||||
|
||||
#include "file.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct sr_input;
|
||||
struct sr_input_format;
|
||||
|
||||
namespace pv {
|
||||
namespace device {
|
||||
|
||||
class InputFile : public File
|
||||
{
|
||||
public:
|
||||
InputFile(const std::string &path);
|
||||
|
||||
sr_dev_inst* dev_inst() const;
|
||||
|
||||
virtual void use(SigSession *owner) throw(QString);
|
||||
|
||||
virtual void release();
|
||||
|
||||
virtual void start();
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Attempts to autodetect the format. Failing that
|
||||
* @param filename The filename of the input file.
|
||||
* @return A pointer to the 'struct sr_input_format' that should be used,
|
||||
* or NULL if no input format was selected or auto-detected.
|
||||
*/
|
||||
static sr_input_format* determine_input_file_format(
|
||||
const std::string &filename);
|
||||
|
||||
static sr_input* load_input_file_format(const std::string &filename,
|
||||
sr_input_format *format);
|
||||
private:
|
||||
sr_input *_input;
|
||||
};
|
||||
|
||||
} // device
|
||||
} // pv
|
||||
|
||||
#endif // DSLOGIC_PV_DEVICE_INPUTFILE_H
|
76
DSLogic-gui/pv/device/sessionfile.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 "sessionfile.h"
|
||||
|
||||
#include <libsigrok4DSLogic//libsigrok.h>
|
||||
|
||||
namespace pv {
|
||||
namespace device {
|
||||
|
||||
SessionFile::SessionFile(const std::string &path) :
|
||||
File(path),
|
||||
_sdi(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
sr_dev_inst* SessionFile::dev_inst() const
|
||||
{
|
||||
return _sdi;
|
||||
}
|
||||
|
||||
void SessionFile::use(SigSession *owner) throw(QString)
|
||||
{
|
||||
assert(!_sdi);
|
||||
|
||||
if (sr_session_load(_path.c_str()) != SR_OK)
|
||||
throw tr("Failed to open file.\n");
|
||||
|
||||
GSList *devlist = NULL;
|
||||
sr_session_dev_list(&devlist);
|
||||
|
||||
if (!devlist || !devlist->data) {
|
||||
if (devlist)
|
||||
g_slist_free(devlist);
|
||||
throw tr("Failed to start session.");
|
||||
}
|
||||
|
||||
_sdi = (sr_dev_inst*)devlist->data;
|
||||
g_slist_free(devlist);
|
||||
|
||||
File::use(owner);
|
||||
}
|
||||
|
||||
void SessionFile::release()
|
||||
{
|
||||
if (!_owner)
|
||||
return;
|
||||
|
||||
assert(_sdi);
|
||||
File::release();
|
||||
sr_dev_close(_sdi);
|
||||
sr_dev_clear(_sdi->driver);
|
||||
sr_session_destroy();
|
||||
_sdi = NULL;
|
||||
}
|
||||
|
||||
} // device
|
||||
} // pv
|
48
DSLogic-gui/pv/device/sessionfile.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of the DSLogic-gui project.
|
||||
* DSLogic-gui is based on PulseView.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DEVICE_SESSIONFILE_H
|
||||
#define DSLOGIC_PV_DEVICE_SESSIONFILE_H
|
||||
|
||||
#include "file.h"
|
||||
|
||||
namespace pv {
|
||||
namespace device {
|
||||
|
||||
class SessionFile : public File
|
||||
{
|
||||
public:
|
||||
SessionFile(const std::string &path);
|
||||
|
||||
sr_dev_inst* dev_inst() const;
|
||||
|
||||
virtual void use(SigSession *owner) throw(QString);
|
||||
|
||||
virtual void release();
|
||||
|
||||
private:
|
||||
sr_dev_inst *_sdi;
|
||||
};
|
||||
|
||||
} // device
|
||||
} // pv
|
||||
|
||||
#endif // DSLOGIC_PV_DEVICE_SESSIONFILE_H
|
@ -22,6 +22,8 @@
|
||||
|
||||
|
||||
#include "devicemanager.h"
|
||||
#include "device/devinst.h"
|
||||
#include "device/device.h"
|
||||
#include "sigsession.h"
|
||||
|
||||
#include <cassert>
|
||||
@ -34,9 +36,17 @@
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <libsigrok4DSLogic/libsigrok.h>
|
||||
|
||||
using namespace std;
|
||||
using boost::shared_ptr;
|
||||
using std::list;
|
||||
using std::map;
|
||||
using std::ostringstream;
|
||||
using std::runtime_error;
|
||||
using std::string;
|
||||
|
||||
char config_path[256];
|
||||
|
||||
namespace pv {
|
||||
@ -53,57 +63,47 @@ DeviceManager::~DeviceManager()
|
||||
release_devices();
|
||||
}
|
||||
|
||||
const std::list<sr_dev_inst*>& DeviceManager::devices() const
|
||||
const std::list<boost::shared_ptr<device::DevInst> > &DeviceManager::devices() const
|
||||
{
|
||||
return _devices;
|
||||
}
|
||||
|
||||
int DeviceManager::use_device(sr_dev_inst *sdi, SigSession *owner)
|
||||
void DeviceManager::add_device(boost::shared_ptr<pv::device::DevInst> device)
|
||||
{
|
||||
assert(sdi);
|
||||
assert(owner);
|
||||
assert(device);
|
||||
|
||||
if (sr_dev_open(sdi) != SR_OK)
|
||||
return SR_ERR;
|
||||
|
||||
_used_devices[sdi] = owner;
|
||||
return SR_OK;
|
||||
if (std::find(_devices.begin(), _devices.end(), device) ==
|
||||
_devices.end())
|
||||
_devices.push_front(device);
|
||||
}
|
||||
|
||||
void DeviceManager::release_device(sr_dev_inst *sdi)
|
||||
{
|
||||
assert(sdi);
|
||||
|
||||
// Notify the owner, and removed the device from the used device list
|
||||
_used_devices[sdi]->release_device(sdi);
|
||||
_used_devices.erase(sdi);
|
||||
|
||||
sr_dev_close(sdi);
|
||||
}
|
||||
|
||||
list<sr_dev_inst*> DeviceManager::driver_scan(
|
||||
std::list<boost::shared_ptr<device::DevInst> > DeviceManager::driver_scan(
|
||||
struct sr_dev_driver *const driver, GSList *const drvopts)
|
||||
{
|
||||
list<sr_dev_inst*> driver_devices;
|
||||
list< shared_ptr<device::DevInst> > driver_devices;
|
||||
|
||||
assert(driver);
|
||||
|
||||
// Remove any device instances from this driver from the device
|
||||
// list. They will not be valid after the scan.
|
||||
list<sr_dev_inst*>::iterator i = _devices.begin();
|
||||
list< shared_ptr<device::DevInst> >::iterator i = _devices.begin();
|
||||
while (i != _devices.end()) {
|
||||
if ((*i)->driver == driver)
|
||||
if ((*i)->dev_inst() &&
|
||||
(*i)->dev_inst()->driver == driver) {
|
||||
(*i)->release();
|
||||
i = _devices.erase(i);
|
||||
else
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Release this driver and all it's attached devices
|
||||
release_driver(driver);
|
||||
// Clear all the old device instances from this driver
|
||||
sr_dev_clear(driver);
|
||||
//release_driver(driver);
|
||||
|
||||
// Check If DSLogic driver
|
||||
if (strcmp(driver->name, "DSLogic") == 0) {
|
||||
QDir dir(QApplication::applicationDirPath());
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
if (!dir.cd("res"))
|
||||
return driver_devices;
|
||||
std::string str = dir.absolutePath().toStdString() + "/";
|
||||
@ -113,43 +113,19 @@ list<sr_dev_inst*> DeviceManager::driver_scan(
|
||||
// Do the scan
|
||||
GSList *const devices = sr_driver_scan(driver, drvopts);
|
||||
for (GSList *l = devices; l; l = l->next)
|
||||
driver_devices.push_back((sr_dev_inst*)l->data);
|
||||
driver_devices.push_front(shared_ptr<device::DevInst>(
|
||||
new device::Device((sr_dev_inst*)l->data)));
|
||||
g_slist_free(devices);
|
||||
driver_devices.sort(compare_devices);
|
||||
//driver_devices.sort(compare_devices);
|
||||
|
||||
// Add the scanned devices to the main list
|
||||
_devices.insert(_devices.end(), driver_devices.begin(),
|
||||
driver_devices.end());
|
||||
_devices.sort(compare_devices);
|
||||
//_devices.sort(compare_devices);
|
||||
|
||||
return driver_devices;
|
||||
}
|
||||
|
||||
string DeviceManager::format_device_title(const sr_dev_inst *const sdi)
|
||||
{
|
||||
ostringstream s;
|
||||
|
||||
assert(sdi);
|
||||
|
||||
if (sdi->vendor && sdi->vendor[0]) {
|
||||
s << sdi->vendor;
|
||||
if ((sdi->model && sdi->model[0]) ||
|
||||
(sdi->version && sdi->version[0]))
|
||||
s << ' ';
|
||||
}
|
||||
|
||||
if (sdi->model && sdi->model[0]) {
|
||||
s << sdi->model;
|
||||
if (sdi->version && sdi->version[0])
|
||||
s << ' ';
|
||||
}
|
||||
|
||||
if (sdi->version && sdi->version[0])
|
||||
s << sdi->version;
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
void DeviceManager::init_drivers()
|
||||
{
|
||||
// Initialise all libsigrok drivers
|
||||
@ -165,17 +141,16 @@ void DeviceManager::init_drivers()
|
||||
|
||||
void DeviceManager::release_devices()
|
||||
{
|
||||
// Release all the used devices
|
||||
for (map<sr_dev_inst*, SigSession*>::iterator i = _used_devices.begin();
|
||||
i != _used_devices.end();)
|
||||
release_device((*i++).first);
|
||||
// Release all the used devices
|
||||
BOOST_FOREACH(shared_ptr<device::DevInst> dev, _devices) {
|
||||
assert(dev);
|
||||
dev->release();
|
||||
}
|
||||
|
||||
_used_devices.clear();
|
||||
|
||||
// Clear all the drivers
|
||||
sr_dev_driver **const drivers = sr_driver_list();
|
||||
for (sr_dev_driver **driver = drivers; *driver; driver++)
|
||||
sr_dev_clear(*driver);
|
||||
// Clear all the drivers
|
||||
sr_dev_driver **const drivers = sr_driver_list();
|
||||
for (sr_dev_driver **driver = drivers; *driver; driver++)
|
||||
sr_dev_clear(*driver);
|
||||
}
|
||||
|
||||
void DeviceManager::scan_all_drivers()
|
||||
@ -188,53 +163,22 @@ void DeviceManager::scan_all_drivers()
|
||||
|
||||
void DeviceManager::release_driver(struct sr_dev_driver *const driver)
|
||||
{
|
||||
assert(driver);
|
||||
// map<sr_dev_inst*, SigSession*>::iterator i = _used_devices.begin();
|
||||
// while(i != _used_devices.end()) {
|
||||
// if((*i).first->driver == driver)
|
||||
// {
|
||||
// // Notify the current owner of the device
|
||||
// (*i).second->release_device((*i).first);
|
||||
BOOST_FOREACH(shared_ptr<device::DevInst> dev, _devices) {
|
||||
assert(dev);
|
||||
if(dev->dev_inst()->driver == driver)
|
||||
dev->release();
|
||||
}
|
||||
|
||||
// // Close the device instance
|
||||
// sr_dev_close((*i).first);
|
||||
|
||||
// // Remove it from the used device list
|
||||
// i = _used_devices.erase(i);
|
||||
// } else {
|
||||
// i++;
|
||||
// }
|
||||
// }
|
||||
for (map<sr_dev_inst*, SigSession*>::iterator i = _used_devices.begin();
|
||||
i != _used_devices.end();)
|
||||
if((*i).first->driver == driver)
|
||||
{
|
||||
// Notify the current owner of the device
|
||||
(*i).second->release_device((*i).first);
|
||||
|
||||
// Close the device instance
|
||||
sr_dev_close((*i).first);
|
||||
|
||||
// Remove it from the used device list
|
||||
_used_devices.erase(i++);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
||||
// Clear all the old device instances from this driver
|
||||
sr_dev_clear(driver);
|
||||
// Clear all the old device instances from this driver
|
||||
sr_dev_clear(driver);
|
||||
}
|
||||
|
||||
bool DeviceManager::compare_devices(const sr_dev_inst *const a,
|
||||
const sr_dev_inst *const b)
|
||||
bool DeviceManager::compare_devices(boost::shared_ptr<device::DevInst> a,
|
||||
boost::shared_ptr<device::DevInst> b)
|
||||
{
|
||||
return format_device_title(a).compare(format_device_title(b)) < 0;
|
||||
}
|
||||
|
||||
int DeviceManager::test_device(sr_dev_inst *sdi)
|
||||
{
|
||||
assert(sdi);
|
||||
return sdi->driver->dev_test(sdi);
|
||||
assert(a);
|
||||
assert(b);
|
||||
return a->format_device_title().compare(b->format_device_title()) <= 0;
|
||||
}
|
||||
|
||||
} // namespace pv
|
||||
|
@ -47,6 +47,10 @@ namespace pv {
|
||||
|
||||
class SigSession;
|
||||
|
||||
namespace device {
|
||||
class DevInst;
|
||||
}
|
||||
|
||||
class DeviceManager
|
||||
{
|
||||
public:
|
||||
@ -54,36 +58,29 @@ public:
|
||||
|
||||
~DeviceManager();
|
||||
|
||||
const std::list<sr_dev_inst*>& devices() const;
|
||||
const std::list< boost::shared_ptr<pv::device::DevInst> >& devices() const;
|
||||
|
||||
int use_device(sr_dev_inst *sdi, SigSession *owner);
|
||||
void add_device(boost::shared_ptr<pv::device::DevInst> device);
|
||||
|
||||
void release_device(sr_dev_inst *sdi);
|
||||
|
||||
std::list<sr_dev_inst*> driver_scan(
|
||||
std::list< boost::shared_ptr<pv::device::DevInst> > driver_scan(
|
||||
struct sr_dev_driver *const driver,
|
||||
GSList *const drvopts = NULL);
|
||||
|
||||
static std::string format_device_title(const sr_dev_inst *const sdi);
|
||||
|
||||
void scan_all_drivers();
|
||||
|
||||
int test_device(sr_dev_inst *sdi);
|
||||
|
||||
private:
|
||||
void init_drivers();
|
||||
|
||||
void release_devices();
|
||||
|
||||
void scan_all_drivers();
|
||||
|
||||
void release_driver(struct sr_dev_driver *const driver);
|
||||
|
||||
static bool compare_devices(const sr_dev_inst *const a,
|
||||
const sr_dev_inst *const b);
|
||||
static bool compare_devices(boost::shared_ptr<device::DevInst> a,
|
||||
boost::shared_ptr<device::DevInst> b);
|
||||
|
||||
private:
|
||||
struct sr_context *const _sr_ctx;
|
||||
std::list<sr_dev_inst*> _devices;
|
||||
std::map<sr_dev_inst*, pv::SigSession*> _used_devices;
|
||||
std::list< boost::shared_ptr<pv::device::DevInst> > _devices;
|
||||
};
|
||||
|
||||
} // namespace pv
|
||||
|
@ -42,7 +42,6 @@ DeviceOptions::DeviceOptions(QWidget *parent, struct sr_dev_inst *sdi) :
|
||||
_layout(this),
|
||||
_probes_box(tr("Channels"), this),
|
||||
_props_box(tr("Mode"), this),
|
||||
_mode_comboBox(this),
|
||||
_button_box(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
|
||||
Qt::Horizontal, this),
|
||||
_device_options_binding(sdi)
|
||||
@ -50,11 +49,6 @@ 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);
|
||||
_props_box_layout.addWidget(get_property_form());
|
||||
_layout.addWidget(&_props_box);
|
||||
@ -68,9 +62,6 @@ DeviceOptions::DeviceOptions(QWidget *parent, struct sr_dev_inst *sdi) :
|
||||
|
||||
connect(&_button_box, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(&_button_box, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
connect(&_mode_comboBox, SIGNAL(currentIndexChanged(QString)),
|
||||
this, SLOT(mode_changed(QString)));
|
||||
}
|
||||
|
||||
void DeviceOptions::accept()
|
||||
@ -79,7 +70,6 @@ void DeviceOptions::accept()
|
||||
|
||||
QDialog::accept();
|
||||
|
||||
_last_mode = _sdi->mode;
|
||||
// Commit the properties
|
||||
const vector< boost::shared_ptr<pv::prop::Property> > &properties =
|
||||
_device_options_binding.properties();
|
||||
@ -90,8 +80,8 @@ void DeviceOptions::accept()
|
||||
|
||||
// Commit the probes
|
||||
int index = 0;
|
||||
for (const GSList *l = _sdi->probes; l; l = l->next) {
|
||||
sr_probe *const probe = (sr_probe*)l->data;
|
||||
for (const GSList *l = _sdi->channels; l; l = l->next) {
|
||||
sr_channel *const probe = (sr_channel*)l->data;
|
||||
assert(probe);
|
||||
|
||||
probe->enabled = (_probes_checkBox_list.at(index)->checkState() == Qt::Checked);
|
||||
@ -104,8 +94,6 @@ 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()
|
||||
@ -114,7 +102,6 @@ QWidget* DeviceOptions::get_property_form()
|
||||
QFormLayout *const layout = new QFormLayout(form);
|
||||
form->setLayout(layout);
|
||||
|
||||
layout->addRow("Device Mode", &_mode_comboBox);
|
||||
const vector< boost::shared_ptr<pv::prop::Property> > &properties =
|
||||
_device_options_binding.properties();
|
||||
BOOST_FOREACH(boost::shared_ptr<pv::prop::Property> p, properties)
|
||||
@ -144,8 +131,8 @@ void DeviceOptions::setup_probes()
|
||||
_probes_label_list.clear();
|
||||
_probes_checkBox_list.clear();
|
||||
|
||||
for (const GSList *l = _sdi->probes; l; l = l->next) {
|
||||
sr_probe *const probe = (sr_probe*)l->data;
|
||||
for (const GSList *l = _sdi->channels; l; l = l->next) {
|
||||
sr_channel *const probe = (sr_channel*)l->data;
|
||||
assert(probe);
|
||||
|
||||
QLabel *probe_label = new QLabel(QString::number(probe->index), this);
|
||||
@ -192,13 +179,5 @@ void DeviceOptions::disable_all_probes()
|
||||
set_all_probes(false);
|
||||
}
|
||||
|
||||
void DeviceOptions::mode_changed(QString mode)
|
||||
{
|
||||
(void)mode;
|
||||
// Commit mode
|
||||
sr_config_set(_sdi, SR_CONF_DEVICE_MODE, g_variant_new_string(_mode_comboBox.currentText().toLocal8Bit()));
|
||||
setup_probes();
|
||||
}
|
||||
|
||||
} // namespace dialogs
|
||||
} // namespace pv
|
||||
|
@ -64,12 +64,9 @@ private:
|
||||
private slots:
|
||||
void enable_all_probes();
|
||||
void disable_all_probes();
|
||||
void mode_changed(QString mode);
|
||||
|
||||
private:
|
||||
struct sr_dev_inst *const _sdi;
|
||||
int _last_mode;
|
||||
|
||||
QVBoxLayout _layout;
|
||||
|
||||
QGroupBox _probes_box;
|
||||
@ -78,7 +75,6 @@ private:
|
||||
QVector <QCheckBox *> _probes_checkBox_list;
|
||||
|
||||
QGroupBox _props_box;
|
||||
QComboBox _mode_comboBox;
|
||||
QVBoxLayout _props_box_layout;
|
||||
|
||||
QDialogButtonBox _button_box;
|
||||
|
84
DSLogic-gui/pv/dialogs/storeprogress.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 "storeprogress.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace pv {
|
||||
namespace dialogs {
|
||||
|
||||
StoreProgress::StoreProgress(const QString &file_name,
|
||||
SigSession &session, QWidget *parent) :
|
||||
QProgressDialog(tr("Saving..."), tr("Cancel"), 0, 0, parent),
|
||||
_session(file_name.toStdString(), session)
|
||||
{
|
||||
connect(&_session, SIGNAL(progress_updated()),
|
||||
this, SLOT(on_progress_updated()));
|
||||
}
|
||||
|
||||
StoreProgress::~StoreProgress()
|
||||
{
|
||||
_session.wait();
|
||||
}
|
||||
|
||||
void StoreProgress::run()
|
||||
{
|
||||
if (_session.start())
|
||||
show();
|
||||
else
|
||||
show_error();
|
||||
}
|
||||
|
||||
void StoreProgress::show_error()
|
||||
{
|
||||
QMessageBox msg(parentWidget());
|
||||
msg.setText(tr("Failed to save session."));
|
||||
msg.setInformativeText(_session.error());
|
||||
msg.setStandardButtons(QMessageBox::Ok);
|
||||
msg.setIcon(QMessageBox::Warning);
|
||||
msg.exec();
|
||||
}
|
||||
|
||||
void StoreProgress::closeEvent(QCloseEvent*)
|
||||
{
|
||||
_session.cancel();
|
||||
}
|
||||
|
||||
void StoreProgress::on_progress_updated()
|
||||
{
|
||||
const std::pair<uint64_t, uint64_t> p = _session.progress();
|
||||
assert(p.first <= p.second);
|
||||
|
||||
setValue(p.first);
|
||||
setMaximum(p.second);
|
||||
|
||||
const QString err = _session.error();
|
||||
if (!err.isEmpty()) {
|
||||
show_error();
|
||||
close();
|
||||
}
|
||||
|
||||
if (p.first == p.second)
|
||||
close();
|
||||
}
|
||||
|
||||
} // dialogs
|
||||
} // pv
|
65
DSLogic-gui/pv/dialogs/storeprogress.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_DIALOGS_SAVEPROGRESS_H
|
||||
#define DSLOGIC_PV_DIALOGS_SAVEPROGRESS_H
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <QProgressDialog>
|
||||
|
||||
#include <pv/storesession.h>
|
||||
|
||||
namespace pv {
|
||||
|
||||
class SigSession;
|
||||
|
||||
namespace dialogs {
|
||||
|
||||
class StoreProgress : public QProgressDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StoreProgress(const QString &file_name, SigSession &session,
|
||||
QWidget *parent = 0);
|
||||
|
||||
virtual ~StoreProgress();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void show_error();
|
||||
|
||||
void closeEvent(QCloseEvent*);
|
||||
|
||||
private slots:
|
||||
void on_progress_updated();
|
||||
|
||||
private:
|
||||
pv::StoreSession _session;
|
||||
};
|
||||
|
||||
} // dialogs
|
||||
} // pv
|
||||
|
||||
#endif // PULSEVIEW_PV_DIALOGS_SAVEPROGRESS_H
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "dsotriggerdock.h"
|
||||
#include "../sigsession.h"
|
||||
#include "../device/devinst.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QLabel>
|
||||
@ -135,11 +136,10 @@ void DsoTriggerDock::paintEvent(QPaintEvent *)
|
||||
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) {
|
||||
ret = _session.get_device()->set_config(NULL, NULL,
|
||||
SR_CONF_HORIZ_TRIGGERPOS,
|
||||
g_variant_new_uint16((uint16_t)pos));
|
||||
if (!ret) {
|
||||
QMessageBox msg(this);
|
||||
msg.setText("Trigger Setting Issue");
|
||||
msg.setInformativeText("Change horiz trigger position failed!");
|
||||
@ -147,6 +147,10 @@ void DsoTriggerDock::pos_changed(int pos)
|
||||
msg.setIcon(QMessageBox::Warning);
|
||||
msg.exec();
|
||||
}
|
||||
|
||||
uint64_t sample_limit = _session.get_device()->get_sample_limit();
|
||||
uint64_t trig_pos = sample_limit * pos / 100;
|
||||
set_trig_pos(trig_pos);
|
||||
}
|
||||
|
||||
void DsoTriggerDock::source_changed()
|
||||
@ -154,8 +158,10 @@ 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) {
|
||||
ret = _session.get_device()->set_config(NULL, NULL,
|
||||
SR_CONF_TRIGGER_SOURCE,
|
||||
g_variant_new_byte(id));
|
||||
if (!ret) {
|
||||
QMessageBox msg(this);
|
||||
msg.setText("Trigger Setting Issue");
|
||||
msg.setInformativeText("Change trigger source failed!");
|
||||
@ -170,8 +176,10 @@ 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) {
|
||||
ret = _session.get_device()->set_config(NULL, NULL,
|
||||
SR_CONF_TRIGGER_SLOPE,
|
||||
g_variant_new_byte(id));
|
||||
if (!ret) {
|
||||
QMessageBox msg(this);
|
||||
msg.setText("Trigger Setting Issue");
|
||||
msg.setInformativeText("Change trigger type failed!");
|
||||
@ -183,7 +191,7 @@ void DsoTriggerDock::type_changed()
|
||||
|
||||
void DsoTriggerDock::device_change()
|
||||
{
|
||||
if (strcmp(_session.get_device()->driver->name, "DSLogic") != 0) {
|
||||
if (strcmp(_session.get_device()->dev_inst()->driver->name, "DSLogic") != 0) {
|
||||
position_spinBox->setDisabled(true);
|
||||
position_slider->setDisabled(true);
|
||||
} else {
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
void device_change();
|
||||
|
||||
signals:
|
||||
void set_trig_pos(quint64 trig_pos);
|
||||
|
||||
private slots:
|
||||
void pos_changed(int pos);
|
||||
|
@ -20,6 +20,7 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "measuredock.h"
|
||||
#include "../sigsession.h"
|
||||
@ -27,6 +28,9 @@
|
||||
#include "../view/view.h"
|
||||
#include "../view/timemarker.h"
|
||||
#include "../view/ruler.h"
|
||||
#include "../view/logicsignal.h"
|
||||
#include "../data/signaldata.h"
|
||||
#include "../data/snapshot.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPainter>
|
||||
@ -34,6 +38,8 @@
|
||||
|
||||
#include "libsigrok4DSLogic/libsigrok.h"
|
||||
|
||||
using boost::shared_ptr;
|
||||
|
||||
namespace pv {
|
||||
namespace dock {
|
||||
|
||||
@ -71,23 +77,42 @@ MeasureDock::MeasureDock(QWidget *parent, View &view, SigSession &session) :
|
||||
_cursor_groupBox = new QGroupBox("Cursor measurement", this);
|
||||
_t1_comboBox = new QComboBox(this);
|
||||
_t2_comboBox = new QComboBox(this);
|
||||
_delta_label = new QLabel("#####", this);
|
||||
_cnt_label = new QLabel("#####", this);
|
||||
_t3_comboBox = new QComboBox(this);
|
||||
_delta_label_t1t2 = new QLabel("#####", this);
|
||||
_cnt_label_t1t2 = new QLabel("#####", this);
|
||||
_delta_label_t2t3 = new QLabel("#####", this);
|
||||
_cnt_label_t2t3 = new QLabel("#####", this);
|
||||
_delta_label_t1t3 = new QLabel("#####", this);
|
||||
_cnt_label_t1t3 = new QLabel("#####", this);
|
||||
_t1_last_index = 0;
|
||||
_t2_last_index = 0;
|
||||
_t3_last_index = 0;
|
||||
|
||||
_cursor_layout = new QGridLayout();
|
||||
_cursor_layout->addWidget(new QLabel("T1: ", this), 0, 0);
|
||||
_cursor_layout->addWidget(_t1_comboBox, 0, 1);
|
||||
_cursor_layout->addWidget(new QLabel("T2: ", this), 1, 0);
|
||||
_cursor_layout->addWidget(_t2_comboBox, 1, 1);
|
||||
_cursor_layout->addWidget(new QLabel("|T2 - T1|: ", this), 2, 0);
|
||||
_cursor_layout->addWidget(_delta_label, 2, 1);
|
||||
_cursor_layout->addWidget(new QLabel("Delta Samples: ", this), 2, 2);
|
||||
_cursor_layout->addWidget(_cnt_label, 2, 3);
|
||||
_cursor_layout->addWidget(new QLabel("T3: ", this), 2, 0);
|
||||
_cursor_layout->addWidget(_t3_comboBox, 2, 1);
|
||||
|
||||
_cursor_layout->addWidget(new QLabel("Cursors", this), 4, 0);
|
||||
_cursor_layout->addWidget(new QLabel("Time/Samples", this), 4, 1);
|
||||
_cursor_layout->addWidget(new QLabel("Sample Value", this), 4, 2);
|
||||
_cursor_layout->addWidget(new QLabel("Value Radix", this), 4, 3);
|
||||
_cursor_layout->addWidget(new QLabel("|T2 - T1|: ", this), 3, 0);
|
||||
_cursor_layout->addWidget(_delta_label_t1t2, 3, 1);
|
||||
_cursor_layout->addWidget(new QLabel("Delta Samples: ", this), 3, 2);
|
||||
_cursor_layout->addWidget(_cnt_label_t1t2, 3, 3);
|
||||
|
||||
_cursor_layout->addWidget(new QLabel("|T3 - T2|: ", this), 4, 0);
|
||||
_cursor_layout->addWidget(_delta_label_t2t3, 4, 1);
|
||||
_cursor_layout->addWidget(new QLabel("Delta Samples: ", this), 4, 2);
|
||||
_cursor_layout->addWidget(_cnt_label_t2t3, 4, 3);
|
||||
|
||||
_cursor_layout->addWidget(new QLabel("|T3 - T1|: ", this), 5, 0);
|
||||
_cursor_layout->addWidget(_delta_label_t1t3, 5, 1);
|
||||
_cursor_layout->addWidget(new QLabel("Delta Samples: ", this), 5, 2);
|
||||
_cursor_layout->addWidget(_cnt_label_t1t3, 5, 3);
|
||||
|
||||
_cursor_layout->addWidget(new QLabel("Cursors", this), 6, 0);
|
||||
_cursor_layout->addWidget(new QLabel("Time/Samples", this), 6, 1);
|
||||
|
||||
_cursor_layout->addWidget(new QLabel(this), 0, 4);
|
||||
_cursor_layout->addWidget(new QLabel(this), 1, 4);
|
||||
@ -106,6 +131,7 @@ MeasureDock::MeasureDock(QWidget *parent, View &view, SigSession &session) :
|
||||
|
||||
connect(_t1_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
connect(_t2_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
connect(_t3_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
|
||||
connect(_fen_checkBox, SIGNAL(stateChanged(int)), &_view, SLOT(set_measure_en(int)));
|
||||
}
|
||||
@ -124,10 +150,16 @@ void MeasureDock::paintEvent(QPaintEvent *)
|
||||
|
||||
void MeasureDock::cursor_update()
|
||||
{
|
||||
using namespace pv::data;
|
||||
|
||||
int index = 1;
|
||||
|
||||
disconnect(_t1_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
disconnect(_t2_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
disconnect(_t3_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
_t1_comboBox->clear();
|
||||
_t2_comboBox->clear();
|
||||
_t3_comboBox->clear();
|
||||
|
||||
if (!_cursor_pushButton_list.empty()) {
|
||||
for (QVector<QPushButton *>::Iterator i = _cursor_pushButton_list.begin();
|
||||
@ -136,20 +168,12 @@ void MeasureDock::cursor_update()
|
||||
for (QVector<QLabel *>::Iterator i = _curpos_label_list.begin();
|
||||
i != _curpos_label_list.end(); i++)
|
||||
delete (*i);
|
||||
for (QVector<QLabel *>::Iterator i = _curvalue_label_list.begin();
|
||||
i != _curvalue_label_list.end(); i++)
|
||||
delete (*i);
|
||||
for (QVector<QComboBox *>::Iterator i = _radix_comboBox_list.begin();
|
||||
i != _radix_comboBox_list.end(); i++)
|
||||
delete (*i);
|
||||
for (QVector<QLabel *>::Iterator i = _space_label_list.begin();
|
||||
i != _space_label_list.end(); i++)
|
||||
delete (*i);
|
||||
|
||||
_cursor_pushButton_list.clear();
|
||||
_curpos_label_list.clear();
|
||||
_curvalue_label_list.clear();
|
||||
_radix_comboBox_list.clear();
|
||||
_space_label_list.clear();
|
||||
}
|
||||
|
||||
@ -158,33 +182,37 @@ void MeasureDock::cursor_update()
|
||||
QString curCursor = "Cursor "+QString::number(index);
|
||||
_t1_comboBox->addItem(curCursor);
|
||||
_t2_comboBox->addItem(curCursor);
|
||||
_t3_comboBox->addItem(curCursor);
|
||||
|
||||
QPushButton *_cursor_pushButton = new QPushButton(curCursor, this);
|
||||
QLabel *_curpos_label = new QLabel(_view.get_cm_time(index - 1), this);
|
||||
QLabel *_curvalue_label = new QLabel("####", this);
|
||||
QComboBox *_radix_comboBox = new QComboBox(this);
|
||||
_radix_comboBox->addItem("Bin");
|
||||
_radix_comboBox->addItem("Oct");
|
||||
_radix_comboBox->addItem("Dec");
|
||||
_radix_comboBox->addItem("Hex");
|
||||
QString _cur_text = _view.get_cm_time(index - 1) + "/" + QString::number(_view.get_cursor_samples(index - 1));
|
||||
QLabel *_curpos_label = new QLabel(_cur_text, this);
|
||||
QLabel *_space_label = new QLabel(this);
|
||||
_cursor_pushButton_list.push_back(_cursor_pushButton);
|
||||
_curpos_label_list.push_back(_curpos_label);
|
||||
_curvalue_label_list.push_back(_curvalue_label);
|
||||
_radix_comboBox_list.push_back(_radix_comboBox);
|
||||
_space_label_list.push_back(_space_label);
|
||||
|
||||
_cursor_layout->addWidget(_cursor_pushButton, 4 + index, 0);
|
||||
_cursor_layout->addWidget(_curpos_label, 4 + index, 1);
|
||||
_cursor_layout->addWidget(_curvalue_label, 4 + index, 2);
|
||||
_cursor_layout->addWidget(_radix_comboBox, 4 + index, 3);
|
||||
_cursor_layout->addWidget(_space_label, 4 + index, 4);
|
||||
_cursor_layout->addWidget(_cursor_pushButton, 6 + index, 0);
|
||||
_cursor_layout->addWidget(_curpos_label, 6 + index, 1);
|
||||
_cursor_layout->addWidget(_space_label, 6 + index, 2);
|
||||
|
||||
connect(_cursor_pushButton, SIGNAL(clicked()), this, SLOT(goto_cursor()));
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (_t1_last_index < _t1_comboBox->count())
|
||||
_t1_comboBox->setCurrentIndex(_t1_last_index);
|
||||
if (_t2_last_index < _t2_comboBox->count())
|
||||
_t2_comboBox->setCurrentIndex(_t2_last_index);
|
||||
if (_t3_last_index < _t3_comboBox->count())
|
||||
_t3_comboBox->setCurrentIndex(_t3_last_index);
|
||||
|
||||
connect(_t1_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
connect(_t2_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
connect(_t3_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(delta_update()));
|
||||
|
||||
delta_update();
|
||||
update();
|
||||
}
|
||||
|
||||
@ -202,7 +230,8 @@ void MeasureDock::cursor_moved()
|
||||
int index = 0;
|
||||
for(std::list<Cursor*>::iterator i = _view.get_cursorList().begin();
|
||||
i != _view.get_cursorList().end(); i++) {
|
||||
_curpos_label_list.at(index)->setText(_view.get_cm_time(index));
|
||||
QString _cur_text = _view.get_cm_time(index) + "/" + QString::number(_view.get_cursor_samples(index));
|
||||
_curpos_label_list.at(index)->setText(_cur_text);
|
||||
//_curvalue_label_list.at(index)->setText(_view.get_cm_value(index));
|
||||
index++;
|
||||
}
|
||||
@ -212,11 +241,28 @@ void MeasureDock::cursor_moved()
|
||||
|
||||
void MeasureDock::delta_update()
|
||||
{
|
||||
_t1_last_index = std::max(_t1_comboBox->currentIndex(), 0);
|
||||
_t2_last_index = std::max(_t2_comboBox->currentIndex(), 0);
|
||||
_t3_last_index = std::max(_t3_comboBox->currentIndex(), 0);
|
||||
if (_t1_comboBox->count() != 0 && _t2_comboBox->count() != 0) {
|
||||
int t1_index = _t1_comboBox->currentIndex();
|
||||
int t2_index = _t2_comboBox->currentIndex();
|
||||
_delta_label->setText(_view.get_cm_delta(t1_index, t2_index));
|
||||
_cnt_label->setText(_view.get_cm_delta_cnt(t1_index, t2_index));
|
||||
uint64_t delta = abs(_view.get_cursor_samples(_t1_last_index) -
|
||||
_view.get_cursor_samples(_t2_last_index));
|
||||
_delta_label_t1t2->setText(_view.get_cm_delta(_t1_last_index, _t2_last_index));
|
||||
_cnt_label_t1t2->setText(QString::number(delta));
|
||||
}
|
||||
|
||||
if (_t2_comboBox->count() != 0 && _t2_comboBox->count() != 0) {
|
||||
uint64_t delta = abs(_view.get_cursor_samples(_t2_last_index) -
|
||||
_view.get_cursor_samples(_t3_last_index));
|
||||
_delta_label_t2t3->setText(_view.get_cm_delta(_t2_last_index, _t3_last_index));
|
||||
_cnt_label_t2t3->setText(QString::number(delta));
|
||||
}
|
||||
|
||||
if (_t1_comboBox->count() != 0 && _t3_comboBox->count() != 0) {
|
||||
uint64_t delta = abs(_view.get_cursor_samples(_t1_last_index) -
|
||||
_view.get_cursor_samples(_t3_last_index));
|
||||
_delta_label_t1t3->setText(_view.get_cm_delta(_t1_last_index, _t3_last_index));
|
||||
_cnt_label_t1t3->setText(QString::number(delta));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,13 +91,19 @@ private:
|
||||
QGroupBox *_cursor_groupBox;
|
||||
QComboBox *_t1_comboBox;
|
||||
QComboBox *_t2_comboBox;
|
||||
QLabel *_delta_label;
|
||||
QLabel *_cnt_label;
|
||||
QComboBox *_t3_comboBox;
|
||||
QLabel *_delta_label_t1t2;
|
||||
QLabel *_cnt_label_t1t2;
|
||||
QLabel *_delta_label_t2t3;
|
||||
QLabel *_cnt_label_t2t3;
|
||||
QLabel *_delta_label_t1t3;
|
||||
QLabel *_cnt_label_t1t3;
|
||||
int _t1_last_index;
|
||||
int _t2_last_index;
|
||||
int _t3_last_index;
|
||||
|
||||
QVector <QPushButton *> _cursor_pushButton_list;
|
||||
QVector <QLabel *> _curpos_label_list;
|
||||
QVector <QLabel *> _curvalue_label_list;
|
||||
QVector <QComboBox *> _radix_comboBox_list;
|
||||
QVector <QLabel *> _space_label_list;
|
||||
};
|
||||
|
||||
|
@ -22,13 +22,17 @@
|
||||
|
||||
|
||||
#include "protocoldock.h"
|
||||
#include "../decoder/democonfig.h"
|
||||
#include "../sigsession.h"
|
||||
#include "../view/decodetrace.h"
|
||||
#include "../device/devinst.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPainter>
|
||||
#include <QMessageBox>
|
||||
#include <QFormLayout>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace pv {
|
||||
namespace dock {
|
||||
@ -49,10 +53,21 @@ ProtocolDock::ProtocolDock(QWidget *parent, SigSession &session) :
|
||||
QIcon(":/icons/del.png")));
|
||||
_del_all_button->setCheckable(true);
|
||||
_protocol_combobox = new QComboBox(this);
|
||||
for (int i = 0; decoder::protocol_list[i] != NULL;) {
|
||||
_protocol_combobox->addItem(decoder::protocol_list[i]);
|
||||
i++;
|
||||
|
||||
GSList *l = g_slist_sort(g_slist_copy(
|
||||
(GSList*)srd_decoder_list()), decoder_name_cmp);
|
||||
for(; l; l = l->next)
|
||||
{
|
||||
const srd_decoder *const d = (srd_decoder*)l->data;
|
||||
assert(d);
|
||||
|
||||
const bool have_probes = (d->channels || d->opt_channels) != 0;
|
||||
if (true == have_probes) {
|
||||
_protocol_combobox->addItem(QString::fromUtf8(d->name), qVariantFromValue(l->data));
|
||||
}
|
||||
}
|
||||
g_slist_free(l);
|
||||
|
||||
hori_layout->addWidget(_add_button);
|
||||
hori_layout->addWidget(_del_all_button);
|
||||
hori_layout->addWidget(_protocol_combobox);
|
||||
@ -74,6 +89,12 @@ ProtocolDock::~ProtocolDock()
|
||||
{
|
||||
}
|
||||
|
||||
int ProtocolDock::decoder_name_cmp(const void *a, const void *b)
|
||||
{
|
||||
return strcmp(((const srd_decoder*)a)->name,
|
||||
((const srd_decoder*)b)->name);
|
||||
}
|
||||
|
||||
void ProtocolDock::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QStyleOption opt;
|
||||
@ -84,7 +105,7 @@ void ProtocolDock::paintEvent(QPaintEvent *)
|
||||
|
||||
void ProtocolDock::add_protocol()
|
||||
{
|
||||
if (_session.get_device()->mode != LOGIC) {
|
||||
if (_session.get_device()->dev_inst()->mode != LOGIC) {
|
||||
QMessageBox msg(this);
|
||||
msg.setText("Protocol Analyzer");
|
||||
msg.setInformativeText("Protocol Analyzer is only valid in Digital Mode!");
|
||||
@ -92,11 +113,12 @@ void ProtocolDock::add_protocol()
|
||||
msg.setIcon(QMessageBox::Warning);
|
||||
msg.exec();
|
||||
} else {
|
||||
pv::decoder::DemoConfig dlg(this, _session.get_device(), _protocol_combobox->currentIndex());
|
||||
if (dlg.exec()) {
|
||||
std::list <int > _sel_probes = dlg.get_sel_probes();
|
||||
QMap <QString, QVariant>& _options = dlg.get_options();
|
||||
QMap <QString, int> _options_index = dlg.get_options_index();
|
||||
srd_decoder *const decoder =
|
||||
(srd_decoder*)(_protocol_combobox->itemData(_protocol_combobox->currentIndex())).value<void*>();
|
||||
if (_session.add_decoder(decoder)) {
|
||||
//std::list <int > _sel_probes = dlg.get_sel_probes();
|
||||
//QMap <QString, QVariant>& _options = dlg.get_options();
|
||||
//QMap <QString, int> _options_index = dlg.get_options_index();
|
||||
|
||||
QPushButton *_del_button = new QPushButton(this);
|
||||
QPushButton *_set_button = new QPushButton(this);
|
||||
@ -105,7 +127,7 @@ void ProtocolDock::add_protocol()
|
||||
QIcon(":/icons/del.png")));
|
||||
_set_button->setFlat(true);
|
||||
_set_button->setIcon(QIcon::fromTheme("protocol",
|
||||
QIcon(":/icons/set.png")));
|
||||
QIcon(":/icons/gear.png")));
|
||||
QLabel *_protocol_label = new QLabel(this);
|
||||
|
||||
_del_button->setCheckable(true);
|
||||
@ -129,7 +151,7 @@ void ProtocolDock::add_protocol()
|
||||
_hori_layout_list.push_back(hori_layout);
|
||||
_layout->insertLayout(_del_button_list.size(), hori_layout);
|
||||
|
||||
_session.add_protocol_analyzer(_protocol_combobox->currentIndex(), _sel_probes, _options, _options_index);
|
||||
//_session.add_protocol_analyzer(_protocol_combobox->currentIndex(), _sel_probes, _options, _options_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,15 +163,16 @@ void ProtocolDock::rst_protocol()
|
||||
i != _set_button_list.end(); i++) {
|
||||
QPushButton *button = qobject_cast<QPushButton *>(sender());
|
||||
if ((*i) == button) {
|
||||
pv::decoder::DemoConfig dlg(this, _session.get_device(), _protocol_index_list.at(rst_index));
|
||||
dlg.set_config(_session.get_decode_probes(rst_index), _session.get_decode_options_index(rst_index));
|
||||
if (dlg.exec()) {
|
||||
std::list <int > _sel_probes = dlg.get_sel_probes();
|
||||
QMap <QString, QVariant>& _options = dlg.get_options();
|
||||
QMap <QString, int> _options_index = dlg.get_options_index();
|
||||
//pv::decoder::DemoConfig dlg(this, _session.get_device(), _protocol_index_list.at(rst_index));
|
||||
//dlg.set_config(_session.get_decode_probes(rst_index), _session.get_decode_options_index(rst_index));
|
||||
//if (dlg.exec()) {
|
||||
//std::list <int > _sel_probes = dlg.get_sel_probes();
|
||||
//QMap <QString, QVariant>& _options = dlg.get_options();
|
||||
//QMap <QString, int> _options_index = dlg.get_options_index();
|
||||
|
||||
_session.rst_protocol_analyzer(rst_index, _sel_probes, _options, _options_index);
|
||||
}
|
||||
//_session.rst_protocol_analyzer(rst_index, _sel_probes, _options, _options_index);
|
||||
//}
|
||||
_session.rst_decoder(rst_index);
|
||||
break;
|
||||
}
|
||||
rst_index++;
|
||||
@ -170,7 +193,7 @@ void ProtocolDock::del_protocol()
|
||||
delete _set_button_list.at(del_index);
|
||||
delete _protocol_label_list.at(del_index);
|
||||
|
||||
_session.del_protocol_analyzer(0);
|
||||
_session.remove_decode_signal(0);
|
||||
del_index++;
|
||||
}
|
||||
_hori_layout_list.clear();
|
||||
@ -204,7 +227,7 @@ void ProtocolDock::del_protocol()
|
||||
_protocol_label_list.remove(del_index);
|
||||
_protocol_index_list.remove(del_index);
|
||||
|
||||
_session.del_protocol_analyzer(del_index);
|
||||
_session.remove_decode_signal(del_index);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -225,7 +248,7 @@ void ProtocolDock::del_all_protocol()
|
||||
delete _set_button_list.at(del_index);
|
||||
delete _protocol_label_list.at(del_index);
|
||||
|
||||
_session.del_protocol_analyzer(0);
|
||||
_session.remove_decode_signal(0);
|
||||
del_index++;
|
||||
}
|
||||
_hori_layout_list.clear();
|
||||
|
@ -24,6 +24,8 @@
|
||||
#ifndef DSLOGIC_PV_PROTOCOLDOCK_H
|
||||
#define DSLOGIC_PV_PROTOCOLDOCK_H
|
||||
|
||||
#include <libsigrokdecode/libsigrokdecode.h>
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QPushButton>
|
||||
#include <QComboBox>
|
||||
@ -36,8 +38,6 @@
|
||||
|
||||
#include <libsigrok4DSLogic/libsigrok.h>
|
||||
|
||||
#include "../decoder/decoder.h"
|
||||
|
||||
namespace pv {
|
||||
|
||||
class SigSession;
|
||||
@ -64,6 +64,7 @@ private slots:
|
||||
void del_protocol();
|
||||
|
||||
private:
|
||||
static int decoder_name_cmp(const void *a, const void *b);
|
||||
|
||||
private:
|
||||
SigSession &_session;
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "../dialogs/search.h"
|
||||
#include "../data/snapshot.h"
|
||||
#include "../data/logicsnapshot.h"
|
||||
#include "../device/devinst.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPainter>
|
||||
@ -45,6 +46,7 @@ namespace pv {
|
||||
namespace dock {
|
||||
|
||||
using namespace pv::view;
|
||||
using namespace pv::widgets;
|
||||
|
||||
SearchDock::SearchDock(QWidget *parent, View &view, SigSession &session) :
|
||||
QWidget(parent),
|
||||
@ -197,7 +199,7 @@ void SearchDock::on_next()
|
||||
|
||||
void SearchDock::on_set()
|
||||
{
|
||||
dialogs::Search dlg(this, _session.get_device(), _pattern);
|
||||
dialogs::Search dlg(this, _session.get_device()->dev_inst(), _pattern);
|
||||
if (dlg.exec()) {
|
||||
_pattern = dlg.get_pattern();
|
||||
_pattern.remove(QChar(' '), Qt::CaseInsensitive);
|
||||
|
@ -45,7 +45,7 @@
|
||||
|
||||
#include <libsigrok4DSLogic/libsigrok.h>
|
||||
|
||||
#include "fakelineedit.h"
|
||||
#include "../widgets/fakelineedit.h"
|
||||
|
||||
namespace pv {
|
||||
|
||||
@ -55,6 +55,10 @@ namespace view {
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace widgets {
|
||||
class FakeLineEdit;
|
||||
}
|
||||
|
||||
namespace dock {
|
||||
|
||||
class SearchDock : public QWidget
|
||||
@ -86,7 +90,7 @@ private:
|
||||
|
||||
QPushButton _pre_button;
|
||||
QPushButton _nxt_button;
|
||||
FakeLineEdit* _search_value;
|
||||
widgets::FakeLineEdit* _search_value;
|
||||
};
|
||||
|
||||
} // namespace dock
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "triggerdock.h"
|
||||
#include "../sigsession.h"
|
||||
#include "../device/devinst.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QGridLayout>
|
||||
@ -209,7 +210,7 @@ void TriggerDock::simple_trigger()
|
||||
|
||||
void TriggerDock::adv_trigger()
|
||||
{
|
||||
if (strcmp(_session.get_device()->driver->name, "DSLogic") == 0) {
|
||||
if (strcmp(_session.get_device()->dev_inst()->driver->name, "DSLogic") == 0) {
|
||||
widget_enable();
|
||||
ds_trigger_set_mode(ADV_TRIGGER);
|
||||
_session.set_adv_trigger(true);
|
||||
@ -341,7 +342,7 @@ void TriggerDock::pos_changed(int pos)
|
||||
|
||||
void TriggerDock::device_change()
|
||||
{
|
||||
if (strcmp(_session.get_device()->driver->name, "DSLogic") != 0) {
|
||||
if (strcmp(_session.get_device()->dev_inst()->driver->name, "DSLogic") != 0) {
|
||||
position_spinBox->setDisabled(true);
|
||||
position_slider->setDisabled(true);
|
||||
} else {
|
||||
|
@ -21,12 +21,14 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifdef ENABLE_SIGROKDECODE
|
||||
#ifdef ENABLE_DECODE
|
||||
#include <libsigrokdecode/libsigrokdecode.h>
|
||||
#include "dock/protocoldock.h"
|
||||
#endif
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
@ -41,27 +43,32 @@
|
||||
#include <QDockWidget>
|
||||
#include <QDebug>
|
||||
#include <QDesktopWidget>
|
||||
#include <QKeyEvent>
|
||||
#include <QEvent>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "devicemanager.h"
|
||||
#include "device/device.h"
|
||||
#include "device/file.h"
|
||||
|
||||
#include "dialogs/about.h"
|
||||
#include "dialogs/connect.h"
|
||||
#include "dialogs/storeprogress.h"
|
||||
|
||||
#include "toolbars/samplingbar.h"
|
||||
#include "toolbars/devicebar.h"
|
||||
#include "toolbars/trigbar.h"
|
||||
#include "toolbars/filebar.h"
|
||||
#include "toolbars/logobar.h"
|
||||
|
||||
#include "dock/protocoldock.h"
|
||||
#include "dock/triggerdock.h"
|
||||
#include "dock/dsotriggerdock.h"
|
||||
#include "dock/measuredock.h"
|
||||
#include "dock/searchdock.h"
|
||||
|
||||
#include "view/view.h"
|
||||
#include "view/trace.h"
|
||||
#include "view/signal.h"
|
||||
#include "view/dsosignal.h"
|
||||
|
||||
/* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */
|
||||
#define __STDC_FORMAT_MACROS
|
||||
@ -69,9 +76,13 @@
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <glib.h>
|
||||
#include <list>
|
||||
#include <libsigrok4DSLogic/libsigrok.h>
|
||||
|
||||
using namespace std;
|
||||
using boost::shared_ptr;
|
||||
using boost::dynamic_pointer_cast;
|
||||
using std::list;
|
||||
using std::vector;
|
||||
|
||||
namespace pv {
|
||||
|
||||
@ -110,103 +121,10 @@ void MainWindow::setup_ui()
|
||||
_vertical_layout->setContentsMargins(0, 0, 0, 0);
|
||||
setCentralWidget(_central_widget);
|
||||
|
||||
// // Setup the menu bar
|
||||
// _menu_bar = new QMenuBar(this);
|
||||
// _menu_bar->setGeometry(QRect(0, 0, 400, 25));
|
||||
|
||||
// // File Menu
|
||||
// _menu_file = new QMenu(_menu_bar);
|
||||
// _menu_file->setTitle(QApplication::translate(
|
||||
// "MainWindow", "&File", 0, QApplication::UnicodeUTF8));
|
||||
|
||||
// _action_open = new QAction(this);
|
||||
// _action_open->setText(QApplication::translate(
|
||||
// "MainWindow", "&Open...", 0, QApplication::UnicodeUTF8));
|
||||
// _action_open->setIcon(QIcon::fromTheme("document-open",
|
||||
// QIcon(":/icons/document-open.png")));
|
||||
// _action_open->setObjectName(QString::fromUtf8("actionOpen"));
|
||||
// _menu_file->addAction(_action_open);
|
||||
|
||||
// _menu_file->addSeparator();
|
||||
|
||||
// _action_connect = new QAction(this);
|
||||
// _action_connect->setText(QApplication::translate(
|
||||
// "MainWindow", "&Connect to Device...", 0,
|
||||
// QApplication::UnicodeUTF8));
|
||||
// _action_connect->setObjectName(QString::fromUtf8("actionConnect"));
|
||||
// _menu_file->addAction(_action_connect);
|
||||
|
||||
// _menu_file->addSeparator();
|
||||
|
||||
// _action_quit = new QAction(this);
|
||||
// _action_quit->setText(QApplication::translate(
|
||||
// "MainWindow", "&Quit", 0, QApplication::UnicodeUTF8));
|
||||
// _action_quit->setIcon(QIcon::fromTheme("application-exit",
|
||||
// QIcon(":/icons/application-exit.png")));
|
||||
// _action_quit->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
|
||||
// _action_quit->setObjectName(QString::fromUtf8("actionQuit"));
|
||||
// _menu_file->addAction(_action_quit);
|
||||
|
||||
// // View Menu
|
||||
// _menu_view = new QMenu(_menu_bar);
|
||||
// _menu_view->setTitle(QApplication::translate(
|
||||
// "MainWindow", "&View", 0, QApplication::UnicodeUTF8));
|
||||
|
||||
// _action_view_zoom_in = new QAction(this);
|
||||
// _action_view_zoom_in->setText(QApplication::translate(
|
||||
// "MainWindow", "Zoom &In", 0, QApplication::UnicodeUTF8));
|
||||
// _action_view_zoom_in->setIcon(QIcon::fromTheme("zoom-in",
|
||||
// QIcon(":/icons/zoom-in.png")));
|
||||
// _action_view_zoom_in->setObjectName(
|
||||
// QString::fromUtf8("actionViewZoomIn"));
|
||||
// _menu_view->addAction(_action_view_zoom_in);
|
||||
|
||||
// _action_view_zoom_out = new QAction(this);
|
||||
// _action_view_zoom_out->setText(QApplication::translate(
|
||||
// "MainWindow", "Zoom &Out", 0, QApplication::UnicodeUTF8));
|
||||
// _action_view_zoom_out->setIcon(QIcon::fromTheme("zoom-out",
|
||||
// QIcon(":/icons/zoom-out.png")));
|
||||
// _action_view_zoom_out->setObjectName(
|
||||
// QString::fromUtf8("actionViewZoomOut"));
|
||||
// _menu_view->addAction(_action_view_zoom_out);
|
||||
|
||||
// _menu_view->addSeparator();
|
||||
|
||||
// _action_view_show_cursors = new QAction(this);
|
||||
// _action_view_show_cursors->setCheckable(true);
|
||||
// _action_view_show_cursors->setChecked(_view->cursors_shown());
|
||||
// _action_view_show_cursors->setShortcut(QKeySequence(Qt::Key_C));
|
||||
// _action_view_show_cursors->setObjectName(
|
||||
// QString::fromUtf8("actionViewShowCursors"));
|
||||
// _action_view_show_cursors->setText(QApplication::translate(
|
||||
// "MainWindow", "Show &Cursors", 0, QApplication::UnicodeUTF8));
|
||||
// _menu_view->addAction(_action_view_show_cursors);
|
||||
|
||||
// // Help Menu
|
||||
// _menu_help = new QMenu(_menu_bar);
|
||||
// _menu_help->setTitle(QApplication::translate(
|
||||
// "MainWindow", "&Help", 0, QApplication::UnicodeUTF8));
|
||||
|
||||
// _action_about = new QAction(this);
|
||||
// _action_about->setObjectName(QString::fromUtf8("actionAbout"));
|
||||
// _action_about->setText(QApplication::translate(
|
||||
// "MainWindow", "&About...", 0, QApplication::UnicodeUTF8));
|
||||
// _menu_help->addAction(_action_about);
|
||||
|
||||
// _menu_bar->addAction(_menu_file->menuAction());
|
||||
// _menu_bar->addAction(_menu_view->menuAction());
|
||||
// _menu_bar->addAction(_menu_help->menuAction());
|
||||
|
||||
//setMenuBar(_menu_bar);
|
||||
//QMenuBar *_void_menu = new QMenuBar(this);
|
||||
//setMenuBar(_void_menu);
|
||||
//QMetaObject::connectSlotsByName(this);
|
||||
|
||||
// Setup the sampling bar
|
||||
_sampling_bar = new toolbars::SamplingBar(this);
|
||||
_sampling_bar = new toolbars::SamplingBar(_session, this);
|
||||
_trig_bar = new toolbars::TrigBar(this);
|
||||
_file_bar = new toolbars::FileBar(_session, this);
|
||||
_device_bar = new toolbars::DeviceBar(this);
|
||||
_logo_bar = new toolbars::LogoBar(_session, this);
|
||||
|
||||
connect(_trig_bar, SIGNAL(on_protocol(bool)), this,
|
||||
@ -217,9 +135,14 @@ void MainWindow::setup_ui()
|
||||
SLOT(on_measure(bool)));
|
||||
connect(_trig_bar, SIGNAL(on_search(bool)), this,
|
||||
SLOT(on_search(bool)));
|
||||
connect(_file_bar, SIGNAL(load_file(QString)), this,
|
||||
SLOT(load_file(QString)));
|
||||
connect(_file_bar, SIGNAL(save()), this,
|
||||
SLOT(on_save()));
|
||||
connect(_file_bar, SIGNAL(on_screenShot()), this,
|
||||
SLOT(on_screenShot()));
|
||||
|
||||
#ifdef ENABLE_DECODE
|
||||
// protocol dock
|
||||
_protocol_dock=new QDockWidget(tr("Protocol"),this);
|
||||
_protocol_dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
|
||||
@ -228,6 +151,8 @@ void MainWindow::setup_ui()
|
||||
//dock::ProtocolDock *_protocol_widget = new dock::ProtocolDock(_protocol_dock, _session);
|
||||
_protocol_widget = new dock::ProtocolDock(_protocol_dock, _session);
|
||||
_protocol_dock->setWidget(_protocol_widget);
|
||||
qDebug() << "Protocol decoder enabled!\n";
|
||||
#endif
|
||||
// trigger dock
|
||||
_trigger_dock=new QDockWidget(tr("Trigger Setting..."),this);
|
||||
_trigger_dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
|
||||
@ -248,41 +173,25 @@ void MainWindow::setup_ui()
|
||||
_view = new pv::view::View(_session, this);
|
||||
_vertical_layout->addWidget(_view);
|
||||
|
||||
// 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()));
|
||||
connect(_device_bar, SIGNAL(device_updated()), this,
|
||||
SLOT(update()));
|
||||
connect(_sampling_bar, SIGNAL(device_reload()), this,
|
||||
SLOT(init()));
|
||||
connect(_sampling_bar, SIGNAL(device_selected()), this,
|
||||
SLOT(update_device_list()));
|
||||
connect(_sampling_bar, SIGNAL(device_updated()), &_session,
|
||||
SLOT(reload()));
|
||||
connect(_sampling_bar, SIGNAL(run_stop()), this,
|
||||
SLOT(run_stop()));
|
||||
connect(_sampling_bar, SIGNAL(instant_stop()), this,
|
||||
SLOT(instant_stop()));
|
||||
connect(_sampling_bar, SIGNAL(update_scale()), _view,
|
||||
SLOT(update_scale()));
|
||||
connect(_dso_trigger_widget, SIGNAL(set_trig_pos(quint64)), _view,
|
||||
SLOT(set_trig_pos(quint64)));
|
||||
|
||||
addToolBar(_sampling_bar);
|
||||
addToolBar(_trig_bar);
|
||||
addToolBar(_device_bar);
|
||||
addToolBar(_file_bar);
|
||||
addToolBar(_logo_bar);
|
||||
|
||||
// Setup the dockWidget
|
||||
// protocol dock
|
||||
// _protocol_dock=new QDockWidget(tr("Protocol"),this);
|
||||
// _protocol_dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
|
||||
// _protocol_dock->setAllowedAreas(Qt::RightDockWidgetArea);
|
||||
// _protocol_dock->setVisible(false);
|
||||
// //dock::ProtocolDock *_protocol_widget = new dock::ProtocolDock(_protocol_dock, _session);
|
||||
// _protocol_widget = new dock::ProtocolDock(_protocol_dock, _session);
|
||||
// _protocol_dock->setWidget(_protocol_widget);
|
||||
// // trigger dock
|
||||
// _trigger_dock=new QDockWidget(tr("Trigger Setting..."),this);
|
||||
// _trigger_dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
|
||||
// _trigger_dock->setAllowedAreas(Qt::RightDockWidgetArea);
|
||||
// _trigger_dock->setVisible(false);
|
||||
// dock::TriggerDock *_trigger_widget = new dock::TriggerDock(_trigger_dock, _session);
|
||||
// _trigger_dock->setWidget(_trigger_widget);
|
||||
// measure dock
|
||||
_measure_dock=new QDockWidget(tr("Measurement"),this);
|
||||
_measure_dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
|
||||
@ -300,10 +209,9 @@ void MainWindow::setup_ui()
|
||||
_search_widget = new dock::SearchDock(_search_dock, *_view, _session);
|
||||
_search_dock->setWidget(_search_widget);
|
||||
|
||||
|
||||
_protocol_dock->setObjectName(tr("protocolDock"));
|
||||
_trigger_dock->setObjectName(tr("triggerDock"));
|
||||
#ifdef ENABLE_DECODE
|
||||
addDockWidget(Qt::RightDockWidgetArea,_protocol_dock);
|
||||
#endif
|
||||
addDockWidget(Qt::RightDockWidgetArea,_trigger_dock);
|
||||
addDockWidget(Qt::RightDockWidgetArea,_dso_trigger_dock);
|
||||
addDockWidget(Qt::RightDockWidgetArea, _measure_dock);
|
||||
@ -322,8 +230,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(&_session, SIGNAL(sample_rate_changed(uint64_t)), _sampling_bar,
|
||||
SLOT(set_sample_rate(uint64_t)));
|
||||
|
||||
connect(_view, SIGNAL(cursor_update()), _measure_widget,
|
||||
SLOT(cursor_update()));
|
||||
@ -331,28 +239,28 @@ void MainWindow::setup_ui()
|
||||
SLOT(cursor_moved()));
|
||||
connect(_view, SIGNAL(mouse_moved()), _measure_widget,
|
||||
SLOT(mouse_moved()));
|
||||
}
|
||||
connect(_view, SIGNAL(mode_changed()), this,
|
||||
SLOT(update_device_list()));
|
||||
|
||||
void MainWindow::init()
|
||||
{
|
||||
_protocol_widget->del_all_protocol();
|
||||
_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);
|
||||
}
|
||||
}
|
||||
// event filter
|
||||
_view->installEventFilter(this);
|
||||
_sampling_bar->installEventFilter(this);
|
||||
_trig_bar->installEventFilter(this);
|
||||
_file_bar->installEventFilter(this);
|
||||
_logo_bar->installEventFilter(this);
|
||||
_dso_trigger_dock->installEventFilter(this);
|
||||
_trigger_dock->installEventFilter(this);
|
||||
#ifdef ENABLE_DECODE
|
||||
_protocol_dock->installEventFilter(this);
|
||||
#endif
|
||||
_measure_dock->installEventFilter(this);
|
||||
_search_dock->installEventFilter(this);
|
||||
|
||||
void MainWindow::update()
|
||||
{
|
||||
if (_session.get_device())
|
||||
_session.update_signals(_session.get_device());
|
||||
// Populate the device list and select the initially selected device
|
||||
_session.set_default_device();
|
||||
update_device_list();
|
||||
_session.start_hotplug_proc(boost::bind(&MainWindow::session_error, this,
|
||||
QString("Hotplug failed"), _1));
|
||||
}
|
||||
|
||||
void MainWindow::session_error(
|
||||
@ -363,92 +271,55 @@ void MainWindow::session_error(
|
||||
Q_ARG(QString, info_text));
|
||||
}
|
||||
|
||||
void MainWindow::update_device_list(struct sr_dev_inst *selected_device)
|
||||
void MainWindow::update_device_list()
|
||||
{
|
||||
assert(_device_bar);
|
||||
assert(_sampling_bar);
|
||||
|
||||
const list<sr_dev_inst*> &devices = _device_manager.devices();
|
||||
_device_bar->set_device_list(devices);
|
||||
_view->show_trig_cursor(false);
|
||||
_trigger_widget->device_change();
|
||||
#ifdef ENABLE_DECODE
|
||||
_protocol_widget->del_all_protocol();
|
||||
#endif
|
||||
_trig_bar->close_all();
|
||||
|
||||
if (!selected_device && !devices.empty()) {
|
||||
// Fall back to the first device in the list.
|
||||
selected_device = devices.front();
|
||||
|
||||
// Try and find the demo device and select that by default
|
||||
BOOST_FOREACH (struct sr_dev_inst *sdi, devices)
|
||||
if (strcmp(sdi->driver->name, "DSLogic") == 0) {
|
||||
selected_device = sdi;
|
||||
}
|
||||
}
|
||||
|
||||
if (selected_device) {
|
||||
if (_session.set_device(selected_device) == SR_OK) {
|
||||
_device_bar->set_selected_device(selected_device, false);
|
||||
_sampling_bar->set_device(selected_device);
|
||||
_sampling_bar->update_sample_rate_selector();
|
||||
_logo_bar->dslogic_connected(strcmp(selected_device->driver->name, "DSLogic") == 0);
|
||||
init();
|
||||
} else {
|
||||
show_session_error("Open Device Failed",
|
||||
"the selected device can't be opened!");
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef HAVE_LA_DSLOGIC
|
||||
_session.start_hotplug_proc(boost::bind(&MainWindow::session_error, this,
|
||||
QString("Hotplug failed"), _1));
|
||||
_session.start_dso_ctrl_proc(boost::bind(&MainWindow::session_error, this,
|
||||
QString("Hotplug failed"), _1));
|
||||
// #endif
|
||||
}
|
||||
|
||||
void MainWindow::device_change()
|
||||
{
|
||||
assert(_device_bar);
|
||||
|
||||
struct sr_dev_inst *selected_device;
|
||||
|
||||
const list<sr_dev_inst*> &devices = _device_manager.devices();
|
||||
_device_bar->set_device_list(devices);
|
||||
|
||||
// Fall back to the first device in the list.
|
||||
selected_device = devices.front();
|
||||
|
||||
// Try and find the demo device and select that by default
|
||||
BOOST_FOREACH (struct sr_dev_inst *sdi, devices)
|
||||
if (strcmp(sdi->driver->name, "DSLogic") == 0) {
|
||||
selected_device = sdi;
|
||||
}
|
||||
|
||||
if (_session.set_device(selected_device) == SR_OK) {;
|
||||
_device_bar->set_selected_device(selected_device, true);
|
||||
_sampling_bar->set_device(selected_device);
|
||||
_sampling_bar->update_sample_rate_selector();
|
||||
_logo_bar->dslogic_connected(strcmp(selected_device->driver->name, "DSLogic") == 0);
|
||||
init();
|
||||
if (_session.get_device()->dev_inst()->mode == DSO) {
|
||||
_sampling_bar->enable_toggle(false);
|
||||
} else {
|
||||
// show_session_error("Open Device Failed",
|
||||
// "the selected device can't be opened!");
|
||||
device_detach();
|
||||
_sampling_bar->enable_toggle(true);
|
||||
}
|
||||
|
||||
// #ifdef HAVE_LA_DSLOGIC
|
||||
_session.stop_hotplug_proc();
|
||||
_session.start_hotplug_proc(boost::bind(&MainWindow::session_error, this,
|
||||
QString("Hotplug failed"), _1));
|
||||
// #endif
|
||||
shared_ptr<pv::device::DevInst> selected_device = _session.get_device();
|
||||
_device_manager.add_device(selected_device);
|
||||
_sampling_bar->set_device_list(_device_manager.devices(), selected_device);
|
||||
_session.init_signals();
|
||||
|
||||
if(dynamic_pointer_cast<pv::device::File>(selected_device)) {
|
||||
const QString errorMessage(
|
||||
QString("Failed to capture file data!"));
|
||||
const QString infoMessage;
|
||||
_session.start_capture(true, boost::bind(&MainWindow::session_error, this,
|
||||
errorMessage, infoMessage));
|
||||
}
|
||||
|
||||
if (strcmp(selected_device->dev_inst()->driver->name, "DSLogic") == 0)
|
||||
_logo_bar->dslogic_connected(true);
|
||||
else
|
||||
_logo_bar->dslogic_connected(false);
|
||||
}
|
||||
|
||||
void MainWindow::load_file(QString file_name)
|
||||
{
|
||||
const QString errorMessage(
|
||||
QString("Failed to load file %1").arg(file_name));
|
||||
const QString infoMessage;
|
||||
_session.load_file(file_name.toStdString(),
|
||||
boost::bind(&MainWindow::session_error, this,
|
||||
errorMessage, infoMessage));
|
||||
try {
|
||||
_session.set_file(file_name.toStdString());
|
||||
} catch(QString e) {
|
||||
show_session_error(tr("Failed to load ") + file_name, e);
|
||||
_session.set_default_device();
|
||||
update_device_list();
|
||||
return;
|
||||
}
|
||||
|
||||
update_device_list();
|
||||
}
|
||||
|
||||
void MainWindow::show_session_error(
|
||||
@ -462,50 +333,9 @@ void MainWindow::show_session_error(
|
||||
msg.exec();
|
||||
}
|
||||
|
||||
void MainWindow::device_selected()
|
||||
{
|
||||
if (_session.set_device(_device_bar->get_selected_device()) == SR_OK) {;
|
||||
_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_hotplug_proc();
|
||||
//_session.stop_hot_plug_proc();
|
||||
|
||||
if (_session.get_capture_state() == SigSession::Running)
|
||||
_session.stop_capture();
|
||||
@ -517,12 +347,13 @@ void MainWindow::device_attach()
|
||||
if (*driver)
|
||||
_device_manager.driver_scan(*driver);
|
||||
|
||||
device_change();
|
||||
_session.set_default_device();
|
||||
update_device_list();
|
||||
}
|
||||
|
||||
void MainWindow::device_detach()
|
||||
{
|
||||
_session.stop_hotplug_proc();
|
||||
//_session.stop_hot_plug_proc();
|
||||
|
||||
if (_session.get_capture_state() == SigSession::Running)
|
||||
_session.stop_capture();
|
||||
@ -534,18 +365,19 @@ void MainWindow::device_detach()
|
||||
if (*driver)
|
||||
_device_manager.driver_scan(*driver);
|
||||
|
||||
device_change();
|
||||
_session.set_default_device();
|
||||
update_device_list();
|
||||
}
|
||||
|
||||
void MainWindow::run_stop()
|
||||
{
|
||||
_sampling_bar->enable_run_stop(false);
|
||||
_sampling_bar->enable_instant(false);
|
||||
switch(_session.get_capture_state()) {
|
||||
case SigSession::Init:
|
||||
case SigSession::Stopped:
|
||||
_view->show_trig_cursor(false);
|
||||
_session.set_total_sample_len(_sampling_bar->get_record_length());
|
||||
_session.start_capture(_sampling_bar->get_record_length(),
|
||||
_session.start_capture(false,
|
||||
boost::bind(&MainWindow::session_error, this,
|
||||
QString("Capture failed"), _1));
|
||||
break;
|
||||
@ -558,29 +390,25 @@ void MainWindow::run_stop()
|
||||
_sampling_bar->enable_run_stop(true);
|
||||
}
|
||||
|
||||
void MainWindow::dso_ch_changed(uint16_t num)
|
||||
void MainWindow::instant_stop()
|
||||
{
|
||||
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));
|
||||
}
|
||||
_sampling_bar->enable_instant(false);
|
||||
_sampling_bar->enable_run_stop(false);
|
||||
switch(_session.get_capture_state()) {
|
||||
case SigSession::Init:
|
||||
case SigSession::Stopped:
|
||||
_view->show_trig_cursor(false);
|
||||
_session.start_capture(true,
|
||||
boost::bind(&MainWindow::session_error, this,
|
||||
QString("Capture failed"), _1));
|
||||
break;
|
||||
|
||||
case SigSession::Running:
|
||||
_session.stop_capture();
|
||||
break;
|
||||
}
|
||||
g_usleep(1000);
|
||||
_sampling_bar->enable_instant(true);
|
||||
}
|
||||
|
||||
void MainWindow::test_data_error()
|
||||
@ -596,12 +424,11 @@ void MainWindow::test_data_error()
|
||||
|
||||
void MainWindow::capture_state_changed(int state)
|
||||
{
|
||||
if (_session.get_device()->mode != DSO) {
|
||||
if (_session.get_device()->dev_inst()->mode != DSO) {
|
||||
_sampling_bar->enable_toggle(state != SigSession::Running);
|
||||
_trig_bar->enable_toggle(state != SigSession::Running);
|
||||
_measure_dock->widget()->setEnabled(state != SigSession::Running);
|
||||
}
|
||||
_device_bar->enable_toggle(state != SigSession::Running);
|
||||
_file_bar->enable_toggle(state != SigSession::Running);
|
||||
_sampling_bar->set_sampling(state == SigSession::Running);
|
||||
_view->on_state_changed(state != SigSession::Running);
|
||||
@ -609,15 +436,20 @@ void MainWindow::capture_state_changed(int state)
|
||||
|
||||
void MainWindow::on_protocol(bool visible)
|
||||
{
|
||||
#ifdef ENABLE_DECODE
|
||||
_protocol_dock->setVisible(visible);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::on_trigger(bool visible)
|
||||
{
|
||||
if (_session.get_device()->mode != DSO)
|
||||
if (_session.get_device()->dev_inst()->mode != DSO) {
|
||||
_trigger_dock->setVisible(visible);
|
||||
else
|
||||
_dso_trigger_dock->setVisible(false);
|
||||
} else {
|
||||
_trigger_dock->setVisible(false);
|
||||
_dso_trigger_dock->setVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_measure(bool visible)
|
||||
@ -648,4 +480,104 @@ void MainWindow::on_screenShot()
|
||||
pixmap.save(fileName, format.toAscii());
|
||||
}
|
||||
|
||||
void MainWindow::on_save()
|
||||
{
|
||||
using pv::dialogs::StoreProgress;
|
||||
|
||||
// Stop any currently running capture session
|
||||
_session.stop_capture();
|
||||
|
||||
// Show the dialog
|
||||
const QString file_name = QFileDialog::getSaveFileName(
|
||||
this, tr("Save File"), "", tr("DSLogic Sessions (*.dsl)"));
|
||||
|
||||
if (file_name.isEmpty())
|
||||
return;
|
||||
|
||||
StoreProgress *dlg = new StoreProgress(file_name, _session, this);
|
||||
dlg->run();
|
||||
}
|
||||
|
||||
|
||||
bool MainWindow::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
(void) object;
|
||||
|
||||
if( event->type() == QEvent::KeyPress ) {
|
||||
const vector< shared_ptr<view::Signal> > sigs(
|
||||
_session.get_signals());
|
||||
|
||||
QKeyEvent *ke = (QKeyEvent *) event;
|
||||
switch(ke->key()) {
|
||||
case Qt::Key_S:
|
||||
run_stop();
|
||||
break;
|
||||
case Qt::Key_I:
|
||||
instant_stop();
|
||||
break;
|
||||
case Qt::Key_T:
|
||||
if (_session.get_device()->dev_inst()->mode == DSO)
|
||||
on_trigger(!_dso_trigger_dock->isVisible());
|
||||
else
|
||||
on_trigger(!_trigger_dock->isVisible());
|
||||
break;
|
||||
case Qt::Key_D:
|
||||
on_protocol(!_protocol_dock->isVisible());
|
||||
break;
|
||||
case Qt::Key_M:
|
||||
on_measure(!_measure_dock->isVisible());
|
||||
break;
|
||||
case Qt::Key_R:
|
||||
on_search(!_search_dock->isVisible());
|
||||
break;
|
||||
case Qt::Key_O:
|
||||
_sampling_bar->on_configure();
|
||||
break;
|
||||
case Qt::Key_PageUp:
|
||||
_view->set_scale_offset(_view->scale(),
|
||||
_view->offset() - _view->scale()*_view->viewport()->width());
|
||||
break;
|
||||
case Qt::Key_PageDown:
|
||||
_view->set_scale_offset(_view->scale(),
|
||||
_view->offset() + _view->scale()*_view->viewport()->width());
|
||||
|
||||
break;
|
||||
case Qt::Key_Left:
|
||||
_view->zoom(1);
|
||||
break;
|
||||
case Qt::Key_Right:
|
||||
_view->zoom(-1);
|
||||
break;
|
||||
case Qt::Key_Up:
|
||||
BOOST_FOREACH(const shared_ptr<view::Signal> s, sigs) {
|
||||
shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
|
||||
if (dsoSig->get_vDialActive()) {
|
||||
dsoSig->go_vDialNext();
|
||||
update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Qt::Key_Down:
|
||||
BOOST_FOREACH(const shared_ptr<view::Signal> s, sigs) {
|
||||
shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
|
||||
if (dsoSig->get_vDialActive()) {
|
||||
dsoSig->go_vDialPre();
|
||||
update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
QWidget::keyPressEvent((QKeyEvent *)event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace pv
|
||||
|
@ -45,7 +45,6 @@ class DeviceManager;
|
||||
|
||||
namespace toolbars {
|
||||
class SamplingBar;
|
||||
class DeviceBar;
|
||||
class TrigBar;
|
||||
class FileBar;
|
||||
class LogoBar;
|
||||
@ -67,10 +66,6 @@ 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,
|
||||
@ -81,35 +76,29 @@ private:
|
||||
|
||||
void session_error(const QString text, const QString info_text);
|
||||
|
||||
/**
|
||||
* Updates the device list in the sampling bar, and updates the
|
||||
* selection.
|
||||
* @param selected_device The device to select, or NULL if the
|
||||
* first device in the device list should be selected.
|
||||
*/
|
||||
void update_device_list(
|
||||
struct sr_dev_inst *selected_device = NULL);
|
||||
|
||||
void device_change();
|
||||
bool eventFilter(QObject *object, QEvent *event);
|
||||
|
||||
private slots:
|
||||
void load_file(QString file_name);
|
||||
|
||||
/**
|
||||
* Updates the device list in the sampling bar, and updates the
|
||||
* selection.
|
||||
* @param selected_device The device to select, or NULL if the
|
||||
* first device in the device list should be selected.
|
||||
*/
|
||||
void update_device_list();
|
||||
|
||||
void show_session_error(
|
||||
const QString text, const QString info_text);
|
||||
|
||||
void device_selected();
|
||||
|
||||
void run_stop();
|
||||
|
||||
void instant_stop();
|
||||
|
||||
void test_data_error();
|
||||
|
||||
void capture_state_changed(int state);
|
||||
|
||||
void init();
|
||||
|
||||
void update();
|
||||
void capture_state_changed(int state);
|
||||
|
||||
void on_protocol(bool visible);
|
||||
|
||||
@ -121,15 +110,14 @@ private slots:
|
||||
|
||||
void on_screenShot();
|
||||
|
||||
void on_save();
|
||||
|
||||
/*
|
||||
* hotplug slot function
|
||||
*/
|
||||
void device_attach();
|
||||
void device_detach();
|
||||
|
||||
/* */
|
||||
void dso_ch_changed(uint16_t num);
|
||||
|
||||
private:
|
||||
DeviceManager &_device_manager;
|
||||
|
||||
@ -155,13 +143,15 @@ private:
|
||||
QVBoxLayout *_vertical_layout;
|
||||
|
||||
toolbars::SamplingBar *_sampling_bar;
|
||||
toolbars::DeviceBar *_device_bar;
|
||||
toolbars::TrigBar *_trig_bar;
|
||||
toolbars::FileBar *_file_bar;
|
||||
toolbars::LogoBar *_logo_bar;
|
||||
|
||||
#ifdef ENABLE_DECODE
|
||||
QDockWidget *_protocol_dock;
|
||||
dock::ProtocolDock *_protocol_widget;
|
||||
#endif
|
||||
|
||||
QDockWidget *_trigger_dock;
|
||||
QDockWidget *_dso_trigger_dock;
|
||||
dock::TriggerDock *_trigger_widget;
|
||||
|
@ -20,9 +20,16 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <QFormLayout>
|
||||
|
||||
#include <pv/prop/property.h>
|
||||
|
||||
#include "binding.h"
|
||||
|
||||
using boost::shared_ptr;
|
||||
|
||||
namespace pv {
|
||||
namespace prop {
|
||||
namespace binding {
|
||||
@ -32,6 +39,58 @@ const std::vector< boost::shared_ptr<Property> >& Binding::properties()
|
||||
return _properties;
|
||||
}
|
||||
|
||||
void Binding::commit()
|
||||
{
|
||||
BOOST_FOREACH(shared_ptr<pv::prop::Property> p, _properties) {
|
||||
assert(p);
|
||||
p->commit();
|
||||
}
|
||||
}
|
||||
|
||||
void Binding::add_properties_to_form(QFormLayout *layout,
|
||||
bool auto_commit) const
|
||||
{
|
||||
assert(layout);
|
||||
|
||||
BOOST_FOREACH(shared_ptr<pv::prop::Property> p, _properties)
|
||||
{
|
||||
assert(p);
|
||||
|
||||
QWidget *const widget = p->get_widget(layout->parentWidget(),
|
||||
auto_commit);
|
||||
if (p->labeled_widget())
|
||||
layout->addRow(widget);
|
||||
else
|
||||
layout->addRow(p->name(), widget);
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* Binding::get_property_form(QWidget *parent,
|
||||
bool auto_commit) const
|
||||
{
|
||||
QWidget *const form = new QWidget(parent);
|
||||
QFormLayout *const layout = new QFormLayout(form);
|
||||
form->setLayout(layout);
|
||||
add_properties_to_form(layout, auto_commit);
|
||||
return form;
|
||||
}
|
||||
|
||||
QString Binding::print_gvariant(GVariant *const gvar)
|
||||
{
|
||||
QString s;
|
||||
|
||||
if (g_variant_is_of_type(gvar, G_VARIANT_TYPE("s")))
|
||||
s = QString::fromUtf8(g_variant_get_string(gvar, NULL));
|
||||
else
|
||||
{
|
||||
gchar *const text = g_variant_print(gvar, FALSE);
|
||||
s = QString::fromUtf8(text);
|
||||
g_free(text);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
} // binding
|
||||
} // prop
|
||||
} // pv
|
||||
|
@ -24,9 +24,14 @@
|
||||
#ifndef DSLOGIC_PV_PROP_BINDING_BINDING_H
|
||||
#define DSLOGIC_PV_PROP_BINDING_BINDING_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <vector>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <QString>
|
||||
|
||||
class QFormLayout;
|
||||
class QWidget;
|
||||
|
||||
namespace pv {
|
||||
@ -41,6 +46,16 @@ class Binding
|
||||
public:
|
||||
const std::vector< boost::shared_ptr<Property> >& properties();
|
||||
|
||||
void commit();
|
||||
|
||||
void add_properties_to_form(QFormLayout *layout,
|
||||
bool auto_commit = false) const;
|
||||
|
||||
QWidget* get_property_form(QWidget *parent,
|
||||
bool auto_commit = false) const;
|
||||
|
||||
static QString print_gvariant(GVariant *const gvar);
|
||||
|
||||
protected:
|
||||
std::vector< boost::shared_ptr<Property> > _properties;
|
||||
|
||||
|
148
DSLogic-gui/pv/prop/binding/decoderoptions.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 <libsigrokdecode/libsigrokdecode.h>
|
||||
|
||||
#include "decoderoptions.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/none_t.hpp>
|
||||
|
||||
#include <pv/data/decoderstack.h>
|
||||
#include <pv/data/decode/decoder.h>
|
||||
#include <pv/prop/double.h>
|
||||
#include <pv/prop/enum.h>
|
||||
#include <pv/prop/int.h>
|
||||
#include <pv/prop/string.h>
|
||||
|
||||
using boost::bind;
|
||||
using boost::none;
|
||||
using boost::shared_ptr;
|
||||
using std::make_pair;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace pv {
|
||||
namespace prop {
|
||||
namespace binding {
|
||||
|
||||
DecoderOptions::DecoderOptions(
|
||||
shared_ptr<pv::data::DecoderStack> decoder_stack,
|
||||
shared_ptr<data::decode::Decoder> decoder) :
|
||||
_decoder_stack(decoder_stack),
|
||||
_decoder(decoder)
|
||||
{
|
||||
assert(_decoder);
|
||||
|
||||
const srd_decoder *const dec = _decoder->decoder();
|
||||
assert(dec);
|
||||
|
||||
for (GSList *l = dec->options; l; l = l->next)
|
||||
{
|
||||
const srd_decoder_option *const opt =
|
||||
(srd_decoder_option*)l->data;
|
||||
|
||||
const QString name = QString::fromUtf8(opt->desc);
|
||||
|
||||
const Property::Getter getter = bind(
|
||||
&DecoderOptions::getter, this, opt->id);
|
||||
const Property::Setter setter = bind(
|
||||
&DecoderOptions::setter, this, opt->id, _1);
|
||||
|
||||
shared_ptr<Property> prop;
|
||||
|
||||
if (opt->values)
|
||||
prop = bind_enum(name, opt, getter, setter);
|
||||
else if (g_variant_is_of_type(opt->def, G_VARIANT_TYPE("d")))
|
||||
prop = shared_ptr<Property>(new Double(name, 2, "",
|
||||
none, none, getter, setter));
|
||||
else if (g_variant_is_of_type(opt->def, G_VARIANT_TYPE("x")))
|
||||
prop = shared_ptr<Property>(
|
||||
new Int(name, "", none, getter, setter));
|
||||
else if (g_variant_is_of_type(opt->def, G_VARIANT_TYPE("s")))
|
||||
prop = shared_ptr<Property>(
|
||||
new String(name, getter, setter));
|
||||
else
|
||||
continue;
|
||||
|
||||
_properties.push_back(prop);
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Property> DecoderOptions::bind_enum(
|
||||
const QString &name, const srd_decoder_option *option,
|
||||
Property::Getter getter, Property::Setter setter)
|
||||
{
|
||||
vector< pair<GVariant*, QString> > values;
|
||||
for (GSList *l = option->values; l; l = l->next) {
|
||||
GVariant *const var = (GVariant*)l->data;
|
||||
assert(var);
|
||||
values.push_back(make_pair(var, print_gvariant(var)));
|
||||
}
|
||||
|
||||
return shared_ptr<Property>(new Enum(name, values, getter, setter));
|
||||
}
|
||||
|
||||
GVariant* DecoderOptions::getter(const char *id)
|
||||
{
|
||||
GVariant *val = NULL;
|
||||
|
||||
assert(_decoder);
|
||||
|
||||
// Get the value from the hash table if it is already present
|
||||
const map<string, GVariant*>& options = _decoder->options();
|
||||
map<string, GVariant*>::const_iterator iter = options.find(id);
|
||||
|
||||
if (iter != options.end())
|
||||
val = (*iter).second;
|
||||
else
|
||||
{
|
||||
assert(_decoder->decoder());
|
||||
|
||||
// Get the default value if not
|
||||
for (GSList *l = _decoder->decoder()->options; l; l = l->next)
|
||||
{
|
||||
const srd_decoder_option *const opt =
|
||||
(srd_decoder_option*)l->data;
|
||||
if (strcmp(opt->id, id) == 0) {
|
||||
val = opt->def;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (val)
|
||||
g_variant_ref(val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void DecoderOptions::setter(const char *id, GVariant *value)
|
||||
{
|
||||
assert(_decoder);
|
||||
_decoder->set_option(id, value);
|
||||
}
|
||||
|
||||
} // binding
|
||||
} // prop
|
||||
} // pv
|
66
DSLogic-gui/pv/prop/binding/decoderoptions.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_PROP_BINDING_DECODEROPTIONS_H
|
||||
#define DSLOGIC_PV_PROP_BINDING_DECODEROPTIONS_H
|
||||
|
||||
#include "binding.h"
|
||||
|
||||
#include <pv/prop/property.h>
|
||||
|
||||
struct srd_decoder_option;
|
||||
|
||||
namespace pv {
|
||||
|
||||
namespace data {
|
||||
class DecoderStack;
|
||||
namespace decode {
|
||||
class Decoder;
|
||||
}
|
||||
}
|
||||
|
||||
namespace prop {
|
||||
namespace binding {
|
||||
|
||||
class DecoderOptions : public Binding
|
||||
{
|
||||
public:
|
||||
DecoderOptions(boost::shared_ptr<pv::data::DecoderStack> decoder_stack,
|
||||
boost::shared_ptr<pv::data::decode::Decoder> decoder);
|
||||
|
||||
private:
|
||||
static boost::shared_ptr<Property> bind_enum(const QString &name,
|
||||
const srd_decoder_option *option,
|
||||
Property::Getter getter, Property::Setter setter);
|
||||
|
||||
GVariant* getter(const char *id);
|
||||
|
||||
void setter(const char *id, GVariant *value);
|
||||
|
||||
private:
|
||||
boost::shared_ptr<pv::data::DecoderStack> _decoder_stack;
|
||||
boost::shared_ptr<pv::data::decode::Decoder> _decoder;
|
||||
};
|
||||
|
||||
} // binding
|
||||
} // prop
|
||||
} // pv
|
||||
|
||||
#endif // DSLOGIC_PV_PROP_BINDING_DECODEROPTIONS_H
|
274
DSLogic-gui/pv/prop/binding/deviceoptions.cpp
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* 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 <boost/bind.hpp>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "deviceoptions.h"
|
||||
|
||||
#include <pv/prop/bool.h>
|
||||
#include <pv/prop/double.h>
|
||||
#include <pv/prop/enum.h>
|
||||
#include <pv/prop/int.h>
|
||||
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
namespace pv {
|
||||
namespace prop {
|
||||
namespace binding {
|
||||
|
||||
DeviceOptions::DeviceOptions(struct sr_dev_inst *sdi) :
|
||||
_sdi(sdi)
|
||||
{
|
||||
GVariant *gvar_opts, *gvar_list;
|
||||
gsize num_opts;
|
||||
|
||||
if ((sr_config_list(sdi->driver, sdi, NULL, SR_CONF_DEVICE_CONFIGS,
|
||||
&gvar_opts) != SR_OK))
|
||||
/* Driver supports no device instance options. */
|
||||
return;
|
||||
|
||||
const int *const options = (const int32_t *)g_variant_get_fixed_array(
|
||||
gvar_opts, &num_opts, sizeof(int32_t));
|
||||
for (unsigned int i = 0; i < num_opts; i++) {
|
||||
const struct sr_config_info *const info =
|
||||
sr_config_info_get(options[i]);
|
||||
|
||||
if (!info)
|
||||
continue;
|
||||
|
||||
const int key = info->key;
|
||||
|
||||
if(sr_config_list(_sdi->driver, _sdi, NULL, key, &gvar_list) != SR_OK)
|
||||
gvar_list = NULL;
|
||||
|
||||
const QString name(info->name);
|
||||
|
||||
switch(key)
|
||||
{
|
||||
case SR_CONF_SAMPLERATE:
|
||||
bind_samplerate(name, gvar_list);
|
||||
break;
|
||||
|
||||
case SR_CONF_CAPTURE_RATIO:
|
||||
bind_int(name, key, "%", pair<int64_t, int64_t>(0, 100));
|
||||
break;
|
||||
|
||||
case SR_CONF_PATTERN_MODE:
|
||||
case SR_CONF_BUFFERSIZE:
|
||||
case SR_CONF_TRIGGER_SOURCE:
|
||||
case SR_CONF_FILTER:
|
||||
case SR_CONF_COUPLING:
|
||||
case SR_CONF_EN_CH:
|
||||
case SR_CONF_OPERATION_MODE:
|
||||
case SR_CONF_THRESHOLD:
|
||||
case SR_CONF_ZERO:
|
||||
bind_enum(name, key, gvar_list);
|
||||
break;
|
||||
|
||||
case SR_CONF_RLE:
|
||||
bind_bool(name, key);
|
||||
break;
|
||||
|
||||
case SR_CONF_CLOCK_TYPE:
|
||||
case SR_CONF_CLOCK_EDGE:
|
||||
bind_bool(name, key);
|
||||
break;
|
||||
|
||||
case SR_CONF_TIMEBASE:
|
||||
bind_enum(name, key, gvar_list, print_timebase);
|
||||
break;
|
||||
|
||||
case SR_CONF_VDIV:
|
||||
bind_enum(name, key, gvar_list, print_vdiv);
|
||||
break;
|
||||
default:
|
||||
gvar_list = NULL;
|
||||
}
|
||||
|
||||
if (gvar_list)
|
||||
g_variant_unref(gvar_list);
|
||||
}
|
||||
g_variant_unref(gvar_opts);
|
||||
}
|
||||
|
||||
GVariant* DeviceOptions::config_getter(
|
||||
const struct sr_dev_inst *sdi, int key)
|
||||
{
|
||||
GVariant *data = NULL;
|
||||
if (sr_config_get(sdi->driver, sdi, NULL, NULL, key, &data) != SR_OK) {
|
||||
qDebug() <<
|
||||
"WARNING: Failed to get value of config id" << key;
|
||||
return NULL;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void DeviceOptions::config_setter(
|
||||
const struct sr_dev_inst *sdi, int key, GVariant* value)
|
||||
{
|
||||
if (sr_config_set(sdi, NULL, NULL, key, value) != SR_OK)
|
||||
qDebug() << "WARNING: Failed to set value of sample rate";
|
||||
}
|
||||
|
||||
void DeviceOptions::bind_bool(const QString &name, int key)
|
||||
{
|
||||
_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, boost::function<QString (GVariant*)> printer)
|
||||
{
|
||||
GVariant *gvar;
|
||||
GVariantIter iter;
|
||||
vector< pair<GVariant*, QString> > values;
|
||||
|
||||
assert(gvar_list);
|
||||
|
||||
g_variant_iter_init (&iter, gvar_list);
|
||||
while ((gvar = g_variant_iter_next_value (&iter)))
|
||||
values.push_back(make_pair(gvar, printer(gvar)));
|
||||
|
||||
_properties.push_back(boost::shared_ptr<Property>(
|
||||
new Enum(name, values,
|
||||
bind(config_getter, _sdi, key),
|
||||
bind(config_setter, _sdi, key, _1))));
|
||||
}
|
||||
|
||||
void DeviceOptions::bind_int(const QString &name, int key, QString suffix,
|
||||
optional< std::pair<int64_t, int64_t> > range)
|
||||
{
|
||||
_properties.push_back(boost::shared_ptr<Property>(
|
||||
new Int(name, suffix, range,
|
||||
bind(config_getter, _sdi, key),
|
||||
bind(config_setter, _sdi, key, _1))));
|
||||
}
|
||||
|
||||
QString DeviceOptions::print_gvariant(GVariant *const gvar)
|
||||
{
|
||||
QString s;
|
||||
|
||||
if (g_variant_is_of_type(gvar, G_VARIANT_TYPE("s")))
|
||||
s = QString(g_variant_get_string(gvar, NULL));
|
||||
else
|
||||
{
|
||||
gchar *const text = g_variant_print(gvar, FALSE);
|
||||
s = QString(text);
|
||||
g_free(text);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void DeviceOptions::bind_samplerate(const QString &name,
|
||||
GVariant *const gvar_list)
|
||||
{
|
||||
GVariant *gvar_list_samplerates;
|
||||
|
||||
assert(gvar_list);
|
||||
|
||||
if ((gvar_list_samplerates = g_variant_lookup_value(gvar_list,
|
||||
"samplerate-steps", G_VARIANT_TYPE("at"))))
|
||||
{
|
||||
gsize num_elements;
|
||||
const uint64_t *const elements =
|
||||
(const uint64_t *)g_variant_get_fixed_array(
|
||||
gvar_list_samplerates, &num_elements, sizeof(uint64_t));
|
||||
|
||||
assert(num_elements == 3);
|
||||
|
||||
_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],
|
||||
bind(samplerate_double_getter, _sdi),
|
||||
bind(samplerate_double_setter, _sdi, _1))));
|
||||
|
||||
g_variant_unref(gvar_list_samplerates);
|
||||
}
|
||||
else if ((gvar_list_samplerates = g_variant_lookup_value(gvar_list,
|
||||
"samplerates", G_VARIANT_TYPE("at"))))
|
||||
{
|
||||
bind_enum(name, SR_CONF_SAMPLERATE,
|
||||
gvar_list_samplerates, print_samplerate);
|
||||
g_variant_unref(gvar_list_samplerates);
|
||||
}
|
||||
}
|
||||
|
||||
QString DeviceOptions::print_samplerate(GVariant *const gvar)
|
||||
{
|
||||
char *const s = sr_samplerate_string(
|
||||
g_variant_get_uint64(gvar));
|
||||
const QString qstring(s);
|
||||
g_free(s);
|
||||
return qstring;
|
||||
}
|
||||
|
||||
GVariant* DeviceOptions::samplerate_double_getter(
|
||||
const struct sr_dev_inst *sdi)
|
||||
{
|
||||
GVariant *const gvar = config_getter(sdi, SR_CONF_SAMPLERATE);
|
||||
|
||||
if(!gvar)
|
||||
return NULL;
|
||||
|
||||
GVariant *const gvar_double = g_variant_new_double(
|
||||
g_variant_get_uint64(gvar));
|
||||
|
||||
g_variant_unref(gvar);
|
||||
|
||||
return gvar_double;
|
||||
}
|
||||
|
||||
void DeviceOptions::samplerate_double_setter(
|
||||
struct sr_dev_inst *sdi, GVariant *value)
|
||||
{
|
||||
GVariant *const gvar = g_variant_new_uint64(
|
||||
g_variant_get_double(value));
|
||||
config_setter(sdi, SR_CONF_SAMPLERATE, gvar);
|
||||
}
|
||||
|
||||
QString DeviceOptions::print_timebase(GVariant *const gvar)
|
||||
{
|
||||
uint64_t p, q;
|
||||
g_variant_get(gvar, "(tt)", &p, &q);
|
||||
return QString(sr_period_string(p * q));
|
||||
}
|
||||
|
||||
QString DeviceOptions::print_vdiv(GVariant *const gvar)
|
||||
{
|
||||
uint64_t p, q;
|
||||
g_variant_get(gvar, "(tt)", &p, &q);
|
||||
return QString(sr_voltage_string(p, q));
|
||||
}
|
||||
|
||||
} // binding
|
||||
} // prop
|
||||
} // pv
|
||||
|
@ -43,7 +43,7 @@ Bool::~Bool()
|
||||
{
|
||||
}
|
||||
|
||||
QWidget* Bool::get_widget(QWidget *parent)
|
||||
QWidget* Bool::get_widget(QWidget *parent, bool auto_commit)
|
||||
{
|
||||
if (_check_box)
|
||||
return _check_box;
|
||||
@ -58,6 +58,10 @@ QWidget* Bool::get_widget(QWidget *parent)
|
||||
g_variant_unref(value);
|
||||
}
|
||||
|
||||
if (auto_commit)
|
||||
connect(_check_box, SIGNAL(stateChanged(int)),
|
||||
this, SLOT(on_state_changed(int)));
|
||||
|
||||
return _check_box;
|
||||
}
|
||||
|
||||
@ -77,5 +81,11 @@ void Bool::commit()
|
||||
_check_box->checkState() == Qt::Checked));
|
||||
}
|
||||
|
||||
|
||||
void Bool::on_state_changed(int)
|
||||
{
|
||||
commit();
|
||||
}
|
||||
|
||||
} // prop
|
||||
} // pv
|
||||
|
@ -33,16 +33,21 @@ namespace prop {
|
||||
|
||||
class Bool : public Property
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
Bool(QString name, Getter getter, Setter setter);
|
||||
|
||||
virtual ~Bool();
|
||||
|
||||
QWidget* get_widget(QWidget *parent);
|
||||
QWidget* get_widget(QWidget *parent, bool auto_commit);
|
||||
bool labeled_widget() const;
|
||||
|
||||
void commit();
|
||||
|
||||
private slots:
|
||||
void on_state_changed(int);
|
||||
|
||||
private:
|
||||
QCheckBox *_check_box;
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ Double::~Double()
|
||||
{
|
||||
}
|
||||
|
||||
QWidget* Double::get_widget(QWidget *parent)
|
||||
QWidget* Double::get_widget(QWidget *parent, bool auto_commit)
|
||||
{
|
||||
if (_spin_box)
|
||||
return _spin_box;
|
||||
@ -73,6 +73,10 @@ QWidget* Double::get_widget(QWidget *parent)
|
||||
g_variant_unref(value);
|
||||
}
|
||||
|
||||
if (auto_commit)
|
||||
connect(_spin_box, SIGNAL(valueChanged(double)),
|
||||
this, SLOT(on_value_changed(double)));
|
||||
|
||||
return _spin_box;
|
||||
}
|
||||
|
||||
@ -86,5 +90,10 @@ void Double::commit()
|
||||
_setter(g_variant_new_double(_spin_box->value()));
|
||||
}
|
||||
|
||||
void Double::on_value_changed(double)
|
||||
{
|
||||
commit();
|
||||
}
|
||||
|
||||
} // prop
|
||||
} // pv
|
||||
|
@ -37,6 +37,8 @@ namespace prop {
|
||||
|
||||
class Double : public Property
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
Double(QString name, int decimals, QString suffix,
|
||||
boost::optional< std::pair<double, double> > range,
|
||||
@ -46,10 +48,13 @@ public:
|
||||
|
||||
virtual ~Double();
|
||||
|
||||
QWidget* get_widget(QWidget *parent);
|
||||
QWidget* get_widget(QWidget *parent, bool auto_commit);
|
||||
|
||||
void commit();
|
||||
|
||||
private slots:
|
||||
void on_value_changed(double);
|
||||
|
||||
private:
|
||||
const int _decimals;
|
||||
const QString _suffix;
|
||||
|
@ -40,6 +40,9 @@ Enum::Enum(QString name,
|
||||
_values(values),
|
||||
_selector(NULL)
|
||||
{
|
||||
for (vector< pair<GVariant*, QString> >::const_iterator i =
|
||||
_values.begin(); i != _values.end(); i++)
|
||||
g_variant_ref((*i).first);
|
||||
}
|
||||
|
||||
Enum::~Enum()
|
||||
@ -48,12 +51,14 @@ Enum::~Enum()
|
||||
g_variant_unref(_values[i].first);
|
||||
}
|
||||
|
||||
QWidget* Enum::get_widget(QWidget *parent)
|
||||
QWidget* Enum::get_widget(QWidget *parent, bool auto_commit)
|
||||
{
|
||||
if (_selector)
|
||||
return _selector;
|
||||
|
||||
GVariant *const value = _getter ? _getter() : NULL;
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
_selector = new QComboBox(parent);
|
||||
for (unsigned int i = 0; i < _values.size(); i++) {
|
||||
@ -65,6 +70,10 @@ QWidget* Enum::get_widget(QWidget *parent)
|
||||
|
||||
g_variant_unref(value);
|
||||
|
||||
if (auto_commit)
|
||||
connect(_selector, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(on_current_item_changed(int)));
|
||||
|
||||
return _selector;
|
||||
}
|
||||
|
||||
@ -82,5 +91,10 @@ void Enum::commit()
|
||||
_setter((GVariant*)_selector->itemData(index).value<void*>());
|
||||
}
|
||||
|
||||
void Enum::on_current_item_changed(int)
|
||||
{
|
||||
commit();
|
||||
}
|
||||
|
||||
} // prop
|
||||
} // pv
|
||||
|
@ -36,16 +36,21 @@ namespace prop {
|
||||
|
||||
class Enum : public Property
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
Enum(QString name, std::vector<std::pair<GVariant*, QString> > values,
|
||||
Getter getter, Setter setter);
|
||||
|
||||
virtual ~Enum();
|
||||
|
||||
QWidget* get_widget(QWidget *parent);
|
||||
QWidget* get_widget(QWidget *parent, bool auto_commit);
|
||||
|
||||
void commit();
|
||||
|
||||
private slots:
|
||||
void on_current_item_changed(int);
|
||||
|
||||
private:
|
||||
const std::vector< std::pair<GVariant*, QString> > _values;
|
||||
|
||||
|
@ -21,14 +21,31 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <QSpinBox>
|
||||
|
||||
#include "int.h"
|
||||
|
||||
using boost::optional;
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
#define INT8_MIN (-0x7f - 1)
|
||||
#define INT16_MIN (-0x7fff - 1)
|
||||
#define INT32_MIN (-0x7fffffff - 1)
|
||||
#define INT64_MIN (-0x7fffffffffffffff - 1)
|
||||
|
||||
#define INT8_MAX 0x7f
|
||||
#define INT16_MAX 0x7fff
|
||||
#define INT32_MAX 0x7fffffff
|
||||
#define INT64_MAX 0x7fffffffffffffff
|
||||
|
||||
#define UINT8_MAX 0xff
|
||||
#define UINT16_MAX 0xffff
|
||||
#define UINT32_MAX 0xffffffff
|
||||
#define UINT64_MAX 0xffffffffffffffff
|
||||
|
||||
namespace pv {
|
||||
namespace prop {
|
||||
@ -41,41 +58,145 @@ Int::Int(QString name,
|
||||
Property(name, getter, setter),
|
||||
_suffix(suffix),
|
||||
_range(range),
|
||||
_value(NULL),
|
||||
_spin_box(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Int::~Int()
|
||||
{
|
||||
if (_value)
|
||||
g_variant_unref(_value);
|
||||
}
|
||||
|
||||
QWidget* Int::get_widget(QWidget *parent)
|
||||
QWidget* Int::get_widget(QWidget *parent, bool auto_commit)
|
||||
{
|
||||
if (_spin_box)
|
||||
return _spin_box;
|
||||
int64_t int_val = 0, range_min = 0, range_max = 0;
|
||||
|
||||
_spin_box = new QSpinBox(parent);
|
||||
_spin_box->setSuffix(_suffix);
|
||||
if (_range)
|
||||
_spin_box->setRange((int)_range->first, (int)_range->second);
|
||||
if (_spin_box)
|
||||
return _spin_box;
|
||||
|
||||
GVariant *const value = _getter ? _getter() : NULL;
|
||||
if (value) {
|
||||
_spin_box->setValue((int)g_variant_get_int64(value));
|
||||
g_variant_unref(value);
|
||||
}
|
||||
if (_value)
|
||||
g_variant_unref(_value);
|
||||
|
||||
return _spin_box;
|
||||
_value = _getter ? _getter() : NULL;
|
||||
if (!_value)
|
||||
return NULL;
|
||||
|
||||
_spin_box = new QSpinBox(parent);
|
||||
_spin_box->setSuffix(_suffix);
|
||||
|
||||
const GVariantType *const type = g_variant_get_type(_value);
|
||||
assert(type);
|
||||
|
||||
if (g_variant_type_equal(type, G_VARIANT_TYPE_BYTE))
|
||||
{
|
||||
int_val = g_variant_get_byte(_value);
|
||||
range_min = 0, range_max = UINT8_MAX;
|
||||
}
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT16))
|
||||
{
|
||||
int_val = g_variant_get_int16(_value);
|
||||
range_min = INT16_MIN, range_max = INT16_MAX;
|
||||
}
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT16))
|
||||
{
|
||||
int_val = g_variant_get_uint16(_value);
|
||||
range_min = 0, range_max = UINT16_MAX;
|
||||
}
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT32))
|
||||
{
|
||||
int_val = g_variant_get_int32(_value);
|
||||
range_min = INT32_MIN, range_max = INT32_MAX;
|
||||
}
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT32))
|
||||
{
|
||||
int_val = g_variant_get_uint32(_value);
|
||||
range_min = 0, range_max = UINT32_MAX;
|
||||
}
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT64))
|
||||
{
|
||||
int_val = g_variant_get_int64(_value);
|
||||
range_min = INT64_MIN, range_max = INT64_MAX;
|
||||
}
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT64))
|
||||
{
|
||||
int_val = g_variant_get_uint64(_value);
|
||||
range_min = 0, range_max = UINT64_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unexpected value type.
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// @todo Sigrok supports 64-bit quantities, but Qt does not have a
|
||||
// standard widget to allow the values to be modified over the full
|
||||
// 64-bit range on 32-bit machines. To solve the issue we need a
|
||||
// custom widget.
|
||||
|
||||
range_min = max(range_min, (int64_t)INT_MIN);
|
||||
range_max = min(range_max, (int64_t)INT_MAX);
|
||||
|
||||
if (_range)
|
||||
_spin_box->setRange((int)_range->first, (int)_range->second);
|
||||
else
|
||||
_spin_box->setRange((int)range_min, (int)range_max);
|
||||
|
||||
_spin_box->setValue((int)int_val);
|
||||
|
||||
if (auto_commit)
|
||||
connect(_spin_box, SIGNAL(valueChanged(int)),
|
||||
this, SLOT(on_value_changed(int)));
|
||||
|
||||
return _spin_box;
|
||||
}
|
||||
|
||||
void Int::commit()
|
||||
{
|
||||
assert(_setter);
|
||||
assert(_setter);
|
||||
|
||||
if (!_spin_box)
|
||||
return;
|
||||
if (!_spin_box)
|
||||
return;
|
||||
|
||||
_setter(g_variant_new_int64(_spin_box->value()));
|
||||
assert(_value);
|
||||
|
||||
GVariant *new_value = NULL;
|
||||
const GVariantType *const type = g_variant_get_type(_value);
|
||||
assert(type);
|
||||
|
||||
if (g_variant_type_equal(type, G_VARIANT_TYPE_BYTE))
|
||||
new_value = g_variant_new_byte(_spin_box->value());
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT16))
|
||||
new_value = g_variant_new_int16(_spin_box->value());
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT16))
|
||||
new_value = g_variant_new_uint16(_spin_box->value());
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT32))
|
||||
new_value = g_variant_new_int32(_spin_box->value());
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT32))
|
||||
new_value = g_variant_new_int32(_spin_box->value());
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT64))
|
||||
new_value = g_variant_new_int64(_spin_box->value());
|
||||
else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT64))
|
||||
new_value = g_variant_new_uint64(_spin_box->value());
|
||||
else
|
||||
{
|
||||
// Unexpected value type.
|
||||
assert(0);
|
||||
}
|
||||
|
||||
assert(new_value);
|
||||
|
||||
g_variant_unref(_value);
|
||||
g_variant_ref(new_value);
|
||||
_value = new_value;
|
||||
|
||||
_setter(new_value);
|
||||
}
|
||||
|
||||
void Int::on_value_changed(int)
|
||||
{
|
||||
commit();
|
||||
}
|
||||
|
||||
} // prop
|
||||
|
@ -37,6 +37,8 @@ namespace prop {
|
||||
|
||||
class Int : public Property
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
Int(QString name, QString suffix,
|
||||
boost::optional< std::pair<int64_t, int64_t> > range,
|
||||
@ -44,14 +46,18 @@ public:
|
||||
|
||||
virtual ~Int();
|
||||
|
||||
QWidget* get_widget(QWidget *parent);
|
||||
QWidget* get_widget(QWidget *parent, bool auto_commit);
|
||||
|
||||
void commit();
|
||||
|
||||
private slots:
|
||||
void on_value_changed(int);
|
||||
|
||||
private:
|
||||
const QString _suffix;
|
||||
const boost::optional< std::pair<int64_t, int64_t> > _range;
|
||||
|
||||
GVariant *_value;
|
||||
QSpinBox *_spin_box;
|
||||
};
|
||||
|
||||
|
@ -36,8 +36,10 @@ class QWidget;
|
||||
namespace pv {
|
||||
namespace prop {
|
||||
|
||||
class Property
|
||||
class Property : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
typedef boost::function<GVariant* ()> Getter;
|
||||
typedef boost::function<void (GVariant*)> Setter;
|
||||
@ -48,7 +50,8 @@ protected:
|
||||
public:
|
||||
const QString& name() const;
|
||||
|
||||
virtual QWidget* get_widget(QWidget *parent) = 0;
|
||||
virtual QWidget* get_widget(QWidget *parent,
|
||||
bool auto_commit = false) = 0;
|
||||
virtual bool labeled_widget() const;
|
||||
|
||||
virtual void commit() = 0;
|
||||
|
77
DSLogic-gui/pv/prop/string.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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 <assert.h>
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
namespace pv {
|
||||
namespace prop {
|
||||
|
||||
String::String(QString name,
|
||||
Getter getter,
|
||||
Setter setter) :
|
||||
Property(name, getter, setter),
|
||||
_line_edit(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
QWidget* String::get_widget(QWidget *parent, bool auto_commit)
|
||||
{
|
||||
if (_line_edit)
|
||||
return _line_edit;
|
||||
|
||||
GVariant *const value = _getter ? _getter() : NULL;
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
_line_edit = new QLineEdit(parent);
|
||||
_line_edit->setText(QString::fromUtf8(
|
||||
g_variant_get_string(value, NULL)));
|
||||
g_variant_unref(value);
|
||||
|
||||
if (auto_commit)
|
||||
connect(_line_edit, SIGNAL(textEdited(const QString&)),
|
||||
this, SLOT(on_text_edited(const QString&)));
|
||||
|
||||
return _line_edit;
|
||||
}
|
||||
|
||||
void String::commit()
|
||||
{
|
||||
assert(_setter);
|
||||
|
||||
if (!_line_edit)
|
||||
return;
|
||||
|
||||
QByteArray ba = _line_edit->text().toLocal8Bit();
|
||||
_setter(g_variant_new_string(ba.data()));
|
||||
}
|
||||
|
||||
void String::on_text_edited(const QString&)
|
||||
{
|
||||
commit();
|
||||
}
|
||||
|
||||
} // prop
|
||||
} // pv
|
52
DSLogic-gui/pv/prop/string.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of the PulseView project.
|
||||
*
|
||||
* Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
*
|
||||
* 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_PROP_STRING_H
|
||||
#define DSLOGIC_PV_PROP_STRING_H
|
||||
|
||||
#include "property.h"
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
namespace pv {
|
||||
namespace prop {
|
||||
|
||||
class String : public Property
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
String(QString name, Getter getter, Setter setter);
|
||||
|
||||
QWidget* get_widget(QWidget *parent, bool auto_commit);
|
||||
|
||||
void commit();
|
||||
|
||||
private slots:
|
||||
void on_text_edited(const QString&);
|
||||
|
||||
private:
|
||||
QLineEdit *_line_edit;
|
||||
};
|
||||
|
||||
} // prop
|
||||
} // pv
|
||||
|
||||
#endif // DSLOGIC_PV_PROP_STRING_H
|