diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..604a5004
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,43 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+**IMPORTANT:** Always unplug and replug the scope if used before with a different application, e.g. sigrok or the original Hantek software.
+
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Select '....'
+3. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots or a video to help explain your problem.
+
+**Computer environment (please complete the following information):**
+ - OpenHantek version: [use always the latest commit, e.g. *release v2.03, commit 1a2b3c4, ...*]
+ - OS: [e.g. *linux, macOS, windows, ...*]
+ - Distribution, version: [e.g. *debian stable amd64, ...*]
+ - Video hardware: [e.g. *Intel Xeon ... Integrated Graphics*]
+ - OpenGL version: [e.g. *OpenGL 4.5, Mesa 19.0.3*]
+ - Qt version: [e.g. *Qt 5.11.x*]
+ - C++ compiler version: [e.g. *gcc 8.3.x*]
+
+**Scope device (please complete the following information):**
+ - Device [e.g. *Hantek 6022BE, ...*]
+ - Program top line [e.g. *OpenHantek6022 (Build ...) - Device ... (FW ...)*]
+ - Input signal: [e.g. *calibration out 1 kHz, sine wave 1 Veff @ 50 Hz, ...*]
+ - Probe setting: [e.g. *no probe, probe X1, probe X10, ...*]
+
+**Additional context**
+Add any other context about the problem here, e.g. the program output if started in a console like xterm.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 00000000..bbcbbe7d
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.gitignore b/.gitignore
index 8041f871..b2d98cb5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,16 @@
.o
.so
.*~
+*~
+*.orig
+*.new
+*.diff
CMakeLists.txt.user
-build/
+build*
firmware/hex
+*.json
+*.kate-swp
+.directory
+*.autosave
+ui_*.h
+*.sh
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..09eadbb9
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "macdeployqtfix"]
+ path = utils/macdeployqtfix
+ url = https://github.com/iltommi/macdeployqtfix
diff --git a/.travis.yml b/.travis.yml
index ab3cb97f..1f4a9b02 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,38 +1,67 @@
language: cpp
-dist: xenial
+dist: bionic
addons:
apt:
packages:
- qtbase5-dev
- - qttools5-dev-tools
+ - qttools5-dev
- libqt5opengl5-dev
- libusb-1.0-0-dev
- libfftw3-dev
+ - binutils-dev
+ - rpm
matrix:
include:
- compiler: gcc
- env: CMAKE_CXX_COMPILER=g++-5
+ env: CMAKE_CXX_COMPILER=/usr/bin/g++
os: linux
- compiler: clang
env: CMAKE_CXX_COMPILER=/usr/bin/clang++
os: osx
-
+
before_install:
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; brew install qt5 fftw binutils; export CMAKE_PREFIX_PATH=$(brew --prefix qt5); fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ brew update; brew install qt5 fftw binutils create-dmg ;
+ export CMAKE_PREFIX_PATH=$(brew --prefix qt5) ;
+ echo "CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" ;
+ fi
- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then pip install cmake --user; fi
before_script:
- mkdir build
- cd build
- - cmake -DCMAKE_CXX_COMPILER=$CMAKE_CXX_COMPILER -DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH ../
+ - cmake -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} ../
script:
- - make -j4
+ - make -j4 # create either a bin or a bundle (.app) - depending on openhantek/CMakeLists.txt
+ - sudo make -j4 package # simply pack the binary, otherwise populate the bundle below
+ - if test -d openhantek/OpenHantek.app; then
+ export PATH=${CMAKE_PREFIX_PATH}/bin:${PATH} ;
+ cd openhantek ;
+ macdeployqt OpenHantek.app -always-overwrite -verbose=1 ;
+ python ../../utils/macdeployqtfix/macdeployqtfix.py OpenHantek.app/Contents/MacOS/OpenHantek ${CMAKE_PREFIX_PATH} ;
+ create-dmg --volname OpenHantek --volicon ../../openhantek/res/images/openhantek.icns --window-pos 200 120 --window-size 800 400 --icon-size 100 --icon "OpenHantek.app" 200 190 --hide-extension "OpenHantek.app" --app-drop-link 600 185 --eula ../../LICENSE OpenHantek.dmg OpenHantek.app ;
+ cd .. ;
+ else
+ ls -l packages ;
+ true;
+ fi
+ - ls -l openhantek || true
before_deploy:
- - sudo make package
+ - if test -d openhantek/OpenHantek.app; then
+ cd openhantek ;
+ sudo tar -cvzf ../packages/openhantek_*_osx_*.tar.gz OpenHantek.app ;
+ if test -f OpenHantek.dmg ; then
+ sudo mv OpenHantek.dmg ../packages/$(basename ../packages/openhantek_*_osx_*.tar.gz .tar.gz).dmg ;
+ fi ;
+ cd .. ;
+ else
+ true;
+ fi
+ - ls -l packages || true
deploy:
provider: releases
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 00000000..2302423a
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,170 @@
+3.1.3
+2020-09-30
+RPM build improvements
+New command line option --fontsize
+Display horizontal trigger level line when marker is moved
+Make smooth trigger setting persistent
+
+3.1.2
+2020-07-29
+Small improvements for FreeBSD
+Hide Windows console
+
+3.1.1
+2020-06-30
+Refresh button to restart roll mode trace
+Help menu link to AC modification howto
+Minor robustness improvements
+
+3.1.1-rc3
+2020-06-26
+Real roll mode for slow sample rates
+
+3.1.1-rc2
+2020-06-23
+Scroll wheel moves the markers
+Configuration menu parameter to use AC coupling HW modification
+
+3.1.1-rc1
+2020-06-20
+Slow timebases up to 10s/div
+Near real time screen updates with trigger mode NONE
+Screenshot and hardcopy are identical to the screen content
+Force OpenGL SL version (option --useGLSL120 or --useGLSL150)
+
+3.1.0
+2020-05-08
+Demo mode without scope hardware (option -d or --demoMode)
+Support for high-dpi displays
+Improved pdf readability
+Russian translation
+
+3.0.4
+2020-04-13
+Better marker setting/removing
+Fix sample rate spinbox handling
+Fix race condition when switching 1ch/2ch
+Persistent calibration out frequency
+FW 0206
+Updated DDS120 FW 0100 (supports more calibration out frequencies)
+Spanish translation
+
+3.0.3
+2020-03-17
+FW 0205
+Fix histogram issue when switching TY -> XY
+
+3.0.2
+2020-03-01
+Apply realtime prio and scheduler
+Histogram for TY voltage traces
+Variable probe gain setting
+French translation complete
+
+3.0.1
+2019-12-13
+More robust USB handling for all OSs
+Improve manipulation and export of frozen or single traces
+Export XY display
+Automatic icon selection for light/dark themes
+Eye candy
+Automatic start after FW upload
+
+3.0.0
+2019-11-15
+Major changes:
+Support for Sainsmart DDS120
+Support for Hantek6022 AC HW modification
+Update to FW 0203
+MacOSX bundle
+Measure duty cycle of triggered trace
+New versioning scheme
+
+v2.16
+2019-10-15
+Major changes from v2.16-rc1:
+Display measured width of triggered pulse in top line.
+Set OpenGL ES as default for Raspberry Pi.
+
+v2.16-rc1
+2019-10-11
+Major changes from v2.15:
+Fix #26 (array overrun during fast increasing of timebase setting)
+
+v2.15 - withdrawn due to #26
+2019-10-05
+Major changes from v2.14:
+Automatic translation (qt linguist),
+better automatic versioning (commit date & build number),
+Sinc interpolation for fast timebase settings,
+modification for FreeBSD compiling.
+
+v2.14
+2019-09-08
+Major changes from v2.13:
+Vpp measure, more oversampling, faster display refresh,
+alternating trigger, faster trigger (and new smooth trigger mode),
+add support for Voltcraft DSO-2020 USB oscilloscope.
+
+v2.13
+2019-08-09
+Major changes from v2.12:
+User manual, new icons.
+Calculate and display dB of AC value.
+
+v2.12
+2019-07-07
+Major changes from v2.11:
+Better frequency detection, Gauss window,
+normalise all windows to 0 dBV display,
+new math mode CH1*CH2.
+
+v2.11
+2019-06-28
+Major changes from v2.10:
+New math mode, calculate AC part of CH1/CH2
+
+v2.10
+2019-06-10
+Major changes from v2.09:
+Use new FW 0202 that allows more and better structured sample rates,
+reload the correct FW version if the wrong version was loaded before.
+
+v2.09
+2019-05-25
+Major changes from v2.08:
+Add slower timebases 20, 50, 100 ms/div with increased samplesize.
+
+v2.08
+2019-05-24
+Major changes from v2.07:
+This release fixes the quite unstable spectrum display. The annoying amplitude jitter has gone.
+
+v2.07
+2019-05-22
+Major changes from v2.06:
+First complete free open source release.
+No longer dependent on nonfree Hantek firmware.
+
+v2.06
+2019-05-14
+Major changes from v2.05:
+Refactor triggering, move from postprocessing chain into earlier hantekdsocontrol.
+Last release with 2090,2150, 2250 and 5200 support.
+
+v2.05
+2019-05-10
+Major changes from v2.03:
+Increase sample size to 20000, better trigger modes
+
+v2.04 - removed due to issues with 10X probe display
+
+v2.03
+2019-05-05
+Major changes from v2.02:
+New checkbox for 10X probes.
+
+v2.02
+2019-04-26
+Major changes from v2.03:
+1st binary release after transfer to OpenHantek/OpenHantek6022
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f4d6c269..4cf7eb93 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-project(OpenHantekProject)
+project(OpenHantek)
set(OpenGL_GL_PREFERENCE GLVND)
@@ -15,38 +15,65 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/")
INCLUDE_DIRECTORIES(".")
-# Use CPack to make deb/rpm/zip/exe installer packages
+# Use CPack to make tgz/deb/rpm/zip installer packages
include(cmake/CPackInfos.cmake)
+if(MSVC)
+ add_compile_options(/W4 -D_CRT_SECURE_NO_WARNINGS)
+else()
+ add_compile_options(-Wall -Wextra -pedantic)
+endif()
+
+# Silence nasty warnings "parameter passing for argument of type ... changed in GCC 7.1"
+if(CMAKE_COMPILER_IS_GNUCXX)
+ add_compile_options(-Wno-psabi)
+endif()
+
+# enable extra feature(s)
+if( ${CMAKE_VERSION} VERSION_LESS "3.12.0" ) # deprecated, but still used in older Ubuntu releases
+ # Enable C++ standard library hardening -> cheap range checks for C++ arrays, vectors, and strings.
+ add_definitions( -D_GLIBCXX_ASSERTIONS )
+ add_definitions( -D_USE_MATH_DEFINES )
+ if ( DEFINED HANTEK_AC )
+ add_definitions( -DHANTEK_AC )
+ endif()
+else() # 'add_compile_definitions()' was introduced with CMake 3.12
+ add_compile_definitions( _GLIBCXX_ASSERTIONS )
+ add_compile_definitions( _USE_MATH_DEFINES )
+ if ( DEFINED HANTEK_AC )
+ add_compile_definitions( HANTEK_AC )
+ endif()
+endif()
+
+# show all compile options and definitions
+get_directory_property( CompOpts COMPILE_OPTIONS )
+message( "-- COMPILE_OPTIONS: ${CompOpts}" )
+get_directory_property( CompDefs COMPILE_DEFINITIONS )
+message( "-- COMPILE_DEFINITIONS: ${CompDefs}" )
+
# Qt Widgets based Gui with OpenGL canvas
add_subdirectory(openhantek)
if (WIN32)
- install(FILES COPYING readme.md DESTINATION ".")
-else()
- add_subdirectory(firmware EXCLUDE_FROM_ALL)
-endif()
-
-if("${CMAKE_SYSTEM}" MATCHES "Linux")
- if(EXISTS "/lib/udev/rules.d/")
- install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/firmware/60-hantek.rules"
- DESTINATION "/lib/udev/rules.d/" COMPONENT Runtime)
- else()
- message(WARNING "Could not find udev rules directory (/lib/udev/rules.d/), skipping installation of udev rules.")
- endif()
+ install(
+ FILES CHANGELOG LICENSE README
+ DESTINATION "."
+ )
endif()
# Add auxiliary files to the project, so that these files appear in VisualStudio/QtCreator
file(GLOB_RECURSE MDFILES "docs/*.md" "openhantek/*.md")
-add_custom_target(readme SOURCES readme.md ${MDFILES})
-
-# Add "cppcheck" command
-add_custom_target(cppcheck COMMAND "cppcheck --enable=all -I \"${CMAKE_CURRENT_LIST_DIR}/openhantek/src\" -q ${SRC} --template=\"{file}:{line}: {severity}: {message}\"")
+add_custom_target(
+ readme
+ SOURCES CHANGELOG LICENSE README readme.md ${MDFILES}
+)
# Add "doc" target to build the documentation.
find_package(Doxygen QUIET)
if (DOXYGEN_FOUND)
- add_custom_target(doc
+ add_custom_target(
+ doc
COMMAND "${CMAKE_COMMAND} -E remove_directory html"
- COMMAND "${DOXYGEN_EXECUTABLE} Doxyfile" WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}")
+ COMMAND "${DOXYGEN_EXECUTABLE} Doxyfile" WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
+ )
endif()
diff --git a/Doxyfile b/Doxyfile
index 6238fedd..a77c7776 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -309,7 +309,7 @@ AUTOLINK_SUPPORT = YES
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
-BUILTIN_STL_SUPPORT = NO
+BUILTIN_STL_SUPPORT = YES
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
@@ -409,25 +409,25 @@ LOOKUP_CACHE_SIZE = 0
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
-EXTRACT_ALL = NO
+EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
-EXTRACT_PRIVATE = NO
+EXTRACT_PRIVATE = YES
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
-EXTRACT_PACKAGE = NO
+EXTRACT_PACKAGE = YES
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
-EXTRACT_STATIC = NO
+EXTRACT_STATIC = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO,
@@ -1371,7 +1371,7 @@ DISABLE_INDEX = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_TREEVIEW = NO
+GENERATE_TREEVIEW = YES
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
@@ -1683,7 +1683,7 @@ USE_PDFLATEX = YES
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_BATCHMODE = NO
+LATEX_BATCHMODE = YES
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..e7eb6476
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,2 @@
+This work is released under the terms of the GNU General Public License, version 3.
+The full text of the license can be found at https://www.gnu.org/licenses/gpl-3.0.html
diff --git a/README b/README
new file mode 100644
index 00000000..47d14db7
--- /dev/null
+++ b/README
@@ -0,0 +1,4 @@
+OpenHantek is an oscilloscope software for Hantek DSO-6022 USB devices.
+The source code and detailed developer documentation is available at:
+https://github.com/OpenHantek/OpenHantek6022 (oscilloscope software)
+https://github.com/Ho-Ro/Hantek6022API (hardware, firmware and tools)
diff --git a/appveyor.yml b/appveyor.yml
index ee1e7598..39101caa 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -7,17 +7,41 @@ image:
shallow_clone: true
before_build:
- - set qtpath="C:\Qt\5.11\msvc2015_64"
+ - set qtpath64="C:\Qt\5.11\msvc2015_64"
- set arch64=x64
- set dir64=build_x64
- md %dir64%
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %arch64%
- - cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_PREFIX_PATH=%qtpath% -DCMAKE_BUILD_TYPE=%configuration% -B%dir64% -H.
+ - cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_PREFIX_PATH=%qtpath64% -DCMAKE_BUILD_TYPE=%configuration% -B%dir64% -H.
+
+ - set qtpath32="C:\Qt\5.11\msvc2015"
+ - set arch32=x86
+ - set dir32=build_x86
+
+ - md %dir32%
+ - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %arch32%
+ - cmake -G "Visual Studio 14 2015" -DCMAKE_PREFIX_PATH=%qtpath32% -DCMAKE_BUILD_TYPE=%configuration% -B%dir32% -H.
build_script:
- cmake --build %dir64% --config %configuration% --target package
+ - cmake --build %dir32% --config %configuration% --target package
artifacts:
- path: $(dir64)\openhantek\$(configuration)
- name: OpenHantek-$(arch64)-$(configuration)-b$(APPVEYOR_BUILD_NUMBER)
+ name: OpenHantek-Win-$(arch64)-$(configuration)-b$(APPVEYOR_BUILD_NUMBER)
+ - path: $(dir32)\openhantek\$(configuration)
+ name: OpenHantek-Win-$(arch32)-$(configuration)-b$(APPVEYOR_BUILD_NUMBER)
+
+deploy:
+ - tag: $(APPVEYOR_REPO_TAG_NAME)
+ provider: GitHub
+ auth_token:
+ secure: 4TSFa7zTbxPVDkS9pGWO0BIPD9r2NnnHGe03pg5rjEuvSH5pntkmMdLM7MePJLma
+ artifact: /.*\.zip/
+ draft: true
+ prerelease: true
+ force_update: true
+ on:
+ #branch: master # release from master branch only
+ APPVEYOR_REPO_TAG: true # deploy on tag push only
diff --git a/cmake/CPackInfos.cmake b/cmake/CPackInfos.cmake
index f31c0d5d..825463ab 100644
--- a/cmake/CPackInfos.cmake
+++ b/cmake/CPackInfos.cmake
@@ -1,7 +1,7 @@
-# This file configures CPack. We setup a version number that contains
-# the current git revision if git is found. A zip file is created on
-# all platforms. Additionally an NSIS Installer exe is created on windows
-# and a .sh installer file for linux.
+# This file configures CPack.
+# A tgz, deb and rpm file is created for linux (tgz and deb tested on debian stretch and buster).
+# A tgz file is created for osx (not tested).
+# A zip file and an NSIS Installer exe is created on windows (not tested).
find_package(Git QUIET)
@@ -14,11 +14,21 @@ if (GIT_EXECUTABLE AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
+# message( STATUS "VCS_REVISION: ${VCS_REVISION}" )
if(NOT DEFINED CMD_RESULT)
set(VCS_BRANCH "master")
+ set(GIT_COMMIT_HASH "1")
set(VCS_REVISION "na")
else()
+ execute_process(
+ COMMAND git log -1 --format=%h
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ OUTPUT_VARIABLE GIT_COMMIT_HASH
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ # message( STATUS "GIT_COMMIT_HASH: ${GIT_COMMIT_HASH}" )
+
execute_process(
COMMAND ${GIT_EXECUTABLE} status
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
@@ -33,7 +43,7 @@ else()
string(REPLACE " " ";" DESCRIBE_STATUS ${DESCRIBE_STATUS})
list(GET DESCRIBE_STATUS 2 VCS_BRANCH)
- message(STATUS "Version: ${VCS_BRANCH}/${VCS_REVISION}")
+ # message(STATUS "Branch: ${VCS_BRANCH}") # /${VCS_REVISION}")
execute_process(
COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url
@@ -41,8 +51,9 @@ else()
RESULT_VARIABLE CMD_RESULT
OUTPUT_VARIABLE VCS_URL
OUTPUT_STRIP_TRAILING_WHITESPACE
- )
-
+ )
+ # message( STATUS "VCS_URL: ${VCS_URL}")
+
set(ENV{LANG} "en_US")
if(GIT_VERSION_STRING VERSION_LESS 2.6)
set(CHANGELOG "")
@@ -53,73 +64,107 @@ else()
RESULT_VARIABLE CMD_RESULT
OUTPUT_VARIABLE CHANGELOG
OUTPUT_STRIP_TRAILING_WHITESPACE
- )
+ )
endif()
file(WRITE "${CMAKE_BINARY_DIR}/changelog" "${CHANGELOG}")
endif()
-string(TIMESTAMP DATE_VERSION "%d.%m.%Y")
-string(TIMESTAMP CURRENT_TIME "%d.%m.%Y %H:%M")
+string(TIMESTAMP DATE_VERSION "%Y%m%d")
+string(TIMESTAMP CURRENT_TIME "%Y%m%d_%H:%M")
if (UNIX)
+ execute_process(
+ COMMAND uname -m
+ WORKING_DIRECTORY "."
+ OUTPUT_VARIABLE CPACK_ARCH
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
set(CPACK_PACKAGING_INSTALL_PREFIX "/usr")
- set(CPACK_GENERATOR STGZ)
- if (NOT APPLE)
- set(CPACK_GENERATOR ${CPACK_GENERATOR} ZIP)
- find_program(LSB_RELEASE lsb_release)
- execute_process(COMMAND ${LSB_RELEASE} -is
- OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT
- OUTPUT_STRIP_TRAILING_WHITESPACE
+ set(CPACK_GENERATOR TGZ)
+
+ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ set(CPACK_TARGET "")
+ set(CPACK_GENERATOR ${CPACK_GENERATOR} DEB RPM)
+ install(
+ FILES utils/udev_rules/60-hantek.rules
+ DESTINATION lib/udev/rules.d
+ )
+ elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ set(CPACK_TARGET "freebsd_")
+ set(CPACK_PACKAGING_INSTALL_PREFIX "/usr/local")
+ install(
+ FILES utils/devd_rules_freebsd/openhantek.conf
+ DESTINATION etc/devd
)
- if (LSB_RELEASE_ID_SHORT MATCHES "Ubuntu")
- set(CPACK_GENERATOR ${CPACK_GENERATOR} DEB)
- else()
- set(CPACK_GENERATOR ${CPACK_GENERATOR} RPM)
- endif()
- endif()
+ elseif(APPLE)
+ set(CPACK_TARGET "osx_")
+ endif()
+
+ # install documentation
+ FILE(GLOB PDF "docs/*.pdf")
+ install(
+ FILES CHANGELOG LICENSE README ${PDF}
+ DESTINATION share/doc/openhantek
+ )
+ # install application starter and icons
+ install(
+ FILES utils/applications/OpenHantek.desktop
+ DESTINATION share/applications
+ )
+ install(
+ FILES openhantek/res/images/OpenHantek.png
+ DESTINATION share/icons/hicolor/48x48/apps
+ )
+ install(
+ FILES openhantek/res/images/OpenHantek.svg
+ DESTINATION share/icons/hicolor/scalable/apps
+ )
+
elseif(WIN32)
- set(CPACK_GENERATOR NSIS)
+ set(CPACK_TARGET "win_")
+ set(CPACK_GENERATOR ${CPACK_GENERATOR} ZIP NSIS)
+ if ((MSVC AND CMAKE_GENERATOR MATCHES "Win64+") OR (CMAKE_SIZEOF_VOID_P EQUAL 8))
+ set(CPACK_ARCH "amd64")
+ else()
+ set(CPACK_ARCH "x86")
+ endif()
endif()
-set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
+message(STATUS "Package: ${CPACK_GENERATOR}")
+message(STATUS "Architecture: ${CPACK_ARCH}")
+
+set(CPACK_PACKAGE_NAME "openhantek")
string(TOLOWER ${CPACK_PACKAGE_NAME} CPACK_PACKAGE_NAME)
-set(CPACK_PACKAGE_VERSION "${DATE_VERSION}_${VCS_REVISION}")
+set(CPACK_PACKAGE_VERSION "${DATE_VERSION}-${VCS_REVISION}")
set(CPACK_PACKAGE_CONTACT "contact@openhantek.org")
set(CPACK_PACKAGE_VENDOR "OpenHantek Community")
-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Digital oscilloscope software for Hantek USB hardware")
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Digital oscilloscope software for Hantek DSO6022 USB hardware")
set(CPACK_PACKAGE_DESCRIPTION "OpenHantek is an oscilloscope software for\nVoltcraft/Darkwire/Protek/Acetech/Hantek USB devices")
set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/readme.md")
-if (EXISTS "${CMAKE_SOURCE_DIR}/COPYING")
- set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
+if (EXISTS "${CMAKE_SOURCE_DIR}/LICENSE")
+ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
endif()
-# Linux DEB+RPM
-set(CPACK_DEBIAN_PACKAGE_SECTION "net")
-set(CPACK_ARCH)
-IF ((MSVC AND CMAKE_GENERATOR MATCHES "Win64+") OR (CMAKE_SIZEOF_VOID_P EQUAL 8))
- set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
- set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64")
- set(CPACK_ARCH "x86_64")
-else()
- set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i586")
- set(CPACK_RPM_PACKAGE_ARCHITECTURE "i586")
- set(CPACK_ARCH "x86")
-endif()
set(CPACK_STRIP_FILES 1)
include(CMakeDetermineSystem)
-# Linux RPM
+# Linux DEB (tested on debian stretch and buster)
+# Architecture for package and file name are automatically detected
+set(CPACK_DEBIAN_PACKAGE_SECTION "electronics")
+set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
+set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
+
+# Linux RPM (not tested on debian)
+# Architecture for package and file name are automatically detected
set(CPACK_RPM_PACKAGE_RELOCATABLE NO)
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2+")
set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION})
-set(CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase-gui%{?_isa} >= 5.4, qt5-qttranslations%{?_isa}")
set(CPACK_RPM_CHANGELOG_FILE "${CMAKE_BINARY_DIR}/changelog")
-
-set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
+set(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
-set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-1.${CPACK_ARCH}")
+set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}-1_${CPACK_TARGET}${CPACK_ARCH}")
set(CPACK_PACKAGE_INSTALL_DIRECTORY ".")
SET(CPACK_OUTPUT_FILE_PREFIX packages)
diff --git a/cmake/OpenHantekBundleInfo.plist.in b/cmake/OpenHantekBundleInfo.plist.in
new file mode 100644
index 00000000..440b841d
--- /dev/null
+++ b/cmake/OpenHantekBundleInfo.plist.in
@@ -0,0 +1,38 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ ${MACOSX_BUNDLE_EXECUTABLE_NAME}
+ CFBundleGetInfoString
+ ${MACOSX_BUNDLE_INFO_STRING}
+ CFBundleIconFile
+ ${MACOSX_BUNDLE_ICON_FILE}
+ CFBundleIdentifier
+ ${MACOSX_BUNDLE_GUI_IDENTIFIER}
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleLongVersionString
+ ${MACOSX_BUNDLE_LONG_VERSION_STRING}
+ CFBundleName
+ ${MACOSX_BUNDLE_BUNDLE_NAME}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ ${MACOSX_BUNDLE_BUNDLE_VERSION}
+ CSResourcesFileMapped
+
+ NSHumanReadableCopyright
+ ${MACOSX_BUNDLE_COPYRIGHT}
+ NSPrincipalClass
+ NSApplication
+ NSHighResolutionCapable
+ True
+
+
diff --git a/docs/CNAME b/docs/CNAME
deleted file mode 100644
index b9fc74bc..00000000
--- a/docs/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-openhantek.org
diff --git a/docs/HANTEK6022_AC_Modification.odt b/docs/HANTEK6022_AC_Modification.odt
new file mode 100644
index 00000000..4f4252bf
Binary files /dev/null and b/docs/HANTEK6022_AC_Modification.odt differ
diff --git a/docs/HANTEK6022_AC_Modification.pdf b/docs/HANTEK6022_AC_Modification.pdf
new file mode 100644
index 00000000..c4830825
Binary files /dev/null and b/docs/HANTEK6022_AC_Modification.pdf differ
diff --git a/docs/OpenHantek6022_User_Manual.odt b/docs/OpenHantek6022_User_Manual.odt
new file mode 100644
index 00000000..c6178ba1
Binary files /dev/null and b/docs/OpenHantek6022_User_Manual.odt differ
diff --git a/docs/OpenHantek6022_User_Manual.pdf b/docs/OpenHantek6022_User_Manual.pdf
new file mode 100644
index 00000000..ea3901b3
Binary files /dev/null and b/docs/OpenHantek6022_User_Manual.pdf differ
diff --git a/docs/OpenHantek6022_zadig_Win10.pdf b/docs/OpenHantek6022_zadig_Win10.pdf
new file mode 100644
index 00000000..ca1540a2
Binary files /dev/null and b/docs/OpenHantek6022_zadig_Win10.pdf differ
diff --git a/docs/_config.yml b/docs/_config.yml
index f59c689e..3dd385df 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -1,8 +1,8 @@
-title: Openhantek
-description: Software for Hantek and compatible (Voltcraft/Darkwire/Protek/Acetech) USB digital signal oscilloscopes
-google_analytics:
+title: OpenHantek 6022
+description: Software for Hantek 6022 and compatible (Voltcraft/Darkwire/Protek/Acetech) USB digital signal oscilloscopes
+google_analytics:
show_downloads: true
-theme: jekyll-theme-slate
+theme: jekyll-theme-leap-day
gems:
- jekyll-mentions
@@ -12,4 +12,4 @@ exclude:
- CNAME
- readme.md
-logo: images/openhantek.png
+logo: images/OpenHantek6022.png
diff --git a/docs/build.md b/docs/build.md
index 2945a3ad..df46fa73 100644
--- a/docs/build.md
+++ b/docs/build.md
@@ -2,41 +2,158 @@
layout: default
---
### [Linux](#linux)
-For debian (stretch and newer), Ubuntu 17.04+ and Mint 17+ and other deb based distributions install named requirements like this:
-> apt install g++ cmake qttools5-dev qttools5-dev-tools libfftw3-dev binutils-dev libusb-1.0-0-dev libqt5opengl5-dev mesa-common-dev libgl1-mesa-dev libgles2-mesa-dev
+For Debian (stretch and newer), Ubuntu 17.04+ and Mint 17+ and other deb based distributions install named requirements like this:
+> apt install g++ make cmake fakeroot qttools5-dev libfftw3-dev binutils-dev libusb-1.0-0-dev libqt5opengl5-dev mesa-common-dev libgl1-mesa-dev libgles2-mesa-dev
For distributions using dnf package manager (Fedora 21+) use this command:
-> dnf install cmake gcc-c++ qt5-qtbase-gui qt5-qttools-devel qt5-qttranslations fftw-devel binutils-devel libusb-devel mesa-libGL-devel mesa-libGLES-devel
+> dnf install make cmake fakeroot gcc-c++ qt5-qtbase-gui qt5-qttools-devel qt5-qttranslations fftw-devel binutils-devel libusb-devel mesa-libGL-devel mesa-libGLES-devel
For OpenSUSE and related distributions use this command
-zypper install cmake gcc-c++ qt5-qtbase-devel qt5-qttools-devel qt5-qttranslations binutils-devel libusb-devel Mesa-libGL-devel Mesa-libGLESv2-devel fftw3-devel
+> zypper install make cmake fakeroot gcc-c++ libqt5-qtbase libqt5-qttools libqt5-qttranslations libusb-1_0 Mesa-libGL1 Mesa-libGLESv2 fftw3
After you've installed the requirements run the following commands inside the directory of this package:
-> mkdir build
-> cd build
-> cmake ../
-> make -j2
-Optionally install the program:
+ mkdir build
+ cd build
+ cmake ..
+ make -j4
-> sudo make install
+After success you can test the newly built program `openhantek/OpenHantek`.
+Due to the included debug information this file is quite big (~20 MB), but the size can be reduced with `strip openhantek/OpenHantek` if you want to put it into a user directory.
+If you do not install the program, you need to copy the file `utils/udev_rules/60-hantek.rules` to `/lib/udev/rules.d/` yourself,
+and replug your device, otherwise you will not have the correct USB permissions to access the device.
-If you do not install the program, you need to copy the file `firmware/60-hantek.rules` to `/lib/udev/rules.d/` yourself,
-and replug your device, otherwise you will not have the correct permissions to access usb devices.
+You can install the program with `sudo make install`, but it is highly recommended to create a debian package,
+which allows a clear installation and removal of the package:
-### [Apple MacOSX](#apple)
-We recommend homebrew to install the required libraries.
-> brew update
-> brew install libusb fftw qt5 cmake;
+ rm -f packages/*
+ fakeroot make package
+ sudo apt install packages/openhantek_*_amd64.deb
+
+If you detect that icons are not displayed correctly, please check if the Qt SVG library is installed on your system.
+The Linux systems mentioned above include this lib when you install according to the provided lists.
+However, an [alpine linux](https://alpinelinux.org/) user [reported](https://github.com/OpenHantek/OpenHantek6022/issues/42#issuecomment-564329632) that he had to install `qt5-qtsvg` separately.
+
+----
+
+### [RaspberryPi](#raspberrypi)
+The general Linux requirements from above also apply to the RPi; precompiled packages are available as [release](https://github.com/OpenHantek/OpenHantek6022/releases) assets.
+Please note, it is important that the correct graphics driver is selected,
+the OpenGL implementation of Qt requires the `Original non-GL desktop driver`, e.g. on my *RPi3B+*:
+
+ sudo raspi-config
+
+
+
+
+
+
+
+Only the 1st setting `G1 Legacy Original non-GL desktop driver` worked for `OpenHantek6022`, the other two resulted in an error as below:
+
+ QEGLPlatformContext: eglMakeCurrent failed: 3009
+ QOpenGLFunctions created with non-current context
+
+Setting `Original non-GL desktop driver` was reported to work also on *RPi4B+*.
+
+----
+
+### [FreeBSD](#freebsd)
+Install the build requirements
+
+ pkg install cmake qt5 fftw3 linux_libusb
After you've installed the requirements run the following commands inside the directory of this package:
-> mkdir build
-> cd build
-> cmake ../ -DCMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.10.1
-> make -j2
-Please adjust the path to Qt5. You can find the path with the command:
-> brew info qt5
+ mkdir build
+ cd build
+ cmake ..
+ make -j4
+
+After success you can test the newly built program `openhantek/OpenHantek`.
+Due to the included debug information this file is quite big (~20 MB), but the size can be reduced with `strip openhantek/OpenHantek` if you want to put it into a user directory.
+
+In order for OpenHantek to work, make sure that your USB device has permissions for your user.
+You can achieve this by copying [`utils/devd_rules_freebsd/openhantek.conf`](../utils/devd_rules_freebsd/openhantek.conf)
+to `/usr/local/etc/devd/`, or create a file with similar content for your device:
+
+ ...
+
+ # Hantek DSO-6022BE
+
+ notify 100 {
+ match "system" "USB";
+ match "subsystem" "DEVICE";
+ match "type" "ATTACH";
+ match "vendor" "0x04b4";
+ match "product" "0x6022";
+ action "chgrp openhantek /dev/$ugen; chmod g+rw /dev/$ugen; chgrp -h openhantek /dev/$ugen; chmod -h g+rw /dev/$ugen";
+ };
+
+ notify 100 {
+ match "system" "USB";
+ match "subsystem" "DEVICE";
+ match "type" "ATTACH";
+ match "vendor" "0x04b5";
+ match "product" "0x6022";
+ action "chgrp openhantek /dev/$ugen; chmod g+rw /dev/$ugen; chgrp -h openhantek /dev/$ugen; chmod -h g+rw /dev/$ugen";
+ };
+
+ ...
+
+- The "action" above doesn't use $device-name due to:
+https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242111
+
+Also please note that devices like this have two vendor/product id combinations,
+before and after loading the firmware, hence two commands above.
+The action changes the device permissions for supported scope devices:
+
+`rw------- root operator` becomes `rw-rw---- root openhantek`
+
+Make sure to be member of the group `openhantek`, e.g.:
+
+ pw groupadd openhantek -g 6022
+ pw groupmod openhantek -M
+
+----
+
+### [MacOSX](#macosx)
+We recommend homebrew to install the required libraries.
+
+ brew update
+ brew install libusb fftw qt5 cmake
+
+If you want to build an OSX bundle make sure the option in `openhantek/CMakeLists.txt` is set accordingly:
+
+ option(BUILD_MACOSX_BUNDLE "Build MacOS app bundle" ON)
+
+After you've installed the requirements run the following commands inside the top directory of this package:
+
+ mkdir build
+ cd build
+ cmake ..
+ #
+ make -j4
+ #
+ # now the target was created in subdir openhantek
+ # .. either as single binary OpenHantek, then you're done
+ # .. or as a bundle if enabled in ../../openhantek/CMakeLists.txt
+ # .. but this bundle is still a template as the dynlibs are not yet bundled
+ # .. this magic will happen now
+ #
+ cd openhantek
+ #
+ # deploy all necessary Qt dynlibs into the bundle
+ macdeployqt OpenHantek.app -always-overwrite -verbose=2
+ #
+ # find all other dependencies, and their dependencies, and their... (you got it!)
+ python ../../macdeployqtfix/macdeployqtfix.py OpenHantek.app/Contents/MacOS/OpenHantek $(brew --prefix qt5)
+ #
+ # finally create OpenHantek.dmg from OpenHantek.app
+ macdeployqt OpenHantek.app -dmg -no-plugins -verbose=2
+ #
+
+----
### [Windows](#windows)
@@ -51,11 +168,40 @@ Hints for Visual Studio 2015/2017 users:
* Build for 64bit. 32bit builds theoretically work, but you are on your own then.
* Use the **CMake GUI** to setup all required Qt include and library paths.
-Microsoft Windows needs an installed driver for every usb device:
+#### Microsoft Windows USB driver install (with Zadig)
-* Make sure your original Hantek driver is uninstalled.
-* Extract `cmake/winusb driver.zip` and customize the `libusb_device.inf` file for your device. The Vendor ID and Device ID as well as a unique GUID need to be entered like in the following example for a Hantek 6022BE.
-* Physically plug (or replug) oscilloscope into PC's. From the Windows device manager update driver for your device and point to your modified libusb_device.inf.
+The device specific USB driver shipped with the vendor software is not going to work in almost all cases.
+You will need to install the WinUSB driver.
+
+For installing the WinUSB driver you can use the [Zadig](http://zadig.akeo.ie/) executable.
+There are two versions, one for Windows XP (zadig_xp.exe), and another one for all other (Vista or higher)
+supported Windows versions (zadig.exe). Both 32 and 64 bit Windows versions are supported.
+
+If you already installed the vendor driver previously, you need to run Zadig and switch to the WinUSB driver (see above).
+There's no need to uninstall or deactivate the vendor driver manually, Zadig will handle all of this.
+
+Note: For Hantek 6022BE and 60222BL you have to assign the WinUSB driver via Zadig twice:
+the first time for the initial USB VID/PID the device has when attaching it via USB,
+and a second time after the firmware has been uploaded to the device and the device has "renumerated"
+with a different VID/PID pair.
+
+See also the [Zadig wiki page](https://github.com/pbatard/libwdi/wiki/Zadig) for more information.
+
+ - 1st install for the newly plugged scope without firmware (VID/PID 04B4/6022 for 6022BE or VID/PID 04B4/602A for 6022BL).
+ - 2nd time for the scope with firmware uploaded (VID/PID 04B5/6022 for 6022BE or VID/PID 04B5/602A for 6022BL).
+
+Some win user reports:
+
+* black2279's wiki entry
+[USB Drivers Installation with Zadig for Hantek 6022 (Windows)](https://github.com/black2279/OpenHantek6022/wiki/USB-Drivers-Installation-with-Zadig-for-Hantek-6022-%28Windows%29)
+* raxis13's [success report](https://www.eevblog.com/forum/testgear/hantek-6022be-20mhz-usb-dso/msg2563869/#msg2563869)
+
+----
+
+#### This is the old and more complex procedure (no positive feedback known)
+ - Make sure your original Hantek driver is uninstalled.
+ - Extract `cmake/winusb driver.zip` and customize the `libusb_device.inf` file for your device. The Vendor ID and Device ID as well as a unique GUID need to be entered like in the following example for a Hantek 6022BE.
+ - Physically plug (or replug) oscilloscope into PC's. From the Windows device manager update driver for your device and point to your modified libusb_device.inf.
````
; =====================================================
@@ -73,4 +219,3 @@ Date = "08/12/2017"
; ========== END USER CONFIGURABLE SECTION ============
; =====================================================
````
-
diff --git a/docs/images/OpenHantek6022.png b/docs/images/OpenHantek6022.png
new file mode 100644
index 00000000..dc68a0fb
Binary files /dev/null and b/docs/images/OpenHantek6022.png differ
diff --git a/docs/images/openhantek.png b/docs/images/openhantek.png
deleted file mode 100644
index f492e4d9..00000000
Binary files a/docs/images/openhantek.png and /dev/null differ
diff --git a/docs/images/screenshot_demo_mode.png b/docs/images/screenshot_demo_mode.png
new file mode 100644
index 00000000..bb32a64d
Binary files /dev/null and b/docs/images/screenshot_demo_mode.png differ
diff --git a/docs/images/screenshot_mainwindow.png b/docs/images/screenshot_mainwindow.png
index fe313cb6..830efc8c 100644
Binary files a/docs/images/screenshot_mainwindow.png and b/docs/images/screenshot_mainwindow.png differ
diff --git a/docs/images/screenshot_mainwindow_dark.png b/docs/images/screenshot_mainwindow_dark.png
new file mode 100644
index 00000000..29bf1a55
Binary files /dev/null and b/docs/images/screenshot_mainwindow_dark.png differ
diff --git a/docs/images/screenshot_mainwindow_win.png b/docs/images/screenshot_mainwindow_win.png
index 1cd5e483..a7b3d783 100644
Binary files a/docs/images/screenshot_mainwindow_win.png and b/docs/images/screenshot_mainwindow_win.png differ
diff --git a/docs/images/screenshot_mainwindow_with_zoom.png b/docs/images/screenshot_mainwindow_with_zoom.png
new file mode 100644
index 00000000..b3a1475b
Binary files /dev/null and b/docs/images/screenshot_mainwindow_with_zoom.png differ
diff --git a/docs/index.md b/docs/index.md
index 8be4cb8b..266447dd 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,19 +1,21 @@
---
layout: default
-overview: true
+overview: false
---
-# OpenHantek [](https://travis-ci.org/OpenHantek/openhantek) [](https://ci.appveyor.com/project/davidgraeff/openhantek/branch/master)
+# OpenHantek6022
-OpenHantek is a free software for Hantek and compatible (Voltcraft/Darkwire/Protek/Acetech) USB digital signal oscilloscopes.
+[](https://travis-ci.org/OpenHantek/OpenHantek6022)
+[](https://ci.appveyor.com/project/Ho-Ro/openhantek6022)
+[](https://www.codefactor.io/repository/github/openhantek/openhantek6022)
+[](https://masterminds.github.io/stability/active.html)
-It has started as an alternative to the official Hantek DSO software for Linux users. Nowadays it works under Microsoft Windows and Apple Mac OS as well.
+OpenHantek6022 is a free software for Hantek and compatible (Voltcraft/Darkwire/Protek/Acetech) USB digital signal oscilloscopes.
+It was initially developed by [David Gräff and others](https://github.com/OpenHantek/openhantek/graphs/contributors) on [github.com/OpenHantek/openhantek](https://github.com/OpenHantek/openhantek). After David [stopped maintaining](https://github.com/OpenHantek/openhantek/issues/277) the programm I cloned the repo to provide some updates - but only for Hantek 6022BE/BL on the linux platform.
-
-
-
-
-
-* Supported operating systems: Linux, MacOSX, Windows¹
-* Supported devices: DSO2xxx Series, DSO52xx Series, 6022BE/BL
+
+* Actively supported devices: Hantek 6022BE/BL on Linux.
+* DSO2xxx Series and DSO52xx Series support is still in but untested due to missing devices.
+* Other operating systems builds: MacOSX, Windows - untested.
+[Technical details and imitations](limitations.md) of Hantek 6022.
diff --git a/docs/limitations.md b/docs/limitations.md
index 22742cb8..81e112f9 100644
--- a/docs/limitations.md
+++ b/docs/limitations.md
@@ -1,9 +1,26 @@
---
layout: default
---
-## Software triggered devices like the 6022BE
+## Valid specs for the 6022BE/BL with [custom firmware by Ho-Ro](https://github.com/Ho-Ro/Hantek6022API).
- - Support 48, 24, 16, 8, 4, 2, 1 M and 500, 200, 100 k Hz samplerates. For the 6022 with modded firmware by [jhoenicke](https://github.com/rpcope1/Hantek6022API)
- - Can detect rising or falling edge of the signal.
- - Note that the first few samples are dropped due to unstable/unusual reading.
+ - The device has no internal storage (except for a small fifo buffer), all data is streamed in real time as USB bulk transfer.
+ - Supports 48, 30, 24, 16, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1 MS/s and 500, 200, 100, 60 kS/s samplerates.
+ - Due to the USB bandwith constraints the max usable samplerate is limited: Max 30 MS/s for CH1 only and max 15 MS/s for CH1+CH2 and also CH2 only - otherwise data overrun occurs.
+ - Under Linux (even better if using a realtime kernel) the priority of the program can be raised when the user is member of a *realtime* group, e.g. audio:
+
+ 1. set limits in /etc/security/limits.d:
+ @audio - rtprio 99
+ 2. add user to the group, e.g. audio:
+ usermod -a -G audio
+ or set the limits only for your user in /etc/security/limits.d:
+ - rtprio 99
+
+ - The scope program works with blocks of 20000 samples - either 8 bit samples for CH1 only or 16 bit samples otherwise.
+ - Two analog input channels with 8-bit sample-width, max input voltage range is -5 V..+5 V, values outside this range are clipped (shown as minimum or maximum value).
+ - For low effective sampling rates < 1 MS/s a 10X..100X oversampling is used to increase the signal-to-noise ratio by 10..20 dB and to get a better voltage resolution (up to > 11 effective bits).
+ - The first samples are unstable (due to the use of the ADC far outside the common mode voltage specifications) -> take about 2000 additional values to settle the ADC and drop the first samples.
+ - No AC coupling available, all signals are measured as DC. (Use either a BNC DC-block or the math mode "CHx AC").
+ - A [little HW modification](HANTEK6022_AC_Modification.pdf) adds AC coupling. OpenHantek6022 supports this feature since v2.17-rc5 / FW0204.
+ - No HW trigger available, SW trigger seaches for trigger condition and positions the trace window accordingly.
+ - Can detect rising or falling edge (also alternating from trace to trace) of the signal, displayed trigger position can be at 0..100% of screen width.
diff --git a/docs/readme.md b/docs/readme.md
new file mode 100644
index 00000000..e13376bc
--- /dev/null
+++ b/docs/readme.md
@@ -0,0 +1,304 @@
+# OpenHantek developer documentation
+
+This document explains the basic data flow and concepts used and should be amended
+whenever a new concept is added to the code base.
+Detailed information about an implementation are to be found in the specific directory readmes though.
+
+## Directory structure
+
+The *res* folder contains mostly binary resource data that are bundled with the executable,
+like icons, images, firmwares and translations.
+
+The *res/translations* folder contains translations in the Qt format. Use Qt linguist
+as a handy graphical interface to translate OpenHantek. A [Translation HowTo](res/translations/Translation_HowTo.md) is available.
+
+The source code within *src* can be divided into a **core**, that is responsible for device communication,
+data acquisition and post processing and the **graphical interface** with several custom widgets,
+a configuration interface and an OpenGL renderer.
+
+### Core structure
+
+The raw device communcation takes place in the *src/usb* directory, especially via the `USBDevice` class.
+To find suitable devices, the `FindDevices` class in the same folder is used. Firmware upload is realized
+via the `ezusb` helper methods and the `UploadFirmware` class.
+
+The hantek protocol structures and constants are defined within `src/hantekprotocol`.
+
+The heart of OpenHantek is the `src/hantekdso` folder and its `hantekdsocontrol` class. All supported models,
+based on the `DsoModel` class, are implemented within a subfolder `src/hantekdso/models` and automatically register
+themself to a `ModelRegistry` class. A model is based on (contains) a specification, the `ControlSpecification` class.
+
+The `hantekdsocontrol` class keeps track of the devices current state (samplerate, selected gain, activated channels,
+etc) via the `ControlSettings` class and field.
+It outputs the channel separated unprocessed samples via a `samplesAvailable(DSOsamples*)` signal.
+
+Before the data is presented to the GUI it arrives in the `src/post/postprocessing` class. Several post
+processing classes are to be found in this directory as well.
+
+### Graphical interface structure
+
+The initial dialog for device selection is realized in *src/selectdevice* where several models
+and dialogs are implemented. This is basically a graphical wrapper around the `src/usb/finddevices` class.
+
+You will find the configuration dialog pages to be implemented in *src/configdialog*.
+
+Custom widgets like a LevelSlider with a unit suffix reside in *src/widgets*, the custom main window docks are
+in *src/docks*.
+
+The code that is responsible for exporting data to images or to the printer is stored in *src/exporting*.
+
+The main window itself doesn't do and shouldn't do much more than connecting signals/slots between the core part
+and the graphical part.
+
+All OpenGL rendering takes place in the `GlScope` class. A helper class `GlScopeGraph` contains exactly one
+data sample snapshot including all channels for voltage and spectrum and a pointer to the respective GPU buffer.
+`GlScope` works normally for **OpenGL 3.2+** and OpenGL ES 2.0+ but if it detects **OpenGL 2.1+** and OpenGL ES 1.2+ on older platforms it switches to a legacy implementation. If both OpenGL and OpenGL Es are present, OpenGL will be prefered, but can be overwritten by the user via a command flag.
+
+### Export
+
+All export related funtionality is within *src/exporting*.
+
+The following exporters are implemented:
+
+* Export to comma separated value file (CSV): Write to a user selected file,
+* Export to an image/pdf: Writes an image/pdf to a user selected file,
+* Print exporter: Creates a printable document and opens the print dialog.
+
+All export classes (exportcsv, exportimage, exportprint) implement the
+ExporterInterface and are registered to the ExporterRegistry in the main.cpp.
+
+Some export classes are still using the legacyExportDrawer class to
+draw the grid and paint all the labels, values and graphs.
+
+The plan is to retire this legacy class and replace the paint code with
+a `GlScope` class shared OpenGL drawing code for at least the grid and the
+scope graphs.
+
+## Persistent settings
+
+Persisent settings are stored in the file `~/.config/OpenHantek/OpenHantek6022.conf`.
+Settings are written at program shutdown or with menu entry `File/Save settings` (`Ctrl-S`).
+The save/load happens in `src/dsosettings.cpp` in the functions `DsoSettings::save()` and `DsoSettings::load()`.
+After loading of the settings the values will be applied to the internal status as well as to the GUI.
+
+An example of making the calibration output frequency (parameter `calfreq`) persistent can be seen in commit [26c1a49](https://github.com/OpenHantek/OpenHantek6022/commit/26c1a49146818aab7419b319705878a5f072460f)
+
+`openhantek/src/dsosettings.cpp`
+
+ void DsoSettings::save() {
+ ...
+ store->setValue("calfreq", scope.horizontal.calfreq);
+ ...
+ }
+
+ void DsoSettings::load() {
+ ...
+ if (store->contains("calfreq")) scope.horizontal.calfreq = store->value("calfreq").toDouble();
+ ...
+ }
+
+`openhantek/src/hantekdso/hantekdsocontrol.cpp`
+
+ void HantekDsoControl::applySettings(DsoSettingsScope *scope) {
+ ...
+ setCalFreq(scope->horizontal.calfreq);
+ ...
+ }
+
+## Scope interface
+
+The scope receives control commands via endpoint 0 and provides the sampled data via bulk transfer on endpoint 6.
+The firmware command parser:
+
+ BOOL handle_vendorcommand(BYTE cmd)
+ {
+ stop_sampling();
+
+ /* Set red LED, toggle after timeout. */
+ LED_RED();
+ ledcounter = ledinit;
+
+ /* Clear EP0BCH/L for each valid command. */
+ if ( cmd >= 0xe0 && cmd <= 0xe6 ) {
+ EP0BCH = 0;
+ EP0BCL = 0;
+ while ( EP0CS & bmEPBUSY )
+ ;
+ }
+
+ switch (cmd) {
+ case 0xa2:
+ return eeprom();
+
+ case 0xe0:
+ return set_voltage( 0, EP0BUF[0] );
+
+ case 0xe1:
+ return set_voltage( 1, EP0BUF[0] );
+
+ case 0xe2:
+ return set_samplerate( EP0BUF[0] );
+
+ case 0xe3:
+ if ( EP0BUF[0] == 1 ) {
+ /* Set green LED while sampling. */
+ LED_GREEN();
+ ledcounter = 0;
+ start_sampling();
+ }
+ return TRUE;
+
+ case 0xe4:
+ return set_numchannels( EP0BUF[0] );
+
+ case 0xe5:
+ SET_COUPLING( EP0BUF[0] );
+ return TRUE;
+
+ case 0xe6:
+ return set_calibration_pulse( EP0BUF[0] );
+
+ }
+
+ return FALSE; /* Not handled by handlers. */
+ }
+
+
+## Data flow
+* The procedure `void HantekDsoControl::stateMachine()` controls the raw data capturing, conversion to real world physical values, trigger detection and timing of screen refresh. The `struct Raw` holds all important values of one sampled data block:
+
+
+ struct Raw {
+ unsigned channels = 0;
+ double samplerate = 0;
+ unsigned oversampling = 0;
+ unsigned gainValue[ 2 ] = {1, 1}; // 1,2,5,10,..
+ unsigned gainIndex[ 2 ] = {7, 7}; // index 0..7
+ unsigned tag = 0;
+ bool freeRun = false; // small buffer, no trigger
+ bool valid = false; // samples can be processed
+ bool rollMode = false; // one complete buffer received, start to roll
+ unsigned size = 0;
+ unsigned received = 0;
+ std::vector< unsigned char > data;
+ mutable QReadWriteLock lock;
+ };
+
+
+* Raw 8-bit ADC values are collected permanently via call to `HantekDsoControl::getSamples(..)` (or `...getDemoSamples(..)` for the demo device) in an own thread `Capturing::Capturing()`.
+At fast sample rates (>= 10 kS/s) one big block is requested via USB command to make the transfer more robust against USB interruptions by other traffic,
+while at slow sample rates it requests the data in small chunks to allow a permanent screen update in roll mode.
+* Raw values are converted in `HantekDsoControl::convertRawDataToSamples()` to real-world double samples (scaled with voltage and sample rate).
+The 2X..200X oversampling for slower sample rates is done here. Also overdriving of the inputs is detected.
+In `Roll` mode the latest sample values are always put at the end of the result buffer while older samples move toward the beginning of the buffer,
+this rolls the displayed trace permanently to the left.
+The conversion uses either the factory calibration values from EEPROM or from a user supplied config file.
+Read more about [calibration](https://github.com/Ho-Ro/Hantek6022API/blob/master/README.md#create-calibration-values-for-openhantek).
+* `searchTriggerPosition()`
+ * Checks if the signal is triggered and calculates the starting point for a stable display.
+ The time distance to the following opposite slope is measured and displayed as pulse width in the top row.
+* `provideTriggeredData()` handles the trigger mode:
+ * If the **trigger condition is false** and the **trigger mode is Normal** or the display is paused
+then we reuse the last triggered samples so that voltage and spectrum traces
+as well as the measurement at the scope's bottom lines are frozen until the trigger condition
+becomes true again. The reused samples are emitted at lower speed (every 20 ms) to reduce CPU load but be responsive to user actions.
+ * If the **trigger condition is false** and the **trigger mode is not Normal** then we display a free running trace and discard the last saved samples.
+* The converted `DSOsamples` are emitted to PostProcessing::input() via signal/slot:
+
+`QObject::connect( &dsoControl, &HantekDsoControl::samplesAvailable, &postProcessing, &PostProcessing::input );`
+
+
+ struct DSOsamples {
+ std::vector< std::vector< double > > data; ///< Pointer to input data from device
+ double samplerate = 0.0; ///< The samplerate of the input data
+ unsigned char clipped = 0; ///< Bitmask of clipped channels
+ bool liveTrigger = false; ///< live samples are triggered
+ unsigned triggeredPosition = 0; ///< position for a triggered trace, 0 = not triggered
+ double pulseWidth1 = 0.0; ///< width from trigger point to next opposite slope
+ double pulseWidth2 = 0.0; ///< width from next opposite slope to third slope
+ bool freeRunning = false; ///< trigger: NONE, half sample count
+ unsigned tag = 0; ///< track individual sample blocks (debug support)
+ mutable QReadWriteLock lock;
+ };
+
+
+* PostProzessing calls all processors that were registered in `main.cpp`.
+ * `MathchannelGenerator::process()`
+ * which creates a third MATH channel as one of these data sample combinations:
+ `CH1 + CH2`, `CH1 - CH2`, `CH2 - CH1`, `CH1 * CH2`, `CH1 AC` or `CH2 AC`.
+ * `SpectrumGenerator::process()`
+ * For each active channel:
+ * Calculate the peak-to-peak, DC (average), AC (rms) and effective value ( sqrt( DC² + AC² ) ).
+ * Apply a user selected window function and scale the result accordingly.
+ * Calculate the spectrum of the AC part of the signal scaled as dBV. fft: f(t) ⊶ F(ω)
+ * Calculate the autocorrelation to get the frequency of the signal:
+ * Calculate power spectrum |F(ω)|² and do an ifft: F(ω) ∙ F(ω) ⊷ f(t) ⊗ f(t) (convolution of f(t) with f(t))
+ * This is quite inaccurate at high frequencies. In these cases the first peak value of the spectrum is used.
+ * `GraphGenerator::process()`
+ * which works either in TY mode and creates two types of traces:
+ * voltage over time `GraphGenerator::generateGraphsTYvoltage()`
+ * spectrum over frequency `GraphGenerator::generateGraphsTYspectrum()`
+ * or in XY mode and creates a voltage over voltage trace `GraphGenerator::generateGraphsXY()`.
+ * `GraphGenerator::generateGraphsTYvoltage()` creates up to three (CH1, CH2, MATH) voltage traces.
+ * `GraphGenerator::generateGraphsTYspectrum()` creates up to three (SP1, SP2, SPM) spectral traces.
+ * Finally `PostProcessing` emits the signal `processingFinished()` that is connected to:
+ * `ExporterRegistry::input()` that takes care of exporting to CSV data.
+ * `MainWindow::showNewData()`.
+ * `MainWindow::showNewData()` calls `DsoWidget::showNew()` that calls `GlScope::showData()` that calls `Graph::writeData()`.
+
+t.b.c.
+
+## Data structures and configuration
+
+* Two main structures/classes hold most of the current status of the oscilloscope:
+
+* The struct `ControlSettings` and its substructures (-> `hantekdso/controlsettings.h`) are the main storage for all scope (HW) parameters that are handled by the class `HantekDsoControl`.
+
+
+ struct ControlSettings {
+ ControlSettings( const ControlSamplerateLimits *limits, size_t channelCount );
+ ~ControlSettings();
+ ControlSettings( const ControlSettings & ) = delete;
+ ControlSettings operator=( const ControlSettings & ) = delete;
+ ControlSettingsSamplerate samplerate; ///< The samplerate settings
+ std::vector< ControlSettingsVoltage > voltage; ///< The amplification settings
+ ControlSettingsTrigger trigger; ///< The trigger settings
+ RecordLengthID recordLengthId = 1; ///< The id in the record length array
+ unsigned channelCount = 0; ///< Number of activated channels
+ Hantek::CalibrationValues *calibrationValues; ///< Calibration data for the channel offsets & gains
+ Hantek::ControlGetLimits cmdGetLimits;
+ };
+
+* The class `DsoSettings` (-> `dsosettings.h`) and its substructures `DsoSettingsScope` (`scopesettings.h`) and `DsoSettingsView` (`viewsettings.h`)
+are the main storage for all persistent scope (program) parameters, see `DsoSettings::save()` and `DsoSettings::load()`.
+
+
+ class DsoSettings {
+ Q_DECLARE_TR_FUNCTIONS( DsoSettings )
+ public:
+ explicit DsoSettings( const Dso::ControlSpecification *deviceSpecification );
+ bool setFilename( const QString &filename );
+
+ DsoSettingsExport exporting; ///< General options of the program
+ DsoSettingsScope scope; ///< All oscilloscope related settings
+ DsoSettingsView view; ///< All view related settings
+ DsoSettingsPostProcessing post; ///< All post processing related settings
+ bool alwaysSave = true; ///< Always save the settings on exit
+
+ QByteArray mainWindowGeometry; ///< Geometry of the main window
+ QByteArray mainWindowState; ///< State of docking windows and toolbars
+
+ /// \brief Read the settings from the last session or another file.
+ void load();
+
+ /// \brief Save the settings to the harddisk.
+ void save();
+
+ private:
+ std::unique_ptr< QSettings > store = std::unique_ptr< QSettings >( new QSettings );
+ const Dso::ControlSpecification *deviceSpecification;
+ };
+
+GUI input either in the docks of by moving sliders changes the `DsoSettings` parameters directly
+and the `ControlSettings` parameters (that live in another thread `dsoControlThread` ) via signal/slot mechanism.
+The (big) class `HantekDsoControl` has a member `const DsoSettingsScope *scope` that gives direct read acces to the (persistent) scope settings.
diff --git a/firmware/60-hantek.rules b/firmware/60-hantek.rules
deleted file mode 100644
index 95b374f3..00000000
--- a/firmware/60-hantek.rules
+++ /dev/null
@@ -1,26 +0,0 @@
-# Hantek DSO-2090
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="2090", TAG+="uaccess", TAG+="udev-acl"
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="2090", TAG+="uaccess", TAG+="udev-acl"
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="8613", TAG+="uaccess", TAG+="udev-acl"
-
-# Hantek DSO-2150
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="2150", TAG+="uaccess", TAG+="udev-acl"
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="2150", TAG+="uaccess", TAG+="udev-acl"
-
-# Hantek DSO-2250
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="2250", TAG+="uaccess", TAG+="udev-acl"
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="2250", TAG+="uaccess", TAG+="udev-acl"
-
-# Hantek DSO-5200
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="5200", TAG+="uaccess", TAG+="udev-acl"
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="5200", TAG+="uaccess", TAG+="udev-acl"
-
-# Hantek DSO-5200A
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="520a", TAG+="uaccess", TAG+="udev-acl"
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="520a", TAG+="uaccess", TAG+="udev-acl"
-
-# Hantek DSO-6022BE/BL
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="6022", TAG+="uaccess", TAG+="udev-acl"
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="602a", TAG+="uaccess", TAG+="udev-acl"
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="6022", TAG+="uaccess", TAG+="udev-acl"
-SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="602a", TAG+="uaccess", TAG+="udev-acl"
diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt
deleted file mode 100644
index ff1baf0c..00000000
--- a/firmware/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-project(FirmwareExtractor C)
-
-find_library( BFD_LIBRARY NAMES bfd libbdf PATH /usr/lib /usr/lib64 )
-find_path(BFD_INCLUDE bfd.h PATHS /usr/include
- /usr/local/include
- /opt/local/include
- /sw/include)
-
-
-if (NOT BFD_LIBRARY OR NOT BFD_INCLUDE)
- message(STATUS "BFD not found. Please install binutils-devel (fedora) / binutils-dev (ubuntu)")
- return()
-endif()
-
-add_executable(${PROJECT_NAME} extractfw.c)
-target_link_libraries(${PROJECT_NAME} ${BFD_LIBRARY} )
-target_include_directories(${PROJECT_NAME} PRIVATE ${BFD_INCLUDE})
diff --git a/firmware/README.md b/firmware/README.md
deleted file mode 100644
index 86775da7..00000000
--- a/firmware/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-Use the `fwget.sh` script to extract a firmware from a windows driver.
-The copyright belongs to Hantek.
diff --git a/firmware/extractfw.c b/firmware/extractfw.c
deleted file mode 100644
index 4e19c026..00000000
--- a/firmware/extractfw.c
+++ /dev/null
@@ -1,258 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// OpenHantek
-// dsoextractfw.c
-// Copyright (C) 2008 Oleg Khudyakov
-// prcoder@potrebitel.ru
-// Copyright (C) 2010, 2011 Oliver Haag
-// oliver.haag@gmail.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 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program. If not, see .
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include
-#include
-#include
-#include
-
-#define PACKAGE_VERSION 1
-#define PACKAGE 1
-#include
-
-
-int extractFirmware(const char *filenameDriver, const char *filenameFirmware, const char *filenameLoader);
-int writeIntelHex(const char *filename, unsigned char *data, unsigned int length);
-
-static const char *filenameEndFirmware = "-firmware.hex";
-static const char *filenameEndLoader = "-loader.hex";
-static const char *filenameEndDriver = "1.sys";
-static const char *nameTarget = "pei-i386";
-static const char *nameSection = ".data";
-static const char *nameSymbolFirmware = "_firmware";
-static const char *nameSymbolLoader = "_loader";
-
-
-/// \brief Parse commandline arguments.
-/// \return 0 on success, negative on error.
-int main(int argc, char **argv) {
- char *filenameDriver, *filenameFirmware, *filenameLoader;
- char *charPointer;
- int prefixLength;
-
- if(argc < 2) {
- fprintf(stderr, "Usage: %s [] []\n", argv[0]);
- return -1;
- }
- filenameDriver = argv[1];
-
- prefixLength = strlen(filenameDriver) - strlen(filenameEndDriver);
-
- if(argc < 3) {
- // Guess correct filename for firmware
- filenameFirmware = (char*)malloc(prefixLength + strlen(filenameEndFirmware) + 1);
- memcpy(filenameFirmware, filenameDriver, prefixLength);
- strcpy(filenameFirmware + prefixLength, filenameEndFirmware);
-
- // Convert filename to lowercase
- charPointer = strrchr(filenameFirmware, '/');
- if(charPointer == NULL)
- charPointer = filenameFirmware;
- for(; *charPointer != 0; charPointer++)
- *charPointer = tolower(*charPointer);
- }
- else {
- filenameFirmware = argv[2];
- }
-
- if(argc < 4) {
- // Guess correct filename for loader
- filenameLoader = (char*)malloc(prefixLength + strlen(filenameEndLoader) + 1);
- memcpy(filenameLoader, filenameDriver, prefixLength);
- strcpy(filenameLoader + prefixLength, filenameEndLoader);
-
- // Convert filename to lowercase
- charPointer = strrchr(filenameLoader, '/');
- if(charPointer == NULL)
- charPointer = filenameLoader;
- for(; *charPointer != 0; charPointer++)
- *charPointer = tolower(*charPointer);
- }
- else {
- filenameFirmware = argv[3];
- }
-
- return extractFirmware(filenameDriver, filenameFirmware, filenameLoader);
-}
-
-/// \brief Extract firmware and loader data from original driver file.
-/// \param filenameDriver Name of the original driver file.
-/// \param filenameFirmware Name of the file where the firmware should be saved.
-/// \param filenameDriver Name of the file where the loader should be saved.
-/// \return 0 on success, negative on error.
-int extractFirmware(const char *filenameDriver, const char *filenameFirmware, const char *filenameLoader) {
- bfd *bfdDriver;
- asection *sectionData;
-
- asymbol **symbols;
- unsigned int symbolCount;
- unsigned currentSymbol;
- const char *symbolName;
-
- bfd_size_type offsetFirmware = 0, offsetLoader = 0;
- bfd_size_type lengthFirmware = 0, lengthLoader = 0;
- unsigned char *bufferFirmware, *bufferLoader;
-
- // Initialize bfd and open driver file
- bfd_init();
- bfdDriver = bfd_openr(filenameDriver, nameTarget);
- if(!bfdDriver) {
- bfd_perror("Error opening file");
- return -1;
- }
-
- if(!bfd_check_format(bfdDriver, bfd_object)) {
- bfd_perror("bfd_check_format");
- bfd_close(bfdDriver);
- return -2;
- }
-
- // Search for the data section
- for(sectionData = bfdDriver->sections; sectionData != NULL; sectionData = sectionData->next)
- if(strcmp(sectionData->name, nameSection) == 0)
- break;
- if(sectionData == NULL) {
- fprintf(stderr, "Section %s not found\n", nameSection);
- return -3;
- }
- printf("Section %s found (starting at 0x%04lx, %li bytes)\n", nameSection, (unsigned long int) sectionData->filepos, (long int) sectionData->size);
-
- // Search for the symbols we want
- symbols = (asymbol**)malloc(bfd_get_symtab_upper_bound(bfdDriver));
- symbolCount = bfd_canonicalize_symtab(bfdDriver, symbols);
- for(currentSymbol = 0; currentSymbol < symbolCount; currentSymbol++) {
- symbolName = bfd_asymbol_name(symbols[currentSymbol]);
-
- if(strcmp(symbolName, nameSymbolFirmware) == 0)
- offsetFirmware = symbols[currentSymbol]->value;
- if(strcmp(symbolName, nameSymbolLoader) == 0)
- offsetLoader = symbols[currentSymbol]->value;
- }
- free(symbols);
-
- // Calculate position in section and length
- offsetFirmware -= sectionData->filepos;
- offsetLoader -= sectionData->filepos;
- lengthFirmware = offsetLoader - offsetFirmware;
- lengthLoader = sectionData->size - lengthFirmware;
-
- printf("Symbol %s found (offset 0x%04lx, %li bytes)\n", nameSymbolFirmware, (unsigned long int) offsetFirmware, (long int) lengthFirmware);
- printf("Symbol %s found (offset 0x%04lx, %li bytes)\n", nameSymbolLoader, (unsigned long int) offsetLoader, (long int) lengthLoader);
-
- // Extract data
- bufferFirmware = (unsigned char*)malloc(lengthFirmware);
- bufferLoader = (unsigned char*)malloc(lengthLoader);
- if (bufferFirmware == NULL || bufferLoader == NULL) {
- fprintf(stderr, "Can't allocate memory\n");
- bfd_close(bfdDriver);
- return -4;
- }
-
- if(!bfd_get_section_contents(bfdDriver, sectionData, bufferFirmware, offsetFirmware, lengthFirmware)) {
- bfd_perror("Can't get firmware contents");
- bfd_close(bfdDriver);
- return -5;
- }
-
- if(!bfd_get_section_contents(bfdDriver, sectionData, bufferLoader, offsetLoader, lengthLoader)) {
- bfd_perror("Can't get loader contents");
- bfd_close(bfdDriver);
- return -6;
- }
-
- printf("Saving firmware as %s\n", filenameFirmware);
- writeIntelHex(filenameFirmware, bufferFirmware, lengthFirmware);
- free(bufferFirmware);
-
- printf("Saving loader as %s\n", filenameLoader);
- writeIntelHex(filenameLoader, bufferLoader, lengthLoader);
- free(bufferLoader);
-
- bfd_close(bfdDriver);
-
- return 0;
-}
-
-/// \brief Save data to a file in intel hex format.
-/// \param filename Name of the output file.
-/// \param data Pointer to the binary data that should be stored.
-/// \param length Size of the data that should be stored.
-/// \return 0 on success, negative on error.
-int writeIntelHex(const char *filename, unsigned char *data, unsigned int length)
-{
- FILE *file;
- unsigned char crc, eof;
- unsigned int dataIndex, byteIndex, byteCount;
- unsigned char *dataPointer;
-
- file = fopen(filename, "wt");
- if(!file) {
- fprintf(stderr, "Can't open %s for writing\n", filename);
- fclose(file);
- return -1;
- }
-
- for(dataIndex = 0; dataIndex < length; dataIndex += 22) {
- eof = -1; // Always check for End of File Record
- dataPointer = data + dataIndex;
-
- // Start code and byte count
- byteCount = *dataPointer;
- fprintf(file, ":%02X", byteCount);
- if(byteCount != 0)
- eof = 0;
- crc = -*dataPointer++;
- dataPointer++;
-
- // Address
- fprintf(file, "%04X", *(unsigned short *) dataPointer);
- if(*(unsigned short *) dataPointer != 0)
- eof = 0;
- crc -= *dataPointer++;
- crc -= *dataPointer++;
-
- // Record type
- fprintf(file, "%02X", *dataPointer);
- if(*dataPointer != 0x01)
- eof = 0;
- crc -= *dataPointer++;
-
- // Data
- for(byteIndex = 0; byteIndex < byteCount; byteIndex++) {
- fprintf(file, "%02X", *dataPointer);
- crc -= *dataPointer++;
- }
-
- // CRC
- fprintf(file, "%02X\n", crc);
-
- if(eof)
- break;
- }
-
- fclose(file);
-
- return 0;
-}
diff --git a/firmware/fwget.sh b/firmware/fwget.sh
deleted file mode 100755
index 9c692c41..00000000
--- a/firmware/fwget.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-shopt -s globstar
-
-rm -rf build
-mkdir build && cd build && cmake ../ && make && cd ..
-
-if [ ! -d ./hex ]; then
-mkdir hex && cd hex && \
-for MODEL in "2090" "2150" "2250" "5200" "5200A"; do
- wget http://www.hantek.com/Product/DSO2000/DSO${MODEL}_Driver.zip
- unzip DSO${MODEL}_Driver.zip
-done && \
-cd ..
-fi
-
-for f in hex/**/*.sys; do
- ./build/FirmwareExtractor $f && rm $f
-done
diff --git a/openhantek/.clang-format b/openhantek/.clang-format
index 2e9d003d..a93b003c 100644
--- a/openhantek/.clang-format
+++ b/openhantek/.clang-format
@@ -5,22 +5,22 @@ AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
-AlignEscapedNewlinesLeft: false
+AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
-AllowShortBlocksOnASingleLine: true
+AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
-AllowShortIfStatementsOnASingleLine: true
-AllowShortLoopsOnASingleLine: true
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
-BraceWrapping:
+BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
@@ -38,7 +38,7 @@ BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
-ColumnLimit: 120
+ColumnLimit: 132
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
@@ -64,7 +64,7 @@ JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
-MaxEmptyLinesToKeep: 1
+MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
@@ -83,13 +83,12 @@ SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
-SpacesInAngles: false
+SpacesInAngles: true
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
-SpacesInParentheses: false
-SpacesInSquareBrackets: false
+SpacesInParentheses: true
+SpacesInSquareBrackets: true
Standard: Cpp11
TabWidth: 8
UseTab: Never
...
-
diff --git a/openhantek/CMakeLists.txt b/openhantek/CMakeLists.txt
index 04fa8132..7fce2987 100644
--- a/openhantek/CMakeLists.txt
+++ b/openhantek/CMakeLists.txt
@@ -1,3 +1,5 @@
+# openhantek/CMakeLists.txt
+
project(OpenHantek CXX)
find_package(Qt5Widgets REQUIRED)
@@ -22,26 +24,56 @@ file(GLOB_RECURSE HEADERS "src/*.h")
file(GLOB_RECURSE UI "src/*.ui")
file(GLOB_RECURSE QRC "res/*.qrc")
+if(WIN32)
+ file(GLOB_RECURSE RC "res/*.rc")
+endif()
+
add_custom_target(format SOURCES ".clang-format"
COMMAND "clang-format" "-style=file" "-i" "-sort-includes" ${SRC} ${HEADERS})
-add_subdirectory(translations)
+# here the translation magic happens
+include(translations/Translations.cmake)
add_definitions(-DVERSION="${CPACK_PACKAGE_VERSION}")
+message( STATUS "VERSION: ${CPACK_PACKAGE_VERSION}" )
set(EXECTYPE "")
if(WIN32 AND MINGW)
set(EXECTYPE WIN32)
endif()
+# Enable MacOSX bundle magic in the next line
+option(BUILD_MACOSX_BUNDLE "Build MacOS app bundle" ON)
+#
+if( APPLE AND BUILD_MACOSX_BUNDLE )
+ set( EXECTYPE MACOSX_BUNDLE )
+ set( MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}" )
+ set( MACOSX_BUNDLE_INFO_STRING "Digital oscilloscope software for Hantek DSO6022" )
+ set( MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_NAME}" )
+ set( MACOSX_BUNDLE_SHORT_VERSION_STRING ${VCS_REVISION} )
+ set( MACOSX_BUNDLE_BUNDLE_VERSION ${CPACK_PACKAGE_VERSION} )
+ string(TIMESTAMP THISYEAR "%Y")
+ set( MACOSX_BUNDLE_COPYRIGHT "(C) 2012-${THISYEAR} OpenHantek community" )
+ set( MACOSX_BUNDLE_ICON_FILE openhantek.icns )
+ set( ICONS ${CMAKE_CURRENT_SOURCE_DIR}/res/images/openhantek.icns )
+ set_source_files_properties( ${ICONS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources" )
+endif()
+
# make executable
-add_executable(${PROJECT_NAME} ${EXECTYPE} ${SRC} ${HEADERS} ${UI} ${QRC} ${TRANSLATION_BIN_FILES} ${TRANSLATION_QRC})
+add_executable(${PROJECT_NAME} ${EXECTYPE} ${SRC} ${HEADERS} ${UI}
+${QRC} ${RC} ${TRANSLATION_BIN_FILES} ${TRANSLATION_QRC} ${ICONS})
target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::PrintSupport Qt5::OpenGL ${OPENGL_LIBRARIES} )
target_compile_features(${PROJECT_NAME} PRIVATE cxx_range_for)
if(MSVC)
target_compile_options(${PROJECT_NAME} PRIVATE "/W4" "/wd4251" "/wd4127" "/wd4275" "/wd4200" "/nologo" "/J" "/Zi")
target_compile_options(${PROJECT_NAME} PRIVATE "$<$:/MDd>")
else()
+ if( APPLE AND BUILD_MACOSX_BUNDLE )
+ # Use own template that defines NSPrincipalClass=NSApplication & NSHighResolutionCapable=True
+ set_target_properties( ${PROJECT_NAME} PROPERTIES
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_LIST_DIR}/../cmake/OpenHantekBundleInfo.plist.in
+ )
+ endif()
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wno-long-long -pedantic)
target_compile_options(${PROJECT_NAME} PRIVATE "$<$:-DDEBUG>")
target_compile_options(${PROJECT_NAME} PRIVATE "$<$:-O0>")
@@ -65,6 +97,7 @@ if(NOT WIN32)
endif()
# install commands
-install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION "bin")
-
+if ( NOT (APPLE AND BUILD_MACOSX_BUNDLE) )
+ install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION "bin")
+endif()
include(../cmake/copy_qt5_dlls_to_bin_dir.cmake)
diff --git a/openhantek/readme.md b/openhantek/readme.md
deleted file mode 100644
index 5ac9b656..00000000
--- a/openhantek/readme.md
+++ /dev/null
@@ -1,80 +0,0 @@
-# OpenHantek developer documentation
-
-This document explains the basic data flow and concepts used and should be amended
-whenever a new concept is added to the code base.
-Detailed information about an implementation are to be found in the specific directory readmes though.
-
-## Directory structure
-
-The *res* folder contains mostly binary resource data that are bundled with the executable,
-like icons, images and firmwares.
-
-The *translations* folder contains translations in the Qt format. Use Qt linguist
-as a handy graphical interface to translate OpenHantek.
-
-The source code within *src* can be divided into a **core**, that is responsible for device communication,
-data acquisition and post processing and the **graphical interface** with several custom widgets,
-a configuration interface and an OpenGL renderer.
-
-### Core structure
-
-The raw device communcation takes place in the *src/usb* directory, especially via the `USBDevice` class.
-To find suitable devices, the `FindDevices` class in the same folder is used. Firmware upload is realized
-via the `ezusb` helper methods and the `UploadFirmware` class.
-
-The hantek protocol structures and constants are defined within `src/hantekprotocol`.
-
-The heart of OpenHantek is the `src/hantekdso` folder and its `hantekdsocontrol` class. All supported
-models, based on the `DsoModel` class, are implemented within a subfolder `src/hantekdso/models` and automatically register themself
-to a `ModelRegistry` class. A model is based on (contains) a specification, the `ControlSpecification` class.
-
-The `hantekdsocontrol` class keeps track of the devices current state (samplerate, selected gain, activated channels, etc)
-via the `ControlSettings` class and field.
-It outputs the channel separated unprocessed samples via a `samplesAvailable(DSOsamples*)` signal.
-
-Before the data is presented to the GUI it arrives in the `src/post/postprocessing` class. Several post
-processing classes are to be found in this directory as well.
-
-### Graphical interface structure
-
-The initial dialog for device selection is realized in *src/selectdevice* where several models
-and dialogs are implemented. This is basically a graphical wrapper around the `src/usb/finddevices` class.
-
-You will find the configuration dialog pages to be implemented in *src/configdialog*.
-
-Custom widgets like a LevelSlider with a unit suffix reside in *src/widgets*, the custom main window docks are
-in *src/docks*.
-
-The code that is responsible for exporting data to images or to the printer is stored in *src/exporting*.
-
-The main window itself doesn't do and shouldn't do much more than connecting signals/slots between the core part
-and the graphical part.
-
-All OpenGL rendering takes place in the `GlScope` class. A helper class `GlScopeGraph` contains exactly one
-data sample snapshot including all channels for voltage and spectrum and a pointer to the respective GPU buffer.
-`GlScope` works for OpenGL 3.2 and OpenGL ES 2.0. If both is present, OpenGL will be prefered, but can be
-overwritten by the user via a command flag.
-
-### Export
-
-All export related funtionality is within *src/exporting*.
-
-The following exporters are implemented:
-
-* Export to comma separated value file (CSV): Write to a user selected file,
-* Export to an image/pdf: Writes an image/pdf to a user selected file,
-* Print exporter: Creates a printable document and opens the print dialog.
-
-All export classes (exportcsv, exportimage, exportprint) implement the
-ExporterInterface and are registered to the ExporterRegistry in the main.cpp.
-
-Some export classes are still using the legacyExportDrawer class to
-draw the grid and paint all the labels, values and graphs.
-
-The plan is to retire this legacy class and replace the paint code with
-a `GlScope` class shared OpenGL drawing code for at least the grid and the
-scope graphs.
-
-## Data flow
-
-To be written
diff --git a/openhantek/res/OpenHantek.rc b/openhantek/res/OpenHantek.rc
new file mode 100644
index 00000000..563f8e40
--- /dev/null
+++ b/openhantek/res/OpenHantek.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "images/OpenHantek.ico"
diff --git a/openhantek/res/application.qrc b/openhantek/res/application.qrc
index 22f9432e..dc7d3638 100644
--- a/openhantek/res/application.qrc
+++ b/openhantek/res/application.qrc
@@ -1,10 +1,22 @@
- images/openhantek.png
- images/switch.png
+ images/switch_6022BL.pngimages/fontawesome-4.7.0.ttf
- images/openhantek.svg
- images/digitalphosphor.svg
+ images/OpenHantek.svg
+ images/phosphor.svg
+ images/histogram.svg
+ images/measure.svg
+ images/pause.svg
+ images/play.svg
+ images/refresh.svg
+ images/zoom.svg
+ images/darktheme/phosphor.svg
+ images/darktheme/histogram.svg
+ images/darktheme/measure.svg
+ images/darktheme/pause.svg
+ images/darktheme/play.svg
+ images/darktheme/refresh.svg
+ images/darktheme/zoom.svg
diff --git a/openhantek/res/configdialog.qrc b/openhantek/res/configdialog.qrc
index 72ad7f3e..0d451255 100644
--- a/openhantek/res/configdialog.qrc
+++ b/openhantek/res/configdialog.qrc
@@ -1,8 +1,7 @@
- images/config/analysis.png
- images/config/colors.png
+ images/config/spectrum.pngimages/config/scope.png
- images/config/files.png
+ images/config/colors.png
diff --git a/openhantek/res/firmware/dds120-firmware.hex b/openhantek/res/firmware/dds120-firmware.hex
new file mode 100644
index 00000000..94862a31
--- /dev/null
+++ b/openhantek/res/firmware/dds120-firmware.hex
@@ -0,0 +1,220 @@
+:203D000012010002FFFFFF40B50420010001010203010A0600020000004001000902890088
+:203D200001010080370904000001FF000000070586020002000904000101FF00010007050C
+:203D400082010014010904000201FF00010007058201000C010904000301FF000100070502
+:203D600082010004010904000401FF000100070582010004020904000501FF0001000705F5
+:203D800082010004030904000601FF000100070582010004040904000701FF0001000705CD
+:053DA000820100020495
+:203DA6000902390002010080370904000001FF000000070586024000000904000101FF0010
+:193DC600010007058201FF03010904000201FF00010007058201000201AF
+:203DE000040309040E0373006900670072006F006B0010036600780032006C0061006600B9
+:203E0000770022035300610069006E0053006D006100720074002000440044005300310048
+:063E20003200300000003A
+:040000000201B9320E
+:01000B0032C2
+:0100130032BA
+:01001B0032B2
+:0100230032AA
+:03002B000203AD20
+:030033000202E4E2
+:01003B003292
+:01004300328A
+:01004B003282
+:01005300327A
+:01005B003272
+:01006300326A
+:03006B000202E7A7
+:03007300020D2A51
+:03007B000208EA8E
+:03008300020395E0
+:03008B000202FF6F
+:0300930002034A1B
+:03009B000208E771
+:0300A300020D54F7
+:0300AB00020D55EE
+:0300B300020D56E5
+:0300BB00020D59DA
+:0300C300020D2902
+:0300CB00020D46DD
+:0300D300020D47D4
+:0300DB00020D49CA
+:0300E3000208EC24
+:0300EB00020DD132
+:0300F3000208E818
+:0300FB000208E90F
+:030103000208EB04
+:03010B000208EDFA
+:030113000208EEF1
+:03011B00020DB41E
+:03012300020D5278
+:03012B00020D576B
+:03013300020D5A60
+:03013B00020D5C56
+:03014300020D5357
+:03014B00020D584A
+:03015300020D5B3F
+:03015B00020D5D35
+:03016300020DB3D7
+:03016B00020D4A38
+:03017300020D4C2E
+:03017B00020D4E24
+:03018300020D501A
+:03018B00020D4B17
+:03019300020D4D0D
+:03019B00020D4F03
+:0301A300020D51F9
+:0301AB00020D48FA
+:0301B300020D2812
+:0C021200750800E4F509F50AC200C201FD
+:030230000201B612
+:0301B6000207D865
+:20023300E582FF70407E0EE4FDFC7401B51302801C7402B5130280197405B513028016742B
+:200253000AB5130280137414B5131680107B0280647B0680607B00805C7B0480587B0880BB
+:200273005475820022BF01497E307D027401B51302801C7402B51302801B7405B51302804F
+:200293001A740AB5130280197414B5132080187B007C0280207B107C02801A7B007C008095
+:2002B300147B107C00800E7B207C0080087582002275820022EEF4FFE5A05207EE5B4FF565
+:2002D300A0EDF4FFE5B15207ED5C4FF5B175820122C2DC32C0E0C082C083D2005391EF901A
+:2002F300E65D7401F0D083D082D0E032C021C0E0C0F0C082C083C007C006C005C004C0032D
+:20031300C002C001C000C0D075D000758200120C185391EF90E65D7410F0D0D0D000D0012A
+:20033300D002D003D004D005D006D007D083D082D0F0D0E0D02132C021C0E0C0F0C082C044
+:2003530083C007C006C005C004C003C002C001C000C0D075D000758201120C185391EF9085
+:20037300E65D7420F0D0D0D000D001D002D003D004D005D006D007D083D082D0F0D0E0D082
+:200393002132C0E0C082C083D2015391EF90E65D7408F0D083D082D0E032C0E0C007C00639
+:2003B300C0D075D000AEB17F006306048EB1E509450A6010150974FFB50902150AE509457B
+:2003D3000A700100C2CFD0D0D006D007D0E032E582FF30E00BADB17E004305088DB1800361
+:2003F30053B1F7EF30E408AEB14306018EB12253B1FE22AF82BF01028003BF021174072FC4
+:20041300FF90E618F090E61AEFF0758201227582002290E6F574FFF000000090E60474806E
+:20043300F000000090E6047482F000000090E6047486F000000090E604E4F02290E6F574A6
+:20045300FFF0000000E50870057E06FF80047E027F0090E648EEF022D2871204257EE87FFB
+:2004730003EE24FFFCEF34FFFD8C068D07EC4D70F0E5BB30E7FB00000090E6D07428F000F7
+:20049300000090E6D1E4F0E50870057E06FF80047E047F008EBB00E4F509F50A22AF8290B7
+:2004B300E680E030E7067D1C7E3D80047DA67E3D8F03E4CBC4CB6BCB54F0CB6BFC74162BDF
+:2004D300FBE43CFCEB2DFDEC3EFC7E80EFF508703590E612E4F090E61474E0F090E6E27432
+:2004F30001F08D828C838EF0120DB590E625F074012DFAE43CFB8E078A828B838FF0120DF9
+:20051300B590E624F02290E61274D8F090E614E4F090E6D204F08D828C838EF0120DB59009
+:20053300E621F00DBD00010C8D828C838EF0120DB5FF90E62074075FF08D828C838EF0125D
+:200553000DB5C423541F90E64004F022AF827E00EE75F007A4FCADF024D6F582ED340DF5C6
+:2005730083E493FBB5070280080EBE11E375820022EC24D6FCED340DFD74062CF582E43D09
+:20059300F583E49390E601F075AF07759DE4759E008C828D83A3E49390E67CF08C828D8386
+:2005B300A3A3E49390E67CF07401F0E4F0F0F0F0F08C828D83A3A3A39390E67CF08C828D79
+:2005D30083A3A3A3A3E49390E67CF07401F0E4F0F0F0F0F08C828D83A3A3A3A3A39390E651
+:2005F3007CF07444F0F0E4F0F0F0F0F0F0F0F0F0F0F0F0F07F0090E67CE4F00FBF6000401D
+:20061300F575820122AF82BF00028049BF01028062BF02028067BF050302069ABF0A030278
+:2006330006A4BF14030206AEBF69028014BF6A028019BF6E02801EBF78028023BF9666800B
+:200653002875CAF075CBD87582012275CA7375CBDF7582012275CA7875CBEC7582012275A1
+:20067300CA3C75CBF67582012275CA1875CBFC7582012275CA0C75CBFE7582012275CA067C
+:2006930075CBFF7582012275CA9C75CBFF7582012275CACE75CBFF7582012275CAE775CBEE
+:2006B300FF7582012275820022AD13AE14AF158D828E838FF0E508120D2B75820122E58258
+:2006D3007006850B821204B0758201227582002275820122AF82C00712044FD007007509BA
+:2006F300E8750A03BFE0004015EF2419401090E68AE4F090E68BF090E6A0E020E1F9BFE0B9
+:2007130000500302078EEF2419500302078EEF2420FE2E90072A73800C800A801B8026805C
+:2007330033803E8049EF2420FF90E740E0F5138F821202337582012290E740E0F582120584
+:200753005F7582012290E740E0FFBF010312046B7582012290E740E0F582120406758201F7
+:200773002290E740E0F5821203E27582012290E740E0F58212061875820122758200229024
+:20079300E613E4F090E615F0D28790E6C2E4F090E6C37480F090E6C0E4F090E6F4F0120402
+:2007B3004F75130175820012023375130175820112023375820112055F7582021204067550
+:2007D30082000204B090E600E053E0E7F0120792E500D2E890E668E0FF43070890E668EF48
+:2007F300F090E65CE0FF43070190E65CEFF0E0FF43071090E65CEFF0E0FF43072090E65C44
+:20081300EFF0E0FF43070890E65CEFF0D2DDD2AF75CA0C75CBFE75C800D2ADD2CA90E680FD
+:20083300E043E00AF09005DC120D5E90E680E053E0F7F090E672E4F090E671F090E670F061
+:2008530075B6FF75B4FF75B2FF10000280031208EF10010280F390E682E043E0C0F090E6C8
+:20087300817401F0AE877F004306018E8700000000000000E50E701C90E682E030E6079068
+:20089300E682E020E0D090E682E030E70790E682E020E1C290E682E030E60790E682E020AF
+:2008B300E00E90E682E030E7A090E682E030E199900005120D5E90E680E0FF43070190E67E
+:1408D30080EFF090000F120D5E90E680E053E0FEF002085C39
+:200DD600308000030000EA1E8000030000AA180100020140EA100101020040EA0F0100027F
+:200DF6000140AA0C0201020040EA0B0101020040AA080302020040EA060202020040AA058A
+:200E16000302020040AA040605020040EA030504020040AA020C0B020040EA011817020021
+:170E360040EA32302F020040EA147877020040EA0AF0EF020040EA7A
+:0108E70032DE
+:0108E80032DD
+:0108E90032DC
+:0108EA0032DB
+:0108EB0032DA
+:0108EC0032D9
+:0108ED0032D8
+:0108EE0032D7
+:0601E800E478FFF6D8FDEB
+:12021E00750D00750E00750FA675103D75111C75123D77
+:2008EF0090E6B9E0FF24F45003020A13EF240A83F582EF241083F583E473213D13591313D5
+:20090F0075137B92B4EE09090A090A0A090A09090909120A95E5826003020A2F90E6A0E075
+:20092F00FF7E0043070190E6A0EFF0020A2F120B29E5826003020A2F90E6A0E0FF7E0043AF
+:20094F00070190E6A0EFF0020A2F120B77E5826003020A2F90E6A0E0FF7E0043070190E683
+:20096F00A0EFF0020A2F120C43020A2F1206DFAF8290E740EFF090E68AE4F090E68B04F08B
+:20098F00020A2F90E6BAE0F5821206E3E5826003020A2F90E6A0E0FF7E0043070190E6A0B2
+:2009AF00EFF0020A2F90E6BCE0FF75130C7514007515408F821206BCE582701190E6A0E053
+:2009CF00FF7E0043070190E6A0EFF0805390E740E50CF090E68AE4F090E68B04F0804190C6
+:2009EF00E6BCE0FF90E6BAE0F50B8F821206D1E582702D90E6A0E0FF7E0043070190E6A085
+:200A0F00EFF0801C90E6B9E0F5821206E7E582700F90E6A0E0FF7E0043070190E6A0EFF02E
+:200A2F0090E6A0E0FF43078090E6A0EFF022AF82747F5FFE24F75003020A91EE240A83F5B1
+:200A4F0082EE240D83F583E4736A6E8191859189918D0A0A0A0A0A0A0A0A0A90E6A022EF6C
+:200A6F0030E7067EA27FE680047EA17FE68E828F832290E6A32290E6A42290E6A52290E64F
+:200A8F00A6229000002290E6B8E0FFBF80028022BF81028008BF82028037020B2190E74034
+:200AAF00E4F090E741F090E68AF090E68B7402F08064E50E25E0FFE50D420790E740EFF0A8
+:200ACF0090E741E4F090E68AF090E68B7402F0804590E6BCE0F582120A3DAE82AF838E0489
+:200AEF008F05EE4F7003F582228C828D83E0FC30E0067E017F0080047E007F0090E740EED6
+:200B0F00F090E741E4F090E68AF090E68B7402F08004758200227582012290E6B8E0FF60CF
+:200B2F0005BF0237801190E6BAE0FFBF0105750E0080317582002290E6BAE0701A90E6BC2B
+:200B4F00E0F582120A3DAE82AF83E0FD5305FE8E828F83EDF0800D7582002290E6B9E0F598
+:200B6F00820206E77582012290E6B8E0FF6008BF02028020020C0B90E6BAE0FFBF02030215
+:200B8F000C1490E6BAE0FFBF0106750E01020C147582002290E6BAE0705E90E6BCE0F5822B
+:200BAF00120A3DAE82AF83EE4F7003F582228E828F83E0FD7C004305018E828F83EDF090CF
+:200BCF00E6BCE0FF53070F90E6BCE0FE530680E4C423CEC423541F6ECE541FCE6ECE30E473
+:200BEF000244E0FD90E683EE2FF0E0FF7E0043072090E683EFF0800D7582002290E6B9E069
+:200C0F00F5820206E775820122AF827E0110AF027E00EF600E750F1C75103D7511A67512E4
+:200C2F003D800C750FA675103D75111C75123DEE1392AF2290E6BBE0FFBF01028019BF02FA
+:200C4F00028024BF0302802CBF0603020CFDBF0703020D0D020D1A7E007F3D90E6B3EFF04C
+:200C6F0090E6B47400F02290E6B3E510F090E6B4E50FF0227DE07E3D7F8090E6BAE0F51348
+:200C8F007B008B020BEAB5130280428D008E018F028D828E838FF0120DB528F8E439F988DE
+:200CAF000589068A0774012DF9E43EFA8F0489828A838CF0120DB5F9B9030280067D007E16
+:200CCF00007F00ED4E6006C3E5139B50B5ED4E600F8D038E0490E6B3ECF090E6B4EDF02290
+:200CEF0090E6A0E0FF43070190E6A0EFF0227E127F3D90E6B3EFF090E6B47412F02290E602
+:190D0F00B3E512F090E6B4E511F02290E6A0E0FF43070190E6A0EFF022A8
+:2001C6007900E94400601B7A00900E4D780075923CE493F2A308B800020592D9F4DAF27565
+:0201E60092FF86
+:010D28003298
+:010D29003297
+:010D2A003296
+:1B0D2B0020F71130F6138883A88220F509F6A8837583002280FEF280F5F022C7
+:010D4600327A
+:010D47003279
+:010D48003278
+:010D49003277
+:03004300023F0079
+:203F00000202E700020D2A000208EA00020395000202FF0002034A000208E700020D53004A
+:203F2000020D5400020D5500020D5600020D5900020D2900020D4600020D4700020D4900B2
+:203F40000208EC00020D5300020DD1000208E8000208E9000208EB000208ED000208EE0060
+:203F6000020DB400020D5300020D5300020D5300020D5200020D5700020D5A00020D5C00BD
+:203F8000020D5800020D5B00020D5D00020DB300020D4A00020D4C00020D4E00020D5000B2
+:183FA000020D4B00020D4D00020D4F00020D5100020D4800020D280007
+:010D4A003276
+:010D4B003275
+:2001EE007800E84400600A790075923CE4F309D8FC7800E84400600C7900903C00E4F0A3A7
+:04020E00D8FCD9FA45
+:010D4C003274
+:010D4D003273
+:010D4E003272
+:010D4F003271
+:010D50003270
+:010D5100326F
+:010D5200326E
+:010D5300326D
+:010D5400326C
+:010D5500326B
+:010D5600326A
+:010D57003269
+:010D58003268
+:010D59003267
+:010D5A003266
+:010D5B003265
+:010D5C003264
+:010D5D003263
+:200D5E00AE82AF8390E600E05418C423541F70057CB1FD801C90E600E05418C423541FFBA5
+:200D7E00BB01067A617B0180047AC27B028A048B058C138D14151374FFB513021514E5131B
+:150D9E00451470F1EE24FFFAEF34FFFB8A068B07EA4B70DD2298
+:010DB300320D
+:010DB400320C
+:0D01B900758121120DD2E58260030201B6AE
+:1C0DB50020F71430F6148883A88220F507E6A88375830022E280F7E49322E0224D
+:010DD10032EF
+:040DD2007582002204
+:00000001FF
diff --git a/openhantek/res/firmware/dso2090x86-firmware.hex b/openhantek/res/firmware/dso2090x86-firmware.hex
deleted file mode 100644
index 891ac6b1..00000000
--- a/openhantek/res/firmware/dso2090x86-firmware.hex
+++ /dev/null
@@ -1,372 +0,0 @@
-:0A0BF50000010202030304040505D9
-:1008AF00E4F52DF52CF52BF52AC20BC208C20AC2AE
-:1008BF0009120CB8E4F50AF50BD2A6C2C975CDFC26
-:1008CF0075CC2AD2CAD2AFD2AD7508087509077E8A
-:1008DF00007F908E0E8F0F7516007517A2750C0086
-:1008EF00750DAC7514007515CC7518007519EC9055
-:1008FF00E680E030E70E850C10850D11851412850A
-:10090F001513800C851410851511850C12850D1388
-:10091F00EE54E07003020A3B752E00752F807E00A7
-:10092F007F908E308F31C374129FFF74019ECF243E
-:10093F0002CF3400FEE48F298E28F527F526F52502
-:10094F00F524F523F522AF29AE28AD27AC26AB252C
-:10095F00AA24A923A822C3120E17502AE52F252552
-:10096F00F582E52E3524F58374CDF0E4FAF9F8E538
-:10097F00252401F525EA3524F524E93523F523E867
-:10098F003522F52280C0E4F525F524F523F522AFB5
-:10099F0029AE28AD27AC26AB25AA24A923A822C3AC
-:1009AF00120E175035AE24AF25E5312FF582E53005
-:1009BF003EF583E0FDE52F2FF582E52E3EF583ED25
-:1009CF00F0E4FAF9F8EF2401F525EA3EF524E935CC
-:1009DF0023F523E83522F52280B5852E0E852F0FBE
-:1009EF0074902480FF740034FFFEC3E5179FF51742
-:1009FF00E5169EF516C3E5119FF511E5109EF5104E
-:100A0F00C3E5139FF513E5129EF512C3E50D9FF590
-:100A1F000DE50C9EF50CC3E5159FF515E5149EF538
-:100A2F0014C3E5199FF519E5189EF518D2E843D8B8
-:100A3F002090E668E04409F090E65CE0443DF0D297
-:100A4F00AF90E680E020E105D20E1210C490E68050
-:100A5F00E054F7F0538EF8C20B300905120616C298
-:100A6F0009300B2912124A5024C20B12114B2008C5
-:100A7F001690E682E030E704E020E1EF90E682E0B6
-:100A8F0030E604E020E0E41210F312124C120BFFD8
-:020A9F0080C70E
-:010AA1002232
-:1006160090E6B9E070030206F114700302079A240B
-:10062600FE700302082F24FB70030206EB1470030E
-:100636000206E51470030206D91470030206DF24CD
-:1006460005600302089B12124E40030208A790E6BB
-:10065600BBE024FE602C14604724FD601614603154
-:1006660024067065E50E90E6B3F0E50F90E6B4F06B
-:100676000208A7E51690E6B3F0E51790E6B4F00297
-:1006860008A7E51090E6B3F0E51190E6B4F002088D
-:10069600A7E51290E6B3F0E51390E6B4F00208A7DA
-:1006A60090E6BAE0FF12111FAA06A9077B01EA49E4
-:1006B600600DEE90E6B3F0EF90E6B4F00208A79076
-:1006C600E6A0E04401F00208A790E6A0E04401F0AD
-:1006D6000208A71212160208A712123A0208A71257
-:1006E6000F4E0208A71212040208A7121250400366
-:1006F6000208A790E6B8E0247F602B14603C240231
-:100706006003020790A208E433FF25E0FFA20AE493
-:10071600334F90E740F0E4A3F090E68AF090E68B42
-:100726007402F00208A7E490E740F0A3F090E68A8E
-:10073600F090E68B7402F00208A790E6BCE0547EC7
-:10074600FF7E00E0D3948040067C007D0180047C1F
-:10075600007D00EC4EFEED4F24F5F582740B3EF560
-:1007660083E493FF3395E0FEEF24A1FFEE34E68F9A
-:1007760082F583E0540190E740F0E4A3F090E68A26
-:10078600F090E68B7402F00208A790E6A0E0440120
-:10079600F00208A712125240030208A790E6B8E03A
-:1007A60024FE601D240260030208A790E6BAE0B4A6
-:1007B6000105C2080208A790E6A0E04401F002087D
-:1007C600A790E6BAE0705990E6BCE0547EFF7E0042
-:1007D600E0D3948040067C007D0180047C007D008F
-:1007E600EC4EFEED4F24F5F582740B3EF583E49353
-:1007F600FF3395E0FEEF24A1FFEE34E68F82F5830A
-:10080600E054FEF090E6BCE05480FF131313541F2F
-:10081600FFE0540F2F90E683F0E04420F00208A793
-:1008260090E6A0E04401F08078121254507390E6EE
-:10083600B8E024FE60202402706790E6BAE0B401B6
-:1008460004D208805C90E6BAE06402605490E6A0A8
-:10085600E04401F0804B90E6BCE0547EFF7E00E071
-:10086600D3948040067C007D0180047C007D00ECF2
-:100876004EFEED4F24F5F582740B3EF583E493FFAF
-:100886003395E0FEEF24A1FFEE34E68F82F583E098
-:100896004401F0800C120114500790E6A0E04401D8
-:0808A600F090E6A0E04480F0B0
-:0108AE002227
-:0300330002008C3C
-:04008C0053D8EF3224
-:03002B00020F13AE
-:100F1300C0E0B2A5E509150970021508E509450801
-:100F2300701E75080475091FE50B6401450A7006F8
-:100F3300B2A6D2A78004B2A7D2A6750A00750B0089
-:0B0F430075CDFC75CC23C2CFD0E0328E
-:100090001201000200000040B5049020000001029F
-:1000A00000010A06000200000040010009022000D1
-:1000B000010100A0FA0904000002FF00000007058A
-:1000C0000202000200070586020002000902200069
-:1000D000010100A0FA0904000002FF00000007056A
-:1000E00002024000000705860240000004030904E4
-:1000F0000E034F0044004D00200020002000140398
-:10010000440053004F002D00320030003900300011
-:0401100020000000CB
-:03004300020C00AC
-:03005300020C009C
-:100C00000211A8000211EE000211D8000211C0006A
-:100C1000020F8500020FBC0002125600021257009C
-:100C2000021258000212590002125A0002125B000E
-:100C300002125C0002125D0002125E0002125F00EE
-:100C400002126000021257000212610002126200DA
-:100C500002126300021264000212650002126600B2
-:100C600002126700021257000212570002125700C8
-:100C7000021268000212690002126A0002126B007E
-:100C800002126C0002126D0002126E0002126F005E
-:100C9000021270000212710002127200021273003E
-:100CA000021274000212750002127600021277001E
-:080CB000021278000212790023
-:1010F30090E682E030E004E020E60B90E682E03008
-:10110300E119E030E71590E680E04401F07F147EBA
-:0C11130000120ECD90E680E054FEF022A9
-:10114B0090E682E044C0F090E681F0438701000016
-:04115B00000000226E
-:1010C400300E0990E680E0440AF0800790E680E064
-:1010D4004408F07FDC7E05120ECD90E65D74FFF0CF
-:0F10E40090E65FF05391EF90E680E054F7F02232
-:02111F00A9071E
-:10112100AE18AF198F828E83A3E064037017AD01EF
-:1011310019ED7001228F828E83E07C002FFDEC3E41
-:09114100FEAF0580DF7E007F0097
-:01114A002282
-:100ECD008E3C8F3D90E600E054187012E53D2401F4
-:100EDD00FFE4353CC313F53CEF13F53D801590E66B
-:100EED0000E05418FFBF100BE53D25E0F53DE53C56
-:100EFD0033F53CE53D153DAE3C7002153C4E6005AD
-:060F0D0012115F80EE22CC
-:10115F007400F58690FDA57C05A3E582458370F9A3
-:01116F00225D
-:100CB80090E600740AF090E6017443F0000000909A
-:100CC800E61274A0F0000000E490E613F0000000C3
-:100CD80090E61474E0F0000000E490E615F00000DF
-:100CE8000090E6047480F00000007402F000000038
-:100CF8007406F0000000E4F000000090E60274E6DC
-:100D0800F000000090E60374F8F000000090E67030
-:100D1800E04440F0000000E490E609F000000043E1
-:100D2800B20F90E61804F00000007411F000000003
-:100D380090E61A7409F0000000E490E671F090E67D
-:100D480072F075B4FF75B6FFC280C20C12124290E1
-:070D5800E67AE04401F022FD
-:010BFF0022D3
-:02124A00D322AD
-:02124C00D322AB
-:02124E00D322A9
-:100F4E0090E680E030E71590E6247402F000000091
-:100F5E00E490E625F0000000D20C8013E490E62425
-:100F6E00F000000090E6257440F0000000C20C90E6
-:070F7E00E6BAE0F51DD322E5
-:1012040090E740E51DF0E490E68AF090E68B04F068
-:02121400D322E3
-:08123A0090E6BAE0F51BD32297
-:1012160090E740E51BF0E490E68AF090E68B04F058
-:02122600D322D1
-:02125000D322A7
-:02125200D322A5
-:02125400D322A3
-:10011400750A00750B0190E678E05410FFC4540F83
-:100124004450F51C13E433F51E90E6B9E0245E70E8
-:100134000302044A24F0B40A0040030206129001A8
-:1001440049F82828730201670201830201C10202EF
-:10015400030203030203460203870203C8020409DD
-:100164000205D2A20CE43390E740F0E490E68AF072
-:1001740090E68B04F090E6A0E04480F0020614E4DC
-:1001840090E68AF090E68BF090E6A0E020E1F9900A
-:10019400E68BE0753600F53700000090E6047480C5
-:1001A400F00000007406F0000000E4F043800BD27D
-:1001B40080C28090E6A0E04480F0020614E490E659
-:1001C4008AF090E68BF090E6A0E020E1F990E68BCF
-:1001D400E0753600F5377F0F7E00120ECD90E745AF
-:1001E400E0FF90E747E0FD90E743E0FB90E741E064
-:0F01F400F53F120E2890E6A0E04480F0020614BA
-:10020300E490E68AF090E68BF090E6A0E020E1F936
-:1002130090E68BE0753600F53790E741E0F5B17570
-:100223003A0F753BA0E53B153B7002153AE53B647D
-:100233000A453A70F090E742E0F5B1753A0F753B25
-:10024300A0E53B153B7002153AE53B640A453A705D
-:10025300F090E743E0F5B1753A0F753BA0E53B1528
-:100263003B7002153AE53B640A453A70F090E74467
-:10027300E0F5B1753A0F753BA0E53B153B700215F0
-:100283003AE53B640A453A70F090E745E0F5B1750D
-:100293003A0F753BA0E53B153B7002153AE53B640D
-:1002A3000A453A70F090E746E0F5B1753A0F753BB1
-:1002B300A0E53B153B7002153AE53B640A453A70ED
-:1002C300F090E747E0F5B1753A0F753BA0E53B15B4
-:1002D3003B7002153AE53B640A453A70F0E4F5B128
-:1002E300753A0F753BA0E53B153B7002153AE53BAC
-:1002F300640A453A70F090E6A0E04480F0020614E8
-:10030300E490E68AF090E68BF090E6A0E020E1F935
-:1003130090E68BE0753600F53700000090E6047434
-:1003230080F0000000C2807406F0000000E4F0904A
-:10033300E740E0FF7E00120ECD90E6A0E04480F09F
-:10034300020614E490E68AF090E68BF090E6A0E0D3
-:1003530020E1F990E68BE0753600F5370000009058
-:10036300E6047480F00000007406F0000000E4F07E
-:1003730090E740E0FF7E00120ECD90E6A0E04480BF
-:10038300F0020614E490E68AF090E68BF090E6A083
-:10039300E020E1F990E68BE0753600F537000000C8
-:1003A30090E6047480F00000007406F0000000E49E
-:1003B300F090E740E0FF7E00120ECD90E6A0E0440F
-:1003C30080F0020614E490E68AF090E68BF090E663
-:1003D300A0E020E1F990E68BE0753600F5370000E8
-:1003E3000090E6047480F00000007406F000000042
-:1003F300E4F090E740E0FF7E00120ECD90E6A0E02F
-:100403004480F0020614E490E68AF090E68BF090C4
-:10041300E6A0E020E1F990E68BE0753600F53700C1
-:10042300000090E6047480F00000007406F0000001
-:1004330000E4F090E740E0FF7E00120ECD90E6A0CE
-:10044300E04480F002061490E6BAE0753200F5331A
-:10045300A3E0FEE4EE423290E6BEE0753400F535EB
-:10046300A3E0FEE4EE423490E6B8E064C060030229
-:10047300053AE5354534700302061490E6A0E02002
-:10048300E1F9C3E5359440E53494005008853436EA
-:10049300853537800675360075374090E6B9E0B488
-:1004A300A335E4F538F539C3E5399537E53895369D
-:1004B3005060E5332539F582E5323538F583E0FFC1
-:1004C30074402539F582E434E7F583EFF00539E527
-:1004D300397002053880D0E4F538F539C3E539952C
-:1004E30037E5389536501874402539F582E434E7FA
-:1004F300F58374CDF00539E5397002053880DDAD3B
-:10050300377AE779407EE77F40AB07AF33AE3212ED
-:100513000BAAE490E68AF090E68BE537F02533F5F5
-:1005230033E5363532F532C3E5359537F535E53400
-:100533009536F53402047590E6B8E0644060030232
-:100543000614E53545347003020614E490E68AF098
-:1005530090E68BF090E6A0E020E1F990E68BE07561
-:100563003600F53790E6B9E0B4A335E4F538F5394C
-:10057300C3E5399537E5389536503874402539F554
-:1005830082E434E7F583E0FFE5332539F582E5328C
-:100593003538F583EFF00539E5397002053880D039
-:1005A300AD377AE779407EE77F40AB07AF33AE32B2
-:1005B300121029E5372533F533E5363532F532C3E5
-:1005C300E5359537F535E5349536F534020545E4DB
-:1005D30090E68AF090E68BF090E6A0E020E1F990B7
-:1005E300E68BE0753600F53700000090E604748072
-:1005F300F00000007406F0000000E4F090E740E033
-:10060300FF7E00120ECD90E6A0E04480F08002D37E
-:0206130022C300
-:0106150022C2
-:1011A800C0E0C083C082D2095391EF90E65D74011C
-:0811B800F0D082D083D0E032B8
-:1011D800C0E0C083C0825391EF90E65D7404F0D004
-:0611E80082D083D0E0324A
-:1011EE00C0E0C083C0825391EF90E65D7402F0D0F0
-:0611FE0082D083D0E03234
-:100F8500C0E0C083C08290E680E030E70E850C109B
-:100F9500850D11851412851513800C851410851582
-:100FA50011850C12850D135391EF90E65D7410F0C9
-:070FB500D082D083D0E032AE
-:1011C000C0E0C083C082D20B5391EF90E65D7408FB
-:0811D000F0D082D083D0E032A0
-:100FBC00C0E0C083C08290E680E030E70E850C1064
-:100FCC00850D11851412851513800C85141085154B
-:100FDC0011850C12850D135391EF90E65D7420F082
-:070FEC00D082D083D0E03277
-:011256003265
-:011257003264
-:011258003263
-:011259003262
-:01125A003261
-:01125B003260
-:01125C00325F
-:01125D00325E
-:01125E00325D
-:01125F00325C
-:01126000325B
-:01126100325A
-:011262003259
-:011263003258
-:011264003257
-:011265003256
-:011266003255
-:011267003254
-:011268003253
-:011269003252
-:01126A003251
-:01126B003250
-:01126C00324F
-:01126D00324E
-:01126E00324D
-:01126F00324C
-:01127000324B
-:01127100324A
-:011272003249
-:011273003248
-:011274003247
-:011275003246
-:011276003245
-:011277003244
-:011278003243
-:011279003242
-:10122800AD071FED600BE4FEEEC3947850F20E801C
-:01123800F7BE
-:011239002292
-:040D5F00A907AB0530
-:100D63007F01121228D2A27F01121228C2A2E4FA32
-:100D7300E9A802088002C333D8FCFC5304807F0136
-:100D8300121228D2A1BC8004D2A08002C2A07F018B
-:100D9300121228C2A10ABA08D7E4FAEBA802088003
-:100DA30002C333D8FCFC5304807F01121228D2A162
-:100DB300BC8004D2A08002C2A07F01121228C2A16B
-:040DC3000ABA08D789
-:010DC7002209
-:040E2800AE07AC0560
-:100E2C00EEC4540F4410FFEEC454F0FDECC4540F48
-:100E3C004450F540ECC454F0F541EBC4540F4490CD
-:100E4C00F542EBC454F0F543E53FC4540F44D0F5E0
-:100E5C0044E53FC454F0F545C2A0C2A1C2A2120D94
-:100E6C005FAD41AF40120D5FAD43AF42120D5FADB0
-:060E7C0045AF44120D5FBA
-:010E8200224D
-:060E8300AB07AA06AC0556
-:100E8900E4FDE51E6010EA7E000DEE2400F582E423
-:100E99003418F583EAF0EBAE050D74002EF582E403
-:100EA9003418F583EBF0AF050D74002FF582E434A7
-:100EB90018F583ECF07A187B00AF1C12118CAF1C6B
-:030EC900120FF312
-:010ECC002203
-:0A1029008E3C8F3D8D3E8A3F8B40C8
-:10103300E4F541E541C3953E5020053DE53DAE3C19
-:101043007002053C14FFE5402541F582E4353FF588
-:0A10530083E0FD120E83054180D9F1
-:01105D002270
-:0A0BAA008E3C8F3D8D3E8A3F8B404C
-:100BB400E4FDF541E51E6012E53CFF7E000DEE24E8
-:100BC40000F582E43418F583EFF0E53DAE050D74CD
-:100BD400002EF582E43418F583E53DF07A187B00A5
-:100BE400AF1C12118CAB40AA3FAD3EAF1C1211706A
-:010BF40022DE
-:08124200E4F54BD2E9D2AF2222
-:100FF30090E678E020E6F9C2E990E678E04480F0F4
-:10100300EF25E090E679F090E678E030E0F990E6BD
-:1010130078E04440F090E678E020E6F990E678E066
-:0610230030E1D6D2E92203
-:10109200A90790E678E020E6F9E54B702390E67820
-:1010A200E04480F0E925E090E679F08D46AF03A9AF
-:1010B200077547018A488949E4F54A754B01D322ED
-:0210C200C32247
-:10105E00A90790E678E020E6F9E54B702590E67852
-:10106E00E04480F0E925E0440190E679F08D46AF4A
-:10107E0003A9077547018A488949E4F54A754B0368
-:04108E00D322C32284
-:03004B00020AA204
-:100AA200C0E0C083C082C085C084C086758600C095
-:100AB200D075D000C000C001C002C003C006C0078C
-:100AC20090E678E030E206754B06020B8C90E678F1
-:100AD200E020E10CE54B64026006754B07020B8CCB
-:100AE200E54B24FE605F14603624FE7003020B7D2A
-:100AF20024FC7003020B8924086003020B8CAB47B1
-:100B0200AA48A949AF4A054A8F82758300120DC8C7
-:100B120090E679F0E54A65467070754B05806B90FA
-:100B2200E679E0AB47AA48A949AE4A8E82758300AE
-:100B3200120DF5754B02E5466401704E90E678E0C1
-:100B42004420F08045E54624FEB54A0790E678E069
-:100B52004420F0E54614B54A0A90E678E04440F0B5
-:100B6200754B0090E679E0AB47AA48A949AE4A8E98
-:100B720082758300120DF5054A800F90E678E044F5
-:100B820040F0754B008003754B005391DFD007D0C6
-:100B920006D003D002D001D000D0D0D086D084D0ED
-:080BA20085D082D083D0E0323F
-:1011700012105EE54B24FA600E146006240770F32B
-:0C118000D322E4F54BD322E4F54BD3223C
-:10118C00121092E54B24FA600E146006240770F3DB
-:0C119C00D322E4F54BD322E4F54BD32220
-:030000000200807B
-:0C008000787FE4F6D8FD75814B0208AFD4
-:100DC800BB010CE58229F582E5833AF583E02250E0
-:100DD80006E92582F8E622BBFE06E92582F8E2222A
-:0D0DE800E58229F582E5833AF583E4932244
-:100DF500F8BB010DE58229F582E5833AF583E8F034
-:100E0500225006E92582C8F622BBFE05E92582C8DF
-:020E1500F222C7
-:100E1700EB9FF5F0EA9E42F0E99D42F0E89C45F031
-:010E270022A8
-:00000001FF
diff --git a/openhantek/res/firmware/dso2090x86-loader.hex b/openhantek/res/firmware/dso2090x86-loader.hex
deleted file mode 100644
index d7758b6f..00000000
--- a/openhantek/res/firmware/dso2090x86-loader.hex
+++ /dev/null
@@ -1,60 +0,0 @@
-:1003680090E668E0FF74FFF0E0B40B04EFF0D322EE
-:0603780090E668EFF0C3FF
-:01037E00225C
-:1001B500907FE9E064A360030202C5A3E07508002F
-:1001C500F509A3E0FEE4EE4208907FEEE0750A0033
-:1001D500F50BA3E0FEE4EE420A907FE8E064407090
-:1001E50064E50B450A70030202D6E4907FC5F090E2
-:1001F5007FB4E020E3F9907FC5E0750C00F50DE4D0
-:10020500FCFDC3ED950DEC950C501F74C02DF582CA
-:10021500E4347EF583E0FFE5092DF582E5083CF53C
-:1002250083EFF00DBD00010C80D8E50D2509F5091A
-:10023500E50C3508F508C3E50B950DF50BE50A95B5
-:100245000CF50A809C907FE8E064C060030202D64A
-:10025500E50B450A607BC3E50B9440E50A94005025
-:1002650008850A0C850B0D8006750C00750D40E49C
-:10027500FCFDC3ED950DEC950C501FE5092DF582A0
-:10028500E5083CF583E0FF74002DF582E4347FF545
-:1002950083EFF00DBD00010C80D8907FB5E50DF022
-:1002A5002509F509E50C3508F508C3E50B950DF5A8
-:1002B5000BE50A950CF50A907FB4E030E29280F7E1
-:1002C500907FE9E0B4AC0AE4907F00F0907FB5043C
-:0802D500F0907FB4E04402F058
-:0102DD0022FE
-:1000800090E6B9E064A36003020198A3E07508005C
-:10009000F509A3E0FEE4EE420890E6BEE0750A0032
-:1000A000F50BA3E0FEE4EE420A90E6B8E06440708F
-:1000B00066E50B450A70030201ADE490E68AF0A301
-:1000C000F090E6A0E020E1F990E68BE0750C00F5F9
-:1000D0000DE4FCFDC3ED950DEC950C501F74402D07
-:1000E000F582E434E7F583E0FFE5092DF582E508C4
-:1000F0003CF583EFF00DBD00010C80D8E50D25091E
-:10010000F509E50C3508F508C3E50B950DF50BE58C
-:100110000A950CF50A809A90E6B8E064C060030284
-:1001200001ADE50B450A70030201ADC3E50B944038
-:10013000E50A94005008850A0C850B0D8006750CA5
-:1001400000750D40E4FCFDC3ED950DEC950C501FC2
-:10015000E5092DF582E5083CF583E0FF74402DF5B7
-:1001600082E434E7F583EFF00DBD00010C80D8E4A4
-:1001700090E68AF0A3E50DF02509F509E50C3508B0
-:10018000F508C3E50B950DF50BE50A950CF50A90FE
-:10019000E6A0E030E18C80F790E6B9E0B4AC0E90D8
-:1001A000E7407401F0E490E68AF0A304F090E6A042
-:0401B000E04480F0B7
-:0101B4002228
-:1002DE00C2011203689200907F95E044C0F0D2E80C
-:1002EE0030000890E65D74FFF08006907FAB74FFDF
-:1002FE00F030000890E6687408F08007907FAFE059
-:10030E004401F030000890E65C7401F08006907FA6
-:10031E00AE7401F0D2AF3001FD30000512008080C6
-:08032E00031201B5C20180EECB
-:03000300020336BF
-:10033600C0E0C083C082C085C084C086758600D2F6
-:10034600015391EF30000890E65D7401F08006904D
-:100356007FAB7401F0D086D084D085D082D083D094
-:02036600E03283
-:03004300020400B4
-:0404000002033600BD
-:0300000002037F79
-:0C037F00787FE4F6D8FD7581200202DED4
-:00000001FF
diff --git a/openhantek/res/firmware/dso2150x86-firmware.hex b/openhantek/res/firmware/dso2150x86-firmware.hex
deleted file mode 100644
index 00ab6553..00000000
--- a/openhantek/res/firmware/dso2150x86-firmware.hex
+++ /dev/null
@@ -1,372 +0,0 @@
-:0A0BF50000010202030304040505D9
-:1008AF00E4F52DF52CF52BF52AC20BC208C20AC2AE
-:1008BF0009120CB8E4F50AF50BD2A6C2C975CDFC26
-:1008CF0075CC2AD2CAD2AFD2AD7508087509077E8A
-:1008DF00007F908E0E8F0F7516007517A2750C0086
-:1008EF00750DAC7514007515CC7518007519EC9055
-:1008FF00E680E030E70E850C10850D11851412850A
-:10090F001513800C851410851511850C12850D1388
-:10091F00EE54E07003020A3B752E00752F807E00A7
-:10092F007F908E308F31C374129FFF74019ECF243E
-:10093F0002CF3400FEE48F298E28F527F526F52502
-:10094F00F524F523F522AF29AE28AD27AC26AB252C
-:10095F00AA24A923A822C3120E17502AE52F252552
-:10096F00F582E52E3524F58374CDF0E4FAF9F8E538
-:10097F00252401F525EA3524F524E93523F523E867
-:10098F003522F52280C0E4F525F524F523F522AFB5
-:10099F0029AE28AD27AC26AB25AA24A923A822C3AC
-:1009AF00120E175035AE24AF25E5312FF582E53005
-:1009BF003EF583E0FDE52F2FF582E52E3EF583ED25
-:1009CF00F0E4FAF9F8EF2401F525EA3EF524E935CC
-:1009DF0023F523E83522F52280B5852E0E852F0FBE
-:1009EF0074902480FF740034FFFEC3E5179FF51742
-:1009FF00E5169EF516C3E5119FF511E5109EF5104E
-:100A0F00C3E5139FF513E5129EF512C3E50D9FF590
-:100A1F000DE50C9EF50CC3E5159FF515E5149EF538
-:100A2F0014C3E5199FF519E5189EF518D2E843D8B8
-:100A3F002090E668E04409F090E65CE0443DF0D297
-:100A4F00AF90E680E020E105D20E1210C490E68050
-:100A5F00E054F7F0538EF8C20B300905120616C298
-:100A6F0009300B2912124A5024C20B12114B2008C5
-:100A7F001690E682E030E704E020E1EF90E682E0B6
-:100A8F0030E604E020E0E41210F312124C120BFFD8
-:020A9F0080C70E
-:010AA1002232
-:1006160090E6B9E070030206F114700302079A240B
-:10062600FE700302082F24FB70030206EB1470030E
-:100636000206E51470030206D91470030206DF24CD
-:1006460005600302089B12124E40030208A790E6BB
-:10065600BBE024FE602C14604724FD601614603154
-:1006660024067065E50E90E6B3F0E50F90E6B4F06B
-:100676000208A7E51690E6B3F0E51790E6B4F00297
-:1006860008A7E51090E6B3F0E51190E6B4F002088D
-:10069600A7E51290E6B3F0E51390E6B4F00208A7DA
-:1006A60090E6BAE0FF12111FAA06A9077B01EA49E4
-:1006B600600DEE90E6B3F0EF90E6B4F00208A79076
-:1006C600E6A0E04401F00208A790E6A0E04401F0AD
-:1006D6000208A71212160208A712123A0208A71257
-:1006E6000F4E0208A71212040208A7121250400366
-:1006F6000208A790E6B8E0247F602B14603C240231
-:100706006003020790A208E433FF25E0FFA20AE493
-:10071600334F90E740F0E4A3F090E68AF090E68B42
-:100726007402F00208A7E490E740F0A3F090E68A8E
-:10073600F090E68B7402F00208A790E6BCE0547EC7
-:10074600FF7E00E0D3948040067C007D0180047C1F
-:10075600007D00EC4EFEED4F24F5F582740B3EF560
-:1007660083E493FF3395E0FEEF24A1FFEE34E68F9A
-:1007760082F583E0540190E740F0E4A3F090E68A26
-:10078600F090E68B7402F00208A790E6A0E0440120
-:10079600F00208A712125240030208A790E6B8E03A
-:1007A60024FE601D240260030208A790E6BAE0B4A6
-:1007B6000105C2080208A790E6A0E04401F002087D
-:1007C600A790E6BAE0705990E6BCE0547EFF7E0042
-:1007D600E0D3948040067C007D0180047C007D008F
-:1007E600EC4EFEED4F24F5F582740B3EF583E49353
-:1007F600FF3395E0FEEF24A1FFEE34E68F82F5830A
-:10080600E054FEF090E6BCE05480FF131313541F2F
-:10081600FFE0540F2F90E683F0E04420F00208A793
-:1008260090E6A0E04401F08078121254507390E6EE
-:10083600B8E024FE60202402706790E6BAE0B401B6
-:1008460004D208805C90E6BAE06402605490E6A0A8
-:10085600E04401F0804B90E6BCE0547EFF7E00E071
-:10086600D3948040067C007D0180047C007D00ECF2
-:100876004EFEED4F24F5F582740B3EF583E493FFAF
-:100886003395E0FEEF24A1FFEE34E68F82F583E098
-:100896004401F0800C120114500790E6A0E04401D8
-:0808A600F090E6A0E04480F0B0
-:0108AE002227
-:0300330002008C3C
-:04008C0053D8EF3224
-:03002B00020F13AE
-:100F1300C0E0B2A5E509150970021508E509450801
-:100F2300701E75080475091FE50B6401450A7006F8
-:100F3300B2A6D2A78004B2A7D2A6750A00750B0089
-:0B0F430075CDFC75CC23C2CFD0E0328E
-:100090001201000200000040B504502100000102DE
-:1000A00000010A06000200000040010009022000D1
-:1000B000010100A0FA0904000002FF00000007058A
-:1000C0000202000200070586020002000902200069
-:1000D000010100A0FA0904000002FF00000007056A
-:1000E00002024000000705860240000004030904E4
-:1000F0000E034F0044004D00200020002000140398
-:10010000440053004F002D00320031003500300014
-:0401100020000000CB
-:03004300020C00AC
-:03005300020C009C
-:100C00000211A8000211EE000211D8000211C0006A
-:100C1000020F8500020FBC0002125600021257009C
-:100C2000021258000212590002125A0002125B000E
-:100C300002125C0002125D0002125E0002125F00EE
-:100C400002126000021257000212610002126200DA
-:100C500002126300021264000212650002126600B2
-:100C600002126700021257000212570002125700C8
-:100C7000021268000212690002126A0002126B007E
-:100C800002126C0002126D0002126E0002126F005E
-:100C9000021270000212710002127200021273003E
-:100CA000021274000212750002127600021277001E
-:080CB000021278000212790023
-:1010F30090E682E030E004E020E60B90E682E03008
-:10110300E119E030E71590E680E04401F07F147EBA
-:0C11130000120ECD90E680E054FEF022A9
-:10114B0090E682E044C0F090E681F0438701000016
-:04115B00000000226E
-:1010C400300E0990E680E0440AF0800790E680E064
-:1010D4004408F07FDC7E05120ECD90E65D74FFF0CF
-:0F10E40090E65FF05391EF90E680E054F7F02232
-:02111F00A9071E
-:10112100AE18AF198F828E83A3E064037017AD01EF
-:1011310019ED7001228F828E83E07C002FFDEC3E41
-:09114100FEAF0580DF7E007F0097
-:01114A002282
-:100ECD008E3C8F3D90E600E054187012E53D2401F4
-:100EDD00FFE4353CC313F53CEF13F53D801590E66B
-:100EED0000E05418FFBF100BE53D25E0F53DE53C56
-:100EFD0033F53CE53D153DAE3C7002153C4E6005AD
-:060F0D0012115F80EE22CC
-:10115F007400F58690FDA57C05A3E582458370F9A3
-:01116F00225D
-:100CB80090E600740AF090E6017443F0000000909A
-:100CC800E61274A0F0000000E490E613F0000000C3
-:100CD80090E61474E0F0000000E490E615F00000DF
-:100CE8000090E6047480F00000007402F000000038
-:100CF8007406F0000000E4F000000090E60274E6DC
-:100D0800F000000090E60374F8F000000090E67030
-:100D1800E04440F0000000E490E609F000000043E1
-:100D2800B20F90E61804F00000007411F000000003
-:100D380090E61A7409F0000000E490E671F090E67D
-:100D480072F075B4FF75B6FFC280C20C12124290E1
-:070D5800E67AE04401F022FD
-:010BFF0022D3
-:02124A00D322AD
-:02124C00D322AB
-:02124E00D322A9
-:100F4E0090E680E030E71590E6247402F000000091
-:100F5E00E490E625F0000000D20C8013E490E62425
-:100F6E00F000000090E6257440F0000000C20C90E6
-:070F7E00E6BAE0F51DD322E5
-:1012040090E740E51DF0E490E68AF090E68B04F068
-:02121400D322E3
-:08123A0090E6BAE0F51BD32297
-:1012160090E740E51BF0E490E68AF090E68B04F058
-:02122600D322D1
-:02125000D322A7
-:02125200D322A5
-:02125400D322A3
-:10011400750A00750B0190E678E05410FFC4540F83
-:100124004450F51C13E433F51E90E6B9E0245E70E8
-:100134000302044A24F0B40A0040030206129001A8
-:1001440049F82828730201670201830201C10202EF
-:10015400030203030203460203870203C8020409DD
-:100164000205D2A20CE43390E740F0E490E68AF072
-:1001740090E68B04F090E6A0E04480F0020614E4DC
-:1001840090E68AF090E68BF090E6A0E020E1F9900A
-:10019400E68BE0753600F53700000090E6047480C5
-:1001A400F00000007406F0000000E4F043800BD27D
-:1001B40080C28090E6A0E04480F0020614E490E659
-:1001C4008AF090E68BF090E6A0E020E1F990E68BCF
-:1001D400E0753600F5377F0F7E00120ECD90E745AF
-:1001E400E0FF90E747E0FD90E743E0FB90E741E064
-:0F01F400F53F120E2890E6A0E04480F0020614BA
-:10020300E490E68AF090E68BF090E6A0E020E1F936
-:1002130090E68BE0753600F53790E741E0F5B17570
-:100223003A0F753BA0E53B153B7002153AE53B647D
-:100233000A453A70F090E742E0F5B1753A0F753B25
-:10024300A0E53B153B7002153AE53B640A453A705D
-:10025300F090E743E0F5B1753A0F753BA0E53B1528
-:100263003B7002153AE53B640A453A70F090E74467
-:10027300E0F5B1753A0F753BA0E53B153B700215F0
-:100283003AE53B640A453A70F090E745E0F5B1750D
-:100293003A0F753BA0E53B153B7002153AE53B640D
-:1002A3000A453A70F090E746E0F5B1753A0F753BB1
-:1002B300A0E53B153B7002153AE53B640A453A70ED
-:1002C300F090E747E0F5B1753A0F753BA0E53B15B4
-:1002D3003B7002153AE53B640A453A70F0E4F5B128
-:1002E300753A0F753BA0E53B153B7002153AE53BAC
-:1002F300640A453A70F090E6A0E04480F0020614E8
-:10030300E490E68AF090E68BF090E6A0E020E1F935
-:1003130090E68BE0753600F53700000090E6047434
-:1003230080F0000000C2807406F0000000E4F0904A
-:10033300E740E0FF7E00120ECD90E6A0E04480F09F
-:10034300020614E490E68AF090E68BF090E6A0E0D3
-:1003530020E1F990E68BE0753600F5370000009058
-:10036300E6047480F00000007406F0000000E4F07E
-:1003730090E740E0FF7E00120ECD90E6A0E04480BF
-:10038300F0020614E490E68AF090E68BF090E6A083
-:10039300E020E1F990E68BE0753600F537000000C8
-:1003A30090E6047480F00000007406F0000000E49E
-:1003B300F090E740E0FF7E00120ECD90E6A0E0440F
-:1003C30080F0020614E490E68AF090E68BF090E663
-:1003D300A0E020E1F990E68BE0753600F5370000E8
-:1003E3000090E6047480F00000007406F000000042
-:1003F300E4F090E740E0FF7E00120ECD90E6A0E02F
-:100403004480F0020614E490E68AF090E68BF090C4
-:10041300E6A0E020E1F990E68BE0753600F53700C1
-:10042300000090E6047480F00000007406F0000001
-:1004330000E4F090E740E0FF7E00120ECD90E6A0CE
-:10044300E04480F002061490E6BAE0753200F5331A
-:10045300A3E0FEE4EE423290E6BEE0753400F535EB
-:10046300A3E0FEE4EE423490E6B8E064C060030229
-:10047300053AE5354534700302061490E6A0E02002
-:10048300E1F9C3E5359440E53494005008853436EA
-:10049300853537800675360075374090E6B9E0B488
-:1004A300A335E4F538F539C3E5399537E53895369D
-:1004B3005060E5332539F582E5323538F583E0FFC1
-:1004C30074402539F582E434E7F583EFF00539E527
-:1004D300397002053880D0E4F538F539C3E539952C
-:1004E30037E5389536501874402539F582E434E7FA
-:1004F300F58374CDF00539E5397002053880DDAD3B
-:10050300377AE779407EE77F40AB07AF33AE3212ED
-:100513000BAAE490E68AF090E68BE537F02533F5F5
-:1005230033E5363532F532C3E5359537F535E53400
-:100533009536F53402047590E6B8E0644060030232
-:100543000614E53545347003020614E490E68AF098
-:1005530090E68BF090E6A0E020E1F990E68BE07561
-:100563003600F53790E6B9E0B4A335E4F538F5394C
-:10057300C3E5399537E5389536503874402539F554
-:1005830082E434E7F583E0FFE5332539F582E5328C
-:100593003538F583EFF00539E5397002053880D039
-:1005A300AD377AE779407EE77F40AB07AF33AE32B2
-:1005B300121029E5372533F533E5363532F532C3E5
-:1005C300E5359537F535E5349536F534020545E4DB
-:1005D30090E68AF090E68BF090E6A0E020E1F990B7
-:1005E300E68BE0753600F53700000090E604748072
-:1005F300F00000007406F0000000E4F090E740E033
-:10060300FF7E00120ECD90E6A0E04480F08002D37E
-:0206130022C300
-:0106150022C2
-:1011A800C0E0C083C082D2095391EF90E65D74011C
-:0811B800F0D082D083D0E032B8
-:1011D800C0E0C083C0825391EF90E65D7404F0D004
-:0611E80082D083D0E0324A
-:1011EE00C0E0C083C0825391EF90E65D7402F0D0F0
-:0611FE0082D083D0E03234
-:100F8500C0E0C083C08290E680E030E70E850C109B
-:100F9500850D11851412851513800C851410851582
-:100FA50011850C12850D135391EF90E65D7410F0C9
-:070FB500D082D083D0E032AE
-:1011C000C0E0C083C082D20B5391EF90E65D7408FB
-:0811D000F0D082D083D0E032A0
-:100FBC00C0E0C083C08290E680E030E70E850C1064
-:100FCC00850D11851412851513800C85141085154B
-:100FDC0011850C12850D135391EF90E65D7420F082
-:070FEC00D082D083D0E03277
-:011256003265
-:011257003264
-:011258003263
-:011259003262
-:01125A003261
-:01125B003260
-:01125C00325F
-:01125D00325E
-:01125E00325D
-:01125F00325C
-:01126000325B
-:01126100325A
-:011262003259
-:011263003258
-:011264003257
-:011265003256
-:011266003255
-:011267003254
-:011268003253
-:011269003252
-:01126A003251
-:01126B003250
-:01126C00324F
-:01126D00324E
-:01126E00324D
-:01126F00324C
-:01127000324B
-:01127100324A
-:011272003249
-:011273003248
-:011274003247
-:011275003246
-:011276003245
-:011277003244
-:011278003243
-:011279003242
-:10122800AD071FED600BE4FEEEC3947850F20E801C
-:01123800F7BE
-:011239002292
-:040D5F00A907AB0530
-:100D63007F01121228D2A27F01121228C2A2E4FA32
-:100D7300E9A802088002C333D8FCFC5304807F0136
-:100D8300121228D2A1BC8004D2A08002C2A07F018B
-:100D9300121228C2A10ABA08D7E4FAEBA802088003
-:100DA30002C333D8FCFC5304807F01121228D2A162
-:100DB300BC8004D2A08002C2A07F01121228C2A16B
-:040DC3000ABA08D789
-:010DC7002209
-:040E2800AE07AC0560
-:100E2C00EEC4540F4410FFEEC454F0FDECC4540F48
-:100E3C004450F540ECC454F0F541EBC4540F4490CD
-:100E4C00F542EBC454F0F543E53FC4540F44D0F5E0
-:100E5C0044E53FC454F0F545C2A0C2A1C2A2120D94
-:100E6C005FAD41AF40120D5FAD43AF42120D5FADB0
-:060E7C0045AF44120D5FBA
-:010E8200224D
-:060E8300AB07AA06AC0556
-:100E8900E4FDE51E6010EA7E000DEE2400F582E423
-:100E99003418F583EAF0EBAE050D74002EF582E403
-:100EA9003418F583EBF0AF050D74002FF582E434A7
-:100EB90018F583ECF07A187B00AF1C12118CAF1C6B
-:030EC900120FF312
-:010ECC002203
-:0A1029008E3C8F3D8D3E8A3F8B40C8
-:10103300E4F541E541C3953E5020053DE53DAE3C19
-:101043007002053C14FFE5402541F582E4353FF588
-:0A10530083E0FD120E83054180D9F1
-:01105D002270
-:0A0BAA008E3C8F3D8D3E8A3F8B404C
-:100BB400E4FDF541E51E6012E53CFF7E000DEE24E8
-:100BC40000F582E43418F583EFF0E53DAE050D74CD
-:100BD400002EF582E43418F583E53DF07A187B00A5
-:100BE400AF1C12118CAB40AA3FAD3EAF1C1211706A
-:010BF40022DE
-:08124200E4F54BD2E9D2AF2222
-:100FF30090E678E020E6F9C2E990E678E04480F0F4
-:10100300EF25E090E679F090E678E030E0F990E6BD
-:1010130078E04440F090E678E020E6F990E678E066
-:0610230030E1D6D2E92203
-:10109200A90790E678E020E6F9E54B702390E67820
-:1010A200E04480F0E925E090E679F08D46AF03A9AF
-:1010B200077547018A488949E4F54A754B01D322ED
-:0210C200C32247
-:10105E00A90790E678E020E6F9E54B702590E67852
-:10106E00E04480F0E925E0440190E679F08D46AF4A
-:10107E0003A9077547018A488949E4F54A754B0368
-:04108E00D322C32284
-:03004B00020AA204
-:100AA200C0E0C083C082C085C084C086758600C095
-:100AB200D075D000C000C001C002C003C006C0078C
-:100AC20090E678E030E206754B06020B8C90E678F1
-:100AD200E020E10CE54B64026006754B07020B8CCB
-:100AE200E54B24FE605F14603624FE7003020B7D2A
-:100AF20024FC7003020B8924086003020B8CAB47B1
-:100B0200AA48A949AF4A054A8F82758300120DC8C7
-:100B120090E679F0E54A65467070754B05806B90FA
-:100B2200E679E0AB47AA48A949AE4A8E82758300AE
-:100B3200120DF5754B02E5466401704E90E678E0C1
-:100B42004420F08045E54624FEB54A0790E678E069
-:100B52004420F0E54614B54A0A90E678E04440F0B5
-:100B6200754B0090E679E0AB47AA48A949AE4A8E98
-:100B720082758300120DF5054A800F90E678E044F5
-:100B820040F0754B008003754B005391DFD007D0C6
-:100B920006D003D002D001D000D0D0D086D084D0ED
-:080BA20085D082D083D0E0323F
-:1011700012105EE54B24FA600E146006240770F32B
-:0C118000D322E4F54BD322E4F54BD3223C
-:10118C00121092E54B24FA600E146006240770F3DB
-:0C119C00D322E4F54BD322E4F54BD32220
-:030000000200807B
-:0C008000787FE4F6D8FD75814B0208AFD4
-:100DC800BB010CE58229F582E5833AF583E02250E0
-:100DD80006E92582F8E622BBFE06E92582F8E2222A
-:0D0DE800E58229F582E5833AF583E4932244
-:100DF500F8BB010DE58229F582E5833AF583E8F034
-:100E0500225006E92582C8F622BBFE05E92582C8DF
-:020E1500F222C7
-:100E1700EB9FF5F0EA9E42F0E99D42F0E89C45F031
-:010E270022A8
-:00000001FF
diff --git a/openhantek/res/firmware/dso2150x86-loader.hex b/openhantek/res/firmware/dso2150x86-loader.hex
deleted file mode 100644
index d7758b6f..00000000
--- a/openhantek/res/firmware/dso2150x86-loader.hex
+++ /dev/null
@@ -1,60 +0,0 @@
-:1003680090E668E0FF74FFF0E0B40B04EFF0D322EE
-:0603780090E668EFF0C3FF
-:01037E00225C
-:1001B500907FE9E064A360030202C5A3E07508002F
-:1001C500F509A3E0FEE4EE4208907FEEE0750A0033
-:1001D500F50BA3E0FEE4EE420A907FE8E064407090
-:1001E50064E50B450A70030202D6E4907FC5F090E2
-:1001F5007FB4E020E3F9907FC5E0750C00F50DE4D0
-:10020500FCFDC3ED950DEC950C501F74C02DF582CA
-:10021500E4347EF583E0FFE5092DF582E5083CF53C
-:1002250083EFF00DBD00010C80D8E50D2509F5091A
-:10023500E50C3508F508C3E50B950DF50BE50A95B5
-:100245000CF50A809C907FE8E064C060030202D64A
-:10025500E50B450A607BC3E50B9440E50A94005025
-:1002650008850A0C850B0D8006750C00750D40E49C
-:10027500FCFDC3ED950DEC950C501FE5092DF582A0
-:10028500E5083CF583E0FF74002DF582E4347FF545
-:1002950083EFF00DBD00010C80D8907FB5E50DF022
-:1002A5002509F509E50C3508F508C3E50B950DF5A8
-:1002B5000BE50A950CF50A907FB4E030E29280F7E1
-:1002C500907FE9E0B4AC0AE4907F00F0907FB5043C
-:0802D500F0907FB4E04402F058
-:0102DD0022FE
-:1000800090E6B9E064A36003020198A3E07508005C
-:10009000F509A3E0FEE4EE420890E6BEE0750A0032
-:1000A000F50BA3E0FEE4EE420A90E6B8E06440708F
-:1000B00066E50B450A70030201ADE490E68AF0A301
-:1000C000F090E6A0E020E1F990E68BE0750C00F5F9
-:1000D0000DE4FCFDC3ED950DEC950C501F74402D07
-:1000E000F582E434E7F583E0FFE5092DF582E508C4
-:1000F0003CF583EFF00DBD00010C80D8E50D25091E
-:10010000F509E50C3508F508C3E50B950DF50BE58C
-:100110000A950CF50A809A90E6B8E064C060030284
-:1001200001ADE50B450A70030201ADC3E50B944038
-:10013000E50A94005008850A0C850B0D8006750CA5
-:1001400000750D40E4FCFDC3ED950DEC950C501FC2
-:10015000E5092DF582E5083CF583E0FF74402DF5B7
-:1001600082E434E7F583EFF00DBD00010C80D8E4A4
-:1001700090E68AF0A3E50DF02509F509E50C3508B0
-:10018000F508C3E50B950DF50BE50A950CF50A90FE
-:10019000E6A0E030E18C80F790E6B9E0B4AC0E90D8
-:1001A000E7407401F0E490E68AF0A304F090E6A042
-:0401B000E04480F0B7
-:0101B4002228
-:1002DE00C2011203689200907F95E044C0F0D2E80C
-:1002EE0030000890E65D74FFF08006907FAB74FFDF
-:1002FE00F030000890E6687408F08007907FAFE059
-:10030E004401F030000890E65C7401F08006907FA6
-:10031E00AE7401F0D2AF3001FD30000512008080C6
-:08032E00031201B5C20180EECB
-:03000300020336BF
-:10033600C0E0C083C082C085C084C086758600D2F6
-:10034600015391EF30000890E65D7401F08006904D
-:100356007FAB7401F0D086D084D085D082D083D094
-:02036600E03283
-:03004300020400B4
-:0404000002033600BD
-:0300000002037F79
-:0C037F00787FE4F6D8FD7581200202DED4
-:00000001FF
diff --git a/openhantek/res/firmware/dso2250x86-firmware.hex b/openhantek/res/firmware/dso2250x86-firmware.hex
deleted file mode 100644
index 47b9329e..00000000
--- a/openhantek/res/firmware/dso2250x86-firmware.hex
+++ /dev/null
@@ -1,372 +0,0 @@
-:0A0BF50000010202030304040505D9
-:1008AF00E4F52DF52CF52BF52AC20BC208C20AC2AE
-:1008BF0009120CB8E4F50AF50BD2A6C2C975CDFC26
-:1008CF0075CC2AD2CAD2AFD2AD7508087509077E8A
-:1008DF00007F908E0E8F0F7516007517A2750C0086
-:1008EF00750DAC7514007515CC7518007519EC9055
-:1008FF00E680E030E70E850C10850D11851412850A
-:10090F001513800C851410851511850C12850D1388
-:10091F00EE54E07003020A3B752E00752F807E00A7
-:10092F007F908E308F31C374129FFF74019ECF243E
-:10093F0002CF3400FEE48F298E28F527F526F52502
-:10094F00F524F523F522AF29AE28AD27AC26AB252C
-:10095F00AA24A923A822C3120E17502AE52F252552
-:10096F00F582E52E3524F58374CDF0E4FAF9F8E538
-:10097F00252401F525EA3524F524E93523F523E867
-:10098F003522F52280C0E4F525F524F523F522AFB5
-:10099F0029AE28AD27AC26AB25AA24A923A822C3AC
-:1009AF00120E175035AE24AF25E5312FF582E53005
-:1009BF003EF583E0FDE52F2FF582E52E3EF583ED25
-:1009CF00F0E4FAF9F8EF2401F525EA3EF524E935CC
-:1009DF0023F523E83522F52280B5852E0E852F0FBE
-:1009EF0074902480FF740034FFFEC3E5179FF51742
-:1009FF00E5169EF516C3E5119FF511E5109EF5104E
-:100A0F00C3E5139FF513E5129EF512C3E50D9FF590
-:100A1F000DE50C9EF50CC3E5159FF515E5149EF538
-:100A2F0014C3E5199FF519E5189EF518D2E843D8B8
-:100A3F002090E668E04409F090E65CE0443DF0D297
-:100A4F00AF90E680E020E105D20E1210C490E68050
-:100A5F00E054F7F0538EF8C20B300905120616C298
-:100A6F0009300B2912124A5024C20B12114B2008C5
-:100A7F001690E682E030E704E020E1EF90E682E0B6
-:100A8F0030E604E020E0E41210F312124C120BFFD8
-:020A9F0080C70E
-:010AA1002232
-:1006160090E6B9E070030206F114700302079A240B
-:10062600FE700302082F24FB70030206EB1470030E
-:100636000206E51470030206D91470030206DF24CD
-:1006460005600302089B12124E40030208A790E6BB
-:10065600BBE024FE602C14604724FD601614603154
-:1006660024067065E50E90E6B3F0E50F90E6B4F06B
-:100676000208A7E51690E6B3F0E51790E6B4F00297
-:1006860008A7E51090E6B3F0E51190E6B4F002088D
-:10069600A7E51290E6B3F0E51390E6B4F00208A7DA
-:1006A60090E6BAE0FF12111FAA06A9077B01EA49E4
-:1006B600600DEE90E6B3F0EF90E6B4F00208A79076
-:1006C600E6A0E04401F00208A790E6A0E04401F0AD
-:1006D6000208A71212160208A712123A0208A71257
-:1006E6000F4E0208A71212040208A7121250400366
-:1006F6000208A790E6B8E0247F602B14603C240231
-:100706006003020790A208E433FF25E0FFA20AE493
-:10071600334F90E740F0E4A3F090E68AF090E68B42
-:100726007402F00208A7E490E740F0A3F090E68A8E
-:10073600F090E68B7402F00208A790E6BCE0547EC7
-:10074600FF7E00E0D3948040067C007D0180047C1F
-:10075600007D00EC4EFEED4F24F5F582740B3EF560
-:1007660083E493FF3395E0FEEF24A1FFEE34E68F9A
-:1007760082F583E0540190E740F0E4A3F090E68A26
-:10078600F090E68B7402F00208A790E6A0E0440120
-:10079600F00208A712125240030208A790E6B8E03A
-:1007A60024FE601D240260030208A790E6BAE0B4A6
-:1007B6000105C2080208A790E6A0E04401F002087D
-:1007C600A790E6BAE0705990E6BCE0547EFF7E0042
-:1007D600E0D3948040067C007D0180047C007D008F
-:1007E600EC4EFEED4F24F5F582740B3EF583E49353
-:1007F600FF3395E0FEEF24A1FFEE34E68F82F5830A
-:10080600E054FEF090E6BCE05480FF131313541F2F
-:10081600FFE0540F2F90E683F0E04420F00208A793
-:1008260090E6A0E04401F08078121254507390E6EE
-:10083600B8E024FE60202402706790E6BAE0B401B6
-:1008460004D208805C90E6BAE06402605490E6A0A8
-:10085600E04401F0804B90E6BCE0547EFF7E00E071
-:10086600D3948040067C007D0180047C007D00ECF2
-:100876004EFEED4F24F5F582740B3EF583E493FFAF
-:100886003395E0FEEF24A1FFEE34E68F82F583E098
-:100896004401F0800C120114500790E6A0E04401D8
-:0808A600F090E6A0E04480F0B0
-:0108AE002227
-:0300330002008C3C
-:04008C0053D8EF3224
-:03002B00020F13AE
-:100F1300C0E0B2A5E509150970021508E509450801
-:100F2300701E75080475091FE50B6401450A7006F8
-:100F3300B2A6D2A78004B2A7D2A6750A00750B0089
-:0B0F430075CDFC75CC23C2CFD0E0328E
-:100090001201000200000040B504502200000102DD
-:1000A00000010A06000200000040010009022000D1
-:1000B000010100A0FA0904000002FF00000007058A
-:1000C0000202000200070586020002000902200069
-:1000D000010100A0FA0904000002FF00000007056A
-:1000E00002024000000705860240000004030904E4
-:1000F0000E034F0044004D00200020002000140398
-:10010000440053004F002D00320032003500300013
-:0401100020000000CB
-:03004300020C00AC
-:03005300020C009C
-:100C00000211A8000211EE000211D8000211C0006A
-:100C1000020F8500020FBC0002125600021257009C
-:100C2000021258000212590002125A0002125B000E
-:100C300002125C0002125D0002125E0002125F00EE
-:100C400002126000021257000212610002126200DA
-:100C500002126300021264000212650002126600B2
-:100C600002126700021257000212570002125700C8
-:100C7000021268000212690002126A0002126B007E
-:100C800002126C0002126D0002126E0002126F005E
-:100C9000021270000212710002127200021273003E
-:100CA000021274000212750002127600021277001E
-:080CB000021278000212790023
-:1010F30090E682E030E004E020E60B90E682E03008
-:10110300E119E030E71590E680E04401F07F147EBA
-:0C11130000120ECD90E680E054FEF022A9
-:10114B0090E682E044C0F090E681F0438701000016
-:04115B00000000226E
-:1010C400300E0990E680E0440AF0800790E680E064
-:1010D4004408F07FDC7E05120ECD90E65D74FFF0CF
-:0F10E40090E65FF05391EF90E680E054F7F02232
-:02111F00A9071E
-:10112100AE18AF198F828E83A3E064037017AD01EF
-:1011310019ED7001228F828E83E07C002FFDEC3E41
-:09114100FEAF0580DF7E007F0097
-:01114A002282
-:100ECD008E3C8F3D90E600E054187012E53D2401F4
-:100EDD00FFE4353CC313F53CEF13F53D801590E66B
-:100EED0000E05418FFBF100BE53D25E0F53DE53C56
-:100EFD0033F53CE53D153DAE3C7002153C4E6005AD
-:060F0D0012115F80EE22CC
-:10115F007400F58690FDA57C05A3E582458370F9A3
-:01116F00225D
-:100CB80090E600740AF090E6017443F0000000909A
-:100CC800E61274A0F0000000E490E613F0000000C3
-:100CD80090E61474E0F0000000E490E615F00000DF
-:100CE8000090E6047480F00000007402F000000038
-:100CF8007406F0000000E4F000000090E60274E6DC
-:100D0800F000000090E60374F8F000000090E67030
-:100D1800E04440F0000000E490E609F000000043E1
-:100D2800B20F90E61804F00000007411F000000003
-:100D380090E61A7409F0000000E490E671F090E67D
-:100D480072F075B4FF75B6FFC280C20C12124290E1
-:070D5800E67AE04401F022FD
-:010BFF0022D3
-:02124A00D322AD
-:02124C00D322AB
-:02124E00D322A9
-:100F4E0090E680E030E71590E6247402F000000091
-:100F5E00E490E625F0000000D20C8013E490E62425
-:100F6E00F000000090E6257440F0000000C20C90E6
-:070F7E00E6BAE0F51DD322E5
-:1012040090E740E51DF0E490E68AF090E68B04F068
-:02121400D322E3
-:08123A0090E6BAE0F51BD32297
-:1012160090E740E51BF0E490E68AF090E68B04F058
-:02122600D322D1
-:02125000D322A7
-:02125200D322A5
-:02125400D322A3
-:10011400750A00750B0190E678E05410FFC4540F83
-:100124004450F51C13E433F51E90E6B9E0245E70E8
-:100134000302044A24F0B40A0040030206129001A8
-:1001440049F82828730201670201830201C10202EF
-:10015400030203030203460203870203C8020409DD
-:100164000205D2A20CE43390E740F0E490E68AF072
-:1001740090E68B04F090E6A0E04480F0020614E4DC
-:1001840090E68AF090E68BF090E6A0E020E1F9900A
-:10019400E68BE0753600F53700000090E6047480C5
-:1001A400F00000007406F0000000E4F043800BD27D
-:1001B40080C28090E6A0E04480F0020614E490E659
-:1001C4008AF090E68BF090E6A0E020E1F990E68BCF
-:1001D400E0753600F5377F0F7E00120ECD90E745AF
-:1001E400E0FF90E747E0FD90E743E0FB90E741E064
-:0F01F400F53F120E2890E6A0E04480F0020614BA
-:10020300E490E68AF090E68BF090E6A0E020E1F936
-:1002130090E68BE0753600F53790E741E0F5B17570
-:100223003A0F753BA0E53B153B7002153AE53B647D
-:100233000A453A70F090E742E0F5B1753A0F753B25
-:10024300A0E53B153B7002153AE53B640A453A705D
-:10025300F090E743E0F5B1753A0F753BA0E53B1528
-:100263003B7002153AE53B640A453A70F090E74467
-:10027300E0F5B1753A0F753BA0E53B153B700215F0
-:100283003AE53B640A453A70F090E745E0F5B1750D
-:100293003A0F753BA0E53B153B7002153AE53B640D
-:1002A3000A453A70F090E746E0F5B1753A0F753BB1
-:1002B300A0E53B153B7002153AE53B640A453A70ED
-:1002C300F090E747E0F5B1753A0F753BA0E53B15B4
-:1002D3003B7002153AE53B640A453A70F0E4F5B128
-:1002E300753A0F753BA0E53B153B7002153AE53BAC
-:1002F300640A453A70F090E6A0E04480F0020614E8
-:10030300E490E68AF090E68BF090E6A0E020E1F935
-:1003130090E68BE0753600F53700000090E6047434
-:1003230080F0000000C2807406F0000000E4F0904A
-:10033300E740E0FF7E00120ECD90E6A0E04480F09F
-:10034300020614E490E68AF090E68BF090E6A0E0D3
-:1003530020E1F990E68BE0753600F5370000009058
-:10036300E6047480F00000007406F0000000E4F07E
-:1003730090E740E0FF7E00120ECD90E6A0E04480BF
-:10038300F0020614E490E68AF090E68BF090E6A083
-:10039300E020E1F990E68BE0753600F537000000C8
-:1003A30090E6047480F00000007406F0000000E49E
-:1003B300F090E740E0FF7E00120ECD90E6A0E0440F
-:1003C30080F0020614E490E68AF090E68BF090E663
-:1003D300A0E020E1F990E68BE0753600F5370000E8
-:1003E3000090E6047480F00000007406F000000042
-:1003F300E4F090E740E0FF7E00120ECD90E6A0E02F
-:100403004480F0020614E490E68AF090E68BF090C4
-:10041300E6A0E020E1F990E68BE0753600F53700C1
-:10042300000090E6047480F00000007406F0000001
-:1004330000E4F090E740E0FF7E00120ECD90E6A0CE
-:10044300E04480F002061490E6BAE0753200F5331A
-:10045300A3E0FEE4EE423290E6BEE0753400F535EB
-:10046300A3E0FEE4EE423490E6B8E064C060030229
-:10047300053AE5354534700302061490E6A0E02002
-:10048300E1F9C3E5359440E53494005008853436EA
-:10049300853537800675360075374090E6B9E0B488
-:1004A300A335E4F538F539C3E5399537E53895369D
-:1004B3005060E5332539F582E5323538F583E0FFC1
-:1004C30074402539F582E434E7F583EFF00539E527
-:1004D300397002053880D0E4F538F539C3E539952C
-:1004E30037E5389536501874402539F582E434E7FA
-:1004F300F58374CDF00539E5397002053880DDAD3B
-:10050300377AE779407EE77F40AB07AF33AE3212ED
-:100513000BAAE490E68AF090E68BE537F02533F5F5
-:1005230033E5363532F532C3E5359537F535E53400
-:100533009536F53402047590E6B8E0644060030232
-:100543000614E53545347003020614E490E68AF098
-:1005530090E68BF090E6A0E020E1F990E68BE07561
-:100563003600F53790E6B9E0B4A335E4F538F5394C
-:10057300C3E5399537E5389536503874402539F554
-:1005830082E434E7F583E0FFE5332539F582E5328C
-:100593003538F583EFF00539E5397002053880D039
-:1005A300AD377AE779407EE77F40AB07AF33AE32B2
-:1005B300121029E5372533F533E5363532F532C3E5
-:1005C300E5359537F535E5349536F534020545E4DB
-:1005D30090E68AF090E68BF090E6A0E020E1F990B7
-:1005E300E68BE0753600F53700000090E604748072
-:1005F300F00000007406F0000000E4F090E740E033
-:10060300FF7E00120ECD90E6A0E04480F08002D37E
-:0206130022C300
-:0106150022C2
-:1011A800C0E0C083C082D2095391EF90E65D74011C
-:0811B800F0D082D083D0E032B8
-:1011D800C0E0C083C0825391EF90E65D7404F0D004
-:0611E80082D083D0E0324A
-:1011EE00C0E0C083C0825391EF90E65D7402F0D0F0
-:0611FE0082D083D0E03234
-:100F8500C0E0C083C08290E680E030E70E850C109B
-:100F9500850D11851412851513800C851410851582
-:100FA50011850C12850D135391EF90E65D7410F0C9
-:070FB500D082D083D0E032AE
-:1011C000C0E0C083C082D20B5391EF90E65D7408FB
-:0811D000F0D082D083D0E032A0
-:100FBC00C0E0C083C08290E680E030E70E850C1064
-:100FCC00850D11851412851513800C85141085154B
-:100FDC0011850C12850D135391EF90E65D7420F082
-:070FEC00D082D083D0E03277
-:011256003265
-:011257003264
-:011258003263
-:011259003262
-:01125A003261
-:01125B003260
-:01125C00325F
-:01125D00325E
-:01125E00325D
-:01125F00325C
-:01126000325B
-:01126100325A
-:011262003259
-:011263003258
-:011264003257
-:011265003256
-:011266003255
-:011267003254
-:011268003253
-:011269003252
-:01126A003251
-:01126B003250
-:01126C00324F
-:01126D00324E
-:01126E00324D
-:01126F00324C
-:01127000324B
-:01127100324A
-:011272003249
-:011273003248
-:011274003247
-:011275003246
-:011276003245
-:011277003244
-:011278003243
-:011279003242
-:10122800AD071FED600BE4FEEEC3947850F20E801C
-:01123800F7BE
-:011239002292
-:040D5F00A907AB0530
-:100D63007F01121228D2A27F01121228C2A2E4FA32
-:100D7300E9A802088002C333D8FCFC5304807F0136
-:100D8300121228D2A1BC8004D2A08002C2A07F018B
-:100D9300121228C2A10ABA08D7E4FAEBA802088003
-:100DA30002C333D8FCFC5304807F01121228D2A162
-:100DB300BC8004D2A08002C2A07F01121228C2A16B
-:040DC3000ABA08D789
-:010DC7002209
-:040E2800AE07AC0560
-:100E2C00EEC4540F4410FFEEC454F0FDECC4540F48
-:100E3C004450F540ECC454F0F541EBC4540F4490CD
-:100E4C00F542EBC454F0F543E53FC4540F44D0F5E0
-:100E5C0044E53FC454F0F545C2A0C2A1C2A2120D94
-:100E6C005FAD41AF40120D5FAD43AF42120D5FADB0
-:060E7C0045AF44120D5FBA
-:010E8200224D
-:060E8300AB07AA06AC0556
-:100E8900E4FDE51E6010EA7E000DEE2400F582E423
-:100E99003418F583EAF0EBAE050D74002EF582E403
-:100EA9003418F583EBF0AF050D74002FF582E434A7
-:100EB90018F583ECF07A187B00AF1C12118CAF1C6B
-:030EC900120FF312
-:010ECC002203
-:0A1029008E3C8F3D8D3E8A3F8B40C8
-:10103300E4F541E541C3953E5020053DE53DAE3C19
-:101043007002053C14FFE5402541F582E4353FF588
-:0A10530083E0FD120E83054180D9F1
-:01105D002270
-:0A0BAA008E3C8F3D8D3E8A3F8B404C
-:100BB400E4FDF541E51E6012E53CFF7E000DEE24E8
-:100BC40000F582E43418F583EFF0E53DAE050D74CD
-:100BD400002EF582E43418F583E53DF07A187B00A5
-:100BE400AF1C12118CAB40AA3FAD3EAF1C1211706A
-:010BF40022DE
-:08124200E4F54BD2E9D2AF2222
-:100FF30090E678E020E6F9C2E990E678E04480F0F4
-:10100300EF25E090E679F090E678E030E0F990E6BD
-:1010130078E04440F090E678E020E6F990E678E066
-:0610230030E1D6D2E92203
-:10109200A90790E678E020E6F9E54B702390E67820
-:1010A200E04480F0E925E090E679F08D46AF03A9AF
-:1010B200077547018A488949E4F54A754B01D322ED
-:0210C200C32247
-:10105E00A90790E678E020E6F9E54B702590E67852
-:10106E00E04480F0E925E0440190E679F08D46AF4A
-:10107E0003A9077547018A488949E4F54A754B0368
-:04108E00D322C32284
-:03004B00020AA204
-:100AA200C0E0C083C082C085C084C086758600C095
-:100AB200D075D000C000C001C002C003C006C0078C
-:100AC20090E678E030E206754B06020B8C90E678F1
-:100AD200E020E10CE54B64026006754B07020B8CCB
-:100AE200E54B24FE605F14603624FE7003020B7D2A
-:100AF20024FC7003020B8924086003020B8CAB47B1
-:100B0200AA48A949AF4A054A8F82758300120DC8C7
-:100B120090E679F0E54A65467070754B05806B90FA
-:100B2200E679E0AB47AA48A949AE4A8E82758300AE
-:100B3200120DF5754B02E5466401704E90E678E0C1
-:100B42004420F08045E54624FEB54A0790E678E069
-:100B52004420F0E54614B54A0A90E678E04440F0B5
-:100B6200754B0090E679E0AB47AA48A949AE4A8E98
-:100B720082758300120DF5054A800F90E678E044F5
-:100B820040F0754B008003754B005391DFD007D0C6
-:100B920006D003D002D001D000D0D0D086D084D0ED
-:080BA20085D082D083D0E0323F
-:1011700012105EE54B24FA600E146006240770F32B
-:0C118000D322E4F54BD322E4F54BD3223C
-:10118C00121092E54B24FA600E146006240770F3DB
-:0C119C00D322E4F54BD322E4F54BD32220
-:030000000200807B
-:0C008000787FE4F6D8FD75814B0208AFD4
-:100DC800BB010CE58229F582E5833AF583E02250E0
-:100DD80006E92582F8E622BBFE06E92582F8E2222A
-:0D0DE800E58229F582E5833AF583E4932244
-:100DF500F8BB010DE58229F582E5833AF583E8F034
-:100E0500225006E92582C8F622BBFE05E92582C8DF
-:020E1500F222C7
-:100E1700EB9FF5F0EA9E42F0E99D42F0E89C45F031
-:010E270022A8
-:00000001FF
diff --git a/openhantek/res/firmware/dso2250x86-loader.hex b/openhantek/res/firmware/dso2250x86-loader.hex
deleted file mode 100644
index d7758b6f..00000000
--- a/openhantek/res/firmware/dso2250x86-loader.hex
+++ /dev/null
@@ -1,60 +0,0 @@
-:1003680090E668E0FF74FFF0E0B40B04EFF0D322EE
-:0603780090E668EFF0C3FF
-:01037E00225C
-:1001B500907FE9E064A360030202C5A3E07508002F
-:1001C500F509A3E0FEE4EE4208907FEEE0750A0033
-:1001D500F50BA3E0FEE4EE420A907FE8E064407090
-:1001E50064E50B450A70030202D6E4907FC5F090E2
-:1001F5007FB4E020E3F9907FC5E0750C00F50DE4D0
-:10020500FCFDC3ED950DEC950C501F74C02DF582CA
-:10021500E4347EF583E0FFE5092DF582E5083CF53C
-:1002250083EFF00DBD00010C80D8E50D2509F5091A
-:10023500E50C3508F508C3E50B950DF50BE50A95B5
-:100245000CF50A809C907FE8E064C060030202D64A
-:10025500E50B450A607BC3E50B9440E50A94005025
-:1002650008850A0C850B0D8006750C00750D40E49C
-:10027500FCFDC3ED950DEC950C501FE5092DF582A0
-:10028500E5083CF583E0FF74002DF582E4347FF545
-:1002950083EFF00DBD00010C80D8907FB5E50DF022
-:1002A5002509F509E50C3508F508C3E50B950DF5A8
-:1002B5000BE50A950CF50A907FB4E030E29280F7E1
-:1002C500907FE9E0B4AC0AE4907F00F0907FB5043C
-:0802D500F0907FB4E04402F058
-:0102DD0022FE
-:1000800090E6B9E064A36003020198A3E07508005C
-:10009000F509A3E0FEE4EE420890E6BEE0750A0032
-:1000A000F50BA3E0FEE4EE420A90E6B8E06440708F
-:1000B00066E50B450A70030201ADE490E68AF0A301
-:1000C000F090E6A0E020E1F990E68BE0750C00F5F9
-:1000D0000DE4FCFDC3ED950DEC950C501F74402D07
-:1000E000F582E434E7F583E0FFE5092DF582E508C4
-:1000F0003CF583EFF00DBD00010C80D8E50D25091E
-:10010000F509E50C3508F508C3E50B950DF50BE58C
-:100110000A950CF50A809A90E6B8E064C060030284
-:1001200001ADE50B450A70030201ADC3E50B944038
-:10013000E50A94005008850A0C850B0D8006750CA5
-:1001400000750D40E4FCFDC3ED950DEC950C501FC2
-:10015000E5092DF582E5083CF583E0FF74402DF5B7
-:1001600082E434E7F583EFF00DBD00010C80D8E4A4
-:1001700090E68AF0A3E50DF02509F509E50C3508B0
-:10018000F508C3E50B950DF50BE50A950CF50A90FE
-:10019000E6A0E030E18C80F790E6B9E0B4AC0E90D8
-:1001A000E7407401F0E490E68AF0A304F090E6A042
-:0401B000E04480F0B7
-:0101B4002228
-:1002DE00C2011203689200907F95E044C0F0D2E80C
-:1002EE0030000890E65D74FFF08006907FAB74FFDF
-:1002FE00F030000890E6687408F08007907FAFE059
-:10030E004401F030000890E65C7401F08006907FA6
-:10031E00AE7401F0D2AF3001FD30000512008080C6
-:08032E00031201B5C20180EECB
-:03000300020336BF
-:10033600C0E0C083C082C085C084C086758600D2F6
-:10034600015391EF30000890E65D7401F08006904D
-:100356007FAB7401F0D086D084D085D082D083D094
-:02036600E03283
-:03004300020400B4
-:0404000002033600BD
-:0300000002037F79
-:0C037F00787FE4F6D8FD7581200202DED4
-:00000001FF
diff --git a/openhantek/res/firmware/dso5200ax86-firmware.hex b/openhantek/res/firmware/dso5200ax86-firmware.hex
deleted file mode 100644
index 692219ac..00000000
--- a/openhantek/res/firmware/dso5200ax86-firmware.hex
+++ /dev/null
@@ -1,377 +0,0 @@
-:0A0CF60000010202030304040505D7
-:10090900E4F52DF52CF52BF52AC20BC208C20AC253
-:1009190009120C04E4F50AF50BD2A6C2C975CDFC7F
-:1009290075CC2AD2CAD2AFD2AD7508087509077E2F
-:10093900007F908E0E8F0F7516007517A2750C002B
-:10094900750DAC7514007515CC7518007519EC90FA
-:10095900E680E030E70E850C10850D1185141285AF
-:100969001513800C851410851511850C12850D132E
-:10097900EE54E07003020A95752E00752F807E00F3
-:100989007F908E308F31C374129FFF74019ECF24E4
-:1009990002CF3400FEE48F298E28F527F526F525A8
-:1009A900F524F523F522AF29AE28AD27AC26AB25D2
-:1009B900AA24A923A822C3120E70502AE52F25259F
-:1009C900F582E52E3524F58374CDF0E4FAF9F8E5DE
-:1009D900252401F525EA3524F524E93523F523E80D
-:1009E9003522F52280C0E4F525F524F523F522AF5B
-:1009F90029AE28AD27AC26AB25AA24A923A822C352
-:100A0900120E705035AE24AF25E5312FF582E53051
-:100A19003EF583E0FDE52F2FF582E52E3EF583EDCA
-:100A2900F0E4FAF9F8EF2401F525EA3EF524E93571
-:100A390023F523E83522F52280B5852E0E852F0F63
-:100A490074902480FF740034FFFEC3E5179FF517E7
-:100A5900E5169EF516C3E5119FF511E5109EF510F3
-:100A6900C3E5139FF513E5129EF512C3E50D9FF536
-:100A79000DE50C9EF50CC3E5159FF515E5149EF5DE
-:100A890014C3E5199FF519E5189EF518D2E843D85E
-:100A99002090E668E04409F090E65CE0443DF0D23D
-:100AA900AF90E680E020E105D20E12110990E680B0
-:100AB900E054F7F0538EF8C20B300905120670C2E4
-:100AC90009300B2912128F5024C20B1211902008E1
-:100AD9001690E682E030E704E020E1EF90E682E05C
-:100AE90030E604E020E0E412113812129112129B50
-:020AF90080C7B4
-:010AFB0022D8
-:1006700090E6B9E0700302074B1470030207F424FC
-:10068000FE700302088924FB7003020745147003FF
-:1006900002073F1470030207331470030207392462
-:1006A0000560030208F5121293400302090190E667
-:1006B000BBE024FE602C14604724FD6016146031FA
-:1006C00024067065E50E90E6B3F0E50F90E6B4F011
-:1006D000020901E51690E6B3F0E51790E6B4F002E2
-:1006E0000901E51090E6B3F0E51190E6B4F00209D7
-:1006F00001E51290E6B3F0E51390E6B4F0020901CB
-:1007000090E6BAE0FF121164AA06A9077B01EA4944
-:10071000600DEE90E6B3F0EF90E6B4F002090190C0
-:10072000E6A0E04401F002090190E6A0E04401F0F7
-:1007300002090112125B02090112127F0209011261
-:100740000F93020901121249020901121295400386
-:1007500002090190E6B8E0247F602B14603C24027B
-:1007600060030207EAA208E433FF25E0FFA20AE4DF
-:10077000334F90E740F0E4A3F090E68AF090E68BE8
-:100780007402F0020901E490E740F0A3F090E68AD9
-:10079000F090E68B7402F002090190E6BCE0547E12
-:1007A000FF7E00E0D3948040067C007D0180047CC5
-:1007B000007D00EC4EFEED4F24F6F582740C3EF504
-:1007C00083E493FF3395E0FEEF24A1FFEE34E68F40
-:1007D00082F583E0540190E740F0E4A3F090E68ACC
-:1007E000F090E68B7402F002090190E6A0E044016B
-:1007F000F0020901121297400302090190E6B8E0E5
-:1008000024FE601D2402600302090190E6BAE0B4F0
-:100810000105C20802090190E6A0E04401F00209C6
-:100820000190E6BAE0705990E6BCE0547EFF7E008D
-:10083000E0D3948040067C007D0180047C007D0034
-:10084000EC4EFEED4F24F6F582740C3EF583E493F6
-:10085000FF3395E0FEEF24A1FFEE34E68F82F583AF
-:10086000E054FEF090E6BCE05480FF131313541FD5
-:10087000FFE0540F2F90E683F0E04420F0020901DE
-:1008800090E6A0E04401F08078121299507390E64F
-:10089000B8E024FE60202402706790E6BAE0B4015C
-:1008A00004D208805C90E6BAE06402605490E6A04E
-:1008B000E04401F0804B90E6BCE0547EFF7E00E017
-:1008C000D3948040067C007D0180047C007D00EC98
-:1008D0004EFEED4F24F6F582740C3EF583E493FF53
-:1008E0003395E0FEEF24A1FFEE34E68F82F583E03E
-:1008F0004401F0800C120114500790E6A0E044017E
-:08090000F090E6A0E04480F055
-:0109080022CC
-:0300330002008C3C
-:04008C0053D8EF3224
-:03002B00020F566B
-:100F5600C0E0B2A5E509150970021508E5094508BE
-:100F66007020B28175080475091FE50B6401450AF6
-:100F76007006B2A6D2A78004B2A7D2A6750A0075DB
-:0D0F86000B0075CDFC75CC23C2CFD0E0323E
-:100090001201000200000040B5040A5200000102F3
-:1000A00000010A06000200000040010009022000D1
-:1000B000010100A0FA0904000002FF00000007058A
-:1000C0000202000200070586020002000902200069
-:1000D000010100A0FA0904000002FF00000007056A
-:1000E00002024000000705860240000004030904E4
-:1000F0000E034F0044004D00200020002000140398
-:10010000440053004F002D00350032003000300015
-:0401100041000000AA
-:03004300020D00AB
-:03005300020D009B
-:100D00000211ED000212330002121D000212050052
-:100D1000020FCA000210010002129C0002129D0084
-:100D200002129E0002129F000212A0000212A100F5
-:100D30000212A2000212A3000212A4000212A500D5
-:100D40000212A60002129D000212A7000212A800C1
-:100D50000212A9000212AA000212AB000212AC0099
-:100D60000212AD0002129D0002129D0002129D00AF
-:100D70000212AE000212AF000212B0000212B10065
-:100D80000212B2000212B3000212B4000212B50045
-:100D90000212B6000212B7000212B8000212B90025
-:100DA0000212BA000212BB000212BC000212BD0005
-:080DB0000212BE000212BF0096
-:1011380090E682E030E004E020E60B90E682E030C2
-:10114800E119E030E71590E680E04401F07F147E75
-:0C11580000120ECB90E680E054FEF02266
-:1011900090E682E044C0F090E681F04387010000D1
-:0411A0000000002229
-:10110900300E0990E680E0440AF0800790E680E01E
-:101119004408F07FDC7E05120ECB90E65D74FFF08B
-:0F11290090E65FF05391EF90E680E054F7F022EC
-:02116400A907D9
-:10116600AE18AF198F828E83A3E064037017AD01AA
-:1011760019ED7001228F828E83E07C002FFDEC3EFC
-:09118600FEAF0580DF7E007F0052
-:01118F00223D
-:100ECB008E3C8F3D90E600E054187012E53D2401F6
-:100EDB00FFE4353CC313F53CEF13F53D801590E66D
-:100EEB0000E05418FFBF100BE53D25E0F53DE53C58
-:100EFB0033F53CE53D153DAE3C7002153C4E6005AF
-:060F0B001211A480EE2289
-:1011A4007400F58690FDA57C05A3E582458370F95E
-:0111B4002218
-:100C040090E600740AF090E6017443F0000000904E
-:100C1400E61274A0F0000000E490E613F000000077
-:100C240090E61474E0F0000000E490E615F0000093
-:100C34000090E6047480F00000007402F0000000EC
-:100C44007406F0000000E4F000000090E60274E690
-:100C5400F000000090E60374F8F000000090E670E5
-:100C6400E04440F0000000E490E609F00000004396
-:100C7400B20F90E61804F00000007411F0000000B8
-:100C840090E61A7409F0000000E490E671F090E632
-:100C940072F075B4FF75B6FFC280C20C1212879051
-:070CA400E67AE04401F022B2
-:01129B002230
-:02128F00D32268
-:02129100D32266
-:02129300D32264
-:100F930090E680E030E71590E6247402F00000004C
-:100FA300E490E625F0000000D20C8013E490E624E0
-:100FB300F000000090E6257440F0000000C20C90A1
-:070FC300E6BAE0F51DD322A0
-:1012490090E740E51DF0E490E68AF090E68B04F023
-:02125900D3229E
-:08127F0090E6BAE0F51BD32252
-:10125B0090E740E51BF0E490E68AF090E68B04F013
-:02126B00D3228C
-:02129500D32262
-:02129700D32260
-:02129900D3225E
-:10011400750A00750B0190E678E05410FFC4540F83
-:100124004450F51C13E433F51E90E6B9E0245E70E8
-:10013400030204A424F0B40B00400302066C9001F3
-:1001440049F828287302016A0201860202030202A6
-:100154005D02035D0203A00203E1020422020463C0
-:1001640002062C0201C4A20CE43390E740F0E490B0
-:10017400E68AF090E68B04F090E6A0E04480F0027A
-:10018400066EE490E68AF090E68BF090E6A0E0201C
-:10019400E1F990E68BE0753600F53700000090E653
-:1001A400047480F00000007406F0000000E4F043E2
-:1001B400800BD280C28090E6A0E04480F002066EFC
-:1001C400E490E68AF090E68BF090E6A0E020E1F976
-:1001D40090E68BE0753600F5377F0F7E00120ECB6C
-:1001E40090E746E0540F4450FFA3E0FDC2A0C2A133
-:1001F400C2A2120DB890E6A0E04480F002066EE4BC
-:1002040090E68AF090E68BF090E6A0E020E1F99089
-:10021400E68BE0753600F5377F0F7E00120ECB902B
-:10022400E745E0FF90E744E0FD90E747E0FB90E717
-:1002340046E0F53F90E743E0F54090E742E0F541C2
-:1002440090E741E0F54290E740E0F543120F11904A
-:09025400E6A0E04480F002066E11
-:10025D00E490E68AF090E68BF090E6A0E020E1F9DC
-:10026D0090E68BE0753600F53790E741E0F5B17516
-:10027D003A0F753BA0E53B153B7002153AE53B6423
-:10028D000A453A70F090E742E0F5B1753A0F753BCB
-:10029D00A0E53B153B7002153AE53B640A453A7003
-:1002AD00F090E743E0F5B1753A0F753BA0E53B15CE
-:1002BD003B7002153AE53B640A453A70F090E7440D
-:1002CD00E0F5B1753A0F753BA0E53B153B70021596
-:1002DD003AE53B640A453A70F090E745E0F5B175B3
-:1002ED003A0F753BA0E53B153B7002153AE53B64B3
-:1002FD000A453A70F090E746E0F5B1753A0F753B57
-:10030D00A0E53B153B7002153AE53B640A453A7092
-:10031D00F090E747E0F5B1753A0F753BA0E53B1559
-:10032D003B7002153AE53B640A453A70F0E4F5B1CD
-:10033D00753A0F753BA0E53B153B7002153AE53B51
-:10034D00640A453A70F090E6A0E04480F002066E33
-:10035D00E490E68AF090E68BF090E6A0E020E1F9DB
-:10036D0090E68BE0753600F53700000090E60474DA
-:10037D0080F0000000C2807406F0000000E4F090F0
-:10038D00E740E0FF7E00120ECB90E6A0E04480F047
-:10039D0002066EE490E68AF090E68BF090E6A0E01F
-:1003AD0020E1F990E68BE0753600F53700000090FE
-:1003BD00E6047480F00000007406F0000000E4F024
-:1003CD0090E740E0FF7E00120ECB90E6A0E0448067
-:1003DD00F002066EE490E68AF090E68BF090E6A0CF
-:1003ED00E020E1F990E68BE0753600F5370000006E
-:1003FD0090E6047480F00000007406F0000000E444
-:10040D00F090E740E0FF7E00120ECB90E6A0E044B6
-:10041D0080F002066EE490E68AF090E68BF090E6AE
-:10042D00A0E020E1F990E68BE0753600F53700008D
-:10043D000090E6047480F00000007406F0000000E7
-:10044D00E4F090E740E0FF7E00120ECB90E6A0E0D6
-:10045D004480F002066EE490E68AF090E68BF09010
-:10046D00E6A0E020E1F990E68BE0753600F5370067
-:10047D00000090E6047480F00000007406F00000A7
-:10048D0000E4F090E740E0FF7E00120ECB90E6A076
-:10049D00E04480F002066E90E6BAE0753200F53366
-:1004AD00A3E0FEE4EE423290E6BEE0753400F53591
-:1004BD00A3E0FEE4EE423490E6B8E064C0600302CF
-:1004CD000594E5354534700302066E90E6A0E020F4
-:1004DD00E1F9C3E5359440E5349400500885343690
-:1004ED00853537800675360075374090E6B9E0B42E
-:1004FD00A335E4F538F539C3E5399537E538953643
-:10050D005060E5332539F582E5323538F583E0FF66
-:10051D0074402539F582E434E7F583EFF00539E5CC
-:10052D00397002053880D0E4F538F539C3E53995D1
-:10053D0037E5389536501874402539F582E434E79F
-:10054D00F58374CDF00539E5397002053880DDADE0
-:10055D00377AE779407EE77F40AB07AF33AE321293
-:10056D000CABE490E68AF090E68BE537F02533F599
-:10057D0033E5363532F532C3E5359537F535E534A6
-:10058D009536F5340204CF90E6B8E064406003027E
-:10059D00066EE5354534700302066EE490E68AF08A
-:1005AD0090E68BF090E6A0E020E1F990E68BE07507
-:1005BD003600F53790E6B9E0B4A335E4F538F539F2
-:1005CD00C3E5399537E5389536503874402539F5FA
-:1005DD0082E434E7F583E0FFE5332539F582E53232
-:1005ED003538F583EFF00539E5397002053880D0DF
-:1005FD00AD377AE779407EE77F40AB07AF33AE3258
-:10060D0012106EE5372533F533E5363532F532C345
-:10061D00E5359537F535E5349536F53402059FE426
-:10062D0090E68AF090E68BF090E6A0E020E1F9905C
-:10063D00E68BE0753600F53700000090E604748017
-:10064D00F00000007406F0000000E4F090E740E0D8
-:10065D00FF7E00120ECB90E6A0E04480F08002D326
-:02066D0022C3A6
-:01066F002268
-:1011ED00C0E0C083C082D2095391EF90E65D7401D7
-:0811FD00F0D082D083D0E03273
-:10121D00C0E0C083C0825391EF90E65D7404F0D0BE
-:06122D0082D083D0E03204
-:10123300C0E0C083C0825391EF90E65D7402F0D0AA
-:0612430082D083D0E032EE
-:100FCA00C0E0C083C08290E680E030E70E850C1056
-:100FDA00850D11851412851513800C85141085153D
-:100FEA0011850C12850D135391EF90E65D7410F084
-:070FFA00D082D083D0E03269
-:10120500C0E0C083C082D20B5391EF90E65D7408B5
-:08121500F0D082D083D0E0325A
-:10100100C0E0C083C08290E680E030E70E850C101E
-:10101100850D11851412851513800C851410851505
-:1010210011850C12850D135391EF90E65D7420F03C
-:07103100D082D083D0E03231
-:01129C00321F
-:01129D00321E
-:01129E00321D
-:01129F00321C
-:0112A000321B
-:0112A100321A
-:0112A2003219
-:0112A3003218
-:0112A4003217
-:0112A5003216
-:0112A6003215
-:0112A7003214
-:0112A8003213
-:0112A9003212
-:0112AA003211
-:0112AB003210
-:0112AC00320F
-:0112AD00320E
-:0112AE00320D
-:0112AF00320C
-:0112B000320B
-:0112B100320A
-:0112B2003209
-:0112B3003208
-:0112B4003207
-:0112B5003206
-:0112B6003205
-:0112B7003204
-:0112B8003203
-:0112B9003202
-:0112BA003201
-:0112BB003200
-:0112BC0032FF
-:0112BD0032FE
-:0112BE0032FD
-:0112BF0032FC
-:10126D00AD071FED600BE4FEEEC3947850F20E80D7
-:01127D00F779
-:01127E00224D
-:040DB800A907AB05D7
-:100DBC007F0112126DD2A27F0112126DC2A2E4FA4F
-:100DCC00E9A802088002C333D8FCFC5304807F01DD
-:100DDC0012126DD2A1BC8004D2A08002C2A07F01ED
-:100DEC0012126DC2A10ABA08D7E4FAEBA802088065
-:100DFC0002C333D8FCFC5304807F0112126DD2A1C4
-:100E0C00BC8004D2A08002C2A07F0112126DC2A1CC
-:040E1C000ABA08D72F
-:010E200022AF
-:020F1100AE0729
-:100F1300ED540F4410FFEEFDE53F540F4450F544EC
-:100F2300EBF545E541540F4490F546E540F547E5BB
-:100F330043540F44D0F548E542F549C2A0C2A1C2CB
-:100F4300A2120DB8AD47AF46120DB8AD49AF481266
-:020F53000DB8D7
-:010F55002279
-:060E8100AB07AA06AC0558
-:100E8700E4FDE51E6010EA7E000DEE2400F582E425
-:100E97003418F583EAF0EBAE050D74002EF582E405
-:100EA7003418F583EBF0AF050D74002FF582E434A9
-:100EB70018F583ECF07A187B00AF1C1211D1AF1C28
-:030EC700121038CE
-:010ECA002205
-:0A106E008E3C8F3D8D3E8A3F8B4083
-:10107800E4F541E541C3953E5020053DE53DAE3CD4
-:101088007002053C14FFE5402541F582E4353FF543
-:0A10980083E0FD120E81054180D9AE
-:0110A200222B
-:0A0CAB008E3C8F3D8D3E8A3F8B404A
-:100CB500E4FDF541E51E6012E53CFF7E000DEE24E6
-:100CC50000F582E43418F583EFF0E53DAE050D74CB
-:100CD500002EF582E43418F583E53DF07A187B00A3
-:100CE500AF1C1211D1AB40AA3FAD3EAF1C1211B5DE
-:010CF50022DC
-:08128700E4F54FD2E9D2AF22D9
-:1010380090E678E020E6F9C2E990E678E04480F0AE
-:10104800EF25E090E679F090E678E030E0F990E678
-:1010580078E04440F090E678E020E6F990E678E021
-:0610680030E1D6D2E922BE
-:1010D700A90790E678E020E6F9E54F702390E678D7
-:1010E700E04480F0E925E090E679F08D4AAF03A966
-:1010F70007754B018A4C894DE4F54E754F01D32294
-:02110700C32201
-:1010A300A90790E678E020E6F9E54F702590E67809
-:1010B300E04480F0E925E0440190E679F08D4AAF01
-:1010C30003A907754B018A4C894DE4F54E754F030F
-:0410D300D322C3223F
-:03004B00020AFCAA
-:100AFC00C0E0C083C082C085C084C086758600C03B
-:100B0C00D075D000C000C001C002C003C006C00731
-:100B1C0090E678E030E206754F06020BE690E67838
-:100B2C00E020E10CE54F64026006754F07020BE60E
-:100B3C00E54F24FE605F14603624FE7003020BD771
-:100B4C0024FC7003020BE324086003020BE6AB4B9E
-:100B5C00AA4CA94DAF4E054E8F82758300120E2103
-:100B6C0090E679F0E54E654A7070754F05806B9094
-:100B7C00E679E0AB4BAA4CA94DAE4E8E8275830044
-:100B8C00120E4E754F02E54A6401704E90E678E005
-:100B9C004420F08045E54A24FEB54E0790E678E007
-:100BAC004420F0E54A14B54E0A90E678E04440F053
-:100BBC00754F0090E679E0AB4BAA4CA94DAE4E8E2A
-:100BCC0082758300120E4E054E800F90E678E0443D
-:100BDC0040F0754F008003754F005391DFD007D064
-:100BEC0006D003D002D001D000D0D0D086D084D093
-:080BFC0085D082D083D0E032E5
-:1011B5001210A3E54F24FA600E146006240770F39D
-:0C11C500D322E4F54FD322E4F54FD322EF
-:1011D1001210D7E54F24FA600E146006240770F34D
-:0C11E100D322E4F54FD322E4F54FD322D3
-:030000000200807B
-:0C008000787FE4F6D8FD75814F02090975
-:100E2100BB010CE58229F582E5833AF583E0225086
-:100E310006E92582F8E622BBFE06E92582F8E222D0
-:0D0E4100E58229F582E5833AF583E49322EA
-:100E4E00F8BB010DE58229F582E5833AF583E8F0DA
-:100E5E00225006E92582C8F622BBFE05E92582C886
-:020E6E00F2226E
-:100E7000EB9FF5F0EA9E42F0E99D42F0E89C45F0D8
-:010E8000224F
-:00000001FF
diff --git a/openhantek/res/firmware/dso5200ax86-loader.hex b/openhantek/res/firmware/dso5200ax86-loader.hex
deleted file mode 100644
index d7758b6f..00000000
--- a/openhantek/res/firmware/dso5200ax86-loader.hex
+++ /dev/null
@@ -1,60 +0,0 @@
-:1003680090E668E0FF74FFF0E0B40B04EFF0D322EE
-:0603780090E668EFF0C3FF
-:01037E00225C
-:1001B500907FE9E064A360030202C5A3E07508002F
-:1001C500F509A3E0FEE4EE4208907FEEE0750A0033
-:1001D500F50BA3E0FEE4EE420A907FE8E064407090
-:1001E50064E50B450A70030202D6E4907FC5F090E2
-:1001F5007FB4E020E3F9907FC5E0750C00F50DE4D0
-:10020500FCFDC3ED950DEC950C501F74C02DF582CA
-:10021500E4347EF583E0FFE5092DF582E5083CF53C
-:1002250083EFF00DBD00010C80D8E50D2509F5091A
-:10023500E50C3508F508C3E50B950DF50BE50A95B5
-:100245000CF50A809C907FE8E064C060030202D64A
-:10025500E50B450A607BC3E50B9440E50A94005025
-:1002650008850A0C850B0D8006750C00750D40E49C
-:10027500FCFDC3ED950DEC950C501FE5092DF582A0
-:10028500E5083CF583E0FF74002DF582E4347FF545
-:1002950083EFF00DBD00010C80D8907FB5E50DF022
-:1002A5002509F509E50C3508F508C3E50B950DF5A8
-:1002B5000BE50A950CF50A907FB4E030E29280F7E1
-:1002C500907FE9E0B4AC0AE4907F00F0907FB5043C
-:0802D500F0907FB4E04402F058
-:0102DD0022FE
-:1000800090E6B9E064A36003020198A3E07508005C
-:10009000F509A3E0FEE4EE420890E6BEE0750A0032
-:1000A000F50BA3E0FEE4EE420A90E6B8E06440708F
-:1000B00066E50B450A70030201ADE490E68AF0A301
-:1000C000F090E6A0E020E1F990E68BE0750C00F5F9
-:1000D0000DE4FCFDC3ED950DEC950C501F74402D07
-:1000E000F582E434E7F583E0FFE5092DF582E508C4
-:1000F0003CF583EFF00DBD00010C80D8E50D25091E
-:10010000F509E50C3508F508C3E50B950DF50BE58C
-:100110000A950CF50A809A90E6B8E064C060030284
-:1001200001ADE50B450A70030201ADC3E50B944038
-:10013000E50A94005008850A0C850B0D8006750CA5
-:1001400000750D40E4FCFDC3ED950DEC950C501FC2
-:10015000E5092DF582E5083CF583E0FF74402DF5B7
-:1001600082E434E7F583EFF00DBD00010C80D8E4A4
-:1001700090E68AF0A3E50DF02509F509E50C3508B0
-:10018000F508C3E50B950DF50BE50A950CF50A90FE
-:10019000E6A0E030E18C80F790E6B9E0B4AC0E90D8
-:1001A000E7407401F0E490E68AF0A304F090E6A042
-:0401B000E04480F0B7
-:0101B4002228
-:1002DE00C2011203689200907F95E044C0F0D2E80C
-:1002EE0030000890E65D74FFF08006907FAB74FFDF
-:1002FE00F030000890E6687408F08007907FAFE059
-:10030E004401F030000890E65C7401F08006907FA6
-:10031E00AE7401F0D2AF3001FD30000512008080C6
-:08032E00031201B5C20180EECB
-:03000300020336BF
-:10033600C0E0C083C082C085C084C086758600D2F6
-:10034600015391EF30000890E65D7401F08006904D
-:100356007FAB7401F0D086D084D085D082D083D094
-:02036600E03283
-:03004300020400B4
-:0404000002033600BD
-:0300000002037F79
-:0C037F00787FE4F6D8FD7581200202DED4
-:00000001FF
diff --git a/openhantek/res/firmware/dso5200x86-firmware.hex b/openhantek/res/firmware/dso5200x86-firmware.hex
deleted file mode 100644
index 9cd64dcd..00000000
--- a/openhantek/res/firmware/dso5200x86-firmware.hex
+++ /dev/null
@@ -1,377 +0,0 @@
-:0A0CF60000010202030304040505D7
-:10090900E4F52DF52CF52BF52AC20BC208C20AC253
-:1009190009120C04E4F50AF50BD2A6C2C975CDFC7F
-:1009290075CC2AD2CAD2AFD2AD7508087509077E2F
-:10093900007F908E0E8F0F7516007517A2750C002B
-:10094900750DAC7514007515CC7518007519EC90FA
-:10095900E680E030E70E850C10850D1185141285AF
-:100969001513800C851410851511850C12850D132E
-:10097900EE54E07003020A95752E00752F807E00F3
-:100989007F908E308F31C374129FFF74019ECF24E4
-:1009990002CF3400FEE48F298E28F527F526F525A8
-:1009A900F524F523F522AF29AE28AD27AC26AB25D2
-:1009B900AA24A923A822C3120E70502AE52F25259F
-:1009C900F582E52E3524F58374CDF0E4FAF9F8E5DE
-:1009D900252401F525EA3524F524E93523F523E80D
-:1009E9003522F52280C0E4F525F524F523F522AF5B
-:1009F90029AE28AD27AC26AB25AA24A923A822C352
-:100A0900120E705035AE24AF25E5312FF582E53051
-:100A19003EF583E0FDE52F2FF582E52E3EF583EDCA
-:100A2900F0E4FAF9F8EF2401F525EA3EF524E93571
-:100A390023F523E83522F52280B5852E0E852F0F63
-:100A490074902480FF740034FFFEC3E5179FF517E7
-:100A5900E5169EF516C3E5119FF511E5109EF510F3
-:100A6900C3E5139FF513E5129EF512C3E50D9FF536
-:100A79000DE50C9EF50CC3E5159FF515E5149EF5DE
-:100A890014C3E5199FF519E5189EF518D2E843D85E
-:100A99002090E668E04409F090E65CE0443DF0D23D
-:100AA900AF90E680E020E105D20E12110990E680B0
-:100AB900E054F7F0538EF8C20B300905120670C2E4
-:100AC90009300B2912128F5024C20B1211902008E1
-:100AD9001690E682E030E704E020E1EF90E682E05C
-:100AE90030E604E020E0E412113812129112129B50
-:020AF90080C7B4
-:010AFB0022D8
-:1006700090E6B9E0700302074B1470030207F424FC
-:10068000FE700302088924FB7003020745147003FF
-:1006900002073F1470030207331470030207392462
-:1006A0000560030208F5121293400302090190E667
-:1006B000BBE024FE602C14604724FD6016146031FA
-:1006C00024067065E50E90E6B3F0E50F90E6B4F011
-:1006D000020901E51690E6B3F0E51790E6B4F002E2
-:1006E0000901E51090E6B3F0E51190E6B4F00209D7
-:1006F00001E51290E6B3F0E51390E6B4F0020901CB
-:1007000090E6BAE0FF121164AA06A9077B01EA4944
-:10071000600DEE90E6B3F0EF90E6B4F002090190C0
-:10072000E6A0E04401F002090190E6A0E04401F0F7
-:1007300002090112125B02090112127F0209011261
-:100740000F93020901121249020901121295400386
-:1007500002090190E6B8E0247F602B14603C24027B
-:1007600060030207EAA208E433FF25E0FFA20AE4DF
-:10077000334F90E740F0E4A3F090E68AF090E68BE8
-:100780007402F0020901E490E740F0A3F090E68AD9
-:10079000F090E68B7402F002090190E6BCE0547E12
-:1007A000FF7E00E0D3948040067C007D0180047CC5
-:1007B000007D00EC4EFEED4F24F6F582740C3EF504
-:1007C00083E493FF3395E0FEEF24A1FFEE34E68F40
-:1007D00082F583E0540190E740F0E4A3F090E68ACC
-:1007E000F090E68B7402F002090190E6A0E044016B
-:1007F000F0020901121297400302090190E6B8E0E5
-:1008000024FE601D2402600302090190E6BAE0B4F0
-:100810000105C20802090190E6A0E04401F00209C6
-:100820000190E6BAE0705990E6BCE0547EFF7E008D
-:10083000E0D3948040067C007D0180047C007D0034
-:10084000EC4EFEED4F24F6F582740C3EF583E493F6
-:10085000FF3395E0FEEF24A1FFEE34E68F82F583AF
-:10086000E054FEF090E6BCE05480FF131313541FD5
-:10087000FFE0540F2F90E683F0E04420F0020901DE
-:1008800090E6A0E04401F08078121299507390E64F
-:10089000B8E024FE60202402706790E6BAE0B4015C
-:1008A00004D208805C90E6BAE06402605490E6A04E
-:1008B000E04401F0804B90E6BCE0547EFF7E00E017
-:1008C000D3948040067C007D0180047C007D00EC98
-:1008D0004EFEED4F24F6F582740C3EF583E493FF53
-:1008E0003395E0FEEF24A1FFEE34E68F82F583E03E
-:1008F0004401F0800C120114500790E6A0E044017E
-:08090000F090E6A0E04480F055
-:0109080022CC
-:0300330002008C3C
-:04008C0053D8EF3224
-:03002B00020F566B
-:100F5600C0E0B2A5E509150970021508E5094508BE
-:100F66007020B28175080475091FE50B6401450AF6
-:100F76007006B2A6D2A78004B2A7D2A6750A0075DB
-:0D0F86000B0075CDFC75CC23C2CFD0E0323E
-:100090001201000200000040B504005200000102FD
-:1000A00000010A06000200000040010009022000D1
-:1000B000010100A0FA0904000002FF00000007058A
-:1000C0000202000200070586020002000902200069
-:1000D000010100A0FA0904000002FF00000007056A
-:1000E00002024000000705860240000004030904E4
-:1000F0000E034F0044004D00200020002000140398
-:10010000440053004F002D00350032003000300015
-:0401100020000000CB
-:03004300020D00AB
-:03005300020D009B
-:100D00000211ED000212330002121D000212050052
-:100D1000020FCA000210010002129C0002129D0084
-:100D200002129E0002129F000212A0000212A100F5
-:100D30000212A2000212A3000212A4000212A500D5
-:100D40000212A60002129D000212A7000212A800C1
-:100D50000212A9000212AA000212AB000212AC0099
-:100D60000212AD0002129D0002129D0002129D00AF
-:100D70000212AE000212AF000212B0000212B10065
-:100D80000212B2000212B3000212B4000212B50045
-:100D90000212B6000212B7000212B8000212B90025
-:100DA0000212BA000212BB000212BC000212BD0005
-:080DB0000212BE000212BF0096
-:1011380090E682E030E004E020E60B90E682E030C2
-:10114800E119E030E71590E680E04401F07F147E75
-:0C11580000120ECB90E680E054FEF02266
-:1011900090E682E044C0F090E681F04387010000D1
-:0411A0000000002229
-:10110900300E0990E680E0440AF0800790E680E01E
-:101119004408F07FDC7E05120ECB90E65D74FFF08B
-:0F11290090E65FF05391EF90E680E054F7F022EC
-:02116400A907D9
-:10116600AE18AF198F828E83A3E064037017AD01AA
-:1011760019ED7001228F828E83E07C002FFDEC3EFC
-:09118600FEAF0580DF7E007F0052
-:01118F00223D
-:100ECB008E3C8F3D90E600E054187012E53D2401F6
-:100EDB00FFE4353CC313F53CEF13F53D801590E66D
-:100EEB0000E05418FFBF100BE53D25E0F53DE53C58
-:100EFB0033F53CE53D153DAE3C7002153C4E6005AF
-:060F0B001211A480EE2289
-:1011A4007400F58690FDA57C05A3E582458370F95E
-:0111B4002218
-:100C040090E600740AF090E6017443F0000000904E
-:100C1400E61274A0F0000000E490E613F000000077
-:100C240090E61474E0F0000000E490E615F0000093
-:100C34000090E6047480F00000007402F0000000EC
-:100C44007406F0000000E4F000000090E60274E690
-:100C5400F000000090E60374F8F000000090E670E5
-:100C6400E04440F0000000E490E609F00000004396
-:100C7400B20F90E61804F00000007411F0000000B8
-:100C840090E61A7409F0000000E490E671F090E632
-:100C940072F075B4FF75B6FFC280C20C1212879051
-:070CA400E67AE04401F022B2
-:01129B002230
-:02128F00D32268
-:02129100D32266
-:02129300D32264
-:100F930090E680E030E71590E6247402F00000004C
-:100FA300E490E625F0000000D20C8013E490E624E0
-:100FB300F000000090E6257440F0000000C20C90A1
-:070FC300E6BAE0F51DD322A0
-:1012490090E740E51DF0E490E68AF090E68B04F023
-:02125900D3229E
-:08127F0090E6BAE0F51BD32252
-:10125B0090E740E51BF0E490E68AF090E68B04F013
-:02126B00D3228C
-:02129500D32262
-:02129700D32260
-:02129900D3225E
-:10011400750A00750B0190E678E05410FFC4540F83
-:100124004450F51C13E433F51E90E6B9E0245E70E8
-:10013400030204A424F0B40B00400302066C9001F3
-:1001440049F828287302016A0201860202030202A6
-:100154005D02035D0203A00203E1020422020463C0
-:1001640002062C0201C4A20CE43390E740F0E490B0
-:10017400E68AF090E68B04F090E6A0E04480F0027A
-:10018400066EE490E68AF090E68BF090E6A0E0201C
-:10019400E1F990E68BE0753600F53700000090E653
-:1001A400047480F00000007406F0000000E4F043E2
-:1001B400800BD280C28090E6A0E04480F002066EFC
-:1001C400E490E68AF090E68BF090E6A0E020E1F976
-:1001D40090E68BE0753600F5377F0F7E00120ECB6C
-:1001E40090E746E0540F4450FFA3E0FDC2A0C2A133
-:1001F400C2A2120DB890E6A0E04480F002066EE4BC
-:1002040090E68AF090E68BF090E6A0E020E1F99089
-:10021400E68BE0753600F5377F0F7E00120ECB902B
-:10022400E745E0FF90E744E0FD90E747E0FB90E717
-:1002340046E0F53F90E743E0F54090E742E0F541C2
-:1002440090E741E0F54290E740E0F543120F11904A
-:09025400E6A0E04480F002066E11
-:10025D00E490E68AF090E68BF090E6A0E020E1F9DC
-:10026D0090E68BE0753600F53790E741E0F5B17516
-:10027D003A0F753BA0E53B153B7002153AE53B6423
-:10028D000A453A70F090E742E0F5B1753A0F753BCB
-:10029D00A0E53B153B7002153AE53B640A453A7003
-:1002AD00F090E743E0F5B1753A0F753BA0E53B15CE
-:1002BD003B7002153AE53B640A453A70F090E7440D
-:1002CD00E0F5B1753A0F753BA0E53B153B70021596
-:1002DD003AE53B640A453A70F090E745E0F5B175B3
-:1002ED003A0F753BA0E53B153B7002153AE53B64B3
-:1002FD000A453A70F090E746E0F5B1753A0F753B57
-:10030D00A0E53B153B7002153AE53B640A453A7092
-:10031D00F090E747E0F5B1753A0F753BA0E53B1559
-:10032D003B7002153AE53B640A453A70F0E4F5B1CD
-:10033D00753A0F753BA0E53B153B7002153AE53B51
-:10034D00640A453A70F090E6A0E04480F002066E33
-:10035D00E490E68AF090E68BF090E6A0E020E1F9DB
-:10036D0090E68BE0753600F53700000090E60474DA
-:10037D0080F0000000C2807406F0000000E4F090F0
-:10038D00E740E0FF7E00120ECB90E6A0E04480F047
-:10039D0002066EE490E68AF090E68BF090E6A0E01F
-:1003AD0020E1F990E68BE0753600F53700000090FE
-:1003BD00E6047480F00000007406F0000000E4F024
-:1003CD0090E740E0FF7E00120ECB90E6A0E0448067
-:1003DD00F002066EE490E68AF090E68BF090E6A0CF
-:1003ED00E020E1F990E68BE0753600F5370000006E
-:1003FD0090E6047480F00000007406F0000000E444
-:10040D00F090E740E0FF7E00120ECB90E6A0E044B6
-:10041D0080F002066EE490E68AF090E68BF090E6AE
-:10042D00A0E020E1F990E68BE0753600F53700008D
-:10043D000090E6047480F00000007406F0000000E7
-:10044D00E4F090E740E0FF7E00120ECB90E6A0E0D6
-:10045D004480F002066EE490E68AF090E68BF09010
-:10046D00E6A0E020E1F990E68BE0753600F5370067
-:10047D00000090E6047480F00000007406F00000A7
-:10048D0000E4F090E740E0FF7E00120ECB90E6A076
-:10049D00E04480F002066E90E6BAE0753200F53366
-:1004AD00A3E0FEE4EE423290E6BEE0753400F53591
-:1004BD00A3E0FEE4EE423490E6B8E064C0600302CF
-:1004CD000594E5354534700302066E90E6A0E020F4
-:1004DD00E1F9C3E5359440E5349400500885343690
-:1004ED00853537800675360075374090E6B9E0B42E
-:1004FD00A335E4F538F539C3E5399537E538953643
-:10050D005060E5332539F582E5323538F583E0FF66
-:10051D0074402539F582E434E7F583EFF00539E5CC
-:10052D00397002053880D0E4F538F539C3E53995D1
-:10053D0037E5389536501874402539F582E434E79F
-:10054D00F58374CDF00539E5397002053880DDADE0
-:10055D00377AE779407EE77F40AB07AF33AE321293
-:10056D000CABE490E68AF090E68BE537F02533F599
-:10057D0033E5363532F532C3E5359537F535E534A6
-:10058D009536F5340204CF90E6B8E064406003027E
-:10059D00066EE5354534700302066EE490E68AF08A
-:1005AD0090E68BF090E6A0E020E1F990E68BE07507
-:1005BD003600F53790E6B9E0B4A335E4F538F539F2
-:1005CD00C3E5399537E5389536503874402539F5FA
-:1005DD0082E434E7F583E0FFE5332539F582E53232
-:1005ED003538F583EFF00539E5397002053880D0DF
-:1005FD00AD377AE779407EE77F40AB07AF33AE3258
-:10060D0012106EE5372533F533E5363532F532C345
-:10061D00E5359537F535E5349536F53402059FE426
-:10062D0090E68AF090E68BF090E6A0E020E1F9905C
-:10063D00E68BE0753600F53700000090E604748017
-:10064D00F00000007406F0000000E4F090E740E0D8
-:10065D00FF7E00120ECB90E6A0E04480F08002D326
-:02066D0022C3A6
-:01066F002268
-:1011ED00C0E0C083C082D2095391EF90E65D7401D7
-:0811FD00F0D082D083D0E03273
-:10121D00C0E0C083C0825391EF90E65D7404F0D0BE
-:06122D0082D083D0E03204
-:10123300C0E0C083C0825391EF90E65D7402F0D0AA
-:0612430082D083D0E032EE
-:100FCA00C0E0C083C08290E680E030E70E850C1056
-:100FDA00850D11851412851513800C85141085153D
-:100FEA0011850C12850D135391EF90E65D7410F084
-:070FFA00D082D083D0E03269
-:10120500C0E0C083C082D20B5391EF90E65D7408B5
-:08121500F0D082D083D0E0325A
-:10100100C0E0C083C08290E680E030E70E850C101E
-:10101100850D11851412851513800C851410851505
-:1010210011850C12850D135391EF90E65D7420F03C
-:07103100D082D083D0E03231
-:01129C00321F
-:01129D00321E
-:01129E00321D
-:01129F00321C
-:0112A000321B
-:0112A100321A
-:0112A2003219
-:0112A3003218
-:0112A4003217
-:0112A5003216
-:0112A6003215
-:0112A7003214
-:0112A8003213
-:0112A9003212
-:0112AA003211
-:0112AB003210
-:0112AC00320F
-:0112AD00320E
-:0112AE00320D
-:0112AF00320C
-:0112B000320B
-:0112B100320A
-:0112B2003209
-:0112B3003208
-:0112B4003207
-:0112B5003206
-:0112B6003205
-:0112B7003204
-:0112B8003203
-:0112B9003202
-:0112BA003201
-:0112BB003200
-:0112BC0032FF
-:0112BD0032FE
-:0112BE0032FD
-:0112BF0032FC
-:10126D00AD071FED600BE4FEEEC3947850F20E80D7
-:01127D00F779
-:01127E00224D
-:040DB800A907AB05D7
-:100DBC007F0112126DD2A27F0112126DC2A2E4FA4F
-:100DCC00E9A802088002C333D8FCFC5304807F01DD
-:100DDC0012126DD2A1BC8004D2A08002C2A07F01ED
-:100DEC0012126DC2A10ABA08D7E4FAEBA802088065
-:100DFC0002C333D8FCFC5304807F0112126DD2A1C4
-:100E0C00BC8004D2A08002C2A07F0112126DC2A1CC
-:040E1C000ABA08D72F
-:010E200022AF
-:020F1100AE0729
-:100F1300ED540F4410FFEEFDE53F540F4450F544EC
-:100F2300EBF545E541540F4490F546E540F547E5BB
-:100F330043540F44D0F548E542F549C2A0C2A1C2CB
-:100F4300A2120DB8AD47AF46120DB8AD49AF481266
-:020F53000DB8D7
-:010F55002279
-:060E8100AB07AA06AC0558
-:100E8700E4FDE51E6010EA7E000DEE2400F582E425
-:100E97003418F583EAF0EBAE050D74002EF582E405
-:100EA7003418F583EBF0AF050D74002FF582E434A9
-:100EB70018F583ECF07A187B00AF1C1211D1AF1C28
-:030EC700121038CE
-:010ECA002205
-:0A106E008E3C8F3D8D3E8A3F8B4083
-:10107800E4F541E541C3953E5020053DE53DAE3CD4
-:101088007002053C14FFE5402541F582E4353FF543
-:0A10980083E0FD120E81054180D9AE
-:0110A200222B
-:0A0CAB008E3C8F3D8D3E8A3F8B404A
-:100CB500E4FDF541E51E6012E53CFF7E000DEE24E6
-:100CC50000F582E43418F583EFF0E53DAE050D74CB
-:100CD500002EF582E43418F583E53DF07A187B00A3
-:100CE500AF1C1211D1AB40AA3FAD3EAF1C1211B5DE
-:010CF50022DC
-:08128700E4F54FD2E9D2AF22D9
-:1010380090E678E020E6F9C2E990E678E04480F0AE
-:10104800EF25E090E679F090E678E030E0F990E678
-:1010580078E04440F090E678E020E6F990E678E021
-:0610680030E1D6D2E922BE
-:1010D700A90790E678E020E6F9E54F702390E678D7
-:1010E700E04480F0E925E090E679F08D4AAF03A966
-:1010F70007754B018A4C894DE4F54E754F01D32294
-:02110700C32201
-:1010A300A90790E678E020E6F9E54F702590E67809
-:1010B300E04480F0E925E0440190E679F08D4AAF01
-:1010C30003A907754B018A4C894DE4F54E754F030F
-:0410D300D322C3223F
-:03004B00020AFCAA
-:100AFC00C0E0C083C082C085C084C086758600C03B
-:100B0C00D075D000C000C001C002C003C006C00731
-:100B1C0090E678E030E206754F06020BE690E67838
-:100B2C00E020E10CE54F64026006754F07020BE60E
-:100B3C00E54F24FE605F14603624FE7003020BD771
-:100B4C0024FC7003020BE324086003020BE6AB4B9E
-:100B5C00AA4CA94DAF4E054E8F82758300120E2103
-:100B6C0090E679F0E54E654A7070754F05806B9094
-:100B7C00E679E0AB4BAA4CA94DAE4E8E8275830044
-:100B8C00120E4E754F02E54A6401704E90E678E005
-:100B9C004420F08045E54A24FEB54E0790E678E007
-:100BAC004420F0E54A14B54E0A90E678E04440F053
-:100BBC00754F0090E679E0AB4BAA4CA94DAE4E8E2A
-:100BCC0082758300120E4E054E800F90E678E0443D
-:100BDC0040F0754F008003754F005391DFD007D064
-:100BEC0006D003D002D001D000D0D0D086D084D093
-:080BFC0085D082D083D0E032E5
-:1011B5001210A3E54F24FA600E146006240770F39D
-:0C11C500D322E4F54FD322E4F54FD322EF
-:1011D1001210D7E54F24FA600E146006240770F34D
-:0C11E100D322E4F54FD322E4F54FD322D3
-:030000000200807B
-:0C008000787FE4F6D8FD75814F02090975
-:100E2100BB010CE58229F582E5833AF583E0225086
-:100E310006E92582F8E622BBFE06E92582F8E222D0
-:0D0E4100E58229F582E5833AF583E49322EA
-:100E4E00F8BB010DE58229F582E5833AF583E8F0DA
-:100E5E00225006E92582C8F622BBFE05E92582C886
-:020E6E00F2226E
-:100E7000EB9FF5F0EA9E42F0E99D42F0E89C45F0D8
-:010E8000224F
-:00000001FF
diff --git a/openhantek/res/firmware/dso5200x86-loader.hex b/openhantek/res/firmware/dso5200x86-loader.hex
deleted file mode 100644
index d7758b6f..00000000
--- a/openhantek/res/firmware/dso5200x86-loader.hex
+++ /dev/null
@@ -1,60 +0,0 @@
-:1003680090E668E0FF74FFF0E0B40B04EFF0D322EE
-:0603780090E668EFF0C3FF
-:01037E00225C
-:1001B500907FE9E064A360030202C5A3E07508002F
-:1001C500F509A3E0FEE4EE4208907FEEE0750A0033
-:1001D500F50BA3E0FEE4EE420A907FE8E064407090
-:1001E50064E50B450A70030202D6E4907FC5F090E2
-:1001F5007FB4E020E3F9907FC5E0750C00F50DE4D0
-:10020500FCFDC3ED950DEC950C501F74C02DF582CA
-:10021500E4347EF583E0FFE5092DF582E5083CF53C
-:1002250083EFF00DBD00010C80D8E50D2509F5091A
-:10023500E50C3508F508C3E50B950DF50BE50A95B5
-:100245000CF50A809C907FE8E064C060030202D64A
-:10025500E50B450A607BC3E50B9440E50A94005025
-:1002650008850A0C850B0D8006750C00750D40E49C
-:10027500FCFDC3ED950DEC950C501FE5092DF582A0
-:10028500E5083CF583E0FF74002DF582E4347FF545
-:1002950083EFF00DBD00010C80D8907FB5E50DF022
-:1002A5002509F509E50C3508F508C3E50B950DF5A8
-:1002B5000BE50A950CF50A907FB4E030E29280F7E1
-:1002C500907FE9E0B4AC0AE4907F00F0907FB5043C
-:0802D500F0907FB4E04402F058
-:0102DD0022FE
-:1000800090E6B9E064A36003020198A3E07508005C
-:10009000F509A3E0FEE4EE420890E6BEE0750A0032
-:1000A000F50BA3E0FEE4EE420A90E6B8E06440708F
-:1000B00066E50B450A70030201ADE490E68AF0A301
-:1000C000F090E6A0E020E1F990E68BE0750C00F5F9
-:1000D0000DE4FCFDC3ED950DEC950C501F74402D07
-:1000E000F582E434E7F583E0FFE5092DF582E508C4
-:1000F0003CF583EFF00DBD00010C80D8E50D25091E
-:10010000F509E50C3508F508C3E50B950DF50BE58C
-:100110000A950CF50A809A90E6B8E064C060030284
-:1001200001ADE50B450A70030201ADC3E50B944038
-:10013000E50A94005008850A0C850B0D8006750CA5
-:1001400000750D40E4FCFDC3ED950DEC950C501FC2
-:10015000E5092DF582E5083CF583E0FF74402DF5B7
-:1001600082E434E7F583EFF00DBD00010C80D8E4A4
-:1001700090E68AF0A3E50DF02509F509E50C3508B0
-:10018000F508C3E50B950DF50BE50A950CF50A90FE
-:10019000E6A0E030E18C80F790E6B9E0B4AC0E90D8
-:1001A000E7407401F0E490E68AF0A304F090E6A042
-:0401B000E04480F0B7
-:0101B4002228
-:1002DE00C2011203689200907F95E044C0F0D2E80C
-:1002EE0030000890E65D74FFF08006907FAB74FFDF
-:1002FE00F030000890E6687408F08007907FAFE059
-:10030E004401F030000890E65C7401F08006907FA6
-:10031E00AE7401F0D2AF3001FD30000512008080C6
-:08032E00031201B5C20180EECB
-:03000300020336BF
-:10033600C0E0C083C082C085C084C086758600D2F6
-:10034600015391EF30000890E65D7401F08006904D
-:100356007FAB7401F0D086D084D085D082D083D094
-:02036600E03283
-:03004300020400B4
-:0404000002033600BD
-:0300000002037F79
-:0C037F00787FE4F6D8FD7581200202DED4
-:00000001FF
diff --git a/openhantek/res/firmware/dso6022be-firmware.hex b/openhantek/res/firmware/dso6022be-firmware.hex
index e875bd25..0e826e0a 100644
--- a/openhantek/res/firmware/dso6022be-firmware.hex
+++ b/openhantek/res/firmware/dso6022be-firmware.hex
@@ -1,405 +1,260 @@
-:02095e00c105d1
-:100cb80090e6007410f0120f1800000090e612740d
-:100cc800a0f0000000e490e613f000000090e614a5
-:100cd80074e0f0000000e490e615f000000090e6f3
-:100ce800047480f00000007402f00000007406f044
-:100cf800000000e4f000000090e61804f000000096
-:100d08007411f000000090e61a7409f000000090d9
-:100d1800e6d27402f000000090e6e214f000000051
-:100d2800e490e671f075b4ff90e670f075b280c299
-:100d3800a4c2a3c2a2c2a7c2a6c2a5f51df51a12d3
-:0a0d4800130990e67ae04401f0225e
-:100b7b00e51d64017031751d0290e6f574fff09070
-:100b8b00e6047480f00000007402f00000007406ac
-:100b9b00f0000000e4f0000000fffe000fbf0001ba
-:100bab000ebe03f7bfe8f4e5bb30e72590e6f4e0b3
-:100bbb0030e01ee5ac20e019e5bb30e7fb90e6d05a
-:100bcb007428f0000000e490e6d1f000000075bb43
-:010bdb000613
-:010bdc0022f6
-:02002800d322e1
-:02004000d322c9
-:02004600d322c3
-:10104c0090e680e030e71800000090e6247402f08f
-:10105c00000000e490e625f0000000d205801600a8
-:10106c000000e490e624f000000090e6257440f0c7
-:0d107c00000000c20590e6bae0f51bd3228b
-:1012dd0090e740e51bf0e490e68af090e68b04f091
-:0212ed00d3220a
-:0813010090e6bae0f518d322d2
-:1012ef0090e740e518f0e490e68af090e68b04f082
-:0212ff00d322f8
-:02004800d322c1
-:02004e00d322bb
-:02005000d322b9
-:1000560090e678e05410ffc4540f4450f51913e4a9
-:1000660033f51cd20290e6b9e0245e605024f060bd
-:100076003024d2b4080040030204d590008f75f0f6
-:1000860003a4c58325f0c5837302024b02029602c0
-:1000960002dc0204460204d50204d50204d5020499
-:1000a60065a205e43390e740f0e490e68af090e636
-:1000b6008b04f090e6a0e04480f00204d790e6ba04
-:1000c600e0752d00f52ea3e0fee4ee422d90e6be8f
-:1000d600e0752f00f530a3e0fee4ee422f90e6b87f
-:1000e600e064c060030201b3e530452f70030204eb
-:1000f600d790e6a0e020e1f9c3e5309440e52f94df
-:10010600005008852f3185303280067531007532f2
-:100116004090e6b9e0b4a335e4f533f534c3e534ed
-:100126009532e53395315060e52e2534f582e52d7f
-:100136003533f583e0ff74402534f582e434e7f582
-:1001460083eff00534e5347002053380d0e4f533ef
-:10015600f534c3e5349532e53395315018744025ae
-:1001660034f582e434e7f58374cdf00534e5347074
-:1001760002053380ddad327ae779407ee77f40ab1a
-:1001860007af2eae2d120fbde490e68af090e68bf7
-:10019600e532f0252ef52ee531352df52dc3e5306a
-:1001a6009532f530e52f9531f52f0200ee90e6b841
-:1001b600e0644060030204d7e530452f7003020473
-:1001c600d7e490e68af090e68bf090e6a0e020e196
-:1001d600f990e68be0753100f53290e6b9e0b4a30c
-:1001e60035e4f533f534c3e5349532e533953150ce
-:1001f6003874402534f582e434e7f583e0ffe52ed4
-:100206002534f582e52d3533f583eff00534e534f5
-:100216007002053380d0ad327ae779407ee77f40c1
-:10022600ab07af2eae2d12112de532252ef52ee59c
-:1002360031352df52dc3e5309532f530e52f953165
-:10024600f52f0201bee490e68af090e68bf090e688
-:10025600a0e020e1f990e740e0f53514602914604c
-:100266001d24fd601024fb60030204d7c2a4d2a3a0
-:10027600d2a20204d7c2a4c2a3c2a20204d7c2a4b5
-:10028600c2a3d2a20204d7c2a4d2a3c2a20204d796
-:10029600e490e68af090e68bf090e6a0e020e1f9a3
-:1002a60090e740e0f53524fe601a24fd600d24fb3e
-:1002b600701bc2a7d2a6d2a50204d7c2a7c2a6c2e5
-:1002c600a50204d7c2a7c2a6d2a50204d7c2a7d246
-:1002d600a6c2a50204d7e490e68af090e68bf090d9
-:1002e600e6a0e020e1f990e740e0f535120ef203d2
-:1002f600880103740403600803c20a034d1003afa8
-:1003060014033b1803291e031730039c3200000315
-:10031600d390e60174eaf090e05074fff0751a018c
-:100326000203d390e60174aaf090e05074fff075d2
-:100336001a010203d390e60174caf090e05074fbf0
-:10034600f0751a010203d390e60174caf090e040fa
-:100356007401f0a3f0e4f51a807390e60174caf014
-:1003660090e0407402f0a304f0e4f51a805f90e692
-:100376000174caf090e0407405f0a304f0e4f51aa5
-:10038600804b90e60174caf090e0407417f0a30425
-:10039600f0e4f51a803790e60174caf090e04074f4
-:1003a60030f0a3f0e4f51a802490e60174caf090c8
-:1003b600e0407478f0a3f0e4f51a801190e6017439
-:1003c600caf090e04074f0f0a3f0e4f51a90e6f578
-:1003d60074fff090e080e090e6f3f090e081e0902a
-:1003e600e6c3f090e082e090e6c1f090e083e09012
-:1003f600e6c2f090e085e090e6c0f090e086e090fe
-:10040600e6f4f075af07e51ab4010a74e0f59a74dc
-:1004160087f59b800874e0f59a7400f59b759de45a
-:10042600e4f59ef533f53490e67be090e67cf00546
-:1004360034e534700205336480453370ea0204d72c
-:10044600e490e68af090e68bf090e6a0e020e1f9f1
-:1004560090e740e0f53564017077751d0180729074
-:10046600e6bae0752d00f52ea3e0fee4ee422d90ef
-:10047600e6bee0752f00f530a3e0fee4ee422fe580
-:1004860030452f604c90e6a0e020e1f9c3e53094ba
-:1004960040e52f94005008852f318530328006754f
-:1004a600310075324090e7407401f0e490e68af03e
-:1004b60090e68be532f0252ef52ee531352df52d1e
-:1004c600c3e5309532f530e52f9531f52f80b0d361
-:0204d60022c33f
-:0104d8002201
-:10128100c0e0c083c082d2015391ef90e65d74014a
-:08129100f0d082d083d0e032de
-:1012b100c0e0c083c0825391ef90e65d7404f0d02a
-:0612c10082d083d0e03270
-:1012c700c0e0c083c0825391ef90e65d7402f0d016
-:0612d70082d083d0e0325a
-:10108900c0e0c083c08290e680e030e70e850a0e9a
-:10109900850b0f851210851311800c85120e85138f
-:1010a9000f850a10850b115391ef90e65d7410f0ce
-:0710b900d082d083d0e032a9
-:10129900c0e0c083c082d2045391ef90e65d740828
-:0812a900f0d082d083d0e032c6
-:1010c000c0e0c083c08290e680e030e70e850a0e63
-:1010d000850b0f851210851311800c85120e851358
-:1010e0000f850a10850b115391ef90e65d7420f087
-:0710f000d082d083d0e03272
-:01002a0032a3
-:01003200329b
-:01004200328b
-:01004a003283
-:01005200327b
-:010bf90032c9
-:010bfa0032c8
-:010bfb0032c7
-:010bfc0032c6
-:010bfd0032c5
-:010bfe0032c4
-:010bff0032c3
-:010dfa0032c6
-:010dfb0032c5
-:010dfc0032c4
-:010dfd0032c3
-:010dfe0032c2
-:010dff0032c1
-:0113110032a9
-:0113120032a8
-:0113130032a7
-:0113140032a6
-:0113150032a5
-:0113160032a4
-:0113170032a3
-:0113180032a2
-:0113190032a1
-:01131a0032a0
-:01131b00329f
-:01131c00329e
-:01131d00329d
-:01131e00329c
-:01131f00329b
-:01132000329a
-:011321003299
-:011322003298
-:060f7300ab07aa06ac0565
-:100f7900e4fde51c6010ea7e000dee2407f582e42d
-:100f890034e1f583eaf0ebae050d74072ef582e442
-:100f990034e1f583ebf0af050d74072ff582e434e6
-:100fa900e1f583ecf07ae17b07af19120ddeaf1999
-:030fb9001210f71c
-:010fbc002212
-:0a112d008e368f378d388a398b3ae1
-:10113700e4f53be53bc3953850200537e537ae3638
-:101147007002053614ffe53a253bf582e43539f59b
-:0a11570083e0fd120f73053b80d901
-:01116100226b
-:0a0fbd008e368f378d388a398b3a53
-:100fc700e4fde51c6012e536ff7e000dee2407f513
-:100fd70082e434e1f583eff0e537ae050d74072eb3
-:100fe700f582e434e1f583e537f07ae17b07af1961
-:0e0ff700120ddeab3aaa39ad38af19120bdd80
-:0110050022c8
-:100960006080e0000e030111010130070100020167
-:1009700000001100fffefffefffeffff0009121244
-:10098000002d123f080301010101010701020401ca
-:1009900000000000fffcfffefffeffff090912122e
-:1009a000002d363f17180101010101070002010067
-:1009b00000001000fffbfffbfbfbfbfb000912121a
-:1009c000002d123f0803013f010101070102000150
-:1009d00000000000fffdffffffffffff09091212eb
-:1009e000002d363f6080e087010201013f010107d1
-:1009f00000000200010000000702020707070707c6
-:100a0000000000003f00003f03013f01010101071a
-:100a10000202050000000000050707070707070797
-:100a200000003f000000003f010180010101bf07fd
-:100a30000202030202021100ffffffffffffffffa0
-:100a400000091212002d123f0101010101010107ed
-:100a5000000000000000000007070707070707075e
-:100a6000000000000000003f47e080c000000fca07
-:020a70001e0066
-:100f180090e60174caf090e6f574fff090e080e086
-:100f280090e6f3f090e081e090e6c3f090e082e094
-:100f380090e6c1f090e083e090e6c2f090e085e0b2
-:100f480090e6c0f090e086e090e6f4f075af0774a4
-:100f5800e0f59a7400f59b759de4e4f59eff90e634
-:0a0f68007be090e67cf00fbf80f400
-:010f7200225c
-:0a00360000010202030304040505a3
-:10077300c204c200c203c201c20275080875090798
-:10078300120cb8c2c975cdf875cc40d2cad2adc26d
-:1007930087c2a0d2a17e0e7f008e0c8f0d75140e22
-:1007a300751512750a0e750b1c75120e75133c75b3
-:1007b300160e75175c90e680e030e70e850a0e850d
-:1007c3000b0f851210851311800c85120e85130fe4
-:1007d300850a10850b11ee54e070030208f77529a2
-:1007e30000752a807e0e7f008e2b8f2cc374909f02
-:1007f300ff740e9ecf2402cf3400fee48f288e2791
-:10080300f526f525f524f523f522f521af28ae27a6
-:10081300ad26ac25ab24aa23a922a821c3120ee13d
-:10082300502ae52a2524f582e5293523f58374cd5d
-:10083300f0e4faf9f8e5242401f524ea3523f52355
-:10084300e93522f522e83521f52180c0e4f524f5c8
-:1008530023f522f521af28ae27ad26ac25ab24aa7c
-:1008630023a922a821c3120ee15037e52c2524f534
-:1008730082e52b3523f583e0ffe52a2524f582e580
-:10088300293523f583eff0e4faf9f8e5242401f59b
-:1008930024ea3523f523e93522f522e83521f5212c
-:1008a30080b385290c852a0d74002480ff740e34cf
-:1008b300fffec3e5159ff515e5149ef514c3e50f7b
-:1008c3009ff50fe50e9ef50ec3e5119ff511e5109b
-:1008d3009ef510c3e50b9ff50be50a9ef50ac3e5ec
-:1008e300139ff513e5129ef512c3e5179ff517e560
-:1008f300169ef516d2e843d82090e668e04409f046
-:1009030090e65ce0443df0d2af90e680e020e10564
-:10091300d2061211fa90e680e054f7f0538ef8c233
-:10092300043001051204d9c20130042912002850f1
-:1009330024c20412000320001690e682e030e7048c
-:10094300e020e1ef90e682e030e604e020e0e4120c
-:0a0953001229120040120b7b80c72e
-:01095d002277
-:1004d90090e6b9e070030205b514700302065e24c4
-:1004e900fe70030206f324fb70030205af147003c8
-:1004f9000205a914700302059d1470030205a324c3
-:1005090005600302075f120046400302076b90e68d
-:10051900bbe024fe602c14604724fd601614603192
-:1005290024067066e50c90e6b3f0e50d90e6b4f0ac
-:1005390002076be51490e6b3f0e51590e6b4f00216
-:10054900076be50e90e6b3f0e50f90e6b4f002070d
-:100559006be51090e6b3f0e51190e6b4f002076b95
-:1005690090e6bae0ff121255aa06a9077b01ea49eb
-:100579004b600dee90e6b3f0ef90e6b4f002076b36
-:1005890090e6a0e04401f002076b90e6a0e0440188
-:10059900f002076b1212ef02076b12130102076bcd
-:1005a90012104c02076b1212dd02076b1200484051
-:1005b9000302076b90e6b8e0247f602b14603c24ab
-:1005c900026003020654a200e433ff25e0ffa20300
-:1005d900e4334f90e740f0e4a3f090e68af090e628
-:1005e9008b7402f002076be490e740f0a3f090e609
-:1005f9008af090e68b7402f002076b90e6bce05437
-:100609007eff7e00e0d3948040067c007d0180045b
-:100619007c007d00ec4efeed4f2436f58274003ee1
-:10062900f583e493ff3395e0feef24a1ffee34e672
-:100639008f82f583e0540190e740f0e4a3f090e65f
-:100649008af090e68b7402f002076b90e6a0e04412
-:1006590001f002076b12004e400302076b90e6b8e7
-:10066900e024fe601d2402600302076b90e6bae0f5
-:10067900b40105c20002076b90e6a0e04401f00254
-:10068900076b90e6bae0705990e6bce0547eff7eb5
-:1006990000e0d3948040067c007d0180047c007dcd
-:1006a90000ec4efeed4f2436f58274003ef583e4ee
-:1006b90093ff3395e0feef24a1ffee34e68f82f538
-:1006c90083e054fef090e6bce05480ff131313540a
-:1006d9001fffe0540f2f90e683f0e04420f002075b
-:1006e9006b90e6a0e04401f08078120050507390be
-:1006f900e6b8e024fe60202402706790e6bae0b410
-:100709000104d200805c90e6bae06402605490e68d
-:10071900a0e04401f0804b90e6bce0547eff7e00ef
-:10072900e0d3948040067c007d0180047c007d003c
-:10073900ec4efeed4f2436f58274003ef583e493ca
-:10074900ff3395e0feef24a1ffee34e68f82f583b7
-:10075900e04401f0800c120056500790e6a0e044f6
-:0907690001f090e6a0e04480f0ec
-:010772002264
-:0300330002002e9a
-:04002e0053d8ef3282
-:03002b0002119629
-:10119600c0e0b287e509150970021508e50945089a
-:1011a600701575080475091f300206b2a1d2a08019
-:1011b60004b2a0d2a1c20275cdf875cc40c2cfd080
-:0211c600e03215
-:100e00001201000200000040b5042260000001024f
-:100e100000010a0600020000004001000902200053
-:100e200001010080320904000002ff0000000705f4
-:100e300002020002000705860200020009022000eb
-:100e400001010080320904000004ff0000000705d2
-:100e50000202400000070586024000000403090466
-:100e60000e034f0044004d0020002000200022030c
-:100e7000480061006e00740065006b004400530080
-:100e80004f003600300032003200420045002000a2
-:020e9000000060
-:1012290090e682e030e004e020e60b90e682e030d0
-:10123900e119e030e71590e680e04401f07f147e83
-:0c1249000012100690e680e054fef02237
-:1000030090e682e044c0f090e681f043870100006f
-:0400130000000022c7
-:1011fa0030060990e680e0440af0800790e680e035
-:10120a004408f07fdc7e0512100690e65d74fff05c
-:0f121a0090e65ff05391ef90e680e054f7f022fa
-:08130900e4f541d2e9d2af2264
-:1010f70090e678e020e6f9c2e990e678e04480f0ef
-:10110700ef25e090e679f090e678e030e0f990e6b8
-:1011170078e04440f090e678e020e6f990e678e061
-:0611270030e1d6d2e922fe
-:1011c800a90790e678e020e6f9e541702390e678f3
-:1011d800e04480f0e925e090e679f08d3caf03a982
-:1011e80007753d018a3e893fe4f540754101d322e8
-:0211f800c32210
-:10116200a90790e678e020e6f9e541702590e67857
-:10117200e04480f0e925e0440190e679f08d3caf4f
-:1011820003a907753d018a3e893fe4f54075410395
-:04119200d322c3227f
-:03004b00020a7333
-:100a7300c0e0c083c082c085c084c086758600c0c4
-:100a8300d075d000c000c001c002c003c006c007bb
-:100a930090e678e030e206754106020b5d90e67859
-:100aa300e020e10ce54164026006754107020b5d3d
-:100ab300e54124fe605f14603624fe7003020b4e92
-:100ac30024fc7003020b5a24086003020b5dab3d48
-:100ad300aa3ea93faf4005408f82758300120e9254
-:100ae30090e679f0e540653c7070754105806b9048
-:100af300e679e0ab3daa3ea93fae408e8275830006
-:100b0300120ebf754102e53c6401704e90e678e039
-:100b13004420f08045e53c24feb5400790e678e0ac
-:100b23004420f0e53c14b5400a90e678e04440f0f8
-:100b330075410090e679e0ab3daa3ea93fae408ef9
-:100b430082758300120ebf0540800f90e678e04463
-:100b530040f075410080037541005391dfd007d009
-:100b630006d003d002d001d000d0d0d086d084d01c
-:080b730085d082d083d0e0326e
-:02125500a907e7
-:10125700ae16af178f828e83a3e064037017ad01bc
-:1012670019ed7001228f828e83e07c002ffdec3e0a
-:09127700feaf0580df7e007f0060
-:01128000224b
-:100bdd00121162e54124fa600e146006240770f3c9
-:0c0bed00d322e4f541d322e4f541d322e9
-:100dde001211c8e54124fa600e146006240770f360
-:0c0dee00d322e4f541d322e4f541d322e6
-:101006008e2d8f2e90e600e054187012e52e2401e6
-:10101600ffe4352dc313f52def13f52e801590e65d
-:1010260000e05418ffbf100be52e25e0f52ee52d48
-:1010360033f52de52e152eae2d7002152d4e6005bd
-:0610460012001780ee22eb
-:100017007400f58690fda57c05a3e582458370f9fc
-:0100270022b6
-:03004300020c00ac
-:03005300020c009c
-:100c0000021281000212c7000212b1000212990002
-:100c1000021089000210c00002002a000200320007
-:100c20000200420002004a0002005200020bf900da
-:100c3000020bfa00020bfb00020bfc00020bfd0092
-:100c4000020bfe0002003200020bff00020dfa0050
-:100c5000020dfb00020dfc00020dfd00020dfe0066
-:100c6000020dff00020032000200320002003200da
-:100c700002131100021312000213130002131400d6
-:100c800002131500021316000213170002131800b6
-:100c90000213190002131a0002131b0002131c0096
-:100ca00002131d0002131e0002131f000213200076
-:080cb0000213210002132200cf
-:03000000020d529c
-:0c0d5200787fe4f6d8fd758141020d9910
-:100e9200bb010ce58229f582e5833af583e0225015
-:100ea20006e92582f8e622bbfe06e92582f8e2225f
-:0d0eb200e58229f582e5833af583e4932279
-:100ebf00f8bb010de58229f582e5833af583e8f069
-:100ecf00225006e92582c8f622bbfe05e92582c815
-:020edf00f222fd
-:100ee100eb9ff5f0ea9e42f0e99d42f0e89c45f067
-:010ef10022de
-:100ef200d083d082f8e4937012740193700da3a38f
-:100f020093f8740193f5828883e4737402936860a2
-:060f1200efa3a3a380dfa2
-:100d5e00020773e493a3f8e493a34003f68001f231
-:100d6e0008dff48029e493a3f85407240cc8c33396
-:100d7e00c4540f4420c8834004f456800146f6df65
-:100d8e00e4800b010204081020408090095ee47e8e
-:100d9e00019360bca3ff543f30e509541ffee4935a
-:100dae00a360010ecf54c025e060a840b8e493a321
-:100dbe00fae493a3f8e493a3c8c582c8cac583ca4c
-:100dce00f0a3c8c582c8cac583cadfe9dee780be04
-:010a72000083
-:03009b0002038cd1
-:1002f50003580103500203480403400803700a032e
-:10030500380c03301003681403281803211e031d3d
-:0e03150030036032000003d374ea800274aa41
-:0f032300751a01805e79017a017b0980467901a4
-:100332007a017b01803e79017a027b018036790263
-:100342007a037b01802e79057a067b018026790b60
-:100352007a0c7b01801e79177a187b018016792f1f
-:100362007a307b01800e79777a787b01800679ef8b
-:100372007af07b0190e040e9f0a3eaf0a3ebf0e42d
-:0f038200f51a74ca90e601f08047e490e68af01d
-:0f03910090e68bf090e6a0e020e1f990e740e0e5
-:0f03a000600a94035006240a90e61af00204d76c
-:010b940082de
-:010b9a0086d4
-:010cf0008281
-:010cf6008677
-:00000001ff
+:04000000020059326F
+:01000B0032C2
+:0100130032BA
+:01001B0032B2
+:0100230032AA
+:03002B000201FBD4
+:0300330002013295
+:01003B003292
+:03004300023F0079
+:01004B003282
+:03005300023F0069
+:1C00B200750800750900750A02750B00750CF4750D01750EF4750F01C200C201BD
+:0300E000020056C5
+:030056000207C2DC
+:2000E300AF827401B54C0280157402B54C0280127405B54C02800F740AB54C12800C7E48C6
+:2001030080107E24800C7E0080087E6C800475820022EF60067DE07F0080047D1C7F00EDD7
+:20012300F4FFE5A05207ED5E4FF5A075820122C2DC32C0E0C082C083D2005391EF90E65D35
+:200143007401F0D083D082D0E032C021C0E0C0F0C082C083C007C006C005C004C003C0025F
+:20016300C001C000C0D075D0007582001212115391EF90E65D7410F0D0D0D000D001D002CD
+:20018300D003D004D005D006D007D083D082D0F0D0E0D02132C021C0E0C0F0C082C083C085
+:2001A30007C006C005C004C003C002C001C000C0D075D0007582011212115391EF90E65D38
+:2001C3007420F0D0D0D000D001D002D003D004D005D006D007D083D082D0F0D0E0D0213224
+:2001E300C0E0C082C083D2015391EF90E65D7408F0D083D082D0E032C0E0C0D0B287E50E0F
+:20020300450F6019150E74FFB50E02150FE50E450F700A850C0E850D0FB2A0D2A1C2CFD068
+:20022300D0D0E032E582FF30E00BADB17E004305088DB1800353B1F7EF30E408AEB14306ED
+:20024300018EB12253B1FE22850A4C754D00905DC01213F0AE82AF83AC097D00C3EC9EEDE8
+:2002630064808FF063F08095F0400990E640E053E07FF02290E640E0FF43078090E640EF19
+:20028300F02285820A7401B50A0280057402B50A18AF0A74072FF50B90E618F090E61AE5DA
+:2002A3000BF012024B758201227582002290E6F574FFF000000000E5BB60FC90E604748076
+:2002C300F00000000090E618E4F00000000090E61AE4F00000000090E6047402F000000085
+:2002E3000090E6047406F00000000090E618E50BF00000000090E61AE50BF00000000090A9
+:20030300E604E4F02290E6F574FFF000000000E50870057E06FF80047E027F0090E648EE18
+:20032300F0221202B07EE87F03EE24FFFCEF34FFFD8C068D07EC4D70F0E5BB30E7FB00005F
+:20034300000090E6D07428F00000000090E6D1E4F0E50870057E06FF80047E047F008EBBFA
+:2003630022AF8290E680E030E7067D1C7E3D80047DA67E3DEF75F010A42416FBE435F0FC3C
+:20038300EB2DFDEC3EFC7E80EFF508703590E612E4F090E61474E0F090E6E27401F08D829A
+:2003A3008C838EF01213D390E625F074012DFAE43CFB8E078A828B838FF01213D390E624B3
+:2003C300F02290E61274D8F090E614E4F090E6D204F08D828C838EF01213D390E621F00D82
+:2003E300BD00010C8D828C838EF01213D3FF90E62074075FF08D828C838EF01213D3C423C2
+:20040300541F90E64004F002024BAF827E00EE75F005A4FCADF024F8F582ED3416F583E403
+:2004230093FBB5070280080EBE16E375820022EC24F8FCED3416FD8C828D83A3A3A3A3E441
+:200443009390E601F08C828D83A3E493FDA3E493FEA3E493FF75AF07759DE4759E007C2069
+:200463008C031CEB60168D828E838FF01213D3FBA3AD82AE8390E67CEBF080E47F608F0633
+:200483001FEE600790E67CE4F080F375820122AF82BF00028064BF0103020529BF02030203
+:2004A3000537BF0503020545BF0A03020553BF1403020561BF320302056FBF640302057D72
+:2004C300BF69028017BF6A028021BF6E02802BBF78028035BF9602803F02058B750C19750D
+:2004E3000D0075CAC075CB6302058F750C1E750D0075CACB75CB7D02058F750C32750D0001
+:2005030075CAE075CBB102058F750C64750D0075CAF075CBD802058F750CFA750D0075CAB2
+:200523006075CBF08066750CF4750D0175CA3075CBF88058750CE8750D0375CA1875CBFC4A
+:20054300804A750CC4750D0975CA7075CBFE803C750C88750D1375CA3875CBFF802E750CD2
+:2005630010750D2775CA9C75CBFF8020750CA8750D6175CAD875CBFF8012750C50750DC3FB
+:2005830075CAEC75CBFF80047582002275820122AD4CAE4DAF4E8D828E838FF0E508121395
+:2005A3002175820122E582700685108212036475820122758200227582012290E6BBE0FE34
+:2005C3007F0090E6BAE07C004207EC420690E6BFE0FC7D0090E6BEE07A004205EA4204906D
+:2005E300E6A0E020E1F990E6B8E0FBBB40028073BBC00280030206BFED4C70030206C3C39E
+:2006030074409DE49C50067A407B0080048D028C0390E6A0E020E1F98A4575460075474063
+:200623007548E77549008F438E44758251C007C006C005C004C002120E58D002D004D0059E
+:20064300D006D00790E68AE4F00000000090E68BEAF07B00EDC39AFDEC9BFCEA2FFFEB3EB5
+:20066300FE8095ED4C605990E68BE4F090E6A0E020E1F990E68BE0FB8B38753900753A4071
+:20068300753BE7753C008F368E37758251C007C006C005C004C003120DC3E582D003D00474
+:2006A300D005D006D0077003F582227A00EB2FFFEA3EFEEDC39BFDEC9AFC80A775820022E6
+:2006C3007582012275820022AF82C007120308D007C2A0D2A1850C0E850D0FBFE0004015EF
+:2006E300EF2419401090E68AE4F090E68BF090E6A0E020E1F9BFA2028023BFE0028021BFBF
+:20070300E1028028BFE202802FBFE3028033BFE4028046BFE502804ABFE65D80520205BE2E
+:2007230090E740E0F54C7582000200E390E740E0F54C7582010200E390E740E0F582020439
+:200743000D90E740E0FFBF010CD2A0C2A1E4F50EF50F1203257582012290E740E0F5820203
+:20076300028590E740E0F5821202277582012290E740E0F5820204927582002290E613E460
+:20078300F090E615F090E6C2F090E6C37480F090E6C0E4F090E6F4F0120308754C0175826C
+:2007A300001200E3754C017582011200E375820112040D75820212028575820002036490F5
+:2007C300E600E054E74410F01208DE12077FD2E890E668E0FF43070890E668EFF090E65CE9
+:2007E300E0FF43070190E65CEFF0E0FF43071090E65CEFF0E0FF43072090E65CEFF0E0FF58
+:2008030043070890E65CEFF0D2DDD2AF75CA3075CBF875C800D2ADD2CA90E680E043E00AA0
+:20082300F09005DC12137C90E680E053E0F7F090E672E4F090E671F090E670F075B109F536
+:20084300A0F58075B6FF75B4FF75B2FFC2A0D2A11000028003120EBC10010280F390E68244
+:20086300E043E0C0F090E6817401F0AE877F004306018E8700000000000000E513701C903F
+:20088300E682E030E60790E682E020E0D090E682E030E70790E682E020E1C290E682E030AF
+:2008A300E60790E682E020E00E90E682E030E7A090E682E030E19990000512137C90E68025
+:2008C300E0FF43070190E680EFF090000F12137C90E680E053E0FEF00208537E107F3E75C2
+:2008E3004C30754D31754E32754F337550347551357552367553377554387555397556419A
+:20090300755742755843755944755A45755B4674182EFCE43FFD90E507E0FB5303F0E4C45F
+:20092300CBC4540F6BCB540FCB6BCB30E30244F0EB244CF987038C828D83EBF074162EFC54
+:20094300E43FFD90E507E0FB53030FEB244CF987038C828D83EBF074142EFCE43FFD90E59A
+:2009630008E0FB5303F0E4C4CBC4540F6BCB540FCB6BCB30E30244F0EB244CF987038C82E2
+:200983008D83EBF074122EFCE43FFD90E508E0FB53030FEB244CF987038C828D83EBF07491
+:2009A300102EFCE43FFD90E509E0FB5303F0E4C4CBC4540F6BCB540FCB6BCB30E30244F0BE
+:2009C300EB244CF987038C828D83EBF0740E2EFCE43FFD90E509E0FB53030FEB244CF987D8
+:2009E300038C828D83EBF0740C2EFCE43FFD90E50AE0FB5303F0E4C4CBC4540F6BCB540F5B
+:200A0300CB6BCB30E30244F0EB244CF987038C828D83EBF0740A2EFCE43FFD90E50AE0FB90
+:200A230053030FEB244CF987038C828D83EBF074082EFCE43FFD90E50BE0FB5303F0E4C468
+:200A4300CBC4540F6BCB540FCB6BCB30E30244F0EB244CF987038C828D83EBF074062EFC43
+:200A6300E43FFD90E50BE0FB53030FEB244CF987038C828D83EBF074042EFCE43FFD90E585
+:200A83000CE0FB5303F0E4C4CBC4540F6BCB540FCB6BCB30E30244F0EB244CF987038C82BD
+:200AA3008D83EBF074022EFEE43FFF90E50CE0FD53050FED244CF987058E828F83EDF022BC
+:201438000F0E0000000000000200010000000000505555000000000000000000000000007A
+:20145800010100000000000002000100000000005055550000000000000000000000000075
+:20147800FAFAFAFAFAF9000002000000000001005055555555555500000000000000000028
+:20149800FAFAF90000000000020000010000000050555555000000000000000000000000F5
+:2014B800C8C8C700000000000200000100000000505555550000000000000000000000006B
+:2014D800FAFAF90000000000020000010000000050555555000000000000000000000000B5
+:2014F8009695000000000000020001000000000050555500000000000000000000000000AC
+:201518000201000000000000020001000000000050555500000000000000000000000000B3
+:201538004B4A00000000000002000100000000005055550000000000000000000000000001
+:2015580025250000000000000200010000000000505555000000000000000000000000002C
+:201578000100000000000000020100000000000050550000000000000000000000000000AA
+:201598001E1D000000000000020001000000000050555500000000000000000000000000FB
+:2015B800010100000000000002000100000000005055550000000000000000000000000014
+:2015D8000707000000000000020001000000000050555500000000000000000000000000E8
+:2015F80001000000000000000201000000000000505500000000000000000000000000002A
+:201618000504000000000000020001000000000050555500000000000000000000000000AC
+:2016380080000000000000000300000000000000000000000000000000000000000000000F
+:2016580006050000000000000200010000000000505555000000000000000000000000006A
+:201678008000000000000000030000000000000000000000000000000000000000000000CF
+:20169800030200000000000002000100000000005055550000000000000000000000000030
+:2016B800020200000000000002000100000000005055550000000000000000000000000011
+:2016D8000302000000000000020001000000000050555500000000000000000000000000F0
+:2016F80030781680EA1E381680AA18F81580CA10B81580CA0F7815808A0C181580CA0A58F3
+:2017180014808A08D81680CA06B816808A059816808A04581680CA031816808A02D8158052
+:201738008A013814808A969815808A8C5815808A783815808A6EF814808A6AD81480CA6904
+:0E175800B814808A689814808A667814808A93
+:203D000012010002FFFFFF40B50422600702010203010A060002000000400100090289001F
+:203D200001010080FA0904000001FF000000070586020002000904000101FF000100070549
+:203D400082010014010904000201FF00010007058201000C010904000301FF000100070502
+:203D600082010004010904000401FF000100070582010004020904000501FF0001000705F5
+:203D800082010004030904000601FF000100070582010004040904000701FF0001000705CD
+:053DA000820100020495
+:203DA6000902390002010080FA0904000001FF000000070586024000000904000101FF004D
+:193DC600010007058201FF03010904000201FF00010007058201000201AF
+:203DE0000403090416034F00700065006E00480061006E00740065006B00160344005300F9
+:203E00004F002D003600300032003200420045001A03300030003000300030003000300068
+:0C3E2000300030003000300030000000A6
+:200AC30085822CE5272522FDE5283523FE752D02903C00E4F0903C00E06004758200229030
+:200AE300E678E0FB7A0043038090E678EBF0E030E21090000AC006C00512137CD005D0063E
+:200B030080D3E52C25E0FB90E679F090E678E020E006903C00E060F3903C00E060047582B5
+:200B2300002290E678E020E2AC90E678E020E14090E678E0FB43034090E678EBF090E678FF
+:200B4300E030E606903C00E060F3903C00E0600475820022E52D14FB8B2D7003F5822290F9
+:200B6300000AC006C00512137CD005D006020AD87A007B00C3EA9DEB9E4003020C0DC3EADA
+:200B83009522EB95235016EA2524F8EB3525F9AC26888289838CF01213D3FC801DEAC395F2
+:200BA30022F8EB9523F9E82529F8E9352AF9AF2B888289838FF01213D3FC90E679ECF00AD5
+:200BC300BA00010B90E678E020E006903C00E060F3903C00E060047582002290E678E03052
+:200BE300E203020AD890E678E020E18890E678E0FF43074090E678EFF090E678E030E606C4
+:200C0300903C00E060F37582002290E678E0FF43074090E678EFF090E678E030E606903CDF
+:200C230000E060F3903C00E060047582002275820122858233903C00E4F004B52E0814B5A9
+:200C43002F0474018001E4FE903C00E06004758200227C007D0090E678E0FB43038090E65F
+:200C630078EBF0E030E20C90000AC00612137CD00680D5E53325E0FB3395E0FA4303019063
+:200C8300E679EBF090E678E020E006903C00E060F3903C00E060047582002290E678E0202D
+:200CA300E2A690E678E020E11E90E678E0FB43034090E678EBF090E678E030E606903C00EE
+:200CC300E060F375820022EE600F90E678E0FB7A0043032090E678EBF090E679E0E4F5341A
+:200CE300F53574012534F8E43535F9C3E8952EE9952F506C90E678E020E006903C00E06003
+:200D0300F3903C00E060047582002290E678E030E203020C4B74022534F8E43535F9E8B5CD
+:200D23002E13E9B52F0F90E678E0F8790043002090E678E8F0A834A9350534E4B534020564
+:200D430035AC34AD35E82530F8E93531F9AF3290E679E0FB888289838FF0121321020CE5A3
+:200D630090E678E020E006903C00E060F3903C00E060047582002290E678E030E203020C83
+:200D83004B90E678E0FF43074090E678EFF0EC2530FCED3531FDAF3290E679E08C828D8386
+:200DA3008FF012132190E678E030E606903C00E060F3903C00E0600475820022758201223F
+:200DC30085823DE4F541F542AB36AC37C3E5419538E54295394003020E547A0090E678E01D
+:200DE30030E4067A018C078F3EEA04FFEA243EF98B02A702EF04FAEF243EF9AE41AF420577
+:200E030041E4B541020542EE253AFEEF353BFFAD3C8E828F838DF01213D3F78A2275230007
+:200E230075243E752500752640E4F527F528F529F52AF52B853D82C004C003120AC3E582D8
+:200E4300D003D0047003F582220BBB00010C020DCF75820122AF827E0090E678E030E4067A
+:200E63007E01AD448D4AEE04FDEE244AF9AE43A7068D2275230075244A752500752640E4C3
+:200E8300F527F528F529F52AF52B8F82C007120AC3E582D0077003F5822285452E85462FC6
+:190EA3008547308548318549328F82120C35E5827003F58222758201224B
+:06008800E478FFF6D8FD4C
+:1200CE007512007513007514A675153D75161C75173DAB
+:200EBC0090E6B9E0FF24F45003020FEAEF240A83F582EF241083F583E473EE0AEA26EAEA3A
+:200EDC0042EA52698BC50E0F0F0F0F0F0F0F0F0F0F0F12106CE582600302100690E6A0E0A6
+:200EFC00FF7E0043070190E6A0EFF0021006121100E582600302100690E6A0E0FF7E004346
+:200F1C00070190E6A0EFF002100612117BE582600302100690E6A0E0FF7E0043070190E6EC
+:200F3C00A0EFF00210061206C7E582600302100612123C0210061205B6AF8290E740EFF031
+:200F5C0090E68AE4F090E68B04F002100690E6BAE0F5821205BAE582600302100690E6A044
+:200F7C00E0FF7E0043070190E6A0EFF002100690E6BCE0FF754C11754D00754E408F8212D5
+:200F9C000593E582701190E6A0E0FF7E0043070190E6A0EFF0805390E740E511F090E68A92
+:200FBC00E4F090E68B04F0804190E6BCE0FF90E6BAE0F5108F821205A8E582702D90E6A07B
+:200FDC00E0FF7E0043070190E6A0EFF0801C90E6B9E0F5821206CBE582700F90E6A0E0FF78
+:200FFC007E0043070190E6A0EFF090E6A0E0FF43078090E6A0EFF022AF82747F5FFE24F7A5
+:20101C005003021068EE240A83F582EE240D83F583E473414558685C6860686410101010EA
+:20103C00101010101090E6A022EF30E7067EA27FE680047EA17FE68E828F832290E6A322F4
+:20105C0090E6A42290E6A52290E6A6229000002290E6B8E0FFBF80028022BF81028008BF92
+:20107C00820280370210F890E740E4F090E741F090E68AF090E68B7402F08064E51325E0A4
+:20109C00FFE512420790E740EFF090E741E4F090E68AF090E68B7402F0804590E6BCE0F5B0
+:2010BC0082121014AE82AF838E048F05EE4F7003F582228C828D83E0FC30E0067E017F007D
+:2010DC0080047E007F0090E740EEF090E741E4F090E68AF090E68B7402F08004758200225E
+:2010FC007582012290E6B8E0FF6005BF0264801B90E6BAE0FFBF0105751300805E90E6BA1E
+:20111C00E0FFBF060280547582002290E6BAE0703D90E6BCE0F582121014AE82AF83E0FD65
+:20113C005305FE8E828F83EDF090E6BCE0FF30E7098F057E004305108D0753071F90E6839D
+:20115C00EFF07E0043072090E683EFF0800D7582002290E6B9E0F5820206CB75820122902B
+:20117C00E6B8E0FF6008BF0202802902120490E6BAE0FFBF020302120D90E6BAE0FFBF0127
+:20119C0005751301806B90E6BAE0FFBF060280617582002290E6BAE0704A90E6BCE0F58297
+:2011BC00121014AE82AF83EE4F7003F582228E828F83E0FD7C004305018E828F83EDF090DF
+:2011DC00E6BCE0FF30E7098F057E004305108D0753071F90E683EFF07E0043072090E68322
+:2011FC00EFF0800D7582002290E6B9E0F5820206CB75820122AF827E0110AF027E00EF609D
+:20121C000E75141C75153D7516A675173D800C7514A675153D75161C75173DEE1392AF22E8
+:20123C0090E6BBE0FFBF01028019BF02028024BF0302802CBF06030212F6BF07030213069A
+:20125C000213137E007F3D90E6B3EFF090E6B47400F02290E6B3E515F090E6B4E514F02210
+:20127C007DE07E3D7F8090E6BAE0F54C7B008B020BEAB54C0280428D008E018F028D828EDE
+:20129C00838FF01213D328F8E439F9880589068A0774012DF9E43EFA8F0489828A838CF077
+:2012BC001213D3F9B9030280067D007E007F00ED4E6006C3E54C9B50B5ED4E600F8D038E66
+:2012DC000490E6B3ECF090E6B4EDF02290E6A0E0FF43070190E6A0EFF0227E127F3D90E6A7
+:2012FC00B3EFF090E6B47412F02290E6B3E517F090E6B4E516F02290E6A0E0FF4307019062
+:05131C00E6A0EFF02245
+:200066007900E94400601B7A00901766780175923CE493F2A308B800020592D9F4DAF275A3
+:0200860092FFE7
+:1B13210020F71130F6138883A88220F509F6A8837583002280FEF280F5F022CB
+:203F0000020135000214360002142B000201E30002014D0002019800021428000213700048
+:203F200002137200021373000213740002137700021435000214370002133C0002133E0021
+:203F400002142D00021370000213EF000214290002142A0002142C0002142E0002142F004B
+:203F60000213D20002137000021370000213700002137100021375000213780002137A009F
+:203F8000021376000213790002137B000213D10002133F0002136A0002136C0002136E00BB
+:183FA0000213400002136B0002136D0002136F0002133D000214340092
+:01133C00327E
+:01133D00327D
+:01133E00327C
+:01133F00327B
+:01134000327A
+:20008E007800E84400600A790075923CE4F309D8FC7801E84400600C7901903C00E4F0A306
+:0400AE00D8FCD9FAA7
+:201341007A10E4FBFCE58225E0F582E58333F583EB33FBEC33FCEB954CF5F0EC954D400638
+:09136100FCABF0438201DADD224D
+:01136A003250
+:01136B00324F
+:01136C00324E
+:01136D00324D
+:01136E00324C
+:01136F00324B
+:01137000324A
+:011371003249
+:011372003248
+:011373003247
+:011374003246
+:011375003245
+:011376003244
+:011377003243
+:011378003242
+:011379003241
+:01137A003240
+:01137B00323F
+:20137C00AE82AF8390E600E05418C423541F70057CB1FD801C90E600E05418C423541FFB81
+:20139C00BB01067A617B0180047AC27B028A048B058C4C8D4D154C74FFB54C02154DE54CA1
+:1513BC00454D70F1EE24FFFAEF34FFFB8A068B07EA4B70DD223B
+:0113D10032E9
+:0113D20032E8
+:0D00590075815B121430E5826003020056D1
+:1C13D30020F71430F6148883A88220F507E6A88375830022E280F7E49322E02229
+:0113EF0032CB
+:2013F000C2D5E58330E70DD2D5E4C39582F582E49583F583E54D30E70DB2D5E4C3954CF510
+:181410004CE4954DF54D12134130D50BE4C39582F582E49583F583222F
+:011428003291
+:011429003290
+:01142A00328F
+:01142B00328E
+:01142C00328D
+:01142D00328C
+:01142E00328B
+:01142F00328A
+:04143000758200229F
+:011434003285
+:011435003284
+:011436003283
+:011437003282
+:00000001FF
diff --git a/openhantek/res/firmware/dso6022be-loader.hex b/openhantek/res/firmware/dso6022be-loader.hex
deleted file mode 100644
index d7758b6f..00000000
--- a/openhantek/res/firmware/dso6022be-loader.hex
+++ /dev/null
@@ -1,60 +0,0 @@
-:1003680090E668E0FF74FFF0E0B40B04EFF0D322EE
-:0603780090E668EFF0C3FF
-:01037E00225C
-:1001B500907FE9E064A360030202C5A3E07508002F
-:1001C500F509A3E0FEE4EE4208907FEEE0750A0033
-:1001D500F50BA3E0FEE4EE420A907FE8E064407090
-:1001E50064E50B450A70030202D6E4907FC5F090E2
-:1001F5007FB4E020E3F9907FC5E0750C00F50DE4D0
-:10020500FCFDC3ED950DEC950C501F74C02DF582CA
-:10021500E4347EF583E0FFE5092DF582E5083CF53C
-:1002250083EFF00DBD00010C80D8E50D2509F5091A
-:10023500E50C3508F508C3E50B950DF50BE50A95B5
-:100245000CF50A809C907FE8E064C060030202D64A
-:10025500E50B450A607BC3E50B9440E50A94005025
-:1002650008850A0C850B0D8006750C00750D40E49C
-:10027500FCFDC3ED950DEC950C501FE5092DF582A0
-:10028500E5083CF583E0FF74002DF582E4347FF545
-:1002950083EFF00DBD00010C80D8907FB5E50DF022
-:1002A5002509F509E50C3508F508C3E50B950DF5A8
-:1002B5000BE50A950CF50A907FB4E030E29280F7E1
-:1002C500907FE9E0B4AC0AE4907F00F0907FB5043C
-:0802D500F0907FB4E04402F058
-:0102DD0022FE
-:1000800090E6B9E064A36003020198A3E07508005C
-:10009000F509A3E0FEE4EE420890E6BEE0750A0032
-:1000A000F50BA3E0FEE4EE420A90E6B8E06440708F
-:1000B00066E50B450A70030201ADE490E68AF0A301
-:1000C000F090E6A0E020E1F990E68BE0750C00F5F9
-:1000D0000DE4FCFDC3ED950DEC950C501F74402D07
-:1000E000F582E434E7F583E0FFE5092DF582E508C4
-:1000F0003CF583EFF00DBD00010C80D8E50D25091E
-:10010000F509E50C3508F508C3E50B950DF50BE58C
-:100110000A950CF50A809A90E6B8E064C060030284
-:1001200001ADE50B450A70030201ADC3E50B944038
-:10013000E50A94005008850A0C850B0D8006750CA5
-:1001400000750D40E4FCFDC3ED950DEC950C501FC2
-:10015000E5092DF582E5083CF583E0FF74402DF5B7
-:1001600082E434E7F583EFF00DBD00010C80D8E4A4
-:1001700090E68AF0A3E50DF02509F509E50C3508B0
-:10018000F508C3E50B950DF50BE50A950CF50A90FE
-:10019000E6A0E030E18C80F790E6B9E0B4AC0E90D8
-:1001A000E7407401F0E490E68AF0A304F090E6A042
-:0401B000E04480F0B7
-:0101B4002228
-:1002DE00C2011203689200907F95E044C0F0D2E80C
-:1002EE0030000890E65D74FFF08006907FAB74FFDF
-:1002FE00F030000890E6687408F08007907FAFE059
-:10030E004401F030000890E65C7401F08006907FA6
-:10031E00AE7401F0D2AF3001FD30000512008080C6
-:08032E00031201B5C20180EECB
-:03000300020336BF
-:10033600C0E0C083C082C085C084C086758600D2F6
-:10034600015391EF30000890E65D7401F08006904D
-:100356007FAB7401F0D086D084D085D082D083D094
-:02036600E03283
-:03004300020400B4
-:0404000002033600BD
-:0300000002037F79
-:0C037F00787FE4F6D8FD7581200202DED4
-:00000001FF
diff --git a/openhantek/res/firmware/dso6022bl-firmware.hex b/openhantek/res/firmware/dso6022bl-firmware.hex
index e2a72a63..ff6cafe4 100644
--- a/openhantek/res/firmware/dso6022bl-firmware.hex
+++ b/openhantek/res/firmware/dso6022bl-firmware.hex
@@ -1,513 +1,261 @@
-:20000000020e5490e682e044c0f090e681f04387010000000000227400f58690fda57c053a
-:20002000a3e582458370f922d3223202126c53d8ef323202002e00010202030304040505f1
-:20004000d32232020d00d322d32232020b6ed322d32232020d0090e678e05410ffc4540f50
-:200060004450f51913e433f51cd20290e6b9e0245e605324f0603324d2b4090040030205e7
-:200080003a90008f75f003a4c58325f0c5837302024e02029c0202e502048602053a020534
-:2000a0003a02053a0204ca0204a9a205e43390e740f0e490e68af090e68b04f090e6a0e022
-:2000c0004480f002053c90e6bae0752d00f52ea3e0fee4ee422d90e6bee0752f00f530a312
-:2000e000e0fee4ee422f90e6b8e064c060030201b6e530452f700302053c90e6a0e020e15b
-:20010000f9c3e5309440e52f94005008852f31853032800675310075324090e6b9e0b4a3f5
-:2001200035e4f533f534c3e5349532e53395315060e52e2534f582e52d3533f583e0ff74fc
-:20014000402534f582e434e7f583eff00534e5347002053380d0e4f533f534c3e534953215
-:20016000e5339531501874402534f582e434e7f58374cdf00534e5347002053380ddad32d5
-:200180007ae779407ee77f40ab07af2eae2d121093e490e68af090e68be532f0252ef52eb0
-:2001a000e531352df52dc3e5309532f530e52f9531f52f0200f190e6b8e0644060030205d4
-:2001c0003ce530452f700302053ce490e68af090e68bf090e6a0e020e1f990e68be0753168
-:2001e00000f53290e6b9e0b4a335e4f533f534c3e5349532e5339531503874402534f5827b
-:20020000e434e7f583e0ffe52e2534f582e52d3533f583eff00534e5347002053380d0addb
-:20022000327ae779407ee77f40ab07af2eae2d121203e532252ef52ee531352df52dc3e5ee
-:20024000309532f530e52f9531f52f0201c1e490e68af090e68bf090e6a0e020e1f990e794
-:2002600040e0f53514602914601d24fd601024fb600302053cc283d282d28102053cc2833c
-:20028000c282c28102053cc283c282d28102053cc283d282c28102053c02053ce490e68a2f
-:2002a000f090e68bf090e6a0e020e1f990e740e0f53524fe601a24fd600d24fb701bc28690
-:2002c000d285d28402053cc286c285c28402053cc286c285d28402053cc286d285c2840207
-:2002e000053c02053ce490e68af090e68bf090e6a0e020e1f990e740e0f535120cd6037f8e
-:2003000001036b0403570803b90a03441003a614033818032c1e032030039332000003caa6
-:2003200090e60174eaf0751a010203ca90e60174aaf0751a010203ca90e60174caf0751a81
-:20034000020203ca90e60174caf090e0407401f0a3f0e4f51a807390e60174caf090e04044
-:200360007402f0a304f0e4f51a805f90e60174caf090e0407405f0a304f0e4f51a804b900b
-:20038000e60174caf090e0407417f0a304f0e4f51a803790e60174caf090e0407430f0a350
-:2003a000f0e4f51a802490e60174caf090e0407478f0a3f0e4f51a801190e60174caf09039
-:2003c000e04074f0f0a3f0e4f51a90e6f574fff090e080e090e6f3f090e081e090e6c3f032
-:2003e00090e082e090e6c1f090e083e090e6c2f090e085e090e6c0f090e086e090e6f4f0de
-:2004000075af07e51a6401704390e6f574fff090e107e090e6f3f090e108e090e6c3f09009
-:20042000e109e090e6c1f090e10ae090e6c2f090e10ce090e6c0f090e10de090e6f4f07598
-:20044000af0774e0f59a7487f59b8017e51ab4020a74e1f59a740ef59b800874e0f59a744d
-:2004600000f59b759de4e4f59ef533f53490e67be090e67cf00534e5347002053364804556
-:200480003370ea02053ce490e68af090e68bf090e6a0e020e1f990e740e0f535640160034e
-:2004a00002053c751d0102053ce490e68af090e68bf090e6a0e020e1f990e740e0f535b4f9
-:2004c0000104d2878076c287807290e6bae0752d00f52ea3e0fee4ee422d90e6bee0752f3e
-:2004e00000f530a3e0fee4ee422fe530452f604c90e6a0e020e1f9c3e5309440e52f94009a
-:200500005008852f31853032800675310075324090e7407401f0e490e68af090e68be5329c
-:20052000f0252ef52ee531352df52dc3e5309532f530e52f9531f52f80b0d322c32290e679
-:20054000b9e0700302061a1470030206c324fe700302075b24fb70030206141470030206e5
-:200560000e147003020602147003020608240560030207cc12004640030207d890e6bbe057
-:2005800024fe602c14604724fd601614603124067066e50c90e6b3f0e50d90e6b4f0020797
-:2005a000d8e51490e6b3f0e51590e6b4f00207d8e50e90e6b3f0e50f90e6b4f00207d8e57c
-:2005c0001090e6b3f0e51190e6b4f00207d890e6bae0ff12132baa06a9077b01ea494b60e8
-:2005e0000dee90e6b3f0ef90e6b4f00207d890e6a0e04401f00207d890e6a0e04401f002c4
-:2006000007d81213e10207d81213f30207d81211220207d81213cf0207d812004840030281
-:2006200007d890e6b8e0247f602b14603c240260030206b9a200e433ff25e0ffa203e4332d
-:200640004f90e740f0e4a3f090e68af090e68b7402f00207d8e490e740f0a3f090e68af0e7
-:2006600090e68b7402f00207d890e6bce0547eff7e00e0d3948040067c007d0180047c00ca
-:200680007d00ec4efeed4f2436f58274003ef583e493ff3395e0feef24a1ffee34e68f8286
-:2006a000f583e0540190e740f0e4a3f090e68af090e68b7402f00207d890e6a0e04401f00c
-:2006c0000207d812004e40030207d890e6b8e024fe601d240260030207d890e6bae0b401d9
-:2006e00005c2000207d890e6a0e04401f00207d890e6bae0705990e6bce0547eff7e00e02c
-:20070000d3948040067c007d0180047c007d00ec4efeed4f2436f58274003ef583e493ff50
-:200720003395e0feef24a1ffee34e68f82f583e054fef090e6bce05480ff131313541fff1d
-:20074000e0540f2f90e683f0e04420f00207d890e6a0e04401f00207d8807d1200505078f6
-:2007600090e6b8e024fe60232402706c90e6bae0b40104d200806190e6bae0b402048058a6
-:20078000805690e6a0e04401f0804d90e6bce0547eff7e00e0d3948040067c007d0180049f
-:2007a0007c007d00ec4efeed4f2436f58274003ef583e493ff3395e0feef24a1ffee34e6fa
-:2007c0008f82f583e04401f0800e800c120056500790e6a0e04401f090e6a0e04480f022ab
-:2007e000c204c200c203c201c202750808750907120db8c2c975cdf875cc40d2cad2adc221
-:20080000a2c2a0d2a17e0f7f008e0c8f0d75140f751512750a0f750b1c75120f75133c75f2
-:20082000160f75175c90e680e030e70e850a0e850b0f851210851311800c85120e85130f4c
-:20084000850a10850b11ee54e07003020964752900752a807e0f7f008e2b8f2cc3748a9fb7
-:20086000ff740f9ecf2402cf3400fee48f288e27f526f525f524f523f522f521af28ae27d3
-:20088000ad26ac25ab24aa23a922a821c3120cc5502ae52a2524f582e5293523f58374cd76
-:2008a000f0e4faf9f8e5242401f524ea3523f523e93522f522e83521f52180c0e4f524f5fb
-:2008c00023f522f521af28ae27ad26ac25ab24aa23a922a821c3120cc55037e52c2524f5cc
-:2008e00082e52b3523f583e0ffe52a2524f582e5293523f583eff0e4faf9f8e5242401f539
-:2009000024ea3523f523e93522f522e83521f52180b385290c852a0d74002480ff740f3437
-:20092000fffec3e5159ff515e5149ef514c3e50f9ff50fe50e9ef50ec3e5119ff511e51073
-:200940009ef510c3e50b9ff50be50a9ef50ac3e5139ff513e5129ef512c3e5179ff517e5c9
-:20096000169ef516d2e843d82090e668e04409f090e65ce0443df0d2af90e680e020e10548
-:20098000d2061212d090e680e054f7f0538ef8c20430010512053ec20130042912002850a6
-:2009a00024c20412000320001690e682e030e704e020e1ef90e682e030e604e020e0e41277
-:2009c00012ff120040120f8c80c722c1056080e0000e0301110101300701000201000011a7
-:2009e00000fffefffefffeffff00091212002d123f08030101010101070102040100000038
-:200a000000fffcfffefffeffff09091212002d363f171801010101010700020100000010bd
-:200a200000fffefffefefefefe00091212002d123f0803013f0101010701020001000000c0
-:200a400000fffdffffffffffff09091212002d363f6080e087010201013f01010700000232
-:200a600000010000000702020707070707000000003f00003f03013f010101010702020572
-:200a80000000000000050707070707070700003f000000003f010180010101bf0702020350
-:200aa0000202021100ffffffffffffffff00091212002d123f01010101010101070000006e
-:200ac00000000000000707070707070707000000000000003f6080e10e010201013f01018a
-:200ae0000700000200010000000702020707070707000000003f00003f03013f01010101f9
-:200b0000070202050000000000050707070707070700003f000000003f3f010101010101cc
-:200b2000070300000000001000feffffffffffffff09091212002d123f01010101010101e9
-:200b40000700000000000000000707070707070707000000000000003f47e080c000000fa1
-:200b6000ca1e0047e107c009000fca1e0000c0e0c083c082c085c084c086758600c0d075aa
-:200b8000d000c000c001c002c003c006c00790e678e030e206754106020c5890e678e020fc
-:200ba000e10ce54164026006754107020c58e54124fe605f14603624fe7003020c4924fc76
-:200bc0007003020c5524086003020c58ab3daa3ea93faf4005408f82758300120c7690e64b
-:200be00079f0e540653c7070754105806b90e679e0ab3daa3ea93fae408e82758300120ca5
-:200c0000a3754102e53c6401704e90e678e04420f08045e53c24feb5400790e678e04420dd
-:200c2000f0e53c14b5400a90e678e04440f075410090e679e0ab3daa3ea93fae408e82759e
-:200c40008300120ca30540800f90e678e04440f075410080037541005391dfd007d006d00b
-:200c600003d002d001d000d0d0d086d084d085d082d083d0e032bb010ce58229f582e583a1
-:200c80003af583e0225006e92582f8e622bbfe06e92582f8e222e58229f582e5833af5834e
-:200ca000e49322f8bb010de58229f582e5833af583e8f0225006e92582c8f622bbfe05e952
-:200cc0002582c8f222eb9ff5f0ea9e42f0e99d42f0e89c45f022d083d082f8e493701274cb
-:200ce0000193700da3a393f8740193f5828883e4737402936860efa3a3a380df3232323261
-:200d0000021373000213b9000213a30002138b0002115f000211960002002a0002003200aa
-:200d20000200420002004a0002005200020cfc00020cfd00020cfe00020cff00020efc0095
-:200d4000020efd0002003200020efe00020eff0002140300021404000214050002140600cb
-:200d600002140700020032000200320002003200021408000214090002140a0002140b003c
-:200d800002140c0002140d0002140e0002140f000214100002141100021412000214130027
-:200da00002141400021415000214160002141700021418000214190090e6007410f0120f1d
-:200dc000ee00000090e61274a0f0000000e490e613f000000090e61474e0f0000000e490fa
-:200de000e615f000000090e6047480f00000007402f00000007406f0000000e4f000000006
-:200e000090e61804f00000007411f000000090e61a7409f000000090e6d27402f000000030
-:200e200090e6e214f0000000e490e671f075b40790e670f075b2ffc283c282c281c286c299
-:200e400085c284f51df51a1213fb90e67ae04401f0d28722787fe4f6d8fd758141020e9b7e
-:200e60000207e0e493a3f8e493a34003f68001f208dff48029e493a3f85407240cc8c333d2
-:200e8000c4540f4420c8834004f456800146f6dfe4800b01020408102040809009cbe47e1e
-:200ea000019360bca3ff543f30e509541ffee493a360010ecf54c025e060a840b8e493a333
-:200ec000fae493a3f8e493a3c8c582c8cac583caf0a3c8c582c8cac583cadfe9dee780be28
-:200ee000121238e54124fa600e146006240770f3d322e4f541d322e4f541d3223232323201
-:200f00001201000200000040b5042a600000010200010a06000200000040010009022000b7
-:200f200001010080320904000002ff0000000705020200020007058602000200090220001c
-:200f400001010080320904000004ff00000007050202400000070586024000000403090495
-:200f60000e034f0044004d002000200020001c03480061006e00740065006b003600300040
-:200f80003200320042004c0020000000e51d64017031751d0290e6f574fff090e604748067
-:200fa000f00000007402f00000007406f0000000e4f0000000fffe000fbf00010ebe03f70b
-:200fc000bfe8f4e5bb30e72590e6f4e030e01ee5ac20e019e5bb30e7fb90e6d07428f000f4
-:200fe0000000e490e6d1f000000075bb062290e60174caf090e6f574fff090e080e090e6c5
-:20100000f3f090e081e090e6c3f090e082e090e6c1f090e083e090e6c2f090e085e090e6b4
-:20102000c0f090e086e090e6f4f075af0774e0f59a7400f59b759de4e4f59eff90e67be081
-:2010400090e67cf00fbf80f422ab07aa06ac05e4fde51c6010ea7e000dee248ef582e43441
-:20106000e1f583eaf0ebae050d748e2ef582e434e1f583ebf0af050d748e2ff582e434e13d
-:20108000f583ecf07ae17b8eaf19121357af191211cd228e368f378d388a398b3ae4fde5dd
-:2010a0001c6012e536ff7e000dee248ef582e434e1f583eff0e537ae050d748e2ef582e42f
-:2010c00034e1f583e537f07ae17b8eaf19121357ab3aaa39ad38af19120ee0228e2d8f2ec0
-:2010e00090e600e054187012e52e2401ffe4352dc313f52def13f52e801590e600e05418bb
-:20110000ffbf100be52e25e0f52ee52d33f52de52e152eae2d7002152d4e60051200178013
-:20112000ee2290e680e030e71800000090e6247402f0000000e490e625f0000000d20580d4
-:2011400016000000e490e624f000000090e6257440f0000000c20590e6bae0f51bd322c030
-:20116000e0c083c08290e680e030e70e850a0e850b0f851210851311800c85120e85130fab
-:20118000850a10850b115391ef90e65d7410f0d082d083d0e032c0e0c083c08290e680e073
-:2011a00030e70e850a0e850b0f851210851311800c85120e85130f850a10850b115391ef93
-:2011c00090e65d7420f0d082d083d0e03290e678e020e6f9c2e990e678e04480f0ef25e043
-:2011e00090e679f090e678e030e0f990e678e04440f090e678e020e6f990e678e030e1d675
-:20120000d2e9228e368f378d388a398b3ae4f53be53bc3953850200537e537ae3670020533
-:201220003614ffe53a253bf582e43539f583e0fd121049053b80d922a90790e678e020e61e
-:20124000f9e541702590e678e04480f0e925e0440190e679f08d3caf03a907753d018a3ea0
-:20126000893fe4f540754103d322c322c0e0b2a2e509150970021508e5094508701575082e
-:201280000475091f300206b2a1d2a08004b2a0d2a1c20275cdf875cc40c2cfd0e032a907c5
-:2012a00090e678e020e6f9e541702390e678e04480f0e925e090e679f08d3caf03a90775b9
-:2012c0003d018a3e893fe4f540754101d322c32230060990e680e0440af0800790e680e0e6
-:2012e0004408f07fdc7e051210dc90e65d74fff090e65ff05391ef90e680e054f7f0229045
-:20130000e682e030e004e020e60b90e682e030e119e030e71590e680e04401f07f147e0056
-:201320001210dc90e680e054fef022a907ae16af178f828e83a3e064037017ad0119ed7084
-:2013400001228f828e83e07c002ffdec3efeaf0580df7e007f002212129ee54124fa600ef2
-:20136000146006240770f3d322e4f541d322e4f541d322c0e0c083c082d2015391ef90e611
-:201380005d7401f0d082d083d0e032c0e0c083c082d2045391ef90e65d7408f0d082d08352
-:2013a000d0e032c0e0c083c0825391ef90e65d7404f0d082d083d0e032c0e0c083c0825319
-:2013c00091ef90e65d7402f0d082d083d0e03290e740e51bf0e490e68af090e68b04f0d38a
-:2013e0002290e740e518f0e490e68af090e68b04f0d32290e6bae0f518d322e4f541d2e982
-:20140000d2af22323232323232323232323232323232323232323232323295b32ff2da0662
-:20142000ae907b06cfa9ef8279e0f50c27414e70eb404f4e58946f5ad304fd12fe04c50852
-:201440002009f609b1cede877f70730193ea77299b5536e0b728dfd37f08930d2aa25623fd
-:20146000bc08ee4cef88ef9103226f44c919db00d787dfe0df108bc07b60ec6d5609f744bd
-:201480005b26ff0213c841107597532e5b61f5da6be6df106a70e7605726eb818749bf604d
-:2014a000edc99702a9604d10f58a8bd0534fdba1fea47f1327c1fa037613ef02da902f62f1
-:2014c0000932eb5d5f8eb302fe96bb14ce0aecd1f9689604ff03f7a87f817f2476452704ca
-:2014e00098245d37bd25679c34047c8817c0f66caf116f107215fc07512477c129d0f906d4
-:201500002d417f807d445b03bd1e73429795da207f40729457e1c13a56d05f10df04fb0816
-:20152000b764d350b7365db6fd10dc13d588fee5f9027d68ffc1ca10f408e6c1c778fc3b9e
-:201540001ce53f15a5cd7f9df70523446f58a7912ab0df43ff13d71de781af49b7c0d8f89d
-:20156000d665df432f203d847910f10b1e61ff08ce54df23d47effe00d886f8add68e94b97
-:20158000b3731e40fb509fb7fbacc6311f201c84cb5ab6a9fa4f7d6cca20eb5a9f9def4059
-:2015a00059bcfe33ad2419615c84bf20e506df15ef06ed8ea3b0ece1d294d188db1afe2c8e
-:2015c0006523db3ad75059907ecfef1af520b300af188e0ee7c2bc12be02f5a3da46accf73
-:2015e0005a05bf10533ba6b98d68bf00fc07e9c8fdc2cbb0f50aef0291459f982f2433d6d5
-:20160000f614ff14fc0182807651e44ae6707ad4fc51f781f2717624aeb49bf8b618ed089b
-:20162000ee0c4f307fc1835dfc18a10d1b20cbbbc351dfa01d17ed527c8edb8126649f3dbc
-:201640001470fb00a5806846fd66e689964fef0fad05da6bd382ef44db345a60dd2c7b4077
-:20166000cdd0ff5c5b0742b3fb009ea9f318d5b0ec41d31c9bb6be40bd25ff00ef53779ca8
-:201680002301fe107ba8f5e6395dedced7b4b6089d053103fb20de10f98aa16250e6f919d3
-:2016a0005116aa08aa047c96ef68fd00db287754fb089f34640fdbb4eb497f8077020dadf1
-:2016c00035897a82ffc5d106ff22ff50fb01f3287992aa4557e8ff014084fe66f91a71d871
-:2016e0003746ca4c27a8fd40f718b9ecfc24a9de8f14ef0bbd26f7256a40dd3bb060760a02
-:20170000a74dcf20ef60cf08fc70dac15ee07802f75c53705f40fd66fd212fc9fb0a94102a
-:20172000e192ffc9332dee47fdc6354bf7145d4dfd098f367562ff00ae927ed13fd2fb0c99
-:201740005990b981fdb02a95f1a44ec0cba0cdf0e81ef784f38ccbc1e4e163886e74cf0141
-:20176000de056f80e932f9a07b62760bab4c39c4fb40d700ff06de81e440ee20bdbc6a8680
-:201780000c233c42749833cbff90f5a86ef178c4bdabdf129a007d89a7329bc1af1966204f
-:2017a000da059f11bf016fb88776bf44b60d77517f463f10e303e504df0c59969b705719f0
-:2017c000365145099e54df2aea1177705a28dfa6eabef7a1fce31e022e21e7366710ff40ef
-:2017e00020227f407b01e6985d017f70ee2fbc57f001eb41ef09f6079da7d608b31e5e3cd2
-:2018000006206a04529ecbb81004ebecf304bfa41e75e716648efd19f303bd029dbabd9586
-:201820002e327b8893182b64cf20d709cf5a7f50e315fd01ff70d31c840a77825df0ef44e9
-:201840008f01f607ce309e93f510ed823d20e700ff11ea05ea009fa0e219e6aff66274553b
-:2018600065e06ee87f500c4cff089d42b9146f88ea1b3c61eea41b187422df85fa88f62102
-:20188000089a7f9d4955f2c196443620ab60e86d767028abfb4397867f009e103764ebc51d
-:2018a0006c53dc40ef2afae4fd265f505d28575eb624bb0e8a1ddf34f44d35353f01df140f
-:2018c000fe80bf041f146785e293733e5f408ef5ff2207bcaf8255266d50a41e8e80bf0282
-:2018e0001d64bfc7fac0fb8f4e88475e4e99fb469b55bb56cc24bf375a89d342ffa8afe4e1
-:20190000396ac73df75117245e60a6329395f32cd624de00b020f104598bb5c82a203c44f8
-:201920000701fb061b41f51f9f00aa11619a5f038ba17f40ff808fa68342d8907750f5856a
-:201940009912fe00c76c6d815f7289c91f186b90fbd155217b52f924af24ff68ae5bd50024
-:2019600056766ec4af62d7c3f6c0a602bcd32be8dfa23f84b634ff0c54cdd96daf909f43fd
-:20198000543dfc43bb8ae540f9073619ff613fa8f96ebde1dd195f8092056d982c917b02c7
-:2019a000c82597146d40f78d4f1ab72266b2e20cfd03ff416f104b8497e06027dc148f36d5
-:2019c00023f7f6c0f76a1300f5067d58731ab5818b761b666f298d54ff748f107275fe201e
-:2019e0003c5a7b025604a799ff463f40f50bdf05f712fb20e007be23e10cf905532afd84bd
-:201a000070233504d781ec28ef06bb1ef71096087424be104e51bd58efc37a00ee887c10d3
-:201a2000d0129b10bfa11b6067305212b73bab40f59200cc4f68e226f614e701ee81fe9c59
-:201a40002bd0ff409cd7fe932c86ff801d24fbce7c124ad0ce6ad1044c568f01dec691ea07
-:201a60009c220dd9a785d480ec83e320973cff91bc117e42d8a3ef85d982fb5e59819e3095
-:201a8000aaeef8275721bf11fb0af9815a1653a29f28421cdf60de866d28eb086fbaa81032
-:201aa0009a885708dfa25d19c904cbc83d220c34ff04fe0832c96ee401de2f005526b029f7
-:201ac0006a84be50eaa2f203be60c7d90e446f5abf2aff14d7443f2867580f803748a711ad
-:201ae0008c309c12dad231e7e724fac1d210bf0d597057020be175216f8bef099f88728491
-:201b0000b3247b036645ff81ed207a49ab50fe64f812fd0a942d5b36ef71d4377e407d22ed
-:201b20006547ff815490a61a7f00f3362aa427c356103766b348b3027600f54edfa2afe1f8
-:201b4000e31ded999f3037a8c674fb2339a9fe38e71f97a3b3b8ae09fe44fbc4dc305fa46f
-:201b60007e4cf95cf5969be0ee84f15667647310ff843bd59f8a41153f42f20af750bc4067
-:201b8000540a6e0367287fc1ff10d6cbfe00fe949a52fe00e3425fccf10efd8acc09d9c237
-:201ba000ea41ce10d90d3fc22a4415345d0c65f3f227fc61ab262fe6fc01ff08543cfb943e
-:201bc0008350ff0d2ec0ad2aef00ff04d890fea8de019f2a3710f240fd0ef3145b80eb0068
-:201be0009718f9315f157d84f708c8ea7ddb3e566633dc09a7da49b1f784d3246e10df4ce6
-:201c00005b86bc04eec3af413c627dc6de1373d85d43fc16f310d5a0bfc9f795cbf28f22b9
-:201c2000dda6f645ff80e82c846367e0d60f7a499fbf3300c2141d61aeb0fe6193867d7acb
-:201c4000b190dfb2e92dee00b639fbc67d92ec0a85267651e9dcf680df89d502e7408794cb
-:201c6000db24ff46bf51ff88af40bb20ad37e3e27b0b37a08e40dce0fd98ff267eb0ba4944
-:201c80002d8277a19f008f60b985bc84fa47bfd49a84ba4d7fb6c29ca250b425cf0bd980e7
-:201ca0003357dbd235261563cb18648a1d62fccd97a62a52fb6bb0b57f02032af40dd91adb
-:201cc000ec02bf41bf00ef008c1cdf14b909dba1af6afb46eb04fa04ded04b147a020c941f
-:201ce000fc00df00ff024610aeab0b020f3cf6c0ab23777a7043ba20a468bf3afd026f8408
-:201d00002609f7c4fd79ef64efdf9b037508f3937a2fe41df4ca2d21eaabf0407b36f12c58
-:201d20003d108d84bd81d7197e0cbdd607f8cd133b0cbf8fad5a73b8de18471bbf24fa47d8
-:201d4000b9acdc46ff112f805fb17fafffc4db67df00ad00cb02575c1970342b8a41ecd57a
-:201d600006d2bb20bd28770949329b94e826e8b18e35d5a5f901de898b14fc0b7b88e32da3
-:201d8000186b370877cbf3c3f7a8fe10f7004f96dd80b79cf22cfc53fbc66629ee20a009dc
-:201da000bc9a479af359e3048fe8fb30fd4affc0bca0db00ef12ed4fed9ecf10ea29ff80a1
-:201dc000fb0a59a0b6d0fd0b37846e81a537e308574a748cf384df0a8de4fe80e502b90076
-:201de00018817d026609b04965d13ac9560e6d4d4f08b55572b275b0c40d06cddf81dac0c4
-:201e0000ea8bf501f5027d04f50cf6a0f987268841887f6255c1e3269a213e40c5806be187
-:201e2000f4a05b8af60a7e402700fb006e0c7397c748e98bdd7cfa04cd7899fb74f86148fd
-:201e4000a9be9c637b48eb36db00e722d6a2b2328f2c7722e843f532fe16f85cddc0e5a0c8
-:201e60008580ffac591033b59e80c750596df311220e9a655bb6ff8cf90809490b51552d66
-:201e80000837f5ec1d245595b203eb283f406b4da5207b205f1a7c22fa9eacd1fb04c5eabe
-:201ea000c2043fc0ba6ec30af947fe058302a30ee316521ca7394cd4e7a0ea913fb86f2af6
-:201ec0006706b61033ca77d1fb057b4b66046f14fda03714fe405917db38fd083f01f26295
-:201ee0005d8e7dd15532da80f724f1287e44bd13a8109d707f40de506e10fb00f8865df705
-:201f000012918e87fb23dc2cffc81f3d9b10de184d6a31083e856e00261b955ab612af74e3
-:201f2000c4c7c5e5f700114ae2687790731e708ccea07bc0f30af70125c7750bfe90ff7035
-:201f40000e22ff02e7403d0699642626ae2dec38b5d4ff08df08d4303d5e9fe45c259a24c6
-:201f6000d6b8ebb0bc142b3ecb50726b9d63afc0351976535c892f80f705679ce225b8a18e
-:201f80009240e50dcf0b0d96bf01798fff14fb2267f0fe29a9816d10df22bd855f94571244
-:201fa0002ec0ffda6bc24d598c696d06df00fd22d4309ea0d221c935ffd3df189d683cb034
-:201fc0002415bb1bb872d522ff207400dfabff42f5933eda7fd02a480b005b68ff087301c9
-:201fe000f185ce8bab44fe245386de063a42f9e0fbe8dd523f50f40d671aeff57f55dea393
-:2020000018f690ee78d680bf402b29cba3ff0c53487d107e00efccb100e7827f11eb905fb5
-:20202000017f13fe5877065a6cdf206c62f6251fe5bfa36e855b42ff40fc02d9387e80ba90
-:2020400010ad6c3e4abe11ba10ece4850bf7646f50cd205f84aca0c735ef28da10fd02fba9
-:20206000205beddfdc3909ff67f759964879535e94f7829c213fe2dfa1de80ed66aeaae7e2
-:20208000804e0833012f815e707b00f36497851e047b16ba6a12cc3d803c90ef813f20efce
-:2020a00004fb02b8cd7752661b96205721e7127360d70a7d0079abaa19ba092728af003719
-:2020c00020ff5125049d145b6cda65eed3f3533c34611136b2ad413f01b86ccd01ff98e345
-:2020e000027c20c521dc00ff29b4a53528da58f9768dc67e285d09b80df580f90ebd047f21
-:202100000073609b24bd20cfa63708fa54914c7b90d5681f44ff827f691ec6ca25a581a6be
-:2021200046de2bfed0df907ba067037b14bfd5fb60d329770d03d27bd2f6863b69bfc98640
-:2021400014d6231ecd65327d12df90ff2933919481bd129f02b70af804f1bc334653d17bff
-:2021600001efa4bf0bbf24aea4bdb7b44697023a3a7fa2f500f959f7edd6a8b138de0a5a5c
-:2021800020bd03f7a0f6044708ae10b41c79cffe817a107f12fdf4958c79c02d68f5c4571f
-:2021a00024eb60e4041f04fdc4d1005f45cc162f22582c6b18b50c97886f00e789c74b3f25
-:2021c00009eb40e7a14fa55b346e1ee3c5be80a61eb5409fa0bfa37d9a2d2bde80d5477794
-:2021e00000b626e1e5c9003f1565687908ef64d38a5d10bfd4f94679899b2a5a24cb00ce05
-:20220000207a89164d4a8b3e51ff84da009e1d7321ff187b0bef1c6702f8883e10e6103b18
-:20222000005f04a30076a69f008c60b304f188ba45dbc87d807f0cdd3ca228bf345723ef58
-:20224000007f08ff0ef7b4d3faee4f7d54ee03ce40f3edcd029c927600ee413f11f944b79f
-:2022600010df33d404ff403efcd21767e21c033f19d635472feb0afcc06b90ed2e7780778c
-:2022800050de50ef82f721ab02db226a28c7006e13ce085720fb455f8b5f08b793cd68f264
-:2022a000049f49ce2dd34af515a31ef23d9f118f90f11e3d095b04d9b83724c353f960cf73
-:2022c00018f3c59f152752d4a5e100a58c77e11b287780bfa2fa8638c6930b6e680f62fe22
-:2022e00048da0d7f30fee92d04a306bf5435c8cfd18bcbbd5df6096ac9bc12fe1ddd90efa8
-:2023000004fd06d550cc43ff0c6b20db243c00e72afa00f921ae1c7e00fd01dd25b4c0bf11
-:2023200004f92293a6edf5f8105f089181fee10efc1f428f6ada312f12ed6087208428f7bc
-:2023400010ff483ede5f01fe21fb218a552323fe28f9d2f216ff65f62e7ce4c278d7a8bcf4
-:2023600000f4cd8b6bae81d58cc92742a2beaa5a32cc8e5632b3254d21bf15ec31ff74ebd7
-:2023800000f284fd414e117e6a71d57d2e3f402608f108f7a8db02ef50f7c4e5206887be83
-:2023a00001bf0addb60700b52ad94754bf0caf3599c750b723ab9aff4ad708d7389fb61f3d
-:2023c000037c40fd04fb12bfc83f44bfc6dda237ad9f24af88f730e751f3427e21ef73842b
-:2023e0004c7d00ef84b3317f403ea38e72ef3bdba87c38ab1695185da3d756de62ca62f1c4
-:20240000407e10ff0c94cfdd88dbd077805d18ef156700de3ae3f1e7257a120700f68297ff
-:2024200002fb8477d063d0af80fd411795ee70af08f903fe08179b44cad709e0409e285a91
-:2024400006fcaef754d999eb82ee9cfe034402ee201c087e0491236f59570cfe69c509fb0e
-:20246000239dea56a13cd77d15ffc29f387700fc2c5b447400ddc574c0bf0ee4c19a0daf2e
-:2024800004f515ff20c8d80e34fce14a146345feccdb43af29bfa3df57af02fe283ab8f633
-:2024a00000be53fb19f301f10097a47ef0270f7a20799aed18d485fd993b94a440df1beff6
-:2024c00000e34b7e0871837f06bc30ae4cbf14c883d5726348ba12df9e9810f77ebfb2ee14
-:2024e00050ae2b9c01b500cf2dc93c9e04f864f3f0b4a5bf1afd807b0d2a15c22fa831aa95
-:2025000004ffc43d1c8fc3d540ff006109cbaca300dd04ff22c90c7b02344afe207732ce4a
-:20252000808629cf22fc96d881ed897a3d6940fa1d8c3cef22daa19182bf41fc6517a2d64c
-:2025400050df30574df520da40ec01d688bf6a390c6babebe3c9156e3355e43f02cf129d35
-:2025600090bb08d2403fa9b337c9f04d11ee28dd16ff4e750407e19e137eedefd57008b747
-:2025800002572dbfa0ba63b37b7fb0e741ebd2bab8cf563564ee90ef12fd127e07faa673a1
-:2025a00001afca30847633dc65f9007f4b9da8bb8afd245dc1bb09fe367a30d3425f08f663
-:2025c00000ff072ba03d0445d4f702db06e5843742b7b27f4bd441ee196d047a11fb10efcf
-:2025e000107729bb927e087d00fd281f21a2307b467f84dda1d2054b08f58066caaf043fa1
-:202600000068102ec1ffa287d0cf264ea15dc633e456289684aa57f06c57227e009c75eb55
-:2026200024ff87798cfd92a904f100464aa0c8fdc4bae8f44c67210c80ff23a3039c0ef1ac
-:2026400001ff1f6f061f00b3a1af907d00bb297750bed0f5fa7500fa3251804f8896939e7f
-:2026600004df2b7f6c76458b50b3482f80fea46762985b7c0afb8526417f1377e7d434cd91
-:2026800042bea86b403fa1d7a025833c4ce6387728758bfd08f729fbe0c92456c0fb0aedae
-:2026a000087750d40ad50afdd2df64820acf02fa75b103ffa40e29ffb5eac055c04be23f43
-:2026c000147d6398447f0cff25bf49d308f9d817336f44d8909a282ab8f900efd26f0cfa8f
-:2026e000d0d724ce3dab8e3713cf4863b04f46f2063840d4928f13f742fb857e6293437b60
-:2027000092d70ab603bf02ff70e972bc0226827f547a0d9b035f0aef15b752c308fb15c48f
-:2027200051ae81b091d801f790b782e289ebe2db007b2df543fa20ac007f38c723ef00ef07
-:2027400004cfc8d31fd542df74faabf7fdb776fc016a0f7f802f0dab04fa0cf121fe63eef5
-:2027600012f788cf14bfc37e10d9caaa40d505f081eb20ff417e42af3931147a28cb58f709
-:2027800094eac8348afd82773ecfc8ef3fb868ff869f42a5cbfbc0f610f55e9d00ee30db9c
-:2027a00020f3d41d99b739aba75905adc56634a105b5c81704fd86f938e5013e30f7a87f6c
-:2027c00002e250ed0cbe5f8e30df44bf32ce40efd89a0957087de0ef50fdc93f8825185b45
-:2027e0000055008a4cc1157b447b787f486e14e5c6ffded70d7b52fe176627c983ffa2f322
-:2028000000bdcd8fc3b309ff25dead7b99adca5720cd03ff015e00ef20f7b4d490d7027ecc
-:20282000004741bf0caa01ff43f2e87f20ee4c9542dec5fa805d923d8cff01ebc4373b8454
-:2028400010394ccd69f732e3865b4ebaa0f321ff803404e720b72c7340ec047e05f54817e9
-:2028600080f714dd285bb2b740bf9aee02bd447448d5a0fd01eb752ec52a40efa0f3917704
-:2028800008afc8f3e0ce02f7006d197406bb02fd24bc50fca09ec8fa3566b193e0de94e721
-:2028a00028fc00f55aec010a20ff083d02794b251dbb716e56ff2025632ca0c9837faf3233
-:2028c000087adcf164df027dc27f48fbd6b05ca125f4c8d220db42bd02be03d601f5c9ffdc
-:2028e000817bd8bf05b380ff0987793380a600b652f302cdc0bd0fe47193907b2cc1247ed4
-:2029000030fb50fad29f00fe7fe8a40310e72f7e42dbc33a20ee00ffc26e8a17120e4c1f9e
-:202920001187686506fea8cb09df7c6d167b627871f19ad304ff12fc98bfb93f9b37949159
-:2029400010bf113b5fe370e208be0df6607c910507ac806b2922087d88ec280b2b4400d732
-:20296000d2bb5ab546d712ec812c28bd003504edf016977f1aff0ebbd1ff017a8af164dee2
-:202980001c6f145c140f177100afe1d684ec683787d700bf8d7592ef04975063c0faf983f8
-:2029a00010fe84ef8dba495e83df62dfa019a0ef61e90cf6603f11d704de88fbb6b647ae24
-:2029c00003dd40ff54fb15fc137bb46e808d10ee8237a74780df12b743ab8a59a72604aca0
-:2029e00000ff105522f64b6b07ff00fe50cd884d00a71853729041be98bb8affb1fe60e9c8
-:202a0000057d227b583a20dba2435acc5e7940e25b3c43b7235cf205cc2b05b4012fa08df2
-:202a200064a440ff5b2f267de0df00ff8c3aeb4ec2b5a1b664ef285f6abfcdcf2dd590c79f
-:202a4000419e13fe1175047fc23f0bfc216922ee07d7414912dd00ff43dfc5dd07ba0e7e74
-:202a600008f59267c3a2d19f20ffa020346a20bc55fd4ed510f7a1f2d84e1d983a9900b8bd
-:202a8000109f1a6a18f300fa50e44897b6d605ff027911ee9b6d867550ea807f155704f73e
-:202aa00000d8400c00a474253b420af3059945dc55df042e50f5864104ff80ec91ae8400d8
-:202ac000a48e00313669107103fdc4d699be713731f680ef54df50db007f209f70ef2927f9
-:202ae00000beeaffe0dbc2df18f5995740390c6f4ba334caf51fdb4201b740d7c87f609fb0
-:202b0000080b78e3257502fae07d50fb4a5f02e8519e40ba2abc543f843f63dd60eea9ff1b
-:202b20004cdf00d901af05ad92fb8a3d09532038092796c530f9402f00ce8cdf8635907709
-:202b400052b7401fcd3d43fac4ff38f9007d01fea2b93d7748b611b502a45deb04fb206412
-:202b600044ffc0b6b183110c487a00cf2dfb10ef4bff50fe7967dcb36add932a045d326b8a
-:202b800088fe33c70bcaa73841de029d82aac2a61a8f047b06f5f073c1eb14b707f224bfd6
-:202ba00000f731ff2067a1f3d375222e6aec8a3634fa00af63df00d718fc04bc823d003f5d
-:202bc0000272a8f480db43ae71ff28430c9a90650bf328d3288e80bb603f41ff00cf041f68
-:202be00000e5b02b196c9cfe12fa24fc05f205337ad221f5645d4aaa05fff117b13b0edf9f
-:202c000034ef17f689bb16ff013c09fd057f597f1067987510ef49afa1fe00deac6306f18e
-:202c200012cf02c181afc7fdad5c28f712cb40ad25d7b9bc043b0c75409e09d6b3f741e74a
-:202c4000114e684bced15c3b82ff249f151113b716de04fe40bf215e84bf4a7fa5bf03769b
-:202c60000366467b20ff0043c3cb20cb05fd01b1b2bfd0ee12e254ef48e7a43972ec945fd8
-:202c800070b0ca6b15fec0df30e00ca65aff41ad6ad5a97712dba4cd64bc3684024d924e5e
-:202ca00000ee672d8c770cff70af077da2fa6da3ecf9c4dd2cf2c09815d794fb224710eb5a
-:202cc00001663075408323ff54b112f713de80f645d3ac4b087b20bf01fcdc7b74fe50bf48
-:202ce00050cf1d96662d410e405b5b9305fb18fd085f48184359aadb83bd5ad70fb01c2f1f
-:202d0000a5c640bf00fe88631a545dc7c8fe24b3087d07c921860c5ccdab61a901df84edfa
-:202d200018cf623f145f06560d1608bb166c5cda4425163ce64aba7634c9005dd21fa0eeaa
-:202d400042be27ffe63d64a32ec556b9ccff24fb19e3016a25d843f140ad2a470b6e3e0a80
-:202d6000007aa0bd214daafc01f17de920c7017495a6448f51cfd1374abe837d193205a680
-:202d800070d901ff18e640ff20fb1ac170c60bb646da0a3e806f01e619d68a3508df08e7fe
-:202da000400e01bbd8fd904744d46c52865852f629de644f83acdeeb9fa5206f2e27c36e56
-:202dc000c81fb1e609ef5d7ad40f42fe2dcd08ffd9f900cfb4b6433c6dbd819701d708ba1c
-:202de00050ff0bf51876d17c85388066adef9bfdd40fa06fc1fd9ee3d2ee92f5b16a4e777a
-:202e00000077c45f08d32bc6cd9a4a3f529d7bf441c484a9921a59b9136162b941b760ee39
-:202e20000079a671b0bf21a5e09f205f515b47f08f29524b02e43f70067a40ba081d14ef60
-:202e400000fc40fe003f867e20df08de68fe88c3d8e35bef027959772937c6fc09ce74b9e9
-:202e6000004f06b1299dc5b014ee0be51ede64ff00a820c4887302dda41f90f753dd51abe4
-:202e800020bd202702d210ecc2c7189909fd405d407e04e809f998fd863f08dc00fa1c7be6
-:202ea000a07f08a68cf609331a9df01f40340ad7c0be80bfa5dd0a75a49848282571a9f8cb
-:202ec00084fba09524ff6c9bd84f90b380bf407f81df016e40fe1afa18df04bf02f300b329
-:202ee000419f03feb99de09d08bf524f2991885904e740ff00fe694390f9b29791b955ca0c
-:202f00005abc428d081ff82720b51cdee2fa29f9c22fa20e511500ff00fe038f36ec94f37a
-:202f2000a0ce98fd805e06f404dfc3ae007992392ad700ff6967325b62ff20f500fc102c13
-:202f400024a7409700df803588a70cb801fda1ed5117507e2078279d06f8e65dd1ada6dfe6
-:202f600000a31876107f10e709ac0b7005fba835807f487f143d6596129c50f27696a80bcc
-:202f8000a1dfcef1b68872fd800e74f382bea88943bc081f40f000ff48bb614a527d727922
-:202fa00041fdd2b660ae405e85e9907d21fb30ed1cbd48e7cdbc61fa0c7bc35634eea11e7e
-:202fc00008fb41f201ff05ea02cc02ef216921ef76f384160f1c8267ca7a54efec57cdcbfa
-:202fe00000750a75a01828ffb053a1cfc9ef12eda0f621ef45f688314aa30c7c242f8c5f87
-:2030000009ec30f730de1c5dc8ef08ba01a790b346d642ba20ef05ff0aff03fe616930f486
-:20302000209f9ac567cd43e5406907f06c7a74a76ca755095e64a4495c7711fc1e7b109e2e
-:20304000009296be02af506f20d8327e2d53602f14fd698301ff80e53488a07f16ec040917
-:2030600014a803b541a654ff24df52087527206908fe80b718b3249f31f9405d49f5a99a0d
-:2030800088bf00f20569427d06d1107e2c79747f0af7d57ff0da00db83f5f2e900fa08fb83
-:2030a00008ffcc89a05c01e52cbe5edd42ec394e202d92ae027f69b62adb4bd384db44dd28
-:2030c000007c7ddda08d905308b703cd95fb09f618b150bbd45ea35f28e9c89800f742b783
-:2030e00000ff808ec0b601fd413c74d70ef54ffd40c312952596d0d606e67092e89f1addc1
-:2031000032bf155da6ff0b79007f63dd87fe80ff80af004fb43e085b62f9f53f17af209e7a
-:20312000c11761f169e9a3ab86c24af50ded0dcfd08600f5405f20af11fdc987543540fb8d
-:20314000483f407fc47f0ab962df22dc24e4409e401e60c18ddf20ff01df2fd710e303eb2d
-:2031600020bcea4504d10a72807714fc089021f890e92c8d86afcc8a0adbcecca0bf0acec8
-:20318000889da33e60ad827d5ca7e2f604fe28ff29af56eecd29563e877224bf33f7b2befd
-:2031a00040fb83af0aaf077508da0a920adf9a2680bc80b5b49dca9014e342ef6dea1d6f1f
-:2031c0000c3f319f68da4d4f43cb49fa30fc04cd28ff825e857d65b721df06bec4b811f240
-:2031e0000afe315dc58e6ced1afb005f1337897848bb40ff46ec01ba25bb637b645685f0b2
-:2032000011fae12f102f04af41fd0cfb87fe08bb82de92af65d509bf5bfe613e11bef5bff6
-:2032200004fe294ea0dfe1ce8cf7d31b00ff1897416f047646fac01c412683982ce291243d
-:2032400000fea0ef116d89bb24ed81f515bb117d41bf88ef3c89859ea993117f13b354985d
-:2032600080db005408d4156d69ffacca05ee9825491d1b7fb44fb173e23d6057abf085385e
-:20328000409d2a2d30b81d7206ae75c7d1ae3afd00ff18f41bdd409b4afb027f9b7ea13f40
-:2032a000c0ef12b900ab6619806b1be92a150061244eb8f370b230ab208f021f32f728b2ee
-:2032c00001c724b7503510f700ff4052d6d648e34b7eca9451f7c4be02073aef40df58dfde
-:2032e000005f02bf1a468cc5385dead3146695c90eb7a58b43b509bae5ad123f0779807fc1
-:20330000409d907d05f71b55239a0ca364c9d46b207f34985896a0ff641fc0bbd2fe40f782
-:20332000099e38e5c47ba85697894d961d1b81fb0bad0c7898ff401faded45d3585e3cc639
-:2033400052d9147b407f0cffd9a3204706f9047705fc00ff537d10d70af7c6eb0efe005fb8
-:2033600080ee10a714bbc1efec8d44b7f7bf2ede4af308df06ff208d0076143df02d80ff3a
-:2033800006bbb1d8a0f9487ec9763467d04bd3f0007f42f233ff664107eecc92213c42df6f
-:2033a00000ef803e4ffb095d48ddb4fe3f5ed021516b25f8007f8af6818f817900fb8dc51c
-:2033c00050f334bf003d18ff32ff10ff829d10b492ff18cf827b205ff8f32add078e293f5d
-:2033e0000a4f04f289e7ccf7d9770dc610db00fdc63f08d50455c0ab0c4bad3f357711cad0
-:2034000006be12be49ff62fa0bff5af3204fa831995146f62959409f20ef00fc448d10df83
-:203420007ada84b50a5d00bf00b5a96a144b821f397a20d749f77ce5a43a20f717d7a43e01
-:20344000e17e92f743c869f639d8306514ffe1d504eb22fa18ff582d82ef62ef806f79fedc
-:2034600018f58ac9296748ef4927805c417e14a67db2d7cac1fec53b1233613e2bb38ab7ce
-:2034800004f362df81d614ff886d13ba883c12fff6cc22f788b342ff00f745dda0f779d79c
-:2034a000b0f370ed49fb84bf44b880ee00cbf24c10f500ef01ed67abc6dbb3e3a8f3900eae
-:2034c000501782f87cd395ea07bf30cd0f9a2499116cc6b54adfd5e633c6cb178defb10b25
-:2034e000007f875399fd0aff1cff002f622fab7d09bf805b505cccb34d9da0f590a14669a4
-:203500004873483986fba4ee09f850ff2aed0ebac3a7286d0a57b0fe44fcc5ba887740fe23
-:2035200028df2cf6815b086302774ec913fc84b388660cd904f308cbc2cf46f9183fa12fb1
-:20354000a0dfa87902f608fd20b4d2fa10b218b7369b482910dba0fb20d9557b116b61cb64
-:2035600004f9a695039e15f72e86a825706b0a3cbbfb58c7b9062ffc00fa9517c23b22f749
-:2035800004eb14e710ff16ffc2d700af182d51fe448d407e68bf05dbcaadc6cfac7e80f7fe
-:2035a000136fe6c9b9e6815b20fd063e403f68d6819c83afe7bb32bf11e720cf44211647b6
-:2035c0000afdc2fe105f00e90edea8cc1e94619f7a5d600f866c41ed20ef21af03ff0d3f27
-:2035e00008eec17f10d7acf1206dd668401c6963003c1638097b822f825db0cfc4d7e05531
-:2036000024c680df552b02bc34f744fd06cf04e189fca37c47f5007d1e7fb71e80ff22dfae
-:2036200000fb187b42bf86fca9ef93de36f7b3f4e07103bf008f811fd1ce549f5b140c73da
-:20364000a02f18ff15a4b0f6259f55ff60cd18fb04a7087706ff1b3b14dd44f541e6c65fd2
-:2036600044aac23e889516ba634d1fd528d96085238ffafc6e7744ad25de95fc87bcc3bf0e
-:2036800041be84ffc0db18bfa5c3009b52ba902e89ad0edbd448906d48bd8069aafdacce22
-:2036a00001dda8dbad5f04fdc06fcbd8b9e72de200d121f71670a223c98e63bd80f729b719
-:2036c00050fb58f6885f44af0efdc8df4c7d20fa400900d1247a284b037630e7c64b10f412
-:2036e00000d748ebe9d311ffc07b60fb65ff05fbc1bf2cf166bfc87702a683cb43ff9d77ad
-:20370000006730f740fd4cbd17de20e564d268af142255ff13ad82d740eb194ec3a9823f2c
-:203720001162409715bfde6361ef477d40b6003a186b817b937316e914f629ffc0fa48bf6f
-:2037400080a304d9a0de182780f784ff2ab561fb1077003c00f8183e816a844fb66b11ed89
-:2037600000fe16457b64005502df00ff20758aea077bc11f572a14ff203f38dda4c75edcc4
-:2037800080f3a7ab44fd01fa562cc15b616500f901eac4fbc093c08fb0723ce70cfa00fe36
-:2037a00020d68f7e48fe1c2b68eb407390ff047a1a7441fd40ee20df21e38ed10ffda25ffd
-:2037c000017f59b9002c10b149e69055c12c411350494425137f83cf4a6b9bdf904a80f6b0
-:2037e00000db282b28e34ef77f8a06ced0ef19b7d629c0ce55f682bca07615ac137c077ddf
-:2038000028f538f86d8f80771c931df718dbea9e20d7807e1063226d99ae908b649f08fcca
-:20382000009f1978093ec87d50c71196c89bc0470c73418306fe0d8b41cec47fb63335da7b
-:2038400000e7fa7f00675a3f20fdea879474cae3a5dd4aff08bf409918e1a6b218ffd2a67a
-:2038600008ef237b146fd9ff40fbdc59422ee4e910d730372267325fad4905fde06b41f7c8
-:2038800040ffc96b925213f7267b8071486d74c728f3fc3c42c102bf152d53f5a47f05eb91
-:2038a00000bb80ee2de842aa289fc4fb21fb80e9e55fcdb5a2b900e255f98a5f7a9061fa34
-:2038c00020ad80bfba53609f61eb10fe1d7b21f68a3b0dfb007f04f5cafd963d011b167b3b
-:2038e00090f6569e00bea0f837d99aa34056b81fdadeb57d42dd03d7ddaf2ae167db4a95a3
-:20390000247e44fc21cd0bf74afd8cf12b6c207f80bf069e0220034f89fba4d780bdc4770d
-:20392000007f18b7f2cc50544eb978a646bd525f3dd68df158eeac0f0bee4996c32218ff98
-:2039400000f3dcb12bb8c1f801fe49f7137ba7dc493746fd279d00d10cf74c7350f348bd99
-:2039600041f5064acb5f0c42972e844d8b3768df229e174fc4ab32e1d2ff02fe02771a732b
-:20398000023f404bc0dd417bdcfb9ef680dc003e011ea0ad0eea759c25f6823c02ac1dfee6
-:2039a00048b4d5e663f7125f01e64a3f9c2f07e51b67875623e5240aa4dc889f15ef649f1b
-:2039c00000f19566526f583904e96039413e98cf509792560a7da0a510ee50be72ef48db12
-:2039e0000df72269f01df3a8e0fc29f68be985c677dc20e74a7a19e5026b07f39d0f9ee722
-:203a0000220310fe35e846d944f5688d1cea0e92cb8adae600fc229f68fe44f348a552e1d4
-:203a20006474499e9f8ce0cfb07b54ee99f211ef0bf4367355f6a0332573c6bb08ed826f30
-:203a400004fb46ecd933489f4dfd1013428e8b1d2867b8ff2c6f8a2500ff01f3d0bf101a21
-:203a600042cdf2bca09f1b25386730bf50f7226d72ef902fac6518ea9c6901ff84ed08fdf8
-:203a800020ef00ee0cde01ff80e100f388ffc55828fe27ff077b1097082b42f73df24ae508
-:203aa00000fe26dba43b89d5ce74aeb9e28c41fe00e70973048d8d6dac5c92d6715fa2e4c0
-:203ac00004ff00f730e7d0b6aef706f9802ec631b4ef453fe0dbb27d007701bf0d5e23f739
-:203ae00005bf9ef3609f2576ad8d003d10ff58394cd72b6523ee0de680bd209ea4f702f47d
-:203b000070cf28f004fec1b718e315f318df8477196380ed5239c7c3626907e5c2f608ff6b
-:203b200010af11fa8e7721b768e930e9696a80de81ffc44f24bb8dff24e529c95695c4f5a6
-:203b4000087d348352bd08b6803e86dcd0ff83ba44930aba748708f390f724abac6800fb3a
-:203b600028ff45fc54b0b84d44bd4e5b01fe70f3e9ca09f886a881aa40f544bcf03742fc21
-:203b8000083b58eeb1a74aec316e79cba449f880055d0876297d900f00db52c5226f22e715
-:203ba000044d2cdf00ee80fce02f49c61055483f7cfe42dcb6ff035e866540831ec408fef1
-:203bc000006fa0fd20e58455992f44ef60bf41fb9603b25f137919f683fd08b342cae04fea
-:203be00020ffe89f4aecb89f7a382f5f24ef28ab20f54af251d773af13b6c43f36b351dcef
-:203c0000207c819f22d7007250b143b203dfc2ee00f310ef45b708e52a3f00b292db229fd1
-:203c200000b3293b605a10fd297f967758cd14eb71fb297ec61d02db093ba2ff91baa47ea8
-:203c40000056096f475c8073a87ed1c68affd645007f253f44f7dbd3b6d7903f149704ffc9
-:203c600098e9d87fb8f6b9ad47eb013f14fc46f6c8fe527101fd305f249dc5fd50cf50eba7
-:203c800030df4dfd319f3a2e027f19baa03b36af1535423c8c7a29f329f731df88ff06be1a
-:203ca000a8afe4d3103d11b780e412e7bb45603fc2d5204bb7f8386b03bf24ffab9c589875
-:203cc00002cf48df831f18d74c5f80ee41e4325600f62929b41150ab806b11fd56ff8a674e
-:203ce0003877a8cf81bf82dbd40c00f3b3af1475505a4b7b3e6a60af940828d42057822269
-:203d0000146360fd30ae00ff40c727eb1a69176e40bf95e344fb09fd01ef24dfd8bf841fe8
-:203d20004475036934eb004fd12a2039449f8ac15ee201f82dfb21ce9f5e203f6b1a0fd45a
-:203d40000076d6bf12c6cc6792bb58d7909bd9e4155fe41559ba409b06e5a1774637004fbf
-:203d6000e25700f482a6e2d6d19595f5264cd472409634ec18cf5443c03de83c58eb423f35
-:203d800020ee00b790f6687e90ef00ffa2c412fb167e94f5802f83bd12f218fb227b857745
-:203da00040d3465e446fa05f5a40c0df01e1c0bded5e78335a6a33c53162d045ad625086c3
-:203dc000007d403f047c30e22cff267c4cfdb6a509f903ff40ef3a8a04fd00df54ea116d51
-:203de0008c794ad33cc40b34b1d360e605fb2ad0e9a5893a027b33b7947d606f118447df4b
-:203e00008046705c02fe4bff80ada1f3c87b22fc89fe0a7f19e842ae1dec24f916fd5a36da
-:203e200048ed095f21574fdb801f18e30ebac26e947721bca4b962bfb1da05af0239c0bc55
-:203e400000ea5937304f41ff20a31cdb00fd25d709fe3efee0b3903f91e704efe2f388fd0c
-:203e6000023612efa8b932af502f07fd72bbaabd25254436847630fb48b68d378794c1ff2a
-:203e800082733462c3db9625016ca1ff86fc20fb00eb4eda00f98cf620fa9678112e29e78f
-:203ea00012ef08f5b0cd76eca16b8fef50b7f0ffe58d1dbb8d970269489d19e80837213650
-:203ec00008fb0ce8e0bf84ff00ef3db705bf16b45a9600bd223a224f3cfb09ff06bf1a6e52
-:203ee0000651555f197688f225e72abc030f034f849b4a9d94fd49d8b0d690fd62fb48b632
-:203f000000bb8c29401f0dff41418a4f0295a3fc415db46f01df40fb0cf75af744bf197e6b
-:203f200004a70016538fb1b30d7b18f7127b15eec17ebadafabe803a00ee343b28ff05f88d
-:203f4000827fb02be8bfbba780ff4efb239000cd30ebaa1a0c790efe821e408f8543047811
-:203f6000004f8e9484b194bb82cb02e662b406b2a0ac08bf414f0db4132828eb12eb9c1de1
-:203f800040bfe1df90e7517f026b989f1aefac7a087840cf417f33da4ebc2e83cd9b212b7d
-:203fa00099e420f06fed008d306f4037bce62bca94249be509fd440f67d48d9613aaa46925
-:203fc000427c205f448c10db677d24d741b0401f11c1d5dd01aa425b3076507730df127ee2
-:203fe000986e3876352712e727d362d738f785bf60fe447eb0e8a154a166043f01ff5bf7c9
-:00000001ff
+:04000000020059326F
+:01000B0032C2
+:0100130032BA
+:01001B0032B2
+:0100230032AA
+:03002B000201FBD4
+:0300330002013295
+:01003B003292
+:03004300023F0079
+:01004B003282
+:03005300023F0069
+:1C00B200750800750900750A02750B00750CF4750D01750EF4750F01C200C201BD
+:0300E000020056C5
+:030056000207C7D7
+:2000E300AF827401B54C0280157402B54C0280127405B54C02800F740AB54C12800C7E24EA
+:2001030080107E12800C7E0080087E36800475820022EF60067D707F0080047D0E7F00ED9D
+:20012300F4FFE5805207ED5E4FF58075820122C2DC32C0E0C082C083D2005391EF90E65D75
+:200143007401F0D083D082D0E032C021C0E0C0F0C082C083C007C006C005C004C003C0025F
+:20016300C001C000C0D075D0007582001212165391EF90E65D7410F0D0D0D000D001D002C8
+:20018300D003D004D005D006D007D083D082D0F0D0E0D02132C021C0E0C0F0C082C083C085
+:2001A30007C006C005C004C003C002C001C000C0D075D0007582011212165391EF90E65D33
+:2001C3007420F0D0D0D000D001D002D003D004D005D006D007D083D082D0F0D0E0D0213224
+:2001E300C0E0C082C083D2015391EF90E65D7408F0D083D082D0E032C0E0C0D0B2A2E50EF4
+:20020300450F6019150E74FFB50E02150FE50E450F700A850C0E850D0FB2A0D2A1C2CFD068
+:20022300D0D0E032E582FF30E00BADB17E004305088DB1800353B1F7EF30E408AEB14306ED
+:20024300018EB12253B1FE22850A4C754D00905DC01213F5AE82AF83AC097D00C3EC9EEDE3
+:2002630064808FF063F08095F0400990E640E053E07FF02290E640E0FF43078090E640EF19
+:20028300F02285820A7401B50A0280057402B50A18AF0A74072FF50B90E618F090E61AE5DA
+:2002A3000BF012024B758201227582002290E6F574FFF000000000E5BB60FC90E604748076
+:2002C300F00000000090E618E4F00000000090E61AE4F00000000090E6047402F000000085
+:2002E3000090E6047406F00000000090E618E50BF00000000090E61AE50BF00000000090A9
+:20030300E604E4F02290E6F574FFF000000000E50870057E06FF80047E027F0090E648EE18
+:20032300F022D2871202B07EE87F03EE24FFFCEF34FFFD8C068D07EC4D70F0E5BB30E7FB06
+:200343000000000090E6D07428F00000000090E6D1E4F0E50870057E06FF80047E047F0043
+:200363008EBB22AF8290E680E030E7067D1C7E3D80047DA67E3DEF75F010A42416FBE435DF
+:20038300F0FCEB2DFDEC3EFC7E80EFF508703590E612E4F090E61474E0F090E6E27401F0BD
+:2003A3008D828C838EF01213D890E625F074012DFAE43CFB8E078A828B838FF01213D890A4
+:2003C300E624F02290E61274D8F090E614E4F090E6D204F08D828C838EF01213D890E62170
+:2003E300F00DBD00010C8D828C838EF01213D8FF90E62074075FF08D828C838EF01213D8A2
+:20040300C423541F90E64004F002024BAF827E00EE75F005A4FCADF024FDF582ED3416F57E
+:2004230083E493FBB5070280080EBE16E375820022EC24FDFCED3416FD8C828D83A3A3A35C
+:20044300A3E49390E601F08C828D83A3E493FDA3E493FEA3E493FF75AF07759DE4759E007E
+:200463007C208C031CEB60168D828E838FF01213D8FBA3AD82AE8390E67CEBF080E47F6027
+:200483008F061FEE600790E67CE4F080F375820122AF82BF00028064BF010302052BBF0271
+:2004A30003020539BF0503020547BF0A03020555BF1403020563BF3203020571BF640302E5
+:2004C300057FBF69028017BF6A028021BF6E02802BBF78028035BF9602803F02058D750C15
+:2004E30019750D0075CAC075CB63020591750C1E750D0075CACB75CB7D020591750C32757C
+:200503000D0075CAE075CBB1020591750C64750D0075CAF075CBD8020591750CFA750D00E0
+:2005230075CA6075CBF08066750CF4750D0175CA3075CBF88058750CE8750D0375CA1875D2
+:20054300CBFC804A750CC4750D0975CA7075CBFE803C750C88750D1375CA3875CBFF802E8C
+:20056300750C10750D2775CA9C75CBFF8020750CA8750D6175CAD875CBFF8012750C50754A
+:200583000DC375CAEC75CBFF80047582002275820122AD4CAE4DAF4E8D828E838FF0E508EA
+:2005A30012132675820122E582700685108212036675820122758200227582012290E6BBE6
+:2005C300E0FE7F0090E6BAE07C004207EC420690E6BFE0FC7D0090E6BEE07A004205EA4223
+:2005E3000490E6A0E020E1F990E6B8E0FBBB40028073BBC00280030206C1ED4C700302068E
+:20060300C5C374409DE49C50067A407B0080048D028C0390E6A0E020E1F98A457546007562
+:2006230047407548E77549008F438E44758251C007C006C005C004C002120E5DD002D004E7
+:20064300D005D006D00790E68AE4F00000000090E68BEAF07B00EDC39AFDEC9BFCEA2FFF09
+:20066300EB3EFE8095ED4C605990E68BE4F090E6A0E020E1F990E68BE0FB8B3875390075C2
+:200683003A40753BE7753C008F368E37758251C007C006C005C004C003120DC8E582D003C9
+:2006A300D004D005D006D0077003F582227A00EB2FFFEA3EFEEDC39BFDEC9AFC80A7758234
+:2006C30000227582012275820022AF82C007120308D007C2A0D2A1850C0E850D0FBFE00022
+:2006E3004015EF2419401090E68AE4F090E68BF090E6A0E020E1F9BFA2028023BFE002804A
+:2007030021BFE1028028BFE202802FBFE3028033BFE4028046BFE502804ABFE65D80520211
+:2007230005C090E740E0F54C7582000200E390E740E0F54C7582010200E390E740E0F5827A
+:2007430002040F90E740E0FFBF010CD2A0C2A1E4F50EF50F1203257582012290E740E0F57F
+:200763008202028590E740E0F5821202277582012290E740E0F5820204947582002290E6D1
+:2007830013E4F090E615F0D28790E6C2E4F090E6C37480F090E6C0E4F090E6F4F0120308F1
+:2007A300754C017582001200E3754C017582011200E375820112040F758202120285758233
+:2007C3000002036690E600E054E74410F01208E3120781D2E890E668E0FF43070890E66898
+:2007E300EFF090E65CE0FF43070190E65CEFF0E0FF43071090E65CEFF0E0FF43072090E6C1
+:200803005CEFF0E0FF43070890E65CEFF0D2DDD2AF75CA3075CBF875C800D2ADD2CA90E613
+:2008230080E043E00AF09005DC12138190E680E053E0F7F090E672E4F090E671F090E670B8
+:20084300F075B109F5A0F58075B6FF75B4FF75B2FFC2A0D2A11000028003120EC110010296
+:2008630080F390E682E043E0C0F090E6817401F0AE877F004306018E8700000000000000E8
+:20088300E513701C90E682E030E60790E682E020E0D090E682E030E70790E682E020E1C2A3
+:2008A30090E682E030E60790E682E020E00E90E682E030E7A090E682E030E19990000512A2
+:2008C300138190E680E0FF43070190E680EFF090000F12138190E680E053E0FEF0020858EE
+:2008E3007E107F3E754C30754D31754E32754F337550347551357552367553377554387574
+:200903005539755641755742755843755944755A45755B4674182EFCE43FFD90E507E0FBB3
+:200923005303F0E4C4CBC4540F6BCB540FCB6BCB30E30244F0EB244CF987038C828D83EB0A
+:20094300F074162EFCE43FFD90E507E0FB53030FEB244CF987038C828D83EBF074142EFC8B
+:20096300E43FFD90E508E0FB5303F0E4C4CBC4540F6BCB540FCB6BCB30E30244F0EB244CDE
+:20098300F987038C828D83EBF074122EFCE43FFD90E508E0FB53030FEB244CF987038C825F
+:2009A3008D83EBF074102EFCE43FFD90E509E0FB5303F0E4C4CBC4540F6BCB540FCB6BCBA8
+:2009C30030E30244F0EB244CF987038C828D83EBF0740E2EFCE43FFD90E509E0FB53030F6A
+:2009E300EB244CF987038C828D83EBF0740C2EFCE43FFD90E50AE0FB5303F0E4C4CBC45428
+:200A03000F6BCB540FCB6BCB30E30244F0EB244CF987038C828D83EBF0740A2EFCE43FFD42
+:200A230090E50AE0FB53030FEB244CF987038C828D83EBF074082EFCE43FFD90E50BE0FBFC
+:200A43005303F0E4C4CBC4540F6BCB540FCB6BCB30E30244F0EB244CF987038C828D83EBE9
+:200A6300F074062EFCE43FFD90E50BE0FB53030FEB244CF987038C828D83EBF074042EFC86
+:200A8300E43FFD90E50CE0FB5303F0E4C4CBC4540F6BCB540FCB6BCB30E30244F0EB244CB9
+:200AA300F987038C828D83EBF074022EFEE43FFF90E50CE0FD53050FED244CF987058E823C
+:050AC3008F83EDF0221D
+:20143D000F0E00000000000002000100000000005055550000000000000000000000000075
+:20145D00010100000000000002000100000000005055550000000000000000000000000070
+:20147D00FAFAFAFAFAF9000002000000000001005055555555555500000000000000000023
+:20149D00FAFAF90000000000020000010000000050555555000000000000000000000000F0
+:2014BD00C8C8C7000000000002000001000000005055555500000000000000000000000066
+:2014DD00FAFAF90000000000020000010000000050555555000000000000000000000000B0
+:2014FD009695000000000000020001000000000050555500000000000000000000000000A7
+:20151D000201000000000000020001000000000050555500000000000000000000000000AE
+:20153D004B4A000000000000020001000000000050555500000000000000000000000000FC
+:20155D00252500000000000002000100000000005055550000000000000000000000000027
+:20157D000100000000000000020100000000000050550000000000000000000000000000A5
+:20159D001E1D000000000000020001000000000050555500000000000000000000000000F6
+:2015BD0001010000000000000200010000000000505555000000000000000000000000000F
+:2015DD000707000000000000020001000000000050555500000000000000000000000000E3
+:2015FD00010000000000000002010000000000005055000000000000000000000000000025
+:20161D000504000000000000020001000000000050555500000000000000000000000000A7
+:20163D0080000000000000000300000000000000000000000000000000000000000000000A
+:20165D00060500000000000002000100000000005055550000000000000000000000000065
+:20167D008000000000000000030000000000000000000000000000000000000000000000CA
+:20169D0003020000000000000200010000000000505555000000000000000000000000002B
+:2016BD0002020000000000000200010000000000505555000000000000000000000000000C
+:2016DD000302000000000000020001000000000050555500000000000000000000000000EB
+:2016FD00307D1680EA1E3D1680AA18FD1580CA10BD1580CA0F7D15808A0C1D1580CA0A5DCB
+:20171D0014808A08DD1680CA06BD16808A059D16808A045D1680CA031D16808A02DD15802F
+:20173D008A013D14808A969D15808A8C5D15808A783D15808A6EFD14808A6ADD1480CA69E1
+:0E175D00BD14808A689D14808A667D14808A7F
+:203D000012010002FFFFFF40B5042A600702010203010A0600020000004001000902890017
+:203D200001010080FA0904000001FF000000070586020002000904000101FF000100070549
+:203D400082010014010904000201FF00010007058201000C010904000301FF000100070502
+:203D600082010004010904000401FF000100070582010004020904000501FF0001000705F5
+:203D800082010004030904000601FF000100070582010004040904000701FF0001000705CD
+:053DA000820100020495
+:203DA6000902390002010080FA0904000001FF000000070586024000000904000101FF004D
+:193DC600010007058201FF03010904000201FF00010007058201000201AF
+:203DE0000403090416034F00700065006E00480061006E00740065006B00160344005300F9
+:203E00004F002D00360030003200320042004C001A03300030003000300030003000300061
+:0C3E2000300030003000300030000000A6
+:200AC80085822CE5272522FDE5283523FE752D02903C00E4F0903C00E0600475820022902B
+:200AE800E678E0FB7A0043038090E678EBF0E030E21090000AC006C005121381D005D00634
+:200B080080D3E52C25E0FB90E679F090E678E020E006903C00E060F3903C00E060047582B0
+:200B2800002290E678E020E2AC90E678E020E14090E678E0FB43034090E678EBF090E678FA
+:200B4800E030E606903C00E060F3903C00E0600475820022E52D14FB8B2D7003F5822290F4
+:200B6800000AC006C005121381D005D006020ADD7A007B00C3EA9DEB9E4003020C12C3EAC6
+:200B88009522EB95235016EA2524F8EB3525F9AC26888289838CF01213D8FC801DEAC395E8
+:200BA80022F8EB9523F9E82529F8E9352AF9AF2B888289838FF01213D8FC90E679ECF00ACB
+:200BC800BA00010B90E678E020E006903C00E060F3903C00E060047582002290E678E0304D
+:200BE800E203020ADD90E678E020E18890E678E0FF43074090E678EFF090E678E030E606BA
+:200C0800903C00E060F37582002290E678E0FF43074090E678EFF090E678E030E606903CDA
+:200C280000E060F3903C00E060047582002275820122858233903C00E4F004B52E0814B5A4
+:200C48002F0474018001E4FE903C00E06004758200227C007D0090E678E0FB43038090E65A
+:200C680078EBF0E030E20C90000AC006121381D00680D5E53325E0FB3395E0FA4303019059
+:200C8800E679EBF090E678E020E006903C00E060F3903C00E060047582002290E678E02028
+:200CA800E2A690E678E020E11E90E678E0FB43034090E678EBF090E678E030E606903C00E9
+:200CC800E060F375820022EE600F90E678E0FB7A0043032090E678EBF090E679E0E4F53415
+:200CE800F53574012534F8E43535F9C3E8952EE9952F506C90E678E020E006903C00E060FE
+:200D0800F3903C00E060047582002290E678E030E203020C5074022534F8E43535F9E8B5C3
+:200D28002E13E9B52F0F90E678E0F8790043002090E678E8F0A834A9350534E4B53402055F
+:200D480035AC34AD35E82530F8E93531F9AF3290E679E0FB888289838FF0121326020CEA94
+:200D680090E678E020E006903C00E060F3903C00E060047582002290E678E030E203020C7E
+:200D88005090E678E0FF43074090E678EFF0EC2530FCED3531FDAF3290E679E08C828D837C
+:200DA8008FF012132690E678E030E606903C00E060F3903C00E06004758200227582012235
+:200DC80085823DE4F541F542AB36AC37C3E5419538E54295394003020E597A0090E678E013
+:200DE80030E4067A018C078F3EEA04FFEA243EF98B02A702EF04FAEF243EF9AE41AF420572
+:200E080041E4B541020542EE253AFEEF353BFFAD3C8E828F838DF01213D8F78A22752300FD
+:200E280075243E752500752640E4F527F528F529F52AF52B853D82C004C003120AC8E582CE
+:200E4800D003D0047003F582220BBB00010C020DD475820122AF827E0090E678E030E40670
+:200E68007E01AD448D4AEE04FDEE244AF9AE43A7068D2275230075244A752500752640E4BE
+:200E8800F527F528F529F52AF52B8F82C007120AC8E582D0077003F5822285452E85462FBC
+:190EA8008547308548318549328F82120C3AE5827003F582227582012241
+:06008800E478FFF6D8FD4C
+:1200CE007512007513007514A675153D75161C75173DAB
+:200EC10090E6B9E0FF24F45003020FEFEF240A83F582EF241083F583E473F30FEF2BEFEF12
+:200EE10047EF576E90CA0E0F0F0F0F0F0F0F0F0F0F0F121071E582600302100B90E6A0E079
+:200F0100FF7E0043070190E6A0EFF002100B121105E582600302100B90E6A0E0FF7E004331
+:200F2100070190E6A0EFF002100B121180E582600302100B90E6A0E0FF7E0043070190E6D8
+:200F4100A0EFF002100B1206C9E582600302100B12124102100B1205B8AF8290E740EFF014
+:200F610090E68AE4F090E68B04F002100B90E6BAE0F5821205BCE582600302100B90E6A033
+:200F8100E0FF7E0043070190E6A0EFF002100B90E6BCE0FF754C11754D00754E408F8212CB
+:200FA1000595E582701190E6A0E0FF7E0043070190E6A0EFF0805390E740E511F090E68A8B
+:200FC100E4F090E68B04F0804190E6BCE0FF90E6BAE0F5108F821205AAE582702D90E6A074
+:200FE100E0FF7E0043070190E6A0EFF0801C90E6B9E0F5821206CDE582700F90E6A0E0FF71
+:201001007E0043070190E6A0EFF090E6A0E0FF43078090E6A0EFF022AF82747F5FFE24F79F
+:20102100500302106DEE240A83F582EE240D83F583E473464A5D6D616D656D6910101010B3
+:20104100101010101090E6A022EF30E7067EA27FE680047EA17FE68E828F832290E6A322EF
+:2010610090E6A42290E6A52290E6A6229000002290E6B8E0FFBF80028022BF81028008BF8D
+:20108100820280370210FD90E740E4F090E741F090E68AF090E68B7402F08064E51325E09A
+:2010A100FFE512420790E740EFF090E741E4F090E68AF090E68B7402F0804590E6BCE0F5AB
+:2010C10082121019AE82AF838E048F05EE4F7003F582228C828D83E0FC30E0067E017F0073
+:2010E10080047E007F0090E740EEF090E741E4F090E68AF090E68B7402F080047582002259
+:201101007582012290E6B8E0FF6005BF0264801B90E6BAE0FFBF0105751300805E90E6BA18
+:20112100E0FFBF060280547582002290E6BAE0703D90E6BCE0F582121019AE82AF83E0FD5B
+:201141005305FE8E828F83EDF090E6BCE0FF30E7098F057E004305108D0753071F90E68398
+:20116100EFF07E0043072090E683EFF0800D7582002290E6B9E0F5820206CD758201229024
+:20118100E6B8E0FF6008BF0202802902120990E6BAE0FFBF020302121290E6BAE0FFBF0118
+:2011A10005751301806B90E6BAE0FFBF060280617582002290E6BAE0704A90E6BCE0F58292
+:2011C100121019AE82AF83EE4F7003F582228E828F83E0FD7C004305018E828F83EDF090D5
+:2011E100E6BCE0FF30E7098F057E004305108D0753071F90E683EFF07E0043072090E6831D
+:20120100EFF0800D7582002290E6B9E0F5820206CD75820122AF827E0110AF027E00EF6095
+:201221000E75141C75153D7516A675173D800C7514A675153D75161C75173DEE1392AF22E3
+:2012410090E6BBE0FFBF01028019BF02028024BF0302802CBF06030212FBBF070302130B8B
+:201261000213187E007F3D90E6B3EFF090E6B47400F02290E6B3E515F090E6B4E514F02206
+:201281007DE07E3D7F8090E6BAE0F54C7B008B020BEAB54C0280428D008E018F028D828ED9
+:2012A100838FF01213D828F8E439F9880589068A0774012DF9E43EFA8F0489828A838CF06D
+:2012C1001213D8F9B9030280067D007E007F00ED4E6006C3E54C9B50B5ED4E600F8D038E5C
+:2012E1000490E6B3ECF090E6B4EDF02290E6A0E0FF43070190E6A0EFF0227E127F3D90E6A2
+:20130100B3EFF090E6B47412F02290E6B3E517F090E6B4E516F02290E6A0E0FF430701905C
+:05132100E6A0EFF02240
+:200066007900E94400601B7A0090176B780175923CE493F2A308B800020592D9F4DAF2759E
+:0200860092FFE7
+:1B13260020F71130F6138883A88220F509F6A8837583002280FEF280F5F022C6
+:203F00000201350002143B00021430000201E30002014D000201980002142D000213750034
+:203F200002137700021378000213790002137C0002143A0002143C000213410002134300F9
+:203F400002143200021375000213F40002142E0002142F0002143100021433000214340023
+:203F60000213D7000213750002137500021375000213760002137A0002137D0002137F0077
+:203F800002137B0002137E00021380000213D6000213440002136F00021371000213730093
+:183FA00002134500021370000213720002137400021342000214390074
+:011341003279
+:011342003278
+:011343003277
+:011344003276
+:011345003275
+:20008E007800E84400600A790075923CE4F309D8FC7801E84400600C7901903C00E4F0A306
+:0400AE00D8FCD9FAA7
+:201346007A10E4FBFCE58225E0F582E58333F583EB33FBEC33FCEB954CF5F0EC954D400633
+:09136600FCABF0438201DADD2248
+:01136F00324B
+:01137000324A
+:011371003249
+:011372003248
+:011373003247
+:011374003246
+:011375003245
+:011376003244
+:011377003243
+:011378003242
+:011379003241
+:01137A003240
+:01137B00323F
+:01137C00323E
+:01137D00323D
+:01137E00323C
+:01137F00323B
+:01138000323A
+:20138100AE82AF8390E600E05418C423541F70057CB1FD801C90E600E05418C423541FFB7C
+:2013A100BB01067A617B0180047AC27B028A048B058C4C8D4D154C74FFB54C02154DE54C9C
+:1513C100454D70F1EE24FFFAEF34FFFB8A068B07EA4B70DD2236
+:0113D60032E4
+:0113D70032E3
+:0D00590075815B121435E5826003020056CC
+:1C13D80020F71430F6148883A88220F507E6A88375830022E280F7E49322E02224
+:0113F40032C6
+:2013F500C2D5E58330E70DD2D5E4C39582F582E49583F583E54D30E70DB2D5E4C3954CF50B
+:181415004CE4954DF54D12134630D50BE4C39582F582E49583F5832225
+:01142D00328C
+:01142E00328B
+:01142F00328A
+:011430003289
+:011431003288
+:011432003287
+:011433003286
+:011434003285
+:04143500758200229A
+:011439003280
+:01143A00327F
+:01143B00327E
+:01143C00327D
+:00000001FF
diff --git a/openhantek/res/firmware/dso6022bl-loader.hex b/openhantek/res/firmware/dso6022bl-loader.hex
deleted file mode 100644
index d7758b6f..00000000
--- a/openhantek/res/firmware/dso6022bl-loader.hex
+++ /dev/null
@@ -1,60 +0,0 @@
-:1003680090E668E0FF74FFF0E0B40B04EFF0D322EE
-:0603780090E668EFF0C3FF
-:01037E00225C
-:1001B500907FE9E064A360030202C5A3E07508002F
-:1001C500F509A3E0FEE4EE4208907FEEE0750A0033
-:1001D500F50BA3E0FEE4EE420A907FE8E064407090
-:1001E50064E50B450A70030202D6E4907FC5F090E2
-:1001F5007FB4E020E3F9907FC5E0750C00F50DE4D0
-:10020500FCFDC3ED950DEC950C501F74C02DF582CA
-:10021500E4347EF583E0FFE5092DF582E5083CF53C
-:1002250083EFF00DBD00010C80D8E50D2509F5091A
-:10023500E50C3508F508C3E50B950DF50BE50A95B5
-:100245000CF50A809C907FE8E064C060030202D64A
-:10025500E50B450A607BC3E50B9440E50A94005025
-:1002650008850A0C850B0D8006750C00750D40E49C
-:10027500FCFDC3ED950DEC950C501FE5092DF582A0
-:10028500E5083CF583E0FF74002DF582E4347FF545
-:1002950083EFF00DBD00010C80D8907FB5E50DF022
-:1002A5002509F509E50C3508F508C3E50B950DF5A8
-:1002B5000BE50A950CF50A907FB4E030E29280F7E1
-:1002C500907FE9E0B4AC0AE4907F00F0907FB5043C
-:0802D500F0907FB4E04402F058
-:0102DD0022FE
-:1000800090E6B9E064A36003020198A3E07508005C
-:10009000F509A3E0FEE4EE420890E6BEE0750A0032
-:1000A000F50BA3E0FEE4EE420A90E6B8E06440708F
-:1000B00066E50B450A70030201ADE490E68AF0A301
-:1000C000F090E6A0E020E1F990E68BE0750C00F5F9
-:1000D0000DE4FCFDC3ED950DEC950C501F74402D07
-:1000E000F582E434E7F583E0FFE5092DF582E508C4
-:1000F0003CF583EFF00DBD00010C80D8E50D25091E
-:10010000F509E50C3508F508C3E50B950DF50BE58C
-:100110000A950CF50A809A90E6B8E064C060030284
-:1001200001ADE50B450A70030201ADC3E50B944038
-:10013000E50A94005008850A0C850B0D8006750CA5
-:1001400000750D40E4FCFDC3ED950DEC950C501FC2
-:10015000E5092DF582E5083CF583E0FF74402DF5B7
-:1001600082E434E7F583EFF00DBD00010C80D8E4A4
-:1001700090E68AF0A3E50DF02509F509E50C3508B0
-:10018000F508C3E50B950DF50BE50A950CF50A90FE
-:10019000E6A0E030E18C80F790E6B9E0B4AC0E90D8
-:1001A000E7407401F0E490E68AF0A304F090E6A042
-:0401B000E04480F0B7
-:0101B4002228
-:1002DE00C2011203689200907F95E044C0F0D2E80C
-:1002EE0030000890E65D74FFF08006907FAB74FFDF
-:1002FE00F030000890E6687408F08007907FAFE059
-:10030E004401F030000890E65C7401F08006907FA6
-:10031E00AE7401F0D2AF3001FD30000512008080C6
-:08032E00031201B5C20180EECB
-:03000300020336BF
-:10033600C0E0C083C082C085C084C086758600D2F6
-:10034600015391EF30000890E65D7401F08006904D
-:100356007FAB7401F0D086D084D085D082D083D094
-:02036600E03283
-:03004300020400B4
-:0404000002033600BD
-:0300000002037F79
-:0C037F00787FE4F6D8FD7581200202DED4
-:00000001FF
diff --git a/openhantek/res/firmwares.qrc b/openhantek/res/firmwares.qrc
index 3bf4b4ce..6f9e3254 100644
--- a/openhantek/res/firmwares.qrc
+++ b/openhantek/res/firmwares.qrc
@@ -1,18 +1,7 @@
- firmware/dso2090x86-firmware.hex
- firmware/dso2090x86-loader.hex
- firmware/dso2150x86-firmware.hex
- firmware/dso2150x86-loader.hex
- firmware/dso2250x86-firmware.hex
- firmware/dso2250x86-loader.hex
- firmware/dso5200ax86-firmware.hex
- firmware/dso5200ax86-loader.hex
- firmware/dso5200x86-firmware.hex
- firmware/dso5200x86-loader.hexfirmware/dso6022be-firmware.hex
- firmware/dso6022be-loader.hexfirmware/dso6022bl-firmware.hex
- firmware/dso6022bl-loader.hex
+ firmware/dds120-firmware.hex
diff --git a/openhantek/res/images/OpenHantek.ico b/openhantek/res/images/OpenHantek.ico
new file mode 100644
index 00000000..8baebe72
Binary files /dev/null and b/openhantek/res/images/OpenHantek.ico differ
diff --git a/openhantek/res/images/OpenHantek.png b/openhantek/res/images/OpenHantek.png
new file mode 100644
index 00000000..d96497e1
Binary files /dev/null and b/openhantek/res/images/OpenHantek.png differ
diff --git a/openhantek/res/images/openhantek.svg b/openhantek/res/images/OpenHantek.svg
similarity index 53%
rename from openhantek/res/images/openhantek.svg
rename to openhantek/res/images/OpenHantek.svg
index 5fbd1d0d..834b1920 100644
--- a/openhantek/res/images/openhantek.svg
+++ b/openhantek/res/images/OpenHantek.svg
@@ -13,11 +13,11 @@
height="48"
id="svg2"
version="1.1"
- inkscape:version="0.47pre4 r22446"
- sodipodi:docname="hantekdso.svg"
- inkscape:export-filename="/home/oliver/Entwicklung/Qt/HantekDSO/res/images/hantekdso.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="OpenHantek.svg"
+ inkscape:export-filename="/home/horo/projects/Measure/OpenHantek/OpenHantek6022/openhantek/res/images/OpenHantek.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96">
-
-
-
+ inkscape:window-x="265"
+ inkscape:window-y="19"
+ inkscape:window-maximized="0"
+ inkscape:showpageshadow="false"
+ showborder="true"
+ borderlayer="true">
image/svg+xml
-
+
@@ -94,45 +89,42 @@
id="layer1"
transform="translate(0,-1004.3622)">
-
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:connector-curvature="0" />
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ width="46"
+ height="46.000076"
+ x="1"
+ y="1005.3622" />
diff --git a/openhantek/res/images/config/analysis.png b/openhantek/res/images/config/analysis.png
deleted file mode 100644
index 4c2a1f03..00000000
Binary files a/openhantek/res/images/config/analysis.png and /dev/null differ
diff --git a/openhantek/res/images/config/analysis.svg b/openhantek/res/images/config/analysis.svg
deleted file mode 100644
index bc218f04..00000000
--- a/openhantek/res/images/config/analysis.svg
+++ /dev/null
@@ -1,5877 +0,0 @@
-
-
-
-
-
-
diff --git a/openhantek/res/images/config/colors.png b/openhantek/res/images/config/colors.png
index b3c35485..890c4bee 100644
Binary files a/openhantek/res/images/config/colors.png and b/openhantek/res/images/config/colors.png differ
diff --git a/openhantek/res/images/config/files.png b/openhantek/res/images/config/files.png
deleted file mode 100644
index 3f55aa61..00000000
Binary files a/openhantek/res/images/config/files.png and /dev/null differ
diff --git a/openhantek/res/images/config/options.png b/openhantek/res/images/config/options.png
index 11a0c22e..3c66b38e 100644
Binary files a/openhantek/res/images/config/options.png and b/openhantek/res/images/config/options.png differ
diff --git a/openhantek/res/images/config/options.svg b/openhantek/res/images/config/options.svg
deleted file mode 100644
index 20c28a59..00000000
--- a/openhantek/res/images/config/options.svg
+++ /dev/null
@@ -1,580 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/openhantek/res/images/config/scope.png b/openhantek/res/images/config/scope.png
index 09da8624..a16053f5 100644
Binary files a/openhantek/res/images/config/scope.png and b/openhantek/res/images/config/scope.png differ
diff --git a/openhantek/res/images/config/scope.svg b/openhantek/res/images/config/scope.svg
new file mode 100644
index 00000000..d722ccdf
--- /dev/null
+++ b/openhantek/res/images/config/scope.svg
@@ -0,0 +1,97 @@
+
+
+
+
diff --git a/openhantek/res/images/config/spectrum.png b/openhantek/res/images/config/spectrum.png
new file mode 100644
index 00000000..b6369c78
Binary files /dev/null and b/openhantek/res/images/config/spectrum.png differ
diff --git a/openhantek/res/images/darktheme/histogram.svg b/openhantek/res/images/darktheme/histogram.svg
new file mode 100644
index 00000000..f2bd5893
--- /dev/null
+++ b/openhantek/res/images/darktheme/histogram.svg
@@ -0,0 +1,92 @@
+
+
diff --git a/openhantek/res/images/darktheme/measure.svg b/openhantek/res/images/darktheme/measure.svg
new file mode 100644
index 00000000..6d8c08ae
--- /dev/null
+++ b/openhantek/res/images/darktheme/measure.svg
@@ -0,0 +1,58 @@
+
+
diff --git a/openhantek/res/images/darktheme/pause.svg b/openhantek/res/images/darktheme/pause.svg
new file mode 100644
index 00000000..fae1825e
--- /dev/null
+++ b/openhantek/res/images/darktheme/pause.svg
@@ -0,0 +1,67 @@
+
+
diff --git a/openhantek/res/images/darktheme/phosphor.svg b/openhantek/res/images/darktheme/phosphor.svg
new file mode 100644
index 00000000..9359f803
--- /dev/null
+++ b/openhantek/res/images/darktheme/phosphor.svg
@@ -0,0 +1,133 @@
+
+
+
+
diff --git a/openhantek/res/images/darktheme/play.svg b/openhantek/res/images/darktheme/play.svg
new file mode 100644
index 00000000..2c49c0d7
--- /dev/null
+++ b/openhantek/res/images/darktheme/play.svg
@@ -0,0 +1,64 @@
+
+
diff --git a/openhantek/res/images/darktheme/refresh.svg b/openhantek/res/images/darktheme/refresh.svg
new file mode 100644
index 00000000..536c4928
--- /dev/null
+++ b/openhantek/res/images/darktheme/refresh.svg
@@ -0,0 +1,59 @@
+
+
diff --git a/openhantek/res/images/darktheme/zoom.svg b/openhantek/res/images/darktheme/zoom.svg
new file mode 100644
index 00000000..9e941335
--- /dev/null
+++ b/openhantek/res/images/darktheme/zoom.svg
@@ -0,0 +1,58 @@
+
+
diff --git a/openhantek/res/images/digitalphosphor.png b/openhantek/res/images/digitalphosphor.png
deleted file mode 100644
index bf04c5f5..00000000
Binary files a/openhantek/res/images/digitalphosphor.png and /dev/null differ
diff --git a/openhantek/res/images/histogram.svg b/openhantek/res/images/histogram.svg
new file mode 100644
index 00000000..2c919e56
--- /dev/null
+++ b/openhantek/res/images/histogram.svg
@@ -0,0 +1,92 @@
+
+
diff --git a/openhantek/res/images/measure.svg b/openhantek/res/images/measure.svg
new file mode 100644
index 00000000..f574511e
--- /dev/null
+++ b/openhantek/res/images/measure.svg
@@ -0,0 +1,58 @@
+
+
diff --git a/openhantek/res/images/openhantek.png b/openhantek/res/images/openhantek.png
deleted file mode 100644
index f492e4d9..00000000
Binary files a/openhantek/res/images/openhantek.png and /dev/null differ
diff --git a/openhantek/res/images/pause.svg b/openhantek/res/images/pause.svg
new file mode 100644
index 00000000..ce5241e0
--- /dev/null
+++ b/openhantek/res/images/pause.svg
@@ -0,0 +1,67 @@
+
+
diff --git a/openhantek/res/images/digitalphosphor.svg b/openhantek/res/images/phosphor.svg
similarity index 59%
rename from openhantek/res/images/digitalphosphor.svg
rename to openhantek/res/images/phosphor.svg
index a06679e3..c3fb68fc 100644
--- a/openhantek/res/images/digitalphosphor.svg
+++ b/openhantek/res/images/phosphor.svg
@@ -9,13 +9,13 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16"
- height="16"
+ width="64"
+ height="64"
id="svg2816"
version="1.1"
- inkscape:version="0.47pre4 r22446"
- sodipodi:docname="digitalphosphor.svg"
- inkscape:export-filename="/home/oliver/Entwicklung/Qt/HantekDSO/res/images/actions/digitalphosphor.png"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="phosphor.svg"
+ inkscape:export-filename="phosphor.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
+ inkscape:window-x="2664"
+ inkscape:window-y="169"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ objecttolerance="10000"
+ guidetolerance="10000"
+ gridtolerance="10000"
+ inkscape:pagecheckerboard="true"
+ inkscape:showpageshadow="false">
+ snapvisiblegridlinesonly="true"
+ originx="0.2764286"
+ originy="2.5898968" />
@@ -99,22 +110,24 @@
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
- transform="translate(0,-32)">
+ transform="translate(1.0234618,12.41009)">
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
diff --git a/openhantek/res/images/play.svg b/openhantek/res/images/play.svg
new file mode 100644
index 00000000..eba88f39
--- /dev/null
+++ b/openhantek/res/images/play.svg
@@ -0,0 +1,64 @@
+
+
diff --git a/openhantek/res/images/refresh.svg b/openhantek/res/images/refresh.svg
new file mode 100644
index 00000000..62ef4179
--- /dev/null
+++ b/openhantek/res/images/refresh.svg
@@ -0,0 +1,59 @@
+
+
diff --git a/openhantek/res/images/switch.png b/openhantek/res/images/switch_6022BL.png
similarity index 94%
rename from openhantek/res/images/switch.png
rename to openhantek/res/images/switch_6022BL.png
index 11e8a768..61cc8070 100644
Binary files a/openhantek/res/images/switch.png and b/openhantek/res/images/switch_6022BL.png differ
diff --git a/openhantek/res/images/zoom.svg b/openhantek/res/images/zoom.svg
new file mode 100644
index 00000000..da6756b8
--- /dev/null
+++ b/openhantek/res/images/zoom.svg
@@ -0,0 +1,58 @@
+
+
diff --git a/openhantek/src/OH_BUILD.h b/openhantek/src/OH_BUILD.h
new file mode 100644
index 00000000..8ef6427d
--- /dev/null
+++ b/openhantek/src/OH_BUILD.h
@@ -0,0 +1,2 @@
+// Do not edit, will be re-created at each commit!
+#define OH_BUILD "20201020 build 741"
diff --git a/openhantek/src/OH_VERSION.h b/openhantek/src/OH_VERSION.h
new file mode 100644
index 00000000..597a9352
--- /dev/null
+++ b/openhantek/src/OH_VERSION.h
@@ -0,0 +1,15 @@
+// define the version that is shown on top of the program
+// if undefined (for development commits) the build will be shown by OpenHantek
+
+// #define OH_VERSION "3.1.4-rc1"
+
+#ifdef OH_VERSION
+#undef VERSION
+#define VERSION OH_VERSION
+#else
+#include "OH_BUILD.h"
+#ifdef OH_BUILD
+#undef VERSION
+#define VERSION OH_BUILD
+#endif
+#endif
diff --git a/openhantek/src/configdialog/DsoConfigAnalysisPage.cpp b/openhantek/src/configdialog/DsoConfigAnalysisPage.cpp
deleted file mode 100644
index 5c02fc23..00000000
--- a/openhantek/src/configdialog/DsoConfigAnalysisPage.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include "DsoConfigAnalysisPage.h"
-
-DsoConfigAnalysisPage::DsoConfigAnalysisPage(DsoSettings *settings, QWidget *parent)
- : QWidget(parent), settings(settings) {
- // Initialize lists for comboboxes
- QStringList windowFunctionStrings;
- windowFunctionStrings << tr("Rectangular") << tr("Hamming") << tr("Hann") << tr("Cosine") << tr("Lanczos")
- << tr("Bartlett") << tr("Triangular") << tr("Gauss") << tr("Bartlett-Hann") << tr("Blackman")
- //<< tr("Kaiser")
- << tr("Nuttall") << tr("Blackman-Harris") << tr("Blackman-Nuttall") << tr("Flat top");
-
- // Initialize elements
- windowFunctionLabel = new QLabel(tr("Window function"));
- windowFunctionComboBox = new QComboBox();
- windowFunctionComboBox->addItems(windowFunctionStrings);
- windowFunctionComboBox->setCurrentIndex((int)settings->post.spectrumWindow);
-
- referenceLevelLabel = new QLabel(tr("Reference level"));
- referenceLevelSpinBox = new QDoubleSpinBox();
- referenceLevelSpinBox->setDecimals(1);
- referenceLevelSpinBox->setMinimum(-40.0);
- referenceLevelSpinBox->setMaximum(100.0);
- referenceLevelSpinBox->setValue(settings->post.spectrumReference);
- referenceLevelUnitLabel = new QLabel(tr("dBm"));
- referenceLevelLayout = new QHBoxLayout();
- referenceLevelLayout->addWidget(referenceLevelSpinBox);
- referenceLevelLayout->addWidget(referenceLevelUnitLabel);
-
- minimumMagnitudeLabel = new QLabel(tr("Minimum magnitude"));
- minimumMagnitudeSpinBox = new QDoubleSpinBox();
- minimumMagnitudeSpinBox->setDecimals(1);
- minimumMagnitudeSpinBox->setMinimum(-40.0);
- minimumMagnitudeSpinBox->setMaximum(100.0);
- minimumMagnitudeSpinBox->setValue(settings->post.spectrumLimit);
- minimumMagnitudeUnitLabel = new QLabel(tr("dBm"));
- minimumMagnitudeLayout = new QHBoxLayout();
- minimumMagnitudeLayout->addWidget(minimumMagnitudeSpinBox);
- minimumMagnitudeLayout->addWidget(minimumMagnitudeUnitLabel);
-
- spectrumLayout = new QGridLayout();
- spectrumLayout->addWidget(windowFunctionLabel, 0, 0);
- spectrumLayout->addWidget(windowFunctionComboBox, 0, 1);
- spectrumLayout->addWidget(referenceLevelLabel, 1, 0);
- spectrumLayout->addLayout(referenceLevelLayout, 1, 1);
- spectrumLayout->addWidget(minimumMagnitudeLabel, 2, 0);
- spectrumLayout->addLayout(minimumMagnitudeLayout, 2, 1);
-
- spectrumGroup = new QGroupBox(tr("Spectrum"));
- spectrumGroup->setLayout(spectrumLayout);
-
- mainLayout = new QVBoxLayout();
- mainLayout->addWidget(spectrumGroup);
- mainLayout->addStretch(1);
-
- setLayout(mainLayout);
-}
-
-/// \brief Saves the new settings.
-void DsoConfigAnalysisPage::saveSettings() {
- settings->post.spectrumWindow = (Dso::WindowFunction)windowFunctionComboBox->currentIndex();
- settings->post.spectrumReference = referenceLevelSpinBox->value();
- settings->post.spectrumLimit = minimumMagnitudeSpinBox->value();
-}
diff --git a/openhantek/src/configdialog/DsoConfigColorsPage.cpp b/openhantek/src/configdialog/DsoConfigColorsPage.cpp
index 85e96e7c..120f6560 100644
--- a/openhantek/src/configdialog/DsoConfigColorsPage.cpp
+++ b/openhantek/src/configdialog/DsoConfigColorsPage.cpp
@@ -2,127 +2,137 @@
#include "DsoConfigColorsPage.h"
-DsoConfigColorsPage::DsoConfigColorsPage(DsoSettings *settings, QWidget *parent) : QWidget(parent), settings(settings) {
+DsoConfigColorsPage::DsoConfigColorsPage( DsoSettings *settings, QWidget *parent ) : QWidget( parent ), settings( settings ) {
// Initialize elements
DsoSettingsView &colorSettings = settings->view;
enum { COL_LABEL = 0, COL_SCR_CHANNEL, COL_SCR_SPECTRUM, COL_PRT_CHANNEL, COL_PRT_SPECTRUM };
// Plot Area
- graphLabel = new QLabel(tr("")); // 4*80
- graphLabel->setAlignment(Qt::AlignRight);
- graphLabel->setTextFormat(Qt::RichText);
+ screenColorsLabel = new QLabel( tr( "Screen" ) );
+ screenColorsLabel->setAlignment( Qt::AlignHCenter );
+ printColorsLabel = new QLabel( tr( "Print" ) );
+ printColorsLabel->setAlignment( Qt::AlignHCenter );
- screenColorsLabel = new QLabel(tr("Screen"));
- screenColorsLabel->setAlignment(Qt::AlignHCenter);
- printColorsLabel = new QLabel(tr("Print"));
- printColorsLabel->setAlignment(Qt::AlignHCenter);
+ backgroundLabel = new QLabel( tr( "Background" ) );
+ backgroundColorBox = new ColorBox( colorSettings.screen.background );
+ printBackgroundColorBox = new ColorBox( colorSettings.print.background );
- axesLabel = new QLabel(tr("Axes"));
- axesColorBox = new ColorBox(colorSettings.screen.axes);
- printAxesColorBox = new ColorBox(colorSettings.print.axes);
+ gridLabel = new QLabel( tr( "Grid" ) );
+ gridColorBox = new ColorBox( colorSettings.screen.grid );
+ printGridColorBox = new ColorBox( colorSettings.print.grid );
- backgroundLabel = new QLabel(tr("Background"));
- backgroundColorBox = new ColorBox(colorSettings.screen.background);
- printBackgroundColorBox = new ColorBox(colorSettings.print.background);
+ axesLabel = new QLabel( tr( "Axes" ) );
+ axesColorBox = new ColorBox( colorSettings.screen.axes );
+ printAxesColorBox = new ColorBox( colorSettings.print.axes );
- borderLabel = new QLabel(tr("Border"));
- borderColorBox = new ColorBox(colorSettings.screen.border);
- printBorderColorBox = new ColorBox(colorSettings.print.border);
+ borderLabel = new QLabel( tr( "Border" ) );
+ borderColorBox = new ColorBox( colorSettings.screen.border );
+ printBorderColorBox = new ColorBox( colorSettings.print.border );
- gridLabel = new QLabel(tr("Grid"));
- gridColorBox = new ColorBox(colorSettings.screen.grid);
- printGridColorBox = new ColorBox(colorSettings.print.grid);
+ markersLabel = new QLabel( tr( "Markers" ) );
+ markersColorBox = new ColorBox( colorSettings.screen.markers );
+ printMarkersColorBox = new ColorBox( colorSettings.print.markers );
- markersLabel = new QLabel(tr("Markers"));
- markersColorBox = new ColorBox(colorSettings.screen.markers);
- printMarkersColorBox = new ColorBox(colorSettings.print.markers);
-
- textLabel = new QLabel(tr("Text"));
- textColorBox = new ColorBox(colorSettings.screen.text);
- printTextColorBox = new ColorBox(colorSettings.print.text);
+ textLabel = new QLabel( tr( "Text" ) );
+ textColorBox = new ColorBox( colorSettings.screen.text );
+ printTextColorBox = new ColorBox( colorSettings.print.text );
// Graph category
- screenChannelLabel = new QLabel(tr("Channel"));
- screenChannelLabel->setAlignment(Qt::AlignHCenter);
- screenSpectrumLabel = new QLabel(tr("Spectrum"));
- screenSpectrumLabel->setAlignment(Qt::AlignHCenter);
- printChannelLabel = new QLabel(tr("Channel"));
- printChannelLabel->setAlignment(Qt::AlignHCenter);
- printSpectrumLabel = new QLabel(tr("Spectrum"));
- printSpectrumLabel->setAlignment(Qt::AlignHCenter);
-
- for (ChannelID channel = 0; channel < settings->scope.voltage.size(); ++channel) {
- colorLabel.push_back(new QLabel(settings->scope.voltage[channel].name));
- screenChannelColorBox.push_back(new ColorBox(colorSettings.screen.voltage[channel]));
- screenSpectrumColorBox.push_back(new ColorBox(colorSettings.screen.spectrum[channel]));
- printChannelColorBox.push_back(new ColorBox(colorSettings.print.voltage[channel]));
- printSpectrumColorBox.push_back(new ColorBox(colorSettings.print.spectrum[channel]));
+ screenChannelLabel = new QLabel( tr( "Channel" ) );
+ screenChannelLabel->setAlignment( Qt::AlignHCenter );
+ screenSpectrumLabel = new QLabel( tr( "Spectrum" ) );
+ screenSpectrumLabel->setAlignment( Qt::AlignHCenter );
+ printChannelLabel = new QLabel( tr( "Channel" ) );
+ printChannelLabel->setAlignment( Qt::AlignHCenter );
+ printSpectrumLabel = new QLabel( tr( "Spectrum" ) );
+ printSpectrumLabel->setAlignment( Qt::AlignHCenter );
+
+ for ( ChannelID channel = 0; channel < settings->scope.voltage.size(); ++channel ) {
+ colorLabel.push_back( new QLabel( settings->scope.voltage[ channel ].name ) );
+ screenChannelColorBox.push_back( new ColorBox( colorSettings.screen.voltage[ channel ] ) );
+ screenSpectrumColorBox.push_back( new ColorBox( colorSettings.screen.spectrum[ channel ] ) );
+ printChannelColorBox.push_back( new ColorBox( colorSettings.print.voltage[ channel ] ) );
+ printSpectrumColorBox.push_back( new ColorBox( colorSettings.print.spectrum[ channel ] ) );
}
// Plot Area Layout
colorsLayout = new QGridLayout();
- colorsLayout->setColumnStretch(COL_LABEL, 1);
- colorsLayout->setColumnMinimumWidth(COL_SCR_CHANNEL, 80);
- colorsLayout->setColumnMinimumWidth(COL_SCR_SPECTRUM, 80);
- colorsLayout->setColumnMinimumWidth(COL_PRT_CHANNEL, 80);
- colorsLayout->setColumnMinimumWidth(COL_PRT_SPECTRUM, 80);
+ colorsLayout->setColumnStretch( COL_LABEL, 1 );
+ colorsLayout->setColumnMinimumWidth( COL_SCR_CHANNEL, 80 );
+ colorsLayout->setColumnMinimumWidth( COL_SCR_SPECTRUM, 80 );
+ colorsLayout->setColumnMinimumWidth( COL_PRT_CHANNEL, 80 );
+ colorsLayout->setColumnMinimumWidth( COL_PRT_SPECTRUM, 80 );
int row = 0;
- colorsLayout->addWidget(screenColorsLabel, row, COL_SCR_CHANNEL, 1, 2);
- colorsLayout->addWidget(printColorsLabel, row, COL_PRT_CHANNEL, 1, 2);
+ colorsLayout->addWidget( screenColorsLabel, row, COL_SCR_CHANNEL, 1, 2 );
+ colorsLayout->addWidget( printColorsLabel, row, COL_PRT_CHANNEL, 1, 2 );
++row;
- colorsLayout->addWidget(backgroundLabel, row, COL_LABEL);
- colorsLayout->addWidget(backgroundColorBox, row, COL_SCR_CHANNEL, 1, 2);
- colorsLayout->addWidget(printBackgroundColorBox, row, COL_PRT_CHANNEL, 1, 2);
+ colorsLayout->addWidget( backgroundLabel, row, COL_LABEL );
+ colorsLayout->addWidget( backgroundColorBox, row, COL_SCR_CHANNEL, 1, 2 );
+ colorsLayout->addWidget( printBackgroundColorBox, row, COL_PRT_CHANNEL, 1, 2 );
++row;
- colorsLayout->addWidget(gridLabel, row, COL_LABEL);
- colorsLayout->addWidget(gridColorBox, row, COL_SCR_CHANNEL, 1, 2);
- colorsLayout->addWidget(printGridColorBox, row, COL_PRT_CHANNEL, 1, 2);
+ colorsLayout->addWidget( gridLabel, row, COL_LABEL );
+ colorsLayout->addWidget( gridColorBox, row, COL_SCR_CHANNEL, 1, 2 );
+ colorsLayout->addWidget( printGridColorBox, row, COL_PRT_CHANNEL, 1, 2 );
++row;
- colorsLayout->addWidget(axesLabel, row, COL_LABEL);
- colorsLayout->addWidget(axesColorBox, row, COL_SCR_CHANNEL, 1, 2);
- colorsLayout->addWidget(printAxesColorBox, row, COL_PRT_CHANNEL, 1, 2);
+ colorsLayout->addWidget( axesLabel, row, COL_LABEL );
+ colorsLayout->addWidget( axesColorBox, row, COL_SCR_CHANNEL, 1, 2 );
+ colorsLayout->addWidget( printAxesColorBox, row, COL_PRT_CHANNEL, 1, 2 );
++row;
- colorsLayout->addWidget(borderLabel, row, COL_LABEL);
- colorsLayout->addWidget(borderColorBox, row, COL_SCR_CHANNEL, 1, 2);
- colorsLayout->addWidget(printBorderColorBox, row, COL_PRT_CHANNEL, 1, 2);
+ colorsLayout->addWidget( borderLabel, row, COL_LABEL );
+ colorsLayout->addWidget( borderColorBox, row, COL_SCR_CHANNEL, 1, 2 );
+ colorsLayout->addWidget( printBorderColorBox, row, COL_PRT_CHANNEL, 1, 2 );
++row;
- colorsLayout->addWidget(markersLabel, row, COL_LABEL);
- colorsLayout->addWidget(markersColorBox, row, COL_SCR_CHANNEL, 1, 2);
- colorsLayout->addWidget(printMarkersColorBox, row, COL_PRT_CHANNEL, 1, 2);
+ colorsLayout->addWidget( markersLabel, row, COL_LABEL );
+ colorsLayout->addWidget( markersColorBox, row, COL_SCR_CHANNEL, 1, 2 );
+ colorsLayout->addWidget( printMarkersColorBox, row, COL_PRT_CHANNEL, 1, 2 );
++row;
- colorsLayout->addWidget(textLabel, row, COL_LABEL);
- colorsLayout->addWidget(textColorBox, row, COL_SCR_CHANNEL, 1, 2);
- colorsLayout->addWidget(printTextColorBox, row, COL_PRT_CHANNEL, 1, 2);
+ colorsLayout->addWidget( textLabel, row, COL_LABEL );
+ colorsLayout->addWidget( textColorBox, row, COL_SCR_CHANNEL, 1, 2 );
+ colorsLayout->addWidget( printTextColorBox, row, COL_PRT_CHANNEL, 1, 2 );
++row;
- // Graph
- colorsLayout->addWidget(graphLabel, row, COL_LABEL, 1, COL_PRT_SPECTRUM - COL_LABEL + 1);
+ // horizontal line
+ horizontalLine = new QLabel( "" );
+ horizontalLine->setAlignment( Qt::AlignRight );
+ horizontalLine->setTextFormat( Qt::RichText );
+ colorsLayout->addWidget( horizontalLine, row, COL_LABEL, 1, COL_PRT_SPECTRUM - COL_LABEL + 1 );
++row;
- colorsLayout->addWidget(screenChannelLabel, row, COL_SCR_CHANNEL);
- colorsLayout->addWidget(screenSpectrumLabel, row, COL_SCR_SPECTRUM);
- colorsLayout->addWidget(printChannelLabel, row, COL_PRT_CHANNEL);
- colorsLayout->addWidget(printSpectrumLabel, row, COL_PRT_SPECTRUM);
+ colorsLayout->addWidget( screenChannelLabel, row, COL_SCR_CHANNEL );
+ colorsLayout->addWidget( screenSpectrumLabel, row, COL_SCR_SPECTRUM );
+ colorsLayout->addWidget( printChannelLabel, row, COL_PRT_CHANNEL );
+ colorsLayout->addWidget( printSpectrumLabel, row, COL_PRT_SPECTRUM );
++row;
- for (ChannelID channel = 0; channel < settings->scope.voltage.size(); ++channel, ++row) {
- colorsLayout->addWidget(colorLabel[channel], row, COL_LABEL);
- colorsLayout->addWidget(screenChannelColorBox[channel], row, COL_SCR_CHANNEL);
- colorsLayout->addWidget(screenSpectrumColorBox[channel], row, COL_SCR_SPECTRUM);
- colorsLayout->addWidget(printChannelColorBox[channel], row, COL_PRT_CHANNEL);
- colorsLayout->addWidget(printSpectrumColorBox[channel], row, COL_PRT_SPECTRUM);
+ for ( ChannelID channel = 0; channel < settings->scope.voltage.size(); ++channel, ++row ) {
+ colorsLayout->addWidget( colorLabel[ channel ], row, COL_LABEL );
+ colorsLayout->addWidget( screenChannelColorBox[ channel ], row, COL_SCR_CHANNEL );
+ colorsLayout->addWidget( screenSpectrumColorBox[ channel ], row, COL_SCR_SPECTRUM );
+ colorsLayout->addWidget( printChannelColorBox[ channel ], row, COL_PRT_CHANNEL );
+ colorsLayout->addWidget( printSpectrumColorBox[ channel ], row, COL_PRT_SPECTRUM );
}
- colorsGroup = new QGroupBox(tr("Screen and Print Colors"));
- colorsGroup->setLayout(colorsLayout);
+ // horizontal line
+ horizontalLine = new QLabel( "" );
+ horizontalLine->setAlignment( Qt::AlignRight );
+ horizontalLine->setTextFormat( Qt::RichText );
+
+ colorsLayout->addWidget( horizontalLine, ++row, COL_LABEL, 1, COL_PRT_SPECTRUM - COL_LABEL + 1 );
+
+ screenColorCheckBox = new QCheckBox( tr( "Export hardcopy images or pdf files with printer colors" ) );
+ screenColorCheckBox->setChecked( settings->view.printerColorImages );
+ colorsLayout->addWidget( screenColorCheckBox, ++row, COL_LABEL );
+
+ colorsGroup = new QGroupBox( tr( "Screen and Print Colors" ) );
+ colorsGroup->setLayout( colorsLayout );
// Main layout
mainLayout = new QVBoxLayout();
- mainLayout->addWidget(colorsGroup);
- mainLayout->addStretch(1);
+ mainLayout->addWidget( colorsGroup );
+ mainLayout->addStretch( 1 );
- setLayout(mainLayout);
+ setLayout( mainLayout );
}
/// \brief Saves the new settings.
@@ -146,10 +156,11 @@ void DsoConfigColorsPage::saveSettings() {
colorSettings.print.text = printTextColorBox->getColor();
// Graph category
- for (ChannelID channel = 0; channel < settings->scope.voltage.size(); ++channel) {
- colorSettings.screen.voltage[channel] = screenChannelColorBox[channel]->getColor();
- colorSettings.screen.spectrum[channel] = screenSpectrumColorBox[channel]->getColor();
- colorSettings.print.voltage[channel] = printChannelColorBox[channel]->getColor();
- colorSettings.print.spectrum[channel] = printSpectrumColorBox[channel]->getColor();
+ for ( ChannelID channel = 0; channel < settings->scope.voltage.size(); ++channel ) {
+ colorSettings.screen.voltage[ channel ] = screenChannelColorBox[ channel ]->getColor();
+ colorSettings.screen.spectrum[ channel ] = screenSpectrumColorBox[ channel ]->getColor();
+ colorSettings.print.voltage[ channel ] = printChannelColorBox[ channel ]->getColor();
+ colorSettings.print.spectrum[ channel ] = printSpectrumColorBox[ channel ]->getColor();
}
+ settings->view.printerColorImages = screenColorCheckBox->isChecked();
}
diff --git a/openhantek/src/configdialog/DsoConfigColorsPage.h b/openhantek/src/configdialog/DsoConfigColorsPage.h
index 00075428..6571c467 100644
--- a/openhantek/src/configdialog/DsoConfigColorsPage.h
+++ b/openhantek/src/configdialog/DsoConfigColorsPage.h
@@ -2,7 +2,7 @@
#include
-#include "settings.h"
+#include "dsosettings.h"
#include
#include
@@ -23,7 +23,7 @@ class DsoConfigColorsPage : public QWidget {
Q_OBJECT
public:
- DsoConfigColorsPage(DsoSettings *settings, QWidget *parent = 0);
+ DsoConfigColorsPage( DsoSettings *settings, QWidget *parent = nullptr );
public slots:
void saveSettings();
@@ -40,15 +40,16 @@ class DsoConfigColorsPage : public QWidget {
QLabel *axesLabel, *backgroundLabel, *borderLabel, *gridLabel, *markersLabel, *textLabel;
ColorBox *axesColorBox, *backgroundColorBox, *borderColorBox, *gridColorBox, *markersColorBox, *textColorBox;
- ColorBox *printAxesColorBox, *printBackgroundColorBox, *printBorderColorBox, *printGridColorBox,
- *printMarkersColorBox, *printTextColorBox;
+ ColorBox *printAxesColorBox, *printBackgroundColorBox, *printBorderColorBox, *printGridColorBox, *printMarkersColorBox,
+ *printTextColorBox;
- QLabel *graphLabel;
+ QLabel *horizontalLine;
QLabel *screenChannelLabel, *screenSpectrumLabel, *printChannelLabel, *printSpectrumLabel;
- std::vector colorLabel;
- std::vector screenChannelColorBox;
- std::vector screenSpectrumColorBox;
- std::vector printChannelColorBox;
- std::vector printSpectrumColorBox;
+ std::vector< QLabel * > colorLabel;
+ std::vector< ColorBox * > screenChannelColorBox;
+ std::vector< ColorBox * > screenSpectrumColorBox;
+ std::vector< ColorBox * > printChannelColorBox;
+ std::vector< ColorBox * > printSpectrumColorBox;
+ QCheckBox *screenColorCheckBox;
};
diff --git a/openhantek/src/configdialog/DsoConfigFilesPage.cpp b/openhantek/src/configdialog/DsoConfigFilesPage.cpp
deleted file mode 100644
index 64e3b2ab..00000000
--- a/openhantek/src/configdialog/DsoConfigFilesPage.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include "DsoConfigFilesPage.h"
-
-DsoConfigFilesPage::DsoConfigFilesPage(DsoSettings *settings, QWidget *parent) : QWidget(parent), settings(settings) {
- // Export group
- screenColorCheckBox = new QCheckBox(tr("Export Images with Screen Colors"));
- screenColorCheckBox->setChecked(settings->view.screenColorImages);
-
- imageWidthLabel = new QLabel(tr("Image width"));
- imageWidthSpinBox = new QSpinBox();
- imageWidthSpinBox->setMinimum(100);
- imageWidthSpinBox->setMaximum(9999);
- imageWidthSpinBox->setValue(settings->exporting.imageSize.width());
- imageHeightLabel = new QLabel(tr("Image height"));
- imageHeightSpinBox = new QSpinBox();
- imageHeightSpinBox->setMinimum(100);
- imageHeightSpinBox->setMaximum(9999);
- imageHeightSpinBox->setValue(settings->exporting.imageSize.height());
-
- exportLayout = new QGridLayout();
- exportLayout->addWidget(screenColorCheckBox, 0, 0, 1, 2);
- exportLayout->addWidget(imageWidthLabel, 1, 0);
- exportLayout->addWidget(imageWidthSpinBox, 1, 1);
- exportLayout->addWidget(imageHeightLabel, 2, 0);
- exportLayout->addWidget(imageHeightSpinBox, 2, 1);
-
- exportGroup = new QGroupBox(tr("Export"));
- exportGroup->setLayout(exportLayout);
-
- // Configuration group
- saveOnExitCheckBox = new QCheckBox(tr("Save default settings on exit"));
- saveOnExitCheckBox->setChecked(settings->alwaysSave);
- saveNowButton = new QPushButton(tr("Save default settings now"));
-
- configurationLayout = new QVBoxLayout();
- configurationLayout->addWidget(saveOnExitCheckBox, 0);
- configurationLayout->addWidget(saveNowButton, 1);
-
- configurationGroup = new QGroupBox(tr("Configuration"));
- configurationGroup->setLayout(configurationLayout);
-
- // Main layout
- mainLayout = new QVBoxLayout();
- mainLayout->addWidget(exportGroup);
- mainLayout->addWidget(configurationGroup);
- mainLayout->addStretch(1);
-
- setLayout(mainLayout);
-
- connect(saveNowButton, &QAbstractButton::clicked, [settings]() { settings->save(); });
-}
-
-/// \brief Saves the new settings.
-void DsoConfigFilesPage::saveSettings() {
- settings->alwaysSave = saveOnExitCheckBox->isChecked();
- settings->view.screenColorImages = screenColorCheckBox->isChecked();
- settings->exporting.imageSize.setWidth(imageWidthSpinBox->value());
- settings->exporting.imageSize.setHeight(imageHeightSpinBox->value());
-}
diff --git a/openhantek/src/configdialog/DsoConfigFilesPage.h b/openhantek/src/configdialog/DsoConfigFilesPage.h
deleted file mode 100644
index 8bcfd719..00000000
--- a/openhantek/src/configdialog/DsoConfigFilesPage.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include
-
-#include "settings.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-////////////////////////////////////////////////////////////////////////////////
-/// \class DsoConfigFilesPage configpages.h
-/// \brief Config page for file loading/saving.
-class DsoConfigFilesPage : public QWidget {
- Q_OBJECT
-
- public:
- DsoConfigFilesPage(DsoSettings *settings, QWidget *parent = 0);
-
- public slots:
- void saveSettings();
-
- private:
- DsoSettings *settings;
-
- QVBoxLayout *mainLayout;
-
- QGroupBox *configurationGroup;
- QVBoxLayout *configurationLayout;
- QCheckBox *saveOnExitCheckBox;
- QPushButton *saveNowButton;
-
- QGroupBox *exportGroup;
- QGridLayout *exportLayout;
- QCheckBox *screenColorCheckBox;
- QLabel *imageWidthLabel;
- QSpinBox *imageWidthSpinBox;
- QLabel *imageHeightLabel;
- QSpinBox *imageHeightSpinBox;
-};
diff --git a/openhantek/src/configdialog/DsoConfigScopePage.cpp b/openhantek/src/configdialog/DsoConfigScopePage.cpp
index c01a1509..5592854e 100644
--- a/openhantek/src/configdialog/DsoConfigScopePage.cpp
+++ b/openhantek/src/configdialog/DsoConfigScopePage.cpp
@@ -2,55 +2,123 @@
#include "DsoConfigScopePage.h"
-DsoConfigScopePage::DsoConfigScopePage(DsoSettings *settings, QWidget *parent) : QWidget(parent), settings(settings) {
+DsoConfigScopePage::DsoConfigScopePage( DsoSettings *settings, QWidget *parent ) : QWidget( parent ), settings( settings ) {
// Initialize lists for comboboxes
QStringList interpolationStrings;
- interpolationStrings << tr("Off") << tr("Linear");
+ interpolationStrings << tr( "Off" ) << tr( "Linear" );
+ QList< double > timebaseSteps = {1.0, 2.0, 5.0, 10.0};
- // Initialize elements
- interpolationLabel = new QLabel(tr("Interpolation"));
+ maxTimebaseLabel = new QLabel( tr( "Set slowest possible timebase" ) );
+ maxTimebaseSiSpinBox = new SiSpinBox();
+ maxTimebaseSiSpinBox = new SiSpinBox( UNIT_SECONDS );
+ maxTimebaseSiSpinBox->setSteps( timebaseSteps );
+ maxTimebaseSiSpinBox->setMinimum( 0.1 ); // default 1000 ms/div (scopesettings.h)
+ maxTimebaseSiSpinBox->setMaximum( 10.0 ); // possible steps: 100, 200, 500, 1000, 2000, 5000, 10000 ms
+ maxTimebaseSiSpinBox->setValue( settings->scope.horizontal.maxTimebase );
+
+ acquireIntervalLabel = new QLabel( tr( "Minimal time between captured frames (Longer times reduce the CPU load)" ) );
+ acquireIntervalSiSpinBox = new SiSpinBox();
+ acquireIntervalSiSpinBox = new SiSpinBox( UNIT_SECONDS );
+ acquireIntervalSiSpinBox->setSteps( timebaseSteps );
+ acquireIntervalSiSpinBox->setMinimum( 1e-3 ); // minimal 1 ms holdOff
+ acquireIntervalSiSpinBox->setMaximum( 100e-3 ); // up to 100 ms holdOff
+ acquireIntervalSiSpinBox->setValue( settings->scope.horizontal.acquireInterval );
+
+ horizontalLayout = new QGridLayout();
+ horizontalLayout->addWidget( maxTimebaseLabel, 0, 0 );
+ horizontalLayout->addWidget( maxTimebaseSiSpinBox, 0, 1 );
+ horizontalLayout->addWidget( acquireIntervalLabel, 1, 0 );
+ horizontalLayout->addWidget( acquireIntervalSiSpinBox, 1, 1 );
+ horizontalGroup = new QGroupBox( tr( "Horizontal" ) );
+ horizontalGroup->setLayout( horizontalLayout );
+
+ interpolationLabel = new QLabel( tr( "Interpolation" ) );
interpolationComboBox = new QComboBox();
- interpolationComboBox->addItems(interpolationStrings);
- interpolationComboBox->setCurrentIndex(settings->view.interpolation);
- digitalPhosphorDepthLabel = new QLabel(tr("Digital phosphor depth"));
+ interpolationComboBox->addItems( interpolationStrings );
+ interpolationComboBox->setCurrentIndex( settings->view.interpolation );
+ digitalPhosphorDepthLabel = new QLabel( tr( "Digital phosphor depth" ) );
digitalPhosphorDepthSpinBox = new QSpinBox();
- digitalPhosphorDepthSpinBox->setMinimum(2);
- digitalPhosphorDepthSpinBox->setMaximum(99);
- digitalPhosphorDepthSpinBox->setValue(settings->view.digitalPhosphorDepth);
+ digitalPhosphorDepthSpinBox->setMinimum( 2 );
+ digitalPhosphorDepthSpinBox->setMaximum( 99 );
+ digitalPhosphorDepthSpinBox->setValue( int( settings->view.digitalPhosphorDepth ) );
graphLayout = new QGridLayout();
- graphLayout->addWidget(interpolationLabel, 1, 0);
- graphLayout->addWidget(interpolationComboBox, 1, 1);
- graphLayout->addWidget(digitalPhosphorDepthLabel, 2, 0);
- graphLayout->addWidget(digitalPhosphorDepthSpinBox, 2, 1);
+ graphLayout->addWidget( interpolationLabel, 1, 0 );
+ graphLayout->addWidget( interpolationComboBox, 1, 1 );
+ graphLayout->addWidget( digitalPhosphorDepthLabel, 2, 0 );
+ graphLayout->addWidget( digitalPhosphorDepthSpinBox, 2, 1 );
- graphGroup = new QGroupBox(tr("Graph"));
- graphGroup->setLayout(graphLayout);
+ graphGroup = new QGroupBox( tr( "Graph" ) );
+ graphGroup->setLayout( graphLayout );
- cursorsLabel = new QLabel(tr("Position"));
+ cursorsLabel = new QLabel( tr( "Position" ) );
cursorsComboBox = new QComboBox();
- cursorsComboBox->addItem("Left", Qt::LeftToolBarArea);
- cursorsComboBox->addItem("Right", Qt::RightToolBarArea);
- cursorsComboBox->setCurrentIndex(settings->view.cursorGridPosition == Qt::LeftToolBarArea ? 0 : 1);
+ cursorsComboBox->addItem( tr( "Left" ), Qt::LeftToolBarArea );
+ cursorsComboBox->addItem( tr( "Right" ), Qt::RightToolBarArea );
+ cursorsComboBox->setCurrentIndex( settings->view.cursorGridPosition == Qt::LeftToolBarArea ? 0 : 1 );
cursorsLayout = new QGridLayout();
- cursorsLayout->addWidget(cursorsLabel, 0, 0);
- cursorsLayout->addWidget(cursorsComboBox, 0, 1);
+ cursorsLayout->addWidget( cursorsLabel, 0, 0 );
+ cursorsLayout->addWidget( cursorsComboBox, 0, 1 );
+
+ cursorsGroup = new QGroupBox( tr( "Cursors" ) );
+ cursorsGroup->setLayout( cursorsLayout );
+
+ // Export group
+ zoomImageCheckBox = new QCheckBox( tr( "Export zoomed screen in double height" ) );
+ zoomImageCheckBox->setChecked( settings->view.zoomImage );
+ exportLayout = new QGridLayout();
+ exportLayout->addWidget( zoomImageCheckBox, 2, 0, 1, 2 );
+
+ exportGroup = new QGroupBox( tr( "Export" ) );
+ exportGroup->setLayout( exportLayout );
+
+ // Configuration group
+ saveOnExitCheckBox = new QCheckBox( tr( "Save settings on exit" ) );
+ saveOnExitCheckBox->setChecked( settings->alwaysSave );
+ defaultSettingsCheckBox = new QCheckBox( tr( "Apply default settings after next restart" ) );
+ defaultSettingsCheckBox->setChecked( 0 == settings->configVersion );
+ saveNowButton = new QPushButton( tr( "Save settings now" ) );
+ hasACmodificationCheckBox =
+ new QCheckBox( tr( "Scope has hardware modification for AC coupling (restart needed to apply the change)" ) );
+ hasACmodificationCheckBox->setChecked( settings->scope.hasACmodification );
+
+ configurationLayout = new QGridLayout();
+ configurationLayout->addWidget( saveOnExitCheckBox, 0, 0 );
+ configurationLayout->addWidget( saveNowButton, 0, 1 );
+ configurationLayout->addWidget( defaultSettingsCheckBox, 1, 0, 1, 2 );
+ if ( settings->scope.hasACcoupling ) {
+ hasACmodificationCheckBox->setChecked( true ); // check but do not show the box
+ } else {
+ configurationLayout->addWidget( hasACmodificationCheckBox, 2, 0, 1, 2 ); // show it
+ }
+
+ configurationGroup = new QGroupBox( tr( "Configuration" ) );
+ configurationGroup->setLayout( configurationLayout );
- cursorsGroup = new QGroupBox(tr("Cursors"));
- cursorsGroup->setLayout(cursorsLayout);
mainLayout = new QVBoxLayout();
- mainLayout->addWidget(graphGroup);
- mainLayout->addWidget(cursorsGroup);
- mainLayout->addStretch(1);
+ mainLayout->addWidget( horizontalGroup );
+ mainLayout->addWidget( graphGroup );
+ mainLayout->addWidget( exportGroup );
+ mainLayout->addWidget( cursorsGroup );
+ mainLayout->addWidget( configurationGroup );
+ mainLayout->addStretch( 1 );
- setLayout(mainLayout);
+ setLayout( mainLayout );
+ connect( saveNowButton, &QAbstractButton::clicked, [settings]() { settings->save(); } );
}
/// \brief Saves the new settings.
void DsoConfigScopePage::saveSettings() {
- settings->view.interpolation = (Dso::InterpolationMode)interpolationComboBox->currentIndex();
- settings->view.digitalPhosphorDepth = digitalPhosphorDepthSpinBox->value();
- settings->view.cursorGridPosition = (Qt::ToolBarArea)cursorsComboBox->currentData().toUInt();
+ settings->scope.hasACmodification = hasACmodificationCheckBox->isChecked();
+ settings->scope.horizontal.maxTimebase = maxTimebaseSiSpinBox->value();
+ settings->scope.horizontal.acquireInterval = acquireIntervalSiSpinBox->value();
+ settings->view.interpolation = Dso::InterpolationMode( interpolationComboBox->currentIndex() );
+ settings->view.digitalPhosphorDepth = unsigned( digitalPhosphorDepthSpinBox->value() );
+ settings->view.cursorGridPosition = Qt::ToolBarArea( cursorsComboBox->currentData().toUInt() );
+ settings->alwaysSave = saveOnExitCheckBox->isChecked();
+ if ( defaultSettingsCheckBox->isChecked() )
+ settings->configVersion = 0;
+ settings->view.zoomImage = zoomImageCheckBox->isChecked();
}
diff --git a/openhantek/src/configdialog/DsoConfigScopePage.h b/openhantek/src/configdialog/DsoConfigScopePage.h
index a185a35a..a890bbe4 100644
--- a/openhantek/src/configdialog/DsoConfigScopePage.h
+++ b/openhantek/src/configdialog/DsoConfigScopePage.h
@@ -2,8 +2,9 @@
#include
-#include "settings.h"
+#include "dsosettings.h"
+#include "sispinbox.h"
#include
#include
#include
@@ -11,6 +12,7 @@
#include
#include
#include
+#include
#include
#include
@@ -21,7 +23,7 @@ class DsoConfigScopePage : public QWidget {
Q_OBJECT
public:
- DsoConfigScopePage(DsoSettings *settings, QWidget *parent = 0);
+ DsoConfigScopePage( DsoSettings *settings, QWidget *parent = nullptr );
public slots:
void saveSettings();
@@ -31,6 +33,13 @@ class DsoConfigScopePage : public QWidget {
QVBoxLayout *mainLayout;
+ QGroupBox *horizontalGroup;
+ QGridLayout *horizontalLayout;
+ QLabel *maxTimebaseLabel;
+ SiSpinBox *maxTimebaseSiSpinBox;
+ QLabel *acquireIntervalLabel;
+ SiSpinBox *acquireIntervalSiSpinBox;
+
QGroupBox *graphGroup;
QGridLayout *graphLayout;
QLabel *digitalPhosphorDepthLabel;
@@ -42,4 +51,15 @@ class DsoConfigScopePage : public QWidget {
QGridLayout *cursorsLayout;
QLabel *cursorsLabel;
QComboBox *cursorsComboBox;
+
+ QGroupBox *configurationGroup;
+ QGridLayout *configurationLayout;
+ QCheckBox *hasACmodificationCheckBox;
+ QCheckBox *saveOnExitCheckBox;
+ QCheckBox *defaultSettingsCheckBox;
+ QPushButton *saveNowButton;
+
+ QGroupBox *exportGroup;
+ QGridLayout *exportLayout;
+ QCheckBox *zoomImageCheckBox;
};
diff --git a/openhantek/src/configdialog/DsoConfigSpectrumPage.cpp b/openhantek/src/configdialog/DsoConfigSpectrumPage.cpp
new file mode 100644
index 00000000..87317ed1
--- /dev/null
+++ b/openhantek/src/configdialog/DsoConfigSpectrumPage.cpp
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include "DsoConfigSpectrumPage.h"
+
+DsoConfigSpectrumPage::DsoConfigSpectrumPage( DsoSettings *settings, QWidget *parent ) : QWidget( parent ), settings( settings ) {
+ // Initialize lists for comboboxes
+ QStringList windowFunctionStrings;
+ windowFunctionStrings << tr( "Rectangular" ) << tr( "Hamming" ) << tr( "Hann" ) << tr( "Cosine" ) << tr( "Lanczos" )
+ << tr( "Bartlett" ) << tr( "Triangular" ) << tr( "Gauss" ) << tr( "Bartlett-Hann" )
+ << tr( "Blackman" )
+ //<< tr("Kaiser")
+ << tr( "Nuttall" ) << tr( "Blackman-Harris" ) << tr( "Blackman-Nuttall" ) << tr( "Flat top" );
+
+ // Initialize elements
+ windowFunctionLabel = new QLabel( tr( "Window function" ) );
+ windowFunctionComboBox = new QComboBox();
+ windowFunctionComboBox->addItems( windowFunctionStrings );
+ windowFunctionComboBox->setCurrentIndex( int( settings->post.spectrumWindow ) );
+
+ referenceLevelLabel = new QLabel(
+ tr( "Reference level 0 dBu = -2.2 dBV 0 dBm (@600 Ω) = -2.2 dBV 0 dBm (@50 Ω) = -13 dBV" ) );
+ referenceLevelSpinBox = new QDoubleSpinBox();
+ referenceLevelSpinBox->setDecimals( 1 );
+ referenceLevelSpinBox->setMinimum( -100.0 );
+ referenceLevelSpinBox->setMaximum( 100.0 );
+ referenceLevelSpinBox->setValue( settings->post.spectrumReference );
+ referenceLevelUnitLabel = new QLabel( tr( "dBV" ) );
+ referenceLevelLayout = new QHBoxLayout();
+ referenceLevelLayout->addWidget( referenceLevelSpinBox );
+ referenceLevelLayout->addWidget( referenceLevelUnitLabel );
+
+ minimumMagnitudeLabel = new QLabel( tr( "Minimum magnitude" ) );
+ minimumMagnitudeSpinBox = new QDoubleSpinBox();
+ minimumMagnitudeSpinBox->setDecimals( 1 );
+ minimumMagnitudeSpinBox->setMinimum( -100.0 );
+ minimumMagnitudeSpinBox->setMaximum( 100.0 );
+ minimumMagnitudeSpinBox->setValue( settings->post.spectrumLimit );
+ minimumMagnitudeUnitLabel = new QLabel( tr( "dBV" ) );
+ minimumMagnitudeLayout = new QHBoxLayout();
+ minimumMagnitudeLayout->addWidget( minimumMagnitudeSpinBox );
+ minimumMagnitudeLayout->addWidget( minimumMagnitudeUnitLabel );
+
+ spectrumLayout = new QGridLayout();
+ spectrumLayout->addWidget( windowFunctionLabel, 0, 0 );
+ spectrumLayout->addWidget( windowFunctionComboBox, 0, 1 );
+ spectrumLayout->addWidget( referenceLevelLabel, 1, 0 );
+ spectrumLayout->addLayout( referenceLevelLayout, 1, 1 );
+ spectrumLayout->addWidget( minimumMagnitudeLabel, 2, 0 );
+ spectrumLayout->addLayout( minimumMagnitudeLayout, 2, 1 );
+
+ spectrumGroup = new QGroupBox( tr( "Spectrum" ) );
+ spectrumGroup->setLayout( spectrumLayout );
+
+ mainLayout = new QVBoxLayout();
+ mainLayout->addWidget( spectrumGroup );
+ mainLayout->addStretch( 1 );
+
+ setLayout( mainLayout );
+}
+
+/// \brief Saves the new settings.
+void DsoConfigSpectrumPage::saveSettings() {
+ settings->post.spectrumWindow = Dso::WindowFunction( windowFunctionComboBox->currentIndex() );
+ settings->post.spectrumReference = referenceLevelSpinBox->value();
+ settings->post.spectrumLimit = minimumMagnitudeSpinBox->value();
+}
diff --git a/openhantek/src/configdialog/DsoConfigAnalysisPage.h b/openhantek/src/configdialog/DsoConfigSpectrumPage.h
similarity index 77%
rename from openhantek/src/configdialog/DsoConfigAnalysisPage.h
rename to openhantek/src/configdialog/DsoConfigSpectrumPage.h
index aa408b51..4705c543 100644
--- a/openhantek/src/configdialog/DsoConfigAnalysisPage.h
+++ b/openhantek/src/configdialog/DsoConfigSpectrumPage.h
@@ -2,7 +2,7 @@
#include
-#include "settings.h"
+#include "dsosettings.h"
#include
#include
@@ -15,13 +15,13 @@
#include
////////////////////////////////////////////////////////////////////////////////
-/// \class DsoConfigAnalysisPage configpages.h
-/// \brief Config page for the data analysis.
-class DsoConfigAnalysisPage : public QWidget {
+/// \class DsoConfigSpectrumPage configpages.h
+/// \brief Config page for the data spectral analysis.
+class DsoConfigSpectrumPage : public QWidget {
Q_OBJECT
public:
- DsoConfigAnalysisPage(DsoSettings *settings, QWidget *parent = 0);
+ DsoConfigSpectrumPage( DsoSettings *settings, QWidget *parent = nullptr );
public slots:
void saveSettings();
diff --git a/openhantek/src/configdialog/configdialog.cpp b/openhantek/src/configdialog/configdialog.cpp
index eabda2f2..2f74909f 100644
--- a/openhantek/src/configdialog/configdialog.cpp
+++ b/openhantek/src/configdialog/configdialog.cpp
@@ -1,20 +1,10 @@
// SPDX-License-Identifier: GPL-2.0+
-/*#if defined(OS_UNIX)
-#define CONFIG_PATH QDir::homePath() + "/.config/paranoiacs.net/openhantek"
-#define CONFIG_FILE CONFIG_PATH "/openhantek.conf"
-#elif defined(OS_DARWIN)
-#define CONFIG_PATH QDir::homePath() + "/Library/Application Support/OpenHantek"
-#define CONFIG_FILE CONFIG_PATH "/openhantek.plist"
-#elif defined(OS_WINDOWS)
-//#define CONFIG_PATH QDir::homePath() + "" // Too hard to get and this OS sucks
-anyway, ignore it
-#define CONFIG_FILE "HKEY_CURRENT_USER\\Software\\paranoiacs.net\\OpenHantek"
-#endif*/
-
-#define CONFIG_LIST_WIDTH 128 ///< The width of the page selection widget
-#define CONFIG_LIST_ITEMHEIGHT 80 ///< The height of one item in the page selection widget
-#define CONFIG_LIST_ICONSIZE 48 ///< The icon size in the page selection widget
+
+#define CONFIG_LIST_WIDTH 128 ///< The width of the page selection widget
+#define CONFIG_LIST_ITEMHEIGHT 100 ///< The height of one item in the page selection widget
+#define CONFIG_LIST_ICONWIDTH 80 ///< The icon size in the page selection widget
+#define CONFIG_LIST_ICONHEIGHT 64 ///< The icon size in the page selection widget
#include
#include
@@ -26,12 +16,11 @@ anyway, ignore it
#include "configdialog.h"
-#include "DsoConfigAnalysisPage.h"
#include "DsoConfigColorsPage.h"
-#include "DsoConfigFilesPage.h"
#include "DsoConfigScopePage.h"
+#include "DsoConfigSpectrumPage.h"
-#include "settings.h"
+#include "dsosettings.h"
////////////////////////////////////////////////////////////////////////////////
// class DsoConfigDialog
@@ -39,107 +28,102 @@ anyway, ignore it
/// \param settings The target settings object.
/// \param parent The parent widget.
/// \param flags Flags for the window manager.
-DsoConfigDialog::DsoConfigDialog(DsoSettings *settings, QWidget *parent, Qt::WindowFlags flags)
- : QDialog(parent, flags), settings(settings) {
-
- this->setWindowTitle(tr("Settings"));
+DsoConfigDialog::DsoConfigDialog( DsoSettings *settings, QWidget *parent ) : QDialog( parent ), settings( settings ) {
+ this->setWindowTitle( tr( "Settings" ) );
this->contentsWidget = new QListWidget;
- this->contentsWidget->setViewMode(QListView::IconMode);
- this->contentsWidget->setIconSize(QSize(CONFIG_LIST_ICONSIZE, CONFIG_LIST_ICONSIZE));
- this->contentsWidget->setMovement(QListView::Static);
+ this->contentsWidget->setViewMode( QListView::IconMode );
+ this->contentsWidget->setIconSize( QSize( CONFIG_LIST_ICONWIDTH, CONFIG_LIST_ICONHEIGHT ) );
+ this->contentsWidget->setMovement( QListView::Static );
this->contentsWidget->setGridSize(
- QSize(CONFIG_LIST_WIDTH - 2 * this->contentsWidget->frameWidth(), CONFIG_LIST_ITEMHEIGHT));
- this->contentsWidget->setMaximumWidth(CONFIG_LIST_WIDTH);
- this->contentsWidget->setMinimumWidth(CONFIG_LIST_WIDTH);
- this->contentsWidget->setMinimumHeight(CONFIG_LIST_ITEMHEIGHT * 3 + 2 * (this->contentsWidget->frameWidth()));
-
- this->analysisPage = new DsoConfigAnalysisPage(settings);
- this->colorsPage = new DsoConfigColorsPage(settings);
- this->filesPage = new DsoConfigFilesPage(settings);
- this->scopePage = new DsoConfigScopePage(settings);
+ QSize( CONFIG_LIST_WIDTH - 2 * this->contentsWidget->frameWidth(), CONFIG_LIST_ITEMHEIGHT ) );
+ this->contentsWidget->setMaximumWidth( CONFIG_LIST_WIDTH );
+ this->contentsWidget->setMinimumWidth( CONFIG_LIST_WIDTH );
+ this->contentsWidget->setMinimumHeight( CONFIG_LIST_ITEMHEIGHT * 3 + 2 * ( this->contentsWidget->frameWidth() ) );
+
+ this->spectrumPage = new DsoConfigSpectrumPage( settings );
+ this->colorsPage = new DsoConfigColorsPage( settings );
+ this->scopePage = new DsoConfigScopePage( settings );
this->pagesWidget = new QStackedWidget;
- this->pagesWidget->addWidget(this->analysisPage);
- this->pagesWidget->addWidget(this->colorsPage);
- this->pagesWidget->addWidget(this->filesPage);
- this->pagesWidget->addWidget(this->scopePage);
+ this->pagesWidget->addWidget( this->scopePage );
+ this->pagesWidget->addWidget( this->spectrumPage );
+ this->pagesWidget->addWidget( this->colorsPage );
- this->acceptButton = new QPushButton(tr("&Ok"));
- this->acceptButton->setDefault(true);
- this->applyButton = new QPushButton(tr("&Apply"));
- this->rejectButton = new QPushButton(tr("&Cancel"));
+ this->acceptButton = new QPushButton( tr( "&Ok" ) );
+ this->acceptButton->setDefault( true );
+ this->applyButton = new QPushButton( tr( "&Apply" ) );
+ this->rejectButton = new QPushButton( tr( "&Cancel" ) );
this->createIcons();
- this->contentsWidget->setCurrentRow(0);
+ this->contentsWidget->setCurrentRow( 0 );
- this->horizontalLayout = new QHBoxLayout;
- this->horizontalLayout->addWidget(this->contentsWidget);
- this->horizontalLayout->addWidget(this->pagesWidget, 1);
+ this->sectionsLayout = new QHBoxLayout;
+ this->sectionsLayout->addWidget( this->contentsWidget );
+ this->sectionsLayout->addWidget( this->pagesWidget, 1 );
this->buttonsLayout = new QHBoxLayout;
- this->buttonsLayout->setSpacing(8);
- this->buttonsLayout->addStretch(1);
- this->buttonsLayout->addWidget(this->acceptButton);
- this->buttonsLayout->addWidget(this->applyButton);
- this->buttonsLayout->addWidget(this->rejectButton);
+ this->buttonsLayout->setSpacing( 8 );
+ this->buttonsLayout->addStretch( 1 );
+ this->buttonsLayout->addWidget( this->acceptButton );
+ this->buttonsLayout->addWidget( this->applyButton );
+ this->buttonsLayout->addWidget( this->rejectButton );
this->mainLayout = new QVBoxLayout;
- this->mainLayout->addLayout(this->horizontalLayout);
- this->mainLayout->addStretch(1);
- this->mainLayout->addSpacing(8);
- this->mainLayout->addLayout(this->buttonsLayout);
- this->setLayout(this->mainLayout);
-
- connect(this->acceptButton, &QAbstractButton::clicked, this, &DsoConfigDialog::accept);
- connect(this->applyButton, &QAbstractButton::clicked, this, &DsoConfigDialog::apply);
- connect(this->rejectButton, &QAbstractButton::clicked, this, &QDialog::reject);
+ mainLayout->addSpacing( 8 );
+ this->mainLayout->addLayout( this->sectionsLayout );
+ this->mainLayout->addStretch( 1 );
+ this->mainLayout->addSpacing( 8 );
+ this->mainLayout->addLayout( this->buttonsLayout );
+ this->setLayout( this->mainLayout );
+
+ connect( this->acceptButton, &QAbstractButton::clicked, this, &DsoConfigDialog::accept );
+ connect( this->applyButton, &QAbstractButton::clicked, this, &DsoConfigDialog::apply );
+ connect( this->rejectButton, &QAbstractButton::clicked, this, &QDialog::reject );
}
+
/// \brief Cleans up the dialog.
DsoConfigDialog::~DsoConfigDialog() {}
+
/// \brief Create the icons for the pages.
void DsoConfigDialog::createIcons() {
- QListWidgetItem *analysisButton = new QListWidgetItem(contentsWidget);
- analysisButton->setIcon(QIcon(":config/analysis.png"));
- analysisButton->setText(tr("Analysis"));
-
- QListWidgetItem *colorsButton = new QListWidgetItem(contentsWidget);
- colorsButton->setIcon(QIcon(":config/colors.png"));
- colorsButton->setText(tr("Colors"));
+ QListWidgetItem *scopeButton = new QListWidgetItem( contentsWidget );
+ scopeButton->setIcon( QIcon( ":config/scope.png" ) );
+ scopeButton->setText( tr( "Scope" ) );
- QListWidgetItem *filesButton = new QListWidgetItem(contentsWidget);
- filesButton->setIcon(QIcon(":config/files.png"));
- filesButton->setText(tr("Files"));
+ QListWidgetItem *spectrumButton = new QListWidgetItem( contentsWidget );
+ spectrumButton->setIcon( QIcon( ":config/spectrum.png" ) );
+ spectrumButton->setText( tr( "Spectrum" ) );
- QListWidgetItem *scopeButton = new QListWidgetItem(contentsWidget);
- scopeButton->setIcon(QIcon(":config/scope.png"));
- scopeButton->setText(tr("Scope"));
+ QListWidgetItem *colorsButton = new QListWidgetItem( contentsWidget );
+ colorsButton->setIcon( QIcon( ":config/colors.png" ) );
+ colorsButton->setText( tr( "Colors" ) );
- connect(contentsWidget, &QListWidget::currentItemChanged, this,
- &DsoConfigDialog::changePage);
+ connect( contentsWidget, &QListWidget::currentItemChanged, this, &DsoConfigDialog::changePage );
}
+
/// \brief Saves the settings and closes the dialog.
void DsoConfigDialog::accept() {
this->apply();
-
QDialog::accept();
}
+
/// \brief Saves the settings.
void DsoConfigDialog::apply() {
- this->analysisPage->saveSettings();
- this->colorsPage->saveSettings();
- this->filesPage->saveSettings();
this->scopePage->saveSettings();
+ this->spectrumPage->saveSettings();
+ this->colorsPage->saveSettings();
}
+
/// \brief Change the config page.
/// \param current The page that has been selected.
/// \param previous The page that was selected before.
-void DsoConfigDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) {
- if (!current) current = previous;
-
- pagesWidget->setCurrentIndex(contentsWidget->row(current));
+void DsoConfigDialog::changePage( QListWidgetItem *current, QListWidgetItem *previous ) {
+ if ( !current )
+ current = previous;
+ pagesWidget->setCurrentIndex( contentsWidget->row( current ) );
}
diff --git a/openhantek/src/configdialog/configdialog.h b/openhantek/src/configdialog/configdialog.h
index f6b577fe..7bca1cd1 100644
--- a/openhantek/src/configdialog/configdialog.h
+++ b/openhantek/src/configdialog/configdialog.h
@@ -2,10 +2,9 @@
#include
-class DsoConfigAnalysisPage;
-class DsoConfigColorsPage;
-class DsoConfigFilesPage;
+class DsoConfigSpectrumPage;
class DsoConfigScopePage;
+class DsoConfigColorsPage;
class DsoSettings;
class QHBoxLayout;
@@ -22,14 +21,14 @@ class DsoConfigDialog : public QDialog {
Q_OBJECT
public:
- DsoConfigDialog(DsoSettings *settings, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ DsoConfigDialog( DsoSettings *settings, QWidget *parent = nullptr );
~DsoConfigDialog();
public slots:
void accept();
void apply();
- void changePage(QListWidgetItem *current, QListWidgetItem *previous);
+ void changePage( QListWidgetItem *current, QListWidgetItem *previous );
private:
void createIcons();
@@ -37,16 +36,15 @@ class DsoConfigDialog : public QDialog {
DsoSettings *settings;
QVBoxLayout *mainLayout;
- QHBoxLayout *horizontalLayout;
+ QHBoxLayout *sectionsLayout;
QHBoxLayout *buttonsLayout;
QListWidget *contentsWidget;
QStackedWidget *pagesWidget;
- DsoConfigAnalysisPage *analysisPage;
- DsoConfigColorsPage *colorsPage;
- DsoConfigFilesPage *filesPage;
DsoConfigScopePage *scopePage;
+ DsoConfigSpectrumPage *spectrumPage;
+ DsoConfigColorsPage *colorsPage;
QPushButton *acceptButton, *applyButton, *rejectButton;
};
diff --git a/openhantek/src/docks/HorizontalDock.cpp b/openhantek/src/docks/HorizontalDock.cpp
index 27cb695f..3433dda8 100644
--- a/openhantek/src/docks/HorizontalDock.cpp
+++ b/openhantek/src/docks/HorizontalDock.cpp
@@ -3,10 +3,11 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
-#include
#include
@@ -17,198 +18,222 @@
#include "sispinbox.h"
#include "utils/printutils.h"
-template struct SELECT {
- template
- static constexpr auto OVERLOAD_OF( R (C::*pmf)(Args...) ) -> decltype(pmf) {
+static int row = 0;
+
+template < typename... Args > struct SELECT {
+ template < typename C, typename R > static constexpr auto OVERLOAD_OF( R ( C::*pmf )( Args... ) ) -> decltype( pmf ) {
return pmf;
}
};
-HorizontalDock::HorizontalDock(DsoSettingsScope *scope, QWidget *parent, Qt::WindowFlags flags)
- : QDockWidget(tr("Horizontal"), parent, flags), scope(scope) {
+HorizontalDock::HorizontalDock( DsoSettingsScope *scope, const Dso::ControlSpecification *spec, QWidget *parent )
+ : QDockWidget( tr( "Horizontal" ), parent ), scope( scope ) {
// Initialize elements
- this->samplerateLabel = new QLabel(tr("Samplerate"));
- this->samplerateSiSpinBox = new SiSpinBox(UNIT_SAMPLES);
- this->samplerateSiSpinBox->setMinimum(1);
- this->samplerateSiSpinBox->setMaximum(1e8);
- this->samplerateSiSpinBox->setUnitPostfix("/s");
-
- timebaseSteps << 1.0 << 2.0 << 4.0 << 10.0;
+ this->samplerateLabel = new QLabel( tr( "Samplerate" ) );
+ this->samplerateSiSpinBox = new SiSpinBox( UNIT_SAMPLES );
+ this->samplerateSiSpinBox->setMinimum( 1 );
+ this->samplerateSiSpinBox->setMaximum( 1e8 );
+ this->samplerateSiSpinBox->setUnitPostfix( tr( "/s" ) );
- this->timebaseLabel = new QLabel(tr("Timebase"));
- this->timebaseSiSpinBox = new SiSpinBox(UNIT_SECONDS);
- this->timebaseSiSpinBox->setSteps(timebaseSteps);
- this->timebaseSiSpinBox->setMinimum(1e-9);
- this->timebaseSiSpinBox->setMaximum(3.6e3);
+ timebaseSteps << 1.0 << 2.0 << 5.0 << 10.0;
- this->frequencybaseLabel = new QLabel(tr("Frequencybase"));
- this->frequencybaseSiSpinBox = new SiSpinBox(UNIT_HERTZ);
- this->frequencybaseSiSpinBox->setMinimum(1.0);
- this->frequencybaseSiSpinBox->setMaximum(100e6);
+ this->timebaseLabel = new QLabel( tr( "Timebase" ) );
+ this->timebaseSiSpinBox = new SiSpinBox( UNIT_SECONDS );
+ this->timebaseSiSpinBox->setSteps( timebaseSteps );
+ this->timebaseSiSpinBox->setMinimum( 1e-9 );
+ this->timebaseSiSpinBox->setMaximum( 1e3 );
- this->recordLengthLabel = new QLabel(tr("Record length"));
- this->recordLengthComboBox = new QComboBox();
-
- this->formatLabel = new QLabel(tr("Format"));
+ this->formatLabel = new QLabel( tr( "Format" ) );
this->formatComboBox = new QComboBox();
- for (Dso::GraphFormat format: Dso::GraphFormatEnum)
- this->formatComboBox->addItem(Dso::graphFormatString(format));
+ for ( Dso::GraphFormat format : Dso::GraphFormatEnum )
+ this->formatComboBox->addItem( Dso::graphFormatString( format ) );
+
+ this->calfreqLabel = new QLabel( tr( "Calibration out" ) );
+ this->calfreqSiSpinBox = new SiSpinBox( UNIT_HERTZ );
+ this->calfreqSiSpinBox->setSteps( spec->calfreqSteps );
+ this->calfreqSiSpinBox->setMinimum( spec->calfreqSteps.first() );
+ this->calfreqSiSpinBox->setMaximum( spec->calfreqSteps.last() );
this->dockLayout = new QGridLayout();
- this->dockLayout->setColumnMinimumWidth(0, 64);
- this->dockLayout->setColumnStretch(1, 1);
- this->dockLayout->addWidget(this->samplerateLabel, 0, 0);
- this->dockLayout->addWidget(this->samplerateSiSpinBox, 0, 1);
- this->dockLayout->addWidget(this->timebaseLabel, 1, 0);
- this->dockLayout->addWidget(this->timebaseSiSpinBox, 1, 1);
- this->dockLayout->addWidget(this->frequencybaseLabel, 2, 0);
- this->dockLayout->addWidget(this->frequencybaseSiSpinBox, 2, 1);
- this->dockLayout->addWidget(this->recordLengthLabel, 3, 0);
- this->dockLayout->addWidget(this->recordLengthComboBox, 3, 1);
- this->dockLayout->addWidget(this->formatLabel, 4, 0);
- this->dockLayout->addWidget(this->formatComboBox, 4, 1);
+ this->dockLayout->setColumnMinimumWidth( 0, 64 );
+ this->dockLayout->setColumnStretch( 1, 1 );
+ this->dockLayout->setSpacing( DOCK_LAYOUT_SPACING );
+
+ row = 0; // allows flexible shift up/down
+ this->dockLayout->addWidget( this->timebaseLabel, row, 0 );
+ this->dockLayout->addWidget( this->timebaseSiSpinBox, row++, 1 );
+ this->dockLayout->addWidget( this->samplerateLabel, row, 0 );
+ this->dockLayout->addWidget( this->samplerateSiSpinBox, row++, 1 );
+ this->dockLayout->addWidget( this->formatLabel, row, 0 );
+ this->dockLayout->addWidget( this->formatComboBox, row++, 1 );
+ this->dockLayout->addWidget( this->calfreqLabel, row, 0 );
+ this->dockLayout->addWidget( this->calfreqSiSpinBox, row++, 1 );
this->dockWidget = new QWidget();
- SetupDockWidget(this, dockWidget, dockLayout);
+ SetupDockWidget( this, dockWidget, dockLayout );
+
+ // Load settings into GUI
+ this->loadSettings( scope );
// Connect signals and slots
- connect(this->samplerateSiSpinBox, SELECT::OVERLOAD_OF(&QDoubleSpinBox::valueChanged), this, &HorizontalDock::samplerateSelected);
- connect(this->timebaseSiSpinBox, SELECT::OVERLOAD_OF(&QDoubleSpinBox::valueChanged), this, &HorizontalDock::timebaseSelected);
- connect(this->frequencybaseSiSpinBox, SELECT::OVERLOAD_OF(&QDoubleSpinBox::valueChanged), this, &HorizontalDock::frequencybaseSelected);
- connect(this->recordLengthComboBox, SELECT::OVERLOAD_OF(&QComboBox::currentIndexChanged), this, &HorizontalDock::recordLengthSelected);
- connect(this->formatComboBox, SELECT::OVERLOAD_OF(&QComboBox::currentIndexChanged), this, &HorizontalDock::formatSelected);
+ connect( this->samplerateSiSpinBox, SELECT< double >::OVERLOAD_OF( &QDoubleSpinBox::valueChanged ), this,
+ &HorizontalDock::samplerateSelected );
+ connect( this->timebaseSiSpinBox, SELECT< double >::OVERLOAD_OF( &QDoubleSpinBox::valueChanged ), this,
+ &HorizontalDock::timebaseSelected );
+ connect( this->formatComboBox, SELECT< int >::OVERLOAD_OF( &QComboBox::currentIndexChanged ), this,
+ &HorizontalDock::formatSelected );
+ connect( this->calfreqSiSpinBox, SELECT< double >::OVERLOAD_OF( &QDoubleSpinBox::valueChanged ), this,
+ &HorizontalDock::calfreqSelected );
+}
+void HorizontalDock::loadSettings( DsoSettingsScope *scope ) {
// Set values
- this->setSamplerate(scope->horizontal.samplerate);
- this->setTimebase(scope->horizontal.timebase);
- this->setFrequencybase(scope->horizontal.frequencybase);
- // this->setRecordLength(scope->horizontal.recordLength);
- this->setFormat(scope->horizontal.format);
+ this->setSamplerate( scope->horizontal.samplerate );
+ this->setTimebase( scope->horizontal.timebase );
+ this->setFormat( scope->horizontal.format );
+ this->setCalfreq( scope->horizontal.calfreq );
}
/// \brief Don't close the dock, just hide it.
/// \param event The close event that should be handled.
-void HorizontalDock::closeEvent(QCloseEvent *event) {
+void HorizontalDock::closeEvent( QCloseEvent *event ) {
this->hide();
-
event->accept();
}
-void HorizontalDock::setFrequencybase(double frequencybase) {
- QSignalBlocker blocker(frequencybaseSiSpinBox);
- frequencybaseSiSpinBox->setValue(frequencybase);
-}
-void HorizontalDock::setSamplerate(double samplerate) {
- QSignalBlocker blocker(samplerateSiSpinBox);
- samplerateSiSpinBox->setValue(samplerate);
+double HorizontalDock::setSamplerate( double samplerate ) {
+ // printf( "HD::setSamplerate( %g )\n", samplerate );
+ QSignalBlocker blocker( timebaseSiSpinBox );
+ timebaseSiSpinBox->setMaximum( scope->horizontal.maxTimebase );
+ blocker = QSignalBlocker( samplerateSiSpinBox );
+ samplerateSiSpinBox->setValue( samplerate );
+ return samplerateSiSpinBox->value();
}
-double HorizontalDock::setTimebase(double timebase) {
- QSignalBlocker blocker(timebaseSiSpinBox);
+
+double HorizontalDock::setTimebase( double timebase ) {
+ // printf( "HD::setTimebase( %g )\n", timebase );
+ QSignalBlocker blocker( timebaseSiSpinBox );
// timebaseSteps are repeated in each decade
- double decade = pow(10, floor(log10(timebase)));
+ double decade = pow( 10, floor( log10( timebase ) ) );
double vNorm = timebase / decade;
- for (int i = 0; i < timebaseSteps.size() - 1; ++i) {
- if (timebaseSteps.at(i) <= vNorm && vNorm < timebaseSteps.at(i + 1)) {
- timebaseSiSpinBox->setValue(decade * timebaseSteps.at(i));
+ for ( int i = 0; i < timebaseSteps.size() - 1; ++i ) {
+ if ( timebaseSteps.at( i ) <= vNorm && vNorm < timebaseSteps.at( i + 1 ) ) {
+ timebaseSiSpinBox->setValue( decade * timebaseSteps.at( i ) );
break;
}
}
+ // printf( "return %g\n", timebaseSiSpinBox->value() );
+ calculateSamplerateSteps( timebase );
return timebaseSiSpinBox->value();
}
-int addRecordLength(QComboBox *recordLengthComboBox, unsigned recordLength) {
- recordLengthComboBox->addItem(
- recordLength == UINT_MAX ? QCoreApplication::translate("HorizontalDock","Roll") : valueToString(recordLength, UNIT_SAMPLES, 3), recordLength);
- return recordLengthComboBox->count()-1;
-}
-
-void HorizontalDock::setRecordLength(unsigned int recordLength) {
- QSignalBlocker blocker(recordLengthComboBox);
- int index = recordLengthComboBox->findData(recordLength);
- scope->horizontal.recordLength = recordLength;
-
- if (index == -1) {
- index = addRecordLength(recordLengthComboBox, recordLength);
- }
- recordLengthComboBox->setCurrentIndex(index);
-}
-int HorizontalDock::setFormat(Dso::GraphFormat format) {
- QSignalBlocker blocker(formatComboBox);
- if (format >= Dso::GraphFormat::TY && format <= Dso::GraphFormat::XY) {
- formatComboBox->setCurrentIndex(format);
+int HorizontalDock::setFormat( Dso::GraphFormat format ) {
+ QSignalBlocker blocker( formatComboBox );
+ if ( format >= Dso::GraphFormat::TY && format <= Dso::GraphFormat::XY ) {
+ formatComboBox->setCurrentIndex( format );
return format;
}
-
return -1;
}
-void HorizontalDock::setAvailableRecordLengths(const std::vector &recordLengths) {
- QSignalBlocker blocker(recordLengthComboBox);
-
- recordLengthComboBox->clear();
- for (auto recordLength : recordLengths) {
- addRecordLength(recordLengthComboBox, recordLength);
- }
- setRecordLength(scope->horizontal.recordLength);
+double HorizontalDock::setCalfreq( double calfreq ) {
+ QSignalBlocker blocker( calfreqSiSpinBox );
+ calfreqSiSpinBox->setValue( calfreq );
+ return calfreqSiSpinBox->value();
}
-void HorizontalDock::setSamplerateLimits(double minimum, double maximum) {
- QSignalBlocker blocker(samplerateSiSpinBox);
- this->samplerateSiSpinBox->setMinimum(minimum);
- this->samplerateSiSpinBox->setMaximum(maximum);
+
+void HorizontalDock::setSamplerateLimits( double minimum, double maximum ) {
+ // printf( "HD::setSamplerateLimits( %g, %g )\n", minimum, maximum );
+ QSignalBlocker blocker( samplerateSiSpinBox );
+ if ( bool( minimum ) )
+ this->samplerateSiSpinBox->setMinimum( minimum );
+ if ( bool( maximum ) )
+ this->samplerateSiSpinBox->setMaximum( maximum );
}
-void HorizontalDock::setSamplerateSteps(int mode, QList steps) {
+
+void HorizontalDock::setSamplerateSteps( int mode, const QList< double > steps ) {
+ // printf( "HD::setSamplerateSteps( %d )\n", mode );
+ // qDebug() << "HD::setSamplerateSteps" << mode << steps;
+ samplerateSteps = steps;
// Assume that method is invoked for fixed samplerate devices only
- QSignalBlocker samplerateBlocker(samplerateSiSpinBox);
- samplerateSiSpinBox->setMode(mode);
- samplerateSiSpinBox->setSteps(steps);
- samplerateSiSpinBox->setMinimum(steps.first());
- samplerateSiSpinBox->setMaximum(steps.last());
+ QSignalBlocker samplerateBlocker( samplerateSiSpinBox );
+ samplerateSiSpinBox->setMode( mode );
+ samplerateSiSpinBox->setSteps( steps );
+ samplerateSiSpinBox->setMinimum( steps.first() );
+ samplerateSiSpinBox->setMaximum( steps.last() );
// Make reasonable adjustments to the timebase spinbox
- QSignalBlocker timebaseBlocker(timebaseSiSpinBox);
- timebaseSiSpinBox->setMinimum(pow(10, floor(log10(1.0 / steps.last()))));
- timebaseSiSpinBox->setMaximum(pow(10, ceil(log10(8192.0 / (steps.first() * 10)))));
+ QSignalBlocker timebaseBlocker( timebaseSiSpinBox );
+ timebaseSiSpinBox->setMinimum( pow( 10, floor( log10( 1.0 / steps.last() ) ) ) );
+ calculateSamplerateSteps( timebaseSiSpinBox->value() );
}
-/// \brief Called when the frequencybase spinbox changes its value.
-/// \param frequencybase The frequencybase in hertz.
-void HorizontalDock::frequencybaseSelected(double frequencybase) {
- scope->horizontal.frequencybase = frequencybase;
- emit frequencybaseChanged(frequencybase);
-}
/// \brief Called when the samplerate spinbox changes its value.
/// \param samplerate The samplerate in samples/second.
-void HorizontalDock::samplerateSelected(double samplerate) {
+void HorizontalDock::samplerateSelected( double samplerate ) {
+ // printf( "HD::samplerateSelected( %g )\n", samplerate );
scope->horizontal.samplerate = samplerate;
- scope->horizontal.samplerateSource = DsoSettingsScopeHorizontal::Samplerrate;
- emit samplerateChanged(samplerate);
+ emit samplerateChanged( samplerate );
}
+
/// \brief Called when the timebase spinbox changes its value.
/// \param timebase The timebase in seconds.
-void HorizontalDock::timebaseSelected(double timebase) {
+void HorizontalDock::timebaseSelected( double timebase ) {
+ // printf( "HD::timebaseSelected( %g )\n", timebase );
scope->horizontal.timebase = timebase;
- scope->horizontal.samplerateSource = DsoSettingsScopeHorizontal::Duration;
- emit timebaseChanged(timebase);
+ calculateSamplerateSteps( timebase );
+ emit timebaseChanged( timebase );
+}
+
+
+void HorizontalDock::calculateSamplerateSteps( double timebase ) {
+ int size = samplerateSteps.size();
+ if ( size ) {
+ // search appropriate min & max sample rate
+ double min = samplerateSteps[ 0 ];
+ double max = samplerateSteps[ 0 ];
+ for ( int id = 0; id < size; ++id ) {
+ double sRate = samplerateSteps[ id ];
+ // printf( "sRate %g, sRate*timebase %g\n", sRate, sRate * timebase );
+ // min must be < maxRate
+ // find minimal samplerate to get at least this number of samples per div
+ if ( id < size - 1 && sRate * timebase <= 10 ) { // 10 samples/div
+ min = sRate;
+ }
+ // max must be > minRate
+ // find max samplesrate to get not more then this number of samples per div
+ // number should be <= 1000 to get enough samples for two full screens (to ensure triggering)
+ if ( id && sRate * timebase <= 1000 ) { // 1000 samples/div
+ max = sRate;
+ }
+ }
+ min = qMax( min, qMin( 10e3, max ) ); // not less than 10kS unless max is smaller
+ // printf( "HD::cSS( %g ) -> %g, %g\n", timebase, min, max );
+ setSamplerateLimits( min, max );
+ }
}
-/// \brief Called when the record length combo box changes its value.
-/// \param index The index of the combo box item.
-void HorizontalDock::recordLengthSelected(int index) {
- scope->horizontal.recordLength = this->recordLengthComboBox->itemData(index).toUInt();
- emit recordLengthChanged(index);
-}
/// \brief Called when the format combo box changes its value.
/// \param index The index of the combo box item.
-void HorizontalDock::formatSelected(int index) {
- scope->horizontal.format = (Dso::GraphFormat)index;
- emit formatChanged(scope->horizontal.format);
+void HorizontalDock::formatSelected( int index ) {
+ scope->horizontal.format = Dso::GraphFormat( index );
+ emit formatChanged( scope->horizontal.format );
+}
+
+
+/// \brief Called when the calfreq spinbox changes its value.
+/// \param calfreq The calibration frequency in hertz.
+void HorizontalDock::calfreqSelected( double calfreq ) {
+ // printf( "calfreqSelected: %g\n", calfreq );
+ scope->horizontal.calfreq = calfreq;
+ emit calfreqChanged( calfreq );
}
diff --git a/openhantek/src/docks/HorizontalDock.h b/openhantek/src/docks/HorizontalDock.h
index da1b16d6..78ea1fbf 100644
--- a/openhantek/src/docks/HorizontalDock.h
+++ b/openhantek/src/docks/HorizontalDock.h
@@ -7,6 +7,7 @@
#include
+#include "hantekdso/controlspecification.h"
#include "hantekdso/enums.h"
class QLabel;
@@ -16,9 +17,10 @@ class QComboBox;
class SiSpinBox;
struct DsoSettingsScope;
+// struct ControlSpecification;
-Q_DECLARE_METATYPE(std::vector)
-Q_DECLARE_METATYPE(std::vector)
+Q_DECLARE_METATYPE( std::vector< unsigned > )
+Q_DECLARE_METATYPE( std::vector< double > )
/// \brief Dock window for the horizontal axis.
/// It contains the settings for the timebase and the display format.
@@ -30,69 +32,69 @@ class HorizontalDock : public QDockWidget {
/// \param settings The target settings object.
/// \param parent The parent widget.
/// \param flags Flags for the window manager.
- HorizontalDock(DsoSettingsScope *scope, QWidget *parent, Qt::WindowFlags flags = 0);
+ HorizontalDock( DsoSettingsScope *scope, const Dso::ControlSpecification *spec, QWidget *parent );
- /// \brief Changes the frequencybase.
- /// \param frequencybase The frequencybase in hertz.
- void setFrequencybase(double timebase);
/// \brief Changes the samplerate.
/// \param samplerate The samplerate in seconds.
- void setSamplerate(double samplerate);
+ double setSamplerate( double samplerate );
/// \brief Changes the timebase.
/// \param timebase The timebase in seconds.
- double setTimebase(double timebase);
+ double setTimebase( double timebase );
/// \brief Changes the record length if the new value is supported.
/// \param recordLength The record length in samples.
- void setRecordLength(unsigned int recordLength);
+ void setRecordLength( unsigned int recordLength );
/// \brief Changes the format if the new value is supported.
/// \param format The format for the horizontal axis.
/// \return Index of format-value, -1 on error.
- int setFormat(Dso::GraphFormat format);
- /// \brief Updates the available record lengths in the combo box.
- /// \param recordLengths The available record lengths for the combo box.
- void setAvailableRecordLengths(const std::vector &recordLengths);
+ int setFormat( Dso::GraphFormat format );
/// \brief Updates the minimum and maximum of the samplerate spin box.
/// \param minimum The minimum value the spin box should accept.
/// \param maximum The minimum value the spin box should accept.
- void setSamplerateLimits(double minimum, double maximum);
+ void setSamplerateLimits( double minimum, double maximum );
/// \brief Updates the mode and steps of the samplerate spin box.
- /// \param mode The mode value the spin box should accept.
/// \param steps The steps value the spin box should accept.
- void setSamplerateSteps(int mode, QList sampleSteps);
+ void setSamplerateSteps( int mode, QList< double > sampleSteps );
+ void calculateSamplerateSteps( double timebase );
+ /// \brief Changes the calibration frequency.
+ /// \param calfreq The calibration frequency in hertz.
+ double setCalfreq( double calfreq );
+
+ public slots:
+ /// \brief Loads settings into GUI
+ /// \param scope Settings to load
+ void loadSettings( DsoSettingsScope *scope );
protected:
- void closeEvent(QCloseEvent *event);
-
- QGridLayout *dockLayout; ///< The main layout for the dock window
- QWidget *dockWidget; ///< The main widget for the dock window
- QLabel *samplerateLabel; ///< The label for the samplerate spinbox
- QLabel *timebaseLabel; ///< The label for the timebase spinbox
- QLabel *frequencybaseLabel; ///< The label for the frequencybase spinbox
- QLabel *recordLengthLabel; ///< The label for the record length combobox
- QLabel *formatLabel; ///< The label for the format combobox
- SiSpinBox *samplerateSiSpinBox; ///< Selects the samplerate for aquisitions
- SiSpinBox *timebaseSiSpinBox; ///< Selects the timebase for voltage graphs
- SiSpinBox *frequencybaseSiSpinBox; ///< Selects the frequencybase for spectrum graphs
- QComboBox *recordLengthComboBox; ///< Selects the record length for aquisitions
- QComboBox *formatComboBox; ///< Selects the way the sampled data is
- /// interpreted and shown
-
- DsoSettingsScope *scope; ///< The settings provided by the parent class
- QList timebaseSteps; ///< Steps for the timebase spinbox
+ void closeEvent( QCloseEvent *event );
+ QGridLayout *dockLayout; ///< The main layout for the dock window
+ QWidget *dockWidget; ///< The main widget for the dock window
+ QLabel *samplerateLabel; ///< The label for the samplerate spinbox
+ QLabel *timebaseLabel; ///< The label for the timebase spinbox
+ QLabel *formatLabel; ///< The label for the format combobox
+ QLabel *calfreqLabel; ///< The label for the calibration frequency spinbox
+ SiSpinBox *samplerateSiSpinBox; ///< Selects the samplerate for aquisitions
+ SiSpinBox *timebaseSiSpinBox; ///< Selects the timebase for voltage graphs
+ QComboBox *formatComboBox; ///< Selects the way the sampled data is
+ /// interpreted and shown
+ SiSpinBox *calfreqSiSpinBox; ///< Selects the calibration frequency
+
+ DsoSettingsScope *scope; ///< The settings provided by the parent class
+ QList< double > timebaseSteps; ///< Steps for the timebase spinbox
+ QList< double > calfreqSteps; ///< Steps for the calfreq spinbox
+ QList< double > samplerateSteps; ///< Possible sampe rates
QStringList formatStrings; ///< Strings for the formats
protected slots:
- void frequencybaseSelected(double frequencybase);
- void samplerateSelected(double samplerate);
- void timebaseSelected(double timebase);
- void recordLengthSelected(int index);
- void formatSelected(int index);
+ void samplerateSelected( double samplerate );
+ void timebaseSelected( double timebase );
+ void formatSelected( int index );
+ void calfreqSelected( double calfreq );
signals:
- void frequencybaseChanged(double frequencybase); ///< The frequencybase has been changed
- void samplerateChanged(double samplerate); ///< The samplerate has been changed
- void timebaseChanged(double timebase); ///< The timebase has been changed
- void recordLengthChanged(unsigned long recordLength); ///< The recordd length has been changed
- void formatChanged(Dso::GraphFormat format); ///< The viewing format has been changed
+ void samplerateChanged( double samplerate ); ///< The samplerate has been changed
+ void timebaseChanged( double timebase ); ///< The timebase has been changed
+ void recordLengthChanged( unsigned long recordLength ); ///< The recordd length has been changed
+ void formatChanged( Dso::GraphFormat format ); ///< The viewing format has been changed
+ void calfreqChanged( double calfreq ); ///< The timebase has been changed
};
diff --git a/openhantek/src/docks/SpectrumDock.cpp b/openhantek/src/docks/SpectrumDock.cpp
index 2d53607b..d380e182 100644
--- a/openhantek/src/docks/SpectrumDock.cpp
+++ b/openhantek/src/docks/SpectrumDock.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -12,89 +13,144 @@
#include "SpectrumDock.h"
#include "dockwindows.h"
-#include "settings.h"
+#include "dsosettings.h"
#include "sispinbox.h"
#include "utils/printutils.h"
-template struct SELECT {
- template
- static constexpr auto OVERLOAD_OF( R (C::*pmf)(Args...) ) -> decltype(pmf) {
+
+template < typename... Args > struct SELECT {
+ template < typename C, typename R > static constexpr auto OVERLOAD_OF( R ( C::*pmf )( Args... ) ) -> decltype( pmf ) {
return pmf;
}
};
-SpectrumDock::SpectrumDock(DsoSettingsScope *scope, QWidget *parent, Qt::WindowFlags flags)
- : QDockWidget(tr("Spectrum"), parent, flags), scope(scope) {
+SpectrumDock::SpectrumDock( DsoSettingsScope *scope, QWidget *parent ) : QDockWidget( tr( "Spectrum" ), parent ), scope( scope ) {
// Initialize lists for comboboxes
- this->magnitudeSteps = { 1e0 , 2e0 , 3e0 , 6e0 , 1e1 , 2e1 , 3e1 , 6e1 , 1e2 , 2e2 , 3e2, 6e2 };
- for (const auto& magnitude: magnitudeSteps)
- this->magnitudeStrings << valueToString(magnitude, UNIT_DECIBEL, 0);
+ this->magnitudeSteps = {1, 2, 3, 6, 10, 20, 40, 60, 80, 100};
+ for ( const auto &magnitude : magnitudeSteps )
+ this->magnitudeStrings << valueToString( magnitude, UNIT_DECIBEL, 0 );
this->dockLayout = new QGridLayout();
- this->dockLayout->setColumnMinimumWidth(0, 64);
- this->dockLayout->setColumnStretch(1, 1);
+ this->dockLayout->setColumnMinimumWidth( 0, 64 );
+ this->dockLayout->setColumnStretch( 1, 1 );
+ this->dockLayout->setSpacing( DOCK_LAYOUT_SPACING );
// Initialize elements
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
+ unsigned channel;
+ for ( channel = 0; channel < scope->voltage.size(); ++channel ) {
ChannelBlock b;
- b.magnitudeComboBox=(new QComboBox());
- b.usedCheckBox=(new QCheckBox(scope->voltage[channel].name));
+ b.magnitudeComboBox = ( new QComboBox() );
+ QString name = scope->spectrum[ channel ].name;
+ name.insert( int( channel ), '&' ); // &SP1, S&P2, SP&M
+ b.usedCheckBox = ( new QCheckBox( name ) );
- channelBlocks.push_back(b);
+ channelBlocks.push_back( b );
- this->dockLayout->addWidget(b.usedCheckBox, (int)channel, 0);
- this->dockLayout->addWidget(b.magnitudeComboBox, (int)channel, 1);
+ this->dockLayout->addWidget( b.usedCheckBox, int( channel ), 0 );
+ this->dockLayout->addWidget( b.magnitudeComboBox, int( channel ), 1 );
- b.magnitudeComboBox->addItems(this->magnitudeStrings);
- this->setMagnitude(channel, scope->spectrum[channel].magnitude);
- this->setUsed(channel, scope->spectrum[channel].used);
+ b.magnitudeComboBox->addItems( this->magnitudeStrings );
// Connect signals and slots
- connect(b.usedCheckBox, &QCheckBox::toggled, [this,channel](bool checked) {
+ connect( b.usedCheckBox, &QCheckBox::toggled, [this, channel]( bool checked ) {
// Send signal if it was one of the checkboxes
- if (channel < this->scope->voltage.size()) {
- this->scope->spectrum[channel].used = checked;
- emit usedChanged(channel, checked);
- }
- });
-
- connect(b.magnitudeComboBox, SELECT::OVERLOAD_OF(&QComboBox::currentIndexChanged), [this,channel](unsigned index) {
- // Send signal if it was one of the comboboxes
- if (channel < this->scope->voltage.size()) {
- this->scope->spectrum[channel].magnitude = this->magnitudeSteps.at(index);
- emit magnitudeChanged(channel, this->scope->spectrum[channel].magnitude);
+ if ( channel < this->scope->voltage.size() ) {
+ this->scope->spectrum[ channel ].used = checked;
+ emit usedChanged( channel, checked );
}
- });
+ } );
+
+ connect( b.magnitudeComboBox, SELECT< int >::OVERLOAD_OF( &QComboBox::currentIndexChanged ),
+ [this, channel]( unsigned index ) {
+ // Send signal if it was one of the comboboxes
+ if ( channel < this->scope->voltage.size() ) {
+ this->scope->spectrum[ channel ].magnitude = this->magnitudeSteps.at( index );
+ emit magnitudeChanged( channel, this->scope->spectrum[ channel ].magnitude );
+ }
+ } );
}
+ frequencybaseLabel = new QLabel( tr( "Frequencybase" ) );
+ frequencybaseSiSpinBox = new SiSpinBox( UNIT_HERTZ );
+ frequencybaseSiSpinBox->setMinimum( 0.1 );
+ frequencybaseSiSpinBox->setMaximum( 100e6 );
+ dockLayout->addWidget( this->frequencybaseLabel, int( channel ), 0 );
+ dockLayout->addWidget( this->frequencybaseSiSpinBox, int( channel ), 1 );
+ connect( frequencybaseSiSpinBox, SELECT< double >::OVERLOAD_OF( &QDoubleSpinBox::valueChanged ), this,
+ &SpectrumDock::frequencybaseSelected );
+
+ // Load settings into GUI
+ this->loadSettings( scope );
dockWidget = new QWidget();
- SetupDockWidget(this, dockWidget, dockLayout);
+ SetupDockWidget( this, dockWidget, dockLayout );
}
+
+void SpectrumDock::loadSettings( DsoSettingsScope *scope ) {
+ // Initialize elements
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ this->setMagnitude( channel, scope->spectrum[ channel ].magnitude );
+ this->setUsed( channel, scope->spectrum[ channel ].used );
+ }
+ setFrequencybase( scope->horizontal.frequencybase );
+}
+
+
/// \brief Don't close the dock, just hide it
/// \param event The close event that should be handled.
-void SpectrumDock::closeEvent(QCloseEvent *event) {
+void SpectrumDock::closeEvent( QCloseEvent *event ) {
this->hide();
-
event->accept();
}
-int SpectrumDock::setMagnitude(ChannelID channel, double magnitude) {
- if (channel >= scope->voltage.size()) return -1;
- QSignalBlocker blocker(channelBlocks[channel].magnitudeComboBox);
- auto indexIt = std::find(magnitudeSteps.begin(),magnitudeSteps.end(),magnitude);
- if (indexIt == magnitudeSteps.end()) return -1;
- int index = (int)std::distance(magnitudeSteps.begin(), indexIt);
- channelBlocks[channel].magnitudeComboBox->setCurrentIndex(index);
+int SpectrumDock::setMagnitude( ChannelID channel, double magnitude ) {
+ if ( channel >= scope->voltage.size() )
+ return -1;
+ QSignalBlocker blocker( channelBlocks[ channel ].magnitudeComboBox );
+
+ auto indexIt = std::find( magnitudeSteps.begin(), magnitudeSteps.end(), magnitude );
+ if ( indexIt == magnitudeSteps.end() )
+ return -1;
+ int index = int( std::distance( magnitudeSteps.begin(), indexIt ) );
+ channelBlocks[ channel ].magnitudeComboBox->setCurrentIndex( index );
return index;
}
-unsigned SpectrumDock::setUsed(ChannelID channel, bool used) {
- if (channel >= scope->voltage.size()) return INT_MAX;
- QSignalBlocker blocker(channelBlocks[channel].usedCheckBox);
- channelBlocks[channel].usedCheckBox->setChecked(used);
+unsigned SpectrumDock::setUsed( ChannelID channel, bool used ) {
+ if ( channel >= scope->voltage.size() )
+ return INT_MAX;
+ QSignalBlocker blocker( channelBlocks[ channel ].usedCheckBox );
+
+ channelBlocks[ channel ].usedCheckBox->setChecked( used );
return channel;
}
+
+
+/// \brief Called when the samplerate from horizontal dock changes its value.
+/// \param samplerare The samplerate in hertz.
+void SpectrumDock::setSamplerate( double samplerate ) {
+ // printf( "SD::setSamplerate( %g )\n", samplerate );
+ double maxFreqBase = samplerate / DIVS_TIME / 2; // Nyquist frequency
+ frequencybaseSiSpinBox->setMaximum( maxFreqBase );
+ if ( frequencybaseSiSpinBox->value() > maxFreqBase )
+ setFrequencybase( maxFreqBase );
+}
+
+
+void SpectrumDock::setFrequencybase( double frequencybase ) {
+ // printf( "SD::setFrequencybase( %g )\n", frequencybase );
+ QSignalBlocker blocker( frequencybaseSiSpinBox );
+ frequencybaseSiSpinBox->setValue( frequencybase );
+}
+
+
+/// \brief Called when the frequencybase spinbox changes its value.
+/// \param frequencybase The frequencybase in hertz.
+void SpectrumDock::frequencybaseSelected( double frequencybase ) {
+ // printf( "SD::frequencybaseSelected( %g )\n", frequencybase );
+ scope->horizontal.frequencybase = frequencybase;
+ emit frequencybaseChanged( frequencybase );
+}
diff --git a/openhantek/src/docks/SpectrumDock.h b/openhantek/src/docks/SpectrumDock.h
index 11b5e12b..4ee56942 100644
--- a/openhantek/src/docks/SpectrumDock.h
+++ b/openhantek/src/docks/SpectrumDock.h
@@ -24,39 +24,58 @@ class SpectrumDock : public QDockWidget {
/// \param settings The target settings object.
/// \param parent The parent widget.
/// \param flags Flags for the window manager.
- SpectrumDock(DsoSettingsScope *scope, QWidget *parent, Qt::WindowFlags flags = 0);
+ SpectrumDock( DsoSettingsScope *scope, QWidget *parent );
/// \brief Sets the magnitude for a channel.
/// \param channel The channel, whose magnitude should be set.
/// \param magnitude The magnitude in dB.
/// \return Index of magnitude-value, -1 on error.
- int setMagnitude(ChannelID channel, double magnitude);
+ int setMagnitude( ChannelID channel, double magnitude );
/// \brief Enables/disables a channel.
/// \param channel The channel, that should be enabled/disabled.
/// \param used True if the channel should be enabled, false otherwise.
/// \return Index of channel, INT_MAX on error.
- unsigned setUsed(ChannelID channel, bool used);
+ unsigned setUsed( ChannelID channel, bool used );
+
+ /// \brief Changes the frequencybase.
+ /// \param frequencybase The frequencybase in hertz.
+ void setFrequencybase( double timebase );
+
+ public slots:
+ /// \brief Loads settings into GUI
+ /// \param scope Settings to load
+ void loadSettings( DsoSettingsScope *scope );
+
+ /// \brief Called when the samplerate from horizontal dock changes its value.
+ /// \param samplerare The samplerate in hertz.
+ void setSamplerate( double samplerate );
+
+ private slots:
+ void frequencybaseSelected( double frequencybase );
protected:
- void closeEvent(QCloseEvent *event);
+ void closeEvent( QCloseEvent *event );
- QGridLayout *dockLayout; ///< The main layout for the dock window
- QWidget *dockWidget; ///< The main widget for the dock window
+ QGridLayout *dockLayout; ///< The main layout for the dock window
+ QWidget *dockWidget; ///< The main widget for the dock window
struct ChannelBlock {
- QCheckBox * usedCheckBox; ///< Enable/disable a specific channel
- QComboBox * magnitudeComboBox; ///< Select the vertical magnitude for the spectrums
+ QCheckBox *usedCheckBox; ///< Enable/disable a specific channel
+ QComboBox *magnitudeComboBox; ///< Select the vertical magnitude for the spectrums
};
- std::vector channelBlocks;
+ std::vector< ChannelBlock > channelBlocks;
- DsoSettingsScope* scope; ///< The settings provided by the parent class
+ DsoSettingsScope *scope; ///< The settings provided by the parent class
- std::vector magnitudeSteps; ///< The selectable magnitude steps in dB/div
- QStringList magnitudeStrings; ///< String representations for the magnitude steps
+ std::vector< double > magnitudeSteps; ///< The selectable magnitude steps in dB/div
+ QStringList magnitudeStrings; ///< String representations for the magnitude steps
+ QLabel *frequencybaseLabel; ///< The label for the frequencybase spinbox
+ SiSpinBox *frequencybaseSiSpinBox; ///< Selects the frequencybase for spectrum graphs
signals:
- void magnitudeChanged(ChannelID channel, double magnitude); ///< A magnitude has been selected
- void usedChanged(ChannelID channel, bool used); ///< A spectrum has been enabled/disabled
+ void magnitudeChanged( ChannelID channel, double magnitude ); ///< A magnitude has been selected
+ void usedChanged( ChannelID channel, bool used ); ///< A spectrum has been enabled/disabled
+ void frequencybaseChanged( double frequencybase ); ///< The frequencybase has been changed
};
diff --git a/openhantek/src/docks/TriggerDock.cpp b/openhantek/src/docks/TriggerDock.cpp
index 03e9297e..7013a16f 100644
--- a/openhantek/src/docks/TriggerDock.cpp
+++ b/openhantek/src/docks/TriggerDock.cpp
@@ -12,105 +12,104 @@
#include "TriggerDock.h"
#include "dockwindows.h"
+#include "dsosettings.h"
#include "hantekdso/controlspecification.h"
-#include "settings.h"
#include "sispinbox.h"
#include "utils/printutils.h"
-TriggerDock::TriggerDock(DsoSettingsScope *scope, const Dso::ControlSpecification *spec, QWidget *parent,
- Qt::WindowFlags flags)
- : QDockWidget(tr("Trigger"), parent, flags), scope(scope), mSpec(spec) {
+
+TriggerDock::TriggerDock( DsoSettingsScope *scope, const Dso::ControlSpecification *spec, QWidget *parent )
+ : QDockWidget( tr( "Trigger" ), parent ), scope( scope ), mSpec( spec ) {
// Initialize lists for comboboxes
- for (ChannelID channel = 0; channel < mSpec->channels; ++channel)
- this->sourceStandardStrings << tr("CH%1").arg(channel + 1);
- for (const Dso::SpecialTriggerChannel &specialTrigger : mSpec->specialTriggerChannels)
- this->sourceSpecialStrings.append(QString::fromStdString(specialTrigger.name));
+ for ( ChannelID channel = 0; channel < mSpec->channels; ++channel )
+ this->sourceStandardStrings << tr( "CH%1" ).arg( channel + 1 );
+ // add "smooth" source
+ for ( ChannelID channel = 0; channel < mSpec->channels; ++channel )
+ this->sourceStandardStrings << tr( "CH%1 smooth" ).arg( channel + 1 );
// Initialize elements
- this->modeLabel = new QLabel(tr("Mode"));
- this->modeComboBox = new QComboBox();
- for (Dso::TriggerMode mode : mSpec->triggerModes) this->modeComboBox->addItem(Dso::triggerModeString(mode));
-
- this->slopeLabel = new QLabel(tr("Slope"));
- this->slopeComboBox = new QComboBox();
- for (Dso::Slope slope : Dso::SlopeEnum) this->slopeComboBox->addItem(Dso::slopeString(slope));
-
- this->sourceLabel = new QLabel(tr("Source"));
- this->sourceComboBox = new QComboBox();
- this->sourceComboBox->addItems(this->sourceStandardStrings);
- this->sourceComboBox->addItems(this->sourceSpecialStrings);
-
- this->dockLayout = new QGridLayout();
- this->dockLayout->setColumnMinimumWidth(0, 64);
- this->dockLayout->setColumnStretch(1, 1);
- this->dockLayout->addWidget(this->modeLabel, 0, 0);
- this->dockLayout->addWidget(this->modeComboBox, 0, 1);
- this->dockLayout->addWidget(this->sourceLabel, 1, 0);
- this->dockLayout->addWidget(this->sourceComboBox, 1, 1);
- this->dockLayout->addWidget(this->slopeLabel, 2, 0);
- this->dockLayout->addWidget(this->slopeComboBox, 2, 1);
-
- this->dockWidget = new QWidget();
- SetupDockWidget(this, dockWidget, dockLayout);
-
- // Set values
- setMode(scope->trigger.mode);
- setSlope(scope->trigger.slope);
- setSource(scope->trigger.special, scope->trigger.source);
+ modeLabel = new QLabel( tr( "Mode" ) );
+ modeComboBox = new QComboBox();
+ for ( Dso::TriggerMode mode : mSpec->triggerModes )
+ modeComboBox->addItem( Dso::triggerModeString( mode ) );
+
+ slopeLabel = new QLabel( tr( "Slope" ) );
+ slopeComboBox = new QComboBox();
+ for ( Dso::Slope slope : Dso::SlopeEnum )
+ slopeComboBox->addItem( Dso::slopeString( slope ) );
+
+ sourceLabel = new QLabel( tr( "Source" ) );
+ sourceComboBox = new QComboBox();
+ sourceComboBox->addItems( sourceStandardStrings );
+
+ dockLayout = new QGridLayout();
+ dockLayout->setColumnMinimumWidth( 0, 64 );
+ dockLayout->setColumnStretch( 1, 1 );
+ dockLayout->setSpacing( DOCK_LAYOUT_SPACING );
+ dockLayout->addWidget( modeLabel, 0, 0 );
+ dockLayout->addWidget( modeComboBox, 0, 1 );
+ dockLayout->addWidget( sourceLabel, 1, 0 );
+ dockLayout->addWidget( sourceComboBox, 1, 1 );
+ dockLayout->addWidget( slopeLabel, 2, 0 );
+ dockLayout->addWidget( slopeComboBox, 2, 1 );
+
+ dockWidget = new QWidget();
+ SetupDockWidget( this, dockWidget, dockLayout );
+
+ // Load settings into GUI
+ loadSettings( scope );
// Connect signals and slots
- connect(this->modeComboBox, static_cast(&QComboBox::currentIndexChanged),
- [this, spec](int index) {
- this->scope->trigger.mode = mSpec->triggerModes[(unsigned)index];
- emit modeChanged(this->scope->trigger.mode);
- });
- connect(this->slopeComboBox, static_cast(&QComboBox::currentIndexChanged),
- [this](int index) {
- this->scope->trigger.slope = (Dso::Slope)index;
- emit slopeChanged(this->scope->trigger.slope);
- });
- connect(this->sourceComboBox, static_cast(&QComboBox::currentIndexChanged),
- [this](int index) {
- bool special = false;
-
- if (index >= this->sourceStandardStrings.count()) {
- index -= this->sourceStandardStrings.count();
- special = true;
- }
-
- this->scope->trigger.source = (unsigned)index;
- this->scope->trigger.special = special;
- emit sourceChanged(special, (unsigned)index);
- });
+ connect( modeComboBox, static_cast< void ( QComboBox::* )( int ) >( &QComboBox::currentIndexChanged ), [this]( int index ) {
+ this->scope->trigger.mode = mSpec->triggerModes[ unsigned( index ) ];
+ emit modeChanged( this->scope->trigger.mode );
+ } );
+ connect( slopeComboBox, static_cast< void ( QComboBox::* )( int ) >( &QComboBox::currentIndexChanged ), [this]( int index ) {
+ this->scope->trigger.slope = Dso::Slope( index );
+ emit slopeChanged( this->scope->trigger.slope );
+ } );
+ connect( sourceComboBox, static_cast< void ( QComboBox::* )( int ) >( &QComboBox::currentIndexChanged ),
+ [this]( unsigned index ) {
+ bool smooth = index >= mSpec->channels;
+ this->scope->trigger.smooth = smooth;
+ this->scope->trigger.source = index & ( mSpec->channels - 1 );
+ emit sourceChanged( index & ( mSpec->channels - 1 ), smooth );
+ } );
+}
+
+void TriggerDock::loadSettings( DsoSettingsScope *scope ) {
+ // Set values
+ setMode( scope->trigger.mode );
+ setSlope( scope->trigger.slope );
+ setSource( int( scope->trigger.source ), scope->trigger.smooth );
}
/// \brief Don't close the dock, just hide it
/// \param event The close event that should be handled.
-void TriggerDock::closeEvent(QCloseEvent *event) {
+void TriggerDock::closeEvent( QCloseEvent *event ) {
this->hide();
event->accept();
}
-void TriggerDock::setMode(Dso::TriggerMode mode) {
- int index = std::find(mSpec->triggerModes.begin(), mSpec->triggerModes.end(), mode) - mSpec->triggerModes.begin();
- QSignalBlocker blocker(modeComboBox);
- modeComboBox->setCurrentIndex(index);
+void TriggerDock::setMode( Dso::TriggerMode mode ) {
+ int index = int( std::find( mSpec->triggerModes.begin(), mSpec->triggerModes.end(), mode ) - mSpec->triggerModes.begin() );
+ QSignalBlocker blocker( modeComboBox );
+ modeComboBox->setCurrentIndex( index );
+ emit modeChanged( this->scope->trigger.mode );
}
-void TriggerDock::setSlope(Dso::Slope slope) {
- QSignalBlocker blocker(slopeComboBox);
- slopeComboBox->setCurrentIndex((int)slope);
+void TriggerDock::setSlope( Dso::Slope slope ) {
+ QSignalBlocker blocker( slopeComboBox );
+ slopeComboBox->setCurrentIndex( int( slope ) );
}
-void TriggerDock::setSource(bool special, unsigned int id) {
- if ((!special && id >= (unsigned int)this->sourceStandardStrings.count()) ||
- (special && id >= (unsigned int)this->sourceSpecialStrings.count()))
+void TriggerDock::setSource( int id, bool smooth ) {
+ if ( smooth )
+ id += mSpec->channels;
+ if ( id >= this->sourceStandardStrings.count() )
return;
-
- int index = (int)id;
- if (special) index += this->sourceStandardStrings.count();
- QSignalBlocker blocker(sourceComboBox);
- sourceComboBox->setCurrentIndex(index);
+ QSignalBlocker blocker( sourceComboBox );
+ sourceComboBox->setCurrentIndex( id );
}
diff --git a/openhantek/src/docks/TriggerDock.h b/openhantek/src/docks/TriggerDock.h
index e361aa16..6e969c99 100644
--- a/openhantek/src/docks/TriggerDock.h
+++ b/openhantek/src/docks/TriggerDock.h
@@ -2,11 +2,11 @@
#pragma once
+#include
+#include
#include
#include
#include
-#include
-#include
#include "hantekdso/enums.h"
@@ -27,23 +27,28 @@ class TriggerDock : public QDockWidget {
/// \param spec
/// \param parent The parent widget.
/// \param flags Flags for the window manager.
- TriggerDock(DsoSettingsScope *scope, const Dso::ControlSpecification* mSpec, QWidget *parent, Qt::WindowFlags flags = 0);
+ TriggerDock( DsoSettingsScope *scope, const Dso::ControlSpecification *mSpec, QWidget *parent );
/// \brief Changes the trigger mode if the new mode is supported.
/// \param mode The trigger mode.
- void setMode(Dso::TriggerMode mode);
+ void setMode( Dso::TriggerMode mode );
/// \brief Changes the trigger source if the new source is supported.
- /// \param special true for a special channel (EXT, ...) as trigger source.
/// \param id The number of the channel, that should be used as trigger.
- void setSource(bool special, unsigned int id);
+ /// \param smooth Don't trigger on glitches
+ void setSource( int id, bool smooth );
/// \brief Changes the trigger slope if the new slope is supported.
/// \param slope The trigger slope.
- void setSlope(Dso::Slope slope);
+ void setSlope( Dso::Slope slope );
+
+ public slots:
+ /// \brief Loads settings into GUI
+ /// \param scope Settings to load
+ void loadSettings( DsoSettingsScope *scope );
protected:
- void closeEvent(QCloseEvent *event);
+ void closeEvent( QCloseEvent *event );
QGridLayout *dockLayout; ///< The main layout for the dock window
QWidget *dockWidget; ///< The main widget for the dock window
@@ -55,12 +60,12 @@ class TriggerDock : public QDockWidget {
QComboBox *slopeComboBox; ///< Select the slope that causes triggering
DsoSettingsScope *scope; ///< The settings provided by the parent class
- const Dso::ControlSpecification* mSpec;
+ const Dso::ControlSpecification *mSpec;
QStringList sourceStandardStrings; ///< Strings for the standard trigger sources
- QStringList sourceSpecialStrings; ///< Strings for the special trigger sources
+
signals:
- void modeChanged(Dso::TriggerMode); ///< The trigger mode has been changed
- void sourceChanged(bool special, unsigned int id); ///< The trigger source has been changed
- void slopeChanged(Dso::Slope); ///< The trigger slope has been changed
+ void modeChanged( Dso::TriggerMode ); ///< The trigger mode has been changed
+ void sourceChanged( unsigned int id, bool smooth ); ///< The trigger source has been changed
+ void slopeChanged( Dso::Slope ); ///< The trigger slope has been changed
};
diff --git a/openhantek/src/docks/VoltageDock.cpp b/openhantek/src/docks/VoltageDock.cpp
index 5cfb7ad0..295878f6 100644
--- a/openhantek/src/docks/VoltageDock.cpp
+++ b/openhantek/src/docks/VoltageDock.cpp
@@ -1,10 +1,8 @@
// SPDX-License-Identifier: GPL-2.0+
-#include
#include
-#include
+#include
#include
-#include
#include
#include
@@ -12,118 +10,186 @@
#include "VoltageDock.h"
#include "dockwindows.h"
-#include "settings.h"
+#include "dsosettings.h"
#include "sispinbox.h"
#include "utils/printutils.h"
-template struct SELECT {
- template
- static constexpr auto OVERLOAD_OF( R (C::*pmf)(Args...) ) -> decltype(pmf) {
+
+template < typename... Args > struct SELECT {
+ template < typename C, typename R > static constexpr auto OVERLOAD_OF( R ( C::*pmf )( Args... ) ) -> decltype( pmf ) {
return pmf;
}
};
-VoltageDock::VoltageDock(DsoSettingsScope *scope, const Dso::ControlSpecification *spec, QWidget *parent, Qt::WindowFlags flags)
- : QDockWidget(tr("Voltage"), parent, flags), scope(scope), spec(spec) {
-
+VoltageDock::VoltageDock( DsoSettingsScope *scope, const Dso::ControlSpecification *spec, QWidget *parent )
+ : QDockWidget( tr( "Voltage" ), parent ), scope( scope ), spec( spec ) {
// Initialize lists for comboboxes
- for (Dso::Coupling c: spec->couplings)
- couplingStrings.append(Dso::couplingString(c));
+ for ( Dso::Coupling c : spec->couplings )
+ if ( c == Dso::Coupling::DC || scope->hasACcoupling || scope->hasACmodification )
+ couplingStrings.append( Dso::couplingString( c ) );
- for( auto e: Dso::MathModeEnum ) {
- modeStrings.append(Dso::mathModeString(e));
+ for ( auto e : Dso::MathModeEnum ) {
+ modeStrings.append( Dso::mathModeString( e ) );
}
- for (double gainStep: scope->gainSteps)
- gainStrings << valueToString(gainStep, UNIT_VOLTS, 0);
+ for ( double gainStep : scope->gainSteps ) {
+ gainStrings << valueToString( gainStep, UNIT_VOLTS, 0 );
+ }
dockLayout = new QGridLayout();
- dockLayout->setColumnMinimumWidth(0, 64);
- dockLayout->setColumnStretch(1, 1);
-
+ dockLayout->setColumnMinimumWidth( 0, 64 );
+ dockLayout->setColumnStretch( 1, 1 ); // stretch ComboBox in 2nd (middle) column
+ dockLayout->setColumnStretch( 2, 1 ); // stretch ComboBox in 3rd (last) column
+ dockLayout->setSpacing( DOCK_LAYOUT_SPACING );
// Initialize elements
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
+ int row = 0;
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
ChannelBlock b;
- b.miscComboBox=(new QComboBox());
- b.gainComboBox=(new QComboBox());
- b.invertCheckBox=(new QCheckBox(tr("Invert")));
- b.usedCheckBox=(new QCheckBox(scope->voltage[channel].name));
-
- channelBlocks.push_back(std::move(b));
-
- if (channel < spec->channels)
- b.miscComboBox->addItems(couplingStrings);
+ if ( channel < spec->channels )
+ b.usedCheckBox = new QCheckBox( tr( "CH&%1" ).arg( channel + 1 ) ); // define shortcut 1 / 2
else
- b.miscComboBox->addItems(modeStrings);
-
- b.gainComboBox->addItems(gainStrings);
-
- dockLayout->addWidget(b.usedCheckBox, (int)channel * 3, 0);
- dockLayout->addWidget(b.gainComboBox, (int)channel * 3, 1);
- dockLayout->addWidget(b.miscComboBox, (int)channel * 3 + 1, 1);
- dockLayout->addWidget(b.invertCheckBox, (int)channel * 3 + 2, 1);
-
- if (channel < spec->channels)
- setCoupling(channel, scope->voltage[channel].couplingOrMathIndex);
+ b.usedCheckBox = new QCheckBox( tr( "MA&TH" ) );
+ b.miscComboBox = new QComboBox();
+ b.gainComboBox = new QComboBox();
+ b.invertCheckBox = new QCheckBox( tr( "Invert" ) );
+ b.attnSpinBox = new QSpinBox();
+ b.attnSpinBox->setMinimum( ATTENUATION_MIN );
+ b.attnSpinBox->setMaximum( ATTENUATION_MAX );
+ b.attnSpinBox->setPrefix( tr( "x" ) );
+
+ channelBlocks.push_back( std::move( b ) );
+
+ if ( channel < spec->channels )
+ b.miscComboBox->addItems( couplingStrings );
else
- setMode(scope->voltage[channel].couplingOrMathIndex);
- setGain(channel, scope->voltage[channel].gainStepIndex);
- setUsed(channel, scope->voltage[channel].used);
-
- connect(b.gainComboBox, SELECT::OVERLOAD_OF(&QComboBox::currentIndexChanged), [this,channel](int index) {
- this->scope->voltage[channel].gainStepIndex = (unsigned)index;
- emit gainChanged(channel, this->scope->gain(channel));
- });
- connect(b.invertCheckBox, &QAbstractButton::toggled, [this,channel](bool checked) {
- this->scope->voltage[channel].inverted = checked;
- });
- connect(b.miscComboBox, SELECT::OVERLOAD_OF(&QComboBox::currentIndexChanged), [this,channel,spec,scope](int index){
- this->scope->voltage[channel].couplingOrMathIndex = (unsigned)index;
- if (channel < spec->channels) {
- emit couplingChanged(channel, scope->coupling(channel, spec));
- } else {
- emit modeChanged(Dso::getMathMode(this->scope->voltage[channel]));
- }
- });
- connect(b.usedCheckBox, &QAbstractButton::toggled, [this,channel](bool checked) {
- this->scope->voltage[channel].used = checked;
- emit usedChanged(channel, checked);
- });
+ b.miscComboBox->addItems( modeStrings );
+
+ b.gainComboBox->addItems( gainStrings );
+
+ dockLayout->addWidget( b.usedCheckBox, row, 0 );
+ dockLayout->addWidget( b.gainComboBox, row++, 1, 1, 2 );
+ dockLayout->addWidget( b.invertCheckBox, row, 0 );
+ dockLayout->addWidget( b.attnSpinBox, row, 1, 1, 1 );
+ dockLayout->addWidget( b.miscComboBox, row++, 2, 1, 1 );
+
+ // draw divider line
+ if ( channel < spec->channels ) {
+ QFrame *divider = new QFrame();
+ divider->setLineWidth( 1 );
+ divider->setFrameShape( QFrame::HLine );
+ dockLayout->addWidget( divider, row++, 0, 1, 3 );
+ }
+
+ connect( b.gainComboBox, SELECT< int >::OVERLOAD_OF( &QComboBox::currentIndexChanged ), [this, channel]( unsigned index ) {
+ this->scope->voltage[ channel ].gainStepIndex = index;
+ emit gainChanged( channel, this->scope->gain( channel ) );
+ } );
+ connect( b.attnSpinBox, SELECT< int >::OVERLOAD_OF( &QSpinBox::valueChanged ), [this, channel]( unsigned attnValue ) {
+ this->scope->voltage[ channel ].probeAttn = attnValue;
+ setAttn( channel, attnValue );
+ emit probeAttnChanged( channel, attnValue ); // make sure to set the probe first, since this will influence the gain
+ emit gainChanged( channel, this->scope->gain( channel ) );
+ } );
+ connect( b.invertCheckBox, &QAbstractButton::toggled, [this, channel]( bool checked ) {
+ this->scope->voltage[ channel ].inverted = checked;
+ emit invertedChanged( channel, checked );
+ } );
+ connect( b.miscComboBox, SELECT< int >::OVERLOAD_OF( &QComboBox::currentIndexChanged ),
+ [this, channel, spec, scope]( unsigned index ) {
+ this->scope->voltage[ channel ].couplingOrMathIndex = index;
+ if ( channel < spec->channels ) {
+ // setCoupling(channel, (unsigned)index);
+ emit couplingChanged( channel, scope->coupling( channel, spec ) );
+ } else {
+ emit modeChanged( Dso::getMathMode( this->scope->voltage[ channel ] ) );
+ }
+ } );
+ connect( b.usedCheckBox, &QAbstractButton::toggled, [this, channel]( bool checked ) {
+ this->scope->voltage[ channel ].used = checked;
+ emit usedChanged( channel, checked );
+ } );
}
+ // Load settings into GUI
+ this->loadSettings( scope, spec );
+
dockWidget = new QWidget();
- SetupDockWidget(this, dockWidget, dockLayout);
+ SetupDockWidget( this, dockWidget, dockLayout );
+}
+
+void VoltageDock::loadSettings( DsoSettingsScope *scope, const Dso::ControlSpecification *spec ) {
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ if ( channel < spec->channels ) {
+ if ( int( scope->voltage[ channel ].couplingOrMathIndex ) < couplingStrings.size() )
+ setCoupling( channel, scope->voltage[ channel ].couplingOrMathIndex );
+ } else {
+ setMode( scope->voltage[ channel ].couplingOrMathIndex );
+ }
+
+ setGain( channel, scope->voltage[ channel ].gainStepIndex );
+ setUsed( channel, scope->voltage[ channel ].used );
+ setAttn( channel, scope->voltage[ channel ].probeAttn );
+ setInverted( channel, scope->voltage[ channel ].inverted );
+ }
}
/// \brief Don't close the dock, just hide it
/// \param event The close event that should be handled.
-void VoltageDock::closeEvent(QCloseEvent *event) {
+void VoltageDock::closeEvent( QCloseEvent *event ) {
hide();
event->accept();
}
-void VoltageDock::setCoupling(ChannelID channel, unsigned couplingIndex) {
- if (channel >= spec->channels) return;
- if (couplingIndex >= spec->couplings.size()) return;
- QSignalBlocker blocker(channelBlocks[channel].miscComboBox);
- channelBlocks[channel].miscComboBox->setCurrentIndex((int)couplingIndex);
+void VoltageDock::setCoupling( ChannelID channel, unsigned couplingIndex ) {
+ if ( channel >= spec->channels )
+ return;
+ if ( couplingIndex >= spec->couplings.size() )
+ return;
+ QSignalBlocker blocker( channelBlocks[ channel ].miscComboBox );
+ channelBlocks[ channel ].miscComboBox->setCurrentIndex( int( couplingIndex ) );
+}
+
+void VoltageDock::setGain( ChannelID channel, unsigned gainStepIndex ) {
+ if ( channel >= scope->voltage.size() )
+ return;
+ if ( gainStepIndex >= scope->gainSteps.size() )
+ return;
+ QSignalBlocker blocker( channelBlocks[ channel ].gainComboBox );
+ channelBlocks[ channel ].gainComboBox->setCurrentIndex( int( gainStepIndex ) );
+}
+
+void VoltageDock::setAttn( ChannelID channel, double attnValue ) {
+ if ( channel >= scope->voltage.size() )
+ return;
+ QSignalBlocker blocker( channelBlocks[ channel ].gainComboBox );
+ int index = channelBlocks[ channel ].gainComboBox->currentIndex();
+ gainStrings.clear();
+ for ( double gainStep : scope->gainSteps ) {
+ gainStrings << valueToString( gainStep * attnValue, UNIT_VOLTS, -1 ); // auto format
+ }
+ channelBlocks[ channel ].gainComboBox->clear();
+ channelBlocks[ channel ].gainComboBox->addItems( gainStrings );
+ channelBlocks[ channel ].gainComboBox->setCurrentIndex( index );
+ scope->voltage[ channel ].probeAttn = attnValue;
+ channelBlocks[ channel ].attnSpinBox->setValue( int( attnValue ) );
}
-void VoltageDock::setGain(ChannelID channel, unsigned gainStepIndex) {
- if (channel >= scope->voltage.size()) return;
- if (gainStepIndex >= scope->gainSteps.size()) return;
- QSignalBlocker blocker(channelBlocks[channel].gainComboBox);
- channelBlocks[channel].gainComboBox->setCurrentIndex((unsigned)gainStepIndex);
+void VoltageDock::setMode( unsigned mathModeIndex ) {
+ QSignalBlocker blocker( channelBlocks[ spec->channels ].miscComboBox );
+ channelBlocks[ spec->channels ].miscComboBox->setCurrentIndex( int( mathModeIndex ) );
}
-void VoltageDock::setMode(unsigned mathModeIndex) {
- QSignalBlocker blocker(channelBlocks[spec->channels].miscComboBox);
- channelBlocks[spec->channels].miscComboBox->setCurrentIndex((int)mathModeIndex);
+void VoltageDock::setUsed( ChannelID channel, bool used ) {
+ if ( channel >= scope->voltage.size() )
+ return;
+ QSignalBlocker blocker( channelBlocks[ channel ].usedCheckBox );
+ channelBlocks[ channel ].usedCheckBox->setChecked( used );
}
-void VoltageDock::setUsed(ChannelID channel, bool used) {
- if (channel >= scope->voltage.size()) return;
- QSignalBlocker blocker(channelBlocks[channel].usedCheckBox);
- channelBlocks[channel].usedCheckBox->setChecked(used);
+void VoltageDock::setInverted( ChannelID channel, bool inverted ) {
+ if ( channel >= scope->voltage.size() )
+ return;
+ QSignalBlocker blocker( channelBlocks[ channel ].invertCheckBox );
+ channelBlocks[ channel ].invertCheckBox->setChecked( inverted );
}
diff --git a/openhantek/src/docks/VoltageDock.h b/openhantek/src/docks/VoltageDock.h
index 260a84b7..430204f3 100644
--- a/openhantek/src/docks/VoltageDock.h
+++ b/openhantek/src/docks/VoltageDock.h
@@ -2,15 +2,19 @@
#pragma once
-#include
-#include
#include
#include
+#include
+#include
#include
+#include
-#include "scopesettings.h"
#include "hantekdso/controlspecification.h"
#include "post/postprocessingsettings.h"
+#include "scopesettings.h"
+
+#define ATTENUATION_MIN 1 ///< Minimum probe attenuation
+#define ATTENUATION_MAX 1000 ///< Maximum probe attenuation
class SiSpinBox;
@@ -25,41 +29,58 @@ class VoltageDock : public QDockWidget {
/// \param settings The target settings object.
/// \param parent The parent widget.
/// \param flags Flags for the window manager.
- VoltageDock(DsoSettingsScope *scope, const Dso::ControlSpecification* spec, QWidget *parent, Qt::WindowFlags flags = 0);
+ VoltageDock( DsoSettingsScope *scope, const Dso::ControlSpecification *spec, QWidget *parent );
/// \brief Sets the coupling for a channel.
/// \param channel The channel, whose coupling should be set.
/// \param couplingIndex The coupling-mode index.
- void setCoupling(ChannelID channel, unsigned couplingIndex);
+ void setCoupling( ChannelID channel, unsigned couplingIndex );
/// \brief Sets the gain for a channel.
/// \param channel The channel, whose gain should be set.
/// \param gain The gain in volts.
- void setGain(ChannelID channel, unsigned gainStepIndex);
+ void setGain( ChannelID channel, unsigned gainStepIndex );
+
+ /// \brief Sets the probe attenuation for a channel.
+ /// \param channel The channel, whose attn should be set.
+ /// \param attn The attn value.
+ void setAttn( ChannelID channel, double attnValue );
/// \brief Sets the mode for the math channel.
/// \param mathModeIndex The math-mode index.
- void setMode(unsigned mathModeIndex);
+ void setMode( unsigned mathModeIndex );
/// \brief Enables/disables a channel.
/// \param channel The channel, that should be enabled/disabled.
/// \param used True if the channel should be enabled, false otherwise.
- void setUsed(ChannelID channel, bool used);
+ void setUsed( ChannelID channel, bool used );
+
+ /// \brief Set channel inverted.
+ /// \param channel The channel, that should be inverted.
+ /// \param used True if the channel should be inverted, false otherwise.
+ void setInverted( ChannelID channel, bool inverted );
+
+ public slots:
+ /// \brief Loads settings into GUI
+ /// \param scope Settings to load
+ /// \param spec Current scope specifications
+ void loadSettings( DsoSettingsScope *scope, const Dso::ControlSpecification *spec );
protected:
- void closeEvent(QCloseEvent *event);
+ void closeEvent( QCloseEvent *event );
- QGridLayout *dockLayout; ///< The main layout for the dock window
- QWidget *dockWidget; ///< The main widget for the dock window
+ QGridLayout *dockLayout; ///< The main layout for the dock window
+ QWidget *dockWidget; ///< The main widget for the dock window
struct ChannelBlock {
- QCheckBox * usedCheckBox; ///< Enable/disable a specific channel
- QComboBox * gainComboBox; ///< Select the vertical gain for the channels
- QComboBox * miscComboBox; ///< Select coupling for real and mode for math channels
- QCheckBox * invertCheckBox; ///< Select if the channels should be displayed inverted
+ QCheckBox *usedCheckBox; ///< Enable/disable a specific channel
+ QComboBox *gainComboBox; ///< Select the vertical gain for the channels
+ QComboBox *miscComboBox; ///< Select coupling for real and mode for math channels
+ QCheckBox *invertCheckBox; ///< Select if the channels should be displayed inverted
+ QSpinBox *attnSpinBox; ///< Enter the attenuation probe value
};
- std::vector channelBlocks;
+ std::vector< ChannelBlock > channelBlocks;
DsoSettingsScope *scope; ///< The settings provided by the parent class
const Dso::ControlSpecification *spec;
@@ -67,10 +88,13 @@ class VoltageDock : public QDockWidget {
QStringList couplingStrings; ///< The strings for the couplings
QStringList modeStrings; ///< The strings for the math mode
QStringList gainStrings; ///< String representations for the gain steps
+ QStringList attnStrings; ///< String representations for the probe attn steps
signals:
- void couplingChanged(ChannelID channel, Dso::Coupling coupling); ///< A coupling has been selected
- void gainChanged(ChannelID channel, double gain); ///< A gain has been selected
- void modeChanged(Dso::MathMode mode); ///< The mode for the math channels has been changed
- void usedChanged(ChannelID channel, bool used); ///< A channel has been enabled/disabled
+ void couplingChanged( ChannelID channel, Dso::Coupling coupling ); ///< A coupling has been selected
+ void gainChanged( ChannelID channel, double gain ); ///< A gain has been selected
+ void modeChanged( Dso::MathMode mode ); ///< The mode for the math channels has been changed
+ void usedChanged( ChannelID channel, bool used ); ///< A channel has been enabled/disabled
+ void probeAttnChanged( ChannelID channel, double probeAttn ); ///< A channel probe attenuation has been changed
+ void invertedChanged( ChannelID channel, bool inverted ); ///< A channel "inverted" has been toggled
};
diff --git a/openhantek/src/docks/dockconstants.h b/openhantek/src/docks/dockconstants.h
new file mode 100644
index 00000000..9e49a7e0
--- /dev/null
+++ b/openhantek/src/docks/dockconstants.h
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#pragma once
+
+// spacing between the individual entries of the docks
+const int DOCK_LAYOUT_SPACING = 1;
diff --git a/openhantek/src/docks/dockwindows.cpp b/openhantek/src/docks/dockwindows.cpp
index 37fff337..3f127b3c 100644
--- a/openhantek/src/docks/dockwindows.cpp
+++ b/openhantek/src/docks/dockwindows.cpp
@@ -8,29 +8,32 @@
#include
-#include "post/postprocessingsettings.h"
+#include "dockwindows.h"
#include "hantekdso/enums.h"
#include "hantekprotocol/types.h"
-#include "dockwindows.h"
+#include "post/postprocessingsettings.h"
+
-void SetupDockWidget(QDockWidget *dockWindow, QWidget *dockWidget, QLayout *layout) {
- dockWindow->setObjectName(dockWindow->windowTitle());
- dockWindow->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
- dockWidget->setLayout(layout);
- dockWidget->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::DefaultType));
- dockWindow->setWidget(dockWidget);
+void SetupDockWidget( QDockWidget *dockWindow, QWidget *dockWidget, QLayout *layout ) {
+ dockWindow->setObjectName( dockWindow->windowTitle() );
+ dockWindow->setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea );
+ dockWindow->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable ); // do not close
+ dockWidget->setLayout( layout );
+ dockWidget->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::DefaultType ) );
+ dockWindow->setWidget( dockWidget );
}
+
void registerDockMetaTypes() {
- qRegisterMetaType();
- qRegisterMetaType();
- qRegisterMetaType();
- qRegisterMetaType();
- qRegisterMetaType();
- qRegisterMetaType();
- qRegisterMetaType();
- qRegisterMetaType();
- qRegisterMetaType >();
- qRegisterMetaType >();
- qRegisterMetaType("ChannelID");
+ qRegisterMetaType< Dso::TriggerMode >();
+ qRegisterMetaType< Dso::MathMode >();
+ qRegisterMetaType< Dso::Slope >();
+ qRegisterMetaType< Dso::Coupling >();
+ qRegisterMetaType< Dso::GraphFormat >();
+ qRegisterMetaType< Dso::ChannelMode >();
+ qRegisterMetaType< Dso::WindowFunction >();
+ qRegisterMetaType< Dso::InterpolationMode >();
+ qRegisterMetaType< std::vector< unsigned > >();
+ qRegisterMetaType< std::vector< double > >();
+ qRegisterMetaType< ChannelID >( "ChannelID" );
}
diff --git a/openhantek/src/docks/dockwindows.h b/openhantek/src/docks/dockwindows.h
index 3a479b44..19800f9a 100644
--- a/openhantek/src/docks/dockwindows.h
+++ b/openhantek/src/docks/dockwindows.h
@@ -5,5 +5,9 @@
#include
#include
+#include "dockconstants.h"
+#include "viewconstants.h"
+
+
void registerDockMetaTypes();
-void SetupDockWidget(QDockWidget *dockWindow, QWidget *dockWidget, QLayout *layout);
+void SetupDockWidget( QDockWidget *dockWindow, QWidget *dockWidget, QLayout *layout );
diff --git a/openhantek/src/dsosettings.cpp b/openhantek/src/dsosettings.cpp
new file mode 100644
index 00000000..54e0f1a2
--- /dev/null
+++ b/openhantek/src/dsosettings.cpp
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include
+#include
+// #include
+#include
+
+#include "dsosettings.h"
+#include "dsowidget.h"
+
+/// \brief Set the number of channels.
+/// \param channels The new channel count, that will be applied to lists.
+DsoSettings::DsoSettings( const Dso::ControlSpecification *deviceSpecification ) : deviceSpecification( deviceSpecification ) {
+ // Add new channels to the list
+ unsigned char trace_hue[] = {60, 240, 0, 120}; // yellow, blue, red, green
+ unsigned index = 0;
+ scope.hasACcoupling = deviceSpecification->hasACcoupling;
+ while ( scope.spectrum.size() < deviceSpecification->channels ) {
+ // Spectrum
+ DsoSettingsScopeSpectrum newSpectrum;
+ newSpectrum.name = tr( "SP%1" ).arg( index + 1 );
+ scope.spectrum.push_back( newSpectrum );
+
+ // Voltage
+ DsoSettingsScopeVoltage newVoltage;
+ newVoltage.name = tr( "CH%1" ).arg( index + 1 );
+ scope.voltage.push_back( newVoltage );
+
+ view.screen.voltage.push_back( QColor::fromHsv( trace_hue[ index ], 0xff, 0xff ) );
+ view.screen.spectrum.push_back( QColor::fromHsv( trace_hue[ index ] - 30, 0xff, 0xff ) );
+ view.print.voltage.push_back( view.screen.voltage.back().darker() );
+ view.print.spectrum.push_back( view.screen.spectrum.back().darker() );
+ if ( ++index >= sizeof trace_hue )
+ index = 0;
+ }
+
+ DsoSettingsScopeSpectrum newSpectrum;
+ newSpectrum.name = tr( "SPM" );
+ scope.spectrum.push_back( newSpectrum );
+
+ DsoSettingsScopeVoltage newVoltage;
+ newVoltage.couplingOrMathIndex = unsigned( Dso::MathMode::ADD_CH1_CH2 );
+ newVoltage.name = tr( "MATH" );
+ scope.voltage.push_back( newVoltage );
+
+ view.screen.voltage.push_back( QColor::fromHsv( 300, 0xff, 0xff ) ); // purple
+ view.screen.spectrum.push_back( QColor::fromHsv( 320, 0xff, 0xff ) );
+ view.print.voltage.push_back( QColor::fromHsv( 300, 0xff, 0xff ) );
+ view.print.spectrum.push_back( QColor::fromHsv( 320, 0xff, 0xff ) );
+
+ load();
+}
+
+
+bool DsoSettings::setFilename( const QString &filename ) {
+ std::unique_ptr< QSettings > local = std::unique_ptr< QSettings >( new QSettings( filename, QSettings::IniFormat ) );
+ if ( local->status() != QSettings::NoError ) {
+ qWarning() << "Could not change the settings file to " << filename;
+ return false;
+ }
+ storeSettings.swap( local );
+ return true;
+}
+
+
+void DsoSettings::load() {
+ // Start with default configuration?
+ if ( storeSettings->value( "configuration/version", 0 ).toUInt() < CONFIG_VERSION ) {
+ // incompatible change or config reset by user
+ storeSettings->clear(); // start with a clean config storage
+ setDefaultConfig();
+ return;
+ }
+
+ alwaysSave = storeSettings->value( "configuration/alwaysSave", alwaysSave ).toBool();
+
+ // Oscilloscope settings
+ storeSettings->beginGroup( "scope" );
+ // Horizontal axis
+ storeSettings->beginGroup( "horizontal" );
+ if ( storeSettings->contains( "format" ) )
+ scope.horizontal.format = Dso::GraphFormat( storeSettings->value( "format" ).toInt() );
+ if ( storeSettings->contains( "frequencybase" ) )
+ scope.horizontal.frequencybase = storeSettings->value( "frequencybase" ).toDouble();
+ for ( int marker = 0; marker < 2; ++marker ) {
+ QString name;
+ name = QString( "marker%1" ).arg( marker );
+ if ( storeSettings->contains( name ) )
+ scope.setMarker( unsigned( marker ), storeSettings->value( name ).toDouble() );
+ }
+ if ( storeSettings->contains( "timebase" ) )
+ scope.horizontal.timebase = storeSettings->value( "timebase" ).toDouble();
+ if ( storeSettings->contains( "maxTimebase" ) )
+ scope.horizontal.maxTimebase = storeSettings->value( "maxTimebase" ).toDouble();
+ if ( storeSettings->contains( "acquireInterval" ) )
+ scope.horizontal.acquireInterval = storeSettings->value( "acquireInterval" ).toDouble();
+ if ( storeSettings->contains( "recordLength" ) )
+ scope.horizontal.recordLength = storeSettings->value( "recordLength" ).toUInt();
+ if ( storeSettings->contains( "samplerate" ) )
+ scope.horizontal.samplerate = storeSettings->value( "samplerate" ).toDouble();
+ if ( storeSettings->contains( "calfreq" ) )
+ scope.horizontal.calfreq = storeSettings->value( "calfreq" ).toDouble();
+ storeSettings->endGroup(); // horizontal
+ // Trigger
+ storeSettings->beginGroup( "trigger" );
+ if ( storeSettings->contains( "mode" ) )
+ scope.trigger.mode = Dso::TriggerMode( storeSettings->value( "mode" ).toUInt() );
+ if ( storeSettings->contains( "position" ) )
+ scope.trigger.offset = storeSettings->value( "position" ).toDouble();
+ if ( storeSettings->contains( "slope" ) )
+ scope.trigger.slope = Dso::Slope( storeSettings->value( "slope" ).toUInt() );
+ if ( storeSettings->contains( "source" ) )
+ scope.trigger.source = storeSettings->value( "source" ).toUInt();
+ if ( storeSettings->contains( "smooth" ) )
+ scope.trigger.smooth = storeSettings->value( "smooth" ).toBool();
+ storeSettings->endGroup(); // trigger
+ // Spectrum
+ for ( ChannelID channel = 0; channel < scope.spectrum.size(); ++channel ) {
+ storeSettings->beginGroup( QString( "spectrum%1" ).arg( channel ) );
+ if ( storeSettings->contains( "magnitude" ) )
+ scope.spectrum[ channel ].magnitude = storeSettings->value( "magnitude" ).toDouble();
+ if ( storeSettings->contains( "offset" ) )
+ scope.spectrum[ channel ].offset = storeSettings->value( "offset" ).toDouble();
+ if ( storeSettings->contains( "used" ) )
+ scope.spectrum[ channel ].used = storeSettings->value( "used" ).toBool();
+ storeSettings->beginGroup( "cursor" );
+ if ( storeSettings->contains( "shape" ) )
+ scope.spectrum[ channel ].cursor.shape =
+ DsoSettingsScopeCursor::CursorShape( storeSettings->value( "shape" ).toUInt() );
+ for ( int marker = 0; marker < 2; ++marker ) {
+ QString name;
+ name = QString( "x%1" ).arg( marker );
+ if ( storeSettings->contains( name ) )
+ scope.spectrum[ channel ].cursor.pos[ marker ].setX( storeSettings->value( name ).toDouble() );
+ name = QString( "y%1" ).arg( marker );
+ if ( storeSettings->contains( name ) )
+ scope.spectrum[ channel ].cursor.pos[ marker ].setY( storeSettings->value( name ).toDouble() );
+ }
+ storeSettings->endGroup(); // cursor
+ storeSettings->endGroup(); // spectrum%1
+ }
+ // Voltage
+ bool defaultConfig = deviceSpecification->isDemoDevice; // use default channel setting in demo mode
+ if ( storeSettings->contains( "hasACmodification" ) )
+ scope.hasACmodification = storeSettings->value( "hasACmodification" ).toBool();
+ for ( ChannelID channel = 0; channel < scope.voltage.size(); ++channel ) {
+ storeSettings->beginGroup( QString( "voltage%1" ).arg( channel ) );
+ if ( storeSettings->contains( "gainStepIndex" ) )
+ scope.voltage[ channel ].gainStepIndex = storeSettings->value( "gainStepIndex" ).toUInt();
+ if ( storeSettings->contains( "couplingOrMathIndex" ) ) {
+ scope.voltage[ channel ].couplingOrMathIndex = storeSettings->value( "couplingOrMathIndex" ).toUInt();
+ if ( channel < deviceSpecification->channels )
+ if ( scope.voltage[ channel ].couplingOrMathIndex >= deviceSpecification->couplings.size() ||
+ ( !scope.hasACcoupling && !scope.hasACmodification ) )
+ scope.voltage[ channel ].couplingOrMathIndex = 0; // set to default if out of range
+ }
+ if ( storeSettings->contains( "inverted" ) )
+ scope.voltage[ channel ].inverted = storeSettings->value( "inverted" ).toBool();
+ if ( storeSettings->contains( "offset" ) )
+ scope.voltage[ channel ].offset = storeSettings->value( "offset" ).toDouble();
+ if ( storeSettings->contains( "trigger" ) )
+ scope.voltage[ channel ].trigger = storeSettings->value( "trigger" ).toDouble();
+ if ( storeSettings->contains( "probeAttn" ) )
+ scope.voltage[ channel ].probeAttn = storeSettings->value( "probeAttn" ).toDouble();
+ if ( storeSettings->contains( "used" ) )
+ scope.voltage[ channel ].used = storeSettings->value( "used" ).toBool();
+ else // no config file found, e.g. 1st run
+ defaultConfig = true; // start with default config
+
+ if ( defaultConfig ) { // useful default: show both voltage channels
+ setDefaultConfig();
+ }
+
+ storeSettings->beginGroup( "cursor" );
+ if ( storeSettings->contains( "shape" ) )
+ scope.voltage[ channel ].cursor.shape = DsoSettingsScopeCursor::CursorShape( storeSettings->value( "shape" ).toUInt() );
+ for ( int marker = 0; marker < 2; ++marker ) {
+ QString name;
+ name = QString( "x%1" ).arg( marker );
+ if ( storeSettings->contains( name ) )
+ scope.voltage[ channel ].cursor.pos[ marker ].setX( storeSettings->value( name ).toDouble() );
+ name = QString( "y%1" ).arg( marker );
+ if ( storeSettings->contains( name ) )
+ scope.voltage[ channel ].cursor.pos[ marker ].setY( storeSettings->value( name ).toDouble() );
+ }
+ storeSettings->endGroup(); // cursor
+ storeSettings->endGroup(); // voltage%1
+ }
+
+ // Post processing
+ if ( storeSettings->contains( "spectrumLimit" ) )
+ post.spectrumLimit = storeSettings->value( "spectrumLimit" ).toDouble();
+ if ( storeSettings->contains( "spectrumReference" ) )
+ post.spectrumReference = storeSettings->value( "spectrumReference" ).toDouble();
+ if ( storeSettings->contains( "spectrumWindow" ) )
+ post.spectrumWindow = Dso::WindowFunction( storeSettings->value( "spectrumWindow" ).toInt() );
+ storeSettings->endGroup(); // scope
+
+ // View
+ storeSettings->beginGroup( "view" );
+ // Colors
+ storeSettings->beginGroup( "color" );
+ DsoSettingsColorValues *colors;
+ for ( int mode = 0; mode < 2; ++mode ) {
+ if ( mode == 0 ) {
+ colors = &view.screen;
+ storeSettings->beginGroup( "screen" );
+ } else {
+ colors = &view.print;
+ storeSettings->beginGroup( "print" );
+ }
+
+ if ( storeSettings->contains( "axes" ) )
+ colors->axes = storeSettings->value( "axes" ).value< QColor >();
+ if ( storeSettings->contains( "background" ) )
+ colors->background = storeSettings->value( "background" ).value< QColor >();
+ if ( storeSettings->contains( "border" ) )
+ colors->border = storeSettings->value( "border" ).value< QColor >();
+ if ( storeSettings->contains( "grid" ) )
+ colors->grid = storeSettings->value( "grid" ).value< QColor >();
+ if ( storeSettings->contains( "markers" ) )
+ colors->markers = storeSettings->value( "markers" ).value< QColor >();
+ for ( ChannelID channel = 0; channel < scope.spectrum.size(); ++channel ) {
+ QString key = QString( "spectrum%1" ).arg( channel );
+ if ( storeSettings->contains( key ) )
+ colors->spectrum[ channel ] = storeSettings->value( key ).value< QColor >();
+ }
+ if ( storeSettings->contains( "text" ) )
+ colors->text = storeSettings->value( "text" ).value< QColor >();
+ for ( ChannelID channel = 0; channel < scope.voltage.size(); ++channel ) {
+ QString key = QString( "voltage%1" ).arg( channel );
+ if ( storeSettings->contains( key ) )
+ colors->voltage[ channel ] = storeSettings->value( key ).value< QColor >();
+ }
+ storeSettings->endGroup(); // screen / print
+ }
+ storeSettings->endGroup(); // color
+ // Other view settings
+ if ( storeSettings->contains( "histogram" ) )
+ scope.histogram = storeSettings->value( "histogram" ).toBool();
+ if ( storeSettings->contains( "digitalPhosphor" ) )
+ view.digitalPhosphor = storeSettings->value( "digitalPhosphor" ).toBool();
+ if ( storeSettings->contains( "interpolation" ) )
+ view.interpolation = Dso::InterpolationMode( storeSettings->value( "interpolation" ).toInt() );
+ if ( storeSettings->contains( "printerColorImages" ) )
+ view.printerColorImages = storeSettings->value( "printerColorImages" ).toBool();
+ if ( storeSettings->contains( "zoom" ) )
+ view.zoom = storeSettings->value( "zoom" ).toBool();
+ if ( storeSettings->contains( "cursorGridPosition" ) )
+ view.cursorGridPosition = Qt::ToolBarArea( storeSettings->value( "cursorGridPosition" ).toUInt() );
+ if ( storeSettings->contains( "cursorsVisible" ) )
+ view.cursorsVisible = storeSettings->value( "cursorsVisible" ).toBool();
+ storeSettings->endGroup(); // view
+
+ storeSettings->beginGroup( "window" );
+ mainWindowGeometry = storeSettings->value( "geometry" ).toByteArray();
+ mainWindowState = storeSettings->value( "state" ).toByteArray();
+ storeSettings->endGroup(); // window
+}
+
+
+void DsoSettings::save() {
+ // Use default configuration after restart?
+ if ( 0 == configVersion ) {
+ storeSettings->clear();
+ return;
+ }
+ storeSettings->beginGroup( "configuration" );
+ storeSettings->setValue( "version", configVersion );
+ storeSettings->setValue( "alwaysSave", alwaysSave );
+ storeSettings->endGroup(); // configuration
+
+ // Oszilloskope settings
+ storeSettings->beginGroup( "scope" );
+ // Horizontal axis
+ storeSettings->beginGroup( "horizontal" );
+ storeSettings->setValue( "format", scope.horizontal.format );
+ storeSettings->setValue( "frequencybase", scope.horizontal.frequencybase );
+ for ( int marker = 0; marker < 2; ++marker )
+ storeSettings->setValue( QString( "marker%1" ).arg( marker ), scope.getMarker( unsigned( marker ) ) );
+ storeSettings->setValue( "timebase", scope.horizontal.timebase );
+ storeSettings->setValue( "maxTimebase", scope.horizontal.maxTimebase );
+ storeSettings->setValue( "acquireInterval", scope.horizontal.acquireInterval );
+ storeSettings->setValue( "recordLength", scope.horizontal.recordLength );
+ storeSettings->setValue( "samplerate", scope.horizontal.samplerate );
+ storeSettings->setValue( "calfreq", scope.horizontal.calfreq );
+ storeSettings->endGroup(); // horizontal
+ // Trigger
+ storeSettings->beginGroup( "trigger" );
+ storeSettings->setValue( "mode", unsigned( scope.trigger.mode ) );
+ storeSettings->setValue( "position", scope.trigger.offset );
+ storeSettings->setValue( "slope", unsigned( scope.trigger.slope ) );
+ storeSettings->setValue( "source", scope.trigger.source );
+ storeSettings->setValue( "smooth", scope.trigger.smooth );
+ storeSettings->endGroup(); // trigger
+ // Spectrum
+ for ( ChannelID channel = 0; channel < scope.spectrum.size(); ++channel ) {
+ storeSettings->beginGroup( QString( "spectrum%1" ).arg( channel ) );
+ storeSettings->setValue( "magnitude", scope.spectrum[ channel ].magnitude );
+ storeSettings->setValue( "offset", scope.spectrum[ channel ].offset );
+ storeSettings->setValue( "used", scope.spectrum[ channel ].used );
+ storeSettings->beginGroup( "cursor" );
+ storeSettings->setValue( "shape", scope.spectrum[ channel ].cursor.shape );
+ for ( int marker = 0; marker < 2; ++marker ) {
+ QString name;
+ name = QString( "x%1" ).arg( marker );
+ storeSettings->setValue( name, scope.spectrum[ channel ].cursor.pos[ marker ].x() );
+ name = QString( "y%1" ).arg( marker );
+ storeSettings->setValue( name, scope.spectrum[ channel ].cursor.pos[ marker ].y() );
+ }
+ storeSettings->endGroup(); // cursor
+ storeSettings->endGroup(); // spectrum%1
+ }
+ // Voltage
+ storeSettings->setValue( "hasACmodification", scope.hasACmodification );
+ for ( ChannelID channel = 0; channel < scope.voltage.size(); ++channel ) {
+ storeSettings->beginGroup( QString( "voltage%1" ).arg( channel ) );
+ storeSettings->setValue( "gainStepIndex", scope.voltage[ channel ].gainStepIndex );
+ storeSettings->setValue( "couplingOrMathIndex", scope.voltage[ channel ].couplingOrMathIndex );
+ storeSettings->setValue( "inverted", scope.voltage[ channel ].inverted );
+ storeSettings->setValue( "offset", scope.voltage[ channel ].offset );
+ storeSettings->setValue( "trigger", scope.voltage[ channel ].trigger );
+ storeSettings->setValue( "used", scope.voltage[ channel ].used );
+ storeSettings->setValue( "probeAttn", scope.voltage[ channel ].probeAttn );
+ storeSettings->beginGroup( "cursor" );
+ storeSettings->setValue( "shape", scope.voltage[ channel ].cursor.shape );
+ for ( int marker = 0; marker < 2; ++marker ) {
+ QString name;
+ name = QString( "x%1" ).arg( marker );
+ storeSettings->setValue( name, scope.voltage[ channel ].cursor.pos[ marker ].x() );
+ name = QString( "y%1" ).arg( marker );
+ storeSettings->setValue( name, scope.voltage[ channel ].cursor.pos[ marker ].y() );
+ }
+ storeSettings->endGroup(); // cursor
+ storeSettings->endGroup(); // voltage%1
+ }
+
+ // Post processing
+ storeSettings->setValue( "spectrumLimit", post.spectrumLimit );
+ storeSettings->setValue( "spectrumReference", post.spectrumReference );
+ storeSettings->setValue( "spectrumWindow", unsigned( post.spectrumWindow ) );
+ storeSettings->endGroup(); // scope
+
+ // View
+ storeSettings->beginGroup( "view" );
+ // Colors
+
+ storeSettings->beginGroup( "color" );
+ DsoSettingsColorValues *colors;
+ for ( int mode = 0; mode < 2; ++mode ) {
+ if ( mode == 0 ) {
+ colors = &view.screen;
+ storeSettings->beginGroup( "screen" );
+ } else {
+ colors = &view.print;
+ storeSettings->beginGroup( "print" );
+ }
+
+ storeSettings->setValue( "axes", colors->axes.name( QColor::HexArgb ) );
+ storeSettings->setValue( "background", colors->background.name( QColor::HexArgb ) );
+ storeSettings->setValue( "border", colors->border.name( QColor::HexArgb ) );
+ storeSettings->setValue( "grid", colors->grid.name( QColor::HexArgb ) );
+ storeSettings->setValue( "markers", colors->markers.name( QColor::HexArgb ) );
+ for ( ChannelID channel = 0; channel < scope.spectrum.size(); ++channel )
+ storeSettings->setValue( QString( "spectrum%1" ).arg( channel ), colors->spectrum[ channel ].name( QColor::HexArgb ) );
+ storeSettings->setValue( "text", colors->text.name( QColor::HexArgb ) );
+ for ( ChannelID channel = 0; channel < scope.voltage.size(); ++channel )
+ storeSettings->setValue( QString( "voltage%1" ).arg( channel ), colors->voltage[ channel ].name( QColor::HexArgb ) );
+ storeSettings->endGroup(); // screen / print
+ }
+ storeSettings->endGroup(); // color
+
+ // Other view settings
+ storeSettings->setValue( "histogram", scope.histogram );
+ storeSettings->setValue( "digitalPhosphor", view.digitalPhosphor );
+ storeSettings->setValue( "interpolation", view.interpolation );
+ storeSettings->setValue( "printerColorImages", view.printerColorImages );
+ storeSettings->setValue( "zoom", view.zoom );
+ storeSettings->setValue( "cursorGridPosition", view.cursorGridPosition );
+ storeSettings->setValue( "cursorsVisible", view.cursorsVisible );
+ storeSettings->endGroup(); // view
+
+ storeSettings->beginGroup( "window" );
+ storeSettings->setValue( "geometry", mainWindowGeometry );
+ storeSettings->setValue( "state", mainWindowState );
+ storeSettings->endGroup(); // window
+}
+
+
+void DsoSettings::setDefaultConfig() {
+ scope.voltage[ 0 ].used = true;
+ scope.voltage[ 0 ].offset = MARGIN_TOP / 2; // mid of upper screen half
+ scope.voltage[ 1 ].used = true;
+ scope.voltage[ 1 ].offset = MARGIN_BOTTOM / 2; // mid of lower screen half
+}
diff --git a/openhantek/src/dsosettings.h b/openhantek/src/dsosettings.h
new file mode 100644
index 00000000..85a01d1f
--- /dev/null
+++ b/openhantek/src/dsosettings.h
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+// increment this value after incompatible config changes
+#define CONFIG_VERSION 1
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+//#include "exporting/exportsettings.h"
+#include "post/postprocessingsettings.h"
+#include "scopesettings.h"
+#include "viewsettings.h"
+
+/// \brief Holds the settings of the program.
+class DsoSettings {
+ Q_DECLARE_TR_FUNCTIONS( DsoSettings )
+
+ public:
+ explicit DsoSettings( const Dso::ControlSpecification *deviceSpecification );
+ bool setFilename( const QString &filename );
+
+ DsoSettingsScope scope; ///< All oscilloscope related settings
+ DsoSettingsView view; ///< All view related settings
+ DsoSettingsPostProcessing post; ///< All post processing related settings
+ bool exportProcessedSamples = true; ///< General options of the program
+ bool alwaysSave = true; ///< Always save the settings on exit
+ unsigned configVersion = CONFIG_VERSION; ///< Handle incompatible changes
+
+ QByteArray mainWindowGeometry; ///< Geometry of the main window
+ QByteArray mainWindowState; ///< State of docking windows and toolbars
+
+ /// \brief Read the settings from the last session or another file.
+ void load();
+
+ /// \brief Save the settings to the harddisk.
+ void save();
+
+ private:
+ std::unique_ptr< QSettings > storeSettings = std::unique_ptr< QSettings >( new QSettings );
+ const Dso::ControlSpecification *deviceSpecification;
+ void setDefaultConfig();
+};
diff --git a/openhantek/src/dsowidget.cpp b/openhantek/src/dsowidget.cpp
index f8c43fc0..4d9ec116 100644
--- a/openhantek/src/dsowidget.cpp
+++ b/openhantek/src/dsowidget.cpp
@@ -11,8 +11,8 @@
#include "dsowidget.h"
-#include "post/postprocessingsettings.h"
#include "post/graphgenerator.h"
+#include "post/postprocessingsettings.h"
#include "post/ppresult.h"
#include "utils/printutils.h"
@@ -20,751 +20,1035 @@
#include "glscope.h"
#include "scopesettings.h"
#include "viewconstants.h"
-#include "viewsettings.h"
-#include "widgets/levelslider.h"
#include "widgets/datagrid.h"
+#include "widgets/levelslider.h"
static int zoomScopeRow = 0;
-DsoWidget::DsoWidget(DsoSettingsScope *scope, DsoSettingsView *view, const Dso::ControlSpecification *spec,
- QWidget *parent, Qt::WindowFlags flags)
- : QWidget(parent, flags), scope(scope), view(view), spec(spec), mainScope(GlScope::createNormal(scope, view)),
- zoomScope(GlScope::createZoomed(scope, view)) {
+
+DsoWidget::DsoWidget( DsoSettingsScope *scope, DsoSettingsView *view, const Dso::ControlSpecification *spec, QWidget *parent )
+ : QWidget( parent ), scope( scope ), view( view ), spec( spec ), mainScope( GlScope::createNormal( scope, view ) ),
+ zoomScope( GlScope::createZoomed( scope, view ) ) {
// Palette for this widget
QPalette palette;
- palette.setColor(QPalette::Background, view->screen.background);
- palette.setColor(QPalette::WindowText, view->screen.text);
-
- setupSliders(mainSliders);
- setupSliders(zoomSliders);
-
- connect(mainScope, &GlScope::markerMoved, [this](unsigned cursorIndex, unsigned marker) {
- mainSliders.markerSlider->setValue(marker, this->scope->getMarker(marker));
- mainScope->updateCursor(cursorIndex);
- zoomScope->updateCursor(cursorIndex);
- });
- connect(zoomScope, &GlScope::markerMoved, [this](unsigned cursorIndex, unsigned marker) {
- mainScope->updateCursor(cursorIndex);
- zoomScope->updateCursor(cursorIndex);
- });
-
- // The table for the settings
+ palette.setColor( QPalette::Background, view->colors->background );
+ palette.setColor( QPalette::WindowText, view->colors->text );
+
+ setupSliders( mainSliders );
+ setupSliders( zoomSliders );
+
+ connect( mainScope, &GlScope::markerMoved, [this]( unsigned cursorIndex, unsigned marker ) {
+ mainSliders.markerSlider->setValue( int( marker ), this->scope->getMarker( marker ) );
+ mainScope->updateCursor( cursorIndex );
+ zoomScope->updateCursor( cursorIndex );
+ } );
+ connect( zoomScope, &GlScope::markerMoved, [this]( unsigned cursorIndex ) {
+ mainScope->updateCursor( cursorIndex );
+ zoomScope->updateCursor( cursorIndex );
+ } );
+
+ // The table for the settings at screen top
settingsTriggerLabel = new QLabel();
- settingsTriggerLabel->setMinimumWidth(160);
- settingsTriggerLabel->setIndent(5);
- settingsRecordLengthLabel = new QLabel();
- settingsRecordLengthLabel->setAlignment(Qt::AlignRight);
- settingsRecordLengthLabel->setPalette(palette);
+ settingsTriggerLabel->setMinimumWidth( 320 );
+ settingsTriggerLabel->setIndent( 5 );
+ settingsSamplesOnScreen = new QLabel();
+ settingsSamplesOnScreen->setAlignment( Qt::AlignRight );
+ settingsSamplesOnScreen->setPalette( palette );
settingsSamplerateLabel = new QLabel();
- settingsSamplerateLabel->setAlignment(Qt::AlignRight);
- settingsSamplerateLabel->setPalette(palette);
+ settingsSamplerateLabel->setAlignment( Qt::AlignRight );
+ settingsSamplerateLabel->setPalette( palette );
settingsTimebaseLabel = new QLabel();
- settingsTimebaseLabel->setAlignment(Qt::AlignRight);
- settingsTimebaseLabel->setPalette(palette);
+ settingsTimebaseLabel->setAlignment( Qt::AlignRight );
+ settingsTimebaseLabel->setPalette( palette );
settingsFrequencybaseLabel = new QLabel();
- settingsFrequencybaseLabel->setAlignment(Qt::AlignRight);
- settingsFrequencybaseLabel->setPalette(palette);
+ settingsFrequencybaseLabel->setAlignment( Qt::AlignRight );
+ settingsFrequencybaseLabel->setPalette( palette );
swTriggerStatus = new QLabel();
- swTriggerStatus->setMinimumWidth(30);
- swTriggerStatus->setText(tr("TR"));
- swTriggerStatus->setAlignment(Qt::AlignCenter);
- swTriggerStatus->setAutoFillBackground(true);
- swTriggerStatus->setVisible(false);
+ swTriggerStatus->setMinimumWidth( 20 );
+ swTriggerStatus->setText( tr( "TR" ) );
+ swTriggerStatus->setAlignment( Qt::AlignCenter );
+ swTriggerStatus->setAutoFillBackground( true );
+ swTriggerStatus->setVisible( false );
settingsLayout = new QHBoxLayout();
- settingsLayout->addWidget(swTriggerStatus);
- settingsLayout->addWidget(settingsTriggerLabel);
- settingsLayout->addWidget(settingsRecordLengthLabel, 1);
- settingsLayout->addWidget(settingsSamplerateLabel, 1);
- settingsLayout->addWidget(settingsTimebaseLabel, 1);
- settingsLayout->addWidget(settingsFrequencybaseLabel, 1);
+ settingsLayout->addWidget( swTriggerStatus );
+ settingsLayout->addWidget( settingsTriggerLabel );
+ settingsLayout->addWidget( settingsSamplesOnScreen, 1 );
+ settingsLayout->addWidget( settingsSamplerateLabel, 1 );
+ settingsLayout->addWidget( settingsTimebaseLabel, 1 );
+ settingsLayout->addWidget( settingsFrequencybaseLabel, 1 );
// The table for the marker details
markerInfoLabel = new QLabel();
- markerInfoLabel->setMinimumWidth(160);
- markerInfoLabel->setPalette(palette);
+ markerInfoLabel->setAlignment( Qt::AlignLeft );
+ markerInfoLabel->setPalette( palette );
markerTimeLabel = new QLabel();
- markerTimeLabel->setAlignment(Qt::AlignRight);
- markerTimeLabel->setPalette(palette);
+ markerTimeLabel->setAlignment( Qt::AlignLeft );
+ markerTimeLabel->setPalette( palette );
markerFrequencyLabel = new QLabel();
- markerFrequencyLabel->setAlignment(Qt::AlignRight);
- markerFrequencyLabel->setPalette(palette);
+ markerFrequencyLabel->setAlignment( Qt::AlignLeft );
+ markerFrequencyLabel->setPalette( palette );
markerTimebaseLabel = new QLabel();
- markerTimebaseLabel->setAlignment(Qt::AlignRight);
- markerTimebaseLabel->setPalette(palette);
+ markerTimebaseLabel->setAlignment( Qt::AlignRight );
+ markerTimebaseLabel->setPalette( palette );
markerFrequencybaseLabel = new QLabel();
- markerFrequencybaseLabel->setAlignment(Qt::AlignRight);
- markerFrequencybaseLabel->setPalette(palette);
+ markerFrequencybaseLabel->setAlignment( Qt::AlignRight );
+ markerFrequencybaseLabel->setPalette( palette );
markerLayout = new QHBoxLayout();
- markerLayout->addWidget(markerInfoLabel);
- markerLayout->addWidget(markerTimeLabel, 1);
- markerLayout->addWidget(markerFrequencyLabel, 1);
- markerLayout->addWidget(markerTimebaseLabel, 1);
- markerLayout->addWidget(markerFrequencybaseLabel, 1);
+ markerLayout->addWidget( markerInfoLabel );
+ markerLayout->addWidget( markerTimeLabel, 1 );
+ markerLayout->addWidget( markerFrequencyLabel, 1 );
+ markerLayout->addWidget( markerTimebaseLabel, 1 );
+ markerLayout->addWidget( markerFrequencybaseLabel, 1 );
- // The table for the measurements
+ // The table for the measurements at screen bottom
QPalette tablePalette = palette;
measurementLayout = new QGridLayout();
- measurementLayout->setColumnMinimumWidth(0, 64);
- measurementLayout->setColumnMinimumWidth(1, 32);
- measurementLayout->setColumnStretch(2, 2);
- measurementLayout->setColumnStretch(3, 2);
- measurementLayout->setColumnStretch(4, 3);
- measurementLayout->setColumnStretch(5, 3);
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
- tablePalette.setColor(QPalette::WindowText, view->screen.voltage[channel]);
- measurementNameLabel.push_back(new QLabel(scope->voltage[channel].name));
- measurementNameLabel[channel]->setPalette(tablePalette);
- measurementMiscLabel.push_back(new QLabel());
- measurementMiscLabel[channel]->setPalette(tablePalette);
- measurementGainLabel.push_back(new QLabel());
- measurementGainLabel[channel]->setAlignment(Qt::AlignRight);
- measurementGainLabel[channel]->setPalette(tablePalette);
- tablePalette.setColor(QPalette::WindowText, view->screen.spectrum[channel]);
- measurementMagnitudeLabel.push_back(new QLabel());
- measurementMagnitudeLabel[channel]->setAlignment(Qt::AlignRight);
- measurementMagnitudeLabel[channel]->setPalette(tablePalette);
- measurementAmplitudeLabel.push_back(new QLabel());
- measurementAmplitudeLabel[channel]->setAlignment(Qt::AlignRight);
- measurementAmplitudeLabel[channel]->setPalette(palette);
- measurementFrequencyLabel.push_back(new QLabel());
- measurementFrequencyLabel[channel]->setAlignment(Qt::AlignRight);
- measurementFrequencyLabel[channel]->setPalette(palette);
- setMeasurementVisible(channel);
- measurementLayout->addWidget(measurementNameLabel[channel], (int)channel, 0);
- measurementLayout->addWidget(measurementMiscLabel[channel], (int)channel, 1);
- measurementLayout->addWidget(measurementGainLabel[channel], (int)channel, 2);
- measurementLayout->addWidget(measurementMagnitudeLabel[channel], (int)channel, 3);
- measurementLayout->addWidget(measurementAmplitudeLabel[channel], (int)channel, 4);
- measurementLayout->addWidget(measurementFrequencyLabel[channel], (int)channel, 5);
- if ((unsigned)channel < spec->channels)
- updateVoltageCoupling((unsigned)channel);
+ int iii = 0;
+ measurementLayout->setColumnMinimumWidth( iii++, 80 );
+ measurementLayout->setColumnMinimumWidth( iii++, 30 );
+ measurementLayout->setColumnStretch( iii++, 3 );
+ measurementLayout->setColumnStretch( iii++, 3 );
+ measurementLayout->setColumnStretch( iii++, 3 );
+ measurementLayout->setColumnStretch( iii++, 3 );
+ measurementLayout->setColumnStretch( iii++, 3 );
+ measurementLayout->setColumnStretch( iii++, 3 );
+ measurementLayout->setColumnStretch( iii++, 3 );
+ measurementLayout->setColumnStretch( iii++, 3 );
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ tablePalette.setColor( QPalette::WindowText, view->colors->voltage[ channel ] );
+ measurementNameLabel.push_back( new QLabel( scope->voltage[ channel ].name ) );
+ measurementNameLabel[ channel ]->setAlignment( Qt::AlignCenter );
+ measurementNameLabel[ channel ]->setPalette( tablePalette );
+ measurementNameLabel[ channel ]->setAutoFillBackground( true );
+ measurementMiscLabel.push_back( new QLabel() );
+ measurementMiscLabel[ channel ]->setAlignment( Qt::AlignLeft );
+ measurementMiscLabel[ channel ]->setPalette( tablePalette );
+ measurementGainLabel.push_back( new QLabel() );
+ measurementGainLabel[ channel ]->setAlignment( Qt::AlignRight );
+ measurementGainLabel[ channel ]->setPalette( tablePalette );
+ tablePalette.setColor( QPalette::WindowText, view->colors->spectrum[ channel ] );
+ measurementMagnitudeLabel.push_back( new QLabel() );
+ measurementMagnitudeLabel[ channel ]->setAlignment( Qt::AlignRight );
+ measurementMagnitudeLabel[ channel ]->setPalette( tablePalette );
+ measurementVppLabel.push_back( new QLabel() );
+ measurementVppLabel[ channel ]->setAlignment( Qt::AlignRight );
+ measurementVppLabel[ channel ]->setPalette( palette );
+ measurementRMSLabel.push_back( new QLabel() );
+ measurementRMSLabel[ channel ]->setAlignment( Qt::AlignRight );
+ measurementRMSLabel[ channel ]->setPalette( palette );
+ measurementDCLabel.push_back( new QLabel() );
+ measurementDCLabel[ channel ]->setAlignment( Qt::AlignRight );
+ measurementDCLabel[ channel ]->setPalette( palette );
+ measurementACLabel.push_back( new QLabel() );
+ measurementACLabel[ channel ]->setAlignment( Qt::AlignRight );
+ measurementACLabel[ channel ]->setPalette( palette );
+ measurementdBLabel.push_back( new QLabel() );
+ measurementdBLabel[ channel ]->setAlignment( Qt::AlignRight );
+ measurementdBLabel[ channel ]->setPalette( palette );
+ measurementFrequencyLabel.push_back( new QLabel() );
+ measurementFrequencyLabel[ channel ]->setAlignment( Qt::AlignRight );
+ measurementFrequencyLabel[ channel ]->setPalette( palette );
+ setMeasurementVisible( channel );
+ iii = 0;
+ measurementLayout->addWidget( measurementNameLabel[ channel ], int( channel ), iii++ );
+ measurementLayout->addWidget( measurementMiscLabel[ channel ], int( channel ), iii++ );
+ measurementLayout->addWidget( measurementGainLabel[ channel ], int( channel ), iii++ );
+ measurementLayout->addWidget( measurementMagnitudeLabel[ channel ], int( channel ), iii++ );
+ measurementLayout->addWidget( measurementVppLabel[ channel ], int( channel ), iii++ );
+ measurementLayout->addWidget( measurementRMSLabel[ channel ], int( channel ), iii++ );
+ measurementLayout->addWidget( measurementDCLabel[ channel ], int( channel ), iii++ );
+ measurementLayout->addWidget( measurementACLabel[ channel ], int( channel ), iii++ );
+ measurementLayout->addWidget( measurementdBLabel[ channel ], int( channel ), iii++ );
+ measurementLayout->addWidget( measurementFrequencyLabel[ channel ], int( channel ), iii++ );
+ if ( channel < spec->channels )
+ updateVoltageCoupling( channel );
else
updateMathMode();
- updateVoltageDetails((unsigned)channel);
- updateSpectrumDetails((unsigned)channel);
+ updateVoltageDetails( channel );
+ updateSpectrumDetails( channel );
}
// Cursors
- cursorDataGrid = new DataGrid(this);
- cursorDataGrid->setBackgroundColor(view->screen.background);
- cursorDataGrid->addItem(tr("Markers"), view->screen.text);
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
- cursorDataGrid->addItem(scope->voltage[channel].name, view->screen.voltage[channel]);
- }
- for (ChannelID channel = 0; channel < scope->spectrum.size(); ++channel) {
- cursorDataGrid->addItem(scope->spectrum[channel].name, view->screen.spectrum[channel]);
- }
- cursorDataGrid->selectItem(0);
-
- connect(cursorDataGrid, &DataGrid::itemSelected, [this] (unsigned index) {
- mainScope->cursorSelected(index);
- zoomScope->cursorSelected(index);
- });
- connect(cursorDataGrid, &DataGrid::itemUpdated, [this, scope] (unsigned index) {
+ cursorDataGrid = new DataGrid( this );
+ cursorDataGrid->setBackgroundColor( view->colors->background );
+ cursorDataGrid->addItem( tr( "Markers" ), view->colors->text );
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ cursorDataGrid->addItem( scope->voltage[ channel ].name, view->colors->voltage[ channel ] );
+ }
+ for ( ChannelID channel = 0; channel < scope->spectrum.size(); ++channel ) {
+ cursorDataGrid->addItem( scope->spectrum[ channel ].name, view->colors->spectrum[ channel ] );
+ }
+ cursorDataGrid->selectItem( 0 );
+
+ connect( cursorDataGrid, &DataGrid::itemSelected, [this]( unsigned index ) {
+ mainScope->cursorSelected( index );
+ zoomScope->cursorSelected( index );
+ } );
+ connect( cursorDataGrid, &DataGrid::itemUpdated, [this, scope]( unsigned index ) {
unsigned channelCount = scope->countChannels();
- if (0 < index && index < channelCount + 1) {
+ if ( 0 < index && index < channelCount + 1 ) {
ChannelID channel = index - 1;
- if (scope->voltage[channel].used) {
- unsigned shape = (unsigned)scope->voltage[channel].cursor.shape;
- if (shape == DsoSettingsScopeCursor::NONE) {
- scope->voltage[channel].cursor.shape = DsoSettingsScopeCursor::RECTANGULAR;
+ if ( scope->voltage[ channel ].used ) {
+ unsigned shape = scope->voltage[ channel ].cursor.shape;
+ if ( shape == DsoSettingsScopeCursor::NONE ) {
+ scope->voltage[ channel ].cursor.shape = DsoSettingsScopeCursor::RECTANGULAR;
} else {
- scope->voltage[channel].cursor.shape = DsoSettingsScopeCursor::NONE;
+ scope->voltage[ channel ].cursor.shape = DsoSettingsScopeCursor::NONE;
}
}
- } else if (channelCount < index && index < 2 * channelCount + 1) {
+ } else if ( channelCount < index && index < 2 * channelCount + 1 ) {
ChannelID channel = index - channelCount - 1;
- if (scope->spectrum[channel].used) {
- unsigned shape = (unsigned)scope->spectrum[channel].cursor.shape;
- if (shape == DsoSettingsScopeCursor::NONE) {
- scope->spectrum[channel].cursor.shape = DsoSettingsScopeCursor::RECTANGULAR;
+ if ( scope->spectrum[ channel ].used ) {
+ unsigned shape = scope->spectrum[ channel ].cursor.shape;
+ if ( shape == DsoSettingsScopeCursor::NONE ) {
+ scope->spectrum[ channel ].cursor.shape = DsoSettingsScopeCursor::RECTANGULAR;
} else {
- scope->spectrum[channel].cursor.shape = DsoSettingsScopeCursor::NONE;
+ scope->spectrum[ channel ].cursor.shape = DsoSettingsScopeCursor::NONE;
}
}
}
updateMarkerDetails();
- mainScope->updateCursor(index);
- zoomScope->updateCursor(index);
- });
+ mainScope->updateCursor( index );
+ zoomScope->updateCursor( index );
+ } );
scope->horizontal.cursor.shape = DsoSettingsScopeCursor::VERTICAL;
// The layout for the widgets
mainLayout = new QGridLayout();
- mainLayout->setColumnStretch(3, 1); // Scopes increase their size
+ mainLayout->setColumnStretch( 3, 1 ); // Scopes increase their size
// Bars around the scope, needed because the slider-drawing-area is outside
// the scope at min/max
- mainLayout->setColumnMinimumWidth(2, mainSliders.triggerPositionSlider->preMargin());
- mainLayout->setColumnMinimumWidth(4, mainSliders.triggerPositionSlider->postMargin());
- mainLayout->setSpacing(0);
+ mainLayout->setColumnMinimumWidth( 2, mainSliders.triggerPositionSlider->preMargin() );
+ mainLayout->setColumnMinimumWidth( 4, mainSliders.triggerPositionSlider->postMargin() );
+ mainLayout->setSpacing( 0 );
int row = 0;
- mainLayout->addLayout(settingsLayout, row++, 1, 1, 5);
- // 5x5 box for mainScope & mainSliders
- mainLayout->setRowMinimumHeight(row + 1, mainSliders.offsetSlider->preMargin());
- mainLayout->setRowMinimumHeight(row + 3, mainSliders.offsetSlider->postMargin());
- mainLayout->setRowStretch(row + 2, 1);
- mainLayout->addWidget(mainScope, row + 2, 3);
- mainLayout->addWidget(mainSliders.offsetSlider, row + 1, 1, 3, 2, Qt::AlignRight);
- mainLayout->addWidget(mainSliders.triggerPositionSlider, row, 2, 2, 3, Qt::AlignBottom);
- mainLayout->addWidget(mainSliders.triggerLevelSlider, row + 1, 4, 3, 2, Qt::AlignLeft);
- mainLayout->addWidget(mainSliders.markerSlider, row + 3, 2, 2, 3, Qt::AlignTop);
- row += 5;
+ // display settings on top of scope
+ mainLayout->addLayout( settingsLayout, row, 1, 1, 5 );
+ ++row;
+ // 5x5 box for mainScope & mainSliders & markerSlider
+ mainLayout->addWidget( mainSliders.triggerPositionSlider, row, 2, 2, 3, Qt::AlignBottom );
+ ++row;
+ mainLayout->setRowMinimumHeight( row, mainSliders.voltageOffsetSlider->preMargin() );
+ mainLayout->addWidget( mainSliders.voltageOffsetSlider, row, 1, 3, 2, Qt::AlignRight );
+ mainLayout->addWidget( mainSliders.triggerLevelSlider, row, 4, 3, 2, Qt::AlignLeft );
+ ++row;
+ mainLayout->setRowStretch( row, 1 ); // the scope gets max space
+ mainLayout->addWidget( mainScope, row, 3 );
+ ++row;
+ mainLayout->setRowMinimumHeight( row, mainSliders.voltageOffsetSlider->postMargin() );
+ mainLayout->addWidget( mainSliders.markerSlider, row, 2, 2, 3, Qt::AlignTop );
+ row += 2; // end 5x5 box
// Separators and markerLayout
- mainLayout->setRowMinimumHeight(row++, 5);
- mainLayout->addLayout(markerLayout, row++, 1, 1, 5);
- mainLayout->setRowMinimumHeight(row++, 4);
- // 5x5 box for zoomScope & zoomSliders
- zoomScopeRow = row + 2;
- mainLayout->addWidget(zoomScope, zoomScopeRow, 3);
- mainLayout->addWidget(zoomSliders.offsetSlider, row + 1, 1, 3, 2, Qt::AlignRight);
- mainLayout->addWidget(zoomSliders.triggerPositionSlider, row, 2, 2, 3, Qt::AlignBottom);
- mainLayout->addWidget(zoomSliders.triggerLevelSlider, row + 1, 4, 3, 2, Qt::AlignLeft);
- row += 5;
+ ++row;
+ mainLayout->addLayout( markerLayout, row, 1, 1, 5 );
+ ++row;
+ ++row;
+ // 5x4 box for zoomScope & zoomSliders
+ mainLayout->addWidget( zoomSliders.triggerPositionSlider, row, 2, 2, 3, Qt::AlignBottom );
+ ++row;
+ mainLayout->setRowMinimumHeight( row, zoomSliders.voltageOffsetSlider->preMargin() );
+ mainLayout->addWidget( zoomSliders.voltageOffsetSlider, row, 1, 3, 2, Qt::AlignRight );
+ mainLayout->addWidget( zoomSliders.triggerLevelSlider, row, 4, 3, 2, Qt::AlignLeft );
+ ++row;
+ mainLayout->addWidget( zoomScope, zoomScopeRow = row, 3 );
+ ++row;
+ mainLayout->setRowMinimumHeight( row, zoomSliders.voltageOffsetSlider->postMargin() );
+ ++row; // end 5x4 box
// Separator and embedded measurementLayout
- mainLayout->setRowMinimumHeight(row++, 8);
- mainLayout->addLayout(measurementLayout, row++, 1, 1, 5);
+ ++row;
+ mainLayout->addLayout( measurementLayout, row, 1, 1, 5 );
- updateCursorGrid(view->cursorsVisible);
+ updateCursorGrid( view->cursorsVisible );
// The widget itself
- setPalette(palette);
- setBackgroundRole(QPalette::Background);
- setAutoFillBackground(true);
- setLayout(mainLayout);
+ setPalette( palette );
+ setBackgroundRole( QPalette::Background );
+ setAutoFillBackground( true );
+ setLayout( mainLayout );
// Connect change-signals of sliders
- connect(mainSliders.offsetSlider, &LevelSlider::valueChanged, this, &DsoWidget::updateOffset);
- connect(zoomSliders.offsetSlider, &LevelSlider::valueChanged, this, &DsoWidget::updateOffset);
+ connect( mainSliders.voltageOffsetSlider, &LevelSlider::valueChanged, this, &DsoWidget::updateOffset );
+ connect( zoomSliders.voltageOffsetSlider, &LevelSlider::valueChanged, this, &DsoWidget::updateOffset );
+
+ connect( mainSliders.triggerPositionSlider, &LevelSlider::valueChanged,
+ [this]( int index, double value ) { updateTriggerOffset( index, value, true ); } );
+ connect( zoomSliders.triggerPositionSlider, &LevelSlider::valueChanged,
+ [this]( int index, double value ) { updateTriggerOffset( index, value, false ); } );
+
+ connect( mainSliders.triggerLevelSlider, &LevelSlider::valueChanged, this, &DsoWidget::updateTriggerLevel );
+ connect( zoomSliders.triggerLevelSlider, &LevelSlider::valueChanged, this, &DsoWidget::updateTriggerLevel );
+
+ // show a horizontal level line as long as the trigger level slider is active
+ connect( mainSliders.triggerLevelSlider, &LevelSlider::valueChanged, [this]( int index, double value, bool pressed ) {
+ mainScope->generateGrid( index, value, pressed );
+ zoomScope->generateGrid( index, value, pressed );
+ } );
+ connect( zoomSliders.triggerLevelSlider, &LevelSlider::valueChanged, [this]( int index, double value, bool pressed ) {
+ mainScope->generateGrid( index, value, pressed );
+ zoomScope->generateGrid( index, value, pressed );
+ } );
+
+ connect( mainSliders.markerSlider, &LevelSlider::valueChanged, [this]( int index, double value ) {
+ updateMarker( unsigned( index ), value );
+ mainScope->updateCursor();
+ zoomScope->updateCursor();
+ } );
+ zoomSliders.markerSlider->setEnabled( false );
+}
- connect(mainSliders.triggerPositionSlider, &LevelSlider::valueChanged, [this](int index, double value) {
- updateTriggerPosition(index, value, true);
- });
- connect(zoomSliders.triggerPositionSlider, &LevelSlider::valueChanged, [this](int index, double value) {
- updateTriggerPosition(index, value, false);
- });
- connect(mainSliders.triggerLevelSlider, &LevelSlider::valueChanged, this, &DsoWidget::updateTriggerLevel);
- connect(zoomSliders.triggerLevelSlider, &LevelSlider::valueChanged, this, &DsoWidget::updateTriggerLevel);
+void DsoWidget::switchToPrintColors() {
+ if ( view->printerColorImages ) {
+ view->colors = &view->print;
+ setColors();
+ }
+}
- connect(mainSliders.markerSlider, &LevelSlider::valueChanged, [this](int index, double value) {
- updateMarker(index, value);
- mainScope->updateCursor();
- zoomScope->updateCursor();
- });
- zoomSliders.markerSlider->setEnabled(false);
+
+void DsoWidget::restoreScreenColors() {
+ if ( view->colors != &view->screen ) {
+ view->colors = &view->screen;
+ setColors();
+ }
}
-void DsoWidget::updateCursorGrid(bool enabled) {
- if (!enabled) {
- cursorDataGrid->selectItem(0);
- cursorDataGrid->setParent(nullptr);
- mainScope->cursorSelected(0);
- zoomScope->cursorSelected(0);
+
+void DsoWidget::setColors() {
+ // Palette for this widget
+ QPalette paletteNow;
+ paletteNow.setColor( QPalette::Background, view->colors->background );
+ paletteNow.setColor( QPalette::WindowText, view->colors->text );
+ settingsSamplesOnScreen->setPalette( paletteNow );
+ settingsSamplerateLabel->setPalette( paletteNow );
+ settingsTimebaseLabel->setPalette( paletteNow );
+ settingsFrequencybaseLabel->setPalette( paletteNow );
+ markerInfoLabel->setPalette( paletteNow );
+ markerTimeLabel->setPalette( paletteNow );
+ markerFrequencyLabel->setPalette( paletteNow );
+ markerTimebaseLabel->setPalette( paletteNow );
+ markerFrequencybaseLabel->setPalette( paletteNow );
+ QPalette tablePalette = paletteNow;
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ tablePalette.setColor( QPalette::WindowText, view->colors->voltage[ channel ] );
+ measurementNameLabel[ channel ]->setPalette( tablePalette );
+ measurementMiscLabel[ channel ]->setPalette( tablePalette );
+ measurementGainLabel[ channel ]->setPalette( tablePalette );
+ mainSliders.voltageOffsetSlider->setColor( ( channel ), view->colors->voltage[ channel ] );
+ zoomSliders.voltageOffsetSlider->setColor( ( channel ), view->colors->voltage[ channel ] );
+ mainSliders.voltageOffsetSlider->setColor( unsigned( scope->voltage.size() ) + channel, view->colors->spectrum[ channel ] );
+ zoomSliders.voltageOffsetSlider->setColor( unsigned( scope->voltage.size() ) + channel, view->colors->spectrum[ channel ] );
+ tablePalette.setColor( QPalette::WindowText, view->colors->spectrum[ channel ] );
+ measurementMagnitudeLabel[ channel ]->setPalette( tablePalette );
+ measurementVppLabel[ channel ]->setPalette( paletteNow );
+ measurementRMSLabel[ channel ]->setPalette( paletteNow );
+ measurementDCLabel[ channel ]->setPalette( paletteNow );
+ measurementACLabel[ channel ]->setPalette( paletteNow );
+ measurementdBLabel[ channel ]->setPalette( paletteNow );
+ measurementFrequencyLabel[ channel ]->setPalette( paletteNow );
+ }
+
+ tablePalette = palette();
+ tablePalette.setColor( QPalette::WindowText, view->colors->voltage[ scope->trigger.source ] );
+ settingsTriggerLabel->setPalette( tablePalette );
+ updateTriggerSource();
+ setPalette( paletteNow );
+ setBackgroundRole( QPalette::Background );
+}
+
+
+void DsoWidget::updateCursorGrid( bool enabled ) {
+ if ( !enabled ) {
+ cursorDataGrid->selectItem( 0 );
+ cursorDataGrid->setParent( nullptr );
+ mainScope->cursorSelected( 0 );
+ zoomScope->cursorSelected( 0 );
return;
}
- switch (view->cursorGridPosition) {
+ switch ( view->cursorGridPosition ) {
case Qt::LeftToolBarArea:
- if (mainLayout->itemAtPosition(0, 0) == nullptr) {
- cursorDataGrid->setParent(nullptr);
- mainLayout->addWidget(cursorDataGrid, 0, 0, mainLayout->rowCount(), 1);
+ if ( mainLayout->itemAtPosition( 0, 0 ) == nullptr ) {
+ cursorDataGrid->setParent( nullptr );
+ mainLayout->addWidget( cursorDataGrid, 0, 0, mainLayout->rowCount(), 1 );
}
break;
case Qt::RightToolBarArea:
- if (mainLayout->itemAtPosition(0, 6) == nullptr) {
- cursorDataGrid->setParent(nullptr);
- mainLayout->addWidget(cursorDataGrid, 0, 6, mainLayout->rowCount(), 1);
+ if ( mainLayout->itemAtPosition( 0, 6 ) == nullptr ) {
+ cursorDataGrid->setParent( nullptr );
+ mainLayout->addWidget( cursorDataGrid, 0, 6, mainLayout->rowCount(), 1 );
}
break;
default:
- if (cursorDataGrid->parent() != nullptr) {
- cursorDataGrid->setParent(nullptr);
+ if ( cursorDataGrid->parent() != nullptr ) {
+ cursorDataGrid->setParent( nullptr );
}
break;
}
}
-void DsoWidget::setupSliders(DsoWidget::Sliders &sliders) {
+
+void DsoWidget::setupSliders( DsoWidget::Sliders &sliders ) {
// The offset sliders for all possible channels
- sliders.offsetSlider = new LevelSlider(Qt::RightArrow);
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
- sliders.offsetSlider->addSlider(scope->voltage[channel].name, channel);
- sliders.offsetSlider->setColor(channel, view->screen.voltage[channel]);
- sliders.offsetSlider->setLimits(channel, -DIVS_VOLTAGE / 2, DIVS_VOLTAGE / 2);
- sliders.offsetSlider->setStep(channel, 0.2);
- sliders.offsetSlider->setValue(channel, scope->voltage[channel].offset);
- sliders.offsetSlider->setIndexVisible(channel, scope->voltage[channel].used);
- }
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
- sliders.offsetSlider->addSlider(scope->spectrum[channel].name, scope->voltage.size() + channel);
- sliders.offsetSlider->setColor(scope->voltage.size() + channel, view->screen.spectrum[channel]);
- sliders.offsetSlider->setLimits(scope->voltage.size() + channel, -DIVS_VOLTAGE / 2, DIVS_VOLTAGE / 2);
- sliders.offsetSlider->setStep(scope->voltage.size() + channel, 0.2);
- sliders.offsetSlider->setValue(scope->voltage.size() + channel, scope->spectrum[channel].offset);
- sliders.offsetSlider->setIndexVisible(scope->voltage.size() + channel, scope->spectrum[channel].used);
+ sliders.voltageOffsetSlider = new LevelSlider( Qt::RightArrow );
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ sliders.voltageOffsetSlider->addSlider( scope->voltage[ channel ].name, int( channel ) );
+ sliders.voltageOffsetSlider->setColor( ( channel ), view->colors->voltage[ channel ] );
+ sliders.voltageOffsetSlider->setLimits( int( channel ), -DIVS_VOLTAGE / 2, DIVS_VOLTAGE / 2 );
+ sliders.voltageOffsetSlider->setStep( int( channel ), 0.2 );
+ sliders.voltageOffsetSlider->setValue( int( channel ), scope->voltage[ channel ].offset );
+ sliders.voltageOffsetSlider->setIndexVisible( channel, scope->voltage[ channel ].used );
+ }
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ sliders.voltageOffsetSlider->addSlider( scope->spectrum[ channel ].name, int( scope->voltage.size() + channel ) );
+ sliders.voltageOffsetSlider->setColor( unsigned( scope->voltage.size() ) + channel, view->colors->spectrum[ channel ] );
+ sliders.voltageOffsetSlider->setLimits( int( scope->voltage.size() + channel ), -DIVS_VOLTAGE / 2, DIVS_VOLTAGE / 2 );
+ sliders.voltageOffsetSlider->setStep( int( scope->voltage.size() + channel ), 0.2 );
+ sliders.voltageOffsetSlider->setValue( int( scope->voltage.size() + channel ), scope->spectrum[ channel ].offset );
+ sliders.voltageOffsetSlider->setIndexVisible( unsigned( scope->voltage.size() ) + channel,
+ scope->spectrum[ channel ].used );
}
// The triggerPosition slider
- sliders.triggerPositionSlider = new LevelSlider(Qt::DownArrow);
+ sliders.triggerPositionSlider = new LevelSlider( Qt::DownArrow );
sliders.triggerPositionSlider->addSlider();
- sliders.triggerPositionSlider->setLimits(0, 0.0, 1.0);
- sliders.triggerPositionSlider->setStep(0, 0.2 / (double)DIVS_TIME);
- sliders.triggerPositionSlider->setValue(0, scope->trigger.position);
- sliders.triggerPositionSlider->setIndexVisible(0, true);
+ sliders.triggerPositionSlider->setLimits( 0, 0.0, 1.0 );
+ sliders.triggerPositionSlider->setStep( 0, 0.2 / double( DIVS_TIME ) );
+ sliders.triggerPositionSlider->setValue( 0, scope->trigger.offset );
+ sliders.triggerPositionSlider->setIndexVisible( 0, true );
// The sliders for the trigger levels
- sliders.triggerLevelSlider = new LevelSlider(Qt::LeftArrow);
- for (ChannelID channel = 0; channel < spec->channels; ++channel) {
- sliders.triggerLevelSlider->addSlider((int)channel);
- sliders.triggerLevelSlider->setColor(channel,
- (!scope->trigger.special && channel == scope->trigger.source)
- ? view->screen.voltage[channel]
- : view->screen.voltage[channel].darker());
- adaptTriggerLevelSlider(sliders, channel);
- sliders.triggerLevelSlider->setValue(channel, scope->voltage[channel].trigger);
- sliders.triggerLevelSlider->setIndexVisible(channel, scope->voltage[channel].used);
+ sliders.triggerLevelSlider = new LevelSlider( Qt::LeftArrow );
+ for ( ChannelID channel = 0; channel < spec->channels; ++channel ) {
+ sliders.triggerLevelSlider->addSlider( int( channel ) );
+ sliders.triggerLevelSlider->setColor( channel, ( channel == scope->trigger.source )
+ ? view->colors->voltage[ channel ]
+ : view->colors->voltage[ channel ].darker() );
+ adaptTriggerLevelSlider( sliders, channel );
+ sliders.triggerLevelSlider->setValue( int( channel ), scope->voltage[ channel ].trigger );
+ sliders.triggerLevelSlider->setIndexVisible( channel, scope->voltage[ channel ].used );
}
// The marker slider
- sliders.markerSlider = new LevelSlider(Qt::UpArrow);
- for (int marker = 0; marker < MARKER_COUNT; ++marker) {
- sliders.markerSlider->addSlider(QString::number(marker + 1), marker);
- sliders.markerSlider->setLimits(marker, -DIVS_TIME / 2, DIVS_TIME / 2);
- sliders.markerSlider->setStep(marker, MARKER_STEP);
- sliders.markerSlider->setValue(marker, scope->horizontal.cursor.pos[marker].x());
- sliders.markerSlider->setIndexVisible(marker, true);
+ sliders.markerSlider = new LevelSlider( Qt::UpArrow );
+ for ( int marker = 0; marker < 2; ++marker ) {
+ sliders.markerSlider->addSlider( QString::number( marker + 1 ), marker );
+ sliders.markerSlider->setLimits( marker, MARGIN_LEFT, MARGIN_RIGHT );
+ sliders.markerSlider->setStep( marker, MARKER_STEP );
+ sliders.markerSlider->setValue( marker, scope->horizontal.cursor.pos[ marker ].x() );
+ sliders.markerSlider->setIndexVisible( unsigned( marker ), true );
}
}
+
/// \brief Set the trigger level sliders minimum and maximum to the new values.
-void DsoWidget::adaptTriggerLevelSlider(DsoWidget::Sliders &sliders, ChannelID channel) {
- sliders.triggerLevelSlider->setLimits((int)channel,
- (-DIVS_VOLTAGE / 2 - scope->voltage[channel].offset) * scope->gain(channel),
- (DIVS_VOLTAGE / 2 - scope->voltage[channel].offset) * scope->gain(channel));
- sliders.triggerLevelSlider->setStep((int)channel, scope->gain(channel) * 0.05);
+void DsoWidget::adaptTriggerLevelSlider( DsoWidget::Sliders &sliders, ChannelID channel ) {
+ // printf( "DW::adaptTriggerLevelSlider( %d )\n", channel );
+ sliders.triggerLevelSlider->setLimits( int( channel ),
+ ( -DIVS_VOLTAGE / 2 - scope->voltage[ channel ].offset ) * scope->gain( channel ),
+ ( DIVS_VOLTAGE / 2 - scope->voltage[ channel ].offset ) * scope->gain( channel ) );
+ sliders.triggerLevelSlider->setStep( int( channel ), scope->gain( channel ) * 0.05 );
+ double value = sliders.triggerLevelSlider->value( int( channel ) );
+ if ( bool( value ) ) { // ignore when first called at init
+ // updateTriggerLevel(channel, value);
+ }
}
-/// \brief Show/Hide a line of the measurement table.
-void DsoWidget::setMeasurementVisible(ChannelID channel) {
- bool visible = scope->voltage[channel].used || scope->spectrum[channel].used;
-
- measurementNameLabel[channel]->setVisible(visible);
- measurementMiscLabel[channel]->setVisible(visible);
-
- measurementAmplitudeLabel[channel]->setVisible(visible);
- measurementFrequencyLabel[channel]->setVisible(visible);
- if (!visible) {
- measurementGainLabel[channel]->setText(QString());
- measurementAmplitudeLabel[channel]->setText(QString());
- measurementFrequencyLabel[channel]->setText(QString());
+/// \brief Show/Hide a line of the measurement table.
+void DsoWidget::setMeasurementVisible( ChannelID channel ) {
+ bool visible = scope->voltage[ channel ].used || scope->spectrum[ channel ].used;
+
+ measurementNameLabel[ channel ]->setVisible( visible );
+ measurementMiscLabel[ channel ]->setVisible( visible );
+ measurementGainLabel[ channel ]->setVisible( visible );
+ measurementVppLabel[ channel ]->setVisible( visible );
+ measurementRMSLabel[ channel ]->setVisible( visible );
+ measurementDCLabel[ channel ]->setVisible( visible );
+ measurementACLabel[ channel ]->setVisible( visible );
+ measurementdBLabel[ channel ]->setVisible( visible );
+ measurementFrequencyLabel[ channel ]->setVisible( visible );
+ if ( !visible ) {
+ measurementGainLabel[ channel ]->setText( QString() );
+ measurementVppLabel[ channel ]->setText( QString() );
+ measurementRMSLabel[ channel ]->setText( QString() );
+ measurementDCLabel[ channel ]->setText( QString() );
+ measurementACLabel[ channel ]->setText( QString() );
+ measurementdBLabel[ channel ]->setText( QString() );
+ measurementFrequencyLabel[ channel ]->setText( QString() );
}
- measurementGainLabel[channel]->setVisible(scope->voltage[channel].used);
- if (!scope->voltage[channel].used) { measurementGainLabel[channel]->setText(QString()); }
+ measurementGainLabel[ channel ]->setVisible( scope->voltage[ channel ].used );
+ if ( !scope->voltage[ channel ].used ) {
+ measurementGainLabel[ channel ]->setText( QString() );
+ }
- measurementMagnitudeLabel[channel]->setVisible(scope->spectrum[channel].used);
- if (!scope->spectrum[channel].used) { measurementMagnitudeLabel[channel]->setText(QString()); }
+ measurementMagnitudeLabel[ channel ]->setVisible( scope->spectrum[ channel ].used );
+ if ( !scope->spectrum[ channel ].used ) {
+ measurementMagnitudeLabel[ channel ]->setText( QString() );
+ }
}
-static QString markerToString(DsoSettingsScope *scope, unsigned index) {
- double value = (DIVS_TIME * (0.5 - scope->trigger.position) + scope->getMarker(index)) * scope->horizontal.timebase;
- int precision = 3 - (int)floor(log10(fabs(value)));
-
- if (scope->horizontal.timebase < 1e-9)
- return QApplication::tr("%L1 ps").arg(value / 1e-12, 0, 'f', qBound(0, precision - 12, 3));
- else if (scope->horizontal.timebase < 1e-6)
- return QApplication::tr("%L1 ns").arg(value / 1e-9, 0, 'f', qBound(0, precision - 9, 3));
- else if (scope->horizontal.timebase < 1e-3)
- return QApplication::tr("%L1 µs").arg(value / 1e-6, 0, 'f', qBound(0, precision - 6, 3));
- else if (scope->horizontal.timebase < 1)
- return QApplication::tr("%L1 ms").arg(value / 1e-3, 0, 'f', qBound(0, precision - 3, 3));
- else
- return QApplication::tr("%L1 s").arg(value, 0, 'f', qBound(0, precision, 3));
-}
/// \brief Update the label about the marker measurements
void DsoWidget::updateMarkerDetails() {
- double divs = fabs(scope->horizontal.cursor.pos[1].x() - scope->horizontal.cursor.pos[0].x());
+ double m1 = scope->horizontal.cursor.pos[ 0 ].x() + DIVS_TIME / 2; // zero at center -> zero at left margin
+ double m2 = scope->horizontal.cursor.pos[ 1 ].x() + DIVS_TIME / 2; // zero at center -> zero at left margin
+ if ( m1 > m2 )
+ std::swap( m1, m2 );
+ double divs = m2 - m1;
+ // t = 0 at trigger position
+ double time0 = ( m1 - DIVS_TIME * scope->trigger.offset ) * scope->horizontal.timebase;
+ double time1 = ( m2 - DIVS_TIME * scope->trigger.offset ) * scope->horizontal.timebase;
double time = divs * scope->horizontal.timebase;
+ double freq0 = m1 * scope->horizontal.frequencybase;
+ double freq1 = m2 * scope->horizontal.frequencybase;
double freq = divs * scope->horizontal.frequencybase;
-
- QString prefix(tr("Markers"));
- if (view->zoom) {
- prefix = tr("Zoom x%L1").arg(DIVS_TIME / divs, -1, 'g', 3);
- markerTimebaseLabel->setText(valueToString(time / DIVS_TIME, UNIT_SECONDS, 3) + tr("/div"));
- markerFrequencybaseLabel->setText(
- valueToString(divs * scope->horizontal.frequencybase / DIVS_TIME, UNIT_HERTZ, 4) + tr("/div"));
- }
- markerInfoLabel->setText(prefix.append(": %1 %2").arg(markerToString(scope, 0)).arg(markerToString(scope, 1)));
- markerTimeLabel->setText(valueToString(time, UNIT_SECONDS, 4));
- markerFrequencyLabel->setText(valueToString(1.0 / time, UNIT_HERTZ, 4));
+ bool timeUsed = false;
+ bool freqUsed = false;
int index = 0;
- cursorDataGrid->updateInfo(index++, true, QString(), valueToString(time, UNIT_SECONDS, 4), valueToString(freq, UNIT_HERTZ, 4));
-
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
- if (scope->voltage[channel].used) {
- QPointF p0 = scope->voltage[channel].cursor.pos[0];
- QPointF p1 = scope->voltage[channel].cursor.pos[1];
- cursorDataGrid->updateInfo(index, true,
- scope->voltage[channel].cursor.shape != DsoSettingsScopeCursor::NONE ? tr("ON") : tr("OFF"),
- valueToString(fabs(p1.x() - p0.x()) * scope->horizontal.timebase, UNIT_SECONDS, 4),
- valueToString(fabs(p1.y() - p0.y()) * scope->gain(channel), UNIT_VOLTS, 4));
+ cursorDataGrid->updateInfo( unsigned( index++ ), true, QString(), valueToString( time, UNIT_SECONDS, 3 ),
+ valueToString( freq, UNIT_HERTZ, 3 ) );
+
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ if ( scope->voltage[ channel ].used ) {
+ timeUsed = true; // at least one voltage channel used -> show marker time details
+ QPointF p0 = scope->voltage[ channel ].cursor.pos[ 0 ];
+ QPointF p1 = scope->voltage[ channel ].cursor.pos[ 1 ];
+ cursorDataGrid->updateInfo( unsigned( index ), true,
+ scope->voltage[ channel ].cursor.shape != DsoSettingsScopeCursor::NONE ? tr( "ON" )
+ : tr( "OFF" ),
+ valueToString( fabs( p1.x() - p0.x() ) * scope->horizontal.timebase, UNIT_SECONDS, 4 ),
+ valueToString( fabs( p1.y() - p0.y() ) * scope->gain( channel ), UNIT_VOLTS, 4 ) );
} else {
- cursorDataGrid->updateInfo(index, false);
+ cursorDataGrid->updateInfo( unsigned( index ), false );
}
++index;
}
- for (ChannelID channel = 0; channel < scope->spectrum.size(); ++channel) {
- if (scope->spectrum[channel].used) {
- QPointF p0 = scope->spectrum[channel].cursor.pos[0];
- QPointF p1 = scope->spectrum[channel].cursor.pos[1];
- cursorDataGrid->updateInfo(index, true,
- scope->spectrum[channel].cursor.shape != DsoSettingsScopeCursor::NONE ? tr("ON") : tr("OFF"),
- valueToString(fabs(p1.x() - p0.x()) * scope->horizontal.frequencybase, UNIT_HERTZ, 4),
- valueToString(fabs(p1.y() - p0.y()) * scope->spectrum[channel].magnitude, UNIT_DECIBEL, 4));
+ for ( ChannelID channel = 0; channel < scope->spectrum.size(); ++channel ) {
+ if ( scope->spectrum[ channel ].used ) {
+ freqUsed = true; // at least one spec channel used -> show marker freq details
+ QPointF p0 = scope->spectrum[ channel ].cursor.pos[ 0 ];
+ QPointF p1 = scope->spectrum[ channel ].cursor.pos[ 1 ];
+ cursorDataGrid->updateInfo(
+ unsigned( index ), true,
+ scope->spectrum[ channel ].cursor.shape != DsoSettingsScopeCursor::NONE ? tr( "ON" ) : tr( "OFF" ),
+ valueToString( fabs( p1.x() - p0.x() ) * scope->horizontal.frequencybase, UNIT_HERTZ, 4 ),
+ valueToString( fabs( p1.y() - p0.y() ) * scope->spectrum[ channel ].magnitude, UNIT_DECIBEL, 4 ) );
} else {
- cursorDataGrid->updateInfo(index, false);
+ cursorDataGrid->updateInfo( unsigned( index ), false );
}
++index;
}
+
+ if ( divs >= DIVS_TIME || ( m1 <= 0 && m2 <= 0 ) || ( m1 >= DIVS_TIME && m2 >= DIVS_TIME ) ) {
+ // markers at left/right margins -> don't display
+ markerInfoLabel->setVisible( false );
+ markerTimeLabel->setVisible( false );
+ markerFrequencyLabel->setVisible( false );
+ markerTimebaseLabel->setVisible( false );
+ markerFrequencybaseLabel->setVisible( false );
+ } else {
+ markerInfoLabel->setVisible( true );
+ markerTimeLabel->setVisible( true );
+ markerFrequencyLabel->setVisible( true );
+ markerTimebaseLabel->setVisible( view->zoom );
+ markerFrequencybaseLabel->setVisible( view->zoom );
+ QString mInfo( tr( "Markers " ) );
+ QString mTime( tr( "Time: " ) );
+ QString mFreq( tr( "Frequency: " ) );
+ if ( view->zoom ) {
+ if ( divs != 0.0 )
+ mInfo = tr( "Zoom x%L1 " ).arg( DIVS_TIME / divs, -1, 'g', 3 );
+ else // avoid div by zero
+ mInfo = tr( "Zoom --- " );
+ mTime = " t: ";
+ mFreq = " f: ";
+ markerTimebaseLabel->setText( " " + valueToString( time / DIVS_TIME, UNIT_SECONDS, 3 ) + tr( "/div" ) );
+ markerTimebaseLabel->setVisible( timeUsed );
+ markerFrequencybaseLabel->setText( " " + valueToString( freq / DIVS_TIME, UNIT_HERTZ, 3 ) + tr( "/div" ) );
+ markerFrequencybaseLabel->setVisible( freqUsed );
+ }
+ markerInfoLabel->setText( mInfo );
+ if ( timeUsed ) {
+ mTime += QString( "%1" ).arg( valueToString( time0, UNIT_SECONDS, 3 ) );
+ if ( time > 0 )
+ mTime += QString( " ... %1, Δt: %2 (%3) " )
+ .arg( valueToString( time1, UNIT_SECONDS, 3 ), valueToString( time, UNIT_SECONDS, 3 ),
+ valueToString( 1 / time, UNIT_HERTZ, 3 ) );
+ markerTimeLabel->setText( mTime );
+ } else {
+ markerTimeLabel->setText( "" );
+ }
+ if ( freqUsed ) {
+ mFreq += QString( "%1" ).arg( valueToString( freq0, UNIT_HERTZ, 3 ) );
+ if ( freq > 0 )
+ mFreq += QString( " ... %2, Δf: %3 " )
+ .arg( valueToString( freq1, UNIT_HERTZ, 3 ), valueToString( freq, UNIT_HERTZ, 3 ) );
+ markerFrequencyLabel->setText( mFreq );
+ } else
+ markerFrequencyLabel->setText( "" );
+ }
}
-/// \brief Update the label about the trigger settings
-void DsoWidget::updateSpectrumDetails(ChannelID channel) {
- setMeasurementVisible(channel);
- if (scope->spectrum[channel].used)
- measurementMagnitudeLabel[channel]->setText(valueToString(scope->spectrum[channel].magnitude, UNIT_DECIBEL, 3) +
- tr("/div"));
+/// \brief Update the label about the spectrum settings
+void DsoWidget::updateSpectrumDetails( ChannelID channel ) {
+ setMeasurementVisible( channel );
+ if ( scope->spectrum[ channel ].used )
+ measurementMagnitudeLabel[ channel ]->setText( valueToString( scope->spectrum[ channel ].magnitude, UNIT_DECIBEL, 3 ) +
+ tr( "/div" ) );
else
- measurementMagnitudeLabel[channel]->setText(QString());
+ measurementMagnitudeLabel[ channel ]->setText( QString() );
}
+
/// \brief Update the label about the trigger settings
void DsoWidget::updateTriggerDetails() {
// Update the trigger details
QPalette tablePalette = palette();
- tablePalette.setColor(QPalette::WindowText, view->screen.voltage[scope->trigger.source]);
- settingsTriggerLabel->setPalette(tablePalette);
- QString levelString = valueToString(scope->voltage[scope->trigger.source].trigger, UNIT_VOLTS, 3);
- QString pretriggerString = tr("%L1%").arg((int)(scope->trigger.position * 100 + 0.5));
- settingsTriggerLabel->setText(tr("%1 %2 %3 %4")
- .arg(scope->voltage[scope->trigger.source].name,
- Dso::slopeString(scope->trigger.slope), levelString, pretriggerString));
-
- /// \todo This won't work for special trigger sources
+ tablePalette.setColor( QPalette::WindowText, view->colors->voltage[ scope->trigger.source ] );
+ settingsTriggerLabel->setPalette( tablePalette );
+ QString levelString = valueToString( scope->voltage[ scope->trigger.source ].trigger, UNIT_VOLTS, 3 );
+ QString pretriggerString = tr( "%L1%" ).arg( int( round( scope->trigger.offset * 100 ) ) );
+ QString pre = Dso::slopeString( scope->trigger.slope ); // trigger slope
+ QString post = pre; // opposite trigger slope
+ if ( scope->trigger.slope == Dso::Slope::Positive )
+ post = Dso::slopeString( Dso::Slope::Negative );
+ else if ( scope->trigger.slope == Dso::Slope::Negative )
+ post = Dso::slopeString( Dso::Slope::Positive );
+ QString pulseWidthString = bool( pulseWidth1 ) ? pre + valueToString( pulseWidth1, UNIT_SECONDS, 3 ) + post : "";
+ pulseWidthString += bool( pulseWidth2 ) ? valueToString( pulseWidth2, UNIT_SECONDS, 3 ) + pre : "";
+ if ( bool( pulseWidth1 ) && bool( pulseWidth2 ) ) {
+ int dutyCyle = int( 0.5 + ( 100.0 * pulseWidth1 ) / ( pulseWidth1 + pulseWidth2 ) );
+ pulseWidthString += " (" + QString::number( dutyCyle ) + "%)";
+ }
+ if ( scope->trigger.mode != Dso::TriggerMode::ROLL ) {
+ settingsTriggerLabel->setText( tr( "%1 %2 %3 %4 %5" )
+ .arg( scope->voltage[ scope->trigger.source ].name,
+ Dso::slopeString( scope->trigger.slope ), levelString, pretriggerString,
+ pulseWidthString ) );
+ } else {
+ settingsTriggerLabel->setText( "" );
+ }
}
+
/// \brief Update the label about the trigger settings
-void DsoWidget::updateVoltageDetails(ChannelID channel) {
- if (channel >= scope->voltage.size()) return;
+void DsoWidget::updateVoltageDetails( ChannelID channel ) {
+ if ( channel >= scope->voltage.size() )
+ return;
- setMeasurementVisible(channel);
+ setMeasurementVisible( channel );
- if (scope->voltage[channel].used)
- measurementGainLabel[channel]->setText(valueToString(scope->gain(channel), UNIT_VOLTS, 3) + tr("/div"));
+ if ( scope->voltage[ channel ].used )
+ measurementGainLabel[ channel ]->setText( valueToString( scope->gain( channel ), UNIT_VOLTS, 3 ) + tr( "/div" ) );
else
- measurementGainLabel[channel]->setText(QString());
+ measurementGainLabel[ channel ]->setText( QString() );
}
+
/// \brief Handles frequencybaseChanged signal from the horizontal dock.
/// \param frequencybase The frequencybase used for displaying the trace.
-void DsoWidget::updateFrequencybase(double frequencybase) {
- settingsFrequencybaseLabel->setText(valueToString(frequencybase, UNIT_HERTZ, 4) + tr("/div"));
+void DsoWidget::updateFrequencybase( double frequencybase ) {
+ settingsFrequencybaseLabel->setText( valueToString( frequencybase, UNIT_HERTZ, -1 ) + tr( "/div" ) );
+ updateMarkerDetails();
}
+
/// \brief Updates the samplerate field after changing the samplerate.
/// \param samplerate The samplerate set in the oscilloscope.
-void DsoWidget::updateSamplerate(double samplerate) {
- settingsSamplerateLabel->setText(valueToString(samplerate, UNIT_SAMPLES, 4) + tr("/s"));
+void DsoWidget::updateSamplerate( double newSamplerate ) {
+ samplerate = newSamplerate;
+ dotsOnScreen = unsigned( samplerate * timebase * DIVS_TIME + 0.99 );
+ // printf( "DsoWidget::updateSamplerate( %g ) -> %d\n", samplerate, dotsOnScreen );
+ settingsSamplerateLabel->setText( valueToString( samplerate, UNIT_SAMPLES, -1 ) + tr( "/s" ) );
}
+
/// \brief Handles timebaseChanged signal from the horizontal dock.
/// \param timebase The timebase used for displaying the trace.
-void DsoWidget::updateTimebase(double timebase) {
- settingsTimebaseLabel->setText(valueToString(timebase, UNIT_SECONDS, 4) + tr("/div"));
-
+void DsoWidget::updateTimebase( double newTimebase ) {
+ timebase = newTimebase;
+ dotsOnScreen = unsigned( samplerate * timebase * DIVS_TIME + 0.99 );
+ // printf( "DsoWidget::updateTimebase( %g ) -> %d\n", timebase, dotsOnScreen );
+ settingsTimebaseLabel->setText( valueToString( timebase, UNIT_SECONDS, -1 ) + tr( "/div" ) );
updateMarkerDetails();
}
+
/// \brief Handles magnitudeChanged signal from the spectrum dock.
/// \param channel The channel whose magnitude was changed.
-void DsoWidget::updateSpectrumMagnitude(ChannelID channel) { updateSpectrumDetails(channel); }
+void DsoWidget::updateSpectrumMagnitude( ChannelID channel ) { updateSpectrumDetails( channel ); }
/// \brief Handles usedChanged signal from the spectrum dock.
/// \param channel The channel whose used-state was changed.
/// \param used The new used-state for the channel.
-void DsoWidget::updateSpectrumUsed(ChannelID channel, bool used) {
- if (channel >= (unsigned int)scope->voltage.size()) return;
-
-// if (!used && cursorDataGrid->spectrumCursors[channel].selector->isChecked()) cursorDataGrid->selectItem(0);
-
- mainSliders.offsetSlider->setIndexVisible(scope->voltage.size() + channel, used);
- zoomSliders.offsetSlider->setIndexVisible(scope->voltage.size() + channel, used);
-
- updateSpectrumDetails(channel);
+void DsoWidget::updateSpectrumUsed( ChannelID channel, bool used ) {
+ if ( channel >= unsigned( scope->voltage.size() ) )
+ return;
+ bool spectrumUsed = false;
+ for ( size_t channel = 0; channel < scope->voltage.size(); ++channel )
+ if ( scope->spectrum[ channel ].used )
+ spectrumUsed = true;
+ settingsFrequencybaseLabel->setVisible( spectrumUsed ); // hide text if no spectrum channel used
+ mainSliders.voltageOffsetSlider->setIndexVisible( unsigned( scope->voltage.size() ) + channel, used );
+ zoomSliders.voltageOffsetSlider->setIndexVisible( unsigned( scope->voltage.size() ) + channel, used );
+
+ updateSpectrumDetails( channel );
updateMarkerDetails();
}
+
/// \brief Handles modeChanged signal from the trigger dock.
void DsoWidget::updateTriggerMode() { updateTriggerDetails(); }
+
/// \brief Handles slopeChanged signal from the trigger dock.
void DsoWidget::updateTriggerSlope() { updateTriggerDetails(); }
+
/// \brief Handles sourceChanged signal from the trigger dock.
void DsoWidget::updateTriggerSource() {
// Change the colors of the trigger sliders
- if (scope->trigger.special || scope->trigger.source >= spec->channels) {
- mainSliders.triggerPositionSlider->setColor(0, view->screen.border);
- zoomSliders.triggerPositionSlider->setColor(0, view->screen.border);
- } else {
- mainSliders.triggerPositionSlider->setColor(0, view->screen.voltage[scope->trigger.source]);
- zoomSliders.triggerPositionSlider->setColor(0, view->screen.voltage[scope->trigger.source]);
- }
-
- for (ChannelID channel = 0; channel < spec->channels; ++channel) {
- QColor color = (!scope->trigger.special && channel == scope->trigger.source)
- ? view->screen.voltage[channel]
- : view->screen.voltage[channel].darker();
- mainSliders.triggerLevelSlider->setColor(channel, color);
- zoomSliders.triggerLevelSlider->setColor(channel, color);
+ mainSliders.triggerPositionSlider->setColor( 0, view->colors->voltage[ scope->trigger.source ] );
+ zoomSliders.triggerPositionSlider->setColor( 0, view->colors->voltage[ scope->trigger.source ] );
+
+ for ( ChannelID channel = 0; channel < spec->channels; ++channel ) {
+ QColor color =
+ ( channel == scope->trigger.source ) ? view->colors->voltage[ channel ] : view->colors->voltage[ channel ].darker();
+ mainSliders.triggerLevelSlider->setColor( channel, color );
+ zoomSliders.triggerLevelSlider->setColor( channel, color );
}
updateTriggerDetails();
}
+
/// \brief Handles couplingChanged signal from the voltage dock.
/// \param channel The channel whose coupling was changed.
-void DsoWidget::updateVoltageCoupling(ChannelID channel) {
- if (channel >= (unsigned int)scope->voltage.size()) return;
-
- measurementMiscLabel[channel]->setText(Dso::couplingString(scope->coupling(channel, spec)));
+void DsoWidget::updateVoltageCoupling( ChannelID channel ) {
+ if ( channel >= unsigned( scope->voltage.size() ) )
+ return;
+ measurementMiscLabel[ channel ]->setText( Dso::couplingString( scope->coupling( channel, spec ) ) );
}
+
/// \brief Handles modeChanged signal from the voltage dock.
void DsoWidget::updateMathMode() {
- measurementMiscLabel[spec->channels]->setText(
- Dso::mathModeString(Dso::getMathMode(scope->voltage[spec->channels])));
+ measurementMiscLabel[ spec->channels ]->setText( Dso::mathModeString( Dso::getMathMode( scope->voltage[ spec->channels ] ) ) );
}
+
/// \brief Handles gainChanged signal from the voltage dock.
/// \param channel The channel whose gain was changed.
-void DsoWidget::updateVoltageGain(ChannelID channel) {
- if (channel >= (unsigned int)scope->voltage.size()) return;
-
- if (channel < spec->channels) {
- adaptTriggerLevelSlider(mainSliders, channel);
- adaptTriggerLevelSlider(zoomSliders, channel);
+void DsoWidget::updateVoltageGain( ChannelID channel ) {
+ if ( channel >= unsigned( scope->voltage.size() ) )
+ return;
+ if ( channel < spec->channels ) {
+ adaptTriggerLevelSlider( mainSliders, channel );
+ adaptTriggerLevelSlider( zoomSliders, channel );
}
-
- updateVoltageDetails(channel);
+ updateVoltageDetails( channel );
}
+
/// \brief Handles usedChanged signal from the voltage dock.
/// \param channel The channel whose used-state was changed.
/// \param used The new used-state for the channel.
-void DsoWidget::updateVoltageUsed(ChannelID channel, bool used) {
- if (channel >= (unsigned int)scope->voltage.size()) return;
+void DsoWidget::updateVoltageUsed( ChannelID channel, bool used ) {
+ if ( channel >= unsigned( scope->voltage.size() ) )
+ return;
-// if (!used && cursorDataGrid->voltageCursors[channel].selector->isChecked()) cursorDataGrid->selectItem(0);
+ // if (!used && cursorDataGrid->voltageCursors[channel].selector->isChecked()) cursorDataGrid->selectItem(0);
- mainSliders.offsetSlider->setIndexVisible(channel, used);
- zoomSliders.offsetSlider->setIndexVisible(channel, used);
+ mainSliders.voltageOffsetSlider->setIndexVisible( channel, used );
+ zoomSliders.voltageOffsetSlider->setIndexVisible( channel, used );
- mainSliders.triggerLevelSlider->setIndexVisible(channel, used);
- zoomSliders.triggerLevelSlider->setIndexVisible(channel, used);
+ mainSliders.triggerLevelSlider->setIndexVisible( channel, used );
+ zoomSliders.triggerLevelSlider->setIndexVisible( channel, used );
- setMeasurementVisible(channel);
- updateVoltageDetails(channel);
+ setMeasurementVisible( channel );
+ updateVoltageDetails( channel );
updateMarkerDetails();
}
+
/// \brief Change the record length.
-void DsoWidget::updateRecordLength(unsigned long size) {
- settingsRecordLengthLabel->setText(valueToString(size, UNIT_SAMPLES, 4));
+void DsoWidget::updateRecordLength( unsigned long size ) {
+ settingsSamplesOnScreen->setText( valueToString( size, UNIT_SAMPLES, -1 ) + tr( " on screen" ) );
}
-/// \brief Show/hide the zoom view.
-void DsoWidget::updateZoom(bool enabled) {
- mainLayout->setRowStretch(zoomScopeRow, enabled ? 1 : 0);
- zoomScope->setVisible(enabled);
-
- if (enabled) {
- zoomSliders.offsetSlider->show();
- zoomSliders.triggerPositionSlider->show();
- zoomSliders.triggerLevelSlider->show();
- } else {
- zoomSliders.offsetSlider->hide();
- zoomSliders.triggerPositionSlider->hide();
- zoomSliders.triggerLevelSlider->hide();
- }
+/// \brief Show/hide the zoom view.
+void DsoWidget::updateZoom( bool enabled ) {
+ mainLayout->setRowStretch( zoomScopeRow, enabled ? 1 : 0 );
+ zoomScope->setVisible( enabled );
+ zoomSliders.voltageOffsetSlider->setVisible( enabled );
+ zoomSliders.triggerPositionSlider->setVisible( enabled );
+ zoomSliders.triggerLevelSlider->setVisible( enabled );
// Show time-/frequencybase and zoom factor if the magnified scope is shown
- markerLayout->setStretch(3, enabled ? 1 : 0);
- markerTimebaseLabel->setVisible(enabled);
- markerLayout->setStretch(4, enabled ? 1 : 0);
- markerFrequencybaseLabel->setVisible(enabled);
+ markerLayout->setStretch( 3, enabled ? 1 : 0 );
+ markerTimebaseLabel->setVisible( enabled );
+ markerLayout->setStretch( 4, enabled ? 1 : 0 );
+ markerFrequencybaseLabel->setVisible( enabled );
updateMarkerDetails();
repaint();
}
+
/// \brief Prints analyzed data.
-void DsoWidget::showNew(std::shared_ptr data) {
- mainScope->showData(data);
- zoomScope->showData(data);
-
- if (spec->isSoftwareTriggerDevice) {
- QPalette triggerLabelPalette = palette();
- triggerLabelPalette.setColor(QPalette::WindowText, Qt::black);
- triggerLabelPalette.setColor(QPalette::Background, data->softwareTriggerTriggered ? Qt::green : Qt::red);
- swTriggerStatus->setPalette(triggerLabelPalette);
- swTriggerStatus->setVisible(true);
- }
-
- updateRecordLength(data.get()->sampleCount());
-
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
- if (scope->voltage[channel].used && data.get()->data(channel)) {
- // Amplitude string representation (4 significant digits)
- measurementAmplitudeLabel[channel]->setText(
- valueToString(data.get()->data(channel)->computeAmplitude(), UNIT_VOLTS, 4));
- // Frequency string representation (5 significant digits)
- measurementFrequencyLabel[channel]->setText(
- valueToString(data.get()->data(channel)->frequency, UNIT_HERTZ, 5));
+void DsoWidget::showNew( std::shared_ptr< PPresult > analysedData ) {
+ mainScope->showData( analysedData );
+ zoomScope->showData( analysedData );
+
+ QPalette triggerLabelPalette = palette();
+ if ( scope->trigger.mode == Dso::TriggerMode::ROLL ) {
+ triggerLabelPalette.setColor( QPalette::WindowText, view->colors->background );
+ triggerLabelPalette.setColor( QPalette::Background, view->colors->background );
+ } else {
+ triggerLabelPalette.setColor( QPalette::WindowText, Qt::black );
+ triggerLabelPalette.setColor( QPalette::Background, analysedData->softwareTriggerTriggered ? Qt::green : Qt::red );
+ }
+ swTriggerStatus->setPalette( triggerLabelPalette );
+ swTriggerStatus->setVisible( true );
+ updateRecordLength( dotsOnScreen );
+ pulseWidth1 = analysedData.get()->data( 0 )->pulseWidth1;
+ pulseWidth2 = analysedData.get()->data( 0 )->pulseWidth2;
+ updateTriggerDetails();
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ if ( scope->voltage[ channel ].used && analysedData.get()->data( channel ) ) {
+ // Vpp Amplitude string representation (3 significant digits)
+ measurementVppLabel[ channel ]->setText( valueToString( analysedData.get()->data( channel )->vpp, UNIT_VOLTS, 3 ) +
+ tr( "pp" ) );
+ // RMS Amplitude string representation (3 significant digits)
+ measurementRMSLabel[ channel ]->setText( valueToString( analysedData.get()->data( channel )->rms, UNIT_VOLTS, 3 ) +
+ tr( "rms" ) );
+ // DC Amplitude string representation (3 significant digits)
+ measurementDCLabel[ channel ]->setText( valueToString( analysedData.get()->data( channel )->dc, UNIT_VOLTS, 3 ) + "=" );
+ // AC Amplitude string representation (3 significant digits)
+ measurementACLabel[ channel ]->setText( valueToString( analysedData.get()->data( channel )->ac, UNIT_VOLTS, 3 ) + "~" );
+ // dB Amplitude string representation (3 significant digits)
+ measurementdBLabel[ channel ]->setText( valueToString( analysedData.get()->data( channel )->dB, UNIT_DECIBEL, 3 ) );
+ // Frequency string representation (3 significant digits)
+ measurementFrequencyLabel[ channel ]->setText(
+ valueToString( analysedData.get()->data( channel )->frequency, UNIT_HERTZ, 4 ) );
+ // Highlight clipped channel
+ QPalette validPalette;
+ if ( analysedData.get()->data( channel )->valid ) { // normal display
+ validPalette.setColor( QPalette::WindowText, view->colors->voltage[ channel ] );
+ validPalette.setColor( QPalette::Background, view->colors->background );
+ } else { // warning
+ validPalette.setColor( QPalette::WindowText, Qt::black );
+ validPalette.setColor( QPalette::Background, Qt::red );
+ }
+ measurementNameLabel[ channel ]->setPalette( validPalette );
}
}
}
-void DsoWidget::showEvent(QShowEvent *event) {
- QWidget::showEvent(event);
+
+void DsoWidget::showEvent( QShowEvent *event ) {
+ QWidget::showEvent( event );
// Apply settings and update measured values
updateTriggerDetails();
- updateRecordLength(scope->horizontal.recordLength);
- updateFrequencybase(scope->horizontal.frequencybase);
- updateSamplerate(scope->horizontal.samplerate);
- updateTimebase(scope->horizontal.timebase);
- updateZoom(view->zoom);
+ updateRecordLength( scope->horizontal.recordLength );
+ updateFrequencybase( scope->horizontal.frequencybase );
+ updateSamplerate( scope->horizontal.samplerate );
+ updateTimebase( scope->horizontal.timebase );
+ updateZoom( view->zoom );
updateTriggerSource();
- adaptTriggerPositionSlider();
+ adaptTriggerOffsetSlider();
}
+
/// \brief Handles valueChanged signal from the offset sliders.
/// \param channel The channel whose offset was changed.
/// \param value The new offset for the channel.
-void DsoWidget::updateOffset(ChannelID channel, double value) {
- if (channel < scope->voltage.size()) {
- scope->voltage[channel].offset = value;
+void DsoWidget::updateOffset( ChannelID channel, double value ) {
+ if ( channel < scope->voltage.size() ) {
+ scope->voltage[ channel ].offset = value;
- if (channel < spec->channels) {
- adaptTriggerLevelSlider(mainSliders, channel);
- adaptTriggerLevelSlider(zoomSliders, channel);
+ if ( channel < spec->channels ) {
+ adaptTriggerLevelSlider( mainSliders, channel );
+ adaptTriggerLevelSlider( zoomSliders, channel );
}
- } else if (channel < scope->voltage.size() * 2)
- scope->spectrum[channel - scope->voltage.size()].offset = value;
-
- if (channel < scope->voltage.size() * 2) {
- if (mainSliders.offsetSlider->value(channel) != value) {
- const QSignalBlocker blocker(mainSliders.offsetSlider);
- mainSliders.offsetSlider->setValue(channel, value);
+ } else if ( channel < scope->voltage.size() * 2 )
+ scope->spectrum[ channel - scope->voltage.size() ].offset = value;
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+ if ( channel < scope->voltage.size() * 2 ) {
+ if ( mainSliders.voltageOffsetSlider->value( int( channel ) ) != value ) { // double != comparison is safe in this case
+ const QSignalBlocker blocker( mainSliders.voltageOffsetSlider );
+ mainSliders.voltageOffsetSlider->setValue( int( channel ), value );
}
- if (zoomSliders.offsetSlider->value(channel) != value) {
- const QSignalBlocker blocker(zoomSliders.offsetSlider);
- zoomSliders.offsetSlider->setValue(channel, value);
+ if ( zoomSliders.voltageOffsetSlider->value( int( channel ) ) != value ) { // double != comparison is safe in this case
+ const QSignalBlocker blocker( zoomSliders.voltageOffsetSlider );
+ zoomSliders.voltageOffsetSlider->setValue( int( channel ), value );
}
}
-
- emit offsetChanged(channel, value);
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+ emit voltageOffsetChanged( channel, value );
}
+
/// \brief Translate horizontal position (0..1) from main view to zoom view.
-double DsoWidget::mainToZoom(double position) const {
- double m1 = scope->getMarker(0);
- double m2 = scope->getMarker(1);
- if (m1 > m2) std::swap(m1, m2);
- return ((position - 0.5) * DIVS_TIME - m1) / (m2 - m1);
+double DsoWidget::mainToZoom( double position ) const {
+ double m1 = scope->getMarker( 0 );
+ double m2 = scope->getMarker( 1 );
+ if ( m1 > m2 )
+ std::swap( m1, m2 );
+ return ( ( position - 0.5 ) * DIVS_TIME - m1 ) / std::max( m2 - m1, 1e-9 );
}
+
/// \brief Translate horizontal position (0..1) from zoom view to main view.
-double DsoWidget::zoomToMain(double position) const {
- double m1 = scope->getMarker(0);
- double m2 = scope->getMarker(1);
- if (m1 > m2) std::swap(m1, m2);
- return 0.5 + (m1 + position * (m2 - m1)) / DIVS_TIME;
+double DsoWidget::zoomToMain( double position ) const {
+ double m1 = scope->getMarker( 0 );
+ double m2 = scope->getMarker( 1 );
+ if ( m1 > m2 )
+ std::swap( m1, m2 );
+ return 0.5 + ( m1 + position * ( m2 - m1 ) ) / DIVS_TIME;
}
+
/// \brief Handles signals affecting trigger position in the zoom view.
-void DsoWidget::adaptTriggerPositionSlider() {
- double value = mainToZoom(scope->trigger.position);
+void DsoWidget::adaptTriggerOffsetSlider() {
+ double value = mainToZoom( scope->trigger.offset );
LevelSlider &slider = *zoomSliders.triggerPositionSlider;
- const QSignalBlocker blocker(slider);
- if (slider.minimum(0) <= value && value <= slider.maximum(0)) {
- slider.setEnabled(true);
- slider.setValue(0, value);
+ const QSignalBlocker blocker( slider );
+ if ( slider.minimum( 0 ) <= value && value <= slider.maximum( 0 ) ) {
+ slider.setEnabled( true );
+ slider.setValue( 0, value );
} else {
- slider.setEnabled(false);
- if (value < slider.minimum(0)) {
- slider.setValue(0, slider.minimum(0));
+ slider.setEnabled( false );
+ if ( value < slider.minimum( 0 ) ) {
+ slider.setValue( 0, slider.minimum( 0 ) );
} else {
- slider.setValue(0, slider.maximum(0));
+ slider.setValue( 0, slider.maximum( 0 ) );
}
}
}
+
/// \brief Handles valueChanged signal from the triggerPosition slider.
/// \param index The index of the slider.
/// \param value The new triggerPosition in seconds relative to the first
/// sample.
-void DsoWidget::updateTriggerPosition(int index, double value, bool mainView) {
- if (index != 0) return;
+void DsoWidget::updateTriggerOffset( int index, double value, bool mainView ) {
+ if ( index != 0 )
+ return;
- if (mainView) {
- scope->trigger.position = value;
- adaptTriggerPositionSlider();
+ if ( mainView ) {
+ scope->trigger.offset = value;
+ adaptTriggerOffsetSlider();
} else {
- scope->trigger.position = zoomToMain(value);
- const QSignalBlocker blocker(mainSliders.triggerPositionSlider);
- mainSliders.triggerPositionSlider->setValue(index, scope->trigger.position);
+ scope->trigger.offset = zoomToMain( value );
+ const QSignalBlocker blocker( mainSliders.triggerPositionSlider );
+ mainSliders.triggerPositionSlider->setValue( index, scope->trigger.offset );
}
updateTriggerDetails();
updateMarkerDetails();
- emit triggerPositionChanged(scope->trigger.position * scope->horizontal.timebase * DIVS_TIME);
+ emit triggerPositionChanged( scope->trigger.offset );
}
+
/// \brief Handles valueChanged signal from the trigger level slider.
/// \param channel The index of the slider.
/// \param value The new trigger level.
-void DsoWidget::updateTriggerLevel(ChannelID channel, double value) {
- scope->voltage[channel].trigger = value;
-
- if (mainSliders.triggerLevelSlider->value(channel) != value) {
- const QSignalBlocker blocker(mainSliders.triggerLevelSlider);
- mainSliders.triggerLevelSlider->setValue(channel, value);
+void DsoWidget::updateTriggerLevel( ChannelID channel, double value ) {
+ // printf("DW::updateTriggerLevel( %d, %g )\n", channel, value);
+ scope->voltage[ channel ].trigger = value;
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+ if ( mainSliders.triggerLevelSlider->value( int( channel ) ) != value ) { // double != comparison is safe in this case
+ const QSignalBlocker blocker( mainSliders.triggerLevelSlider );
+ mainSliders.triggerLevelSlider->setValue( int( channel ), value );
}
- if (zoomSliders.triggerLevelSlider->value(channel) != value) {
- const QSignalBlocker blocker(zoomSliders.triggerLevelSlider);
- zoomSliders.triggerLevelSlider->setValue(channel, value);
+ if ( zoomSliders.triggerLevelSlider->value( int( channel ) ) != value ) { // double != comparison is safe in this case
+ const QSignalBlocker blocker( zoomSliders.triggerLevelSlider );
+ zoomSliders.triggerLevelSlider->setValue( int( channel ), value );
}
-
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
updateTriggerDetails();
- emit triggerLevelChanged(channel, value);
+ emit triggerLevelChanged( channel, value );
}
+
/// \brief Handles valueChanged signal from the marker slider.
/// \param marker The index of the slider.
/// \param value The new marker position.
-void DsoWidget::updateMarker(int marker, double value) {
- scope->setMarker(marker, value);
- adaptTriggerPositionSlider();
+void DsoWidget::updateMarker( unsigned marker, double value ) {
+ scope->setMarker( marker, value );
+ adaptTriggerOffsetSlider();
+ updateMarkerDetails();
+}
+
+
+/// \brief Update the sliders settings.
+void DsoWidget::updateSlidersSettings() {
+ // The offset sliders for all possible channels
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ updateOffset( channel, scope->voltage[ channel ].offset );
+ mainSliders.voltageOffsetSlider->setColor( ( channel ), view->colors->voltage[ channel ] );
+ mainSliders.voltageOffsetSlider->setValue( int( channel ), scope->voltage[ channel ].offset );
+ mainSliders.voltageOffsetSlider->setIndexVisible( channel, scope->voltage[ channel ].used );
+ zoomSliders.voltageOffsetSlider->setColor( ( channel ), view->colors->voltage[ channel ] );
+ zoomSliders.voltageOffsetSlider->setValue( int( channel ), scope->voltage[ channel ].offset );
+ zoomSliders.voltageOffsetSlider->setIndexVisible( channel, scope->voltage[ channel ].used );
+
+ updateOffset( unsigned( scope->voltage.size() + channel ), scope->spectrum[ channel ].offset );
+ mainSliders.voltageOffsetSlider->setColor( unsigned( scope->voltage.size() ) + channel, view->colors->spectrum[ channel ] );
+ mainSliders.voltageOffsetSlider->setValue( int( scope->voltage.size() + channel ), scope->spectrum[ channel ].offset );
+ mainSliders.voltageOffsetSlider->setIndexVisible( unsigned( scope->voltage.size() ) + channel,
+ scope->spectrum[ channel ].used );
+ zoomSliders.voltageOffsetSlider->setColor( unsigned( scope->voltage.size() ) + channel, view->colors->spectrum[ channel ] );
+ zoomSliders.voltageOffsetSlider->setValue( int( scope->voltage.size() + channel ), scope->spectrum[ channel ].offset );
+ zoomSliders.voltageOffsetSlider->setIndexVisible( unsigned( scope->voltage.size() ) + channel,
+ scope->spectrum[ channel ].used );
+ }
+
+ // The trigger position slider
+ mainSliders.triggerPositionSlider->setValue( 0, scope->trigger.offset );
+ updateTriggerOffset( 0, scope->trigger.offset, true ); // main slider
+ updateTriggerOffset( 0, mainToZoom( scope->trigger.offset ), false ); // zoom slider
+
+ // The sliders for the trigger levels
+ for ( ChannelID channel = 0; channel < spec->channels; ++channel ) {
+ mainSliders.triggerLevelSlider->setValue( int( channel ), scope->voltage[ channel ].trigger );
+ adaptTriggerLevelSlider( mainSliders, channel );
+ mainSliders.triggerLevelSlider->setColor( channel, ( channel == scope->trigger.source )
+ ? view->colors->voltage[ channel ]
+ : view->colors->voltage[ channel ].darker() );
+ mainSliders.triggerLevelSlider->setIndexVisible( channel, scope->voltage[ channel ].used );
+ zoomSliders.triggerLevelSlider->setValue( int( channel ), scope->voltage[ channel ].trigger );
+ adaptTriggerLevelSlider( zoomSliders, channel );
+ zoomSliders.triggerLevelSlider->setColor( channel, ( channel == scope->trigger.source )
+ ? view->colors->voltage[ channel ]
+ : view->colors->voltage[ channel ].darker() );
+ zoomSliders.triggerLevelSlider->setIndexVisible( channel, scope->voltage[ channel ].used );
+ }
+ updateTriggerDetails();
+
+ // The marker slider
+ for ( int marker = 0; marker < 2; ++marker ) {
+ mainSliders.markerSlider->setValue( marker, scope->horizontal.cursor.pos[ marker ].x() );
+ }
updateMarkerDetails();
}
diff --git a/openhantek/src/dsowidget.h b/openhantek/src/dsowidget.h
index e1aca1f5..c581b5db 100644
--- a/openhantek/src/dsowidget.h
+++ b/openhantek/src/dsowidget.h
@@ -2,15 +2,16 @@
#pragma once
+#include
#include
#include
#include
-#include
#include
#include "glscope.h"
-#include "levelslider.h"
#include "hantekdso/controlspecification.h"
+#include "levelslider.h"
+#include "viewsettings.h"
class SpectrumGenerator;
struct DsoSettingsScope;
@@ -23,9 +24,8 @@ class DsoWidget : public QWidget {
Q_OBJECT
public:
-
struct Sliders {
- LevelSlider *offsetSlider; ///< The sliders for the graph offsets
+ LevelSlider *voltageOffsetSlider; ///< The sliders for the graph offsets
LevelSlider *triggerPositionSlider; ///< The slider for the pretrigger
LevelSlider *triggerLevelSlider; ///< The sliders for the trigger level
LevelSlider *markerSlider; ///< The sliders for the markers
@@ -36,38 +36,41 @@ class DsoWidget : public QWidget {
/// \param dataAnalyzer The data analyzer that should be used as data source.
/// \param parent The parent widget.
/// \param flags Flags for the window manager.
- DsoWidget(DsoSettingsScope* scope, DsoSettingsView* view, const Dso::ControlSpecification* spec, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ DsoWidget( DsoSettingsScope *scope, DsoSettingsView *view, const Dso::ControlSpecification *spec, QWidget *parent = nullptr );
// Data arrived
- void showNew(std::shared_ptr data);
+ void showNew( std::shared_ptr< PPresult > analysedData );
+
+ void switchToPrintColors();
+ void restoreScreenColors();
protected:
- virtual void showEvent(QShowEvent *event);
- void setupSliders(Sliders &sliders);
- void adaptTriggerLevelSlider(DsoWidget::Sliders &sliders, ChannelID channel);
- void adaptTriggerPositionSlider();
- void setMeasurementVisible(ChannelID channel);
+ virtual void showEvent( QShowEvent *event );
+ void setupSliders( Sliders &sliders );
+ void adaptTriggerLevelSlider( DsoWidget::Sliders &sliders, ChannelID channel );
+ void adaptTriggerOffsetSlider();
+ void setMeasurementVisible( ChannelID channel );
void updateMarkerDetails();
- void updateSpectrumDetails(ChannelID channel);
+ void updateSpectrumDetails( ChannelID channel );
void updateTriggerDetails();
- void updateVoltageDetails(ChannelID channel);
+ void updateVoltageDetails( ChannelID channel );
- double mainToZoom(double position) const;
- double zoomToMain(double position) const;
+ double mainToZoom( double position ) const;
+ double zoomToMain( double position ) const;
Sliders mainSliders;
Sliders zoomSliders;
- QGridLayout *mainLayout; ///< The main layout for this widget
+ QGridLayout *mainLayout; ///< The main layout for this widget
QHBoxLayout *settingsLayout; ///< The table for the settings info
QLabel *settingsTriggerLabel; ///< The trigger details
- QLabel *settingsRecordLengthLabel; ///< The record length
+ QLabel *settingsSamplesOnScreen; ///< The displayed dots on screen
QLabel *settingsSamplerateLabel; ///< The samplerate
QLabel *settingsTimebaseLabel; ///< The timebase of the main scope
QLabel *settingsFrequencybaseLabel; ///< The frequencybase of the main scope
- QLabel *swTriggerStatus; ///< The status of SW trigger
+ QLabel *swTriggerStatus; ///< The status of SW trigger
QHBoxLayout *markerLayout; ///< The table for the marker details
QLabel *markerInfoLabel; ///< The info about the zoom factor
@@ -76,29 +79,41 @@ class DsoWidget : public QWidget {
QLabel *markerTimebaseLabel; ///< The timebase for the zoomed scope
QLabel *markerFrequencybaseLabel; ///< The frequencybase for the zoomed scope
- QGridLayout *measurementLayout; ///< The table for the signal details
- std::vector measurementNameLabel; ///< The name of the channel
- std::vector measurementGainLabel; ///< The gain for the voltage (V/div)
- std::vector measurementMagnitudeLabel; ///< The magnitude for the spectrum (dB/div)
- std::vector measurementMiscLabel; ///< Coupling or math mode
- std::vector measurementAmplitudeLabel; ///< Amplitude of the signal (V)
- std::vector measurementFrequencyLabel; ///< Frequency of the signal (Hz)
+ QGridLayout *measurementLayout; ///< The table for the signal details
+ std::vector< QLabel * > measurementNameLabel; ///< The name of the channel
+ std::vector< QLabel * > measurementGainLabel; ///< The gain for the voltage (V/div)
+ std::vector< QLabel * > measurementMagnitudeLabel; ///< The magnitude for the spectrum (dB/div)
+ std::vector< QLabel * > measurementMiscLabel; ///< Coupling or math mode
+ std::vector< QLabel * > measurementVppLabel; ///< Peak-to-peak amplitude of the signal (V)
+ std::vector< QLabel * > measurementRMSLabel; ///< RMS Amplitude of the signal (V) = sqrt( DC² + AC² )
+ std::vector< QLabel * > measurementDCLabel; ///< DC Amplitude of the signal (V)
+ std::vector< QLabel * > measurementACLabel; ///< AC Amplitude of the signal (V)
+ std::vector< QLabel * > measurementdBLabel; ///< AC Amplitude in dB
+ std::vector< QLabel * > measurementFrequencyLabel; ///< Frequency of the signal (Hz)
DataGrid *cursorDataGrid;
- DsoSettingsScope* scope;
- DsoSettingsView* view;
- const Dso::ControlSpecification* spec;
+ DsoSettingsScope *scope;
+ DsoSettingsView *view;
+ const Dso::ControlSpecification *spec;
+
+ GlScope *mainScope; ///< The main scope screen
+ GlScope *zoomScope; ///< The optional magnified scope screen
- GlScope *mainScope; ///< The main scope screen
- GlScope *zoomScope; ///< The optional magnified scope screen
+ private:
+ double samplerate;
+ double timebase;
+ unsigned int dotsOnScreen;
+ double pulseWidth1 = 0.0;
+ double pulseWidth2 = 0.0;
+ void setColors();
public slots:
// Horizontal axis
// void horizontalFormatChanged(HorizontalFormat format);
- void updateFrequencybase(double frequencybase);
- void updateSamplerate(double samplerate);
- void updateTimebase(double timebase);
+ void updateFrequencybase( double frequencybase );
+ void updateSamplerate( double samplerate );
+ void updateTimebase( double timebase );
// Trigger
void updateTriggerMode();
@@ -106,32 +121,35 @@ class DsoWidget : public QWidget {
void updateTriggerSource();
// Spectrum
- void updateSpectrumMagnitude(ChannelID channel);
- void updateSpectrumUsed(ChannelID channel, bool used);
+ void updateSpectrumMagnitude( ChannelID channel );
+ void updateSpectrumUsed( ChannelID channel, bool used );
// Vertical axis
- void updateVoltageCoupling(ChannelID channel);
+ void updateVoltageCoupling( ChannelID channel );
void updateMathMode();
- void updateVoltageGain(ChannelID channel);
- void updateVoltageUsed(ChannelID channel, bool used);
+ void updateVoltageGain( ChannelID channel );
+ void updateVoltageUsed( ChannelID channel, bool used );
// Menus
- void updateRecordLength(unsigned long size);
+ void updateRecordLength( unsigned long size );
+
+ // Scope control
+ void updateZoom( bool enabled );
+ void updateCursorGrid( bool enabled );
// Scope control
- void updateZoom(bool enabled);
- void updateCursorGrid(bool enabled);
+ void updateSlidersSettings();
private slots:
// Sliders
- void updateOffset(ChannelID channel, double value);
- void updateTriggerPosition(int index, double value, bool mainView = true);
- void updateTriggerLevel(ChannelID channel, double value);
- void updateMarker(int marker, double value);
+ void updateOffset( ChannelID channel, double value );
+ void updateTriggerOffset( int index, double value, bool mainView = true );
+ void updateTriggerLevel( ChannelID channel, double value );
+ void updateMarker( unsigned marker, double value );
signals:
// Sliders
- void offsetChanged(ChannelID channel, double value); ///< A graph offset has been changed
- void triggerPositionChanged(double value); ///< The pretrigger has been changed
- void triggerLevelChanged(ChannelID channel, double value); ///< A trigger level has been changed
+ void voltageOffsetChanged( ChannelID channel, double value ); ///< A graph offset has been changed
+ void triggerPositionChanged( double value ); ///< The pretrigger has been changed
+ void triggerLevelChanged( ChannelID channel, double value ); ///< A trigger level has been changed
};
diff --git a/openhantek/src/exporting/exportcsv.cpp b/openhantek/src/exporting/exportcsv.cpp
index d543bbf6..1e7eb305 100644
--- a/openhantek/src/exporting/exportcsv.cpp
+++ b/openhantek/src/exporting/exportcsv.cpp
@@ -1,102 +1,113 @@
// SPDX-License-Identifier: GPL-2.0+
#include "exportcsv.h"
+#include "dsosettings.h"
#include "exporterregistry.h"
-#include "post/ppresult.h"
-#include "settings.h"
#include "iconfont/QtAwesome.h"
+#include "post/ppresult.h"
#include
-#include
#include
#include
+#include
+#include
ExporterCSV::ExporterCSV() {}
-void ExporterCSV::create(ExporterRegistry *registry) { this->registry = registry; data.reset(); }
+void ExporterCSV::create( ExporterRegistry *newRegistry ) {
+ this->registry = newRegistry;
+ data.reset();
+}
-QIcon ExporterCSV::icon() { return iconFont->icon(fa::filetexto); }
+int ExporterCSV::faIcon() { return fa::filetexto; }
-QString ExporterCSV::name() { return QCoreApplication::tr("Export CSV"); }
+QString ExporterCSV::name() { return tr( "Export &CSV .." ); }
ExporterInterface::Type ExporterCSV::type() { return Type::SnapshotExport; }
-bool ExporterCSV::samples(const std::shared_ptr data) {
- this->data = std::move(data);
+bool ExporterCSV::samples( const std::shared_ptr< PPresult > newData ) {
+ data = std::move( newData );
return false;
}
bool ExporterCSV::save() {
- QStringList filters;
- filters << QCoreApplication::tr("Comma-Separated Values (*.csv)");
-
- QFileDialog fileDialog(nullptr, QCoreApplication::tr("Export file..."), QString(), filters.join(";;"));
- fileDialog.setFileMode(QFileDialog::AnyFile);
- fileDialog.setAcceptMode(QFileDialog::AcceptSave);
- if (fileDialog.exec() != QDialog::Accepted) return false;
+ QFileDialog fileDialog( nullptr, tr( "Save CSV" ), QString(), tr( "Comma-Separated Values (*.csv)" ) );
+ fileDialog.setFileMode( QFileDialog::AnyFile );
+ fileDialog.setAcceptMode( QFileDialog::AcceptSave );
+ if ( fileDialog.exec() != QDialog::Accepted )
+ return false;
- QFile csvFile(fileDialog.selectedFiles().first());
- if (!csvFile.open(QIODevice::WriteOnly | QIODevice::Text)) return false;
+ QFile csvFile( fileDialog.selectedFiles().first() );
+ if ( !csvFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
+ return false;
- QTextStream csvStream(&csvFile);
- csvStream.setRealNumberNotation(QTextStream::FixedNotation);
- csvStream.setRealNumberPrecision(10);
+ QTextStream csvStream( &csvFile );
+ csvStream.setRealNumberNotation( QTextStream::FixedNotation );
+ csvStream.setRealNumberPrecision( 10 );
size_t chCount = registry->settings->scope.voltage.size();
- std::vector voltageData(size_t(chCount), nullptr);
- std::vector spectrumData(size_t(chCount), nullptr);
+ std::vector< const SampleValues * > voltageData( size_t( chCount ), nullptr );
+ std::vector< const SampleValues * > spectrumData( size_t( chCount ), nullptr );
size_t maxRow = 0;
bool isSpectrumUsed = false;
double timeInterval = 0;
double freqInterval = 0;
- for (ChannelID channel = 0; channel < chCount; ++channel) {
- if (data->data(channel)) {
- if (registry->settings->scope.voltage[channel].used) {
- voltageData[channel] = &(data->data(channel)->voltage);
- maxRow = std::max(maxRow, voltageData[channel]->sample.size());
- timeInterval = data->data(channel)->voltage.interval;
+ // use semicolon as data separator if comma is already used as decimal separator - e.g. with german locale
+ const char *sep = QLocale::system().decimalPoint() == ',' ? ";" : ",";
+
+ for ( ChannelID channel = 0; channel < chCount; ++channel ) {
+ if ( data->data( channel ) ) {
+ if ( registry->settings->scope.voltage[ channel ].used ) {
+ voltageData[ channel ] = &( data->data( channel )->voltage );
+ maxRow = std::max( maxRow, voltageData[ channel ]->sample.size() );
+ timeInterval = data->data( channel )->voltage.interval;
}
- if (registry->settings->scope.spectrum[channel].used) {
- spectrumData[channel] = &(data->data(channel)->spectrum);
- maxRow = std::max(maxRow, spectrumData[channel]->sample.size());
- freqInterval = data->data(channel)->spectrum.interval;
+ if ( registry->settings->scope.spectrum[ channel ].used ) {
+ spectrumData[ channel ] = &( data->data( channel )->spectrum );
+ maxRow = std::max( maxRow, spectrumData[ channel ]->sample.size() );
+ freqInterval = data->data( channel )->spectrum.interval;
isSpectrumUsed = true;
}
}
}
// Start with channel names
- csvStream << "\"t\"";
- for (ChannelID channel = 0; channel < chCount; ++channel) {
- if (voltageData[channel] != nullptr) { csvStream << ",\"" << registry->settings->scope.voltage[channel].name << "\""; }
+ csvStream << "\"t / s\"";
+ for ( ChannelID channel = 0; channel < chCount; ++channel ) {
+ if ( voltageData[ channel ] != nullptr ) {
+ csvStream << sep << "\"" << registry->settings->scope.voltage[ channel ].name << " / V\"";
+ }
}
- if (isSpectrumUsed) {
- csvStream << ",\"f\"";
- for (ChannelID channel = 0; channel < chCount; ++channel) {
- if (spectrumData[channel] != nullptr) {
- csvStream << ",\"" << registry->settings->scope.spectrum[channel].name << "\"";
+ if ( isSpectrumUsed ) {
+ csvStream << sep << "\"f / Hz\"";
+ for ( ChannelID channel = 0; channel < chCount; ++channel ) {
+ if ( spectrumData[ channel ] != nullptr ) {
+ csvStream << sep << "\"" << registry->settings->scope.spectrum[ channel ].name << " / dB\"";
}
}
}
csvStream << "\n";
- for (unsigned int row = 0; row < maxRow; ++row) {
-
- csvStream << timeInterval * row;
- for (ChannelID channel = 0; channel < chCount; ++channel) {
- if (voltageData[channel] != nullptr) {
- csvStream << ",";
- if (row < voltageData[channel]->sample.size()) { csvStream << voltageData[channel]->sample[row]; }
+ for ( unsigned int row = 0; row < maxRow; ++row ) {
+ csvStream << QLocale::system().toString( timeInterval * row );
+ for ( ChannelID channel = 0; channel < chCount; ++channel ) {
+ if ( voltageData[ channel ] != nullptr ) {
+ csvStream << sep;
+ if ( row < voltageData[ channel ]->sample.size() ) {
+ csvStream << QLocale::system().toString( voltageData[ channel ]->sample[ row ] );
+ }
}
}
- if (isSpectrumUsed) {
- csvStream << "," << freqInterval * row;
- for (ChannelID channel = 0; channel < chCount; ++channel) {
- if (spectrumData[channel] != nullptr) {
- csvStream << ",";
- if (row < spectrumData[channel]->sample.size()) { csvStream << spectrumData[channel]->sample[row]; }
+ if ( isSpectrumUsed ) {
+ csvStream << sep << QLocale::system().toString( freqInterval * row );
+ for ( ChannelID channel = 0; channel < chCount; ++channel ) {
+ if ( spectrumData[ channel ] != nullptr ) {
+ csvStream << sep;
+ if ( row < spectrumData[ channel ]->sample.size() ) {
+ csvStream << QLocale::system().toString( spectrumData[ channel ]->sample[ row ] );
+ }
}
}
}
@@ -108,4 +119,5 @@ bool ExporterCSV::save() {
return true;
}
+
float ExporterCSV::progress() { return data ? 1.0f : 0; }
diff --git a/openhantek/src/exporting/exportcsv.h b/openhantek/src/exporting/exportcsv.h
index 09a2278c..89eb9ada 100644
--- a/openhantek/src/exporting/exportcsv.h
+++ b/openhantek/src/exporting/exportcsv.h
@@ -3,17 +3,19 @@
#pragma once
#include "exporterinterface.h"
-class ExporterCSV : public ExporterInterface
-{
-public:
+class ExporterCSV : public ExporterInterface {
+ Q_DECLARE_TR_FUNCTIONS( LegacyExportDrawer )
+
+ public:
ExporterCSV();
- virtual void create(ExporterRegistry *registry) override;
- virtual QIcon icon() override;
- virtual QString name() override;
- virtual Type type() override;
- virtual bool samples(const std::shared_ptrdata) override;
- virtual bool save() override;
- virtual float progress() override;
-private:
- std::shared_ptr data;
+ void create( ExporterRegistry *registry ) override;
+ int faIcon() override;
+ QString name() override;
+ Type type() override;
+ bool samples( const std::shared_ptr< PPresult > newData ) override;
+ bool save() override;
+ float progress() override;
+
+ private:
+ std::shared_ptr< PPresult > data;
};
diff --git a/openhantek/src/exporting/exporterinterface.cpp b/openhantek/src/exporting/exporterinterface.cpp
new file mode 100644
index 00000000..3c1c30b1
--- /dev/null
+++ b/openhantek/src/exporting/exporterinterface.cpp
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include "exporterinterface.h"
+
+ExporterInterface::~ExporterInterface() {}
diff --git a/openhantek/src/exporting/exporterinterface.h b/openhantek/src/exporting/exporterinterface.h
index 2720d102..674a6f72 100644
--- a/openhantek/src/exporting/exporterinterface.h
+++ b/openhantek/src/exporting/exporterinterface.h
@@ -2,6 +2,7 @@
#pragma once
+#include
#include
#include
@@ -15,22 +16,22 @@ class PPresult;
* in the main routine to make an Exporter available.
*/
class ExporterInterface {
-public:
-
+ public:
+ virtual ~ExporterInterface();
/**
- * Starts up this exporter. Aquires resources etc. Do not call this directly, it
- * will be called by the exporter registry at some point. Release your resources in the
- * destructor as usual.
- * @param registry The exporter registry instance. This is used to obtain a reference
- * to the settings.
- */
- virtual void create(ExporterRegistry *registry) = 0;
+ * Starts up this exporter. Aquires resources etc. Do not call this directly, it
+ * will be called by the exporter registry at some point. Release your resources in the
+ * destructor as usual.
+ * @param registry The exporter registry instance. This is used to obtain a reference
+ * to the settings.
+ */
+ virtual void create( ExporterRegistry *registry ) = 0;
/**
* @return Return the icon representation of this exporter. Will be used in graphical
* interfaces.
*/
- virtual QIcon icon() = 0;
+ virtual int faIcon() = 0;
/**
* @return Return the text representation / name of this exporter. Will be used in graphical
@@ -54,7 +55,7 @@ class ExporterInterface {
* If it is a snapshot exporter, only one set of samples will be received.
* @return Return true if you want to receive another sample or false if you are done (progres()==1).
*/
- virtual bool samples(const std::shared_ptr) = 0;
+ virtual bool samples( const std::shared_ptr< PPresult > ) = 0;
/**
* Exporter: Save your received data and perform any conversions necessary.
@@ -73,6 +74,7 @@ class ExporterInterface {
* A continous exporter may report the used memory / reservered memory ratio here.
*/
virtual float progress() = 0;
-protected:
+
+ protected:
ExporterRegistry *registry;
};
diff --git a/openhantek/src/exporting/exporterprocessor.cpp b/openhantek/src/exporting/exporterprocessor.cpp
index 7e435500..71c52dd3 100644
--- a/openhantek/src/exporting/exporterprocessor.cpp
+++ b/openhantek/src/exporting/exporterprocessor.cpp
@@ -1,6 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
+
#include "exporterprocessor.h"
#include "exporterregistry.h"
-ExporterProcessor::ExporterProcessor(ExporterRegistry *registry) : registry(registry) {}
+ExporterProcessor::ExporterProcessor( ExporterRegistry *registry ) : registry( registry ) {}
-void ExporterProcessor::process(PPresult *data) { registry->addRawSamples(data); }
+void ExporterProcessor::process( PPresult *data ) { registry->addRawSamples( data ); }
diff --git a/openhantek/src/exporting/exporterprocessor.h b/openhantek/src/exporting/exporterprocessor.h
index a920ac9f..3250a890 100644
--- a/openhantek/src/exporting/exporterprocessor.h
+++ b/openhantek/src/exporting/exporterprocessor.h
@@ -1,14 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+
#pragma once
#include "post/processor.h"
class ExporterRegistry;
-class ExporterProcessor : public Processor
-{
-public:
- ExporterProcessor(ExporterRegistry* registry);
- virtual void process(PPresult *) override;
-private:
- ExporterRegistry* registry;
+class ExporterProcessor : public Processor {
+ public:
+ explicit ExporterProcessor( ExporterRegistry *registry );
+ void process( PPresult * ) override;
+
+ private:
+ ExporterRegistry *registry;
};
diff --git a/openhantek/src/exporting/exporterregistry.cpp b/openhantek/src/exporting/exporterregistry.cpp
index 249eba36..230e6581 100644
--- a/openhantek/src/exporting/exporterregistry.cpp
+++ b/openhantek/src/exporting/exporterregistry.cpp
@@ -6,79 +6,80 @@
#include
#include "controlspecification.h"
+#include "dsosettings.h"
#include "post/ppresult.h"
-#include "settings.h"
-ExporterRegistry::ExporterRegistry(const Dso::ControlSpecification *deviceSpecification, DsoSettings *settings,
- QObject *parent)
- : QObject(parent), deviceSpecification(deviceSpecification), settings(settings) {}
+ExporterRegistry::ExporterRegistry( const Dso::ControlSpecification *deviceSpecification, DsoSettings *settings, QObject *parent )
+ : QObject( parent ), deviceSpecification( deviceSpecification ), settings( settings ) {}
-bool ExporterRegistry::processData(std::shared_ptr &data, ExporterInterface *const &exporter) {
- if (!exporter->samples(data)) {
- waitToSaveExporters.insert(exporter);
+bool ExporterRegistry::processData( std::shared_ptr< PPresult > &data, ExporterInterface *const &exporter ) {
+ if ( !exporter->samples( data ) ) {
+ waitToSaveExporters.insert( exporter );
emit exporterProgressChanged();
return true;
}
return false;
}
-void ExporterRegistry::addRawSamples(PPresult *d) {
- if (settings->exporting.useProcessedSamples) return;
- std::shared_ptr data(d);
- enabledExporters.remove_if([&data, this](ExporterInterface *const &i) { return processData(data, i); });
+void ExporterRegistry::addRawSamples( PPresult *d ) {
+ if ( settings->exportProcessedSamples )
+ return;
+ std::shared_ptr< PPresult > data( d );
+ enabledExporters.remove_if( [&data, this]( ExporterInterface *const &i ) { return processData( data, i ); } );
}
-void ExporterRegistry::input(std::shared_ptr data) {
- if (!settings->exporting.useProcessedSamples) return;
- enabledExporters.remove_if([&data, this](ExporterInterface *const &i) { return processData(data, i); });
+void ExporterRegistry::input( std::shared_ptr< PPresult > data ) {
+ if ( !settings->exportProcessedSamples )
+ return;
+ enabledExporters.remove_if( [&data, this]( ExporterInterface *const &i ) { return processData( data, i ); } );
}
-void ExporterRegistry::registerExporter(ExporterInterface *exporter) {
- exporters.push_back(exporter);
- exporter->create(this);
+void ExporterRegistry::registerExporter( ExporterInterface *exporter ) {
+ exporters.push_back( exporter );
+ exporter->create( this );
}
-void ExporterRegistry::setExporterEnabled(ExporterInterface *exporter, bool enabled) {
+void ExporterRegistry::setExporterEnabled( ExporterInterface *exporter, bool enabled ) {
bool wasInList = false;
- enabledExporters.remove_if([exporter, &wasInList](ExporterInterface *inlist) {
- if (inlist == exporter) {
+ enabledExporters.remove_if( [exporter, &wasInList]( ExporterInterface *inlist ) {
+ if ( inlist == exporter ) {
wasInList = true;
return true;
} else
return false;
- });
+ } );
- if (enabled) {
+ if ( enabled ) {
// If the exporter was waiting for the user save confirmation,
// reset it instead.
- auto localFind = waitToSaveExporters.find(exporter);
- if (localFind != waitToSaveExporters.end()) {
- waitToSaveExporters.erase(localFind);
- exporter->create(this);
+ auto localFind = waitToSaveExporters.find( exporter );
+ if ( localFind != waitToSaveExporters.end() ) {
+ waitToSaveExporters.erase( localFind );
+ exporter->create( this );
}
- enabledExporters.push_back(exporter);
- } else if (wasInList) {
+ enabledExporters.push_back( exporter );
+ } else if ( wasInList ) {
// If exporter made some progress: Add to waiting for GUI list
- if (exporter->progress() > 0) {
- waitToSaveExporters.insert(exporter);
+ if ( exporter->progress() > 0 ) {
+ waitToSaveExporters.insert( exporter );
emit exporterProgressChanged();
} else // Reset exporter
- exporter->create(this);
+ exporter->create( this );
}
}
void ExporterRegistry::checkForWaitingExporters() {
- for (ExporterInterface *exporter : waitToSaveExporters) {
- if (exporter->save()) {
- emit exporterStatusChanged(exporter->name(), tr("Data saved"));
+ for ( ExporterInterface *exporter : waitToSaveExporters ) {
+ if ( exporter->save() ) {
+ emit exporterStatusChanged( exporter->name(), tr( "Data saved" ) );
} else {
- emit exporterStatusChanged(exporter->name(), tr("No data exported"));
+ emit exporterStatusChanged( exporter->name(), tr( "No data exported" ) );
}
- exporter->create(this);
+ exporter->create( this );
}
waitToSaveExporters.clear();
}
-std::vector::const_iterator ExporterRegistry::begin() { return exporters.begin(); }
+std::vector< ExporterInterface * >::const_iterator ExporterRegistry::begin() { return exporters.begin(); }
-std::vector::const_iterator ExporterRegistry::end() { return exporters.end(); }
+std::vector< ExporterInterface * >::const_iterator ExporterRegistry::end() { return exporters.end(); }
diff --git a/openhantek/src/exporting/exporterregistry.h b/openhantek/src/exporting/exporterregistry.h
index fe9fae14..2c978ef3 100644
--- a/openhantek/src/exporting/exporterregistry.h
+++ b/openhantek/src/exporting/exporterregistry.h
@@ -22,23 +22,24 @@ class ExporterInterface;
class ExporterRegistry : public QObject {
Q_OBJECT
+
public:
- explicit ExporterRegistry(const Dso::ControlSpecification *deviceSpecification, DsoSettings *settings,
- QObject *parent = nullptr);
+ explicit ExporterRegistry( const Dso::ControlSpecification *deviceSpecification, DsoSettings *settings,
+ QObject *parent = nullptr );
// Sample input. This will proably be performed in the post processing
// thread context. Do not open GUI dialogs or interrupt the control flow.
- void addRawSamples(PPresult *data);
- void input(std::shared_ptr data);
+ void addRawSamples( PPresult *data );
+ void input( std::shared_ptr< PPresult > data );
- void registerExporter(ExporterInterface *exporter);
- void setExporterEnabled(ExporterInterface *exporter, bool enabled);
+ void registerExporter( ExporterInterface *exporter );
+ void setExporterEnabled( ExporterInterface *exporter, bool enabled );
void checkForWaitingExporters();
// Iterate over this class object
- std::vector::const_iterator begin();
- std::vector::const_iterator end();
+ std::vector< ExporterInterface * >::const_iterator begin();
+ std::vector< ExporterInterface * >::const_iterator end();
/// Device specifications
const Dso::ControlSpecification *deviceSpecification;
@@ -46,19 +47,20 @@ class ExporterRegistry : public QObject {
private:
/// List of all available exporters
- std::vector exporters;
+ std::vector< ExporterInterface * > exporters;
/// List of exporters that collect samples at the moment
- std::list enabledExporters;
+ std::list< ExporterInterface * > enabledExporters;
/// List of exporters that wait to be called back by the user to save their work
- std::set waitToSaveExporters;
+ std::set< ExporterInterface * > waitToSaveExporters;
/// Process data from addRawSamples() or input() in the given exporter. Add the
/// exporter to waitToSaveExporters if it finishes.
///
/// @return Return true if the exporter has finished and want to be removed from the
/// enabledExporters list.
- bool processData(std::shared_ptr &data, ExporterInterface *const &exporter);
+ bool processData( std::shared_ptr< PPresult > &data, ExporterInterface *const &exporter );
+
signals:
- void exporterStatusChanged(const QString &exporterName, const QString &status);
+ void exporterStatusChanged( const QString &exporterName, const QString &status );
void exporterProgressChanged();
};
diff --git a/openhantek/src/exporting/exportimage.cpp b/openhantek/src/exporting/exportimage.cpp
deleted file mode 100644
index 9139251d..00000000
--- a/openhantek/src/exporting/exportimage.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include "exportimage.h"
-#include "exporterregistry.h"
-#include "iconfont/QtAwesome.h"
-#include "legacyexportdrawer.h"
-#include "post/ppresult.h"
-#include "settings.h"
-#include "viewsettings.h"
-
-#include
-#include
-#include
-
-ExporterImage::ExporterImage() {}
-
-void ExporterImage::create(ExporterRegistry *registry) { this->registry = registry; data.reset(); }
-
-QIcon ExporterImage::icon() { return iconFont->icon(fa::image); }
-
-QString ExporterImage::name() { return QCoreApplication::tr("Export Image/PDF"); }
-
-ExporterInterface::Type ExporterImage::type() { return Type::SnapshotExport; }
-
-bool ExporterImage::samples(const std::shared_ptr data) {
- this->data = std::move(data);
- return false;
-}
-
-bool ExporterImage::save() {
- QStringList filters;
- filters << QCoreApplication::tr("Portable Document Format (*.pdf)")
- << QCoreApplication::tr("Image (*.png *.xpm *.jpg)");
-
- QFileDialog fileDialog(nullptr, QCoreApplication::tr("Export file..."), QString(), filters.join(";;"));
- fileDialog.setFileMode(QFileDialog::AnyFile);
- fileDialog.setAcceptMode(QFileDialog::AcceptSave);
- if (fileDialog.exec() != QDialog::Accepted) return false;
-
- bool isPdf = filters.indexOf(fileDialog.selectedNameFilter()) == 0;
- std::unique_ptr paintDevice;
-
- const DsoSettingsColorValues *colorValues = &(registry->settings->view.print);
-
- if (!isPdf) {
- // We need a QPixmap for image-export
- QPixmap *qPixmap = new QPixmap(registry->settings->exporting.imageSize);
- qPixmap->fill(colorValues->background);
- paintDevice = std::unique_ptr(qPixmap);
- } else {
- // We need a QPrinter for printing, pdf- and ps-export
- std::unique_ptr printer = std::unique_ptr(new QPrinter(QPrinter::HighResolution));
- printer->setOrientation(registry->settings->view.zoom ? QPrinter::Portrait : QPrinter::Landscape);
- printer->setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);
- printer->setOutputFileName(fileDialog.selectedFiles().first());
- printer->setOutputFormat(QPrinter::PdfFormat);
- paintDevice = std::move(printer);
- }
-
- if (!paintDevice) return false;
-
- LegacyExportDrawer::exportSamples(data.get(), paintDevice.get(), registry->deviceSpecification, registry->settings,
- false, colorValues);
-
- if (!isPdf) static_cast(paintDevice.get())->save(fileDialog.selectedFiles().first());
- return true;
-}
-
-float ExporterImage::progress() { return data ? 1.0f : 0; }
diff --git a/openhantek/src/exporting/exportimage.h b/openhantek/src/exporting/exportimage.h
deleted file mode 100644
index b8dd2f26..00000000
--- a/openhantek/src/exporting/exportimage.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#pragma once
-#include "exporterinterface.h"
-
-class ExporterImage : public ExporterInterface
-{
-public:
- ExporterImage();
- virtual void create(ExporterRegistry *registry) override;
- virtual QIcon icon() override;
- virtual QString name() override;
- virtual Type type() override;
- virtual bool samples(const std::shared_ptrdata) override;
- virtual bool save() override;
- virtual float progress() override;
-private:
- std::shared_ptr data;
-};
diff --git a/openhantek/src/exporting/exportprint.cpp b/openhantek/src/exporting/exportprint.cpp
deleted file mode 100644
index 4b4b81b7..00000000
--- a/openhantek/src/exporting/exportprint.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include "exportprint.h"
-#include "exporterregistry.h"
-#include "iconfont/QtAwesome.h"
-#include "legacyexportdrawer.h"
-#include "post/ppresult.h"
-#include "settings.h"
-#include "viewsettings.h"
-
-#include
-#include
-#include
-
-ExporterPrint::ExporterPrint() {}
-
-void ExporterPrint::create(ExporterRegistry *registry) { this->registry = registry; data.reset(); }
-
-QIcon ExporterPrint::icon() { return iconFont->icon(fa::print); }
-
-QString ExporterPrint::name() { return QCoreApplication::tr("Print"); }
-
-ExporterInterface::Type ExporterPrint::type() { return Type::SnapshotExport; }
-
-bool ExporterPrint::samples(const std::shared_ptr data) {
- this->data = std::move(data);
- return false;
-}
-
-bool ExporterPrint::save() {
- // We need a QPrinter for printing, pdf- and ps-export
- std::unique_ptr printer = std::unique_ptr(new QPrinter(QPrinter::HighResolution));
- printer->setOrientation(registry->settings->view.zoom ? QPrinter::Portrait : QPrinter::Landscape);
- printer->setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);
-
- // Show the printing dialog
- QPrintDialog dialog(printer.get());
- dialog.setWindowTitle(QCoreApplication::tr("Print oscillograph"));
- if (dialog.exec() != QDialog::Accepted) { return false; }
-
- const DsoSettingsColorValues *colorValues = &(registry->settings->view.print);
-
- LegacyExportDrawer::exportSamples(data.get(), printer.get(), registry->deviceSpecification, registry->settings,
- true, colorValues);
-
- return true;
-}
-
-float ExporterPrint::progress() { return data ? 1.0f : 0; }
diff --git a/openhantek/src/exporting/exportprint.h b/openhantek/src/exporting/exportprint.h
deleted file mode 100644
index 51fcd135..00000000
--- a/openhantek/src/exporting/exportprint.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#pragma once
-#include "exporterinterface.h"
-
-class ExporterPrint : public ExporterInterface
-{
-public:
- ExporterPrint();
- virtual void create(ExporterRegistry *registry) override;
- virtual QIcon icon() override;
- virtual QString name() override;
- virtual Type type() override;
- virtual bool samples(const std::shared_ptrdata) override;
- virtual bool save() override;
- virtual float progress() override;
-private:
- std::shared_ptr data;
-};
diff --git a/openhantek/src/exporting/exportsettings.h b/openhantek/src/exporting/exportsettings.h
deleted file mode 100644
index 996873ed..00000000
--- a/openhantek/src/exporting/exportsettings.h
+++ /dev/null
@@ -1,12 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#pragma once
-
-#include
-
-/// \brief Holds the export options of the program.
-struct DsoSettingsExport {
- QSize imageSize = QSize(640, 480); ///< Size of exported images in pixels
- unsigned exportSizeBytes = 1024*1024*10; ///< For exporters that save a continous stream. Default: 10 Megabytes
- bool useProcessedSamples = true; ///< Export raw or processed samples
-};
diff --git a/openhantek/src/exporting/legacyexportdrawer.cpp b/openhantek/src/exporting/legacyexportdrawer.cpp
deleted file mode 100644
index 20cb7ba4..00000000
--- a/openhantek/src/exporting/legacyexportdrawer.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include "legacyexportdrawer.h"
-
-#include "controlspecification.h"
-#include "post/graphgenerator.h"
-#include "post/ppresult.h"
-#include "settings.h"
-#include "utils/printutils.h"
-#include "viewconstants.h"
-
-#define tr(msg) QCoreApplication::translate("Exporter", msg)
-
-bool LegacyExportDrawer::exportSamples(const PPresult *result, QPaintDevice* paintDevice,
- const Dso::ControlSpecification *deviceSpecification,
- const DsoSettings *settings, bool isPrinter, const DsoSettingsColorValues *colorValues) {
- // Create a painter for our device
- QPainter painter(paintDevice);
-
- // Get line height
- QFont font;
- QFontMetrics fontMetrics(font, paintDevice);
- double lineHeight = fontMetrics.height();
-
- painter.setBrush(Qt::SolidPattern);
-
- // Draw the settings table
- double stretchBase = (double)(paintDevice->width() - lineHeight * 10) / 4;
-
- // Print trigger details
- painter.setPen(colorValues->voltage[settings->scope.trigger.source]);
- QString levelString = valueToString(settings->scope.voltage[settings->scope.trigger.source].trigger, UNIT_VOLTS, 3);
- QString pretriggerString = tr("%L1%").arg((int)(settings->scope.trigger.position * 100 + 0.5));
- painter.drawText(QRectF(0, 0, lineHeight * 10, lineHeight),
- tr("%1 %2 %3 %4")
- .arg(settings->scope.voltage[settings->scope.trigger.source].name,
- Dso::slopeString(settings->scope.trigger.slope), levelString, pretriggerString));
-
- double scopeHeight;
-
- { // DataAnalyser mutex lock
- // Print sample count
- painter.setPen(colorValues->text);
- painter.drawText(QRectF(lineHeight * 10, 0, stretchBase, lineHeight), tr("%1 S").arg(result->sampleCount()),
- QTextOption(Qt::AlignRight));
- // Print samplerate
- painter.drawText(QRectF(lineHeight * 10 + stretchBase, 0, stretchBase, lineHeight),
- valueToString(settings->scope.horizontal.samplerate, UNIT_SAMPLES) + tr("/s"),
- QTextOption(Qt::AlignRight));
- // Print timebase
- painter.drawText(QRectF(lineHeight * 10 + stretchBase * 2, 0, stretchBase, lineHeight),
- valueToString(settings->scope.horizontal.timebase, UNIT_SECONDS, 0) + tr("/div"),
- QTextOption(Qt::AlignRight));
- // Print frequencybase
- painter.drawText(QRectF(lineHeight * 10 + stretchBase * 3, 0, stretchBase, lineHeight),
- valueToString(settings->scope.horizontal.frequencybase, UNIT_HERTZ, 0) + tr("/div"),
- QTextOption(Qt::AlignRight));
-
- // Draw the measurement table
- stretchBase = (double)(paintDevice->width() - lineHeight * 6) / 10;
- int channelCount = 0;
- for (int channel = settings->scope.voltage.size() - 1; channel >= 0; channel--) {
- if ((settings->scope.voltage[channel].used || settings->scope.spectrum[channel].used) &&
- result->data(channel)) {
- ++channelCount;
- double top = (double)paintDevice->height() - channelCount * lineHeight;
-
- // Print label
- painter.setPen(colorValues->voltage[channel]);
- painter.drawText(QRectF(0, top, lineHeight * 4, lineHeight), settings->scope.voltage[channel].name);
- // Print coupling/math mode
- if ((unsigned int)channel < deviceSpecification->channels)
- painter.drawText(QRectF(lineHeight * 4, top, lineHeight * 2, lineHeight),
- Dso::couplingString(settings->scope.coupling(channel, deviceSpecification)));
- else
- painter.drawText(
- QRectF(lineHeight * 4, top, lineHeight * 2, lineHeight),
- Dso::mathModeString(Dso::getMathMode(settings->scope.voltage[channel])));
-
- // Print voltage gain
- painter.drawText(QRectF(lineHeight * 6, top, stretchBase * 2, lineHeight),
- valueToString(settings->scope.gain(channel), UNIT_VOLTS, 0) + tr("/div"),
- QTextOption(Qt::AlignRight));
- // Print spectrum magnitude
- if (settings->scope.spectrum[channel].used) {
- painter.setPen(colorValues->spectrum[channel]);
- painter.drawText(QRectF(lineHeight * 6 + stretchBase * 2, top, stretchBase * 2, lineHeight),
- valueToString(settings->scope.spectrum[channel].magnitude, UNIT_DECIBEL, 0) +
- tr("/div"),
- QTextOption(Qt::AlignRight));
- }
-
- // Amplitude string representation (4 significant digits)
- painter.setPen(colorValues->text);
- painter.drawText(QRectF(lineHeight * 6 + stretchBase * 4, top, stretchBase * 3, lineHeight),
- valueToString(result->data(channel)->computeAmplitude(), UNIT_VOLTS, 4),
- QTextOption(Qt::AlignRight));
- // Frequency string representation (5 significant digits)
- painter.drawText(QRectF(lineHeight * 6 + stretchBase * 7, top, stretchBase * 3, lineHeight),
- valueToString(result->data(channel)->frequency, UNIT_HERTZ, 5),
- QTextOption(Qt::AlignRight));
- }
- }
-
- // Draw the marker table
- stretchBase = (double)(paintDevice->width() - lineHeight * 10) / 4;
- painter.setPen(colorValues->text);
-
- // Calculate variables needed for zoomed scope
- double m1 = settings->scope.getMarker(0);
- double m2 = settings->scope.getMarker(1);
- double divs = fabs(m2 - m1);
- double time = divs * settings->scope.horizontal.timebase;
- double zoomFactor = DIVS_TIME / divs;
- double zoomOffset = (m1 + m2) / 2;
-
- if (settings->view.zoom) {
- scopeHeight = (double)(paintDevice->height() - (channelCount + 5) * lineHeight) / 2;
- double top = 2.5 * lineHeight + scopeHeight;
-
- painter.drawText(QRectF(0, top, stretchBase, lineHeight),
- tr("Zoom x%L1").arg(DIVS_TIME / divs, -1, 'g', 3));
-
- painter.drawText(QRectF(lineHeight * 10, top, stretchBase, lineHeight),
- valueToString(time, UNIT_SECONDS, 4), QTextOption(Qt::AlignRight));
- painter.drawText(QRectF(lineHeight * 10 + stretchBase, top, stretchBase, lineHeight),
- valueToString(1.0 / time, UNIT_HERTZ, 4), QTextOption(Qt::AlignRight));
-
- painter.drawText(QRectF(lineHeight * 10 + stretchBase * 2, top, stretchBase, lineHeight),
- valueToString(time / DIVS_TIME, UNIT_SECONDS, 3) + tr("/div"),
- QTextOption(Qt::AlignRight));
- painter.drawText(QRectF(lineHeight * 10 + stretchBase * 3, top, stretchBase, lineHeight),
- valueToString(divs * settings->scope.horizontal.frequencybase / DIVS_TIME, UNIT_HERTZ, 3) +
- tr("/div"),
- QTextOption(Qt::AlignRight));
- } else {
- scopeHeight = (double)paintDevice->height() - (channelCount + 4) * lineHeight;
- double top = 2.5 * lineHeight + scopeHeight;
-
- painter.drawText(QRectF(0, top, stretchBase, lineHeight), tr("Marker 1/2"));
-
- painter.drawText(QRectF(lineHeight * 10, top, stretchBase * 2, lineHeight),
- valueToString(time, UNIT_SECONDS, 4), QTextOption(Qt::AlignRight));
- painter.drawText(QRectF(lineHeight * 10 + stretchBase * 2, top, stretchBase * 2, lineHeight),
- valueToString(1.0 / time, UNIT_HERTZ, 4), QTextOption(Qt::AlignRight));
- }
-
- // Set DIVS_TIME x DIVS_VOLTAGE matrix for oscillograph
- painter.setMatrix(QMatrix((paintDevice->width() - 1) / DIVS_TIME, 0, 0, -(scopeHeight - 1) / DIVS_VOLTAGE,
- (double)(paintDevice->width() - 1) / 2, (scopeHeight - 1) / 2 + lineHeight * 1.5),
- false);
-
- // Draw the graphs
- painter.setRenderHint(QPainter::Antialiasing);
- painter.setBrush(Qt::NoBrush);
-
- for (int zoomed = 0; zoomed < (settings->view.zoom ? 2 : 1); ++zoomed) {
- switch (settings->scope.horizontal.format) {
- case Dso::GraphFormat::TY:
- // Add graphs for channels
- for (ChannelID channel = 0; channel < settings->scope.voltage.size(); ++channel) {
- if (settings->scope.voltage[channel].used && result->data(channel)) {
- painter.setPen(QPen(colorValues->voltage[channel], 0));
-
- // What's the horizontal distance between sampling points?
- double horizontalFactor =
- result->data(channel)->voltage.interval / settings->scope.horizontal.timebase;
- // How many samples are visible?
- double centerPosition, centerOffset;
- if (zoomed) {
- centerPosition = (zoomOffset + DIVS_TIME / 2) / horizontalFactor;
- centerOffset = DIVS_TIME / horizontalFactor / zoomFactor / 2;
- } else {
- centerPosition = DIVS_TIME / 2 / horizontalFactor;
- centerOffset = DIVS_TIME / horizontalFactor / 2;
- }
- unsigned int firstPosition = qMax((int)(centerPosition - centerOffset), 0);
- unsigned int lastPosition = qMin((int)(centerPosition + centerOffset),
- (int)result->data(channel)->voltage.sample.size() - 1);
-
- // Draw graph
- QPointF *graph = new QPointF[lastPosition - firstPosition + 1];
-
- for (unsigned int position = firstPosition; position <= lastPosition; ++position)
- graph[position - firstPosition] = QPointF(position * horizontalFactor - DIVS_TIME / 2,
- result->data(channel)->voltage.sample[position] /
- settings->scope.gain(channel) +
- settings->scope.voltage[channel].offset);
-
- painter.drawPolyline(graph, lastPosition - firstPosition + 1);
- delete[] graph;
- }
- }
-
- // Add spectrum graphs
- for (ChannelID channel = 0; channel < settings->scope.spectrum.size(); ++channel) {
- if (settings->scope.spectrum[channel].used && result->data(channel)) {
- painter.setPen(QPen(colorValues->spectrum[channel], 0));
-
- // What's the horizontal distance between sampling points?
- double horizontalFactor =
- result->data(channel)->spectrum.interval / settings->scope.horizontal.frequencybase;
- // How many samples are visible?
- double centerPosition, centerOffset;
- if (zoomed) {
- centerPosition = (zoomOffset + DIVS_TIME / 2) / horizontalFactor;
- centerOffset = DIVS_TIME / horizontalFactor / zoomFactor / 2;
- } else {
- centerPosition = DIVS_TIME / 2 / horizontalFactor;
- centerOffset = DIVS_TIME / horizontalFactor / 2;
- }
- unsigned int firstPosition = qMax((int)(centerPosition - centerOffset), 0);
- unsigned int lastPosition = qMin((int)(centerPosition + centerOffset),
- (int)result->data(channel)->spectrum.sample.size() - 1);
-
- // Draw graph
- QPointF *graph = new QPointF[lastPosition - firstPosition + 1];
-
- for (unsigned int position = firstPosition; position <= lastPosition; ++position)
- graph[position - firstPosition] =
- QPointF(position * horizontalFactor - DIVS_TIME / 2,
- result->data(channel)->spectrum.sample[position] /
- settings->scope.spectrum[channel].magnitude +
- settings->scope.spectrum[channel].offset);
-
- painter.drawPolyline(graph, lastPosition - firstPosition + 1);
- delete[] graph;
- }
- }
- break;
-
- case Dso::GraphFormat::XY:
- break;
-
- default:
- break;
- }
-
- // Set DIVS_TIME / zoomFactor x DIVS_VOLTAGE matrix for zoomed
- // oscillograph
- painter.setMatrix(QMatrix((paintDevice->width() - 1) / DIVS_TIME * zoomFactor, 0, 0,
- -(scopeHeight - 1) / DIVS_VOLTAGE,
- (double)(paintDevice->width() - 1) / 2 -
- zoomOffset * zoomFactor * (paintDevice->width() - 1) / DIVS_TIME,
- (scopeHeight - 1) * 1.5 + lineHeight * 4),
- false);
- }
- } // dataanalyser mutex release
-
- drawGrids(painter, colorValues, lineHeight, scopeHeight, paintDevice->width(),
- isPrinter, settings->view.zoom);
- painter.end();
-
- return true;
-}
-
-void LegacyExportDrawer::drawGrids(QPainter &painter, const DsoSettingsColorValues *colorValues, double lineHeight, double scopeHeight,
- int scopeWidth, bool isPrinter, bool zoom) {
- painter.setRenderHint(QPainter::Antialiasing, false);
- for (int zoomed = 0; zoomed < (zoom ? 2 : 1); ++zoomed) {
- // Set DIVS_TIME x DIVS_VOLTAGE matrix for oscillograph
- painter.setMatrix(QMatrix((scopeWidth - 1) / DIVS_TIME, 0, 0, -(scopeHeight - 1) / DIVS_VOLTAGE,
- (double)(scopeWidth - 1) / 2,
- (scopeHeight - 1) * (zoomed + 0.5) + lineHeight * 1.5 + lineHeight * 2.5 * zoomed),
- false);
-
- // Grid lines
- painter.setPen(QPen(colorValues->grid, 0));
-
- if (isPrinter) {
- // Draw vertical lines
- for (int div = 1; div < DIVS_TIME / 2; ++div) {
- for (int dot = 1; dot < DIVS_VOLTAGE / 2 * 5; ++dot) {
- painter.drawLine(QPointF((double)-div - 0.02, (double)-dot / 5),
- QPointF((double)-div + 0.02, (double)-dot / 5));
- painter.drawLine(QPointF((double)-div - 0.02, (double)dot / 5),
- QPointF((double)-div + 0.02, (double)dot / 5));
- painter.drawLine(QPointF((double)div - 0.02, (double)-dot / 5),
- QPointF((double)div + 0.02, (double)-dot / 5));
- painter.drawLine(QPointF((double)div - 0.02, (double)dot / 5),
- QPointF((double)div + 0.02, (double)dot / 5));
- }
- }
- // Draw horizontal lines
- for (int div = 1; div < DIVS_VOLTAGE / 2; ++div) {
- for (int dot = 1; dot < DIVS_TIME / 2 * 5; ++dot) {
- painter.drawLine(QPointF((double)-dot / 5, (double)-div - 0.02),
- QPointF((double)-dot / 5, (double)-div + 0.02));
- painter.drawLine(QPointF((double)dot / 5, (double)-div - 0.02),
- QPointF((double)dot / 5, (double)-div + 0.02));
- painter.drawLine(QPointF((double)-dot / 5, (double)div - 0.02),
- QPointF((double)-dot / 5, (double)div + 0.02));
- painter.drawLine(QPointF((double)dot / 5, (double)div - 0.02),
- QPointF((double)dot / 5, (double)div + 0.02));
- }
- }
- } else {
- // Draw vertical lines
- for (int div = 1; div < DIVS_TIME / 2; ++div) {
- for (int dot = 1; dot < DIVS_VOLTAGE / 2 * 5; ++dot) {
- painter.drawPoint(QPointF(-div, (double)-dot / 5));
- painter.drawPoint(QPointF(-div, (double)dot / 5));
- painter.drawPoint(QPointF(div, (double)-dot / 5));
- painter.drawPoint(QPointF(div, (double)dot / 5));
- }
- }
- // Draw horizontal lines
- for (int div = 1; div < DIVS_VOLTAGE / 2; ++div) {
- for (int dot = 1; dot < DIVS_TIME / 2 * 5; ++dot) {
- if (dot % 5 == 0) continue; // Already done by vertical lines
- painter.drawPoint(QPointF((double)-dot / 5, -div));
- painter.drawPoint(QPointF((double)dot / 5, -div));
- painter.drawPoint(QPointF((double)-dot / 5, div));
- painter.drawPoint(QPointF((double)dot / 5, div));
- }
- }
- }
-
- // Axes
- painter.setPen(QPen(colorValues->axes, 0));
- painter.drawLine(QPointF(-DIVS_TIME / 2, 0), QPointF(DIVS_TIME / 2, 0));
- painter.drawLine(QPointF(0, -DIVS_VOLTAGE / 2), QPointF(0, DIVS_VOLTAGE / 2));
- for (double div = 0.2; div <= DIVS_TIME / 2; div += 0.2) {
- painter.drawLine(QPointF(div, -0.05), QPointF(div, 0.05));
- painter.drawLine(QPointF(-div, -0.05), QPointF(-div, 0.05));
- }
- for (double div = 0.2; div <= DIVS_VOLTAGE / 2; div += 0.2) {
- painter.drawLine(QPointF(-0.05, div), QPointF(0.05, div));
- painter.drawLine(QPointF(-0.05, -div), QPointF(0.05, -div));
- }
-
- // Borders
- painter.setPen(QPen(colorValues->border, 0));
- painter.drawRect(QRectF(-DIVS_TIME / 2, -DIVS_VOLTAGE / 2, DIVS_TIME, DIVS_VOLTAGE));
- }
-}
diff --git a/openhantek/src/exporting/legacyexportdrawer.h b/openhantek/src/exporting/legacyexportdrawer.h
deleted file mode 100644
index e9d3d3ce..00000000
--- a/openhantek/src/exporting/legacyexportdrawer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include "exportsettings.h"
-
-class DsoSettings;
-class PPresult;
-struct DsoSettingsColorValues;
-namespace Dso { struct ControlSpecification; }
-
-/// \brief Exports the oscilloscope screen to a file or prints it.
-/// TODO
-/// Rewrite image exporter with OpenGL drawn grid and graphs
-///
-/// Sources:
-/// http://doc.qt.io/qt-5/qoffscreensurface.html
-/// http://doc.qt.io/qt-5/qopenglframebufferobject.html
-///
-/// https://dangelog.wordpress.com/2013/02/10/using-fbos-instead-of-pbuffers-in-qt-5-2/
-class LegacyExportDrawer {
- public:
- /// Draw the graphs coming from source and labels to the destination paintdevice.
- static bool exportSamples(const PPresult *source, QPaintDevice* dest,
- const Dso::ControlSpecification* deviceSpecification,
- const DsoSettings *settings, bool isPrinter, const DsoSettingsColorValues *colorValues);
-
- private:
- static void drawGrids(QPainter &painter, const DsoSettingsColorValues *colorValues, double lineHeight, double scopeHeight,
- int scopeWidth, bool isPrinter, bool zoom);
-};
diff --git a/openhantek/src/exporting/readme.md b/openhantek/src/exporting/readme.md
index 5c81a388..18f98726 100644
--- a/openhantek/src/exporting/readme.md
+++ b/openhantek/src/exporting/readme.md
@@ -1,7 +1,8 @@
# Content
This directory contains exporting functionality and exporters, namely
-* Export to comma separated value file (CSV): Write to a user selected file,
+* Export to comma separated value file (CSV): Write to a user selected file,
+use localisation for data and decimal separator
* Export to an image/pdf: Writes an image/pdf to a user selected file,
* Print exporter: Creates a printable document and opens the print dialog.
diff --git a/openhantek/src/glscope.cpp b/openhantek/src/glscope.cpp
index f6b0e71f..4f15090e 100644
--- a/openhantek/src/glscope.cpp
+++ b/openhantek/src/glscope.cpp
@@ -12,6 +12,7 @@
#include
#include
+#include
#include
#include "glscope.h"
@@ -22,168 +23,270 @@
#include "viewconstants.h"
#include "viewsettings.h"
-GlScope *GlScope::createNormal(DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent) {
- GlScope *s = new GlScope(scope, view, parent);
+
+GlScope *GlScope::createNormal( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent ) {
+ GlScope *s = new GlScope( scope, view, parent );
s->zoomed = false;
return s;
}
-GlScope *GlScope::createZoomed(DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent) {
- GlScope *s = new GlScope(scope, view, parent);
+
+GlScope *GlScope::createZoomed( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent ) {
+ GlScope *s = new GlScope( scope, view, parent );
s->zoomed = true;
return s;
}
-void GlScope::fixOpenGLversion(QSurfaceFormat::RenderableType t) {
- QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
+
+void GlScope::useQSurfaceFormat( QSurfaceFormat::RenderableType t ) {
+ QCoreApplication::setAttribute( Qt::AA_ShareOpenGLContexts, true );
// Prefer full desktop OpenGL without fixed pipeline
QSurfaceFormat format;
- format.setSamples(4); // Antia-Aliasing, Multisampling
- format.setProfile(QSurfaceFormat::CoreProfile);
- if (t==QSurfaceFormat::OpenGLES) {
- format.setVersion(2, 0);
- format.setRenderableType(QSurfaceFormat::OpenGLES);
- QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
+ // TODO: check from time to time if warning has gone, comment next line for now
+ format.setSamples( 4 ); // antialiasing gives warning with some HW, Qt & OpenGL versions.
+ format.setProfile( QSurfaceFormat::CoreProfile );
+ if ( t == QSurfaceFormat::OpenGLES ) {
+ format.setVersion( 2, 0 );
+ format.setRenderableType( QSurfaceFormat::OpenGLES );
+ QCoreApplication::setAttribute( Qt::AA_UseOpenGLES, true );
} else {
- format.setVersion(3, 2);
- format.setRenderableType(QSurfaceFormat::OpenGL);
+ format.setVersion( 3, 2 );
+ format.setRenderableType( QSurfaceFormat::OpenGL );
}
- QSurfaceFormat::setDefaultFormat(format);
+ QSurfaceFormat::setDefaultFormat( format );
}
-GlScope::GlScope(DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent)
- : QOpenGLWidget(parent), scope(scope), view(view) {
+
+GlScope::GlScope( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent )
+ : QOpenGLWidget( parent ), scope( scope ), view( view ) {
+ // get OpenGL version to define appropriate OpenGLSL version
+ // reason:
+ // some not so new intel graphic driver report a very conservative version
+ // e.g. debian buster -> "2.1 Mesa 18.3.4"
+ QOffscreenSurface surface;
+ surface.create();
+ QOpenGLContext context;
+ context.create();
+ context.makeCurrent( &surface );
+ QString glVersion = reinterpret_cast< const char * >( context.functions()->glGetString( GL_VERSION ) );
+ GLSLversion = glVersion >= "3.2" ? 150 : 120; // version string "3.2 xxxx" > "3.2" is true
+ // qDebug() << "OpenGL version" << glVersion << GLSLversion;
+ surface.destroy();
+
cursorInfo.clear();
- cursorInfo.push_back(&scope->horizontal.cursor);
+ cursorInfo.push_back( &scope->horizontal.cursor );
selectedCursor = 0;
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
- cursorInfo.push_back(&scope->voltage[channel].cursor);
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ cursorInfo.push_back( &scope->voltage[ channel ].cursor );
}
- for (ChannelID channel = 0; channel < scope->spectrum.size(); ++channel) {
- cursorInfo.push_back(&scope->spectrum[channel].cursor);
+ for ( ChannelID channel = 0; channel < scope->spectrum.size(); ++channel ) {
+ cursorInfo.push_back( &scope->spectrum[ channel ].cursor );
}
- vaMarker.resize(cursorInfo.size());
+ vaMarker.resize( cursorInfo.size() );
+}
+
+
+GlScope::~GlScope() { /* virtual destructor necessary */
}
-GlScope::~GlScope() {/* virtual destructor necessary */}
-QPointF GlScope::eventToPosition(QMouseEvent *event) {
- QPointF position((double)(event->x() - width() / 2) * DIVS_TIME / (double)width(),
- (double)(height() / 2 - event->y()) * DIVS_VOLTAGE / (double)height());
- if (zoomed) {
- double m1 = scope->getMarker(0);
- double m2 = scope->getMarker(1);
- if (m1 > m2) std::swap(m1, m2);
- position.setX(m1 + (0.5 + (position.x() / DIVS_TIME)) * (m2 - m1));
+QPointF GlScope::posToPosition( QPointF pos ) {
+ QPointF position( double( pos.x() - width() / 2 ) * DIVS_TIME / double( width() ),
+ double( height() / 2 - pos.y() ) * DIVS_VOLTAGE / double( height() ) );
+ if ( zoomed ) {
+ double m1 = scope->getMarker( 0 );
+ double m2 = scope->getMarker( 1 );
+ if ( m1 > m2 )
+ std::swap( m1, m2 );
+ position.setX( m1 + ( 0.5 + ( position.x() / DIVS_TIME ) ) * ( m2 - m1 ) );
}
return position;
}
-void GlScope::mousePressEvent(QMouseEvent *event) {
- if (!(zoomed && selectedCursor == 0) && event->button() == Qt::LeftButton) {
- QPointF position = eventToPosition(event);
+
+void GlScope::mousePressEvent( QMouseEvent *event ) {
+ if ( !( zoomed && selectedCursor == 0 ) && event->button() == Qt::LeftButton ) {
+ QPointF position = posToPosition( event->pos() );
selectedMarker = NO_MARKER;
- DsoSettingsScopeCursor *cursor = cursorInfo[selectedCursor];
+ DsoSettingsScopeCursor *cursor = cursorInfo[ selectedCursor ];
// Capture nearest marker located within snap area (+/- 1% of full scale).
- double dX0 = fabs(cursor->pos[0].x() - position.x());
- double dX1 = fabs(cursor->pos[1].x() - position.x());
- double dY0 = fabs(cursor->pos[0].y() - position.y());
- double dY1 = fabs(cursor->pos[1].y() - position.y());
+ double dX0 = fabs( cursor->pos[ 0 ].x() - position.x() );
+ double dX1 = fabs( cursor->pos[ 1 ].x() - position.x() );
+ double dY0 = fabs( cursor->pos[ 0 ].y() - position.y() );
+ double dY1 = fabs( cursor->pos[ 1 ].y() - position.y() );
- switch (cursor->shape) {
+ switch ( cursor->shape ) {
case DsoSettingsScopeCursor::RECTANGULAR:
- if (std::min(dX0, dX1) < 1.0 / DIVS_SUB && std::min(dY0, dY1) < 1.0 / DIVS_SUB) {
+ if ( std::min( dX0, dX1 ) < 1.0 / DIVS_SUB && std::min( dY0, dY1 ) < 1.0 / DIVS_SUB ) {
// Do we need to swap Y-coords?
- if ((dX0 < dX1 && dY0 > dY1) || (dX0 > dX1 && dY0 < dY1)) {
- std::swap(cursor->pos[0].ry(), cursor->pos[1].ry());
+ if ( ( dX0 < dX1 && dY0 > dY1 ) || ( dX0 > dX1 && dY0 < dY1 ) ) {
+ std::swap( cursor->pos[ 0 ].ry(), cursor->pos[ 1 ].ry() );
}
- selectedMarker = (dX0 < dX1) ? 0 : 1;
+ selectedMarker = ( dX0 < dX1 ) ? 0 : 1;
}
break;
case DsoSettingsScopeCursor::VERTICAL:
- if (dX0 < dX1) {
- if (dX0 < 1.0 / DIVS_SUB) selectedMarker = 0;
+ if ( dX0 < dX1 ) {
+ if ( dX0 < 1.0 / DIVS_SUB )
+ selectedMarker = 0;
} else {
- if (dX1 < 1.0 / DIVS_SUB) selectedMarker = 1;
+ if ( dX1 < 1.0 / DIVS_SUB )
+ selectedMarker = 1;
}
break;
case DsoSettingsScopeCursor::HORIZONTAL:
- if (dY0 < dY1) {
- if (dY0 < 1.0 / DIVS_SUB) selectedMarker = 0;
+ if ( dY0 < dY1 ) {
+ if ( dY0 < 1.0 / DIVS_SUB )
+ selectedMarker = 0;
} else {
- if (dY1 < 1.0 / DIVS_SUB) selectedMarker = 1;
+ if ( dY1 < 1.0 / DIVS_SUB )
+ selectedMarker = 1;
}
break;
case DsoSettingsScopeCursor::NONE:
break;
- default:
- break;
}
- if (selectedMarker != NO_MARKER) {
- cursorInfo[selectedCursor]->pos[selectedMarker] = position;
- if (selectedCursor == 0) emit markerMoved(selectedCursor, selectedMarker);
+ if ( selectedMarker != NO_MARKER ) {
+ cursorInfo[ selectedCursor ]->pos[ selectedMarker ] = position;
+ if ( selectedCursor == 0 )
+ emit markerMoved( selectedCursor, selectedMarker );
}
}
event->accept();
}
-void GlScope::mouseMoveEvent(QMouseEvent *event) {
- if (!(zoomed && selectedCursor == 0) && (event->buttons() & Qt::LeftButton) != 0) {
- QPointF position = eventToPosition(event);
- if (selectedMarker == NO_MARKER) {
+
+void GlScope::mouseMoveEvent( QMouseEvent *event ) {
+ if ( !( zoomed && selectedCursor == 0 ) && ( event->buttons() & Qt::LeftButton ) != 0 ) {
+ QPointF position = posToPosition( event->pos() );
+ if ( selectedMarker == NO_MARKER ) {
+ // qDebug() << "mouseMoveEvent";
// User started draging outside the snap area of any marker:
// move all markers to current position and select last marker in the array.
- for (unsigned marker = 0; marker < MARKER_COUNT; ++marker) {
- cursorInfo[selectedCursor]->pos[marker] = position;
- emit markerMoved(selectedCursor, marker);
+ for ( unsigned marker = 0; marker < 2; ++marker ) {
+ cursorInfo[ selectedCursor ]->pos[ marker ] = position;
+ emit markerMoved( selectedCursor, marker );
selectedMarker = marker;
}
- } else if (selectedMarker < MARKER_COUNT) {
- cursorInfo[selectedCursor]->pos[selectedMarker] = position;
- emit markerMoved(selectedCursor, selectedMarker);
+ } else if ( selectedMarker < 2 ) {
+ cursorInfo[ selectedCursor ]->pos[ selectedMarker ] = position;
+ emit markerMoved( selectedCursor, selectedMarker );
}
}
event->accept();
}
-void GlScope::mouseReleaseEvent(QMouseEvent *event) {
- if (!(zoomed && selectedCursor == 0) && event->button() == Qt::LeftButton) {
- QPointF position = eventToPosition(event);
- if (selectedMarker < MARKER_COUNT) {
- cursorInfo[selectedCursor]->pos[selectedMarker] = position;
- emit markerMoved(selectedCursor, selectedMarker);
+
+void GlScope::mouseReleaseEvent( QMouseEvent *event ) {
+ if ( !( zoomed && selectedCursor == 0 ) && event->button() == Qt::LeftButton ) {
+ QPointF position = posToPosition( event->pos() );
+ if ( selectedMarker < 2 ) {
+ // qDebug() << "mouseReleaseEvent";
+ cursorInfo[ selectedCursor ]->pos[ selectedMarker ] = position;
+ emit markerMoved( selectedCursor, selectedMarker );
+ }
+ selectedMarker = NO_MARKER;
+ }
+ event->accept();
+}
+
+
+void GlScope::mouseDoubleClickEvent( QMouseEvent *event ) {
+ if ( !( zoomed && selectedCursor == 0 ) && ( event->buttons() & Qt::LeftButton ) != 0 ) {
+ // left double click positions two markers left and right of clicked pos with zoom=100
+ QPointF position = posToPosition( event->pos() );
+ if ( selectedMarker == NO_MARKER ) {
+ // User double clicked outside the snap area of any marker
+ QPointF p = QPointF( 0.5, 0 ); // 10x zoom
+ if ( event->modifiers() & Qt::CTRL ) // 100x zoom
+ p /= 10;
+ if ( event->modifiers() & Qt::SHIFT ) // center at trigger position
+ position = QPointF( 10 * scope->trigger.offset - 5, 0 );
+ // move 1st marker left of current position.
+ cursorInfo[ selectedCursor ]->pos[ 0 ] = position - p;
+ emit markerMoved( selectedCursor, 0 );
+ // move 2nd marker right of current position to make zoom=10 or 100.
+ cursorInfo[ selectedCursor ]->pos[ 1 ] = position + p;
+ emit markerMoved( selectedCursor, 1 );
+ // select no marker
+ selectedMarker = NO_MARKER;
+ }
+ } else if ( !( zoomed && selectedCursor == 0 ) && ( event->buttons() & Qt::RightButton ) != 0 ) {
+ // right double click moves all markers out of the way
+ cursorInfo[ selectedCursor ]->pos[ 0 ] = QPointF( MARGIN_LEFT, 0 );
+ cursorInfo[ selectedCursor ]->pos[ 1 ] = QPointF( MARGIN_RIGHT, 0 );
+ emit markerMoved( selectedCursor, 0 );
+ emit markerMoved( selectedCursor, 1 );
+ }
+ event->accept();
+}
+
+
+void GlScope::wheelEvent( QWheelEvent *event ) {
+ static std::vector< int > zoomList = {1, 2, 5, 10, 20, 50, 100, 200, 500};
+ if ( !( zoomed && selectedCursor == 0 ) ) {
+ if ( selectedMarker == NO_MARKER ) {
+ double step = event->angleDelta().y() / 1200.0; // one click = 0.1
+ // qDebug() << "wheeelEvent" << selectedCursor << event->globalPos() << step;
+ double &m1 = cursorInfo[ selectedCursor ]->pos[ 0 ].rx();
+ double &m2 = cursorInfo[ selectedCursor ]->pos[ 1 ].rx();
+ if ( m1 > m2 )
+ std::swap( m1, m2 );
+ double dm = m2 - m1;
+ if ( event->modifiers() & Qt::CTRL ) { // zoom in/out
+ if ( ( step > 0 && dm <= 1 ) || ( step < 0 && dm < 1 ) )
+ step *= 0.1;
+ if ( dm >= 3 * step ) {
+ m1 += step;
+ m2 -= step;
+ }
+ } else {
+ if ( step < 0 ) { // shift zoom range left ..
+ step = qMax( step, MARGIN_LEFT - m1 ); // .. until m1 == MARGIN_LEFT
+ } else { // shift zoom range right ..
+ step = qMin( step, MARGIN_RIGHT - m2 ); // .. until m2 == MARGIN_RIGHT
+ }
+ m1 += step;
+ m2 += step;
+ }
}
+ emit markerMoved( selectedCursor, 0 );
+ emit markerMoved( selectedCursor, 1 );
selectedMarker = NO_MARKER;
}
event->accept();
}
-void GlScope::paintEvent(QPaintEvent *event) {
- // Draw error message if OpenGL failed
- if (!shaderCompileSuccess) {
- QPainter painter(this);
- painter.setRenderHint(QPainter::Antialiasing, true);
+
+void GlScope::paintEvent( QPaintEvent *event ) {
+ if ( shaderCompileSuccess ) {
+ QOpenGLWidget::paintEvent( event );
+ } else if ( !zoomed ) { // draw error message on normal view if OpenGL failed
+ QPainter painter( this );
+ painter.setRenderHint( QPainter::Antialiasing, true );
QFont font = painter.font();
- font.setPointSize(18);
- painter.setFont(font);
- painter.drawText(rect(), Qt::AlignCenter, errorMessage);
- event->accept();
- } else
- QOpenGLWidget::paintEvent(event);
+ font.setPointSize( 18 );
+ painter.setFont( font );
+ painter.drawText( rect(), Qt::AlignCenter | Qt::TextWordWrap, errorMessage );
+ }
+ event->accept(); // consume the event
}
+
+unsigned GlScope::forceGLSLversion = 0;
+
void GlScope::initializeGL() {
- if (!QOpenGLShaderProgram::hasOpenGLShaderPrograms(context())) {
- errorMessage = tr("System does not support OpenGL Shading Language (GLSL)");
+ if ( !QOpenGLShaderProgram::hasOpenGLShaderPrograms( context() ) ) {
+ errorMessage = tr( "System does not support OpenGL Shading Language (GLSL)" );
return;
}
- if (m_program) {
- qWarning() << "OpenGL init called twice!";
+ if ( m_program ) {
+ qWarning() << tr( "OpenGL init called twice!" );
return;
}
- auto program = std::unique_ptr(new QOpenGLShaderProgram(context()));
+ auto program = std::unique_ptr< QOpenGLShaderProgram >( new QOpenGLShaderProgram( context() ) );
const char *vshaderES = R"(
#version 100
@@ -201,7 +304,23 @@ void GlScope::initializeGL() {
void main() { gl_FragColor = colour; }
)";
- const char *vshaderDesktop = R"(
+ const char *vshaderDesktop120 = R"(
+ #version 120
+ attribute highp vec3 vertex;
+ uniform mat4 matrix;
+ void main()
+ {
+ gl_Position = matrix * vec4(vertex, 1.0);
+ gl_PointSize = 1.0;
+ }
+ )";
+ const char *fshaderDesktop120 = R"(
+ #version 120
+ uniform highp vec4 colour;
+ void main() { gl_FragColor = colour; }
+ )";
+
+ const char *vshaderDesktop150 = R"(
#version 150
in highp vec3 vertex;
uniform mat4 matrix;
@@ -211,383 +330,500 @@ void GlScope::initializeGL() {
gl_PointSize = 1.0;
}
)";
- const char *fshaderDesktop = R"(
+ const char *fshaderDesktop150 = R"(
#version 150
uniform highp vec4 colour;
out vec4 flatColor;
void main() { flatColor = colour; }
)";
- qDebug() << "compile shaders";
+ if ( GlScope::forceGLSLversion )
+ GLSLversion = GlScope::forceGLSLversion;
+ // qDebug() << "compile shaders" << GlScope::forceGLSLversion << GLSLversion;
+
+ const char *vshaderDesktop = GLSLversion == 120 ? vshaderDesktop120 : vshaderDesktop150;
+ const char *fshaderDesktop = GLSLversion == 120 ? fshaderDesktop120 : fshaderDesktop150;
+
// Compile vertex shader
- bool usesOpenGL = QSurfaceFormat::defaultFormat().renderableType()==QSurfaceFormat::OpenGL;
- if (!program->addShaderFromSourceCode(QOpenGLShader::Vertex, usesOpenGL ? vshaderDesktop : vshaderES) ||
- !program->addShaderFromSourceCode(QOpenGLShader::Fragment, usesOpenGL ? fshaderDesktop : fshaderES)) {
- errorMessage = "Failed to compile OpenGL shader programs.\n" + program->log();
+ bool usesOpenGL = QSurfaceFormat::defaultFormat().renderableType() == QSurfaceFormat::OpenGL;
+ if ( !program->addShaderFromSourceCode( QOpenGLShader::Vertex, usesOpenGL ? vshaderDesktop : vshaderES ) ||
+ !program->addShaderFromSourceCode( QOpenGLShader::Fragment, usesOpenGL ? fshaderDesktop : fshaderES ) ) {
+ errorMessage = tr( "Failed to compile OpenGL shader programs.\n" ) + program->log();
return;
}
// Link shader pipeline
- if (!program->link() || !program->bind()) {
- errorMessage = "Failed to link/bind OpenGL shader programs\n" + program->log();
+ if ( !program->link() || !program->bind() ) {
+ errorMessage = tr( "Failed to link/bind OpenGL shader programs.\n" ) + program->log();
return;
}
- vertexLocation = program->attributeLocation("vertex");
- matrixLocation = program->uniformLocation("matrix");
- colorLocation = program->uniformLocation("colour");
+ vertexLocation = program->attributeLocation( "vertex" );
+ matrixLocation = program->uniformLocation( "matrix" );
+ colorLocation = program->uniformLocation( "colour" );
- if (vertexLocation == -1 || colorLocation == -1 || matrixLocation == -1) {
- qWarning() << "Failed to locate shader variable";
+ if ( vertexLocation == -1 || colorLocation == -1 || matrixLocation == -1 ) {
+ qWarning() << tr( "Failed to locate shader variable." );
return;
}
program->bind();
auto *gl = context()->functions();
- gl->glDisable(GL_DEPTH_TEST);
- gl->glEnable(GL_BLEND);
+ gl->glDisable( GL_DEPTH_TEST );
+ gl->glEnable( GL_BLEND );
// Enable depth buffer
- gl->glEnable(GL_DEPTH_TEST);
+ gl->glEnable( GL_DEPTH_TEST );
// Enable back face culling
- gl->glEnable(GL_CULL_FACE);
- gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ gl->glEnable( GL_CULL_FACE );
+ gl->glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
- QColor bg = view->screen.background;
- gl->glClearColor((GLfloat)bg.redF(), (GLfloat)bg.greenF(), (GLfloat)bg.blueF(), (GLfloat)bg.alphaF());
+ QColor bg = view->colors->background;
+ gl->glClearColor( GLfloat( bg.redF() ), GLfloat( bg.greenF() ), GLfloat( bg.blueF() ), GLfloat( bg.alphaF() ) );
- generateGrid(program.get());
{
m_vaoMarker.create();
- QOpenGLVertexArrayObject::Binder b(&m_vaoMarker);
+ QOpenGLVertexArrayObject::Binder b( &m_vaoMarker );
m_marker.create();
m_marker.bind();
- m_marker.setUsagePattern(QOpenGLBuffer::StaticDraw);
- m_marker.allocate(int(vaMarker.size() * sizeof(Vertices)));
- program->enableAttributeArray(vertexLocation);
- program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, 0);
+ m_marker.setUsagePattern( QOpenGLBuffer::StaticDraw );
+ m_marker.allocate( int( vaMarker.size() * sizeof( Vertices ) ) );
+ program->enableAttributeArray( vertexLocation );
+ program->setAttributeBuffer( vertexLocation, GL_FLOAT, 0, 3, 0 );
}
updateCursor();
- m_program = std::move(program);
+ m_program = std::move( program );
+
+ generateGrid(); // initialize the grid draw structures
+
shaderCompileSuccess = true;
}
-void GlScope::showData(std::shared_ptr data) {
- if (!shaderCompileSuccess) return;
+
+void GlScope::showData( std::shared_ptr< PPresult > newData ) {
+ if ( !shaderCompileSuccess )
+ return;
makeCurrent();
// Remove too much entries
- while (view->digitalPhosphorDraws() < m_GraphHistory.size()) m_GraphHistory.pop_back();
+ while ( view->digitalPhosphorDraws() < m_GraphHistory.size() )
+ m_GraphHistory.pop_back();
// Add if missing
- if (view->digitalPhosphorDraws() > m_GraphHistory.size()) { m_GraphHistory.resize(m_GraphHistory.size() + 1); }
+ if ( view->digitalPhosphorDraws() > m_GraphHistory.size() ) {
+ m_GraphHistory.resize( m_GraphHistory.size() + 1 );
+ }
// Move last item to front
- m_GraphHistory.splice(m_GraphHistory.begin(), m_GraphHistory, std::prev(m_GraphHistory.end()));
+ m_GraphHistory.splice( m_GraphHistory.begin(), m_GraphHistory, std::prev( m_GraphHistory.end() ) );
// Add new entry
- m_GraphHistory.front().writeData(data.get(), m_program.get(), vertexLocation);
+ m_GraphHistory.front().writeData( newData.get(), m_program.get(), vertexLocation );
// doneCurrent();
update();
}
-void GlScope::generateVertices(unsigned marker, const DsoSettingsScopeCursor &cursor) {
+
+void GlScope::generateVertices( unsigned marker, const DsoSettingsScopeCursor &cursor ) {
const float Z_ORDER = 1.0f;
- switch (cursor.shape) {
+ switch ( cursor.shape ) {
case DsoSettingsScopeCursor::NONE:
- vaMarker[marker] = {
- QVector3D(-DIVS_TIME, -DIVS_VOLTAGE, Z_ORDER),
- QVector3D(-DIVS_TIME, DIVS_VOLTAGE, Z_ORDER),
- QVector3D( DIVS_TIME, DIVS_VOLTAGE, Z_ORDER),
- QVector3D( DIVS_TIME, -DIVS_VOLTAGE, Z_ORDER)
- };
+ vaMarker[ marker ] = {QVector3D( -DIVS_TIME, -DIVS_VOLTAGE, Z_ORDER ), QVector3D( -DIVS_TIME, DIVS_VOLTAGE, Z_ORDER ),
+ QVector3D( DIVS_TIME, DIVS_VOLTAGE, Z_ORDER ), QVector3D( DIVS_TIME, -DIVS_VOLTAGE, Z_ORDER )};
break;
case DsoSettingsScopeCursor::VERTICAL:
- vaMarker[marker] = {
- QVector3D(cursor.pos[0].x(), -DIVS_VOLTAGE, Z_ORDER),
- QVector3D(cursor.pos[0].x(), DIVS_VOLTAGE, Z_ORDER),
- QVector3D(cursor.pos[1].x(), DIVS_VOLTAGE, Z_ORDER),
- QVector3D(cursor.pos[1].x(), -DIVS_VOLTAGE, Z_ORDER)
- };
+ vaMarker[ marker ] = {QVector3D( GLfloat( cursor.pos[ 0 ].x() ), -GLfloat( DIVS_VOLTAGE ), Z_ORDER ),
+ QVector3D( GLfloat( cursor.pos[ 0 ].x() ), GLfloat( DIVS_VOLTAGE ), Z_ORDER ),
+ QVector3D( GLfloat( cursor.pos[ 1 ].x() ), GLfloat( DIVS_VOLTAGE ), Z_ORDER ),
+ QVector3D( GLfloat( cursor.pos[ 1 ].x() ), -GLfloat( DIVS_VOLTAGE ), Z_ORDER )};
break;
case DsoSettingsScopeCursor::HORIZONTAL:
- vaMarker[marker] = {
- QVector3D(-DIVS_TIME, cursor.pos[0].y(), Z_ORDER),
- QVector3D( DIVS_TIME, cursor.pos[0].y(), Z_ORDER),
- QVector3D( DIVS_TIME, cursor.pos[1].y(), Z_ORDER),
- QVector3D(-DIVS_TIME, cursor.pos[1].y(), Z_ORDER)
- };
+ vaMarker[ marker ] = {QVector3D( -GLfloat( DIVS_TIME ), GLfloat( cursor.pos[ 0 ].y() ), Z_ORDER ),
+ QVector3D( GLfloat( DIVS_TIME ), GLfloat( cursor.pos[ 0 ].y() ), Z_ORDER ),
+ QVector3D( GLfloat( DIVS_TIME ), GLfloat( cursor.pos[ 1 ].y() ), Z_ORDER ),
+ QVector3D( -GLfloat( DIVS_TIME ), GLfloat( cursor.pos[ 1 ].y() ), Z_ORDER )};
break;
case DsoSettingsScopeCursor::RECTANGULAR:
- if ((cursor.pos[1].x() - cursor.pos[0].x()) * (cursor.pos[1].y() - cursor.pos[0].y()) > 0.0) {
- vaMarker[marker] = {
- QVector3D(cursor.pos[0].x(), cursor.pos[0].y(), Z_ORDER),
- QVector3D(cursor.pos[1].x(), cursor.pos[0].y(), Z_ORDER),
- QVector3D(cursor.pos[1].x(), cursor.pos[1].y(), Z_ORDER),
- QVector3D(cursor.pos[0].x(), cursor.pos[1].y(), Z_ORDER)
- };
+ if ( ( cursor.pos[ 1 ].x() - cursor.pos[ 0 ].x() ) * ( cursor.pos[ 1 ].y() - cursor.pos[ 0 ].y() ) > 0.0 ) {
+ vaMarker[ marker ] = {QVector3D( GLfloat( cursor.pos[ 0 ].x() ), GLfloat( cursor.pos[ 0 ].y() ), Z_ORDER ),
+ QVector3D( GLfloat( cursor.pos[ 1 ].x() ), GLfloat( cursor.pos[ 0 ].y() ), Z_ORDER ),
+ QVector3D( GLfloat( cursor.pos[ 1 ].x() ), GLfloat( cursor.pos[ 1 ].y() ), Z_ORDER ),
+ QVector3D( GLfloat( cursor.pos[ 0 ].x() ), GLfloat( cursor.pos[ 1 ].y() ), Z_ORDER )};
} else {
- vaMarker[marker] = {
- QVector3D(cursor.pos[0].x(), cursor.pos[0].y(), Z_ORDER),
- QVector3D(cursor.pos[0].x(), cursor.pos[1].y(), Z_ORDER),
- QVector3D(cursor.pos[1].x(), cursor.pos[1].y(), Z_ORDER),
- QVector3D(cursor.pos[1].x(), cursor.pos[0].y(), Z_ORDER)
- };
+ vaMarker[ marker ] = {QVector3D( GLfloat( cursor.pos[ 0 ].x() ), GLfloat( cursor.pos[ 0 ].y() ), Z_ORDER ),
+ QVector3D( GLfloat( cursor.pos[ 0 ].x() ), GLfloat( cursor.pos[ 1 ].y() ), Z_ORDER ),
+ QVector3D( GLfloat( cursor.pos[ 1 ].x() ), GLfloat( cursor.pos[ 1 ].y() ), Z_ORDER ),
+ QVector3D( GLfloat( cursor.pos[ 1 ].x() ), GLfloat( cursor.pos[ 0 ].y() ), Z_ORDER )};
}
break;
- default:
- break;
}
}
-void GlScope::updateCursor(unsigned index) {
- if (index > 0) {
- generateVertices(index, *cursorInfo[index]);
- } else for (index = 0; index < cursorInfo.size(); ++index) {
- generateVertices(index, *cursorInfo[index]);
- }
+
+void GlScope::updateCursor( unsigned index ) {
+ if ( index > 0 ) {
+ generateVertices( index, *cursorInfo[ index ] );
+ } else
+ for ( index = 0; index < cursorInfo.size(); ++index ) {
+ generateVertices( index, *cursorInfo[ index ] );
+ }
// Write coordinates to GPU
makeCurrent();
m_marker.bind();
- m_marker.write(0, vaMarker.data(), vaMarker.size() * sizeof(Vertices));
+ m_marker.write( 0, vaMarker.data(), int( vaMarker.size() * sizeof( Vertices ) ) );
}
+
void GlScope::paintGL() {
- if (!shaderCompileSuccess) return;
+ if ( !shaderCompileSuccess )
+ return;
auto *gl = context()->functions();
+ QColor bg = view->colors->background;
+ gl->glClearColor( GLfloat( bg.redF() ), GLfloat( bg.greenF() ), GLfloat( bg.blueF() ), GLfloat( bg.alphaF() ) );
+
// Clear OpenGL buffer and configure settings
// TODO Don't clear if view->digitalPhosphorDraws()>1
- gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- gl->glLineWidth(1);
+ gl->glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ gl->glLineWidth( 1 );
m_program->bind();
// Apply zoom settings via matrix transformation
- if (zoomed) {
+ if ( zoomed ) {
QMatrix4x4 m;
- m.scale(QVector3D(DIVS_TIME / (GLfloat)fabs(scope->getMarker(1) - scope->getMarker(0)), 1.0f, 1.0f));
- m.translate((GLfloat) - (scope->getMarker(0) + scope->getMarker(1)) / 2, 0.0f, 0.0f);
- m_program->setUniformValue(matrixLocation, pmvMatrix * m);
+ m.scale( QVector3D( GLfloat( DIVS_TIME ) / GLfloat( fabs( scope->getMarker( 1 ) - scope->getMarker( 0 ) ) ), 1.0f, 1.0f ) );
+ m.translate( -GLfloat( scope->getMarker( 0 ) + scope->getMarker( 1 ) ) / 2, 0.0f, 0.0f );
+ m_program->setUniformValue( matrixLocation, pmvMatrix * m );
}
drawMarkers();
unsigned historyIndex = 0;
- for (Graph &graph : m_GraphHistory) {
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) {
- if (scope->horizontal.format == Dso::GraphFormat::TY) {
- drawSpectrumChannelGraph(channel, graph, (int)historyIndex);
+ for ( Graph &graph : m_GraphHistory ) {
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel ) {
+ if ( scope->horizontal.format == Dso::GraphFormat::TY ) {
+ drawSpectrumChannelGraph( channel, graph, int( historyIndex ) );
+ if ( scope->histogram ) {
+ drawHistogramChannelGraph( channel, graph, int( historyIndex ) );
+ }
}
- drawVoltageChannelGraph(channel, graph, (int)historyIndex);
+ drawVoltageChannelGraph( channel, graph, int( historyIndex ) );
}
++historyIndex;
}
- if (zoomed) { m_program->setUniformValue(matrixLocation, pmvMatrix); }
+ if ( zoomed ) {
+ m_program->setUniformValue( matrixLocation, pmvMatrix );
+ }
drawGrid();
m_program->release();
}
-void GlScope::resizeGL(int width, int height) {
- if (!shaderCompileSuccess) return;
+
+void GlScope::resizeGL( int width, int height ) {
+ if ( !shaderCompileSuccess )
+ return;
auto *gl = context()->functions();
- gl->glViewport(0, 0, (GLint)width, (GLint)height);
+ gl->glViewport( 0, 0, GLint( width ), GLint( height ) );
// Set axes to div-scale and apply correction for exact pixelization
- float pixelizationWidthCorrection = (float)width / (width - 1);
- float pixelizationHeightCorrection = (float)height / (height - 1);
+ float pixelizationWidthCorrection = float( width ) / ( width - 1 );
+ float pixelizationHeightCorrection = float( height ) / ( height - 1 );
pmvMatrix.setToIdentity();
- pmvMatrix.ortho(-(DIVS_TIME / 2.0f) * pixelizationWidthCorrection, (DIVS_TIME / 2.0f) * pixelizationWidthCorrection,
- -(DIVS_VOLTAGE / 2.0f) * pixelizationHeightCorrection,
- (DIVS_VOLTAGE / 2.0f) * pixelizationHeightCorrection, -1.0f, 1.0f);
+ pmvMatrix.ortho( -float( DIVS_TIME ) / 2.0f * pixelizationWidthCorrection,
+ float( DIVS_TIME ) / 2.0f * pixelizationWidthCorrection,
+ -float( DIVS_VOLTAGE ) / 2.0f * pixelizationHeightCorrection,
+ float( DIVS_VOLTAGE ) / 2.0f * pixelizationHeightCorrection, -1.0f, 1.0f );
m_program->bind();
- m_program->setUniformValue(matrixLocation, pmvMatrix);
+ m_program->setUniformValue( matrixLocation, pmvMatrix );
m_program->release();
}
-void GlScope::generateGrid(QOpenGLShaderProgram *program) {
- gridDrawCounts[0] = 0;
- gridDrawCounts[1] = 0;
- gridDrawCounts[2] = 0;
- m_grid.create();
+// draw 4 small crosses @ (x,y), (-x,y), (x,-y) and (-x,-y)
+// section 0:grid, 1:axes, 2:border
+void GlScope::draw4Cross( std::vector< QVector3D > &va, int section, float x, float y ) {
+ const float d = 0.05f; // cross size
+ for ( int xSign : {-1, 1} ) {
+ for ( int ySign : {-1, 1} ) {
+ gridDrawCounts[ section ] += 4;
+ va.push_back( QVector3D( xSign * ( x - d ), ySign * y, 0 ) );
+ va.push_back( QVector3D( xSign * ( x + d ), ySign * y, 0 ) );
+ va.push_back( QVector3D( xSign * x, ySign * ( y - d ), 0 ) );
+ va.push_back( QVector3D( xSign * x, ySign * ( y + d ), 0 ) );
+ }
+ }
+}
+
+// prepare the static grid structure that is shown by 'drawGrid()'
+// show a line as long as the trigger level marker is clicked or moved
+// index: channel, value: trigger level, pressed: marker is activated
+void GlScope::generateGrid( int index, double value, bool pressed ) {
+ // printf( "prepareGrid( %d, %g, %d )\n", index, value, pressed );
+
+ QOpenGLShaderProgram *program = m_program.get();
+ if ( program == nullptr )
+ return;
+
+ for ( int iii = 0; iii < gridItems; ++iii )
+ gridDrawCounts[ iii ] = 0;
+
+ if ( !m_grid.isCreated() )
+ m_grid.create();
m_grid.bind();
- m_grid.setUsagePattern(QOpenGLBuffer::StaticDraw);
+ m_grid.setUsagePattern( QOpenGLBuffer::StaticDraw );
+
+ std::vector< QVector3D > vaGrid;
- std::vector vaGrid;
+ int item = 0;
{ // Bind draw vertical lines
- m_vaoGrid[0].create();
- QOpenGLVertexArrayObject::Binder b(&m_vaoGrid[0]);
+ if ( !m_vaoGrid[ item ].isCreated() )
+ m_vaoGrid[ item ].create();
+ QOpenGLVertexArrayObject::Binder b( &m_vaoGrid[ item ] );
m_grid.bind();
- program->enableAttributeArray(vertexLocation);
- program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, 0);
- }
-
- // Draw vertical lines
- for (int div = 1; div < DIVS_TIME / 2; ++div) {
- for (int dot = 1; dot < DIVS_VOLTAGE / 2 * DIVS_SUB; ++dot) {
- float dotPosition = (float)dot / DIVS_SUB;
- gridDrawCounts[0] += 4;
- vaGrid.push_back(QVector3D(-div, -dotPosition, 0));
- vaGrid.push_back(QVector3D(-div, dotPosition, 0));
- vaGrid.push_back(QVector3D(div, -dotPosition, 0));
- vaGrid.push_back(QVector3D(div, dotPosition, 0));
+ program->enableAttributeArray( vertexLocation );
+ program->setAttributeBuffer( vertexLocation, GL_FLOAT, 0, 3, 0 );
+ }
+
+ // Draw vertical dot lines
+ for ( int vDiv = 1; vDiv < DIVS_TIME / 2; ++vDiv ) {
+ for ( int dot = 1; dot < DIVS_VOLTAGE / 2 * DIVS_SUB; ++dot ) {
+ float dotPosition = float( dot ) / DIVS_SUB;
+ gridDrawCounts[ item ] += 4;
+ vaGrid.push_back( QVector3D( -vDiv, -dotPosition, 0 ) );
+ vaGrid.push_back( QVector3D( -vDiv, dotPosition, 0 ) );
+ vaGrid.push_back( QVector3D( vDiv, -dotPosition, 0 ) );
+ vaGrid.push_back( QVector3D( vDiv, dotPosition, 0 ) );
}
}
- // Draw horizontal lines
- for (int div = 1; div < DIVS_VOLTAGE / 2; ++div) {
- for (int dot = 1; dot < DIVS_TIME / 2 * DIVS_SUB; ++dot) {
- if (dot % DIVS_SUB == 0) continue; // Already done by vertical lines
- float dotPosition = (float)dot / DIVS_SUB;
- gridDrawCounts[0] += 4;
- vaGrid.push_back(QVector3D(-dotPosition, -div, 0));
- vaGrid.push_back(QVector3D(dotPosition, -div, 0));
- vaGrid.push_back(QVector3D(-dotPosition, div, 0));
- vaGrid.push_back(QVector3D(dotPosition, div, 0));
+ // Draw horizontal dot lines
+ for ( int hDiv = 1; hDiv < DIVS_VOLTAGE / 2; ++hDiv ) {
+ for ( int dot = 1; dot < DIVS_TIME / 2 * DIVS_SUB; ++dot ) {
+ if ( dot % DIVS_SUB == 0 )
+ continue; // Already done by vertical lines
+ float dotPosition = float( dot ) / DIVS_SUB;
+ gridDrawCounts[ item ] += 4;
+ vaGrid.push_back( QVector3D( -dotPosition, -hDiv, 0 ) );
+ vaGrid.push_back( QVector3D( dotPosition, -hDiv, 0 ) );
+ vaGrid.push_back( QVector3D( -dotPosition, hDiv, 0 ) );
+ vaGrid.push_back( QVector3D( dotPosition, hDiv, 0 ) );
}
}
+ ++item;
+
{ // Bind draw axes
- m_vaoGrid[1].create();
- QOpenGLVertexArrayObject::Binder b(&m_vaoGrid[1]);
+ if ( !m_vaoGrid[ item ].isCreated() )
+ m_vaoGrid[ item ].create();
+ QOpenGLVertexArrayObject::Binder b( &m_vaoGrid[ item ] );
m_grid.bind();
- program->enableAttributeArray(vertexLocation);
- program->setAttributeBuffer(vertexLocation, GL_FLOAT, int(vaGrid.size() * sizeof(QVector3D)), 3);
+ program->enableAttributeArray( vertexLocation );
+ program->setAttributeBuffer( vertexLocation, GL_FLOAT, int( vaGrid.size() * sizeof( QVector3D ) ), 3 );
}
// Axes
// Horizontal axis
- gridDrawCounts[1] += 4;
- vaGrid.push_back(QVector3D(-DIVS_TIME / 2, 0, 0));
- vaGrid.push_back(QVector3D(DIVS_TIME / 2, 0, 0));
+ gridDrawCounts[ item ] += 2;
+ vaGrid.push_back( QVector3D( -DIVS_TIME / 2, 0, 0 ) );
+ vaGrid.push_back( QVector3D( DIVS_TIME / 2, 0, 0 ) );
// Vertical axis
- vaGrid.push_back(QVector3D(0, -DIVS_VOLTAGE / 2, 0));
- vaGrid.push_back(QVector3D(0, DIVS_VOLTAGE / 2, 0));
+ gridDrawCounts[ item ] += 2;
+ vaGrid.push_back( QVector3D( 0, -DIVS_VOLTAGE / 2, 0 ) );
+ vaGrid.push_back( QVector3D( 0, DIVS_VOLTAGE / 2, 0 ) );
// Subdiv lines on horizontal axis
- for (int line = 1; line < DIVS_TIME / 2 * DIVS_SUB; ++line) {
- float linePosition = (float)line / DIVS_SUB;
- gridDrawCounts[1] += 4;
- vaGrid.push_back(QVector3D(linePosition, -0.05f, 0));
- vaGrid.push_back(QVector3D(linePosition, 0.05f, 0));
- vaGrid.push_back(QVector3D(-linePosition, -0.05f, 0));
- vaGrid.push_back(QVector3D(-linePosition, 0.05f, 0));
+ for ( int line = 1; line < DIVS_TIME / 2 * DIVS_SUB; ++line ) {
+ float linePosition = float( line ) / DIVS_SUB;
+ gridDrawCounts[ item ] += 4;
+ vaGrid.push_back( QVector3D( linePosition, -0.05f, 0 ) );
+ vaGrid.push_back( QVector3D( linePosition, 0.05f, 0 ) );
+ vaGrid.push_back( QVector3D( -linePosition, -0.05f, 0 ) );
+ vaGrid.push_back( QVector3D( -linePosition, 0.05f, 0 ) );
}
// Subdiv lines on vertical axis
- for (int line = 1; line < DIVS_VOLTAGE / 2 * DIVS_SUB; ++line) {
- float linePosition = (float)line / DIVS_SUB;
- gridDrawCounts[1] += 4;
- vaGrid.push_back(QVector3D(-0.05f, linePosition, 0));
- vaGrid.push_back(QVector3D(0.05f, linePosition, 0));
- vaGrid.push_back(QVector3D(-0.05f, -linePosition, 0));
- vaGrid.push_back(QVector3D(0.05f, -linePosition, 0));
+ for ( int line = 1; line < DIVS_VOLTAGE / 2 * DIVS_SUB; ++line ) {
+ float linePosition = float( line ) / DIVS_SUB;
+ gridDrawCounts[ item ] += 4;
+ vaGrid.push_back( QVector3D( -0.05f, linePosition, 0 ) );
+ vaGrid.push_back( QVector3D( 0.05f, linePosition, 0 ) );
+ vaGrid.push_back( QVector3D( -0.05f, -linePosition, 0 ) );
+ vaGrid.push_back( QVector3D( 0.05f, -linePosition, 0 ) );
}
- {
- m_vaoGrid[2].create();
- QOpenGLVertexArrayObject::Binder b(&m_vaoGrid[2]);
+ // Draw vertical cross lines
+ for ( int vDiv = 1; vDiv < DIVS_TIME / 2; ++vDiv ) {
+ for ( int hDiv = 1; hDiv < DIVS_VOLTAGE / 2; ++hDiv ) {
+ draw4Cross( vaGrid, 1, vDiv, hDiv );
+ }
+ }
+ // Draw horizontal cross lines
+ for ( int hDiv = 1; hDiv < DIVS_VOLTAGE / 2; ++hDiv ) {
+ for ( int vDiv = 1; vDiv < DIVS_TIME / 2; ++vDiv ) {
+ if ( vDiv % DIVS_SUB == 0 )
+ continue; // Already done by vertical lines
+ draw4Cross( vaGrid, 1, vDiv, hDiv );
+ }
+ }
+
+ ++item;
+
+ { // Border
+ if ( !m_vaoGrid[ item ].isCreated() )
+ m_vaoGrid[ item ].create();
+ QOpenGLVertexArrayObject::Binder b( &m_vaoGrid[ item ] );
m_grid.bind();
- program->enableAttributeArray(vertexLocation);
- program->setAttributeBuffer(vertexLocation, GL_FLOAT, int(vaGrid.size() * sizeof(QVector3D)), 3);
+ program->enableAttributeArray( vertexLocation );
+ program->setAttributeBuffer( vertexLocation, GL_FLOAT, int( vaGrid.size() * sizeof( QVector3D ) ), 3 );
}
+ gridDrawCounts[ item ] += 4;
+ vaGrid.push_back( QVector3D( -DIVS_TIME / 2, -DIVS_VOLTAGE / 2, 0 ) );
+ vaGrid.push_back( QVector3D( DIVS_TIME / 2, -DIVS_VOLTAGE / 2, 0 ) );
+ vaGrid.push_back( QVector3D( DIVS_TIME / 2, DIVS_VOLTAGE / 2, 0 ) );
+ vaGrid.push_back( QVector3D( -DIVS_TIME / 2, DIVS_VOLTAGE / 2, 0 ) );
- // Border
- gridDrawCounts[2] += 4;
- vaGrid.push_back(QVector3D(-DIVS_TIME / 2, -DIVS_VOLTAGE / 2, 0));
- vaGrid.push_back(QVector3D(DIVS_TIME / 2, -DIVS_VOLTAGE / 2, 0));
- vaGrid.push_back(QVector3D(DIVS_TIME / 2, DIVS_VOLTAGE / 2, 0));
- vaGrid.push_back(QVector3D(-DIVS_TIME / 2, DIVS_VOLTAGE / 2, 0));
+ ++item;
+
+
+ { // prepare (dynamic) trigger level marker line
+ if ( !m_vaoGrid[ item ].isCreated() )
+ m_vaoGrid[ item ].create();
+ QOpenGLVertexArrayObject::Binder b( &m_vaoGrid[ item ] );
+ m_grid.bind();
+ program->enableAttributeArray( vertexLocation );
+ program->setAttributeBuffer( vertexLocation, GL_FLOAT, int( vaGrid.size() * sizeof( QVector3D ) ), 3 );
+ }
+ if ( pressed && index >= 0 ) {
+ triggerLineColor = view->colors->voltage[ unsigned( index ) ];
+ if ( index != int( scope->trigger.source ) )
+ triggerLineColor = triggerLineColor.darker();
+ gridDrawCounts[ item ] += 2;
+ float yPos = float( ( value / scope->gain( unsigned( index ) ) + scope->voltage[ unsigned( index ) ].offset ) );
+ vaGrid.push_back( QVector3D( -DIVS_TIME / 2, yPos, 0 ) );
+ vaGrid.push_back( QVector3D( DIVS_TIME / 2, yPos, 0 ) );
+ }
- m_grid.allocate(&vaGrid[0], int(vaGrid.size() * sizeof(QVector3D)));
+ m_grid.allocate( &vaGrid[ 0 ], int( vaGrid.size() * sizeof( QVector3D ) ) );
m_grid.release();
}
+
void GlScope::drawGrid() {
auto *gl = context()->functions();
- gl->glLineWidth(1);
+
+ gl->glLineWidth( 1 );
+
+ int item = 3;
+ // Trigger level (draw this on top of the other items)
+ m_vaoGrid[ item ].bind();
+ m_program->setUniformValue( colorLocation, triggerLineColor );
+ gl->glDrawArrays( GL_LINES, 0, gridDrawCounts[ item ] );
+ m_vaoGrid[ item ].release();
// Grid
- m_vaoGrid[0].bind();
- m_program->setUniformValue(colorLocation, view->screen.grid);
- gl->glDrawArrays(GL_POINTS, 0, gridDrawCounts[0]);
- m_vaoGrid[0].release();
+ item = 0;
+ m_vaoGrid[ item ].bind();
+ m_program->setUniformValue( colorLocation, view->colors->grid );
+ gl->glDrawArrays( GL_POINTS, 0, gridDrawCounts[ item ] );
+ m_vaoGrid[ item ].release();
- // Axes
- m_vaoGrid[1].bind();
- m_program->setUniformValue(colorLocation, view->screen.axes);
- gl->glDrawArrays(GL_LINES, 0, gridDrawCounts[1]);
- m_vaoGrid[1].release();
+
+ // Axes and div crosses
+ ++item;
+ m_vaoGrid[ item ].bind();
+ m_program->setUniformValue( colorLocation, view->colors->axes );
+ gl->glDrawArrays( GL_LINES, 0, gridDrawCounts[ item ] );
+ m_vaoGrid[ item ].release();
// Border
- m_vaoGrid[2].bind();
- m_program->setUniformValue(colorLocation, view->screen.border);
- gl->glDrawArrays(GL_LINE_LOOP, 0, gridDrawCounts[2]);
- m_vaoGrid[2].release();
+ ++item;
+ m_vaoGrid[ item ].bind();
+ m_program->setUniformValue( colorLocation, view->colors->border );
+ gl->glDrawArrays( GL_LINE_LOOP, 0, gridDrawCounts[ item ] );
+ m_vaoGrid[ item ].release();
}
-void GlScope::drawVertices(QOpenGLFunctions *gl, unsigned marker, QColor color) {
- m_program->setUniformValue(colorLocation, (marker == selectedCursor) ? color : color.darker());
- gl->glDrawArrays(GL_LINE_LOOP, GLint(marker * VERTICES_ARRAY_SIZE), VERTICES_ARRAY_SIZE);
- if (cursorInfo[marker]->shape == DsoSettingsScopeCursor::RECTANGULAR) {
- color.setAlphaF(0.25);
- m_program->setUniformValue(colorLocation, color.darker());
- gl->glDrawArrays(GL_TRIANGLE_FAN, GLint(marker * VERTICES_ARRAY_SIZE), VERTICES_ARRAY_SIZE);
+
+void GlScope::drawVertices( QOpenGLFunctions *gl, unsigned marker, QColor color ) {
+ m_program->setUniformValue( colorLocation, ( marker == selectedCursor ) ? color : color.darker() );
+ gl->glDrawArrays( GL_LINE_LOOP, GLint( marker * VERTICES_ARRAY_SIZE ), GLint( VERTICES_ARRAY_SIZE ) );
+ if ( cursorInfo[ marker ]->shape == DsoSettingsScopeCursor::RECTANGULAR ) {
+ color.setAlphaF( 0.25 );
+ m_program->setUniformValue( colorLocation, color.darker() );
+ gl->glDrawArrays( GL_TRIANGLE_FAN, GLint( marker * VERTICES_ARRAY_SIZE ), GLint( VERTICES_ARRAY_SIZE ) );
}
}
+
void GlScope::drawMarkers() {
auto *gl = context()->functions();
m_vaoMarker.bind();
unsigned marker = 0;
- drawVertices(gl, marker, view->screen.markers);
+ drawVertices( gl, marker, view->colors->markers );
++marker;
- if (view->cursorsVisible) {
- gl->glDepthMask(GL_FALSE);
- for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel, ++marker) {
- if (scope->voltage[channel].used) {
- drawVertices(gl, marker, view->screen.voltage[channel]);
+ if ( view->cursorsVisible ) {
+ gl->glDepthMask( GL_FALSE );
+ for ( ChannelID channel = 0; channel < scope->voltage.size(); ++channel, ++marker ) {
+ if ( scope->voltage[ channel ].used ) {
+ drawVertices( gl, marker, view->colors->voltage[ channel ] );
}
}
- for (ChannelID channel = 0; channel < scope->spectrum.size(); ++channel, ++marker) {
- if (scope->spectrum[channel].used) {
- drawVertices(gl, marker, view->screen.spectrum[channel]);
+ for ( ChannelID channel = 0; channel < scope->spectrum.size(); ++channel, ++marker ) {
+ if ( scope->spectrum[ channel ].used ) {
+ drawVertices( gl, marker, view->colors->spectrum[ channel ] );
}
}
- gl->glDepthMask(GL_TRUE);
+ gl->glDepthMask( GL_TRUE );
}
m_vaoMarker.release();
}
-void GlScope::drawVoltageChannelGraph(ChannelID channel, Graph &graph, int historyIndex) {
- if (!scope->voltage[channel].used) return;
- m_program->setUniformValue(colorLocation, view->screen.voltage[channel].darker(100 + 10 * historyIndex));
- Graph::VaoCount &v = graph.vaoVoltage[channel];
+void GlScope::drawVoltageChannelGraph( ChannelID channel, Graph &graph, int historyIndex ) {
+ if ( !scope->voltage[ channel ].used )
+ return;
- QOpenGLVertexArrayObject::Binder b(v.first);
- const GLenum dMode = (view->interpolation == Dso::INTERPOLATION_OFF) ? GL_POINTS : GL_LINE_STRIP;
- context()->functions()->glDrawArrays(dMode, 0, v.second);
+ m_program->setUniformValue( colorLocation, view->colors->voltage[ channel ].darker( 100 + 10 * historyIndex ) );
+ Graph::VaoCount &v = graph.vaoVoltage[ channel ];
+
+ QOpenGLVertexArrayObject::Binder b( v.first );
+ const GLenum dMode = ( view->interpolation == Dso::INTERPOLATION_OFF ) ? GL_POINTS : GL_LINE_STRIP;
+ context()->functions()->glDrawArrays( dMode, 0, v.second );
}
-void GlScope::drawSpectrumChannelGraph(ChannelID channel, Graph &graph, int historyIndex) {
- if (!scope->spectrum[channel].used) return;
- m_program->setUniformValue(colorLocation, view->screen.spectrum[channel].darker(100 + 10 * historyIndex));
- Graph::VaoCount &v = graph.vaoSpectrum[channel];
+void GlScope::drawHistogramChannelGraph( ChannelID channel, Graph &graph, int historyIndex ) {
+ if ( !scope->voltage[ channel ].used )
+ return;
+
+ m_program->setUniformValue( colorLocation, view->colors->voltage[ channel ].darker( 100 + 10 * historyIndex ) );
+ Graph::VaoCount &h = graph.vaoHistogram[ channel ];
+
+ QOpenGLVertexArrayObject::Binder b( h.first );
+ const GLenum dMode = ( view->interpolation == Dso::INTERPOLATION_OFF ) ? GL_POINTS : GL_LINES;
+ context()->functions()->glDrawArrays( dMode, 0, h.second );
+}
+
+
+void GlScope::drawSpectrumChannelGraph( ChannelID channel, Graph &graph, int historyIndex ) {
+ if ( !scope->spectrum[ channel ].used )
+ return;
+
+ m_program->setUniformValue( colorLocation, view->colors->spectrum[ channel ].darker( 100 + 10 * historyIndex ) );
+ Graph::VaoCount &v = graph.vaoSpectrum[ channel ];
- QOpenGLVertexArrayObject::Binder b(v.first);
- const GLenum dMode = (view->interpolation == Dso::INTERPOLATION_OFF) ? GL_POINTS : GL_LINE_STRIP;
- context()->functions()->glDrawArrays(dMode, 0, v.second);
+ QOpenGLVertexArrayObject::Binder b( v.first );
+ const GLenum dMode = ( view->interpolation == Dso::INTERPOLATION_OFF ) ? GL_POINTS : GL_LINE_STRIP;
+ context()->functions()->glDrawArrays( dMode, 0, v.second );
}
diff --git a/openhantek/src/glscope.h b/openhantek/src/glscope.h
index 4d32e32d..e7c9fe5b 100644
--- a/openhantek/src/glscope.h
+++ b/openhantek/src/glscope.h
@@ -2,15 +2,15 @@
#pragma once
-#include
#include
+#include
-#include
#include
#include
#include
#include
#include
+#include
#include "glscopegraph.h"
#include "hantekdso/enums.h"
@@ -26,60 +26,67 @@ class GlScope : public QOpenGLWidget {
Q_OBJECT
public:
- static GlScope *createNormal(DsoSettingsScope *scope, DsoSettingsView *view,
- QWidget *parent = 0);
- static GlScope *createZoomed(DsoSettingsScope *scope, DsoSettingsView *view,
- QWidget *parent = 0);
+ static GlScope *createNormal( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent = nullptr );
+ static GlScope *createZoomed( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent = nullptr );
/**
- * We need at least OpenGL 3.2 with shader version 150 or
+ * We need at least OpenGL 3.2 with shader version 150 (else version 120) or
* OpenGL ES 2.0 with shader version 100.
*/
- static void fixOpenGLversion(QSurfaceFormat::RenderableType t=QSurfaceFormat::DefaultRenderableType);
+ static void useQSurfaceFormat( QSurfaceFormat::RenderableType t = QSurfaceFormat::DefaultRenderableType );
+ // force either GLSL version 1.20 or 1.50
+ static void useOpenGLSLversion( unsigned version ) { forceGLSLversion = version; }
/**
* Show new post processed data
* @param data
*/
- void showData(std::shared_ptr data);
- void updateCursor(unsigned index = 0);
- void cursorSelected(unsigned index) { selectedCursor = index; updateCursor(index); }
+ void showData( std::shared_ptr< PPresult > newData );
+ void updateCursor( unsigned index = 0 );
+ void cursorSelected( unsigned index ) {
+ selectedCursor = index;
+ updateCursor( index );
+ }
+ void generateGrid( int index = -1, double value = 0.0, bool pressed = false );
protected:
/// \brief Initializes the scope widget.
/// \param settings The settings that should be used.
/// \param parent The parent widget.
- GlScope(DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent = 0);
- virtual ~GlScope();
- GlScope(const GlScope&) = delete;
+ GlScope( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent = nullptr );
+ ~GlScope() override;
+ GlScope( const GlScope & ) = delete;
/// \brief Initializes OpenGL output.
- virtual void initializeGL() override;
+ void initializeGL() override;
/// \brief Draw the graphs, marker and the grid.
- virtual void paintGL() override;
+ void paintGL() override;
/// \brief Resize the widget.
/// \param width The new width of the widget.
/// \param height The new height of the widget.
- virtual void resizeGL(int width, int height) override;
+ void resizeGL( int width, int height ) override;
- virtual void mousePressEvent(QMouseEvent *event) override;
- virtual void mouseMoveEvent(QMouseEvent *event) override;
- virtual void mouseReleaseEvent(QMouseEvent *event) override;
- virtual void paintEvent(QPaintEvent *event) override;
+ void mousePressEvent( QMouseEvent *event ) override;
+ void mouseMoveEvent( QMouseEvent *event ) override;
+ void mouseReleaseEvent( QMouseEvent *event ) override;
+ void mouseDoubleClickEvent( QMouseEvent *event ) override;
+ void wheelEvent( QWheelEvent *event ) override;
+ void paintEvent( QPaintEvent *event ) override;
/// \brief Draw the grid.
void drawGrid();
/// Draw vertical lines at marker positions
void drawMarkers();
- void generateVertices(unsigned marker, const DsoSettingsScopeCursor &cursor);
- void drawVertices(QOpenGLFunctions *gl, unsigned marker, QColor color);
+ void generateVertices( unsigned marker, const DsoSettingsScopeCursor &cursor );
+ void drawVertices( QOpenGLFunctions *gl, unsigned marker, QColor color );
- void drawVoltageChannelGraph(ChannelID channel, Graph &graph, int historyIndex);
- void drawSpectrumChannelGraph(ChannelID channel, Graph &graph, int historyIndex);
- QPointF eventToPosition(QMouseEvent *event);
+ void drawVoltageChannelGraph( ChannelID channel, Graph &graph, int historyIndex );
+ void drawHistogramChannelGraph( ChannelID channel, Graph &graph, int historyIndex );
+ void drawSpectrumChannelGraph( ChannelID channel, Graph &graph, int historyIndex );
+ QPointF posToPosition( QPointF pos );
signals:
- void markerMoved(unsigned cursorIndex, unsigned marker);
+ void markerMoved( unsigned cursorIndex, unsigned marker );
private:
// User settings
@@ -89,35 +96,39 @@ class GlScope : public QOpenGLWidget {
// Marker
const unsigned NO_MARKER = UINT_MAX;
- #pragma pack(push, 1)
+#pragma pack( push, 1 )
struct Vertices {
QVector3D a, b, c, d;
};
- #pragma pack(pop)
- const unsigned VERTICES_ARRAY_SIZE = sizeof(Vertices) / sizeof(QVector3D);
- std::vector vaMarker;
+#pragma pack( pop )
+ const unsigned VERTICES_ARRAY_SIZE = sizeof( Vertices ) / sizeof( QVector3D );
+ std::vector< Vertices > vaMarker;
unsigned selectedMarker = NO_MARKER;
QOpenGLBuffer m_marker;
QOpenGLVertexArrayObject m_vaoMarker;
// Cursors
- std::vector cursorInfo;
+ std::vector< DsoSettingsScopeCursor * > cursorInfo;
unsigned selectedCursor = 0;
// Grid
QOpenGLBuffer m_grid;
- QOpenGLVertexArrayObject m_vaoGrid[3];
- GLsizei gridDrawCounts[3];
- void generateGrid(QOpenGLShaderProgram *program);
+ static const int gridItems = 4;
+ QOpenGLVertexArrayObject m_vaoGrid[ gridItems ];
+ GLsizei gridDrawCounts[ gridItems ];
+ void draw4Cross( std::vector< QVector3D > &va, int section, float x, float y );
+ QColor triggerLineColor = QColor( "black" );
// Graphs
- std::list m_GraphHistory;
+ std::list< Graph > m_GraphHistory;
unsigned currentGraphInHistory = 0;
// OpenGL shader, matrix, var-locations
+ unsigned int GLSLversion = 150;
+ static unsigned forceGLSLversion;
bool shaderCompileSuccess = false;
QString errorMessage;
- std::unique_ptr m_program;
+ std::unique_ptr< QOpenGLShaderProgram > m_program;
QMatrix4x4 pmvMatrix; ///< projection, view matrix
int colorLocation;
int vertexLocation;
diff --git a/openhantek/src/glscopegraph.cpp b/openhantek/src/glscopegraph.cpp
index 29ca3ade..6cf576ac 100644
--- a/openhantek/src/glscopegraph.cpp
+++ b/openhantek/src/glscopegraph.cpp
@@ -1,66 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0+
+
#include "glscopegraph.h"
#include
-Graph::Graph() : buffer(QOpenGLBuffer::VertexBuffer) {
+Graph::Graph() : buffer( QOpenGLBuffer::VertexBuffer ) {
buffer.create();
- buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
+ buffer.setUsagePattern( QOpenGLBuffer::DynamicDraw );
}
-void Graph::writeData(PPresult *data, QOpenGLShaderProgram *program, int vertexLocation) {
+void Graph::writeData( PPresult *data, QOpenGLShaderProgram *program, int vertexLocation ) {
// Determine memory
int neededMemory = 0;
- for (ChannelGraph &cg : data->vaChannelVoltage) neededMemory += cg.size() * sizeof(QVector3D);
- for (ChannelGraph &cg : data->vaChannelSpectrum) neededMemory += cg.size() * sizeof(QVector3D);
+ for ( ChannelGraph &cg : data->vaChannelVoltage )
+ neededMemory += int( cg.size() * sizeof( QVector3D ) );
+ for ( ChannelGraph &cg : data->vaChannelHistogram )
+ neededMemory += int( cg.size() * sizeof( QVector3D ) );
+ for ( ChannelGraph &cg : data->vaChannelSpectrum )
+ neededMemory += int( cg.size() * sizeof( QVector3D ) );
buffer.bind();
program->bind();
// Allocate space if necessary
- if (neededMemory > allocatedMem) {
- buffer.allocate(neededMemory);
+ if ( neededMemory > allocatedMem ) {
+ buffer.allocate( neededMemory );
allocatedMem = neededMemory;
}
// Write data to buffer
int offset = 0;
- vaoVoltage.resize(data->vaChannelVoltage.size());
- vaoSpectrum.resize(data->vaChannelSpectrum.size());
- for (ChannelID channel = 0; channel < vaoVoltage.size(); ++channel) {
+ vaoVoltage.resize( data->vaChannelVoltage.size() );
+ vaoHistogram.resize( data->vaChannelHistogram.size() );
+ vaoSpectrum.resize( data->vaChannelSpectrum.size() );
+ for ( ChannelID channel = 0; channel < std::max( std::max( vaoVoltage.size(), vaoHistogram.size() ), vaoSpectrum.size() );
+ ++channel ) {
int dataSize;
// Voltage channel
- if (channel < vaoVoltage.size()) {
- VaoCount &v = vaoVoltage[channel];
- if (!v.first) {
+ if ( channel < vaoVoltage.size() ) {
+ VaoCount &v = vaoVoltage[ channel ];
+ if ( !v.first ) {
v.first = new QOpenGLVertexArrayObject;
- if (!v.first->create()) throw new std::runtime_error("QOpenGLVertexArrayObject create failed");
+ if ( !v.first->create() )
+ throw new std::runtime_error( "QOpenGLVertexArrayObject create failed" );
}
- ChannelGraph &gVoltage = data->vaChannelVoltage[channel];
+ ChannelGraph &gVoltage = data->vaChannelVoltage[ channel ];
v.first->bind();
- dataSize = int(gVoltage.size() * sizeof(QVector3D));
- buffer.write(offset, gVoltage.data(), dataSize);
- program->enableAttributeArray(vertexLocation);
- program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, 0);
+ dataSize = int( gVoltage.size() * sizeof( QVector3D ) );
+ buffer.write( offset, gVoltage.data(), dataSize );
+ program->enableAttributeArray( vertexLocation );
+ program->setAttributeBuffer( vertexLocation, GL_FLOAT, offset, 3, 0 );
v.first->release();
- v.second = (int)gVoltage.size();
+ v.second = int( gVoltage.size() );
+ offset += dataSize;
+ }
+
+ // Histogram channel
+ if ( channel < vaoHistogram.size() ) {
+ VaoCount &h = vaoHistogram[ channel ];
+ if ( !h.first ) {
+ h.first = new QOpenGLVertexArrayObject;
+ if ( !h.first->create() )
+ throw new std::runtime_error( "QOpenGLVertexArrayObject create failed" );
+ }
+ ChannelGraph &gHistogram = data->vaChannelHistogram[ channel ];
+ h.first->bind();
+ dataSize = int( gHistogram.size() * sizeof( QVector3D ) );
+ buffer.write( offset, gHistogram.data(), dataSize );
+ program->enableAttributeArray( vertexLocation );
+ program->setAttributeBuffer( vertexLocation, GL_FLOAT, offset, 3, 0 );
+ h.first->release();
+ h.second = int( gHistogram.size() );
offset += dataSize;
}
// Spectrum channel
- if (channel < vaoSpectrum.size()) {
- VaoCount &s = vaoSpectrum[channel];
- if (!s.first) {
+ if ( channel < vaoSpectrum.size() ) {
+ VaoCount &s = vaoSpectrum[ channel ];
+ if ( !s.first ) {
s.first = new QOpenGLVertexArrayObject;
- if (!s.first->create()) throw new std::runtime_error("QOpenGLVertexArrayObject create failed");
+ if ( !s.first->create() )
+ throw new std::runtime_error( "QOpenGLVertexArrayObject create failed" );
}
- ChannelGraph &gSpectrum = data->vaChannelSpectrum[channel];
+ ChannelGraph &gSpectrum = data->vaChannelSpectrum[ channel ];
s.first->bind();
- dataSize = int(gSpectrum.size() * sizeof(QVector3D));
- buffer.write(offset, gSpectrum.data(), dataSize);
- program->enableAttributeArray(vertexLocation);
- program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, 0);
+ dataSize = int( gSpectrum.size() * sizeof( QVector3D ) );
+ buffer.write( offset, gSpectrum.data(), dataSize );
+ program->enableAttributeArray( vertexLocation );
+ program->setAttributeBuffer( vertexLocation, GL_FLOAT, offset, 3, 0 );
s.first->release();
- s.second = (int)gSpectrum.size();
+ s.second = int( gSpectrum.size() );
offset += dataSize;
}
}
@@ -69,13 +98,19 @@ void Graph::writeData(PPresult *data, QOpenGLShaderProgram *program, int vertexL
}
Graph::~Graph() {
- for (auto &vao : vaoVoltage) {
+ for ( auto &vao : vaoVoltage ) {
vao.first->destroy();
delete vao.first;
}
- for (auto &vao : vaoSpectrum) {
+ for ( auto &vao : vaoHistogram ) {
vao.first->destroy();
delete vao.first;
}
- if (buffer.isCreated()) { buffer.destroy(); }
+ for ( auto &vao : vaoSpectrum ) {
+ vao.first->destroy();
+ delete vao.first;
+ }
+ if ( buffer.isCreated() ) {
+ buffer.destroy();
+ }
}
diff --git a/openhantek/src/glscopegraph.h b/openhantek/src/glscopegraph.h
index 222bd19d..008cefbe 100644
--- a/openhantek/src/glscopegraph.h
+++ b/openhantek/src/glscopegraph.h
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
+
#pragma once
#include
@@ -13,15 +15,16 @@
struct Graph {
explicit Graph();
- Graph(const Graph &) = delete;
- Graph(const Graph &&) = delete;
+ Graph( const Graph & ) = delete;
+ Graph( const Graph && ) = delete;
~Graph();
- void writeData(PPresult *data, QOpenGLShaderProgram *program, int vertexLocation);
- typedef std::pair VaoCount;
+ void writeData( PPresult *data, QOpenGLShaderProgram *program, int vertexLocation );
+ typedef std::pair< QOpenGLVertexArrayObject *, GLsizei > VaoCount;
public:
int allocatedMem = 0;
QOpenGLBuffer buffer;
- std::vector vaoVoltage;
- std::vector vaoSpectrum;
+ std::vector< VaoCount > vaoVoltage;
+ std::vector< VaoCount > vaoHistogram;
+ std::vector< VaoCount > vaoSpectrum;
};
diff --git a/openhantek/src/hantekdso/capturing.cpp b/openhantek/src/hantekdso/capturing.cpp
new file mode 100644
index 00000000..86721e32
--- /dev/null
+++ b/openhantek/src/hantekdso/capturing.cpp
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+// #define TIMESTAMPDEBUG
+
+#include "capturing.h"
+#include "usb/scopedevice.h"
+#include
+#include
+
+
+Capturing::Capturing( HantekDsoControl *hdc ) : hdc( hdc ) { hdc->capturing = true; }
+
+
+void Capturing::run() {
+ forever {
+ if ( !hdc->capturing || QThread::currentThread()->isInterruptionRequested() ) {
+ hdc->quitSampling(); // stop the scope
+ hdc->stopStateMachine(); // stop the state machine
+ return; // stop this thread
+ }
+ if ( hdc->scope ) { // device is initialized
+ if ( hdc->sampling ) {
+ capture();
+ // add user defined hold-off time to lower CPU load
+ QThread::msleep( unsigned( 1000 * hdc->scope->horizontal.acquireInterval ) );
+ } else {
+ QThread::msleep( unsigned( hdc->displayInterval ) );
+ }
+ }
+ }
+}
+
+
+double id2sr( uint8_t timediv ) {
+ if ( timediv < 100 )
+ return timediv * 1e6;
+ return ( timediv - 100 ) * 1e4;
+}
+
+
+void Capturing::xferSamples() {
+ QWriteLocker locker( &hdc->raw.lock );
+ if ( !freeRun )
+ swap( data, hdc->raw.data );
+ hdc->raw.channels = channels;
+ hdc->raw.samplerate = samplerate;
+ hdc->raw.oversampling = oversampling;
+ hdc->raw.gainValue[ 0 ] = gainValue[ 0 ];
+ hdc->raw.gainValue[ 1 ] = gainValue[ 1 ];
+ hdc->raw.gainIndex[ 0 ] = gainIndex[ 0 ];
+ hdc->raw.gainIndex[ 1 ] = gainIndex[ 1 ];
+ hdc->raw.freeRun = freeRun;
+ hdc->raw.valid = valid;
+ hdc->raw.tag = tag;
+}
+
+
+void Capturing::capture() {
+ if ( !hdc->samplingStarted )
+ return;
+ int errorCode;
+ // Send all pending control commands
+ ControlCommand *controlCommand = hdc->firstControlCommand;
+ while ( controlCommand ) {
+ if ( controlCommand->pending ) {
+ switch ( int( controlCommand->code ) ) {
+ case uint8_t( ControlCode::CONTROL_SETGAIN_CH1 ):
+ gainValue[ 0 ] = controlCommand->data()[ 0 ];
+ gainIndex[ 0 ] = controlCommand->data()[ 1 ];
+ break;
+ case uint8_t( ControlCode::CONTROL_SETGAIN_CH2 ):
+ gainValue[ 1 ] = controlCommand->data()[ 0 ];
+ gainIndex[ 1 ] = controlCommand->data()[ 1 ];
+ break;
+ case uint8_t( ControlCode::CONTROL_SETNUMCHANNELS ):
+ if ( realSlow ) { // force 2 channels for slow samplings where roll mode is possible
+ if ( *controlCommand->data() == channels )
+ controlCommand->pending = false;
+ else
+ *controlCommand->data() = 2;
+ }
+ channels = *controlCommand->data();
+ break;
+ case uint8_t( ControlCode::CONTROL_SETSAMPLERATE ):
+ samplerate = id2sr( controlCommand->data()[ 0 ] );
+ uint8_t sampleIndex = controlCommand->data()[ 1 ];
+ oversampling = uint8_t( hdc->specification->fixedSampleRates[ sampleIndex ].oversampling );
+ effectiveSamplerate = hdc->specification->fixedSampleRates[ sampleIndex ].samplerate;
+ if ( !realSlow && effectiveSamplerate < 10e3 &&
+ hdc->scope->trigger.mode == Dso::TriggerMode::ROLL ) { // switch to real slow rolling
+ for ( auto it = data.begin(); it != data.end(); ++it )
+ *it = 0x80; // fill with "zeros"
+ QWriteLocker locker( &hdc->raw.lock );
+ hdc->raw.rollMode = false;
+ swap( data, hdc->raw.data ); // "clear screen"
+ }
+ realSlow = effectiveSamplerate < 10e3;
+ if ( realSlow ) { // roll mode possible?
+ if ( channels != 2 ) // always switch to two channels
+ hdc->modifyCommand< ControlSetNumChannels >( ControlCode::CONTROL_SETNUMCHANNELS )->setNumChannels( 2 );
+ } else {
+ if ( channels == 2 && hdc->isSingleChannel() ) // switch back to real user setting
+ hdc->modifyCommand< ControlSetNumChannels >( ControlCode::CONTROL_SETNUMCHANNELS )->setNumChannels( 1 );
+ }
+ break;
+ }
+ QString name = "";
+ if ( controlCommand->code >= 0xe0 && controlCommand->code <= 0xe6 )
+ name = hdc->controlNames[ controlCommand->code - 0xe0 ];
+ timestampDebug( QString( "Sending control command 0x%1 (%2): %3" )
+ .arg( QString::number( controlCommand->code, 16 ), name,
+ hexdecDump( controlCommand->data(), unsigned( controlCommand->size() ) ) ) );
+ if ( hdc->scopeDevice->isRealHW() ) { // do the USB communication with scope HW
+ errorCode = hdc->scopeDevice->controlWrite( controlCommand );
+ if ( errorCode < 0 ) {
+ qWarning( "Sending control command %2x failed: %s", uint8_t( controlCommand->code ),
+ libUsbErrorString( errorCode ).toLocal8Bit().data() );
+
+ if ( errorCode == LIBUSB_ERROR_NO_DEVICE ) {
+ return;
+ }
+ } else {
+ controlCommand->pending = false;
+ }
+ } else {
+ controlCommand->pending = false;
+ }
+ }
+ controlCommand = controlCommand->next;
+ }
+ valid = true;
+ freeRun = hdc->triggerModeNONE() && realSlow;
+ // sample step by step into the target if rollMode, else buffer and switch one big block
+ dp = freeRun ? &hdc->raw.data : &data;
+ rawSamplesize = hdc->grossSampleCount( hdc->getSamplesize() * oversampling ) * channels;
+ dp->resize( rawSamplesize, 0x80 );
+ if ( tag && freeRun ) // in free run mode transfer settings immediately
+ xferSamples();
+ ++tag;
+ if ( hdc->scopeDevice->isRealHW() ) {
+ received = getRealSamples();
+ } else {
+ received = getDemoSamples();
+ }
+ if ( received != rawSamplesize ) {
+ // qDebug() << "retval != rawSamplesize" << received << rawSamplesize;
+ auto end = dp->end();
+ for ( auto it = dp->begin(); it != end; ++it )
+ *it = 0x80; // fill with "zeros"
+ valid = false;
+ hdc->raw.rollMode = false;
+ } else {
+ hdc->raw.rollMode = true; // one complete buffer available, start to roll
+ }
+ if ( !freeRun ) // in normal capturing mode transfer after capturing one block
+ xferSamples();
+}
+
+
+unsigned Capturing::getRealSamples() {
+ int errorCode;
+ errorCode = hdc->scopeDevice->controlWrite( hdc->getCommand( ControlCode::CONTROL_STARTSAMPLING ) );
+ if ( errorCode < 0 ) {
+ qWarning() << "controlWrite: Getting sample data failed: " << libUsbErrorString( errorCode );
+ dp->clear();
+ return 0;
+ }
+ // Save raw data to temporary buffer
+ // timestampDebug( QString( "Request packet %1: %2 bytes" ).arg( tag ).arg( rawSamplesize ) );
+ hdc->raw.received = 0;
+ int retval = hdc->scopeDevice->bulkReadMulti( dp->data(), rawSamplesize, realSlow, hdc->raw.received );
+ if ( retval < 0 ) {
+ if ( retval == LIBUSB_ERROR_NO_DEVICE )
+ hdc->scopeDevice->disconnectFromDevice();
+ qWarning() << "bulkReadMulti: Getting sample data failed: " << libUsbErrorString( retval );
+ dp->clear();
+ return 0;
+ }
+ // timestampDebug( QString( "Received packet %1: %2 bytes" ).arg( tag ).arg( retval ) );
+ return unsigned( retval );
+}
+
+
+unsigned Capturing::getDemoSamples() {
+ const uint8_t binaryOffset = 0x80; // ADC format: binary offset
+ const int8_t V_zero = 0; // ADC = 0V
+ const int8_t V_plus_1 = 25; // ADC = 1V
+ const int8_t V_plus_2 = 50; // ADC = 2V
+ const int8_t V_minus_1 = -25; // ADC = -1V
+ const int8_t V_minus_2 = -50; // ADC = -2V
+ const int gain1 = int( gainValue[ 0 ] );
+ const int gain2 = int( gainValue[ 1 ] );
+ static int ch1 = 0;
+ static int ch2 = 0;
+ static int counter = 0;
+ unsigned received = 0;
+ hdc->raw.received = 0;
+ // timestampDebug( QString( "Request dummy packet %1: %2 bytes" ).arg( tag ).arg( rawSamplesize ) );
+ int deltaT = 99;
+ // deltaT (=99) defines the frequency of the dummy signals:
+ // ch1 = 1 kHz and ch2 = 500 Hz
+ // uncomment the next two lines to disable sample slowdown for low sample rates
+ // if ( samplerate < 10e6 )
+ // deltaT = int( round( deltaT * samplerate / 10e6 ) );
+ // adapt demo samples for high sample rates >10 MS/s
+ if ( samplerate > 10e6 )
+ deltaT = int( round( deltaT * samplerate / 10e6 ) );
+ const unsigned packetLength = 512 * 78; // 50 blocks for one screen width of 20000
+ unsigned block = 0;
+ dp->resize( rawSamplesize, binaryOffset );
+ auto end = dp->end();
+ unsigned packet = 0;
+ // bool couplingAC1 = hdc->scope->coupling( 0, hdc->specification ) == Dso::Coupling::AC; // not yet used
+ bool couplingAC2 = hdc->scope->coupling( 1, hdc->specification ) == Dso::Coupling::AC;
+ for ( auto it = dp->begin(); it != end; ++it ) {
+ if ( ++counter >= deltaT ) {
+ counter = 0;
+ if ( --ch1 < V_minus_2 ) {
+ ch1 = V_plus_2;
+ if ( couplingAC2 )
+ ch2 = ch2 <= V_zero ? V_plus_1 : V_minus_1; // -1V <-> +1V
+ else
+ ch2 = ch2 <= V_plus_1 ? V_plus_2 : V_zero; // 0V <-> 2V
+ }
+ }
+ *it = uint8_t( qBound( 0, ch1 * gain1 + binaryOffset, 0xFF ) ); // clip if outside 8bit range
+ ++received;
+ if ( 2 == channels ) {
+ *++it = uint8_t( qBound( 0, ch2 * gain2 + binaryOffset, 0xFF ) ); // clip ..
+ ++received;
+ }
+ if ( ( block += channels ) >= packetLength ) {
+ ++packet;
+ block = 0;
+ hdc->raw.received = received;
+ QThread::usleep( unsigned( 1e6 * packetLength / channels / samplerate ) );
+ if ( !hdc->capturing || hdc->scopeDevice->hasStopped() )
+ break;
+ }
+ }
+ // timestampDebug( QString( "Received dummy packet %1: %2 bytes" ).arg( packet ).arg( rawSamplesize ) );
+ return received;
+}
diff --git a/openhantek/src/hantekdso/capturing.h b/openhantek/src/hantekdso/capturing.h
new file mode 100644
index 00000000..1bc44a2f
--- /dev/null
+++ b/openhantek/src/hantekdso/capturing.h
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#pragma once
+
+#include "hantekdsocontrol.h"
+
+class Capturing : public QThread {
+ Q_OBJECT
+
+ public:
+ Capturing( HantekDsoControl *hdc );
+ void quitCapturing() { hdc->capturing = false; }
+
+ private:
+ void run() override;
+ void capture();
+ unsigned getRealSamples();
+ unsigned getDemoSamples();
+ void xferSamples();
+ // bool active = true;
+ HantekDsoControl *hdc;
+ unsigned channels = 0;
+ double effectiveSamplerate = 0;
+ bool realSlow = false;
+ double samplerate = 0;
+ unsigned oversampling = 0;
+ unsigned rawSamplesize = 0;
+ unsigned received = 0;
+ unsigned gainValue[ 2 ] = {0, 0}; // 1,2,5,10,..
+ unsigned gainIndex[ 2 ] = {0, 0}; // index 0..7
+ unsigned tag = 0;
+ bool valid = true;
+ bool freeRun = false;
+ std::vector< unsigned char > data;
+ std::vector< unsigned char > *dp = &data;
+};
diff --git a/openhantek/src/hantekdso/controlsettings.cpp b/openhantek/src/hantekdso/controlsettings.cpp
index 6b119baf..afde69a6 100644
--- a/openhantek/src/hantekdso/controlsettings.cpp
+++ b/openhantek/src/hantekdso/controlsettings.cpp
@@ -1,19 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+
#include "controlsettings.h"
#include "hantekprotocol/definitions.h"
namespace Dso {
-ControlSettings::ControlSettings(const ControlSamplerateLimits * limits, size_t channelCount) : cmdGetLimits(channelCount)
-{
+ControlSettings::ControlSettings( const ControlSamplerateLimits *limits, size_t channelCount ) : cmdGetLimits() {
samplerate.limits = limits;
- trigger.level.resize(channelCount);
- voltage.resize(channelCount);
- offsetLimit = new Hantek::OffsetsPerGainStep[channelCount];
+ trigger.level.resize( channelCount );
+ voltage.resize( channelCount );
+ calibrationValues = new Hantek::CalibrationValues;
}
-ControlSettings::~ControlSettings()
-{
- delete [] offsetLimit;
-}
+ControlSettings::~ControlSettings() { delete calibrationValues; }
-}
+} // namespace Dso
diff --git a/openhantek/src/hantekdso/controlsettings.h b/openhantek/src/hantekdso/controlsettings.h
index a328f507..6cb017cc 100644
--- a/openhantek/src/hantekdso/controlsettings.h
+++ b/openhantek/src/hantekdso/controlsettings.h
@@ -1,12 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+
#pragma once
#include "enums.h"
-#include "hantekprotocol/types.h"
-#include "hantekprotocol/bulkcode.h"
#include "hantekprotocol/controlStructs.h"
+#include "hantekprotocol/types.h"
namespace Hantek {
-struct OffsetsPerGainStep;
+struct CalibrationValues;
}
namespace Dso {
@@ -23,44 +24,44 @@ struct ControlSettingsSamplerateTarget {
/// \brief Stores the current samplerate settings of the device.
struct ControlSettingsSamplerate {
ControlSettingsSamplerateTarget target; ///< The target samplerate values
- const ControlSamplerateLimits * limits; ///< The samplerate limits
+ const ControlSamplerateLimits *limits; ///< The samplerate limits
unsigned int downsampler = 1; ///< The variable downsampling factor
- double current = 1e8; ///< The current samplerate
+ double current = 1e6; ///< The current samplerate
};
/// \brief Stores the current trigger settings of the device.
struct ControlSettingsTrigger {
- std::vector level; ///< The trigger level for each channel in V
- double position = 0.0; ///< The current pretrigger position
- unsigned int point = 0; ///< The trigger position in Hantek coding
- Dso::TriggerMode mode = Dso::TriggerMode::HARDWARE_SOFTWARE; ///< The trigger mode
- Dso::Slope slope = Dso::Slope::Positive; ///< The trigger slope
- bool special = false; ///< true, if the trigger source is special
- unsigned int source = 0; ///< The trigger source
+ std::vector< double > level; ///< The trigger level for each channel in V
+ double position = 0.0; ///< The current pretrigger position
+ unsigned int point = 0; ///< The trigger position in Hantek coding
+ Dso::TriggerMode mode = Dso::TriggerMode::AUTO; ///< The trigger mode
+ Dso::Slope slope = Dso::Slope::Positive; ///< The trigger slope
+ unsigned int source = 0; ///< The trigger source
+ bool smooth = false; ///< Don't trigger on glitches
};
/// \brief Stores the current amplification settings of the device.
struct ControlSettingsVoltage {
- double offset = 0.0; ///< The screen offset for each channel
- double offsetReal = 0.0; ///< The real offset for each channel (Due to quantization)
- unsigned gain = 0; ///< The gain id
- bool used = false; ///< true, if the channel is used
+ double offset = 0.0; ///< The screen offset for each channel
+ unsigned gain = 0; ///< The gain id
+ bool used = false; ///< true, if the channel is used
+ bool inverted = false; ///< true, if the channel is inverted
+ double probeAttn = 1.0; ///< attenuation of probe
+ Dso::Coupling coupling = Dso::Coupling::DC; ///< The coupling
};
/// \brief Stores the current settings of the device.
struct ControlSettings {
- ControlSettings(const ControlSamplerateLimits *limits, size_t channelCount);
+ ControlSettings( const ControlSamplerateLimits *limits, size_t channelCount );
~ControlSettings();
- ControlSettingsSamplerate samplerate; ///< The samplerate settings
- std::vector voltage; ///< The amplification settings
- ControlSettingsTrigger trigger; ///< The trigger settings
- RecordLengthID recordLengthId = 1; ///< The id in the record length array
- unsigned usedChannels = 0; ///< Number of activated channels
- unsigned swSampleMargin = 2000; ///< Software trigger, sample margin
- Hantek::OffsetsPerGainStep *offsetLimit; ///< Calibration data for the channel offsets
-
-
- Hantek::ControlBeginCommand beginCommandControl;
+ ControlSettings( const ControlSettings & ) = delete;
+ ControlSettings operator=( const ControlSettings & ) = delete;
+ ControlSettingsSamplerate samplerate; ///< The samplerate settings
+ std::vector< ControlSettingsVoltage > voltage; ///< The amplification settings
+ ControlSettingsTrigger trigger; ///< The trigger settings
+ RecordLengthID recordLengthId = 1; ///< The id in the record length array
+ unsigned channelCount = 0; ///< Number of activated channels
+ Hantek::CalibrationValues *calibrationValues; ///< Calibration data for the channel offsets & gains
Hantek::ControlGetLimits cmdGetLimits;
};
-}
+} // namespace Dso
diff --git a/openhantek/src/hantekdso/controlspecification.cpp b/openhantek/src/hantekdso/controlspecification.cpp
index 9cdccc9f..bbffd9ab 100644
--- a/openhantek/src/hantekdso/controlspecification.cpp
+++ b/openhantek/src/hantekdso/controlspecification.cpp
@@ -1,5 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
+
#include "controlspecification.h"
-Dso::ControlSpecification::ControlSpecification(unsigned channels) : channels(channels) {
- voltageLimit.resize(channels);
+Dso::ControlSpecification::ControlSpecification( unsigned channels ) : channels( channels ) {
+ voltageScale.resize( channels );
+ voltageOffset.resize( channels );
}
diff --git a/openhantek/src/hantekdso/controlspecification.h b/openhantek/src/hantekdso/controlspecification.h
index 964207bb..7515d625 100644
--- a/openhantek/src/hantekdso/controlspecification.h
+++ b/openhantek/src/hantekdso/controlspecification.h
@@ -5,7 +5,6 @@
#include "enums.h"
#include "hantekprotocol/definitions.h"
#include "hantekprotocol/types.h"
-#include "hantekprotocol/bulkcode.h"
#include
namespace Dso {
@@ -14,81 +13,61 @@ using namespace Hantek;
/// \brief Stores the samplerate limits for calculations.
struct ControlSamplerateLimits {
- double base; ///< The base for sample rate calculations
- double max; ///< The maximum sample rate
- unsigned int maxDownsampler; ///< The maximum downsampling ratio
- std::vector recordLengths; ///< Available record lengths, UINT_MAX means rolling
+ double base; ///< The base for sample rate calculations
+ double max; ///< The maximum sample rate
+ std::vector< unsigned > recordLengths; ///< Available record lengths, UINT_MAX means rolling
};
/// \brief Stores the samplerate limits.
struct ControlSpecificationSamplerate {
- ControlSamplerateLimits single = {50e6, 50e6, 0, std::vector()}; ///< The limits for single channel mode
- ControlSamplerateLimits multi = {100e6, 100e6, 0, std::vector()}; ///< The limits for multi channel mode
+ ControlSamplerateLimits single = {50e6, 50e6, std::vector< unsigned >()}; ///< The limits for single channel mode
+ ControlSamplerateLimits multi = {100e6, 100e6, std::vector< unsigned >()}; ///< The limits for multi channel mode
};
struct ControlSpecificationGainLevel {
/// The index of the selected gain on the hardware
- unsigned char gainIndex;
- /// Available voltage steps in V/screenheight
- double gainSteps;
+ unsigned char gainValue; // 1, 2, 5, 10, ..
+ /// Available voltage steps in V/div
+ double Vdiv;
+ // double gainError;
};
struct FixedSampleRate {
- unsigned char id;
double samplerate;
-};
-
-struct SpecialTriggerChannel {
- std::string name;
- int hardwareID;
+ unsigned char id;
+ unsigned oversampling;
};
/// \brief Stores the specifications of the currently connected device.
struct ControlSpecification {
- ControlSpecification(unsigned channels);
+ explicit ControlSpecification( unsigned channels );
const ChannelID channels;
- // Interface
- BulkCode cmdSetChannels = BulkCode::INVALID; ///< Command for setting used channels
- BulkCode cmdSetSamplerate = BulkCode::INVALID; ///< Command for samplerate settings
- BulkCode cmdSetRecordLength = BulkCode::INVALID; ///< Command for buffer settings
- BulkCode cmdSetTrigger = BulkCode::INVALID; ///< Command for trigger settings
- BulkCode cmdSetPretrigger = BulkCode::INVALID; ///< Command for pretrigger settings
- BulkCode cmdForceTrigger = BulkCode::FORCETRIGGER; ///< Command for forcing a trigger event
- BulkCode cmdCaptureStart = BulkCode::STARTSAMPLING; ///< Command for starting the sampling
- BulkCode cmdTriggerEnabled = BulkCode::ENABLETRIGGER; ///< Command for enabling the trigger
- BulkCode cmdGetData = BulkCode::GETDATA; ///< Command for retrieve sample data
- BulkCode cmdGetCaptureState = BulkCode::GETCAPTURESTATE; ///< Command for retrieve the capture state
- BulkCode cmdSetGain = BulkCode::SETGAIN; ///< Command for setting the gain
-
// Limits
- ControlSpecificationSamplerate samplerate; ///< The samplerate specifications
- std::vector bufferDividers; ///< Samplerate dividers for record lengths
- unsigned char sampleSize; ///< Number of bits per sample
+ ControlSpecificationSamplerate samplerate; ///< The samplerate specifications
- /// For devices that support only fixed sample rates (isFixedSamplerateDevice=true)
- std::vector fixedSampleRates;
+ /// For devices that support only fixed sample rates
+ std::vector< FixedSampleRate > fixedSampleRates;
// Calibration
-
- /// The sample values at the top of the screen
- typedef std::vector VoltageLimit;
- std::vector voltageLimit; // Per channel
+ /// DSO6022 has calibration in small EEPROM, DDS120 has big fw EEPROM
+ bool hasCalibrationEEPROM = true;
+ bool isDemoDevice = false;
+ /// The sample values for one div
+ typedef std::vector< double > VoltageScale;
+ std::vector< VoltageScale > voltageScale; // Per channel
+ typedef std::vector< double > VoltageOffset;
+ std::vector< VoltageOffset > voltageOffset; // Per channel
/// Gain levels
- std::vector