Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2757911bf6 |
@@ -1,88 +0,0 @@
|
||||
# Use the latest 2.1 version of CircleCI pipeline process engine.
|
||||
# See: https://circleci.com/docs/2.0/configuration-reference
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
build-std:
|
||||
docker:
|
||||
- image: ajjjjjjjj/opentx-docker-i6x:1.4.0
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
python3 ./tools/build-flysky.py -bI6X -tALL $PWD/
|
||||
- store_artifacts:
|
||||
path: output
|
||||
|
||||
build-std-dfplayer:
|
||||
docker:
|
||||
- image: ajjjjjjjj/opentx-docker-i6x:1.4.0
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
python3 ./tools/build-flysky.py -bI6X_DFPLAYER -tALL $PWD/
|
||||
- store_artifacts:
|
||||
path: output
|
||||
|
||||
build-heli:
|
||||
docker:
|
||||
- image: ajjjjjjjj/opentx-docker-i6x:1.4.0
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
python3 ./tools/build-flysky.py -bI6X_HELI -tALL $PWD/
|
||||
- store_artifacts:
|
||||
path: output
|
||||
|
||||
build-heli-dfplayer:
|
||||
docker:
|
||||
- image: ajjjjjjjj/opentx-docker-i6x:1.4.0
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
python3 ./tools/build-flysky.py -bI6X_HELI_DFPLAYER -tALL $PWD/
|
||||
- store_artifacts:
|
||||
path: output
|
||||
|
||||
build-en:
|
||||
docker:
|
||||
- image: ajjjjjjjj/opentx-docker-i6x:1.4.0
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
python3 ./tools/build-flysky.py -bI6X_DFPLAYER -bI6X_HELI -bI6X -tEN $PWD/
|
||||
- store_artifacts:
|
||||
path: output
|
||||
|
||||
workflows:
|
||||
openi6x-release-workflow:
|
||||
jobs:
|
||||
- build-en:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- master
|
||||
- /.*-maintenance/
|
||||
- build-std:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /.*-maintenance/
|
||||
- build-std-dfplayer:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /.*-maintenance/
|
||||
- build-heli:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /.*-maintenance/
|
||||
- build-heli-dfplayer:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /.*-maintenance/
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
# Handle line endings automatically for files detected as text
|
||||
# and leave all files detected as binary untouched.
|
||||
* text=auto
|
||||
|
||||
#
|
||||
# The above will handle all files NOT found below
|
||||
#
|
||||
# These files are text and should be normalized (Convert crlf => lf)
|
||||
|
||||
# Source files
|
||||
*.c text
|
||||
*.cc text
|
||||
*.cxx text
|
||||
*.cpp text
|
||||
*.c++ text
|
||||
*.hpp text
|
||||
*.h text
|
||||
*.h++ text
|
||||
*.hh text
|
||||
*.lua text
|
||||
*.pxd text
|
||||
*.py text
|
||||
*.py3 text
|
||||
*.pyw text
|
||||
*.pyx text
|
||||
*.pl text
|
||||
*.pm text
|
||||
*.sln text eol=crlf
|
||||
*.csproj text eol=crlf
|
||||
*.vbproj text eol=crlf
|
||||
*.vcxproj text eol=crlf
|
||||
*.vcproj text eol=crlf
|
||||
*.dbproj text eol=crlf
|
||||
*.fsproj text eol=crlf
|
||||
*.lsproj text eol=crlf
|
||||
*.wixproj text eol=crlf
|
||||
*.modelproj text eol=crlf
|
||||
*.sqlproj text eol=crlf
|
||||
*.wmaproj text eol=crlf
|
||||
*.xproj text eol=crlf
|
||||
*.props text eol=crlf
|
||||
*.filters text eol=crlf
|
||||
*.vcxitems text eol=crlf
|
||||
*.sh eol=lf
|
||||
|
||||
# Compiled Object files
|
||||
*.slo binary
|
||||
*.lo binary
|
||||
*.o binary
|
||||
*.obj binary
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch binary
|
||||
*.pch binary
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so binary
|
||||
*.dylib binary
|
||||
*.dll binary
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai binary
|
||||
*.la binary
|
||||
*.a binary
|
||||
*.lib binary
|
||||
|
||||
# Executables
|
||||
*.exe binary
|
||||
*.out binary
|
||||
*.app binary
|
||||
|
||||
# Binary files
|
||||
*.db binary
|
||||
*.p binary
|
||||
*.pkl binary
|
||||
*.pyc binary
|
||||
*.pyd binary
|
||||
*.pyo binary
|
||||
|
||||
# Documents
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
*.md text
|
||||
*.adoc text
|
||||
*.textile text
|
||||
*.mustache text
|
||||
*.csv text
|
||||
*.tab text
|
||||
*.tsv text
|
||||
*.sql text
|
||||
|
||||
# Graphics
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.tif binary
|
||||
*.tiff binary
|
||||
*.ico binary
|
||||
# SVG treated as an asset (binary) by default. If you want to treat it as text,
|
||||
# comment-out the following line and uncomment the line after.
|
||||
*.svg binary
|
||||
#*.svg text
|
||||
*.eps binary
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help the OpenTX team to improve OpenTX
|
||||
|
||||
---
|
||||
*Before submitting, search the open issue if there is already a report of the bug*
|
||||
|
||||
Also often minor bugs are already fixed in nightly builds, often it is
|
||||
a good idea to test (in a controlled environment like a bench setup)
|
||||
with a nightly firmware to see if the bug still exists.
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**General information**
|
||||
- OpenI6X version (e.g. 1.8.0)
|
||||
- Hardware (e.g. external module model)
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
name: Help
|
||||
about: Problems or question of using OpenTX
|
||||
|
||||
---
|
||||
|
||||
The issue tracker here is for devlopment of OpenTX. This is not a
|
||||
support site, only a bug tracking system. Please use support groups
|
||||
like [rcgroups](https://rcgroups.com/) or
|
||||
[openrcforum](https://www.openrcforums.com/forum/). See also our
|
||||
[manual](https://opentx.gitbooks.io/manual-for-opentx-2-2/).
|
||||
|
||||
For quick questions you can also join our general chat.
|
||||
|
||||
Issues that fall into the category of asking for help, will be
|
||||
generally closed as invalid without an answer.
|
||||
@@ -1,18 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project to make OpenTX even better
|
||||
|
||||
---
|
||||
*Before suggesting a new feature here, please search the open issue if there is already a request for the feature*
|
||||
|
||||
**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.
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
/.idea/
|
||||
/.*project
|
||||
/.settings
|
||||
/.autotools
|
||||
/*.user
|
||||
/*.user.*
|
||||
build*/
|
||||
cmake-build-*/
|
||||
/debian/
|
||||
/CMakeFiles/*
|
||||
radio/src/CmakeFiles/*
|
||||
/.vscode/
|
||||
*.cmake
|
||||
*.make
|
||||
*.marks
|
||||
/nbproject/
|
||||
*.bin
|
||||
/radio/src/CMakeFiles/firmware.dir/link.txt
|
||||
.push.settings.jsonc
|
||||
build.sh
|
||||
firm.sh
|
||||
flash.sh
|
||||
*.patch
|
||||
@@ -1,3 +0,0 @@
|
||||
[submodule "radio/src/thirdparty/GCS_MAVLink/include_v1.0"]
|
||||
path = radio/src/thirdparty/GCS_MAVLink/include_v1.0
|
||||
url = https://github.com/mavlink/c_library_v1.git
|
||||
@@ -1,7 +0,0 @@
|
||||
# .gitpod.yml
|
||||
image:
|
||||
file: Dockerfile
|
||||
|
||||
tasks:
|
||||
- init: echo 'Welcome!'
|
||||
- command: mkdir build && cd build
|
||||
@@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
sudo: required
|
||||
dist: trusty
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
|
||||
env:
|
||||
global:
|
||||
# - QT_BASE=53
|
||||
# - QT_BASE=54
|
||||
# - QT_BASE=55
|
||||
# - QT_BASE=56
|
||||
- QT_BASE=57
|
||||
# - GCC_ARM=/opt/gcc-arm-none-eabi/bin
|
||||
- PYTHONPATH=${PYTHONPATH}:/usr/lib/python3/dist-packages
|
||||
matrix:
|
||||
#
|
||||
# ALL will build every individual board & DEFAULT, sequentially.
|
||||
# DEFAULT is "make all" (including Companion & Simulator), with default settings
|
||||
#
|
||||
# - FLAVOR=ALL
|
||||
- FLAVOR=DEFAULT
|
||||
- FLAVOR=ARM9X
|
||||
# - FLAVOR=AR9X
|
||||
# - FLAVOR=SKY9X
|
||||
# - FLAVOR=9XRPRO
|
||||
- FLAVOR=X7
|
||||
- FLAVOR=XLITE
|
||||
- FLAVOR=X9
|
||||
# - FLAVOR=X9D
|
||||
# - FLAVOR=X9D+
|
||||
# - FLAVOR=X9E
|
||||
- FLAVOR=HORUS
|
||||
# - FLAVOR=X10
|
||||
# - FLAVOR=X12Sr10
|
||||
# - FLAVOR=X12S
|
||||
|
||||
before_install:
|
||||
- sudo add-apt-repository ppa:ubuntu-sdk-team/ppa --yes
|
||||
- sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded --yes
|
||||
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test --yes
|
||||
- if [ "$QT_BASE" = "53" ]; then sudo add-apt-repository ppa:beineri/opt-qt532-trusty -y; fi
|
||||
- if [ "$QT_BASE" = "54" ]; then sudo add-apt-repository ppa:beineri/opt-qt542-trusty -y; fi
|
||||
- if [ "$QT_BASE" = "55" ]; then sudo add-apt-repository ppa:beineri/opt-qt551-trusty -y; fi
|
||||
- if [ "$QT_BASE" = "56" ]; then sudo add-apt-repository ppa:beineri/opt-qt562-trusty -y; fi
|
||||
- if [ "$QT_BASE" = "57" ]; then sudo add-apt-repository ppa:beineri/opt-qt571-trusty -y; fi
|
||||
- sudo apt-get update -qq
|
||||
- pyenv uninstall -f 2.7.6 && pyenv install 3.5.4 && pyenv global 3.5.4
|
||||
- pip install pillow
|
||||
|
||||
install:
|
||||
- sudo apt-get --yes --force-yes install curl libmpfr4 libmpc3 libfox-1.6-dev libgtest-dev
|
||||
- sudo apt-get --yes --force-yes install gcc-arm-none-eabi
|
||||
# Trying to build with gcc-arm 4.7 isn't working because it can't find the compiler, despite adding to PATH (in commit-tests.sh) by defining GCC_ARM above
|
||||
# - wget --quiet https://launchpad.net/gcc-arm-embedded/4.7/4.7-2013-q3-update/+download/gcc-arm-none-eabi-4_7-2013q3-20130916-linux.tar.bz2
|
||||
# - tar xjf gcc-arm-none-eabi-4_7-2013q3-20130916-linux.tar.bz2
|
||||
# - mv gcc-arm-none-eabi-4_7-2013q3 /opt/gcc-arm-none-eabi
|
||||
- sudo apt-get install --yes --force-yes -qq qt${QT_BASE}base qt${QT_BASE}multimedia qt${QT_BASE}svg qt${QT_BASE}tools; source /opt/qt${QT_BASE}/bin/qt${QT_BASE}-env.sh
|
||||
|
||||
script:
|
||||
- ./tools/commit-tests.sh
|
||||
-196
@@ -1,196 +0,0 @@
|
||||
project(OpenTX)
|
||||
|
||||
set(VERSION_MAJOR "2")
|
||||
set(VERSION_MINOR "1")
|
||||
set(VERSION_REVISION "0")
|
||||
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
|
||||
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
|
||||
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX})
|
||||
set(SDCARD_REVISION "0018")
|
||||
set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
cmake_policy(SET CMP0020 NEW)
|
||||
cmake_policy(SET CMP0023 OLD)
|
||||
if(POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
endif()
|
||||
if(POLICY CMP0043)
|
||||
cmake_policy(SET CMP0043 NEW)
|
||||
endif()
|
||||
if(POLICY CMP0054)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
if(POLICY CMP0058)
|
||||
cmake_policy(SET CMP0058 NEW) # for ninja
|
||||
endif()
|
||||
|
||||
set(CMAKE_COLOR_MAKEFILE ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
set(RADIO_DIRECTORY ${PROJECT_SOURCE_DIR}/radio)
|
||||
set(RADIO_SRC_DIRECTORY ${RADIO_DIRECTORY}/src)
|
||||
set(COMPANION_SRC_DIRECTORY ${PROJECT_SOURCE_DIR}/companion/src)
|
||||
set(SIMU_SRC_DIRECTORY ${COMPANION_SRC_DIRECTORY}/simulation)
|
||||
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
|
||||
|
||||
include(Macros)
|
||||
today(DATE)
|
||||
now(TIME)
|
||||
git_id(GIT_STR)
|
||||
|
||||
message(STATUS "OpenI6X ${VERSION} @${GIT_STR}")
|
||||
|
||||
# options shared by all targets
|
||||
|
||||
option(APP_CUSTOM_DBG_HANDLER "Use custom message handler for debug output in all Qt apps." ON)
|
||||
set(APP_CUSTOM_DBG_LEVEL "0" CACHE STRING
|
||||
"Debug output level: 0=debug+; 1=info+; 2=warn+; 3=critical+; 4=fatal only.")
|
||||
set(APP_CUSTOM_DBG_SHOW_FILE "DEFAULT" CACHE STRING
|
||||
"Show source file names in debug output. 1/0/DEFAULT (default is ON with DEBUG builds).")
|
||||
|
||||
option(VERBOSE_CMAKELISTS "Show extra information while processing CMakeLists.txt files." OFF)
|
||||
option(WARNINGS_AS_ERRORS "Treat any compiler warning as an error (adds -Werror flag)." OFF)
|
||||
|
||||
if(WIN32)
|
||||
set(WIN_EXTRA_LIBS_PATH "C:/Programs" CACHE PATH
|
||||
"Base path to extra libs/headers on Windows (SDL & pthreads folders should be in here).")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${WIN_EXTRA_LIBS_PATH}" "${WIN_EXTRA_LIBS_PATH}/SDL") # hints for FindSDL
|
||||
endif()
|
||||
|
||||
# Python check
|
||||
find_package("PythonInterp")
|
||||
if(PYTHONINTERP_FOUND)
|
||||
message(STATUS "Python found, version: ${PYTHON_VERSION_STRING}")
|
||||
get_filename_component(PYTHON_DIRECTORY ${PYTHON_EXECUTABLE} DIRECTORY)
|
||||
else()
|
||||
message(WARNING "Python not found! Most firmware and simu flavors not buildable.")
|
||||
set(LUA NO)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # regular Clang or AppleClang
|
||||
set(CLANG TRUE)
|
||||
endif()
|
||||
|
||||
option(DISABLE_COMPANION "Disable building companion and simulators" OFF)
|
||||
|
||||
if(NOT DISABLE_COMPANION) # FIXME cosmetics/style
|
||||
find_package(Qt5Core)
|
||||
find_package(Qt5Widgets)
|
||||
find_package(Qt5Xml)
|
||||
find_package(Qt5LinguistTools)
|
||||
find_package(Qt5PrintSupport)
|
||||
find_package(Qt5Multimedia)
|
||||
find_package(Qt5Svg)
|
||||
|
||||
if(Qt5Core_FOUND)
|
||||
message(STATUS "Qt Version: ${Qt5Core_VERSION}")
|
||||
|
||||
### Get locations of Qt binary executables & libs (libs are for distros, not for linking)
|
||||
# first set up some hints
|
||||
get_target_property(QtCore_LOCATION Qt5::Core LOCATION)
|
||||
get_filename_component(qt_core_path ${QtCore_LOCATION} PATH)
|
||||
if(APPLE)
|
||||
get_filename_component(qt_core_path "${qt_core_path}/.." ABSOLUTE)
|
||||
endif()
|
||||
|
||||
set(QT_LIB_DIR ${qt_core_path} CACHE PATH "Path to Qt libraries (.dll|.framework|.so).")
|
||||
find_path(QT_BIN_DIR NAMES "qmake" "qmake.exe" HINTS "${CMAKE_PREFIX_PATH}/bin" "${qt_core_path}/../bin" "${qt_core_path}" DOC "Path to Qt binaries (qmake, lupdate, etc.).")
|
||||
find_program(QT_QMAKE_EXECUTABLE qmake HINTS "${QT_BIN_DIR}" DOC "Location of qmake program.")
|
||||
find_program(QT_LUPDATE_EXECUTABLE lupdate HINTS "${QT_BIN_DIR}" DOC "Location of Qt's 'lupdate' program for updating translation files.")
|
||||
|
||||
# Try to find Qt translations
|
||||
if(QT_QMAKE_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_INSTALL_TRANSLATIONS
|
||||
OUTPUT_VARIABLE qt_translations_hint
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
find_path(QT_TRANSLATIONS_DIR NAMES "qt_en.qm" HINTS "${qt_translations_hint}" DOC "Path to prebuilt Qt translations (qt_*.qm).")
|
||||
|
||||
### Common definitions for the Qt-based apps
|
||||
list(APPEND APP_COMMON_DEFINES -DSIMU)
|
||||
list(APPEND APP_COMMON_DEFINES -DQXT_STATIC)
|
||||
list(APPEND APP_COMMON_DEFINES -DQT_USE_QSTRINGBUILDER) # more efficient QString construction using % operator
|
||||
|
||||
if(MSVC)
|
||||
list(APPEND APP_COMMON_DEFINES -D__STDC_LIMIT_MACROS)
|
||||
endif()
|
||||
if(APP_CUSTOM_DBG_HANDLER)
|
||||
# provide full qDebug log context to our custom handler. This may also affect libsimulator, which is why it is here
|
||||
list(APPEND APP_COMMON_DEFINES -DQT_MESSAGELOGCONTEXT)
|
||||
list(APPEND APP_COMMON_DEFINES -DAPP_DBG_HANDLER_ENABLE=1)
|
||||
if(APP_CUSTOM_DBG_LEVEL GREATER -1 AND APP_CUSTOM_DBG_LEVEL LESS 5)
|
||||
list(APPEND APP_COMMON_DEFINES -DAPP_DBG_HANDLER_DEFAULT_LEVEL=${APP_CUSTOM_DBG_LEVEL})
|
||||
endif()
|
||||
if(NOT APP_CUSTOM_DBG_SHOW_FILE STREQUAL "DEFAULT" AND (APP_CUSTOM_DBG_SHOW_FILE STREQUAL "1" OR APP_CUSTOM_DBG_SHOW_FILE STREQUAL "0"))
|
||||
list(APPEND APP_COMMON_DEFINES -DAPP_DBG_HANDLER_SHOW_SRC_PATH=${APP_CUSTOM_DBG_SHOW_FILE})
|
||||
endif()
|
||||
else()
|
||||
list(APPEND APP_COMMON_DEFINES -DAPP_DBG_HANDLER_ENABLE=0)
|
||||
endif()
|
||||
|
||||
else()
|
||||
message(WARNING "Qt not found! Companion and Simulator builds disabled.")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
find_package(Fox QUIET) # QUIET not working on WIN32?
|
||||
if (FOX_FOUND)
|
||||
message(STATUS "Foxlib found at ${FOX_LIBRARY}")
|
||||
else() # if(NOT WIN32)
|
||||
message("Libfox not found, simu target will not be available")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(Qt5Core_FOUND OR FOX_FOUND)
|
||||
set(SDL_BUILDING_LIBRARY YES) # this prevents FindSDL from appending SDLmain lib to the results, which we don't want
|
||||
find_package("SDL")
|
||||
if(SDL_FOUND)
|
||||
message(STATUS "SDL Lib: ${SDL_LIBRARY}; Headers: ${SDL_INCLUDE_DIR}; Version: ${SDL_VERSION_STRING}")
|
||||
if (NOT ${SDL_VERSION_STRING} VERSION_LESS "2.0")
|
||||
message(FATAL_ERROR "OpenTX requires SDL 1.x, not 2.x")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "SDL not found! Simulator audio, and joystick inputs, will not work.")
|
||||
endif()
|
||||
endif()
|
||||
endif(NOT DISABLE_COMPANION)
|
||||
|
||||
# Check for a file that is typically left from a OpenTX 2.1 build and abort if found
|
||||
if (EXISTS ${RADIO_SRC_DIRECTORY}/stamp.h OR EXISTS ${RADIO_SRC_DIRECTORY}/translations/en.h)
|
||||
message(FATAL_ERROR "Source directory contains files leftover from a OpenTX 2.1 build. Please run `git clean -f` in source directory (Careful: Will remove any extra files) or do a new clean git checkout")
|
||||
endif()
|
||||
|
||||
# Windows-specific includes and libs shared by sub-projects
|
||||
if(WIN32)
|
||||
list(APPEND WIN_INCLUDE_DIRS "${RADIO_SRC_DIRECTORY}/thirdparty/windows/dirent")
|
||||
if(MSVC)
|
||||
list(APPEND WIN_INCLUDE_DIRS "${RADIO_SRC_DIRECTORY}/thirdparty/windows/msinttypes")
|
||||
set(WIN_PTHREAD_BASE_PATH "${WIN_EXTRA_LIBS_PATH}/pthreads/Pre-built.2" CACHE PATH "Where to find pthreads include and lib folders.")
|
||||
list(APPEND WIN_INCLUDE_DIRS "${WIN_PTHREAD_BASE_PATH}/include")
|
||||
find_file(WIN_PTHREAD_LIB pthreadVC2.lib PATHS "${WIN_PTHREAD_BASE_PATH}" PATH_SUFFIXES lib/x86 lib NO_DEFAULT_PATH)
|
||||
find_file(WIN_PTHREAD_DLL pthreadVC2.dll PATHS "${WIN_PTHREAD_BASE_PATH}" PATH_SUFFIXES lib/x86 lib dll/x86 dll NO_DEFAULT_PATH)
|
||||
if(WIN_PTHREAD_LIB)
|
||||
list(APPEND WIN_LINK_LIBRARIES "${WIN_PTHREAD_LIB}")
|
||||
else()
|
||||
message(SEND_ERROR "pthreadVC2.lib not found!")
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES OFF)
|
||||
set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES OFF)
|
||||
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES OFF)
|
||||
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(${RADIO_SRC_DIRECTORY})
|
||||
|
||||
if(Qt5Core_FOUND AND NOT DISABLE_COMPANION)
|
||||
add_subdirectory(${COMPANION_SRC_DIRECTORY})
|
||||
endif()
|
||||
-1493
File diff suppressed because it is too large
Load Diff
-46
@@ -1,46 +0,0 @@
|
||||
# Dockerfile
|
||||
FROM archlinux:base
|
||||
RUN pacman -Syu --noconfirm
|
||||
|
||||
# Install misc packages
|
||||
RUN pacman -S --noconfirm \
|
||||
7zip \
|
||||
arm-none-eabi-gcc \
|
||||
arm-none-eabi-newlib \
|
||||
base-devel \
|
||||
bc \
|
||||
cmake \
|
||||
cpio \
|
||||
curl \
|
||||
dos2unix \
|
||||
erofs-utils \
|
||||
git \
|
||||
less \
|
||||
nano \
|
||||
python \
|
||||
python-pip \
|
||||
python-pilkit \
|
||||
screen \
|
||||
tree \
|
||||
unzip \
|
||||
vim \
|
||||
wget \
|
||||
zip
|
||||
|
||||
# HACK: Allow base-devel to run with root user
|
||||
RUN sed -i '/E_ROOT/d' /usr/bin/makepkg
|
||||
|
||||
# Install yay
|
||||
RUN git clone https://aur.archlinux.org/yay-bin.git /tmp/yay-bin && \
|
||||
cd /tmp/yay-bin && \
|
||||
makepkg -si --noconfirm && \
|
||||
cd && rm -rf /tmp/yay-bin
|
||||
|
||||
#RUN git clone --recursive https://github.com/STMicroelectronics/STM32CubeG0.git /workspace/STM32CubeG0
|
||||
#RUN git clone --recursive https://github.com/STMicroelectronics/STM32CubeG4.git /workspace/STM32CubeG4
|
||||
|
||||
# Personal dir dotfiles
|
||||
#ADD home /home/
|
||||
|
||||
# Personal uploader scripts
|
||||
#ADD root/bin /usr/local/bin/
|
||||
@@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
@@ -1,59 +0,0 @@
|
||||
[](https://github.com/OpenI6X/opentx/releases/latest)
|
||||
[](https://github.com/OpenI6X/opentx/releases)
|
||||
[](https://github.com/openi6x/opentx/blob/master/LICENSE)
|
||||

|
||||
[](https://gitpod.io/#https://github.com/openi6x/opentx/tree/master)
|
||||
[](https://discord.gg/3vKfYNTVa2)
|
||||
|
||||

|
||||
|
||||
# Custom OpenTX / EdgeTX for Flysky FS-i6X
|
||||
|
||||
Join our [Discord](https://discord.gg/3vKfYNTVa2), [RCGroups](https://www.rcgroups.com/forums/showthread.php?3916435-FlySky-I6X-port-of-OpenTX) or [Telegram](https://t.me/otx_flysky_i6x) to contribute, discuss or get help.<br>
|
||||
|
||||
## Instructions
|
||||
|
||||
- [FlySky i6X user interface](https://github.com/OpenI6X/opentx/wiki/Manual) and other differences to official EdgeTX/OpenTX devices.<br>
|
||||
- [EdgeTX manual](https://manual.edgetx.org/bw-radios)
|
||||
- [How to install, upgrade or restore firmware](https://github.com/OpenI6X/opentx/wiki/Flashing-&-Upgrading)<br>
|
||||
- [Developers guide, how to build](https://github.com/OpenI6X/opentx/wiki/Development)<br>
|
||||
- [Modifications](https://github.com/OpenI6X/opentx/wiki/Modifications)<br>
|
||||
|
||||
## Comparison
|
||||
|
||||
| Feature | FlySky i6X | OpenI6X |
|
||||
|---------------------------|------------|------------------------------|
|
||||
| Channels | 6/10 | 16 |
|
||||
| Mixers | 3 | 32 |
|
||||
| Models | 20 | 20 / unlimited<sup>[1]</sup> |
|
||||
| Protocols | AFHDS, AFHDS2A, PPM | AFHDS2A + 16Ch modes, PPM, CRSF |
|
||||
| Trainer | PPM | PPM, SBUS |
|
||||
| Timers | _ | ✓ |
|
||||
| Voice annoucements | _ | ✓<sup>[2]</sup> |
|
||||
| Variometer | _ | ✓ |
|
||||
| ExpressLRS ready | _ | ✓ Configurator built-in (no need for LUA) |
|
||||
| Adjustable screen brightness | _ | ✓<sup>[3]</sup> |
|
||||
| USB Modes | Joystick | Joystick, Storage, Serial (Telemetry mirror, Debug) |
|
||||
| AUX Serial port | _ | ✓ SBUS Trainer, Telemetry mirror, Debug |
|
||||
| FlySky FS-HZCZ03-ADJ Gimbal support | _ | ✓<sup>[4]</sup> |
|
||||
| Languages | EN, CN | PL, EN, CZ, DE, ES, FI, FR, IT, NL, PT, SE |
|
||||
|
||||
<sub>[1] Unlimited by using USB mass storage mode eeprom backup/restore.</sub><br>
|
||||
<sub>[2] By adding DFPlayer, see [instructions](https://github.com/OpenI6X/opentx/wiki/Modifications#dfplayer) in wiki.</sub><br>
|
||||
<sub>[3] By wiring 2 pads, see [instructions](https://github.com/OpenI6X/opentx/wiki/Modifications#adjustable-backlight-level) in wiki.</sub><br>
|
||||
<sub>[4] See [instructions](https://github.com/OpenI6X/opentx/wiki/Modifications#flysky-fs-hzcz03-adj-gimbal) in wiki.</sub>
|
||||
|
||||
## Credits
|
||||
|
||||
* Janek ([ajjjjjjjj](https://github.com/ajjjjjjjj)), continues Kuba's and Mariano's work, added sound, USB, ExpressLRS V2/V3 configuration, telemetry mirror, SBUS trainer, new/fixed drivers, ports, bugfixes.
|
||||
* Mariano ([marianomd](https://github.com/marianomd)), continued Kuba's work and made it up to useable condition! Added gimbals, buttons, AFHDS2A, PPM, CRSF.
|
||||
* Kuba ([qba667](https://github.com/qba667)), started this work and made this project possible, it is forked from his repo.
|
||||
* Wilhelm ([wimalopaan](https://github.com/wimalopaan)) added 16 channels SBUS16 / IBUS16 modes.
|
||||
* Rafael ([rafolg](https://github.com/rafolg)), ported FlySky Hall Gimbal support from EdgeTX.
|
||||
* Tom ([tmcadam](https://github.com/tmcadam)) fixed AFHDS2A PWM mode selection.
|
||||
* The internal RF code was taken from the great KotelloRC's [erfly6: Er9X for i6 and i6x](https://bitbucket.org/KotelloRC/erfly6/src/master/).
|
||||
* Some of the internal RF fixes are a result of analysing [pascallanger's](https://github.com/pascallanger) [DIY-Multiprotocol-TX-Module](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module).
|
||||
* ExpressLRS configurator is based on elrsV2/V3.lua from [ExpressLRS](https://github.com/ExpressLRS/ExpressLRS).
|
||||
* Some of the ports are from [EdgeTX](https://github.com/EdgeTX/edgetx/).
|
||||
* ADC code taken from [OpenGround](https://github.com/fishpepper/OpenGround).
|
||||
* All the contributors of [OpenTX](https://github.com/opentx/opentx/).
|
||||
@@ -0,0 +1,5 @@
|
||||
TODO list (no particular order)
|
||||
|
||||
- DSM2 channel order (Cam)
|
||||
- Variometer (rate as cm/sec)
|
||||
- Trace telemetry data
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
******************************************
|
||||
CHANGELOG: 07-05-2012 BSS
|
||||
AutoSwitch feature added
|
||||
Mix Warning was not so regular (sometime 2 ticks instead of 3)
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 06-05-2012 BSS
|
||||
FW options now stored in a byte of the EEPROM
|
||||
[Arm] getSwitch() problem with Custom Switches
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 05-05-2012 BSS
|
||||
[FrSky] Speed in Gauges configuration was buggy
|
||||
[FrSky] We stored Min Speed instead of Max Speed
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 04-05-2012 BSS
|
||||
Momentary Switches in Function Switches
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 03-05-2012 BSS
|
||||
[Arm] Audio / Haptic refactoring
|
||||
[Arm] Timer blocked at 10:55
|
||||
[V4] SDcard menu reworked
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 02-05-2012 BSS
|
||||
[V4/Arm] Problem in Models Move
|
||||
[stock] Flash saving (840bytes)
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 01-05-2012 BSS
|
||||
[FrSky] GPS distance bug fix
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 29-04-2012 BSS
|
||||
[V4/Arm] EEPROM marked as dirty on reboot
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 27-04-2012 BSS
|
||||
Vario feature added
|
||||
New EEPROM format 205
|
||||
[FrSky] Telemetry offset for A1/A2 on 12bits
|
||||
[V4] Models with empty name bug when SDcard backup
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 26-04-2012 BSS
|
||||
[Arm] 32Channels 9Phases 64Mixes 32Expos 32VSwitches 32FSwitches
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 23-04-2012 BSS
|
||||
[V4] SDcard Models storage implemented
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 20-04-2012 BSS
|
||||
[Stock] 400bytes flash saving
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 15-03-2012 BSS
|
||||
FAAST option in protocol to enable startPulses before the splash screen
|
||||
Telemetry configurable screen
|
||||
Confirmation before applying templates
|
||||
Used channels cleaned before applying a template
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 14-03-2012 BSS
|
||||
Potscroll option added
|
||||
|
||||
******************************************
|
||||
|
||||
Version 364:
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 04-03-2012 BSS
|
||||
New EEPROM format 205
|
||||
Introduction of differential in Mixers
|
||||
Introduction of Switches as Mixer Source (FULL now removed)
|
||||
Negative curves in Mixers
|
||||
Optimizations in Mixer
|
||||
Extended chars for localization
|
||||
Swedish translations
|
||||
Beep length updated
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 01-03-2012 BSS
|
||||
Feature "Use THR trim as a slider" now finished
|
||||
[FrSky] Jitter (2us) introduced by last optimization removed
|
||||
Trim parameter in Mixer is OFF if the source is not a stick
|
||||
GPS distance fixed
|
||||
|
||||
******************************************
|
||||
|
||||
Version 304:
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 28-02-2012 BSS
|
||||
Flash saving (600bytes)
|
||||
[FrSky] NO DATA displayed on the status line when nothing received
|
||||
Sticks/Pots center beep now more accurate
|
||||
Beeps length for center beep and inactivity reduced
|
||||
Vibration when MIN/MID/MAX trim position reached
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 27-02-2012 BSS
|
||||
Flash saving (idea from er9x)
|
||||
Trims2Offsets function removed
|
||||
A "Safety CHxx" function is not applied when it is currently edited
|
||||
The Stick Mode needs confirmation before being applied
|
||||
|
||||
******************************************
|
||||
|
||||
Version 288:
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 24-02-2012 BSS
|
||||
Throttle Trace bug solved when using P1-P3
|
||||
New way of dealing with recursive mixers in Flight Phases (with FadeIn / FadeOut)
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 23-02-2012 BSS
|
||||
PXX updates + optimizations pulled from er9x
|
||||
FrSky TELEMETRY menu is now moved to [DOWN long]
|
||||
Optimizations
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 22-02-2012 BSS
|
||||
Blades count may now be 4
|
||||
V4: New mixers/expos fields inflight modifiable through RE1
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 21-02-2012 BSS
|
||||
V4: Logs format ported from gruvin9x
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 20-02-2012 BSS
|
||||
Last GPS coords displayed even when streaming stops (model lost)
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 19-02-2012 BSS
|
||||
V4: Inflight fields modification through RE1 feature added
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 17-02-2012 BSS
|
||||
RSSI thresholds on a per model basis
|
||||
Flash Saving
|
||||
FrSky Hub variometer + cells voltage fix
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 16-02-2012 BSS
|
||||
Beeper mode splitted from Beeper length
|
||||
Haptic redesigned
|
||||
No FrSky alarms when Tx asked to be quiet
|
||||
Flash Saving
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 14-02-2012 BSS
|
||||
Blades count configuration for RPMs
|
||||
Instant trim bug fixed for stick modes != RETA
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 1O-02-2012 BSS
|
||||
Copyright updated
|
||||
GPS distance and speed bug fixes
|
||||
|
||||
******************************************
|
||||
|
||||
Version 232:
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 09-02-2012 BSS
|
||||
Multiplier added for telemetry A1/A2 => 204.0v!
|
||||
GPS distance added
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 08-02-2012 BSS
|
||||
Telemetry bars screen
|
||||
Add individual cell voltages from FrSky Hub 2.0
|
||||
New units for A1/A2
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 06-02-2012 BSS
|
||||
Flash saving
|
||||
Telemetry screens redesigned
|
||||
|
||||
******************************************
|
||||
|
||||
Version 213:
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 05-02-2012 BSS
|
||||
Add GPS speed display, with max speed
|
||||
GPS screen redesigned
|
||||
|
||||
******************************************
|
||||
|
||||
Version 205:
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 04-02-2012 BSS
|
||||
New way of configuring A1 and A2 using Range and Offset
|
||||
Named sounds in Func Switches
|
||||
Haptic only sounds skipped when HAPTIC option disable
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 03-02-2012 BSS
|
||||
Safety switches screen removed (moved to Func Switches)
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 02-02-2012 BSS
|
||||
French translations updated
|
||||
AUDIO optimizations
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 01-02-2012 BSS
|
||||
AUDIO and HAPTIC may be enabled separately
|
||||
AUDIO bug fixes
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 31-01-2012 BSS
|
||||
HAPTIC now working
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 29-01-2012 BSS
|
||||
Inactivity timer reset on Keys and Trims press
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 28-01-2012 BSS
|
||||
New splash
|
||||
|
||||
******************************************
|
||||
CHANGELOG: 27-01-2012 BSS
|
||||
NMEA and ARDUPILOT ported from er9x
|
||||
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
macro(add_bitmaps_target targetname filter width format)
|
||||
set(bitmaps_files)
|
||||
file(GLOB bitmaps ${filter})
|
||||
foreach(bitmap ${bitmaps})
|
||||
get_filename_component(target ${bitmap} NAME_WE)
|
||||
set(target ${target}.lbm)
|
||||
add_custom_command(
|
||||
OUTPUT ${target}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/img2lbm.py ${bitmap} ${target} ${width} ${format} ${ARGN}
|
||||
DEPENDS ${bitmap}
|
||||
)
|
||||
list(APPEND bitmaps_files ${target})
|
||||
endforeach()
|
||||
add_custom_target(${targetname} DEPENDS ${bitmaps_files})
|
||||
endmacro(add_bitmaps_target)
|
||||
|
||||
macro(add_truetype_font_target radio name font size offset)
|
||||
set(target ${RADIO_SRC_DIRECTORY}/fonts/${radio}/font_${name})
|
||||
add_custom_target(ttf_${radio}_${name}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/font2png.py ${font} ${size} ${offset} ${target}
|
||||
WORKING_DIRECTORY ${RADIO_SRC_DIRECTORY}
|
||||
)
|
||||
set(ttf_${radio}_fonts_targets ${ttf_${radio}_fonts_targets} ttf_${radio}_${name})
|
||||
endmacro(add_truetype_font_target)
|
||||
@@ -1,63 +0,0 @@
|
||||
# Imported from the DeskVox project (LPGL 2.1)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
set(hints
|
||||
$ENV{LIB_BASE_PATH}/fox
|
||||
)
|
||||
|
||||
set(paths
|
||||
/usr
|
||||
/usr/local
|
||||
)
|
||||
|
||||
find_path(FOX_INCLUDE_DIR
|
||||
NAMES
|
||||
fx.h
|
||||
HINTS
|
||||
${hints}
|
||||
PATHS
|
||||
${paths}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
include/fox
|
||||
include/fox-1.6
|
||||
)
|
||||
|
||||
find_library(FOX_LIBRARY
|
||||
NAMES
|
||||
FOX-1.6
|
||||
fox-1.6
|
||||
HINTS
|
||||
${hints}
|
||||
PATHS
|
||||
${paths}
|
||||
PATH_SUFFIXES
|
||||
lib64
|
||||
lib
|
||||
)
|
||||
|
||||
find_library(FOX_LIBRARY_DEBUG
|
||||
NAMES
|
||||
FOXD-1.6
|
||||
foxd-1.6
|
||||
HINTS
|
||||
${hints}
|
||||
PATHS
|
||||
${paths}
|
||||
PATH_SUFFIXES
|
||||
lib64
|
||||
lib
|
||||
)
|
||||
|
||||
if(FOX_LIBRARY_DEBUG)
|
||||
set(FOX_LIBRARIES optimized ${FOX_LIBRARY} debug ${FOX_LIBRARY_DEBUG})
|
||||
else()
|
||||
set(FOX_LIBRARIES ${FOX_LIBRARY})
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(FOX
|
||||
DEFAULT_MSG
|
||||
FOX_INCLUDE_DIR
|
||||
FOX_LIBRARY
|
||||
)
|
||||
@@ -1,71 +0,0 @@
|
||||
# Find libphonon
|
||||
# Once done this will define
|
||||
#
|
||||
# PHONON_FOUND - system has Phonon Library
|
||||
# PHONON_INCLUDES - the Phonon include directory
|
||||
# PHONON_LIBS - link these to use Phonon
|
||||
# PHONON_VERSION - the version of the Phonon Library
|
||||
|
||||
# Copyright (c) 2008, Matthias Kretz <kretz@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
macro(_phonon_find_version)
|
||||
set(_phonon_namespace_header_file "${PHONON_INCLUDE_DIR}/phonon/phononnamespace.h")
|
||||
if (APPLE AND EXISTS "${PHONON_INCLUDE_DIR}/Headers/phononnamespace.h")
|
||||
set(_phonon_namespace_header_file "${PHONON_INCLUDE_DIR}/Headers/phononnamespace.h")
|
||||
endif (APPLE AND EXISTS "${PHONON_INCLUDE_DIR}/Headers/phononnamespace.h")
|
||||
file(READ ${_phonon_namespace_header_file} _phonon_header LIMIT 5000 OFFSET 1000)
|
||||
string(REGEX MATCH "define PHONON_VERSION_STR \"(4\\.[0-9]+\\.[0-9a-z]+)\"" _phonon_version_match "${_phonon_header}")
|
||||
set(PHONON_VERSION "${CMAKE_MATCH_1}")
|
||||
message(STATUS "Phonon Version: ${PHONON_VERSION}")
|
||||
endmacro(_phonon_find_version)
|
||||
|
||||
if(PHONON_FOUND)
|
||||
# Already found, nothing more to do except figuring out the version
|
||||
_phonon_find_version()
|
||||
else(PHONON_FOUND)
|
||||
if(PHONON_INCLUDE_DIR AND PHONON_LIBRARY)
|
||||
set(PHONON_FIND_QUIETLY TRUE)
|
||||
endif(PHONON_INCLUDE_DIR AND PHONON_LIBRARY)
|
||||
|
||||
# As discussed on kde-buildsystem: first look at CMAKE_PREFIX_PATH, then at the suggested PATHS (kde4 install dir)
|
||||
find_library(PHONON_LIBRARY NAMES phonon phonon4 PATHS ${KDE4_LIB_INSTALL_DIR} ${QT_LIBRARY_DIR} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH)
|
||||
# then at the default system locations (CMAKE_SYSTEM_PREFIX_PATH, i.e. /usr etc.)
|
||||
find_library(PHONON_LIBRARY NAMES phonon)
|
||||
|
||||
find_path(PHONON_INCLUDE_DIR NAMES phonon/phonon_export.h PATHS ${KDE4_INCLUDE_INSTALL_DIR} ${QT_INCLUDE_DIR} ${INCLUDE_INSTALL_DIR} ${QT_LIBRARY_DIR} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH)
|
||||
find_path(PHONON_INCLUDE_DIR NAMES phonon/phonon_export.h)
|
||||
|
||||
if(PHONON_INCLUDE_DIR AND PHONON_LIBRARY)
|
||||
set(PHONON_LIBS ${phonon_LIB_DEPENDS} ${PHONON_LIBRARY})
|
||||
set(PHONON_INCLUDES ${PHONON_INCLUDE_DIR}/KDE ${PHONON_INCLUDE_DIR})
|
||||
set(PHONON_FOUND TRUE)
|
||||
_phonon_find_version()
|
||||
else(PHONON_INCLUDE_DIR AND PHONON_LIBRARY)
|
||||
set(PHONON_FOUND FALSE)
|
||||
endif(PHONON_INCLUDE_DIR AND PHONON_LIBRARY)
|
||||
|
||||
if(PHONON_FOUND)
|
||||
if(NOT PHONON_FIND_QUIETLY)
|
||||
message(STATUS "Found Phonon: ${PHONON_LIBRARY}")
|
||||
message(STATUS "Found Phonon Includes: ${PHONON_INCLUDES}")
|
||||
endif(NOT PHONON_FIND_QUIETLY)
|
||||
else(PHONON_FOUND)
|
||||
if(Phonon_FIND_REQUIRED)
|
||||
if(NOT PHONON_INCLUDE_DIR)
|
||||
message(STATUS "Phonon includes NOT found!")
|
||||
endif(NOT PHONON_INCLUDE_DIR)
|
||||
if(NOT PHONON_LIBRARY)
|
||||
message(STATUS "Phonon library NOT found!")
|
||||
endif(NOT PHONON_LIBRARY)
|
||||
message(FATAL_ERROR "Phonon library or includes NOT found!")
|
||||
else(Phonon_FIND_REQUIRED)
|
||||
message(STATUS "Unable to find Phonon")
|
||||
endif(Phonon_FIND_REQUIRED)
|
||||
endif(PHONON_FOUND)
|
||||
|
||||
|
||||
mark_as_advanced(PHONON_INCLUDE_DIR PHONON_LIBRARY PHONON_INCLUDES)
|
||||
endif(PHONON_FOUND)
|
||||
@@ -1,256 +0,0 @@
|
||||
#.rst:
|
||||
# FindSDL
|
||||
# -------
|
||||
#
|
||||
# Locate SDL library
|
||||
#
|
||||
# This module defines
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# SDL_FOUND, if false, do not try to link to SDL
|
||||
# SDL_LIBRARY, the name(s) of the library(ies) to link against
|
||||
# SDL_LIBSDL, the full path and name of libSDL (or SDL.[lib|dll].
|
||||
# SDL_LIBSDLMAIN, full path and name of libSDLmain (or SDLmain.lib).
|
||||
# SDL_LIBRARY_PATH, the full path to the found libSDL
|
||||
# SDL_INCLUDE_DIR, where to find SDL.h
|
||||
# SDL_VERSION_STRING, human-readable string containing the version of SDL
|
||||
#
|
||||
#
|
||||
#
|
||||
# This module responds to the flag:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# SDL_BUILDING_LIBRARY
|
||||
# If this is defined, then no SDL_main will be linked in because
|
||||
# only applications need main().
|
||||
# Otherwise, it is assumed you are building an application and this
|
||||
# module will attempt to locate and set the proper link flags
|
||||
# as part of the returned SDL_LIBRARY variable.
|
||||
#
|
||||
#
|
||||
#
|
||||
# Don't forget to include SDLmain.h and SDLmain.m your project for the
|
||||
# OS X framework based version. (Other versions link to -lSDLmain which
|
||||
# this module will try to find on your behalf.) Also for OS X, this
|
||||
# module will automatically add the -framework Cocoa on your behalf.
|
||||
#
|
||||
#
|
||||
#
|
||||
# Additional Note: If you see an empty SDL_LIBSDL in your
|
||||
# configuration and no SDL_LIBRARY, it means CMake did not find your SDL
|
||||
# library (SDL.dll, libsdl.so, SDL.framework, etc). Set
|
||||
# SDL_LIBSDL to point to your SDL library, and configure again.
|
||||
# Similarly, if you see an empty SDL_LIBSDLMAIN, you should set this
|
||||
# value as appropriate. These values are used to generate the final
|
||||
# SDL_LIBRARY variable, but when these values are unset, SDL_LIBRARY
|
||||
# does not get created.
|
||||
#
|
||||
#
|
||||
#
|
||||
# $SDLDIR is an environment variable that would correspond to the
|
||||
# ./configure --prefix=$SDLDIR used in building SDL. l.e.galup 9-20-02
|
||||
#
|
||||
# Modified by Eric Wing. Added code to assist with automated building
|
||||
# by using environmental variables and providing a more
|
||||
# controlled/consistent search behavior. Added new modifications to
|
||||
# recognize OS X frameworks and additional Unix paths (FreeBSD, etc).
|
||||
# Also corrected the header search path to follow "proper" SDL
|
||||
# guidelines. Added a search for SDLmain which is needed by some
|
||||
# platforms. Added a search for threads which is needed by some
|
||||
# platforms. Added needed compile switches for MinGW.
|
||||
#
|
||||
# On OSX, this will prefer the Framework version (if found) over others.
|
||||
# People will have to manually change the cache values of SDL_LIBRARY to
|
||||
# override this selection or set the CMake environment
|
||||
# CMAKE_INCLUDE_PATH to modify the search paths.
|
||||
#
|
||||
# Note that the header path has changed from SDL/SDL.h to just SDL.h
|
||||
# This needed to change because "proper" SDL convention is #include
|
||||
# "SDL.h", not <SDL/SDL.h>. This is done for portability reasons
|
||||
# because not all systems place things in SDL/ (see FreeBSD).
|
||||
|
||||
#
|
||||
# Modified for OpenTx by Maxim Paperno 19-Dec-2016
|
||||
# Added SDL_LIBSDL, SDL_LIBSDLMAIN & SDL_LIBRARY_PATH, removed SDLMAIN_LIBRARY,
|
||||
# SDL_LIBRARY_TEMP, and fixed bug with recursive appending of supporting
|
||||
# libraries to cached SDL_LIBRARY_TEMP variable.
|
||||
#
|
||||
|
||||
#=============================================================================
|
||||
#CMake - Cross Platform Makefile Generator
|
||||
#Copyright 2000-2015 Kitware, Inc.
|
||||
#Copyright 2000-2011 Insight Software Consortium
|
||||
#All rights reserved.
|
||||
#
|
||||
#Redistribution and use in source and binary forms, with or without
|
||||
#modification, are permitted provided that the following conditions
|
||||
#are met:
|
||||
#
|
||||
#* Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
#* Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
#* Neither the names of Kitware, Inc., the Insight Software Consortium,
|
||||
# nor the names of their contributors may be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
#"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
#LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
#A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
#HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
#SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
#LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
#DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
#THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
#The above copyright and license notice applies to distributions of
|
||||
#CMake in source and binary form. Some source files contain additional
|
||||
#notices of original copyright by their contributors; see each source
|
||||
#for details. Third-party software packages supplied with CMake under
|
||||
#compatible licenses provide their own copyright notices documented in
|
||||
#corresponding subdirectories.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
#CMake was initially developed by Kitware with the following sponsorship:
|
||||
#
|
||||
# * National Library of Medicine at the National Institutes of Health
|
||||
# as part of the Insight Segmentation and Registration Toolkit (ITK).
|
||||
#
|
||||
# * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel
|
||||
# Visualization Initiative.
|
||||
#
|
||||
# * National Alliance for Medical Image Computing (NAMIC) is funded by the
|
||||
# National Institutes of Health through the NIH Roadmap for Medical Research,
|
||||
# Grant U54 EB005149.
|
||||
#
|
||||
# * Kitware, Inc.
|
||||
#=============================================================================
|
||||
|
||||
|
||||
find_path(SDL_INCLUDE_DIR SDL.h
|
||||
HINTS
|
||||
ENV SDLDIR
|
||||
PATH_SUFFIXES SDL SDL12 SDL11
|
||||
# path suffixes to search inside ENV{SDLDIR}
|
||||
include/SDL include/SDL12 include/SDL11 include
|
||||
)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(VC_LIB_PATH_SUFFIX lib/x64)
|
||||
else()
|
||||
set(VC_LIB_PATH_SUFFIX lib/x86)
|
||||
endif()
|
||||
|
||||
# SDL-1.1 is the name used by FreeBSD ports...
|
||||
# don't confuse it for the version number.
|
||||
find_library(SDL_LIBSDL
|
||||
NAMES SDL SDL-1.1
|
||||
HINTS
|
||||
ENV SDLDIR
|
||||
PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
|
||||
)
|
||||
|
||||
# Non-OS X framework versions expect you to also dynamically link to
|
||||
# SDLmain. This is mainly for Windows and OS X. Other (Unix) platforms
|
||||
# seem to provide SDLmain for compatibility even though they don't
|
||||
# necessarily need it.
|
||||
find_library(SDL_LIBSDLMAIN
|
||||
NAMES SDLmain SDLmain-1.1
|
||||
HINTS
|
||||
ENV SDLDIR
|
||||
PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
|
||||
PATHS
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
)
|
||||
|
||||
# SDL may require threads on your system.
|
||||
# The Apple build may not need an explicit flag because one of the
|
||||
# frameworks may already provide it.
|
||||
# But for non-OSX systems, I will use the CMake Threads package.
|
||||
if(NOT APPLE)
|
||||
find_package(Threads)
|
||||
endif()
|
||||
|
||||
# MinGW needs an additional library, mwindows
|
||||
# It's total link flags should look like -lmingw32 -lSDLmain -lSDL
|
||||
if(MINGW)
|
||||
set(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
|
||||
endif()
|
||||
|
||||
if(SDL_LIBSDL)
|
||||
# For SDLmain
|
||||
if(SDL_LIBSDLMAIN AND NOT SDL_BUILDING_LIBRARY AND NOT SDL_INCLUDE_DIR MATCHES ".framework")
|
||||
list(FIND SDL_LIBSDL "${SDL_LIBSDLMAIN}" _SDL_MAIN_INDEX)
|
||||
if(_SDL_MAIN_INDEX EQUAL -1)
|
||||
list(APPEND _SDL_LIBRARY_TEMP "${SDL_LIBSDLMAIN}")
|
||||
endif()
|
||||
unset(_SDL_MAIN_INDEX)
|
||||
endif()
|
||||
|
||||
list(APPEND _SDL_LIBRARY_TEMP "${SDL_LIBSDL}")
|
||||
|
||||
# For OS X, SDL uses Cocoa as a backend so it must link to Cocoa.
|
||||
# CMake doesn't display the -framework Cocoa string in the UI even
|
||||
# though it actually is there if I modify a pre-used variable.
|
||||
# I think it has something to do with the CACHE STRING.
|
||||
# So I use a temporary variable until the end so I can set the
|
||||
# "real" variable in one-shot.
|
||||
if(APPLE)
|
||||
list(APPEND _SDL_LIBRARY_TEMP "-framework Cocoa")
|
||||
endif()
|
||||
|
||||
if(Threads_FOUND)
|
||||
list(APPEND _SDL_LIBRARY_TEMP ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
# MinGW needs an additional library, mwindows
|
||||
# It's total link flags should look like -lmingw32 -lSDLmain -lSDL
|
||||
if(MINGW)
|
||||
list(INSERT 0 _SDL_LIBRARY_TEMP mingw32)
|
||||
endif()
|
||||
|
||||
# Set the final string here so the GUI reflects the final state.
|
||||
set(SDL_LIBRARY ${_SDL_LIBRARY_TEMP} CACHE STRING "Full list of required SDL & supporting libraries.")
|
||||
unset(_SDL_LIBRARY_TEMP)
|
||||
|
||||
get_filename_component(_SDL_LIBRARY_TEMP ${SDL_LIBSDL} PATH)
|
||||
set(SDL_LIBRARY_PATH ${_SDL_LIBRARY_TEMP} CACHE PATH "Path to SDL library.")
|
||||
unset(_SDL_LIBRARY_TEMP)
|
||||
endif()
|
||||
|
||||
if(SDL_INCLUDE_DIR AND EXISTS "${SDL_INCLUDE_DIR}/SDL_version.h")
|
||||
file(STRINGS "${SDL_INCLUDE_DIR}/SDL_version.h" SDL_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+$")
|
||||
file(STRINGS "${SDL_INCLUDE_DIR}/SDL_version.h" SDL_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+$")
|
||||
file(STRINGS "${SDL_INCLUDE_DIR}/SDL_version.h" SDL_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+$")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL_VERSION_MAJOR "${SDL_VERSION_MAJOR_LINE}")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL_VERSION_MINOR "${SDL_VERSION_MINOR_LINE}")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL_VERSION_PATCH "${SDL_VERSION_PATCH_LINE}")
|
||||
set(SDL_VERSION_STRING ${SDL_VERSION_MAJOR}.${SDL_VERSION_MINOR}.${SDL_VERSION_PATCH})
|
||||
unset(SDL_VERSION_MAJOR_LINE)
|
||||
unset(SDL_VERSION_MINOR_LINE)
|
||||
unset(SDL_VERSION_PATCH_LINE)
|
||||
unset(SDL_VERSION_MAJOR)
|
||||
unset(SDL_VERSION_MINOR)
|
||||
unset(SDL_VERSION_PATCH)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL
|
||||
REQUIRED_VARS SDL_LIBRARY SDL_LIBRARY_PATH SDL_INCLUDE_DIR
|
||||
VERSION_VAR SDL_VERSION_STRING)
|
||||
@@ -1,68 +0,0 @@
|
||||
# Find Xerces-C
|
||||
# The following setings are defined
|
||||
# XERCESC_ROOT_DIR, the root of the include and lib directory
|
||||
# XERCESC_INCLUDE_DIR, the full path of the include dir (ADVANCED)
|
||||
# XERCESC_LIBRARIES, the name of the xerces-c library (ADVANCED)
|
||||
|
||||
# Look for a root installation
|
||||
IF( MSVC )
|
||||
SET( XERCES_WINDIR C:/Programs/xerces-vc )
|
||||
ELSE( )
|
||||
SET( XERCES_WINDIR C:/Programs/xerces )
|
||||
ENDIF( )
|
||||
|
||||
FIND_PATH(XERCESC_ROOT_DIR include/xercesc/parsers/SAXParser.hpp
|
||||
${XERCES_WINDIR}
|
||||
"C:/mingw/msys/1.0/local"
|
||||
"C:/Program Files/CodeSynthesis XSD 3.2"
|
||||
/usr
|
||||
/usr/local
|
||||
"C:/MinGW"
|
||||
$ENV{CODESYNTH}
|
||||
DOC "The root of an installed xerces-c installation"
|
||||
)
|
||||
|
||||
# try to find the header
|
||||
FIND_PATH(XERCESC_INCLUDE_DIR xercesc/parsers/SAXParser.hpp
|
||||
${XERCESC_ROOT_DIR}/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
)
|
||||
|
||||
# Find the library
|
||||
FIND_LIBRARY(XERCESC_LIBRARY
|
||||
NAMES xerces-c xerces-c_3
|
||||
PATHS
|
||||
${XERCESC_ROOT_DIR}/lib
|
||||
${XERCESC_ROOT_DIR}/lib/vc-9.0
|
||||
${XERCESC_ROOT_DIR}/lib64/vc-9.0
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
DOC "The name of the xerces-c library"
|
||||
)
|
||||
|
||||
IF (XERCESC_ROOT_DIR)
|
||||
IF (XERCESC_INCLUDE_DIR AND XERCESC_LIBRARY)
|
||||
SET (XERCESC_FOUND TRUE)
|
||||
SET (XERCESC_LIBRARIES "${XERCESC_LIBRARY}")
|
||||
# FIXME: There should be a better way of handling this?
|
||||
# FIXME: How can we test to see if the lib dir isn't
|
||||
# FIXME: one of the default dirs?
|
||||
LINK_DIRECTORIES(${XERCESC_ROOT_DIR}/lib)
|
||||
ENDIF (XERCESC_INCLUDE_DIR AND XERCESC_LIBRARY)
|
||||
ENDIF (XERCESC_ROOT_DIR)
|
||||
|
||||
IF (XERCESC_FOUND)
|
||||
IF (NOT XERCESC_FIND_QUIETLY)
|
||||
MESSAGE (STATUS " found xerces-c: ${XERCESC_LIBRARY}")
|
||||
ENDIF (NOT XERCESC_FIND_QUIETLY)
|
||||
ELSE (XERCESC_FOUND)
|
||||
IF (XERCESC_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find Xerces-C")
|
||||
ENDIF (XERCESC_FIND_REQUIRED)
|
||||
ENDIF (XERCESC_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
XERCESC_INCLUDE_DIR
|
||||
XERCESC_LIBRARY
|
||||
)
|
||||
@@ -1,54 +0,0 @@
|
||||
# Locate Xsd from code synthesis include paths and binary
|
||||
# Xsd can be found at http://codesynthesis.com/products/xsd/
|
||||
# Written by Frederic Heem, frederic.heem _at_ telsey.it
|
||||
|
||||
# This module defines
|
||||
# XSD_INCLUDE_DIR, where to find elements.hxx, etc.
|
||||
# XSD_EXECUTABLE, where is the xsd compiler
|
||||
# XSD_FOUND, If false, don't try to use xsd
|
||||
|
||||
FIND_PATH( XSD_INCLUDE_DIR xsd/cxx/parser/elements.hxx
|
||||
"/opt/local/xsd-3.3.0-i686-macosx/libxsd"
|
||||
"C:/Programs/xsd-3.3.0/libxsd"
|
||||
"C:/Program Files/CodeSynthesis XSD 3.2/include"
|
||||
"C:/mingw/xsd-3.3.0-i686-windows/libxsd"
|
||||
$ENV{XSDDIR}/include
|
||||
$ENV{CODESYNTH}/include
|
||||
/usr/local/include /usr/include
|
||||
$ENV{XSDDIR}/libxsd
|
||||
)
|
||||
|
||||
IF( WIN32 )
|
||||
SET( XSDCXX_FILENAME1 xsd-cxx.exe )
|
||||
ELSE( )
|
||||
SET( XSDCXX_FILENAME1 xsdcxx )
|
||||
SET( XSDCXX_FILENAME2 xsd )
|
||||
ENDIF( )
|
||||
|
||||
FIND_PROGRAM( XSDCXX_EXECUTABLE
|
||||
NAMES
|
||||
${XSDCXX_FILENAME1} ${XSDCXX_FILENAME2}
|
||||
PATHS
|
||||
"/opt/local/xsd-3.3.0-i686-macosx/bin"
|
||||
"C:/Programs/xsd-3.3.0/bin"
|
||||
"C:/mingw/xsd-3.3.0-i686-windows/bin"
|
||||
"C:/Program Files/CodeSynthesis XSD 3.2/bin"
|
||||
$ENV{XSDDIR}/bin
|
||||
/usr/local/bin
|
||||
/usr/bin
|
||||
$ENV{XSDDIR}/xsd
|
||||
)
|
||||
|
||||
MESSAGE(STATUS ${XSDCXX_EXECUTABLE})
|
||||
|
||||
# if the include and the program are found then we have it
|
||||
IF( XSD_INCLUDE_DIR )
|
||||
IF( XSDCXX_EXECUTABLE )
|
||||
SET( XSD_FOUND "YES" )
|
||||
ENDIF( XSDCXX_EXECUTABLE )
|
||||
ENDIF( XSD_INCLUDE_DIR )
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
XSD_INCLUDE_DIR
|
||||
XSDCXX_EXECUTABLE
|
||||
)
|
||||
@@ -1,75 +0,0 @@
|
||||
macro(today RESULT)
|
||||
if(WIN32)
|
||||
execute_process(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT})
|
||||
string(REGEX REPLACE "[^0-9]*([0-9]+)[^0-9]([0-9]+)[^0-9]([0-9]+).*" "\\1-\\2-\\3" ${RESULT} ${${RESULT}})
|
||||
elseif(UNIX)
|
||||
execute_process(COMMAND "date" "+%Y-%m-%d" OUTPUT_VARIABLE ${RESULT})
|
||||
string(REGEX REPLACE "(....)-(..)-(..).*" "\\1-\\2-\\3" ${RESULT} ${${RESULT}})
|
||||
else(WIN32)
|
||||
message(WARNING "date not implemented")
|
||||
set(${RESULT} 00-00-0000)
|
||||
endif(WIN32)
|
||||
endmacro(today)
|
||||
|
||||
macro(now RESULT)
|
||||
if(WIN32)
|
||||
execute_process(COMMAND "cmd" " /C time /T" OUTPUT_VARIABLE ${RESULT})
|
||||
string(REGEX REPLACE "(..):(..).*" "\\1:\\2:00" ${RESULT} ${${RESULT}})
|
||||
elseif(UNIX)
|
||||
execute_process(COMMAND "date" "+%H:%M:%S" OUTPUT_VARIABLE ${RESULT})
|
||||
string(REGEX REPLACE "(..):(..):(..).*" "\\1:\\2:\\3" ${RESULT} ${${RESULT}})
|
||||
else(WIN32)
|
||||
message(WARNING "time not implemented")
|
||||
set(${RESULT} 00:00:00)
|
||||
endif(WIN32)
|
||||
endmacro(now)
|
||||
|
||||
find_package(Git)
|
||||
|
||||
macro(git_id RESULT)
|
||||
set(${RESULT} 0)
|
||||
if (GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
|
||||
execute_process(COMMAND "${GIT_EXECUTABLE}" "--git-dir=${PROJECT_SOURCE_DIR}/.git" "rev-parse" "--short=8" "HEAD" OUTPUT_VARIABLE proc_out ERROR_VARIABLE proc_err)
|
||||
if(proc_err)
|
||||
message(WARNING "Git failed with error: ${proc_err}")
|
||||
else()
|
||||
string(REGEX REPLACE "(.*)\n" "\\1" ${RESULT} ${proc_out})
|
||||
endif()
|
||||
elseif(NOT GIT_FOUND)
|
||||
message(WARNING "Git executable not found, revision number not available.")
|
||||
else()
|
||||
message(STATUS "Git repository not found, revision number not available.")
|
||||
endif()
|
||||
endmacro(git_id)
|
||||
|
||||
macro(use_cxx11)
|
||||
if (CMAKE_VERSION VERSION_LESS "3.1" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set (CMAKE_CXX_FLAGS "--std=gnu++11 ${CMAKE_CXX_FLAGS}")
|
||||
endif ()
|
||||
endmacro(use_cxx11)
|
||||
|
||||
macro(PrintTargetReport targetName)
|
||||
if(CMAKE_CXX_COMPILER MATCHES "/(clang-)?cl\\.exe$")
|
||||
set(cpp_version ${CMAKE_CXX_COMPILER_VERSION})
|
||||
else()
|
||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE cpp_version)
|
||||
endif()
|
||||
if(cpp_version)
|
||||
string(STRIP "v${cpp_version}" cpp_version)
|
||||
else()
|
||||
set(cpp_version "WARNING: COMPILER NOT FOUND!")
|
||||
endif()
|
||||
message("TARGET ${targetName}: cpp compiler ${CMAKE_CXX_COMPILER} ${cpp_version}")
|
||||
|
||||
if(VERBOSE_CMAKELISTS)
|
||||
get_directory_property(DirOpts COMPILE_OPTIONS)
|
||||
get_directory_property(DirDefs COMPILE_DEFINITIONS)
|
||||
string(REPLACE ";" " " DirOpts "${DirOpts}")
|
||||
string(REPLACE ";" "; " DirDefs "${DirDefs}")
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
|
||||
message("\twith cpp flags: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${build_type}} ${DirOpts}")
|
||||
message("\twith link flags: ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
message("\twith defs: ${DirDefs}")
|
||||
message("--------------")
|
||||
endif()
|
||||
endmacro(PrintTargetReport)
|
||||
@@ -1,484 +0,0 @@
|
||||
<h2>Version 2.2.1 / 2017-12-17</h2>
|
||||
|
||||
Please see <a href=http://www.open-tx.org/2017/12/16/opentx-2.2.1>this page</a> for details.
|
||||
|
||||
<h2>Version 2.2.0 / 2017-05-30</h2>
|
||||
|
||||
Major release! Please see <a href=http://www.open-tx.org/2017/05/30/opentx-2.2.0>this page</a> for details.
|
||||
|
||||
<h2>Version 2.1.9 / 2016-09-14</h2>
|
||||
|
||||
<ul>
|
||||
<li>SD sync fixes (<a href=https://github.com/opentx/opentx/issues/3351>#3351</a>)</li>
|
||||
<li>Fixed: Telemetry mode "FrSky D (cable)" choice was missing for Taranis (<a href=https://github.com/opentx/opentx/issues/3372>#3372</a>)</li>
|
||||
<li>Show persistent option only for calculated sensors (<a href=https://github.com/opentx/opentx/issues/3454>#3454</a>)</li>
|
||||
<li>Fixed Flight mode clear command (<a href=https://github.com/opentx/opentx/issues/3214>#3214</a>)</li>
|
||||
<li>Fixed a problem with Rotary encoders linked to flight mode (could freeze Companion) (<a href=https://github.com/opentx/opentx/issues/3459>#3459</a>, <a href=https://github.com/opentx/opentx/issues/3470>#3470</a>)</li>
|
||||
<li>Telemetry simulator improvements: added fuel quantity sensor, increased RPM range (<a href=https://github.com/opentx/opentx/issues/3505>#3505</a>, <a href=https://github.com/opentx/opentx/issues/3506>#3506</a>)</li>
|
||||
<li>Implemented minimal support for the DYI Multimodule (<a href=https://github.com/opentx/opentx/issues/3526>#3526</a>)</li>
|
||||
<li>Fixed: GVar combo-box not being refreshed when GV check-box (re-)selected (<a href=https://github.com/opentx/opentx/issues/3518>#3518</a>)</li>
|
||||
<li>Fixed: Heli inversion not correctly shown/saved from Companion on Radios without virtual inputs (<a href=https://github.com/opentx/opentx/issues/3510>#3510</a>)</li>
|
||||
<li>Implemented print functions for the Heli setup screen (<a href=https://github.com/opentx/opentx/issues/3554>#3554</a>)</li>
|
||||
<li>Fixed: Flight modes linked trims display value (<a href=https://github.com/opentx/opentx/issues/3547>#3547</a>, <a href=https://github.com/opentx/opentx/issues/3568>#3568</a>)</li>
|
||||
<li>Fixed: New model global variables and rotary encoders initialisation (<a href=https://github.com/opentx/opentx/issues/3473>#3473</a>)</li>
|
||||
<li>Fixed: Prevent circular linked global variables and rotary encoders (<a href=https://github.com/opentx/opentx/issues/3472>#3472</a>)</li>
|
||||
<li>Fixed wrong log replay speed issue in Telemetry simulator (<a href=https://github.com/opentx/opentx/issues/3708>#3708</a>)</li>
|
||||
<li>Various texts and translations corrections</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.1.8 / 2016-04-14</h2>
|
||||
|
||||
<ul>
|
||||
<li>Telemetry Simulator sensor instance number fixed (<a href=https://github.com/opentx/opentx/issues/3207>#3207</a>)</li>
|
||||
<li>Fixed: Throttle Source combo-box was populated multiple times (<a href=https://github.com/opentx/opentx/issues/3222>#3222</a>)</li>
|
||||
<li>RTC option tool-tip corrected (<a href=https://github.com/opentx/opentx/issues/3225>#3225</a>)</li>
|
||||
<li>Fixed: Companion was looking for custom scripts at the wrong place (<a href=https://github.com/opentx/opentx/issues/3237>#3237</a>)</li>
|
||||
<li>Offset displayed in inputs screen (<a href=https://github.com/opentx/opentx/issues/3248>#3248</a>)</li>
|
||||
<li>Import/export handling was broken for Average formula telemetry sensors (<a href=https://github.com/opentx/opentx/issues/3262>#3262</a>)</li>
|
||||
<li>Fixed: Hardware Setup control types and names were not stored in profile (<a href=https://github.com/opentx/opentx/issues/3260>#3260</a>)</li>
|
||||
<li>Fixed voice language list (<a href=https://github.com/opentx/opentx/issues/3338>#3338</a>)</li>
|
||||
<li>Fixed data overflow in Special Functions Override Channel (<a href=https://github.com/opentx/opentx/issues/3347>#3347</a>)</li>
|
||||
<li>Fixed: Sync dialog new line problem (only present for some UI languages) (<a href=https://github.com/opentx/opentx/issues/3350>#3350</a>)</li>
|
||||
<li>Removed a few legacy timer limitations, fix non-working limit (<a href=https://github.com/opentx/opentx/issues/3301>#3301</a>)</li>
|
||||
<li>Default AVR fuse settings changed to disable JTAG interface (<a href=https://github.com/opentx/opentx/issues/3379>#3379</a>)</li>
|
||||
<li>Channel range fix (Start, Channels) in Model Settings, Setup page, int/ext module settings</li>
|
||||
<li>Use friendly GVAR names in dialogs (if available) (<a href=https://github.com/opentx/opentx/issues/3353>#3353</a>)</li>
|
||||
<li>Various texts and translations corrections</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.1.7 / 2016-01-04</h2>
|
||||
|
||||
<ul>
|
||||
<li>Lua 'execute' failed in non-root directory (in Simulator) (<a href=https://github.com/opentx/opentx/issues/3024>#3024</a>)</li>
|
||||
<!-- this is disabled until the speed problem is fixed <li>Header line always visible in Outputs, Logical Switches and Special Functions (<a href=https://github.com/opentx/opentx/issues/2861>#2861</a>)</li> -->
|
||||
<li>LR12 changes: removed option for remote failsafe configuration, added in EU firmware variant</li>
|
||||
<li>Added Clear option to the flight mode context menu (right click on the Name label) (<a href=https://github.com/opentx/opentx/issues/3026>#3026</a>)</li>
|
||||
<li>New features for Telemetry Simulator: log replay, user friendly sensor values (<a href=https://github.com/opentx/opentx/issues/3124>#3124</a>)</li>
|
||||
<li>Added F7 key to reload LUA permanent scripts in radio simulator (<a href=https://github.com/opentx/opentx/issues/3141>#3141</a>)</li>
|
||||
<li>AR9X firmware flashing fall-back was wrong</li>
|
||||
<li>Command line options support added to standalone simulator (try "./simulator21 --help" on Linux and "simulator.exe /help" on Windows for usage) (<a href=https://github.com/opentx/opentx/issues/3160>#3160</a>)</li>
|
||||
<li>Various rounding problem fixed: Telemetry sensor Ratio parameter (<a href=https://github.com/opentx/opentx/issues/3117>#3117</a>),
|
||||
Outputs Sub-trim, Min and Max values (<a href=https://github.com/opentx/opentx/issues/3156>#3156</a>)</li>
|
||||
<li>Fixed: telemetry sensors Ratio and Offset value increment/decrement step (<a href=https://github.com/opentx/opentx/issues/3121>#3121</a>)</li>
|
||||
<li>Hardware/Calibration tab split int two tabs (<a href=https://github.com/opentx/opentx/issues/2974>#2974</a>)</li>
|
||||
<li>Fixed Fahrenheit temperature conversion error (if PREC was not 0) (<a href=https://github.com/opentx/opentx/issues/3146>#3146</a>)</li>
|
||||
<li>Application Setting 'Enable automatic backup before writing firmware' was not saved (<a href=https://github.com/opentx/opentx/issues/3040>#3040</a>)</li>
|
||||
<li>Fixed RPM package problem on Fedora (<a href=https://github.com/opentx/opentx/issues/3130>#3130</a>)</li>
|
||||
<li>Fixed conversion errors when loading 2.0.x EEPE (<a href=https://github.com/opentx/opentx/issues/3177>#3177</a>)</li>
|
||||
<li>Various texts and translations corrections</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.1.6 / 2015-11-11</h2>
|
||||
|
||||
<ul>
|
||||
<li>Telemetry custom screen changes didn't emit modified signal (<a href=https://github.com/opentx/opentx/issues/3029>#3029</a>)</li>
|
||||
<li>Hide D8/LR12 when eu firmware option is selected</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.1.5 / 2015-11-05</h2>
|
||||
|
||||
Notice: version 2.1.4 was skipped by the OpenTX team to avoid confusion with FrSky's release of OpenTX 2.1.4
|
||||
|
||||
<ul>
|
||||
<li>Fixed: changing any setting on the telemetry panel does not set the file as being modified (<a href=https://github.com/opentx/opentx/issues/2875>#2875</a>)</li>
|
||||
<li>Print model fix for "Play value.... not on startup" (<a href=https://github.com/opentx/opentx/issues/2736>#2736</a>)</li>
|
||||
<li>Top LCD Timer could not be selected for X9E (<a href=https://github.com/opentx/opentx/issues/2850>#2850</a>)</li>
|
||||
<li>More informative error/info messages when openin eepe files (<a href=https://github.com/opentx/opentx/issues/2778>#2778</a>)</li>
|
||||
<li>Print model fix for curves (<a href=https://github.com/opentx/opentx/issues/2896>#2896</a>)</li>
|
||||
<li>Added missing special functions (bind, range check, set failsafe) (<a href=https://github.com/opentx/opentx/issues/2753>#2753</a>)</li>
|
||||
<li>Some defaults missing when changing telemetry formula, update propagation issues (<a href=https://github.com/opentx/opentx/issues/2928>#2928</a>)</li>
|
||||
<li>Fixed wrong import of Logical switches from OpenTX 2.0.x version (<a href=https://github.com/opentx/opentx/issues/2942>#2942</a>)</li>
|
||||
<li>Fixed a problem with updates path on Windows (<a href=https://github.com/opentx/opentx/issues/2876>#2876</a>)</li>
|
||||
<li>Edge representation unified (changed from "no release" to "instant") (<a href=https://github.com/opentx/opentx/issues/2837>#2837</a>)</li>
|
||||
<li>Added channel names on failsafe sliders (<a href=https://github.com/opentx/opentx/issues/3021>#3021</a>)</li>
|
||||
<li>Corrected failsafe mapping when using Custom failsafe mode, D16 protocol and channel range different from from 1-8.
|
||||
Users with such setups are advised to re-check their failsafe settings (<a href=https://github.com/opentx/opentx/issues/2975>#2975</a>)</li>
|
||||
<li>Various texts and translations corrections</li>
|
||||
<li>Various small bug-fixes: <a href=https://github.com/opentx/opentx/issues/2994>#2994</a>,
|
||||
<a href=https://github.com/opentx/opentx/issues/3016>#3016</a>,
|
||||
<a href=https://github.com/opentx/opentx/issues/3012>#3012</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.1.3 / 2015-09-09</h2>
|
||||
|
||||
<ul>
|
||||
<li>Fix missing translations in inputs/mixes tabs, print and compare dialogs (<a href=https://github.com/opentx/opentx/issues/2847>#2847</a>)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.1.2 / 2015-09-07</h2>
|
||||
|
||||
<ul>
|
||||
<li>Fixed: Lua model scripts outputs not working in a simulator (<a href=https://github.com/opentx/opentx/issues/2684>#2684</a>)</li>
|
||||
<li>Fixed a problem of Companion 2.1 trying to install into 2.0 path.
|
||||
The effect will only be visible for the users that did not install any of the previous 2.1.x versions.
|
||||
(<a href=https://github.com/opentx/opentx/issues/2645>#2645</a>)</li>
|
||||
<li>Added missing SDL libraries to MAC package (<a href=https://github.com/opentx/opentx/issues/2678>#2678</a>)</li>
|
||||
<li>Added used channels check/warning in Wizard (<a href=https://github.com/opentx/opentx/issues/2091>#2091</a>)</li>
|
||||
<li>Model Print and Model Compare improvements and fixes (<a href=https://github.com/opentx/opentx/issues/2734>#2734</a>, <a href=https://github.com/opentx/opentx/issues/2737>#2737</a>, <a href=https://github.com/opentx/opentx/issues/2576>#2576</a>)</li>
|
||||
<li>Negative telemetry offset value was reset when writing back to radio (<a href=https://github.com/opentx/opentx/issues/2738>#2738</a>)</li>
|
||||
<li>Telemetry sensor names were not displayed (<a href=https://github.com/opentx/opentx/issues/2807>#2807</a>)</li>
|
||||
<li>Mixes multiplex representation now the same as on the radio (<a href=https://github.com/opentx/opentx/issues/2808>#2808</a>)</li>
|
||||
<li>Fixed language-related startup crash on Mac (<a href=https://github.com/opentx/opentx/issues/2815>#2815</a>)</li>
|
||||
<li>Fixed issues with conversion from 2.0 (<a href=https://github.com/opentx/opentx/issues/2809>#2809</a>, <a href=https://github.com/opentx/opentx/issues/2800>#2800</a>)</li>
|
||||
<li>Fixed Throttle source export issue on X9E (<a href=https://github.com/opentx/opentx/issues/2844>#2844</a>)</li>
|
||||
<li>Added support for the AR9X replacement board (prototype) for the Turnigy 9X radio, info <a href=http://www.rcgroups.com/forums/showthread.php?t=2479552>here</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.1.1 / 2015-08-06</h2>
|
||||
<ul>
|
||||
<li>Vario source and center silent options were not saved(<a href=https://github.com/opentx/opentx/issues/2476>#2476</a>)</li>
|
||||
<li>DSM receiver numbers for external module were not converted from previous version EEPROM (<a href=https://github.com/opentx/opentx/issues/2474>#2474</a>)</li>
|
||||
<li>Precision incorrectly set for Calculated->Cells sensor (<a href=https://github.com/opentx/opentx/issues/2479>#2479</a>)</li>
|
||||
<li>Unit incorrectly set for Calculated->Cells sensor (<a href=https://github.com/opentx/opentx/issues/2485>#2485</a>)</li>
|
||||
<li>Fixed import/export of trim values (<a href=https://github.com/opentx/opentx/issues/2484>#2484</a>)</li>
|
||||
<li>Removed constant access to floppy disk (<a href=https://github.com/opentx/opentx/issues/2160>#2160</a>)</li>
|
||||
<li>Telemetry view script combo box list was empty (<a href=https://github.com/opentx/opentx/issues/2465>#2465</a>)</li>
|
||||
<li>Telemetry view bars ranges not transfered to radio (<a href=https://github.com/opentx/opentx/issues/2491>#2491</a>)</li>
|
||||
<li>Fixed Standalone simulator radio selection display problem (<a href=https://github.com/opentx/opentx/issues/2503>#2503</a>)</li>
|
||||
<li>Added missing simulation libraries and enabled side by side installation of Companion 2.0 and 2.1 on Linux (<a href=https://github.com/opentx/opentx/issues/2500>#2500</a>)</li>
|
||||
<li>Standalone simulator now remembers which radio was simulated in previous session (<a href=https://github.com/opentx/opentx/issues/2503>#2503</a>)</li>
|
||||
<li>Radio calibration value were not displayed (<a href=https://github.com/opentx/opentx/issues/2502>#2502</a>)</li>
|
||||
<li>Fixed Vario / Voltage / Current sources export problem</li>
|
||||
<li>Writing model settings to 9XR-PRO did not work (<a href=https://github.com/opentx/opentx/issues/2402>#2402</a>, <a href=https://github.com/opentx/opentx/issues/2517>#2517</a>)</li>
|
||||
<li>Model Print and Model Compare improvements</li>
|
||||
<li>Fixed Companion OSX version (<a href=https://github.com/opentx/opentx/issues/2549>#2549</a>)</li>
|
||||
<li>Firmware nightly builds are now downloadable from nightly builds of Companion (<a href=https://github.com/opentx/opentx/issues/2526>#2526</a>, <a href=https://github.com/opentx/opentx/issues/2634>#2634</a>)</li>
|
||||
<li>Fixed telemetry item lists (<a href=https://github.com/opentx/opentx/issues/2541>#2541</a>)</li>
|
||||
<li>Fixed missing pots P1..P3 for 9X (<a href=https://github.com/opentx/opentx/issues/2543>#2543</a>)</li>
|
||||
<li>Fixed "Invalid model and settings" error message when writing models and settings to the radio (<a href=https://github.com/opentx/opentx/issues/2544>#2544</a>)</li>
|
||||
<li>Global Functions fixes (<a href=https://github.com/opentx/opentx/issues/2558>#2558</a>)</li>
|
||||
<li>Export to Google Earth now working (only) with the new telemetry fields (GPS, GAlt and GSpd) (<a href=https://github.com/opentx/opentx/issues/2546>#2546</a>)</li>
|
||||
<li>Fixed unsuccessful writing of setting to the radio for 9XR PRO (<a href=https://github.com/opentx/opentx/issues/2605>#2605</a>)</li>
|
||||
<li>Fixed missing LUA script outputs in special function "Play Value" (<a href=https://github.com/opentx/opentx/issues/2649>#2649</a>)</li>
|
||||
<li>Various texts and translations corrections</li>
|
||||
<li>Various small bug-fixes</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.1.0 / 2015-07-16</h2>
|
||||
<ul>
|
||||
<li>SD card synchronizaton tool</li>
|
||||
<li>Added session duraton information in Log Viewer</li>
|
||||
<li>Enabled <i>Mixers monitor</i> in Taranis simulator</li>
|
||||
<li>Better support for multi-axes in Log Viewer (<a href=https://github.com/opentx/opentx/issues/2267>#2267</a>)</li>
|
||||
<li>File path issue in Taranis simulator function <i>findTrueFileName()</i> on Windows (<a href=https://github.com/opentx/opentx/issues/2301>#2301</a>)</li>
|
||||
<li>Added simulator volume gain setting (<a href=https://github.com/opentx/opentx/issues/2260>#2260</a>)</li>
|
||||
<li>Added GPS glitch filtering and Latitude/Longitude position synchronization to Google Earth export (<a href=https://github.com/opentx/opentx/issues/2326>#2326</a>)</li>
|
||||
<li>Fixed a rare program crash when editing Input for 9X radio (<a href=https://github.com/opentx/opentx/issues/2420>#2420</a>)</li>
|
||||
<li>Fixed missing RSSI audio warnings if simulator was started multiple times (<a href=https://github.com/opentx/opentx/issues/2446>#2446</a>)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.0.17 / 2015-05-04</h2>
|
||||
<ul>
|
||||
<li>Simulator crash (<a href=https://github.com/opentx/opentx/issues/2253>#2253</a>)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.0.16 / 2015-05-03</h2>
|
||||
<ul>
|
||||
<li><i>nooverridech</i> firmware option was not working</li>
|
||||
<li>Fixed setting Expo from gvars for 9XR-Pro (<a href=https://github.com/opentx/opentx/issues/2040>#2040</a>)</li>
|
||||
<li>Added Mixers Monitor screen option <i>mixersmon</i> (<a href=https://github.com/opentx/opentx/issues/1945>#1945</a>)</li>
|
||||
<li>Added audio playing in simulator (<a href=https://github.com/opentx/opentx/issues/457>#457</a>)</li>
|
||||
<li>Fixed sorting of audio tracks (<a href=https://github.com/opentx/opentx/issues/2002>#2002</a>)</li>
|
||||
<li>Model wizard fixes (<a href=https://github.com/opentx/opentx/issues/2091>#2091</a>)</li>
|
||||
<li>GVAR names removed for 9x, radio doesn't support them (<a href=https://github.com/opentx/opentx/issues/2150>#2150</a>)</li>
|
||||
<li>Some LS sources didn't follow the Imperial units setting (<a href=https://github.com/opentx/opentx/issues/2180>#2180</a>)</li>
|
||||
<li>Added more fields to the telemetry simulator (<a href=https://github.com/opentx/opentx/issues/2171>#2171</a>)</li>
|
||||
<li>Log viewer improvements and massive speed increase (<a href=https://github.com/opentx/opentx/issues/1863>#1863</a>, <a href=https://github.com/opentx/opentx/issues/2163>#2163</a>)</li>
|
||||
<li>Added Battery meter range setting (<a href=https://github.com/opentx/opentx/issues/2195>#2195</a>)</li>
|
||||
<li>Improvements in Print and Compare dialogs (<a href=https://github.com/opentx/opentx/issues/2219>#2219</a>)</li>
|
||||
<li>Reset pots to the middle by right double clicking them in Simulator (<a href=https://github.com/opentx/opentx/issues/1939>#1939</a>)</li>
|
||||
<li>Minor fixes: <a href=https://github.com/opentx/opentx/issues/2153>#2153</a>,
|
||||
<a href=https://github.com/opentx/opentx/issues/2138>#2138</a>,
|
||||
<a href=https://github.com/opentx/opentx/issues/2090>#2090</a>,
|
||||
<a href=https://github.com/opentx/opentx/issues/2122>#2122</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Version 2.0.15 / 2015-01-13</h2>
|
||||
<ul>
|
||||
<li>Firmware was not written correctly on radio when compatibility warning check enabled</li>
|
||||
<li>Time format for Special Functions Set Timers</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.14 / 2015-01-12</h2>
|
||||
<ul>
|
||||
<li>OpenTX Companion and Companion9x can now be installed side by side on Linux</li>
|
||||
<li>Improved TAB order in dialogs</li>
|
||||
<li>Special Function <i>Start Logs</i> renamed to more appropriate <i>SD Logs</i></li>
|
||||
<li>Improvements for MAC build</li>
|
||||
<li>Fixes to Google Earth logs export</li>
|
||||
<li>Firmware compatibility warning check added when flashing new firmware to radio</li>
|
||||
<li>Fixed issue with Telemetry Type setting on 9XR-PRO</li>
|
||||
<li>Added Telemetry simulator</li>
|
||||
<li>Added Trainer simulator</li>
|
||||
<li>Added Debug Output window</li>
|
||||
<li>Various texts and translations corrections</li>
|
||||
<li>Various small bug-fixes</li>
|
||||
<li>More reliable method of writing EEPROM.BIN and FIRMWARE.BIN to radio</li>
|
||||
<li>Fixed issue with Edge function INSTANT for V1>2s</li>
|
||||
<li>Fixed buffer overflow in Joystick code</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.13 / 2014-11-20</h2>
|
||||
<ul>
|
||||
<li>Too many curves shown on non ARM boards</li>
|
||||
<li>Fixed vario limits</li>
|
||||
<li>Fixes in compare dialog</li>
|
||||
<li>Fixed receiver number range</li>
|
||||
<li>Virtual inputs not selectable in SF Volume and heli Collective Source</li>
|
||||
<li>Joystick calibration crash after channel assignment</li>
|
||||
<li>Gvar import error for limits</li>
|
||||
<li>Companion shows too many curve types in input/mixer for 9x</li>
|
||||
<li>NOT curves removed from inputs (for non ARM platforms)</li>
|
||||
<li>Companion again builds on OS X (Mac)</li>
|
||||
<li>Companion simulator Lua crash on OS X 64bit (Mac)</li>
|
||||
<li>Companion didn't take care of PlayScript functions</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.12 / 2014-09-15</h2>
|
||||
<ul>
|
||||
<li>Typos & Translations updated</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.11 / 2014-09-10</h2>
|
||||
<ul>
|
||||
<li>Limits EEPROM export was broken (all boards except Taranis)</li>
|
||||
<li>Fix issue when a GVAR was used as Offset</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.10 / 2014-09-08</h2>
|
||||
<ul>
|
||||
<li>Taranis is now the default board in General Settings</li>
|
||||
<li>GVARS allowed in Limits min/max/offset</li>
|
||||
<li>Limits displayed in us when ppmus option selected
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.8 / 2014-07-23</h2>
|
||||
<ul>
|
||||
<li>Compare dialog bugfixes</li>
|
||||
<li>Curve index correctly resetted when type changed</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.7</h2>
|
||||
<ul>
|
||||
<li>SafetyCH function was missing in simulator</li>
|
||||
<li>EEPROM export warning when exporting logical switches > L12 on 9X128</li>
|
||||
<li>FAS offset was not exported on 9X/9XR boards</li>
|
||||
<li>Trims modes bugfix on non Taranis boards</li>
|
||||
<li>It was impossible to open a backuped model from the Tx</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.6</h2>
|
||||
<ul>
|
||||
<li>Fix Mix curves bug on Sky9x boards</li>
|
||||
<li>Channels 17-32 are displayed in the simulator</li>
|
||||
<li>Backlight simulation bugfix</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.5</h2>
|
||||
<ul>
|
||||
<li>Fix crash on startup</li>
|
||||
<li>Fix version number in simu</li>
|
||||
<li>9XR-Pro now supported on Mac</li>
|
||||
<li>Fix loss of settings in telemetry custom screens</li>
|
||||
<li>Fix 10000% bug when using GVs in mixer weithg or offset</li>
|
||||
<li>Fix Cnsp range in logical switches (up to 30000mAh)</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.4</h2>
|
||||
<ul>
|
||||
<li>Sound should be ok on all platforms</li>
|
||||
<li>Min/Max reviewed in Logical switches (for the whole telemetry)</li>
|
||||
<li>Various bug fixes</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.3</h2>
|
||||
<ul>
|
||||
<li>EEPROM import bug on AdjustGVAR function</li>
|
||||
<li>Timers correctly displayed in logical switches tab</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.2</h2>
|
||||
<ul>
|
||||
<li>Mouse scroll wheel behaves differently</li>
|
||||
<li>Play Sounds should now work on all platforms</li>
|
||||
<li>A lot of small bug fixes</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.1</h2>
|
||||
<ul>
|
||||
<li>Fix on recursive GVars</li>
|
||||
<li>Sky9x EEPROM read/write fix</li>
|
||||
<li>Translations updated
|
||||
<li>Wizard fixes
|
||||
<li>Fix on invalid splashes bitmaps
|
||||
</ul>
|
||||
|
||||
<h2>Version 2.0.0</h2>
|
||||
<ul>
|
||||
<li>Companion now merged into OpenTX</li>
|
||||
<li>Too many changes to list them all!</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.52</h2>
|
||||
<ul>
|
||||
<li>Fix crash when writing certain EEPROMS</li>
|
||||
<li>Google Earth export of logs containing GPS positions</li>
|
||||
<li>DSM2 added for Taranis</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.51</h2>
|
||||
<ul>
|
||||
<li>Wrong DFU-Util default path (MAC)</li>
|
||||
<li>new voices download server (ip address changed to new fiber connection)</li>
|
||||
<li>Fixed contributor list</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.50</h2>
|
||||
<ul>
|
||||
<li>solved issue with taranis radio with some linux distributions</li>
|
||||
<li>blank eeprom created using a radio profile that holds calibration data, will contain calibration data from the profile</li>
|
||||
<li>new opentx compilation server (ip address changed to new fiber connection)</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.49</h2>
|
||||
<ul>
|
||||
<li>Stack usage optimizations</li>
|
||||
<li>Playsound order is misaligned between companion9x and the TX</li>
|
||||
<li>Model image could not be reset.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.48</h2>
|
||||
<ul>
|
||||
<li>Interface fixes</li>
|
||||
<li>Hide include dr/expo when not applicable</li>
|
||||
<li>Fix extraction of grayscale images from taranis firmwares</li>
|
||||
<li>No TX and RX in Taranis telemetry fields</li>
|
||||
<li>Issue 255 fixed - "No GVAR selection possible for PLAY VALUE"</li>
|
||||
<li>Issue 254 fixed - "SE Language for building opentx"</li>
|
||||
<li>Issue 253 fixed - "OpenTX doesn't accept this protocol (DSM2 on Sky9x)"</li>
|
||||
<li>Prevent segfault while parsing wrong log files or files with broken lines</li>
|
||||
<li>Small bug in model printout</li>
|
||||
<li>Fixed wrong display of values in custom functions</li>
|
||||
<li>Image in preferences was saved only black & white</li>
|
||||
<li>Issue 247 fixed - "Labelled items on radio should not be translated."</li>
|
||||
<li>Added support of tstick (taranis like stick) compile option for sky9x opentx firmware</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.47</h2>
|
||||
<ul>
|
||||
<li>Interface fixes (issues 232,233,238,241)</li>
|
||||
<li>Fix for print/compare models</li>
|
||||
<li>Function switch parameter on screen different than printout.</li>
|
||||
<li>Translations fixes</li>
|
||||
<li>Command line print mode</li>
|
||||
<li>Better mavlink support</li>
|
||||
<li>SE tts language added for taranis</li>
|
||||
<li>Alternate font option for opentx added</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.46</h2>
|
||||
<ul>
|
||||
<li>Interface fixes (issues 224,225)</li>
|
||||
<li>Show persistent timers value in modeledit</li>
|
||||
<li>Consistent naming of Custom Switches in c9x</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.45</h2>
|
||||
<ul>
|
||||
<li>Various fixes</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.44</h2>
|
||||
<ul>
|
||||
<li>Fix regression on AND parameter in custom functions</li>
|
||||
<li>Add mavlink support for stock and m128 boards</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.43</h2>
|
||||
<ul>
|
||||
<li>Copy Malfunctions in Custom Functions (Issue 205)</li>
|
||||
<li>Enable repeat parameter in functions for all boards</li>
|
||||
<li>Remove sink tones from vario for stock/m128 board</li>
|
||||
<li>Fix for wrongly named channels in mixerlist (Issue 210)</li>
|
||||
<li>Fix badly exported gvars in mixers</li>
|
||||
<li>Fix while editing custom switches</li>
|
||||
<li>Add access to the release notes of currently selected firmware</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.42</h2>
|
||||
<ul>
|
||||
<li>Add Companion9X changelog</li>
|
||||
<li>Add Fw release notes browser</li>
|
||||
<li>Simplify burn menu for sky9x and Taranis.</li>
|
||||
<li>Fix in telemetry conversion (rssi alarm) for stock board</li>
|
||||
<li>Drop support of sky9x boards on MacOS due to missing SAM-BA tool.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.41</h2>
|
||||
<ul>
|
||||
<li>Fix unneeded rescaling of splash images</li>
|
||||
<li>Fix for telemetry screens for Taranis</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.40</h2>
|
||||
<ul>
|
||||
<li>Log dialog - Split of logging sessions.</li>
|
||||
<li>Telemetry screen 1 as default (issue 206)</li>
|
||||
<li>Rename all channels in mixer tab accordingly to limits names</li>
|
||||
<li>Fix a segfault in phases tabs (Issue 203 regression introduced in release 2140)</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.39</h2>
|
||||
<ul>
|
||||
<li>Custom functions cut&paste </li>
|
||||
<li>Custom switches cut&paste </li>
|
||||
<li>Color button text in curve editor for MACOSX</li>
|
||||
<li>Adjust name lengths for Taranis</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.38</h2>
|
||||
<ul>
|
||||
<li>Core when model names were > 10 chars</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.37</h2>
|
||||
<ul>
|
||||
<li>Fix OpenTX segfault in Taranis simulator</li>
|
||||
<li>Implement brightness control for Taranis</li>
|
||||
<li>Reduce modeledit windows size</li>
|
||||
<li>Taranis splash screen in grayscale</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.36</h2>
|
||||
<ul>
|
||||
<li>Burning windows (with progress bar) now in foreground (Issue 197)</li>
|
||||
<li>Allow a selection of tracks for Background Music (Issue 199)</li>
|
||||
</ul>
|
||||
|
||||
<h2>Version 1.35</h2>
|
||||
<ul>
|
||||
<li>Country names mismatch between Taranis and Companion 9X (Issue 198)</li>
|
||||
<li>TIM function in custom switches</li>
|
||||
<li>Fix timer switches.</li>
|
||||
<li>Taranis LCD adjustment in general settings.</li>
|
||||
<li>New tool in curve editor</li>
|
||||
<li>Minor fixes</li>
|
||||
<li>Expo move bug + invalid chars in channels, expo and mixer names</li>
|
||||
<li>Try to reduce modeledit window form MAC</li>
|
||||
<li>Wrong init of RF-Module data</li>
|
||||
<li>Read flash from TX didn't worked for Taranis</li>
|
||||
</ul>
|
||||
@@ -1,586 +0,0 @@
|
||||
set(SIMULATOR_INSTALL_PREFIX "" CACHE STRING "Alternative simulator library search path")
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(Linux|FreeBSD)")
|
||||
set(C9X_NAME_SUFFIX ${VERSION_MAJOR}${VERSION_MINOR})
|
||||
set(COMPANION_NAME "companion${C9X_NAME_SUFFIX}")
|
||||
set(SIMULATOR_NAME "simulator${C9X_NAME_SUFFIX}")
|
||||
if (NOT ${SIMULATOR_INSTALL_PREFIX} STREQUAL "")
|
||||
set(SIMULATOR_LIB_PATH ${SIMULATOR_INSTALL_PREFIX}/lib/companion${C9X_NAME_SUFFIX})
|
||||
else()
|
||||
set(SIMULATOR_LIB_PATH ${CMAKE_INSTALL_PREFIX}/lib/companion${C9X_NAME_SUFFIX})
|
||||
endif()
|
||||
message(STATUS "Simulators library search path: " ${SIMULATOR_LIB_PATH})
|
||||
set(SIMULATOR_LIB_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/lib/companion${C9X_NAME_SUFFIX})
|
||||
else()
|
||||
set(COMPANION_NAME "companion")
|
||||
set(SIMULATOR_NAME "simulator")
|
||||
endif()
|
||||
|
||||
# This the name that the user will see in the generated DMG and what the application
|
||||
# will be called under /Applications. We include the version string to make installing
|
||||
# different versions for different eeproms easier, i.e. without manually renaming
|
||||
set(COMPANION_OSX_APP_BUNDLE_NAME "OpenTX Companion ${VERSION_MAJOR}.${VERSION_MINOR}")
|
||||
|
||||
# On OS X we copy dfu-util to the application bundle. This the path from which we copy
|
||||
# the binary (default homebrew path)
|
||||
set(DFU_UTIL_PATH "/usr/local/bin/dfu-util")
|
||||
set(AVRDUDE_PATH "/usr/local/bin/avrdude")
|
||||
set(AVRDUDE_CONF "/usr/local/etc/avrdude.conf")
|
||||
|
||||
option(ALLOW_NIGHTLY_BUILDS "Allow nightly builds download / update") # Disabled by default
|
||||
if(ALLOW_NIGHTLY_BUILDS)
|
||||
add_definitions(-DALLOW_NIGHTLY_BUILDS)
|
||||
endif(ALLOW_NIGHTLY_BUILDS)
|
||||
|
||||
option(DEBUG_STORAGE_IMPORT "Turn on debug output for storage import") # Disabled by default
|
||||
if(DEBUG_STORAGE_IMPORT)
|
||||
add_definitions(-DDEBUG_STORAGE_IMPORT)
|
||||
message(STATUS "Storage import debugging enabled")
|
||||
endif()
|
||||
if(DEBUG)
|
||||
add_definitions(-DDEBUG)
|
||||
endif()
|
||||
|
||||
option(TABLE_LAYOUT "Use QTableWidget for grid layouts") # Disabled by default
|
||||
if(TABLE_LAYOUT)
|
||||
add_definitions(-DTABLE_LAYOUT)
|
||||
message(STATUS "Using QTableWidget")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
option(WIN_DO_FULL_INSTALL "'install' target will perform a full installation into CMAKE_INSTALL_PREFIX path, otherwise only supporting DLLs are copied to binaries folder (default)" OFF)
|
||||
option(WIN_USE_CONSOLE "Open a Windows command console for Simulator debug output." OFF)
|
||||
if(WIN_USE_CONSOLE)
|
||||
add_definitions(-DWIN_USE_CONSOLE_STDIO)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SDL_FOUND)
|
||||
include_directories(${SDL_INCLUDE_DIR})
|
||||
add_definitions(-DJOYSTICKS)
|
||||
endif()
|
||||
|
||||
add_definitions(${APP_COMMON_DEFINES}) # set in top-level CMakeLists
|
||||
|
||||
if(NOT MSVC)
|
||||
set(WARNING_FLAGS "${WARNING_FLAGS} -Wall")
|
||||
if(WARNINGS_AS_ERRORS)
|
||||
set(WARNING_FLAGS "${WARNING_FLAGS} -Werror")
|
||||
endif()
|
||||
else()
|
||||
# silence lots of warnings regarding "insecure" use of functions (sprintf, strcpy, etc)
|
||||
set(WARNING_FLAGS "${WARNING_FLAGS} /D_CRT_SECURE_NO_WARNINGS")
|
||||
if(WARNINGS_AS_ERRORS)
|
||||
set(WARNING_FLAGS "${WARNING_FLAGS} /WX")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
include_directories(SYSTEM ${WIN_INCLUDE_DIRS})
|
||||
if(NOT WIN_USE_CONSOLE)
|
||||
set(WIN_EXECUTABLE_TYPE WIN32) # GUI (WinMain) app
|
||||
endif()
|
||||
if(MSVC)
|
||||
if(NOT CLANG)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /LD /MP")
|
||||
endif()
|
||||
if(NOT WIN_USE_CONSOLE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,5.01") # is this even needed?
|
||||
endif()
|
||||
elseif(MINGW)
|
||||
get_filename_component(MINGW_DIR ${CMAKE_CXX_COMPILER} DIRECTORY)
|
||||
# struct packing breaks on MinGW w/out -mno-ms-bitfields: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 & http://stackoverflow.com/questions/24015852/struct-packing-and-alignment-with-mingw
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-ms-bitfields")
|
||||
endif()
|
||||
else()
|
||||
set(PTHREAD_LIBRARY pthread)
|
||||
link_directories(/usr/local/lib)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}")
|
||||
|
||||
use_cxx11() # ensure gnu++11 in CXX_FLAGS with CMake < 3.1
|
||||
|
||||
include_directories(
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${COMPANION_SRC_DIRECTORY}
|
||||
${COMPANION_SRC_DIRECTORY}/shared
|
||||
${SIMU_SRC_DIRECTORY}
|
||||
${COMPANION_SRC_DIRECTORY}/thirdparty/qcustomplot
|
||||
${COMPANION_SRC_DIRECTORY}/thirdparty/miniz
|
||||
${COMPANION_SRC_DIRECTORY}/storage
|
||||
)
|
||||
|
||||
############# Do macro replacements on input files #############
|
||||
configure_file(${COMPANION_SRC_DIRECTORY}/version.h.in ${CMAKE_BINARY_DIR}/version.h @ONLY)
|
||||
configure_file(${COMPANION_SRC_DIRECTORY}/companion.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/companion.desktop @ONLY)
|
||||
configure_file(${COMPANION_SRC_DIRECTORY}/simulator.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/simulator.desktop @ONLY)
|
||||
|
||||
############# Translations ###############
|
||||
|
||||
### Generate .qm files and assemble resource (qrc) file.
|
||||
|
||||
# available Companion translations (src/translations/*.ts)
|
||||
set(LANGUAGES cs de en es fi fr it pl sv zh_CN)
|
||||
foreach(language ${LANGUAGES})
|
||||
list(APPEND companion_TS translations/companion_${language}.ts)
|
||||
endforeach(language)
|
||||
# .ts -> .qm
|
||||
qt5_add_translation(companion_QM ${companion_TS})
|
||||
|
||||
# add Qt translations if found
|
||||
if(QT_TRANSLATIONS_DIR)
|
||||
# Some languages have all translations in one qt_*.qm file and others break them up into modules, in which case we need qt_base_*.qm
|
||||
file(GLOB qtbase_QM "${QT_TRANSLATIONS_DIR}/qtbase_*.qm")
|
||||
file(GLOB qt_QM "${QT_TRANSLATIONS_DIR}/qt_??.qm") # don't want to match "qt_help_*.qm"
|
||||
list(APPEND qt_QM "${QT_TRANSLATIONS_DIR}/qt_zh_CN.qm" "${QT_TRANSLATIONS_DIR}/qt_zh_TW.qm") # exceptions not matched by the GLOB
|
||||
else()
|
||||
message(STATUS "QT_TRANSLATIONS_DIR not found, unable to package pre-built Qt translations with application.")
|
||||
endif()
|
||||
|
||||
set(TRANSLATIONS_QRC "${CMAKE_CURRENT_BINARY_DIR}/translations.qrc")
|
||||
|
||||
# Dynamically create translations.qrc file (XML) from all collected translation files.
|
||||
foreach(qm_file ${companion_QM} ${qt_QM} ${qtbase_QM})
|
||||
get_filename_component(qm_file_name ${qm_file} NAME)
|
||||
# Add file with full path and file name (w/out path) as alias to be used in actual code
|
||||
set(TRANSLATION_FILES_LIST "${TRANSLATION_FILES_LIST} <file alias=\"${qm_file_name}\">${qm_file}</file>\n")
|
||||
endforeach()
|
||||
configure_file(${COMPANION_SRC_DIRECTORY}/translations.qrc.in ${TRANSLATIONS_QRC} @ONLY)
|
||||
|
||||
### Add optional "translations" target for updating .ts files
|
||||
if(QT_LUPDATE_EXECUTABLE)
|
||||
add_custom_target(translations
|
||||
WORKING_DIRECTORY ${COMPANION_SRC_DIRECTORY}
|
||||
COMMAND ${QT_LUPDATE_EXECUTABLE} ${CMAKE_SOURCE_DIR} -no-obsolete -ts ${companion_TS}
|
||||
)
|
||||
else()
|
||||
message(STATUS "Qt lupdate not found, 'translations' target will not be availabe.")
|
||||
endif()
|
||||
|
||||
############# Common lib ###############
|
||||
|
||||
set(common_SRCS
|
||||
appdebugmessagehandler.cpp
|
||||
customdebug.cpp
|
||||
helpers.cpp
|
||||
translations.cpp
|
||||
modeledit/node.cpp # used in simulator
|
||||
modeledit/edge.cpp # used by node
|
||||
)
|
||||
|
||||
set(common_MOC_HDRS
|
||||
appdebugmessagehandler.h
|
||||
helpers.h
|
||||
modeledit/node.h
|
||||
)
|
||||
|
||||
set(common_RESOURCES
|
||||
companion.qrc
|
||||
${TRANSLATIONS_QRC}
|
||||
)
|
||||
|
||||
qt5_wrap_cpp(common_SRCS ${common_MOC_HDRS})
|
||||
qt5_add_resources(common_RCC ${common_RESOURCES})
|
||||
|
||||
add_library(common ${common_SRCS} ${common_RCC})
|
||||
|
||||
target_link_libraries(common
|
||||
firmwares
|
||||
storage
|
||||
simulation
|
||||
maxLibQtWidgets
|
||||
Qt5::Core
|
||||
Qt5::Xml
|
||||
Qt5::Widgets
|
||||
${PTHREAD_LIBRARY}
|
||||
${SDL_LIBRARY}
|
||||
${WIN_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
set(CPN_COMMON_LIB common)
|
||||
|
||||
############# Supporting libraries ###############
|
||||
|
||||
add_subdirectory(datamodels)
|
||||
add_subdirectory(firmwares)
|
||||
add_subdirectory(shared)
|
||||
add_subdirectory(modeledit)
|
||||
add_subdirectory(generaledit)
|
||||
add_subdirectory(simulation)
|
||||
add_subdirectory(storage)
|
||||
add_subdirectory(thirdparty/qcustomplot)
|
||||
add_subdirectory(thirdparty/maxlibqt/src/widgets)
|
||||
|
||||
############# Companion ###############
|
||||
|
||||
set(companion_SRCS
|
||||
helpers_html.cpp
|
||||
mdichild.cpp
|
||||
modelslist.cpp
|
||||
apppreferencesdialog.cpp
|
||||
fwpreferencesdialog.cpp
|
||||
burnconfigdialog.cpp
|
||||
multimodelprinter.cpp
|
||||
comparedialog.cpp
|
||||
creditsdialog.cpp
|
||||
releasenotesdialog.cpp
|
||||
releasenotesfirmwaredialog.cpp
|
||||
customizesplashdialog.cpp
|
||||
radiointerface.cpp
|
||||
progresswidget.cpp
|
||||
progressdialog.cpp
|
||||
process_copy.cpp
|
||||
process_flash.cpp
|
||||
process_sync.cpp
|
||||
flashfirmwaredialog.cpp
|
||||
flasheepromdialog.cpp
|
||||
printdialog.cpp
|
||||
modelprinter.cpp
|
||||
fusesdialog.cpp
|
||||
logsdialog.cpp
|
||||
downloaddialog.cpp
|
||||
splashlibrarydialog.cpp
|
||||
mainwindow.cpp
|
||||
companion.cpp
|
||||
radionotfound.cpp
|
||||
wizarddata.cpp
|
||||
wizarddialog.cpp
|
||||
styleeditdialog.cpp
|
||||
dialogs/filesyncdialog.cpp # TODO move to own lib with other dialogs
|
||||
)
|
||||
|
||||
set(companion_MOC_HDRS
|
||||
apppreferencesdialog.h
|
||||
fwpreferencesdialog.h
|
||||
burnconfigdialog.h
|
||||
comparedialog.h
|
||||
printdialog.h
|
||||
fusesdialog.h
|
||||
logsdialog.h
|
||||
creditsdialog.h
|
||||
releasenotesdialog.h
|
||||
releasenotesfirmwaredialog.h
|
||||
customizesplashdialog.h
|
||||
splashlibrarydialog.h
|
||||
splashlabel.h
|
||||
progresswidget.h
|
||||
progressdialog.h
|
||||
process_copy.h
|
||||
process_flash.h
|
||||
process_sync.h
|
||||
flashfirmwaredialog.h
|
||||
flasheepromdialog.h
|
||||
downloaddialog.h
|
||||
mdichild.h
|
||||
mainwindow.h
|
||||
radionotfound.h
|
||||
wizarddialog.h
|
||||
modelprinter.h
|
||||
multimodelprinter.h
|
||||
modelslist.h
|
||||
styleeditdialog.h
|
||||
helpers_html.h
|
||||
dialogs/filesyncdialog.h
|
||||
)
|
||||
|
||||
set(companion_UIS
|
||||
mdichild.ui
|
||||
comparedialog.ui
|
||||
fusesdialog.ui
|
||||
logsdialog.ui
|
||||
apppreferencesdialog.ui
|
||||
fwpreferencesdialog.ui
|
||||
burnconfigdialog.ui
|
||||
downloaddialog.ui
|
||||
printdialog.ui
|
||||
htmldialog.ui
|
||||
customizesplashdialog.ui
|
||||
splashlibrarydialog.ui
|
||||
progresswidget.ui
|
||||
progressdialog.ui
|
||||
flashfirmwaredialog.ui
|
||||
flasheepromdialog.ui
|
||||
radionotfound.ui
|
||||
styleeditdialog.ui
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(icon_RC images/winicons/icon.rc)
|
||||
endif()
|
||||
|
||||
qt5_wrap_ui(companion_SRCS ${companion_UIS})
|
||||
qt5_wrap_cpp(companion_SRCS ${companion_MOC_HDRS})
|
||||
|
||||
add_executable(${COMPANION_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${companion_SRCS} ${icon_RC})
|
||||
target_link_libraries(${COMPANION_NAME} PRIVATE generaledit modeledit qcustomplot shared ${CPN_COMMON_LIB})
|
||||
|
||||
PrintTargetReport("${COMPANION_NAME}")
|
||||
|
||||
############# Standalone simulator ###############
|
||||
|
||||
set(simu_SRCS simulator.cpp )
|
||||
|
||||
add_executable(${SIMULATOR_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${simu_SRCS} ${icon_RC})
|
||||
target_link_libraries(${SIMULATOR_NAME} PRIVATE ${CPN_COMMON_LIB})
|
||||
|
||||
############# Install ####################
|
||||
|
||||
# Generate list of simulator plugins, used by all platforms
|
||||
file(GLOB simulator_plugins "${CMAKE_BINARY_DIR}/*opentx-*simulator${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
# the current flavour is not automatically added if build in the current cmake iteration, so always
|
||||
# add its library name to be sure
|
||||
string(TOLOWER ${PCB} FLAVOUR)
|
||||
if(POLICY CMP0026)
|
||||
cmake_policy(SET CMP0026 OLD) # https://cmake.org/cmake/help/v3.0/policy/CMP0026.html
|
||||
endif()
|
||||
if(SIMU_TARGET)
|
||||
get_property(current_plugin TARGET opentx-${FLAVOUR}-simulator PROPERTY LOCATION)
|
||||
list(APPEND simulator_plugins "${current_plugin}")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
|
||||
message(STATUS "install " ${CMAKE_BINARY_DIR} " to " ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
install(TARGETS ${COMPANION_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
install(TARGETS ${SIMULATOR_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
install(FILES ${simulator_plugins} DESTINATION "${SIMULATOR_LIB_INSTALL_PATH}")
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/companion.desktop DESTINATION share/applications RENAME companion${C9X_NAME_SUFFIX}.desktop)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/simulator.desktop DESTINATION share/applications RENAME simulator${C9X_NAME_SUFFIX}.desktop)
|
||||
if(${CMAKE_INSTALL_PREFIX} MATCHES "/usr/local")
|
||||
set(INSTALL_TEMP_SHR_PFX "/usr/")
|
||||
set(INSTALL_TEMP_LIB_PFX "/")
|
||||
endif()
|
||||
install(FILES images/linuxicons/16x16/companion.png DESTINATION ${INSTALL_TEMP_SHR_PFX}share/icons/hicolor/16x16/apps RENAME companion${C9X_NAME_SUFFIX}.png)
|
||||
install(FILES images/linuxicons/22x22/companion.png DESTINATION ${INSTALL_TEMP_SHR_PFX}share/icons/hicolor/22x22/apps RENAME companion${C9X_NAME_SUFFIX}.png)
|
||||
install(FILES images/linuxicons/24x24/companion.png DESTINATION ${INSTALL_TEMP_SHR_PFX}share/icons/hicolor/24x24/apps RENAME companion${C9X_NAME_SUFFIX}.png)
|
||||
install(FILES images/linuxicons/32x32/companion.png DESTINATION ${INSTALL_TEMP_SHR_PFX}share/icons/hicolor/32x32/apps RENAME companion${C9X_NAME_SUFFIX}.png)
|
||||
install(FILES images/linuxicons/48x48/companion.png DESTINATION ${INSTALL_TEMP_SHR_PFX}share/icons/hicolor/48x48/apps RENAME companion${C9X_NAME_SUFFIX}.png)
|
||||
install(FILES images/linuxicons/128x128/companion.png DESTINATION ${INSTALL_TEMP_SHR_PFX}share/icons/hicolor/128x128/apps RENAME companion${C9X_NAME_SUFFIX}.png)
|
||||
install(FILES images/linuxicons/256x256/companion.png DESTINATION ${INSTALL_TEMP_SHR_PFX}share/icons/hicolor/256x256/apps RENAME companion${C9X_NAME_SUFFIX}.png)
|
||||
install(FILES images/linuxicons/512x512/companion.png DESTINATION ${INSTALL_TEMP_SHR_PFX}share/icons/hicolor/512x512/apps RENAME companion${C9X_NAME_SUFFIX}.png)
|
||||
install(FILES images/linuxicons/scalable/companion.svg DESTINATION ${INSTALL_TEMP_SHR_PFX}share/icons/hicolor/scalable/apps RENAME companion${C9X_NAME_SUFFIX}.svg)
|
||||
install(FILES ../targets/linux/45-companion-taranis.rules DESTINATION ${INSTALL_TEMP_LIB_PFX}lib/udev/rules.d RENAME 45-companion${C9X_NAME_SUFFIX}-taranis.rules)
|
||||
install(FILES ../targets/linux/45-usbasp.rules DESTINATION ${INSTALL_TEMP_LIB_PFX}lib/udev/rules.d RENAME 45-companion${C9X_NAME_SUFFIX}-usbasp.rules)
|
||||
# Linux specific code
|
||||
set(OperatingSystem "Linux")
|
||||
|
||||
elseif(WIN32)
|
||||
|
||||
if(NOT WIN_DO_FULL_INSTALL)
|
||||
# Just copy supporting DLLs to build folder
|
||||
set(INSTALL_DESTINATION "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
||||
message(STATUS "Partial install to " ${INSTALL_DESTINATION})
|
||||
else()
|
||||
# Full Windows installation with all supporting files
|
||||
set(INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
message(STATUS "Full install to " ${INSTALL_DESTINATION})
|
||||
# companion & simulator binaries
|
||||
install(TARGETS ${COMPANION_NAME} DESTINATION ${INSTALL_DESTINATION})
|
||||
install(TARGETS ${SIMULATOR_NAME} DESTINATION ${INSTALL_DESTINATION})
|
||||
install(FILES ${simulator_plugins} DESTINATION "${INSTALL_DESTINATION}")
|
||||
# supporting utilities
|
||||
set(INSTALL_TEMP_FILES avrdude.exe avrdude.conf dfu-util.exe libusb0.dll libusb-1.0.dll license.txt)
|
||||
foreach(tmpfile ${INSTALL_TEMP_FILES})
|
||||
install(FILES "${COMPANION_SRC_DIRECTORY}/../targets/windows/${tmpfile}" DESTINATION ${INSTALL_DESTINATION})
|
||||
endforeach()
|
||||
endif() # WIN_DO_FULL_INSTALL
|
||||
|
||||
# Qt dlls (using windeployqt)
|
||||
## Qt translations are already packaged into our custom qrc. Also don't need software rendering engines.
|
||||
set(wdqtopts --no-translations --no-opengl-sw --no-system-d3d-compiler --no-angle)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
set(wdqtopts ${wdqtopts} --release) # release builds aren't always properly detected with mingw
|
||||
endif()
|
||||
if(MSVC)
|
||||
set(wdqtopts ${wdqtopts} --no-compiler-runtime) # --compiler-runtime includes vcredist_x86, but we just copy the required DLLs manually
|
||||
endif()
|
||||
set(wdqtopts ${wdqtopts} -dir "${INSTALL_DESTINATION}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${COMPANION_NAME}.exe" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${SIMULATOR_NAME}.exe")
|
||||
# Add installer command to execute windeployqt
|
||||
install(CODE "execute_process(COMMAND \"${QT_BIN_DIR}/windeployqt.exe\" ${wdqtopts})")
|
||||
|
||||
# SDL dll
|
||||
if(SDL_FOUND AND EXISTS "${SDL_LIBRARY_PATH}/SDL.dll")
|
||||
set(SDL_DIR ${SDL_LIBRARY_PATH}) # this is also used by NSIS installer script
|
||||
install(FILES ${SDL_DIR}/SDL.dll DESTINATION ${INSTALL_DESTINATION})
|
||||
elseif(SDL_FOUND)
|
||||
message(WARNING "Installer: SDL.dll not found, set SDL_LIBRARY_PATH manually.")
|
||||
endif()
|
||||
|
||||
# libeay (SSL) dlls (used by QtNetwork) -- not strictly required but avoids possible issues with downloads and Qt warnings.
|
||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" WIN_PROGRAM_FILES)
|
||||
find_path(EAY_LIB_DIR libeay32.dll HINTS
|
||||
"${WIN_PROGRAM_FILES}/OpenSSL" "${WIN_PROGRAM_FILES}/OpenSSL-Win32"
|
||||
"C:/OpenSSL/" "C:/OpenSSL-Win32/"
|
||||
"${WIN_EXTRA_LIBS_PATH}" "${WIN_EXTRA_LIBS_PATH}/OpenSSL" "${WIN_EXTRA_LIBS_PATH}/OpenSSL-Win32"
|
||||
"${MINGW_DIR}/../opt/bin"
|
||||
"${PYTHON_DIRECTORY}/lib/site-packages/PyQt4"
|
||||
PATH_SUFFIXES bin
|
||||
DOC "Path to libeay32.dll and ssleay32.dll (OpenSSL)"
|
||||
)
|
||||
if (EAY_LIB_DIR)
|
||||
install(FILES "${EAY_LIB_DIR}/libeay32.dll" "${EAY_LIB_DIR}/ssleay32.dll" DESTINATION ${INSTALL_DESTINATION} OPTIONAL)
|
||||
else()
|
||||
message(WARNING "Installer: SSL libs not found, set EAY_LIB_DIR manually.")
|
||||
endif()
|
||||
|
||||
# C++/system dlls, depends on compiler
|
||||
if(MSVC)
|
||||
file(TO_CMAKE_PATH "$ENV{windir}/SysWOW64" WIN_SYSDIR) # This would be "system32" for a 64-bit build or on x86... but how to tell?
|
||||
if (NOT EXISTS "${WIN_SYSDIR}")
|
||||
file(TO_CMAKE_PATH "$ENV{windir}/system32" WIN_SYSDIR) # Must be 32-bit Windows.
|
||||
endif()
|
||||
install(FILES "${WIN_SYSDIR}/msvcp140.dll" "${WIN_SYSDIR}/vcruntime140.dll" DESTINATION ${INSTALL_DESTINATION} OPTIONAL)
|
||||
if(WIN_PTHREAD_DLL)
|
||||
install(FILES "${WIN_PTHREAD_DLL}" DESTINATION ${INSTALL_DESTINATION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif() # WIN32 install
|
||||
|
||||
############# Packaging ####################
|
||||
|
||||
# Create Windows installer with NSIS
|
||||
if(WIN32)
|
||||
|
||||
find_program(NSIS_EXE makensis.exe PATHS
|
||||
"C:/Program Files/NSIS"
|
||||
"C:/Program Files (x86)/NSIS"
|
||||
"C:/Programs/NSIS"
|
||||
"${WIN_EXTRA_LIBS_PATH}/NSIS"
|
||||
)
|
||||
|
||||
if (NSIS_EXE)
|
||||
file(TO_NATIVE_PATH "${INSTALL_DESTINATION}" NSIS_DISTRO) # all files in here will be included in installer
|
||||
set(NSI_FILE "${PROJECT_BINARY_DIR}/companion/companion.nsi")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../targets/windows/companion.nsi.in" "${NSI_FILE}" @ONLY)
|
||||
|
||||
add_custom_target(installer
|
||||
# The 'install' target prepares all the distro files, make sure it has been executed first.
|
||||
COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --target install
|
||||
COMMAND "${NSIS_EXE}" "${NSI_FILE}"
|
||||
DEPENDS "${NSI_FILE}"
|
||||
COMMENT "Building Windows NSIS installer..."
|
||||
)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
set(CPACK_PACKAGE_NAME "companion${C9X_NAME_SUFFIX}")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Models and settings editor for the OpenTX open source firmware")
|
||||
string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_PACKAGE_NAME_LOWERCASE)
|
||||
|
||||
# The file stripping is deliberately disabled, with the stripped file we get
|
||||
# very poor trace-backs from the users when they report Companion crash
|
||||
set(CPACK_STRIP_FILES FALSE)
|
||||
|
||||
# Qt5 + Cmake + Mac is poorly documented. A lot of this is guesswork
|
||||
# and trial and error. Do not hesitate to fix it for the better
|
||||
IF(APPLE)
|
||||
set(plugin_dest_dir ${COMPANION_NAME}.app/Contents/Plugins)
|
||||
set(qtconf_dest_dir ${COMPANION_NAME}.app/Contents/Resources)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/${COMPANION_NAME}.app")
|
||||
set(companion_res_dir ${COMPANION_NAME}.app/Contents/Resources)
|
||||
|
||||
set_target_properties(${COMPANION_NAME} PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Companion ${VERSION_MAJOR}.${VERSION_MINOR}")
|
||||
set_target_properties(${SIMULATOR_NAME} PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simulator ${VERSION_MAJOR}.${VERSION_MINOR}")
|
||||
|
||||
# Use a non standard Info.plist that adds Retina support flags
|
||||
set_target_properties(${COMPANION_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/companion/targets/mac/MacOSXBundleInfo.plist.in)
|
||||
set_target_properties(${SIMULATOR_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/companion/targets/mac/MacOSXBundleInfo.plist.in)
|
||||
|
||||
INSTALL(TARGETS ${COMPANION_NAME}
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION bin COMPONENT Runtime
|
||||
)
|
||||
|
||||
install(FILES ${simulator_plugins} DESTINATION "${companion_res_dir}" COMPONENT Runtime)
|
||||
|
||||
# Write qt.conf to tell qt where to find it plugins
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
|
||||
"[Paths]\nPlugins = Plugins\n")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
|
||||
DESTINATION "${companion_res_dir}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
# menu file
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/companion/targets/mac/qt_menu.nib DESTINATION "${companion_res_dir}" COMPONENT Runtime)
|
||||
|
||||
# manually add the required plugins
|
||||
foreach (plugin ${Qt5Multimedia_PLUGINS} ${Qt5PrintSupport_PLUGINS} ${Qt5Gui_PLUGINS} ${Qt5Svg_PLUGINS})
|
||||
get_target_property(QPA_PLUGIN ${plugin} LOCATION)
|
||||
get_filename_component(QPA_PLUGIN_FILENAME ${QPA_PLUGIN} NAME)
|
||||
# Todo is there a nicer way to get the QT Plugin directory name?!
|
||||
get_filename_component(QPA_PLUGIN_DIRECTORY ${QPA_PLUGIN} DIRECTORY)
|
||||
get_filename_component(QPA_PLUGIN_DIRECTORY ${QPA_PLUGIN_DIRECTORY} NAME)
|
||||
|
||||
install(FILES ${QPA_PLUGIN} DESTINATION "${plugin_dest_dir}/${QPA_PLUGIN_DIRECTORY}/" COMPONENT Runtime)
|
||||
|
||||
list(APPEND bundle_qt_libs "\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/${QPA_PLUGIN_DIRECTORY}/${QPA_PLUGIN_FILENAME}")
|
||||
endforeach()
|
||||
|
||||
# Add icon
|
||||
set(MACOSX_BUNDLE_ICON_FILE iconmac.icns)
|
||||
set(MAC_ICON_FILE ${COMPANION_SRC_DIRECTORY}/images/${MACOSX_BUNDLE_ICON_FILE})
|
||||
SET_SOURCE_FILES_PROPERTIES(${MAC_ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
set(${COMPANION_SOURCES} ${COMPANION_SOURCES} ${PROJECT_SOURCE_DIR}/images/${MACOSX_BUNDLE_ICON_FILE})
|
||||
install(FILES ${MAC_ICON_FILE} DESTINATION ${companion_res_dir} COMPONENT Runtime)
|
||||
|
||||
# Copy dfu-util and avrdude, resolve symlink first
|
||||
get_filename_component(DFU_UTIL_ABSOLUTE_PATH ${DFU_UTIL_PATH} REALPATH)
|
||||
get_filename_component(AVRDUDE_ABSOLUTE_PATH ${AVRDUDE_PATH} REALPATH)
|
||||
get_filename_component(AVRDUDECONF_ABSOLUTE_PATH ${AVRDUDE_CONF} REALPATH)
|
||||
install(PROGRAMS ${DFU_UTIL_ABSOLUTE_PATH} ${AVRDUDE_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime)
|
||||
install(FILES ${AVRDUDECONF_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime)
|
||||
|
||||
set(bundle_tools_path "\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/dfu-util;\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/avrdude")
|
||||
|
||||
|
||||
# Include depencies (adding frameworks, fixing the embbeded libraries)
|
||||
# I get write errors without setting BU_CHMOD_BUNDLE_ITEMS even though it is
|
||||
# technically a hack (that is already is in the Bundle library ...)
|
||||
install(CODE "
|
||||
include(BundleUtilities)
|
||||
file(GLOB bundle_simulator_libs \"\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/libopentx-*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
|
||||
set(BU_CHMOD_BUNDLE_ITEMS on)
|
||||
fixup_bundle(\"${APPS}\" \"\${bundle_simulator_libs};${bundle_qt_libs};${bundle_tools_path}\" \"${QT_LIB_DIR}\")
|
||||
file(RENAME \"\${CMAKE_INSTALL_PREFIX}/${COMPANION_NAME}.app\" \"\${CMAKE_INSTALL_PREFIX}/${COMPANION_OSX_APP_BUNDLE_NAME}.app\")
|
||||
" COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
execute_process(
|
||||
COMMAND ${DPKG_PROGRAM} --print-architecture
|
||||
OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME_LOWERCASE}_${VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Bertrand Songis <bsongis-nosp@m-gmail.com>")
|
||||
set(CPACK_DEBIAN_PACKAGE_VERSION ${VERSION})
|
||||
set(CPACK_DEBIAN_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
|
||||
set(CPACK_DEBIAN_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
|
||||
set(CPACK_DEBIAN_ARCHITECTURE $(CMAKE_SYSTEM_PROCESSOR))
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins")
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
elseif(APPLE)
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
# set(CPACK_GENERATOR "TGZ") # for quick testing
|
||||
set(CPACK_BINARY_DRAGNDROP ON)
|
||||
set(CPACK_DMG_BACKGROUND_IMAGE ${COMPANION_SRC_DIRECTORY}/images/splash22_3_dmg.png)
|
||||
set(CPACK_DMG_VOLUME_NAME "OpenTX Companion")
|
||||
set(CPACK_DMG_DS_STORE ${PROJECT_SOURCE_DIR}/companion/targets/mac/DS_Store)
|
||||
set(CPACK_PACKAGE_FILE_NAME "opentx-${CPACK_PACKAGE_NAME_LOWERCASE}-${VERSION}")
|
||||
else(DPKG_PROGRAM)
|
||||
set(CPACK_GENERATOR "RPM")
|
||||
set(CPACK_RPM_PACKAGE_VERSION ${VERSION})
|
||||
set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION_SUMMARY})
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME_LOWERCASE}-${VERSION}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/lib /lib/udev /lib/udev/rules.d")
|
||||
endif(DPKG_PROGRAM)
|
||||
|
||||
include(CPack)
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "appdebugmessagehandler.h"
|
||||
|
||||
#include <QFileDevice>
|
||||
|
||||
AppDebugMessageHandler::AppDebugMessageHandler(QObject * parent) :
|
||||
QObject(parent),
|
||||
m_appDebugOutputLevel(APP_DBG_HANDLER_DEFAULT_LEVEL),
|
||||
m_showSourcePath(APP_DBG_HANDLER_SHOW_SRC_PATH),
|
||||
m_showFunctionDeclarations(APP_DBG_HANDLER_SHOW_FUNCTION_DECL)
|
||||
{
|
||||
m_srcPathFilter = QRegularExpression("^" APP_DBG_HANDLER_SRC_PATH "[\\\\\\/](.*?)$", QRegularExpression::InvertedGreedinessOption);
|
||||
m_functionFilter = QRegularExpression("^.+?(\\w+\\().+$");
|
||||
}
|
||||
|
||||
AppDebugMessageHandler * AppDebugMessageHandler::instance()
|
||||
{
|
||||
static AppDebugMessageHandler * _instance = NULL;
|
||||
#if APP_DBG_HANDLER_ENABLE
|
||||
if(_instance == NULL && !qApp->closingDown())
|
||||
_instance = new AppDebugMessageHandler(qApp); // Ensure this object is cleaned up when the QApplication exits.
|
||||
#endif
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void AppDebugMessageHandler::setAppDebugOutputLevel(const quint8 & appDebugOutputLevel)
|
||||
{
|
||||
m_appDebugOutputLevel = appDebugOutputLevel;
|
||||
}
|
||||
|
||||
void AppDebugMessageHandler::setShowSourcePath(bool showSourcePath)
|
||||
{
|
||||
m_showSourcePath = showSourcePath;
|
||||
}
|
||||
|
||||
void AppDebugMessageHandler::setShowFunctionDeclarations(bool showFunctionDeclarations)
|
||||
{
|
||||
m_showFunctionDeclarations = showFunctionDeclarations;
|
||||
}
|
||||
|
||||
void AppDebugMessageHandler::addOutputDevice(QIODevice * device)
|
||||
{
|
||||
if (device && !m_outputDevices.contains(device))
|
||||
m_outputDevices.append(device);
|
||||
}
|
||||
|
||||
void AppDebugMessageHandler::removeOutputDevice(QIODevice * device)
|
||||
{
|
||||
if (device) {
|
||||
// no QVector::removeAll() in Qt < 5.4
|
||||
int i = 0;
|
||||
foreach (QIODevice * d, m_outputDevices) {
|
||||
if (d == device)
|
||||
m_outputDevices.remove(i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppDebugMessageHandler::installAppMessageHandler()
|
||||
{
|
||||
m_defaultHandler = qInstallMessageHandler(g_appDebugMessageHandler);
|
||||
}
|
||||
|
||||
void AppDebugMessageHandler::messageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg)
|
||||
{
|
||||
static const char symbols[] = { 'D', 'W', 'E', 'X', 'I' }; // correspond to QtMsgType enum
|
||||
// normalize types, QtDebugMsg stays 0, QtInfoMsg becomes 1, rest are QtMsgType + 1
|
||||
quint8 lvl = type;
|
||||
if (type == QtInfoMsg)
|
||||
lvl = 1;
|
||||
else if (type > QtDebugMsg)
|
||||
++lvl;
|
||||
|
||||
if (lvl < m_appDebugOutputLevel && type != QtFatalMsg)
|
||||
return;
|
||||
|
||||
#if defined(Q_OS_LINUX) && (QT_VERSION < QT_VERSION_CHECK(5, 3, 0))
|
||||
// Filter out lots of QPainter warnings from undocked QDockWidgets... hackish but effective (only workaround found so far)
|
||||
if (lvl == 2 && QString(context.function).contains("QPainter::"))
|
||||
return;
|
||||
#endif
|
||||
|
||||
QString msgPattern = QString("[%1] ").arg(symbols[type]);
|
||||
|
||||
if (m_showSourcePath) {
|
||||
QString file = QString("%1::").arg(context.file);
|
||||
file.replace(m_srcPathFilter, "\\1");
|
||||
msgPattern.append(file);
|
||||
}
|
||||
if (m_showFunctionDeclarations)
|
||||
msgPattern.append(context.function);
|
||||
else
|
||||
msgPattern.append("%{function}()");
|
||||
|
||||
msgPattern.append(":%{line} -%{if-category} [%{category}]%{endif} %{message}");
|
||||
|
||||
if (type == QtFatalMsg)
|
||||
msgPattern.append("\nBACKTRACE:\n%{backtrace depth=12 separator=\"\n\"}");
|
||||
|
||||
qSetMessagePattern(msgPattern);
|
||||
|
||||
if (!m_defaultHandler || m_outputDevices.size() || receivers(SIGNAL(messageOutput(quint8, const QString &)))) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
|
||||
msgPattern = qFormatLogMessage(type, context, msg);
|
||||
#else
|
||||
msgPattern.replace("%{line}", QString::number(context.line));
|
||||
msgPattern.replace("%{if-category} [%{category}]%{endif}", QString(context.category));
|
||||
msgPattern.replace("%{message}", msg);
|
||||
if (!m_showFunctionDeclarations) {
|
||||
QString func = context.function;
|
||||
msgPattern.replace("%{function}", func.replace(m_functionFilter, "\\1)"));
|
||||
}
|
||||
#endif
|
||||
|
||||
emit messageOutput(lvl, msgPattern);
|
||||
|
||||
foreach (QIODevice * d, m_outputDevices) {
|
||||
if (d && d->isWritable() && (!d->property("level").isValid() || d->property("level").toInt() <= lvl)) {
|
||||
d->write(qPrintable(msgPattern % "\n"));
|
||||
if (QFileDevice * fd = qobject_cast<QFileDevice *>(d))
|
||||
fd->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (QThread::currentThread() == qApp->thread()) // gui thread
|
||||
|
||||
if (m_defaultHandler) {
|
||||
m_defaultHandler(type, context, msg);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s", qPrintable(msgPattern));
|
||||
if (type == QtFatalMsg)
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
// Message handler which is installed using qInstallMessageHandler. This needs to be global.
|
||||
void g_appDebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||
{
|
||||
if (AppDebugMessageHandler::instance())
|
||||
AppDebugMessageHandler::instance()->messageHandler(type, context, msg);
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef APPDEBUGMESSAGEHANDLER_H
|
||||
#define APPDEBUGMESSAGEHANDLER_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QIODevice>
|
||||
#include <QMessageLogContext>
|
||||
#include <QObject>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
|
||||
/*
|
||||
* Custom debug/message handler class to work in conjunction with qDebug() family of functions.
|
||||
* Formats all stderr output generated by the application in a consistent manner.
|
||||
* It can also be used by other event listeners to intercept messages they may be interested in (connect to messageOutput() signal).
|
||||
*
|
||||
* Include this header to use qInfo() safely with Qt < v5.5 (qInfo becomes alias for qDebug).
|
||||
*
|
||||
* Note that the default message format can still be overriden by setting QT_MESSAGE_PATTERN environment variable at _runtime_.
|
||||
* see: https://doc.qt.io/qt-5/qtglobal.html#qSetMessagePattern
|
||||
*
|
||||
* This is an app-wide "global" thread-safe singleton class, use it with AppDebugMessageHandler::instance().
|
||||
* For example, at start of application:
|
||||
*
|
||||
* QApplication app(argc, argv);
|
||||
* AppDebugMessageHandler::instance()->installAppMessageHandler();
|
||||
*
|
||||
* To connect to a signal:
|
||||
*
|
||||
* connect(AppDebugMessageHandler::instance(), &AppDebugMessageHandler::messageOutput, this, &DebugOutput::onAppDebugMessage);
|
||||
*
|
||||
* This singleton will self-destruct upon QApplication termination.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(QT_DEBUG) || defined(DEBUG)
|
||||
#define APP_DBG_HANDLER_IS_DBG_BUILD 1
|
||||
#else
|
||||
#define APP_DBG_HANDLER_IS_DBG_BUILD 0
|
||||
#endif
|
||||
|
||||
// Enable/disable this custom handler handler entirely
|
||||
#ifndef APP_DBG_HANDLER_ENABLE
|
||||
#define APP_DBG_HANDLER_ENABLE 1
|
||||
#endif
|
||||
|
||||
// Default log level (can also be set with setAppDebugOutputLevel()):
|
||||
// 0 = debug+; 1 = info+; 2 = warn+; 3 = critical+; 4 = fatal only
|
||||
#ifndef APP_DBG_HANDLER_DEFAULT_LEVEL
|
||||
#define APP_DBG_HANDLER_DEFAULT_LEVEL 0
|
||||
#endif
|
||||
|
||||
// Include source file path/name in output (filtered with APP_DBG_HANDLER_SRC_PATH)
|
||||
#ifndef APP_DBG_HANDLER_SHOW_SRC_PATH
|
||||
#define APP_DBG_HANDLER_SHOW_SRC_PATH APP_DBG_HANDLER_IS_DBG_BUILD
|
||||
#endif
|
||||
|
||||
// Show just the function Class::name vs. full declaration with return and param types
|
||||
#ifndef APP_DBG_HANDLER_SHOW_FUNCTION_DECL
|
||||
#define APP_DBG_HANDLER_SHOW_FUNCTION_DECL 0
|
||||
#endif
|
||||
|
||||
// base path for source file name filter, everything after this is kept; RegEx, non-greedy
|
||||
#ifndef APP_DBG_HANDLER_SRC_PATH
|
||||
#define APP_DBG_HANDLER_SRC_PATH ".*src"
|
||||
#endif
|
||||
|
||||
// Make sure to include this header if using qInfo()
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))
|
||||
#if defined(QT_NO_INFO_OUTPUT)
|
||||
#define qInfo QT_NO_QDEBUG_MACRO
|
||||
#else
|
||||
#define qInfo qDebug
|
||||
#endif
|
||||
#define QtInfoMsg QtMsgType(4)
|
||||
#endif
|
||||
|
||||
class AppDebugMessageHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// This class implements the singleton design pattern and is therefore publicly accessible only through instance().
|
||||
static AppDebugMessageHandler * instance();
|
||||
AppDebugMessageHandler(AppDebugMessageHandler const &) = delete;
|
||||
void operator = (AppDebugMessageHandler const &) = delete;
|
||||
|
||||
void setAppDebugOutputLevel(const quint8 & appDebugOutputLevel);
|
||||
void setShowSourcePath(bool showSourcePath);
|
||||
void setShowFunctionDeclarations(bool showFunctionDeclarations);
|
||||
void addOutputDevice(QIODevice * device);
|
||||
void removeOutputDevice(QIODevice * device);
|
||||
|
||||
void installAppMessageHandler();
|
||||
void messageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg);
|
||||
|
||||
private:
|
||||
// This class implements the singleton design pattern and therefore has only a private constructor.
|
||||
explicit AppDebugMessageHandler(QObject * parent = Q_NULLPTR);
|
||||
~AppDebugMessageHandler() { }
|
||||
|
||||
QtMessageHandler m_defaultHandler;
|
||||
QRegularExpression m_srcPathFilter;
|
||||
QRegularExpression m_functionFilter;
|
||||
quint8 m_appDebugOutputLevel;
|
||||
QVector<QIODevice *> m_outputDevices;
|
||||
bool m_showSourcePath;
|
||||
bool m_showFunctionDeclarations;
|
||||
|
||||
signals:
|
||||
void messageOutput(quint8 level, const QString & msg);
|
||||
};
|
||||
|
||||
// Message handler which is installed using qInstallMessageHandler. This needs to be global.
|
||||
// Use AppDebugMessageHandler::instance()->installAppMessageHandler();
|
||||
// instead of installing this function directly (it will verify this handler is enabled, etc).
|
||||
void g_appDebugMessageHandler(QtMsgType, const QMessageLogContext &, const QString &);
|
||||
|
||||
#endif // APPDEBUGMESSAGEHANDLER_H
|
||||
@@ -1,560 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "apppreferencesdialog.h"
|
||||
#include "ui_apppreferencesdialog.h"
|
||||
#include "mainwindow.h"
|
||||
#include "appdata.h"
|
||||
#include "helpers.h"
|
||||
#include "storage.h"
|
||||
#if defined(JOYSTICKS)
|
||||
#include "joystick.h"
|
||||
#include "joystickdialog.h"
|
||||
#endif
|
||||
|
||||
AppPreferencesDialog::AppPreferencesDialog(QWidget * parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AppPreferencesDialog),
|
||||
updateLock(false),
|
||||
mainWinHasDirtyChild(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowIcon(CompanionIcon("apppreferences.png"));
|
||||
|
||||
initSettings();
|
||||
connect(ui->downloadVerCB, SIGNAL(currentIndexChanged(int)), this, SLOT(onBaseFirmwareChanged()));
|
||||
connect(ui->opt_appDebugLog, &QCheckBox::toggled, this, &AppPreferencesDialog::toggleAppLogSettings);
|
||||
connect(ui->opt_fwTraceLog, &QCheckBox::toggled, this, &AppPreferencesDialog::toggleAppLogSettings);
|
||||
|
||||
#if !defined(JOYSTICKS)
|
||||
ui->joystickCB->hide();
|
||||
ui->joystickCB->setDisabled(true);
|
||||
ui->joystickcalButton->hide();
|
||||
ui->joystickChkB->hide();
|
||||
ui->label_11->hide();
|
||||
#endif
|
||||
|
||||
shrink();
|
||||
}
|
||||
|
||||
AppPreferencesDialog::~AppPreferencesDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::setMainWinHasDirtyChild(bool value)
|
||||
{
|
||||
mainWinHasDirtyChild = value;
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::accept()
|
||||
{
|
||||
Profile & profile = g.currentProfile();
|
||||
|
||||
g.autoCheckApp(ui->autoCheckCompanion->isChecked());
|
||||
g.OpenTxBranch(AppData::DownloadBranchType(ui->OpenTxBranch->currentIndex()));
|
||||
g.autoCheckFw(ui->autoCheckFirmware->isChecked());
|
||||
g.showSplash(ui->showSplash->isChecked());
|
||||
g.simuSW(ui->simuSW->isChecked());
|
||||
g.removeModelSlots(ui->opt_removeBlankSlots->isChecked());
|
||||
g.newModelAction(ui->opt_newMdl_useWizard->isChecked() ? AppData::MODEL_ACT_WIZARD : ui->opt_newMdl_useEditor->isChecked() ? AppData::MODEL_ACT_EDITOR : AppData::MODEL_ACT_NONE);
|
||||
g.historySize(ui->historySize->value());
|
||||
g.backLight(ui->backLightColor->currentIndex());
|
||||
profile.volumeGain(round(ui->volumeGain->value() * 10.0));
|
||||
g.libDir(ui->libraryPath->text());
|
||||
g.gePath(ui->ge_lineedit->text());
|
||||
g.embedSplashes(ui->splashincludeCB->currentIndex());
|
||||
g.enableBackup(ui->backupEnable->isChecked());
|
||||
|
||||
g.appDebugLog(ui->opt_appDebugLog->isChecked());
|
||||
g.fwTraceLog(ui->opt_fwTraceLog->isChecked());
|
||||
g.appLogsDir(ui->appLogsDir->text());
|
||||
|
||||
if (ui->joystickChkB ->isChecked() && ui->joystickCB->isEnabled()) {
|
||||
g.jsSupport(ui->joystickChkB ->isChecked());
|
||||
g.jsCtrl(ui->joystickCB ->currentIndex());
|
||||
}
|
||||
else {
|
||||
g.jsSupport(false);
|
||||
g.jsCtrl(0);
|
||||
}
|
||||
profile.channelOrder(ui->channelorderCB->currentIndex());
|
||||
profile.defaultMode(ui->stickmodeCB->currentIndex());
|
||||
profile.renameFwFiles(ui->renameFirmware->isChecked());
|
||||
profile.burnFirmware(ui->burnFirmware->isChecked());
|
||||
profile.sdPath(ui->sdPath->text());
|
||||
profile.pBackupDir(ui->profilebackupPath->text());
|
||||
profile.penableBackup(ui->pbackupEnable->isChecked());
|
||||
profile.splashFile(ui->SplashFileName->text());
|
||||
|
||||
// The profile name may NEVER be empty
|
||||
if (ui->profileNameLE->text().isEmpty())
|
||||
profile.name(tr("My Radio"));
|
||||
else
|
||||
profile.name(ui->profileNameLE->text());
|
||||
|
||||
bool fwchange = false;
|
||||
Firmware * newFw = getFirmwareVariant(); // always !null
|
||||
// If a new fw type has been choosen, several things need to reset
|
||||
if (Firmware::getCurrentVariant()->getId() != newFw->getId()) {
|
||||
// check if we're going to be converting to a new radio type and there are unsaved files in the main window
|
||||
if (mainWinHasDirtyChild && !Boards::isBoardCompatible(Firmware::getCurrentVariant()->getBoard(), newFw->getBoard())) {
|
||||
QString q = tr("<p><b>You cannot switch Radio Type or change Build Options while there are unsaved file changes. What do you wish to do?</b></p> <ul>" \
|
||||
"<li><i>Save All</i> - Save any open file(s) before saving Settings.<li>" \
|
||||
"<li><i>Reset</i> - Revert to the previous Radio Type and Build Options before saving Settings.</li>" \
|
||||
"<li><i>Cancel</i> - Return to the Settings editor dialog.</li></ul>");
|
||||
int resp = QMessageBox::question(this, windowTitle(), q, (QMessageBox::SaveAll | QMessageBox::Reset | QMessageBox::Cancel), QMessageBox::Cancel);
|
||||
if (resp == QMessageBox::SaveAll) {
|
||||
// signal main window to save files, need to do this before the fw actually changes
|
||||
emit firmwareProfileAboutToChange();
|
||||
}
|
||||
else if (resp == QMessageBox::Reset) {
|
||||
// bail out early before saving the radio type & firmware options
|
||||
QDialog::accept();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// we do not accept the dialog close
|
||||
return;
|
||||
}
|
||||
}
|
||||
Firmware::setCurrentVariant(newFw);
|
||||
profile.fwName("");
|
||||
profile.resetFwVariables();
|
||||
profile.fwType(newFw->getId());
|
||||
fwchange = true;
|
||||
}
|
||||
|
||||
QDialog::accept();
|
||||
|
||||
if (fwchange)
|
||||
emit firmwareProfileChanged(); // important to do this after the accepted() signal
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::on_snapshotPathButton_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getExistingDirectory(this, tr("Select your snapshot folder"), g.snapshotDir());
|
||||
if (!fileName.isEmpty()) {
|
||||
g.snapshotDir(fileName);
|
||||
g.snapToClpbrd(false);
|
||||
ui->snapshotPath->setText(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::initSettings()
|
||||
{
|
||||
const Profile & profile = g.currentProfile();
|
||||
|
||||
ui->snapshotClipboardCKB->setChecked(g.snapToClpbrd());
|
||||
ui->burnFirmware->setChecked(profile.burnFirmware());
|
||||
ui->snapshotPath->setText(g.snapshotDir());
|
||||
ui->snapshotPath->setReadOnly(true);
|
||||
if (ui->snapshotClipboardCKB->isChecked()) {
|
||||
ui->snapshotPath->setDisabled(true);
|
||||
ui->snapshotPathButton->setDisabled(true);
|
||||
}
|
||||
|
||||
#if !defined(ALLOW_NIGHTLY_BUILDS)
|
||||
// remove nightly version option entirely unless it's the current one (because user might have nightly version also installed)
|
||||
if (g.OpenTxBranch() != AppData::BRANCH_NIGHTLY_UNSTABLE)
|
||||
ui->OpenTxBranch->removeItem(2);
|
||||
// if it's already selected, add a warning message
|
||||
else
|
||||
ui->updatesLayout->addWidget(new QLabel("<font color='red'>" % tr("Note: Nightly builds are not available in this version, Release/RC update channel will be used.") % "</font>", this));
|
||||
#endif
|
||||
ui->OpenTxBranch->setCurrentIndex(g.OpenTxBranch());
|
||||
|
||||
ui->autoCheckCompanion->setChecked(g.autoCheckApp());
|
||||
ui->autoCheckFirmware->setChecked(g.autoCheckFw());
|
||||
ui->showSplash->setChecked(g.showSplash());
|
||||
ui->historySize->setValue(g.historySize());
|
||||
ui->backLightColor->setCurrentIndex(g.backLight());
|
||||
ui->volumeGain->setValue(profile.volumeGain() / 10.0);
|
||||
|
||||
if (IS_TARANIS(getCurrentBoard())) {
|
||||
ui->backLightColor->setEnabled(false);
|
||||
}
|
||||
|
||||
ui->simuSW->setChecked(g.simuSW());
|
||||
ui->opt_removeBlankSlots->setChecked(g.removeModelSlots());
|
||||
ui->opt_newMdl_useNone->setChecked(g.newModelAction() == AppData::MODEL_ACT_NONE);
|
||||
ui->opt_newMdl_useWizard->setChecked(g.newModelAction() == AppData::MODEL_ACT_WIZARD);
|
||||
ui->opt_newMdl_useEditor->setChecked(g.newModelAction() == AppData::MODEL_ACT_EDITOR);
|
||||
ui->libraryPath->setText(g.libDir());
|
||||
ui->ge_lineedit->setText(g.gePath());
|
||||
|
||||
if (!g.backupDir().isEmpty()) {
|
||||
if (QDir(g.backupDir()).exists()) {
|
||||
ui->backupPath->setText(g.backupDir());
|
||||
ui->backupEnable->setEnabled(true);
|
||||
ui->backupEnable->setChecked(g.enableBackup());
|
||||
}
|
||||
else {
|
||||
ui->backupEnable->setDisabled(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ui->backupEnable->setDisabled(true);
|
||||
}
|
||||
ui->splashincludeCB->setCurrentIndex(g.embedSplashes());
|
||||
|
||||
ui->opt_appDebugLog->setChecked(g.appDebugLog());
|
||||
ui->opt_fwTraceLog->setChecked(g.fwTraceLog());
|
||||
ui->appLogsDir->setText(g.appLogsDir());
|
||||
toggleAppLogSettings();
|
||||
|
||||
#if defined(JOYSTICKS)
|
||||
ui->joystickChkB->setChecked(g.jsSupport());
|
||||
if (ui->joystickChkB->isChecked()) {
|
||||
QStringList joystickNames;
|
||||
joystickNames << tr("No joysticks found");
|
||||
joystick = new Joystick(0,false,0,0);
|
||||
ui->joystickcalButton->setDisabled(true);
|
||||
ui->joystickCB->setDisabled(true);
|
||||
|
||||
if ( joystick ) {
|
||||
if ( joystick->joystickNames.count() > 0 ) {
|
||||
joystickNames = joystick->joystickNames;
|
||||
ui->joystickCB->setEnabled(true);
|
||||
ui->joystickcalButton->setEnabled(true);
|
||||
}
|
||||
joystick->close();
|
||||
}
|
||||
ui->joystickCB->clear();
|
||||
ui->joystickCB->insertItems(0, joystickNames);
|
||||
ui->joystickCB->setCurrentIndex(g.jsCtrl());
|
||||
}
|
||||
else {
|
||||
ui->joystickCB->clear();
|
||||
ui->joystickCB->setDisabled(true);
|
||||
ui->joystickcalButton->setDisabled(true);
|
||||
}
|
||||
#endif
|
||||
// Profile Tab Inits
|
||||
ui->channelorderCB->setCurrentIndex(profile.channelOrder());
|
||||
ui->stickmodeCB->setCurrentIndex(profile.defaultMode());
|
||||
ui->renameFirmware->setChecked(profile.renameFwFiles());
|
||||
ui->sdPath->setText(profile.sdPath());
|
||||
if (!profile.pBackupDir().isEmpty()) {
|
||||
if (QDir(profile.pBackupDir()).exists()) {
|
||||
ui->profilebackupPath->setText(profile.pBackupDir());
|
||||
ui->pbackupEnable->setEnabled(true);
|
||||
ui->pbackupEnable->setChecked(profile.penableBackup());
|
||||
} else {
|
||||
ui->pbackupEnable->setDisabled(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ui->pbackupEnable->setDisabled(true);
|
||||
}
|
||||
|
||||
ui->profileNameLE->setText(profile.name());
|
||||
|
||||
QString hwSettings;
|
||||
if (profile.stickPotCalib() == "" ) {
|
||||
hwSettings = tr("EMPTY: No radio settings stored in profile");
|
||||
}
|
||||
else {
|
||||
QString str = profile.timeStamp();
|
||||
if (str.isEmpty())
|
||||
hwSettings = tr("AVAILABLE: Radio settings of unknown age");
|
||||
else
|
||||
hwSettings = tr("AVAILABLE: Radio settings stored %1").arg(str);
|
||||
}
|
||||
ui->lblGeneralSettings->setText(hwSettings);
|
||||
|
||||
QString currType = QStringList(profile.fwType().split('-').mid(0, 2)).join('-');
|
||||
foreach(Firmware * firmware, Firmware::getRegisteredFirmwares()) {
|
||||
ui->downloadVerCB->addItem(firmware->getName(), firmware->getId());
|
||||
if (currType == firmware->getId()) {
|
||||
ui->downloadVerCB->setCurrentIndex(ui->downloadVerCB->count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
onBaseFirmwareChanged();
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::on_libraryPathButton_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select your library folder"), g.libDir());
|
||||
if (!fileName.isEmpty()) {
|
||||
g.libDir(fileName);
|
||||
ui->libraryPath->setText(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::on_snapshotClipboardCKB_clicked()
|
||||
{
|
||||
if (ui->snapshotClipboardCKB->isChecked()) {
|
||||
ui->snapshotPath->setDisabled(true);
|
||||
ui->snapshotPathButton->setDisabled(true);
|
||||
g.snapToClpbrd(true);
|
||||
}
|
||||
else {
|
||||
ui->snapshotPath->setEnabled(true);
|
||||
ui->snapshotPath->setReadOnly(true);
|
||||
ui->snapshotPathButton->setEnabled(true);
|
||||
g.snapToClpbrd(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::on_backupPathButton_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select your Models and Settings backup folder"), g.backupDir());
|
||||
if (!fileName.isEmpty()) {
|
||||
g.backupDir(fileName);
|
||||
ui->backupPath->setText(fileName);
|
||||
ui->backupEnable->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::on_ProfilebackupPathButton_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select your Models and Settings backup folder"), g.backupDir());
|
||||
if (!fileName.isEmpty()) {
|
||||
ui->profilebackupPath->setText(fileName);
|
||||
ui->pbackupEnable->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AppPreferencesDialog::on_btn_appLogsDir_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getExistingDirectory(this, tr("Select a folder for application logs"), ui->appLogsDir->text());
|
||||
if (!fileName.isEmpty()) {
|
||||
ui->appLogsDir->setText(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::on_ge_pathButton_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select Google Earth executable"),ui->ge_lineedit->text());
|
||||
if (!fileName.isEmpty()) {
|
||||
ui->ge_lineedit->setText(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(JOYSTICKS)
|
||||
void AppPreferencesDialog::on_joystickChkB_clicked() {
|
||||
if (ui->joystickChkB->isChecked()) {
|
||||
QStringList joystickNames;
|
||||
joystickNames << tr("No joysticks found");
|
||||
joystick = new Joystick(0,false,0,0);
|
||||
ui->joystickcalButton->setDisabled(true);
|
||||
ui->joystickCB->setDisabled(true);
|
||||
|
||||
if ( joystick ) {
|
||||
if ( joystick->joystickNames.count() > 0 ) {
|
||||
joystickNames = joystick->joystickNames;
|
||||
ui->joystickCB->setEnabled(true);
|
||||
ui->joystickcalButton->setEnabled(true);
|
||||
}
|
||||
joystick->close();
|
||||
}
|
||||
ui->joystickCB->clear();
|
||||
ui->joystickCB->insertItems(0, joystickNames);
|
||||
}
|
||||
else {
|
||||
ui->joystickCB->clear();
|
||||
ui->joystickCB->setDisabled(true);
|
||||
ui->joystickcalButton->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::on_joystickcalButton_clicked() {
|
||||
joystickDialog * jd=new joystickDialog(this, ui->joystickCB->currentIndex());
|
||||
jd->exec();
|
||||
}
|
||||
#endif
|
||||
|
||||
// ******** Profile tab functions
|
||||
|
||||
void AppPreferencesDialog::on_sdPathButton_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select the folder replicating your SD structure"), g.currentProfile().sdPath());
|
||||
if (!fileName.isEmpty()) {
|
||||
ui->sdPath->setText(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
bool AppPreferencesDialog::displayImage(const QString & fileName)
|
||||
{
|
||||
// Start by clearing the label
|
||||
ui->imageLabel->clear();
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return false;
|
||||
|
||||
QImage image(fileName);
|
||||
if (image.isNull())
|
||||
return false;
|
||||
|
||||
ui->imageLabel->setPixmap(makePixMap(image));
|
||||
ui->imageLabel->setFixedSize(getCurrentFirmware()->getCapability(LcdWidth), getCurrentFirmware()->getCapability(LcdHeight));
|
||||
return true;
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::on_SplashSelect_clicked()
|
||||
{
|
||||
QString supportedImageFormats;
|
||||
for (int formatIndex = 0; formatIndex < QImageReader::supportedImageFormats().count(); formatIndex++) {
|
||||
supportedImageFormats += QLatin1String(" *.") + QImageReader::supportedImageFormats()[formatIndex];
|
||||
}
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(this,
|
||||
tr("Open Image to load"), g.imagesDir(), tr("Images (%1)").arg(supportedImageFormats));
|
||||
|
||||
if (!fileName.isEmpty()){
|
||||
g.imagesDir(QFileInfo(fileName).dir().absolutePath());
|
||||
|
||||
displayImage(fileName);
|
||||
ui->SplashFileName->setText(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::on_clearImageButton_clicked()
|
||||
{
|
||||
ui->imageLabel->clear();
|
||||
ui->SplashFileName->clear();
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::onBaseFirmwareChanged()
|
||||
{
|
||||
populateFirmwareOptions(getBaseFirmware());
|
||||
}
|
||||
|
||||
Firmware *AppPreferencesDialog::getBaseFirmware() const
|
||||
{
|
||||
return Firmware::getFirmwareForId(ui->downloadVerCB->currentData().toString());
|
||||
}
|
||||
|
||||
Firmware * AppPreferencesDialog::getFirmwareVariant() const
|
||||
{
|
||||
QString id = ui->downloadVerCB->currentData().toString();
|
||||
|
||||
foreach(QCheckBox *cb, optionsCheckBoxes.values()) {
|
||||
if (cb->isChecked())
|
||||
id += "-" + cb->text();
|
||||
}
|
||||
|
||||
if (ui->langCombo->count())
|
||||
id += "-" + ui->langCombo->currentText();
|
||||
|
||||
return Firmware::getFirmwareForId(id);
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::onFirmwareOptionChanged(bool state)
|
||||
{
|
||||
QCheckBox *cb = qobject_cast<QCheckBox*>(sender());
|
||||
if (!(cb && state))
|
||||
return;
|
||||
|
||||
// This de-selects any mutually exlusive options (that is, members of the same QList<Option> list).
|
||||
const Firmware::OptionsList & fwOpts = getBaseFirmware()->optionGroups();
|
||||
for (const Firmware::OptionsGroup & optGrp : fwOpts) {
|
||||
for (const Firmware::Option & opt : optGrp) {
|
||||
if (cb->text() == opt.name) {
|
||||
QCheckBox *ocb = nullptr;
|
||||
foreach(const Firmware::Option & other, optGrp)
|
||||
if (other.name != opt.name && (ocb = optionsCheckBoxes.value(other.name, nullptr)))
|
||||
ocb->setChecked(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::toggleAppLogSettings()
|
||||
{
|
||||
bool vis = (ui->opt_appDebugLog->isChecked() || ui->opt_fwTraceLog->isChecked());
|
||||
ui->appLogsDir->setVisible(vis);
|
||||
ui->lbl_appLogsDir->setVisible(vis);
|
||||
ui->btn_appLogsDir->setVisible(vis);
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::populateFirmwareOptions(const Firmware * firmware)
|
||||
{
|
||||
const Firmware * baseFw = firmware->getFirmwareBase();
|
||||
QStringList currVariant = Firmware::getCurrentVariant()->getId().split('-');
|
||||
const QString currLang = ui->langCombo->count() ? ui->langCombo->currentText() : currVariant.last();
|
||||
|
||||
updateLock = true;
|
||||
|
||||
ui->langCombo->clear();
|
||||
for (const char *lang : baseFw->languageList()) {
|
||||
ui->langCombo->addItem(lang);
|
||||
if (currLang == lang) {
|
||||
ui->langCombo->setCurrentIndex(ui->langCombo->count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (optionsCheckBoxes.size()) {
|
||||
currVariant.clear();
|
||||
QMutableMapIterator<QString, QCheckBox *> it(optionsCheckBoxes);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
QCheckBox * cb = it.value();
|
||||
if (cb->isChecked())
|
||||
currVariant.append(it.key()); // keep previous selections
|
||||
ui->optionsLayout->removeWidget(cb);
|
||||
cb->deleteLater();
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
QWidget * prevFocus = ui->langCombo;
|
||||
for (const Firmware::OptionsGroup &optGrp : baseFw->optionGroups()) {
|
||||
for (const Firmware::Option &opt : optGrp) {
|
||||
QCheckBox * cb = new QCheckBox(ui->profileTab);
|
||||
cb->setText(opt.name);
|
||||
cb->setToolTip(opt.tooltip);
|
||||
cb->setChecked(currVariant.contains(opt.name));
|
||||
ui->optionsLayout->addWidget(cb, index / 4, index % 4);
|
||||
QWidget::setTabOrder(prevFocus, cb);
|
||||
// connect to duplicates check handler if this option is part of a group
|
||||
if (optGrp.size() > 1)
|
||||
connect(cb, &QCheckBox::toggled, this, &AppPreferencesDialog::onFirmwareOptionChanged);
|
||||
optionsCheckBoxes.insert(opt.name, cb);
|
||||
prevFocus = cb;
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove once splash replacement supported on Horus
|
||||
// NOTE: 480x272 image causes issues on screens <800px high, needs a solution like scrolling once reinstated
|
||||
if (IS_HORUS(baseFw->getBoard())) {
|
||||
ui->widget_splashImage->hide();
|
||||
ui->SplashFileName->setText("");
|
||||
}
|
||||
else {
|
||||
ui->widget_splashImage->show();
|
||||
ui->SplashFileName->setText(g.currentProfile().splashFile());
|
||||
displayImage(g.currentProfile().splashFile());
|
||||
}
|
||||
|
||||
updateLock = false;
|
||||
QTimer::singleShot(50, this, &AppPreferencesDialog::shrink);
|
||||
}
|
||||
|
||||
void AppPreferencesDialog::shrink()
|
||||
{
|
||||
adjustSize();
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _APPPREFERENCESDIALOG_H_
|
||||
#define _APPPREFERENCESDIALOG_H_
|
||||
|
||||
#include <QDialog>
|
||||
#include <QCheckBox>
|
||||
#include "eeprominterface.h"
|
||||
|
||||
namespace Ui {
|
||||
class AppPreferencesDialog;
|
||||
}
|
||||
|
||||
class Joystick;
|
||||
|
||||
class AppPreferencesDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AppPreferencesDialog(QWidget * parent = 0);
|
||||
~AppPreferencesDialog();
|
||||
|
||||
Joystick * joystick;
|
||||
|
||||
public slots:
|
||||
void accept() Q_DECL_OVERRIDE;
|
||||
void setMainWinHasDirtyChild(bool value);
|
||||
|
||||
signals:
|
||||
void firmwareProfileChanged();
|
||||
void firmwareProfileAboutToChange(bool saveFiles = true);
|
||||
|
||||
protected slots:
|
||||
void shrink();
|
||||
void onBaseFirmwareChanged();
|
||||
void onFirmwareOptionChanged(bool state);
|
||||
void toggleAppLogSettings();
|
||||
|
||||
void on_libraryPathButton_clicked();
|
||||
void on_snapshotPathButton_clicked();
|
||||
void on_snapshotClipboardCKB_clicked();
|
||||
void on_backupPathButton_clicked();
|
||||
void on_ProfilebackupPathButton_clicked();
|
||||
void on_ge_pathButton_clicked();
|
||||
|
||||
void on_sdPathButton_clicked();
|
||||
void on_SplashSelect_clicked();
|
||||
void on_clearImageButton_clicked();
|
||||
void on_btn_appLogsDir_clicked();
|
||||
|
||||
#if defined(JOYSTICKS)
|
||||
void on_joystickChkB_clicked();
|
||||
void on_joystickcalButton_clicked();
|
||||
#endif
|
||||
|
||||
private:
|
||||
void initSettings();
|
||||
void populateFirmwareOptions(const Firmware *);
|
||||
Firmware * getBaseFirmware() const;
|
||||
Firmware * getFirmwareVariant() const;
|
||||
bool displayImage(const QString & fileName);
|
||||
|
||||
Ui::AppPreferencesDialog *ui;
|
||||
QMap<QString, QCheckBox *> optionsCheckBoxes;
|
||||
bool updateLock;
|
||||
bool mainWinHasDirtyChild;
|
||||
};
|
||||
|
||||
#endif // _APPPREFERENCESDIALOG_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,390 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "burnconfigdialog.h"
|
||||
#include "ui_burnconfigdialog.h"
|
||||
#include "eeprominterface.h"
|
||||
#include "helpers.h"
|
||||
#include "appdata.h"
|
||||
#include "progressdialog.h"
|
||||
#include "process_flash.h"
|
||||
|
||||
#if !defined _MSC_VER && defined __GNUC__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
burnConfigDialog::burnConfigDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::burnConfigDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowIcon(CompanionIcon("configure.png"));
|
||||
ui->avrdude_programmer->model()->sort(0);
|
||||
|
||||
getSettings();
|
||||
populateProgrammers();
|
||||
Board::Type board = getCurrentBoard();
|
||||
if (IS_STM32(board)) {
|
||||
setWindowTitle(tr("DFU-UTIL Configuration"));
|
||||
ui->avrArgs->hide();
|
||||
ui->avrdude_location->hide();
|
||||
ui->avrdude_port->hide();
|
||||
ui->avrdude_programmer->hide();
|
||||
ui->label_av1->hide();
|
||||
ui->label_av2->hide();
|
||||
ui->label_av4->hide();
|
||||
ui->label_av5->hide();
|
||||
ui->pushButton->hide();
|
||||
ui->pushButton_3->hide();
|
||||
ui->pushButton_4->hide();
|
||||
ui->label_sb1->hide();
|
||||
ui->label_sb3->hide();
|
||||
ui->samba_location->hide();
|
||||
ui->samba_port->hide();
|
||||
ui->sb_browse->hide();
|
||||
}
|
||||
else if (IS_SKY9X(board)) {
|
||||
setWindowTitle(tr("SAM-BA Configuration"));
|
||||
ui->avrArgs->hide();
|
||||
ui->avrdude_location->hide();
|
||||
ui->avrdude_port->hide();
|
||||
ui->avrdude_programmer->hide();
|
||||
ui->label_av1->hide();
|
||||
ui->label_av2->hide();
|
||||
ui->label_av4->hide();
|
||||
ui->label_av5->hide();
|
||||
ui->pushButton->hide();
|
||||
ui->pushButton_3->hide();
|
||||
ui->pushButton_4->hide();
|
||||
ui->label_dfu1->hide();
|
||||
ui->dfu_location->hide();
|
||||
ui->dfu_browse->hide();
|
||||
}
|
||||
else {
|
||||
setWindowTitle(tr("AVRDUDE Configuration"));
|
||||
ui->label_sb1->hide();
|
||||
ui->label_sb3->hide();
|
||||
ui->samba_location->hide();
|
||||
ui->samba_port->hide();
|
||||
ui->sb_browse->hide();
|
||||
ui->label_dfu1->hide();
|
||||
ui->label_dfu2->hide();
|
||||
ui->dfu_location->hide();
|
||||
ui->dfu_browse->hide();
|
||||
}
|
||||
ui->label_av3->hide();
|
||||
ui->avrdude_mcu->hide();
|
||||
ui->label_sb2->hide();
|
||||
ui->arm_mcu->hide();
|
||||
ui->label_dfu2->hide();
|
||||
ui->dfuArgs->hide();
|
||||
|
||||
QTimer::singleShot(0, this, SLOT(shrink()));
|
||||
connect(this, SIGNAL(accepted()), this, SLOT(putSettings()));
|
||||
}
|
||||
|
||||
burnConfigDialog::~burnConfigDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QStringList burnConfigDialog::getAvrdudeArgs()
|
||||
{
|
||||
QStringList args = avrArgs;
|
||||
if (!avrPort.isEmpty())
|
||||
args << "-P" << avrPort;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
args << "-C" << QFileInfo(QApplication::applicationDirPath() + "/../Resources/avrdude.conf").absoluteFilePath();
|
||||
#endif
|
||||
return args;
|
||||
}
|
||||
|
||||
void burnConfigDialog::getSettings()
|
||||
{
|
||||
avrLoc = g.avrdudeLocation();
|
||||
sambaLoc = g.sambaLocation();
|
||||
dfuLoc = g.dfuLocation();
|
||||
|
||||
#if defined WIN32 || !defined __GNUC__
|
||||
if ( avrLoc.isEmpty())
|
||||
avrLoc = QFileInfo("avrdude.exe").absoluteFilePath();
|
||||
if ( sambaLoc.isEmpty())
|
||||
sambaLoc = QFileInfo("sam-ba.exe").absoluteFilePath();
|
||||
if ( dfuLoc.isEmpty())
|
||||
dfuLoc = QFileInfo("dfu-util.exe").absoluteFilePath();
|
||||
#elif defined __APPLE__
|
||||
if ( avrLoc.isEmpty())
|
||||
avrLoc = QFileInfo(QApplication::applicationDirPath() + "/../Resources/avrdude").absoluteFilePath();
|
||||
if ( sambaLoc.isEmpty())
|
||||
sambaLoc = "/usr/local/bin/sam-ba";
|
||||
if ( dfuLoc.isEmpty())
|
||||
dfuLoc = QFileInfo(QApplication::applicationDirPath() + "/../Resources/dfu-util").absoluteFilePath();
|
||||
#elif defined __FreeBSD__
|
||||
if (avrLoc.isEmpty())
|
||||
avrLoc = "/usr/local/bin/avrdude";
|
||||
if (dfuLoc.isEmpty())
|
||||
dfuLoc = "/usr/local/bin/dfu-util";
|
||||
#else
|
||||
if ( avrLoc.isEmpty())
|
||||
avrLoc = "/usr/bin/avrdude";
|
||||
if ( sambaLoc.isEmpty())
|
||||
sambaLoc = "/usr/bin/sam-ba";
|
||||
if ( dfuLoc.isEmpty())
|
||||
dfuLoc = QFileInfo("/usr/bin/dfu-util").absoluteFilePath();
|
||||
#endif
|
||||
|
||||
dfuArgs = g.dfuArguments().split(" ", QString::SkipEmptyParts);
|
||||
avrArgs = g.avrArguments().split(" ", QString::SkipEmptyParts);
|
||||
avrProgrammer = g.programmer();
|
||||
avrPort = g.avrPort();
|
||||
avrMCU = g.mcu();
|
||||
armMCU = g.armMcu();
|
||||
sambaPort = g.sambaPort();
|
||||
|
||||
ui->avrdude_location->setText(getAVRDUDE());
|
||||
ui->avrArgs->setText(avrArgs.join(" "));
|
||||
|
||||
ui->samba_location->setText(getSAMBA());
|
||||
ui->samba_port->setText(getSambaPort());
|
||||
|
||||
ui->dfu_location->setText(getDFU());
|
||||
ui->dfuArgs->setText(getDFUArgs().join(" "));
|
||||
|
||||
int idx1 = ui->avrdude_programmer->findText(getProgrammer());
|
||||
int idx2 = ui->avrdude_port->findText(getPort());
|
||||
int idx3 = ui->avrdude_mcu->findText(getMCU());
|
||||
int idx4 = ui->arm_mcu->findText(getArmMCU());
|
||||
if(idx1>=0) ui->avrdude_programmer->setCurrentIndex(idx1);
|
||||
if(idx2>=0) ui->avrdude_port->setCurrentIndex(idx2);
|
||||
if(idx3>=0) ui->avrdude_mcu->setCurrentIndex(idx3);
|
||||
if(idx4>=0) ui->arm_mcu->setCurrentIndex(idx4);
|
||||
QFile file;
|
||||
if (file.exists(avrLoc)) {
|
||||
ui->pushButton_3->setEnabled(true);
|
||||
} else {
|
||||
ui->pushButton_3->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void burnConfigDialog::putSettings()
|
||||
{
|
||||
g.avrdudeLocation( avrLoc );
|
||||
g.programmer( avrProgrammer);
|
||||
g.mcu( avrMCU );
|
||||
g.avrPort( avrPort );
|
||||
g.avrArguments( avrArgs.join(" ") );
|
||||
g.sambaLocation( sambaLoc );
|
||||
g.sambaPort( sambaPort );
|
||||
g.armMcu( armMCU );
|
||||
g.dfuLocation( dfuLoc );
|
||||
g.dfuArguments( dfuArgs.join(" ") );
|
||||
}
|
||||
|
||||
void burnConfigDialog::populateProgrammers()
|
||||
{
|
||||
QString fileName = QFileInfo(avrLoc).canonicalPath() + "/avrdude.conf"; //for windows
|
||||
if(!QFileInfo(fileName).exists()) fileName = "/etc/avrdude.conf"; //for linux
|
||||
if(!QFileInfo(fileName).exists()) fileName = "/etc/avrdude/avrdude.conf"; //for linux
|
||||
if(!QFileInfo(fileName).exists()) return; // not found avrdude.conf - returning
|
||||
|
||||
QFile file(fileName);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return;
|
||||
|
||||
QStringList items;
|
||||
QString line = "";
|
||||
QString prevline = "";
|
||||
QTextStream in(&file);
|
||||
while (!in.atEnd())
|
||||
{
|
||||
prevline = line;
|
||||
line = in.readLine();
|
||||
|
||||
if(prevline.left(10).toLower()=="programmer")
|
||||
items << line.section('"',1,1);
|
||||
}
|
||||
file.close();
|
||||
|
||||
items.sort();
|
||||
|
||||
QString avrProgrammer_temp = avrProgrammer;
|
||||
ui->avrdude_programmer->clear();
|
||||
ui->avrdude_programmer->addItems(items);
|
||||
int idx1 = ui->avrdude_programmer->findText(avrProgrammer_temp);
|
||||
if(idx1>=0) ui->avrdude_programmer->setCurrentIndex(idx1);
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_avrdude_programmer_currentIndexChanged(QString )
|
||||
{
|
||||
avrProgrammer = ui->avrdude_programmer->currentText();
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_avrdude_mcu_currentIndexChanged(QString )
|
||||
{
|
||||
avrMCU = ui->avrdude_mcu->currentText();
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_avrdude_location_editingFinished()
|
||||
{
|
||||
avrLoc = ui->avrdude_location->text();
|
||||
if (avrLoc.isEmpty()) {
|
||||
ui->pushButton_3->setDisabled(true);
|
||||
} else {
|
||||
QFile file;
|
||||
if (file.exists(avrLoc)) {
|
||||
ui->pushButton_3->setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_avrArgs_editingFinished()
|
||||
{
|
||||
avrArgs = ui->avrArgs->text().split(" ", QString::SkipEmptyParts);
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_avrdude_port_currentIndexChanged(QString )
|
||||
{
|
||||
avrPort = ui->avrdude_port->currentText();
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_samba_location_editingFinished()
|
||||
{
|
||||
sambaLoc = ui->samba_location->text();
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_samba_port_editingFinished()
|
||||
{
|
||||
sambaPort = ui->samba_port->text();
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_arm_mcu_currentIndexChanged(QString )
|
||||
{
|
||||
armMCU = ui->arm_mcu->currentText();
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_pushButton_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select Location"),ui->avrdude_location->text());
|
||||
|
||||
if(!fileName.isEmpty())
|
||||
{
|
||||
ui->avrdude_location->setText(fileName);
|
||||
avrLoc = fileName;
|
||||
}
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_sb_browse_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select Location"),ui->samba_location->text());
|
||||
if(!fileName.isEmpty())
|
||||
{
|
||||
ui->samba_location->setText(fileName);
|
||||
sambaLoc = fileName;
|
||||
}
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_dfu_browse_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select Location"),ui->dfu_location->text());
|
||||
|
||||
if(!fileName.isEmpty())
|
||||
{
|
||||
ui->dfu_location->setText(fileName);
|
||||
dfuLoc = fileName;
|
||||
}
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_dfu_location_editingFinished()
|
||||
{
|
||||
dfuLoc = ui->dfu_location->text();
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_dfuArgs_editingFinished()
|
||||
{
|
||||
dfuArgs = ui->dfuArgs->text().split(" ", QString::SkipEmptyParts);
|
||||
}
|
||||
|
||||
void burnConfigDialog::listAvrdudeProgrammers()
|
||||
{
|
||||
ProgressDialog progressDialog(this, tr("List available programmers"), CompanionIcon("list.png"), true);
|
||||
FlashProcess flashProcess(ui->avrdude_location->text(), QStringList() << "-c?", progressDialog.progress());
|
||||
flashProcess.run();
|
||||
}
|
||||
|
||||
// TODO choose better name when no merge in progress....
|
||||
void burnConfigDialog::on_pushButton_3_clicked()
|
||||
{
|
||||
listAvrdudeProgrammers();
|
||||
}
|
||||
|
||||
// TODO choose better name when no merge in progress....
|
||||
void burnConfigDialog::on_pushButton_4_clicked()
|
||||
{
|
||||
ProgressDialog progressDialog(this, tr("Avrdude help"), CompanionIcon("configure.png"), true);
|
||||
FlashProcess flashProcess(ui->avrdude_location->text(), QStringList() << "-?", progressDialog.progress());
|
||||
flashProcess.run();
|
||||
}
|
||||
|
||||
void burnConfigDialog::on_advCtrChkB_toggled(bool checked)
|
||||
{
|
||||
Board::Type board = getCurrentBoard();
|
||||
if (checked) {
|
||||
if (IS_STM32(board)) {
|
||||
ui->label_dfu2->show();
|
||||
ui->dfuArgs->show();
|
||||
}
|
||||
else if (IS_SKY9X(board)) {
|
||||
ui->label_sb2->show();
|
||||
ui->arm_mcu->show();
|
||||
}
|
||||
else {
|
||||
ui->label_av3->show();
|
||||
ui->avrdude_mcu->show();
|
||||
QMessageBox::warning(this, CPN_STR_APP_NAME,
|
||||
tr("<b><u>WARNING!</u></b><br>Normally CPU type is automatically selected according to the chosen firmware.<br>If you change the CPU type the resulting eeprom could be inconsistent."),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (IS_STM32(board)) {
|
||||
ui->label_dfu2->hide();
|
||||
ui->dfuArgs->hide();
|
||||
}
|
||||
else if (IS_SKY9X(board)) {
|
||||
ui->label_sb2->hide();
|
||||
ui->arm_mcu->hide();
|
||||
}
|
||||
else {
|
||||
ui->label_av3->hide();
|
||||
ui->avrdude_mcu->hide();
|
||||
}
|
||||
}
|
||||
QTimer::singleShot(0, this, SLOT(shrink()));
|
||||
}
|
||||
|
||||
|
||||
void burnConfigDialog::shrink()
|
||||
{
|
||||
resize(0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _BURNCONFIGDIALOG_H_
|
||||
#define _BURNCONFIGDIALOG_H_
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#define MEM_TYPE_EEPROM 1
|
||||
#define MEM_TYPE_FLASH 2
|
||||
|
||||
#define OPR_TYPE_READ 1
|
||||
#define OPR_TYPE_WRITE 2
|
||||
|
||||
namespace Ui {
|
||||
class burnConfigDialog;
|
||||
}
|
||||
|
||||
class burnConfigDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
burnConfigDialog(QWidget *parent = 0);
|
||||
~burnConfigDialog();
|
||||
|
||||
QString getAVRDUDE() {return avrLoc;}
|
||||
QString getSAMBA() {return sambaLoc;}
|
||||
QString getDFU() {return dfuLoc;}
|
||||
QStringList getAvrdudeArgs();
|
||||
QStringList getDFUArgs() {return dfuArgs;}
|
||||
QString getProgrammer() {return avrProgrammer;}
|
||||
QString getMCU() {return avrMCU;}
|
||||
QString getArmMCU() {return armMCU;}
|
||||
QString getPort() {return avrPort;}
|
||||
QString getSambaPort() {return sambaPort;}
|
||||
|
||||
void listAvrdudeProgrammers();
|
||||
|
||||
private:
|
||||
Ui::burnConfigDialog *ui;
|
||||
|
||||
void populateProgrammers();
|
||||
|
||||
QString avrLoc;
|
||||
QString sambaLoc;
|
||||
QString dfuLoc;
|
||||
QStringList avrArgs;
|
||||
QString avrProgrammer;
|
||||
QString avrMCU;
|
||||
QString armMCU;
|
||||
QString avrPort;
|
||||
QString sambaPort;
|
||||
QStringList dfuArgs;
|
||||
|
||||
private slots:
|
||||
void shrink();
|
||||
void on_avrArgs_editingFinished();
|
||||
void on_pushButton_4_clicked();
|
||||
void on_pushButton_3_clicked();
|
||||
void on_pushButton_clicked();
|
||||
void on_avrdude_location_editingFinished();
|
||||
void on_avrdude_programmer_currentIndexChanged(QString );
|
||||
void on_avrdude_mcu_currentIndexChanged(QString );
|
||||
void on_avrdude_port_currentIndexChanged(QString );
|
||||
void on_samba_location_editingFinished();
|
||||
void on_samba_port_editingFinished();
|
||||
void on_arm_mcu_currentIndexChanged(QString );
|
||||
void on_sb_browse_clicked();
|
||||
void on_dfu_browse_clicked();
|
||||
void on_dfu_location_editingFinished();
|
||||
void on_dfuArgs_editingFinished();
|
||||
void on_advCtrChkB_toggled(bool checked);
|
||||
void getSettings();
|
||||
void putSettings();
|
||||
};
|
||||
|
||||
#endif // _BURNCONFIGDIALOG_H_
|
||||
@@ -1,867 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>burnConfigDialog</class>
|
||||
<widget class="QDialog" name="burnConfigDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>531</width>
|
||||
<height>422</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>531</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Programmer Configuration</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="companion.qrc">
|
||||
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="9" column="2">
|
||||
<widget class="QLineEdit" name="dfu_location">
|
||||
<property name="toolTip">
|
||||
<string>Location of sam-ba executable</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>The location of the AVRDUDE executable.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">dfu-util</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_dfu1">
|
||||
<property name="text">
|
||||
<string>DFU-Util Location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="avrdude_location">
|
||||
<property name="toolTip">
|
||||
<string>Location of AVRDUDE executable</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>The location of the AVRDUDE executable.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4" rowspan="2">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="whatsThis">
|
||||
<string>Use this button to browse and look for the AVRDUDE executable file.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_av2">
|
||||
<property name="text">
|
||||
<string>Programmer</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QComboBox" name="avrdude_programmer">
|
||||
<property name="whatsThis">
|
||||
<string>Programmer used for communicating with the controller.
|
||||
Please consult the programmer's documentation and the AVRDUDE documentation to select the appropriate programmer.</string>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertAlphabetically</enum>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">c2n232i</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dasa3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dasa</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">siprog</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">ponyser</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">89isp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">frank-stk200</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">blaster</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">ere-isp-avr</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">atisp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dapa</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">xil</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">futurlec</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">abcmini</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">picoweb</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">sp12</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">alf</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">bascom</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dt006</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">pony-stk200</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">stk200</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">bsd</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">pavr</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dragon_pdi</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dragon_dw</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dragon_hvsp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dragon_pp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dragon_isp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dragon_jtag</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtag2pdi</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtag2avr32</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtagmkII_avr32</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtag2dw</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtag2isp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtag2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtag2fast</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtag2slow</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtagmkII</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtag1slow</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtag1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">jtagmkI</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">avr911</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">avr109</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">butterfly</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">usbtiny</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">usbasp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">avr910</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">stk600hvsp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">stk600pp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">stk600</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">stk500hvsp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">stk500pp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">stk500v2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">mib510</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">stk500v1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">stk500</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">buspirate</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">avrisp2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">avrispmkII</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">avrispv2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">avrisp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">arduino</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="pushButton_3">
|
||||
<property name="whatsThis">
|
||||
<string>List all available programmers.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>List Available</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLineEdit" name="avrArgs">
|
||||
<property name="toolTip">
|
||||
<string>Extra arguments that will be passed to AVRDUDE on every call</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Extra arguments used in AVRDUDE.
|
||||
This can be used for providing extra information to AVRDUDE.
|
||||
|
||||
Please only use this if you know what you are doing. There are no error checks and you could cripple your controller.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_av5">
|
||||
<property name="text">
|
||||
<string>Extra Arguments</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QPushButton" name="pushButton_4">
|
||||
<property name="whatsThis">
|
||||
<string>Show AVRDUDE help</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Help</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QComboBox" name="avrdude_port">
|
||||
<property name="whatsThis">
|
||||
<string>Communication port to the programmer.
|
||||
</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">usb</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com4</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com5</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com6</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com7</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com8</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com9</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com10</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com11</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com12</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com13</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com14</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">com15</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">lpt1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">lpt2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">lpt3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">lpt4</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">avrdoper</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">/dev/ttyUSB0</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">/dev/ttyUSB1</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_av4">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_av1">
|
||||
<property name="text">
|
||||
<string>AVRDUDE Location</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_av3">
|
||||
<property name="text">
|
||||
<string>MCU</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QComboBox" name="avrdude_mcu">
|
||||
<property name="toolTip">
|
||||
<string>CPU of your TX</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>CPU present on your 9x radio
|
||||
Should be m64 for stock radios
|
||||
m2560 for v4.1 boards</string>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertAlphabetically</enum>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">m64</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">m128</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">m2560</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QComboBox" name="arm_mcu">
|
||||
<property name="toolTip">
|
||||
<string>CPU of your TX</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>CPU present on your 9x radio
|
||||
Should be m64 for stock radios
|
||||
m2560 for v4.1 boards</string>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertAlphabetically</enum>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">at91sam3s4-9x</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>at91sam3s8-9xr</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_sb1">
|
||||
<property name="text">
|
||||
<string>SAM-BA Location</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLineEdit" name="samba_location">
|
||||
<property name="toolTip">
|
||||
<string>Location of sam-ba executable</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>The location of the AVRDUDE executable.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">sam-ba.exe</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_sb2">
|
||||
<property name="text">
|
||||
<string>ARM MCU</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_sb3">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QLineEdit" name="samba_port">
|
||||
<property name="toolTip">
|
||||
<string>sam-ba serial port</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>The location of the AVRDUDE executable.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">\USBserial\COM23</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_dfu2">
|
||||
<property name="text">
|
||||
<string>Alternate device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<widget class="QLineEdit" name="dfuArgs">
|
||||
<property name="toolTip">
|
||||
<string>Extra arguments that will be passed to AVRDUDE on every call</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Extra arguments used in AVRDUDE.
|
||||
This can be used for providing extra information to AVRDUDE.
|
||||
|
||||
Please only use this if you know what you are doing. There are no error checks and you could cripple your controller.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="4">
|
||||
<widget class="QPushButton" name="sb_browse">
|
||||
<property name="whatsThis">
|
||||
<string>Use this button to browse and look for the AVRDUDE executable file.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="4">
|
||||
<widget class="QPushButton" name="dfu_browse">
|
||||
<property name="whatsThis">
|
||||
<string>Use this button to browse and look for the AVRDUDE executable file.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="2">
|
||||
<widget class="QCheckBox" name="advCtrChkB">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Use advanced controls</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>avrdude_location</tabstop>
|
||||
<tabstop>pushButton</tabstop>
|
||||
<tabstop>avrdude_programmer</tabstop>
|
||||
<tabstop>pushButton_3</tabstop>
|
||||
<tabstop>avrdude_mcu</tabstop>
|
||||
<tabstop>avrdude_port</tabstop>
|
||||
<tabstop>avrArgs</tabstop>
|
||||
<tabstop>pushButton_4</tabstop>
|
||||
<tabstop>samba_location</tabstop>
|
||||
<tabstop>sb_browse</tabstop>
|
||||
<tabstop>arm_mcu</tabstop>
|
||||
<tabstop>samba_port</tabstop>
|
||||
<tabstop>dfu_location</tabstop>
|
||||
<tabstop>dfu_browse</tabstop>
|
||||
<tabstop>dfuArgs</tabstop>
|
||||
<tabstop>advCtrChkB</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="companion.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>burnConfigDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>burnConfigDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
#include <QSplashScreen>
|
||||
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
|
||||
#include <SDL.h>
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
#include "appdebugmessagehandler.h"
|
||||
#include "customdebug.h"
|
||||
#include "mainwindow.h"
|
||||
#include "version.h"
|
||||
#include "appdata.h"
|
||||
#include "simulatorinterface.h"
|
||||
#include "storage.h"
|
||||
#include "translations.h"
|
||||
#include "helpers.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <QProxyStyle>
|
||||
|
||||
class MyProxyStyle : public QProxyStyle
|
||||
{
|
||||
public:
|
||||
void polish ( QWidget * w ) {
|
||||
QMenu* mn = dynamic_cast<QMenu*>(w);
|
||||
QPushButton* pb = dynamic_cast<QPushButton*>(w);
|
||||
if(!(mn || pb) && !w->testAttribute(Qt::WA_MacNormalSize))
|
||||
w->setAttribute(Qt::WA_MacSmallSize);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
void importError()
|
||||
{
|
||||
QMessageBox::critical(nullptr, CPN_STR_APP_NAME, QCoreApplication::translate("Companion", "The saved settings could not be imported, please try again or continue with current settings."), QMessageBox::Ok, 0);
|
||||
}
|
||||
|
||||
void checkSettingsImport(bool force = false)
|
||||
{
|
||||
QString previousVersion;
|
||||
bool found;
|
||||
if (!(found = g.findPreviousVersionSettings(&previousVersion))) {
|
||||
found = QDir(CPN_SETTINGS_BACKUP_DIR).entryList(QStringList({"*.ini"}), QDir::Files).size() > 0;
|
||||
}
|
||||
if (!found && !force)
|
||||
return;
|
||||
|
||||
const QString impFileBtn = QCoreApplication::translate("Companion", "Import from File");
|
||||
const QString impPrevBtn = QCoreApplication::translate("Companion", "Import from v%1").arg(previousVersion);
|
||||
const QString impNoneBtn = QCoreApplication::translate("Companion", "Do not import");
|
||||
|
||||
QString msg;
|
||||
if (previousVersion.isEmpty()) {
|
||||
if (found)
|
||||
msg = QCoreApplication::translate("Companion", "We have found possible Companion settings backup file(s).\nDo you want to import settings from a file?");
|
||||
else
|
||||
msg = QCoreApplication::translate("Companion", "Import settings from a file, or start with current values.");
|
||||
}
|
||||
else {
|
||||
msg = QCoreApplication::translate("Companion", "We have found existing settings for Companion version: %1.\nDo you want to import them?\n\n" \
|
||||
"If you have a settings backup file, you may import that instead.").arg(previousVersion);
|
||||
}
|
||||
|
||||
const int ret = QMessageBox::question(nullptr, CPN_STR_APP_NAME, msg, impNoneBtn, impFileBtn, (previousVersion.isEmpty() ? QString() : impPrevBtn), 0, 0);
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
// Import from previous version
|
||||
if (ret == 2) {
|
||||
if (!g.importSettings(previousVersion)) {
|
||||
// very unlikely, but just in case of unexpected error, restart the import
|
||||
importError();
|
||||
checkSettingsImport();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Import from file
|
||||
bool err = false;
|
||||
QString impFile = CPN_SETTINGS_BACKUP_DIR;
|
||||
impFile = QFileDialog::getOpenFileName(nullptr, QCoreApplication::translate("Companion", "Select %1:").arg(CPN_STR_APP_SETTINGS_FILES), impFile, CPN_STR_APP_SETTINGS_FILTER);
|
||||
|
||||
if (!impFile.isEmpty() && QFileInfo(impFile).isReadable()) {
|
||||
QSettings fromSettings(impFile, QSettings::IniFormat);
|
||||
if (g.importSettings(&fromSettings)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
importError();
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
// Restart the import prompt if user cancelled the file select dialog but we do have previous settings, or if we had a file import error.
|
||||
if (err || !previousVersion.isEmpty())
|
||||
checkSettingsImport();
|
||||
}
|
||||
|
||||
void printHelpText()
|
||||
{
|
||||
printf(qPrintable(QString(APP_COMPANION % " v%s\n\n")), VERSION);
|
||||
const char tmpl[] = " %s \t %s\n";
|
||||
printf(tmpl, "--export", QCoreApplication::translate("Companion", "Save application settings to file...").toUtf8().constData());
|
||||
printf(tmpl, "--import", QCoreApplication::translate("Companion", "Load application settings from file or previous version...").toUtf8().constData());
|
||||
printf(tmpl, "--defaults", QCoreApplication::translate("Companion", "Reset ALL application settings to default and remove radio profiles...").toUtf8().constData());
|
||||
printf(tmpl, "--quit ", QCoreApplication::translate("Companion", "Exit before settings initialization and application startup.").toUtf8().constData());
|
||||
printf(tmpl, "--version", QCoreApplication::translate("Companion", "Print version number and exit.").toUtf8().constData());
|
||||
printf(tmpl, "--help|-h", QCoreApplication::translate("Companion", "Print this help text.").toUtf8().constData());
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
/* From doc: This attribute must be set before Q(Gui)Application is constructed. */
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
#endif
|
||||
|
||||
QApplication app(argc, argv);
|
||||
app.setApplicationName(APP_COMPANION);
|
||||
app.setOrganizationName(COMPANY);
|
||||
app.setOrganizationDomain(COMPANY_DOMAIN);
|
||||
app.setAttribute(Qt::AA_DontShowIconsInMenus, false);
|
||||
|
||||
const QStringList args(QApplication::arguments());
|
||||
|
||||
if (args.contains("--help") || args.contains("-h") || args.contains("/?")) {
|
||||
printHelpText();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (args.contains("--version")) {
|
||||
printf("%s\n", VERSION);
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
Q_INIT_RESOURCE(companion);
|
||||
|
||||
if (AppDebugMessageHandler::instance())
|
||||
AppDebugMessageHandler::instance()->installAppMessageHandler();
|
||||
|
||||
CustomDebug::setFilterRules();
|
||||
|
||||
// handle settings export/import/reset via CLI
|
||||
|
||||
bool doExport = args.contains("--export");
|
||||
bool doImport = args.contains("--import");
|
||||
bool doReset = args.contains("--defaults");
|
||||
|
||||
if (doExport)
|
||||
Helpers::exportAppSettings();
|
||||
|
||||
if (doReset) {
|
||||
char ok;
|
||||
printf("%s [Y/N] ", QCoreApplication::translate("Companion", "Reset ALL application settings to default values and remove radio profiles, are you sure?").toUtf8().constData());
|
||||
std::cin >> ok;
|
||||
if (ok != 'Y' && ok != 'y')
|
||||
exit(0);
|
||||
if (!doExport) {
|
||||
printf("%s [Y/N] ", QCoreApplication::translate("Companion", "Would you like to perform a backup first?").toUtf8().constData());
|
||||
std::cin >> ok;
|
||||
if (ok == 'Y' || ok == 'y')
|
||||
Helpers::exportAppSettings();
|
||||
}
|
||||
g.resetAllSettings();
|
||||
g.storeAllSettings();
|
||||
std::cout << QCoreApplication::translate("Companion", "Application settings were reset and saved.").toUtf8().constData() << std::endl;
|
||||
}
|
||||
|
||||
if (doImport)
|
||||
checkSettingsImport(true);
|
||||
|
||||
// give option to quit before settings init
|
||||
if (args.contains("--quit"))
|
||||
exit(0);
|
||||
|
||||
// end CLI handling
|
||||
|
||||
if (!doImport && g.isFirstUse())
|
||||
checkSettingsImport(false);
|
||||
|
||||
g.init();
|
||||
|
||||
QFile dbgLog;
|
||||
if (AppDebugMessageHandler::instance() && g.appDebugLog() && !g.appLogsDir().isEmpty() && QDir().mkpath(g.appLogsDir())) {
|
||||
QString fn = g.appLogsDir() % "/CompanionDebug_" % QDateTime::currentDateTime().toString("yy-MM-dd_HH-mm-ss") % ".log";
|
||||
dbgLog.setFileName(fn);
|
||||
if (dbgLog.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
AppDebugMessageHandler::instance()->addOutputDevice(&dbgLog);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
app.setStyle(new MyProxyStyle);
|
||||
#endif
|
||||
|
||||
Translations::installTranslators();
|
||||
|
||||
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
|
||||
uint32_t sdlFlags = 0;
|
||||
#ifdef JOYSTICKS
|
||||
sdlFlags |= SDL_INIT_JOYSTICK;
|
||||
#endif
|
||||
#ifdef SIMU_AUDIO
|
||||
sdlFlags |= SDL_INIT_AUDIO;
|
||||
#endif
|
||||
if (SDL_Init(sdlFlags) < 0) {
|
||||
fprintf(stderr, "ERROR: couldn't initialize SDL: %s\n", SDL_GetError());
|
||||
}
|
||||
#endif
|
||||
|
||||
registerStorageFactories();
|
||||
registerOpenTxFirmwares();
|
||||
SimulatorLoader::registerSimulators();
|
||||
|
||||
Profile & profile = g.currentProfile();
|
||||
if (profile.fwType().isEmpty()){
|
||||
profile.fwType(Firmware::getDefaultVariant()->getId());
|
||||
profile.fwName("");
|
||||
}
|
||||
|
||||
QString splashScreen;
|
||||
splashScreen = ":/images/splash.png";
|
||||
|
||||
QPixmap pixmap = QPixmap(splashScreen);
|
||||
QSplashScreen *splash = new QSplashScreen(pixmap);
|
||||
|
||||
Firmware::setCurrentVariant(Firmware::getFirmwareForId(g.profile[g.id()].fwType()));
|
||||
|
||||
MainWindow *mainWin = new MainWindow();
|
||||
if (g.showSplash()) {
|
||||
splash->show();
|
||||
QTimer::singleShot(1000*SPLASH_TIME, splash, SLOT(close()));
|
||||
QTimer::singleShot(1000*SPLASH_TIME, mainWin, SLOT(show()));
|
||||
}
|
||||
else {
|
||||
mainWin->show();
|
||||
}
|
||||
|
||||
int result = app.exec();
|
||||
|
||||
delete splash;
|
||||
delete mainWin;
|
||||
|
||||
SimulatorLoader::unregisterSimulators();
|
||||
unregisterOpenTxFirmwares();
|
||||
unregisterStorageFactories();
|
||||
|
||||
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
|
||||
SDL_Quit();
|
||||
#endif
|
||||
|
||||
qDebug() << "COMPANION EXIT" << result;
|
||||
|
||||
if (dbgLog.isOpen()) {
|
||||
AppDebugMessageHandler::instance()->removeOutputDevice(&dbgLog);
|
||||
dbgLog.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Encoding=UTF-8
|
||||
Name=Companion @VERSION@
|
||||
GenericName=Transmitter Companion App
|
||||
Comment=The Ultimate Transmitter Companion
|
||||
Icon=@COMPANION_NAME@
|
||||
Exec='@COMPANION_NAME@'
|
||||
Terminal=false
|
||||
StartupNotify=false
|
||||
Categories=Application
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "comparedialog.h"
|
||||
#include "ui_comparedialog.h"
|
||||
#include "appdata.h"
|
||||
#include "helpers.h"
|
||||
#include "modelslist.h"
|
||||
#include "styleeditdialog.h"
|
||||
#include <QPrinter>
|
||||
#include <QPrintDialog>
|
||||
|
||||
//class DragDropHeader {
|
||||
// public:
|
||||
// DragDropHeader():
|
||||
// general_settings(false),
|
||||
// models_count(0)
|
||||
// {
|
||||
// }
|
||||
// bool general_settings;
|
||||
// uint8_t models_count;
|
||||
// uint8_t models[CPN_MAX_MODELS];
|
||||
//};
|
||||
|
||||
CompareDialog::CompareDialog(QWidget * parent, Firmware * firmware):
|
||||
QDialog(parent, Qt::Window),
|
||||
multimodelprinter(new MultiModelPrinter(firmware)),
|
||||
ui(new Ui::CompareDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowIcon(CompanionIcon("compare.png"));
|
||||
setAcceptDrops(true);
|
||||
if (!g.compareWinGeo().isEmpty()) {
|
||||
restoreGeometry(g.compareWinGeo());
|
||||
}
|
||||
}
|
||||
|
||||
CompareDialog::~CompareDialog()
|
||||
{
|
||||
delete multimodelprinter;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CompareDialog::dragMoveEvent(QDragMoveEvent * event)
|
||||
{
|
||||
if (event->mimeData()->hasFormat("application/x-companion-modeldata")) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void CompareDialog::dragEnterEvent(QDragEnterEvent * event)
|
||||
{
|
||||
if (event->mimeData()->hasFormat("application/x-companion-modeldata")) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void CompareDialog::dragLeaveEvent(QDragLeaveEvent * event)
|
||||
{
|
||||
event->accept();
|
||||
}
|
||||
|
||||
bool CompareDialog::handleMimeData(const QMimeData * mimeData)
|
||||
{
|
||||
QVector<ModelData> mList;
|
||||
GeneralSettings gs;
|
||||
if (!TreeModel::decodeMimeData(mimeData, &mList, &gs) || mList.isEmpty())
|
||||
return false;
|
||||
for (int i=0; i < mList.size(); ++i) {
|
||||
GMData data;
|
||||
data.model = mList[i];
|
||||
data.gs = gs;
|
||||
modelsList.append(data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CompareDialog::closeEvent(QCloseEvent * event)
|
||||
{
|
||||
g.compareWinGeo(saveGeometry());
|
||||
}
|
||||
|
||||
void CompareDialog::dropEvent(QDropEvent *event)
|
||||
{
|
||||
if (handleMimeData(event->mimeData())) {
|
||||
event->accept();
|
||||
compare();
|
||||
}
|
||||
}
|
||||
|
||||
void CompareDialog::compare()
|
||||
{
|
||||
QLayoutItem *child;
|
||||
while ((child = ui->layout_modelNames->takeAt(0))) {
|
||||
if (child->widget())
|
||||
delete child->widget();
|
||||
delete child;
|
||||
}
|
||||
|
||||
multimodelprinter->clearModels();
|
||||
ui->textEdit->clear();
|
||||
|
||||
for (int i=0; i < modelsList.size(); ++i) {
|
||||
multimodelprinter->setModel(i, &modelsList[i].model, &modelsList[i].gs);
|
||||
QString name(modelsList.at(i).model.name);
|
||||
if (name.isEmpty())
|
||||
name = tr("Unnamed Model %1").arg(i+1);
|
||||
|
||||
QWidget * hdr = new QWidget(this);
|
||||
hdr->setLayout(new QHBoxLayout());
|
||||
hdr->layout()->setContentsMargins(0, 0, 0, 0);
|
||||
hdr->layout()->setSpacing(2);
|
||||
QToolButton * btn = new QToolButton(hdr);
|
||||
btn->setIcon(CompanionIcon("clear.png"));
|
||||
btn->setProperty("index", i);
|
||||
btn->setFixedSize(18, 18);
|
||||
btn->setToolTip(tr("Click to remove this model."));
|
||||
hdr->layout()->addWidget(btn);
|
||||
QLabel * lbl = new QLabel(name, this);
|
||||
lbl->setStyleSheet("font-weight: bold;");
|
||||
hdr->layout()->addWidget(lbl);
|
||||
connect(btn, &QToolButton::clicked, this, &CompareDialog::removeModelBtnClicked);
|
||||
|
||||
ui->layout_modelNames->addWidget(hdr);
|
||||
}
|
||||
if (modelsList.size())
|
||||
ui->textEdit->setHtml(multimodelprinter->print(ui->textEdit->document()));
|
||||
}
|
||||
|
||||
void CompareDialog::removeModel(int idx)
|
||||
{
|
||||
if (idx < modelsList.size()) {
|
||||
modelsList.remove(idx);
|
||||
compare();
|
||||
}
|
||||
}
|
||||
|
||||
void CompareDialog::removeModelBtnClicked()
|
||||
{
|
||||
if (sender() && sender()->property("index").isValid())
|
||||
removeModel(sender()->property("index").toInt());
|
||||
}
|
||||
|
||||
void CompareDialog::on_printButton_clicked()
|
||||
{
|
||||
QPrinter printer;
|
||||
printer.setPageMargins(10.0, 10.0, 10.0, 10.0, printer.Millimeter);
|
||||
QPrintDialog * dialog = new QPrintDialog(&printer, this);
|
||||
dialog->setWindowTitle(tr("Print Document"));
|
||||
if (dialog->exec() != QDialog::Accepted)
|
||||
return;
|
||||
ui->textEdit->print(&printer);
|
||||
}
|
||||
|
||||
void CompareDialog::on_printFileButton_clicked()
|
||||
{
|
||||
QPrinter printer;
|
||||
QString filename = QFileDialog::getSaveFileName(this, tr("Select PDF output file"), QString(), "Pdf File(*.pdf)");
|
||||
printer.setPageMargins(10.0, 10.0, 10.0, 10.0, printer.Millimeter);
|
||||
printer.setOutputFormat(QPrinter::PdfFormat);
|
||||
printer.setOrientation(QPrinter::Landscape);
|
||||
printer.setColorMode(QPrinter::Color);
|
||||
if (!filename.isEmpty()) {
|
||||
if (QFileInfo(filename).suffix().isEmpty())
|
||||
filename.append(".pdf");
|
||||
printer.setOutputFileName(filename);
|
||||
ui->textEdit->print(&printer);
|
||||
}
|
||||
}
|
||||
|
||||
void CompareDialog::on_styleButton_clicked()
|
||||
{
|
||||
StyleEditDialog *g = new StyleEditDialog(this, MODEL_PRINT_CSS);
|
||||
if (g->exec() == QDialog::Accepted)
|
||||
compare();
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _COMPAREDIALOG_H_
|
||||
#define _COMPAREDIALOG_H_
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "multimodelprinter.h"
|
||||
|
||||
namespace Ui {
|
||||
class CompareDialog;
|
||||
}
|
||||
|
||||
class CompareDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CompareDialog(QWidget *parent, Firmware * firmware);
|
||||
~CompareDialog();
|
||||
|
||||
protected:
|
||||
struct GMData {
|
||||
ModelData model;
|
||||
GeneralSettings gs;
|
||||
};
|
||||
|
||||
MultiModelPrinter * multimodelprinter;
|
||||
QVector<GMData> modelsList;
|
||||
QMap<int, GMData> modelsMap;
|
||||
Ui::CompareDialog * ui;
|
||||
|
||||
protected slots:
|
||||
void removeModelBtnClicked();
|
||||
void on_printButton_clicked();
|
||||
void on_printFileButton_clicked();
|
||||
void on_styleButton_clicked();
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent * event);
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event);
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event);
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *event);
|
||||
virtual void dropEvent(QDropEvent *event);
|
||||
bool handleMimeData(const QMimeData * mimeData);
|
||||
void compare();
|
||||
void removeModel(int idx);
|
||||
};
|
||||
|
||||
#endif // _COMPAREDIALOG_H_
|
||||
@@ -1,134 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CompareDialog</class>
|
||||
<widget class="QDialog" name="CompareDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>580</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>780</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Compare Models</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>To compare models, drag and drop them anywhere in this window.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="styleButton">
|
||||
<property name="text">
|
||||
<string>Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="printButton">
|
||||
<property name="text">
|
||||
<string>Print</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="printFileButton">
|
||||
<property name="text">
|
||||
<string>Print to file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="layout_modelNames">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>closeButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>CompareDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>739</x>
|
||||
<y>636</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>565</x>
|
||||
<y>623</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CONSTANTS_H_
|
||||
#define _CONSTANTS_H_
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
#define CPN_MAX_MODELS 60
|
||||
#define CPN_MAX_TIMERS 3
|
||||
#define CPN_MAX_FLIGHT_MODES 9
|
||||
#define CPN_MAX_MIXERS 64
|
||||
#define CPN_MAX_INPUTS 32
|
||||
#define CPN_MAX_EXPOS 64
|
||||
#define CPN_MAX_CURVES 32
|
||||
#define CPN_MAX_POINTS 17
|
||||
#define CPN_MAX_GVARS 9
|
||||
#define CPN_MAX_ENCODERS 2 // rotary encoders
|
||||
#define CPN_MAX_CHNOUT 32 // number of real output channels
|
||||
#define CPN_MAX_LOGICAL_SWITCHES 64 // number of custom switches
|
||||
#define CPN_MAX_SPECIAL_FUNCTIONS 64 // number of functions assigned to switches
|
||||
#define CPN_MAX_MODULES 2
|
||||
#define CPN_MAX_STICKS Board::STICK_AXIS_COUNT
|
||||
#define CPN_MAX_TRIMS Board::TRIM_AXIS_COUNT
|
||||
#define CPN_MAX_TRIM_SW Board::TRIM_SW_COUNT
|
||||
#define CPN_MAX_KNOBS 4
|
||||
#define CPN_MAX_SLIDERS 4
|
||||
#define CPN_MAX_POTS (CPN_MAX_KNOBS + CPN_MAX_SLIDERS)
|
||||
#define CPN_MAX_CYC 3
|
||||
#define CPN_MAX_SWITCHES 32
|
||||
#define CPN_MAX_KEYS 32
|
||||
#define CPN_MAX_MOUSE_ANALOGS 2
|
||||
#define CPN_MAX_ANALOGS (CPN_MAX_STICKS + CPN_MAX_POTS + CPN_MAX_MOUSE_ANALOGS)
|
||||
|
||||
#define CPN_STR_APP_NAME QCoreApplication::translate("Companion", "OpenTX Companion")
|
||||
#define CPN_STR_TTL_INFO QCoreApplication::translate("Companion", "Information") // shared Title Case words, eg. for a window title or section heading
|
||||
#define CPN_STR_TTL_WARNING QCoreApplication::translate("Companion", "Warning")
|
||||
#define CPN_STR_TTL_ERROR QCoreApplication::translate("Companion", "Error")
|
||||
#define CPN_STR_TTL_CONFIRM QCoreApplication::translate("Companion", "Please Confirm")
|
||||
|
||||
#define CPN_STR_FILES QCoreApplication::translate("Companion", "files")
|
||||
#define CPN_STR_RAD_MOD_SETTINGS QCoreApplication::translate("Companion", "Radio and Models settings")
|
||||
#define HEX_FILES_FILTER "HEX " % CPN_STR_FILES % " (*.hex);;"
|
||||
#define BIN_FILES_FILTER "BIN " % CPN_STR_FILES % " (*.bin);;"
|
||||
#define DFU_FILES_FILTER "DFU " % CPN_STR_FILES % " (*.dfu);;"
|
||||
#define EEPE_FILES_FILTER "EEPE " % CPN_STR_FILES % " (*.eepe);;"
|
||||
#define OTX_FILES_FILTER "OpenTX " % CPN_STR_FILES % " (*.otx);;"
|
||||
#define EEPROM_FILES_FILTER CPN_STR_RAD_MOD_SETTINGS % " " % CPN_STR_FILES % " (*.otx *.eepe *.bin *.hex);;" % OTX_FILES_FILTER % EEPE_FILES_FILTER % BIN_FILES_FILTER % HEX_FILES_FILTER
|
||||
#define FLASH_FILES_FILTER "FLASH " % CPN_STR_FILES % " (*.bin *.hex *.dfu);;" % BIN_FILES_FILTER % HEX_FILES_FILTER % DFU_FILES_FILTER
|
||||
#define EXTERNAL_EEPROM_FILES_FILTER "EEPROM " % CPN_STR_FILES % " (*.bin *.hex);;" % BIN_FILES_FILTER % HEX_FILES_FILTER
|
||||
#define ER9X_EEPROM_FILE_TYPE "ER9X_EEPROM_FILE"
|
||||
#define EEPE_EEPROM_FILE_HEADER "EEPE EEPROM FILE"
|
||||
#define EEPE_MODEL_FILE_HEADER "EEPE MODEL FILE"
|
||||
|
||||
#define CPN_STR_APP_SETTINGS QCoreApplication::translate("Companion", "Application Settings")
|
||||
#define CPN_STR_APP_SETTINGS_FILES CPN_STR_APP_SETTINGS % " " % CPN_STR_FILES
|
||||
#define CPN_STR_APP_SETTINGS_FILTER CPN_STR_APP_SETTINGS_FILES % " (*.ini)"
|
||||
|
||||
#define CPN_STR_UNKNOWN_ITEM "???"
|
||||
|
||||
#define CPN_STR_SW_INDICATOR_UP QCoreApplication::translate("RawSwitch", "\xE2\x86\x91") // Switch up position indicator: Up arrow, or similar.
|
||||
#define CPN_STR_SW_INDICATOR_DN QCoreApplication::translate("RawSwitch", "\xE2\x86\x93") // Switch down position indicator: Down arrow, or similar.
|
||||
#define CPN_STR_SW_INDICATOR_NEUT QCoreApplication::translate("RawSwitch", "-") // Switch neutral (middle) position indicator.
|
||||
#define CPN_STR_SW_INDICATOR_REV QCoreApplication::translate("RawSwitch", "!") // Switch reversed logic (NOT) indicator.
|
||||
|
||||
#endif // _CONSTANTS_H_
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "creditsdialog.h"
|
||||
#include "ui_htmldialog.h"
|
||||
#include "helpers.h"
|
||||
#include <QFile>
|
||||
|
||||
CreditsDialog::CreditsDialog(QWidget * parent):
|
||||
QDialog(parent),
|
||||
ui(new Ui::HtmlDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowTitle(tr("OpenTX Contributors"));
|
||||
setWindowIcon(CompanionIcon("contributors.png"));
|
||||
|
||||
QString str = "<html>" \
|
||||
"<head>" \
|
||||
" <style type=\"text/css\">" \
|
||||
" .normal { font-weight:normal;color:#000000;vertical-align:top;font-size:10px;text-align:left;font-family:arial,helvetica,sans-serif; }" \
|
||||
" .bold { font-weight:bold;color:#C00000;vertical-align:top;font-size:10px;text-align:left;font-family:arial,helvetica,sans-serif; }" \
|
||||
" .title { font-weight:bold;color:#000000;font-size:14px;text-align:left;font-family:arial,helvetica,sans-serif; }" \
|
||||
" </style>" \
|
||||
"</head>"
|
||||
"<body class=\"normal\">";
|
||||
|
||||
foreach(CreditsSection section, readCredits()) {
|
||||
str.append(formatTable(sectionTitle(section.title), section.names, 3));
|
||||
}
|
||||
|
||||
str.append("<table><tr><td class=\"normal\"> </td></tr>" \
|
||||
" <tr><td class=\"normal\">" + tr("Honors go to Rafal Tomczak (RadioClone), Thomas Husterer (th9x) and Erez Raviv (er9x and eePe)") + "<br/></td></tr>" \
|
||||
"</table>");
|
||||
|
||||
#if 0
|
||||
QFile blacklist(":/BLACKLIST.txt");
|
||||
if (blacklist.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QStringList names;
|
||||
names << blacklist.readAll();
|
||||
str.append(formatTable(tr("OpenTX Blacklist"), names, 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
str.append("</body></html>");
|
||||
ui->textEditor->setHtml(str);
|
||||
ui->textEditor->scroll(0, 0);
|
||||
ui->textEditor->setOpenExternalLinks(true);
|
||||
}
|
||||
|
||||
CreditsDialog::~CreditsDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QList<CreditsDialog::CreditsSection> CreditsDialog::readCredits()
|
||||
{
|
||||
QFile credits(":/CREDITS.txt");
|
||||
QList<CreditsSection> result;
|
||||
if (credits.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
while (!credits.atEnd()) {
|
||||
QByteArray line = credits.readLine().trimmed();
|
||||
if (line.size() >= 2) {
|
||||
if (line.startsWith("[") && line.endsWith("]")) {
|
||||
result.push_back(CreditsSection(line.mid(1, line.size() - 2)));
|
||||
} else {
|
||||
result.back().addName(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QString CreditsDialog::sectionTitle(const QString & title)
|
||||
{
|
||||
if (title == "Main developers")
|
||||
return tr("Main developers");
|
||||
else if (title == "Translators")
|
||||
return tr("Translators");
|
||||
else if (title == "Companies and projects who have donated to OpenTX")
|
||||
return tr("Companies and projects who have donated to OpenTX");
|
||||
else if (title == "People who have donated to OpenTX")
|
||||
return tr("People who have donated to OpenTX");
|
||||
else
|
||||
return tr("Other contributors");
|
||||
}
|
||||
|
||||
QString CreditsDialog::formatTable(const QString & title, const QStringList & names, int columns)
|
||||
{
|
||||
const float cwidth = 100.0 / columns;
|
||||
QString str = "<table width=\"100%\" border=0 cellspacing=0 cellpadding=2>" \
|
||||
" <tr><td class=\"normal\"> </td></tr>" \
|
||||
" <tr><td class=\"title\">" + title + "</td></tr>" \
|
||||
"</table>";
|
||||
|
||||
str.append("<table width=\"100%\" border=0 cellspacing=0 cellpadding=2>");
|
||||
|
||||
int column = 0;
|
||||
foreach(QString name, names) {
|
||||
if (column == 0) {
|
||||
str.append("<tr>");
|
||||
}
|
||||
QString trclass = name.contains("monthly") ? "bold" : "normal";
|
||||
str.append(QString("<td width=\"%1%\" class=\"%2\">%3</td>").arg(cwidth).arg(trclass).arg(name.trimmed().replace("monthly", tr("monthly"))));
|
||||
if (++column == columns) {
|
||||
str.append("</tr>");
|
||||
column = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (column != 0) {
|
||||
str.append("</tr>");
|
||||
}
|
||||
|
||||
str.append("</table>");
|
||||
return str;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CREDITSDIALOG_H_
|
||||
#define _CREDITSDIALOG_H_
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class HtmlDialog;
|
||||
}
|
||||
|
||||
class CreditsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class CreditsSection
|
||||
{
|
||||
public:
|
||||
CreditsSection(const QString & title):
|
||||
title(title)
|
||||
{
|
||||
}
|
||||
|
||||
void addName(const QString & name)
|
||||
{
|
||||
names.push_back(name);
|
||||
}
|
||||
|
||||
QString title;
|
||||
QStringList names;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit CreditsDialog(QWidget * parent = 0);
|
||||
~CreditsDialog();
|
||||
|
||||
private:
|
||||
Ui::HtmlDialog * ui;
|
||||
QList<CreditsSection> readCredits();
|
||||
QString sectionTitle(const QString & title);
|
||||
QString formatTable(const QString & title, const QStringList & names, int colums);
|
||||
};
|
||||
|
||||
#endif // _CREDITSDIALOG_H_
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "customdebug.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(eepromImport, "eeprom.import")
|
||||
|
||||
Q_LOGGING_CATEGORY(simulatorInterfaceLoader, "simulator.interface.loader")
|
||||
|
||||
void CustomDebug::setFilterRules()
|
||||
{
|
||||
QString rules;
|
||||
rules.append("eeprom.import=");
|
||||
#if defined(DEBUG_STORAGE_IMPORT)
|
||||
rules.append("true\n");
|
||||
#else
|
||||
rules.append("false\n");
|
||||
#endif
|
||||
|
||||
rules.append("simulator.interface.*=true\n");
|
||||
|
||||
QLoggingCategory::setFilterRules(rules);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CUSTOMDEBUG_H_
|
||||
#define _CUSTOMDEBUG_H_
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
// Controls the generation of debug output for EEPROM import
|
||||
Q_DECLARE_LOGGING_CATEGORY(eepromImport) // "eeprom.import"
|
||||
|
||||
// Controls the generation of debug output of SimulatorLoader class
|
||||
Q_DECLARE_LOGGING_CATEGORY(simulatorInterfaceLoader) // "simulator.interface.loader"
|
||||
|
||||
class CustomDebug
|
||||
{
|
||||
public:
|
||||
static void setFilterRules();
|
||||
};
|
||||
|
||||
#endif // _CUSTOMDEBUG_H_
|
||||
@@ -1,282 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "customizesplashdialog.h"
|
||||
#include "ui_customizesplashdialog.h"
|
||||
#include "flashfirmwaredialog.h"
|
||||
#include "appdata.h"
|
||||
#include "helpers.h"
|
||||
#include "firmwareinterface.h"
|
||||
#include "splashlibrarydialog.h"
|
||||
|
||||
//*** Side Class ***
|
||||
|
||||
Side::Side(){
|
||||
imageLabel = 0;
|
||||
fileNameEdit = 0;
|
||||
saveButton = 0;
|
||||
loadFwButton=0;
|
||||
loadPictButton = 0;
|
||||
loadProfileButton = 0;
|
||||
saveToFileName = new QString("");
|
||||
source = new Source(UNDEFINED);
|
||||
format = new LCDFormat(LCDTARANIS);
|
||||
}
|
||||
|
||||
void Side::markSourceButton()
|
||||
{
|
||||
loadFwButton->setChecked(*source == FW ? true : false );
|
||||
loadPictButton->setChecked(*source == PICT ? true : false );
|
||||
loadProfileButton->setChecked(*source == PROFILE ? true : false );
|
||||
}
|
||||
|
||||
void Side::copyImage( Side side )
|
||||
{
|
||||
if ((*source!=UNDEFINED) && (*side.source!=UNDEFINED))
|
||||
imageLabel->setPixmap(*side.imageLabel->pixmap());
|
||||
}
|
||||
|
||||
bool Side::displayImage(QString fileName, Source pictSource)
|
||||
{
|
||||
QImage image;
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return false;
|
||||
|
||||
// Determine which picture format to use
|
||||
if (pictSource == FW) {
|
||||
FirmwareInterface firmware(fileName);
|
||||
if (!firmware.hasSplash())
|
||||
return false;
|
||||
else
|
||||
image = firmware.getSplash();
|
||||
*format = (firmware.getSplashWidth()==WIDTH_TARANIS ? LCDTARANIS : LCD9X);
|
||||
}
|
||||
else {
|
||||
image.load(fileName);
|
||||
if (pictSource== PICT)
|
||||
*format = image.width()>WIDTH_9X ? LCDTARANIS : LCD9X;
|
||||
else if (pictSource == PROFILE)
|
||||
*format = (g.profile[g.id()].fwType().contains("x9")) ? LCDTARANIS : LCD9X;
|
||||
}
|
||||
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load image
|
||||
QPixmap pixmap = makePixMap(image);
|
||||
imageLabel->setPixmap(pixmap);
|
||||
imageLabel->setFixedSize(pixmap.width()*2, pixmap.height()*2);
|
||||
|
||||
switch (pictSource) {
|
||||
case FW:
|
||||
fileNameEdit->setText(CustomizeSplashDialog::tr("FW: %1").arg(fileName));
|
||||
*saveToFileName = fileName;
|
||||
*source = FW;
|
||||
break;
|
||||
case PICT:
|
||||
fileNameEdit->setText(CustomizeSplashDialog::tr("Pict: %1").arg(fileName));
|
||||
*saveToFileName = fileName;
|
||||
*source = PICT;
|
||||
break;
|
||||
case PROFILE:
|
||||
fileNameEdit->setText(CustomizeSplashDialog::tr("Profile image"));
|
||||
*saveToFileName = fileName;
|
||||
*source = PROFILE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
saveButton->setEnabled(true);
|
||||
libraryButton->setEnabled(true);
|
||||
invertButton->setEnabled(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Side::refreshImage()
|
||||
{
|
||||
return displayImage( *saveToFileName, *source );
|
||||
}
|
||||
|
||||
bool Side::saveImage()
|
||||
{
|
||||
if (*source == FW )
|
||||
{
|
||||
FirmwareInterface firmware(*saveToFileName);
|
||||
if (!firmware.hasSplash()) {
|
||||
return false;
|
||||
}
|
||||
QImage image = imageLabel->pixmap()->toImage().scaled(firmware.getSplashWidth(), firmware.getSplashHeight());
|
||||
if (firmware.setSplash(image) && (firmware.save(*saveToFileName) > 0)) {
|
||||
g.flashDir( QFileInfo(*saveToFileName).dir().absolutePath() );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (*source == PICT) {
|
||||
QImage image = imageLabel->pixmap()->toImage().scaled(imageLabel->width()/2, imageLabel->height()/2).convertToFormat(QImage::Format_Indexed8);
|
||||
if (image.save(*saveToFileName)) {
|
||||
g.imagesDir( QFileInfo(*saveToFileName).dir().absolutePath() );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (*source == PROFILE) {
|
||||
QImage image = imageLabel->pixmap()->toImage().scaled(imageLabel->width()/2, imageLabel->height()/2).convertToFormat(QImage::Format_Indexed8);
|
||||
if (!image.save(*saveToFileName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CustomizeSplashDialog::CustomizeSplashDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::CustomizeSplashDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowIcon(CompanionIcon("paintbrush.png"));
|
||||
ui->leftLibraryButton->setIcon(CompanionIcon("library.png"));
|
||||
ui->rightLibraryButton->setIcon(CompanionIcon("library.png"));
|
||||
|
||||
left.imageLabel = ui->leftImageLabel;
|
||||
right.imageLabel = ui->rightImageLabel;
|
||||
left.fileNameEdit = ui->leftFileNameEdit;
|
||||
right.fileNameEdit = ui->rightFileNameEdit;
|
||||
left.saveButton = ui->leftSaveButton;
|
||||
right.saveButton = ui->rightSaveButton;
|
||||
left.libraryButton = ui->leftLibraryButton;
|
||||
right.libraryButton = ui->rightLibraryButton;
|
||||
left.invertButton = ui->leftInvertButton;
|
||||
right.invertButton = ui->rightInvertButton;
|
||||
|
||||
left.loadFwButton = ui->leftLoadFwButton;
|
||||
right.loadFwButton = ui->rightLoadFwButton;
|
||||
left.loadPictButton = ui->leftLoadPictButton;
|
||||
right.loadPictButton = ui->rightLoadPictButton;
|
||||
left.loadProfileButton = ui->leftLoadProfileButton;
|
||||
right.loadProfileButton = ui->rightLoadProfileButton;
|
||||
|
||||
loadProfile(left);
|
||||
left.markSourceButton();
|
||||
|
||||
resize(0,0);
|
||||
}
|
||||
|
||||
CustomizeSplashDialog::~CustomizeSplashDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CustomizeSplashDialog::on_copyRightToLeftButton_clicked() {
|
||||
left.copyImage(right);
|
||||
}
|
||||
void CustomizeSplashDialog::on_copyLeftToRightButton_clicked() {
|
||||
right.copyImage(left);
|
||||
}
|
||||
|
||||
|
||||
void CustomizeSplashDialog::on_leftLoadFwButton_clicked() {loadFirmware(left);}
|
||||
void CustomizeSplashDialog::on_rightLoadFwButton_clicked() {loadFirmware(right);}
|
||||
void CustomizeSplashDialog::loadFirmware(Side side)
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Firmware File"), g.flashDir(), FLASH_FILES_FILTER);
|
||||
if (!fileName.isEmpty()) {
|
||||
if (!side.displayImage( fileName, FW ))
|
||||
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Can not load embedded image from firmware file %1.").arg(fileName));
|
||||
else
|
||||
g.flashDir( QFileInfo(fileName).dir().absolutePath() );
|
||||
}
|
||||
side.markSourceButton();
|
||||
}
|
||||
|
||||
void CustomizeSplashDialog::on_leftLoadPictButton_clicked() {loadPicture(left);}
|
||||
void CustomizeSplashDialog::on_rightLoadPictButton_clicked() {loadPicture(right);}
|
||||
void CustomizeSplashDialog::loadPicture(Side side)
|
||||
{
|
||||
QString supportedImageFormats;
|
||||
for (int formatIndex = 0; formatIndex < QImageReader::supportedImageFormats().count(); formatIndex++) {
|
||||
supportedImageFormats += QLatin1String(" *.") + QImageReader::supportedImageFormats()[formatIndex];
|
||||
}
|
||||
QString fileName = QFileDialog::getOpenFileName(this,
|
||||
tr("Open Image to load"), g.imagesDir(), tr("Images (%1)").arg(supportedImageFormats));
|
||||
|
||||
if (!fileName.isEmpty()) {
|
||||
if (!side.displayImage( fileName, PICT ))
|
||||
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Cannot load the image file %1.").arg(fileName));
|
||||
else
|
||||
g.imagesDir( QFileInfo(fileName).dir().absolutePath() );
|
||||
}
|
||||
side.markSourceButton();
|
||||
}
|
||||
|
||||
void CustomizeSplashDialog::on_leftLoadProfileButton_clicked() {loadProfile(left);}
|
||||
void CustomizeSplashDialog::on_rightLoadProfileButton_clicked() {loadProfile(right);}
|
||||
void CustomizeSplashDialog::loadProfile(Side side)
|
||||
{
|
||||
QString fileName=g.profile[g.id()].splashFile();
|
||||
|
||||
if (!fileName.isEmpty()) {
|
||||
if (!side.displayImage( fileName, PROFILE ))
|
||||
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Cannot load profile image %1.").arg(fileName));
|
||||
}
|
||||
side.markSourceButton();
|
||||
}
|
||||
|
||||
void CustomizeSplashDialog::on_leftLibraryButton_clicked(){libraryButton_clicked(left);}
|
||||
void CustomizeSplashDialog::on_rightLibraryButton_clicked(){libraryButton_clicked(right);}
|
||||
void CustomizeSplashDialog::libraryButton_clicked( Side side )
|
||||
{
|
||||
QString fileName;
|
||||
SplashLibraryDialog *ld = new SplashLibraryDialog(this,&fileName);
|
||||
ld->exec();
|
||||
if (!fileName.isEmpty()) {
|
||||
if (!side.displayImage( fileName, UNDEFINED ))
|
||||
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Cannot load the library image %1.").arg(fileName));
|
||||
}
|
||||
}
|
||||
|
||||
void CustomizeSplashDialog::on_leftSaveButton_clicked(){saveButton_clicked(left);}
|
||||
void CustomizeSplashDialog::on_rightSaveButton_clicked(){saveButton_clicked(right);}
|
||||
void CustomizeSplashDialog::saveButton_clicked( Side side )
|
||||
{
|
||||
if (side.saveImage()){
|
||||
QMessageBox::information(this, tr("File Saved"), tr("The image was saved to the file %1").arg(*side.saveToFileName));
|
||||
if ( !side.refreshImage()){
|
||||
QMessageBox::critical(this, tr("Image Refresh Error"), tr("Failed to refresh image from file %1").arg(*side.saveToFileName));
|
||||
}
|
||||
}
|
||||
else
|
||||
QMessageBox::critical(this, tr("File Save Error"), tr("Failed to write image to %1").arg(*side.saveToFileName));
|
||||
}
|
||||
|
||||
void CustomizeSplashDialog::on_leftInvertButton_clicked(){invertButton_clicked(left);}
|
||||
void CustomizeSplashDialog::on_rightInvertButton_clicked(){invertButton_clicked(right);}
|
||||
void CustomizeSplashDialog::invertButton_clicked(Side side)
|
||||
{
|
||||
QImage image = side.imageLabel->pixmap()->toImage();
|
||||
image.invertPixels();
|
||||
side.imageLabel->setPixmap(QPixmap::fromImage(image));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CUSTOMIZESPLASHDIALOG_H_
|
||||
#define _CUSTOMIZESPLASHDIALOG_H_
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "firmwareinterface.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CustomizeSplashDialog;
|
||||
}
|
||||
|
||||
const int WIDTH_TARANIS = 212;
|
||||
const int HEIGHT_TARANIS = 64;
|
||||
const int WIDTH_9X = 128;
|
||||
const int HEIGHT_9X = 64;
|
||||
|
||||
enum Source {FW, PICT, PROFILE, UNDEFINED};
|
||||
enum LCDFormat {LCD9X, LCDTARANIS};
|
||||
|
||||
class Side
|
||||
{
|
||||
public:
|
||||
Side();
|
||||
void markSourceButton();
|
||||
void copyImage( Side );
|
||||
bool displayImage( QString fileName, Source source );
|
||||
bool saveImage();
|
||||
bool refreshImage();
|
||||
|
||||
QLabel *imageLabel;
|
||||
QLineEdit *fileNameEdit;
|
||||
QPushButton *saveButton;
|
||||
QPushButton *invertButton;
|
||||
QToolButton *libraryButton;
|
||||
QPushButton *loadFwButton;
|
||||
QPushButton *loadPictButton;
|
||||
QPushButton *loadProfileButton;
|
||||
|
||||
QString *saveToFileName;
|
||||
|
||||
private:
|
||||
Source *source;
|
||||
LCDFormat *format;
|
||||
};
|
||||
|
||||
class CustomizeSplashDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Side left;
|
||||
Side right;
|
||||
|
||||
public:
|
||||
explicit CustomizeSplashDialog(QWidget *parent = 0);
|
||||
~CustomizeSplashDialog();
|
||||
|
||||
private slots:
|
||||
void on_leftLoadFwButton_clicked();
|
||||
void on_leftLoadPictButton_clicked();
|
||||
void on_leftLoadProfileButton_clicked();
|
||||
void on_leftLibraryButton_clicked();
|
||||
void on_leftSaveButton_clicked();
|
||||
void on_leftInvertButton_clicked();
|
||||
|
||||
void on_rightLoadFwButton_clicked();
|
||||
void on_rightLoadPictButton_clicked();
|
||||
void on_rightLoadProfileButton_clicked();
|
||||
void on_rightLibraryButton_clicked();
|
||||
void on_rightSaveButton_clicked();
|
||||
void on_rightInvertButton_clicked();
|
||||
|
||||
void on_copyRightToLeftButton_clicked();
|
||||
void on_copyLeftToRightButton_clicked();
|
||||
|
||||
private:
|
||||
void loadFirmware( Side );
|
||||
void loadPicture( Side );
|
||||
void loadProfile( Side );
|
||||
void libraryButton_clicked( Side );
|
||||
void saveButton_clicked( Side );
|
||||
void invertButton_clicked( Side );
|
||||
|
||||
Ui::CustomizeSplashDialog *ui;
|
||||
enum sideEnum { LEFT, RIGHT };
|
||||
};
|
||||
|
||||
#endif // _CUSTOMIZESPLASHDIALOG_H_
|
||||
@@ -1,667 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CustomizeSplashDialog</class>
|
||||
<widget class="QDialog" name="CustomizeSplashDialog">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1087</width>
|
||||
<height>298</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Transmitter Splash Screen Editor</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="Line" name="line_13">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="leftFileNameEdit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>424</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>426</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="leftImageLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>424</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>424</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="leftInvertButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Invert</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="leftLibraryButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Open Splash Library</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QPushButton" name="leftLoadProfileButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load Profile</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="leftLoadFwButton">
|
||||
<property name="text">
|
||||
<string>Load FW</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="leftLoadPictButton">
|
||||
<property name="text">
|
||||
<string>Load Pict</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="leftSaveButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QToolButton" name="copyRightToLeftButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="arrowType">
|
||||
<enum>Qt::LeftArrow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="copyLeftToRightButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="arrowType">
|
||||
<enum>Qt::RightArrow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="Line" name="line_14">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="rightFileNameEdit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>426</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>424</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_10">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rightImageLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>424</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>424</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QPushButton" name="rightInvertButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Invert</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="rightLibraryButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Open Splash Library</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QPushButton" name="rightLoadProfileButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load Profile</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rightLoadFwButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load FW</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rightLoadPictButton">
|
||||
<property name="text">
|
||||
<string>Load Pict</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rightSaveButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_10">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>leftFileNameEdit</tabstop>
|
||||
<tabstop>leftInvertButton</tabstop>
|
||||
<tabstop>leftLibraryButton</tabstop>
|
||||
<tabstop>leftLoadProfileButton</tabstop>
|
||||
<tabstop>leftLoadFwButton</tabstop>
|
||||
<tabstop>leftLoadPictButton</tabstop>
|
||||
<tabstop>leftSaveButton</tabstop>
|
||||
<tabstop>copyLeftToRightButton</tabstop>
|
||||
<tabstop>copyRightToLeftButton</tabstop>
|
||||
<tabstop>rightFileNameEdit</tabstop>
|
||||
<tabstop>rightInvertButton</tabstop>
|
||||
<tabstop>rightLibraryButton</tabstop>
|
||||
<tabstop>rightLoadProfileButton</tabstop>
|
||||
<tabstop>rightLoadFwButton</tabstop>
|
||||
<tabstop>rightLoadPictButton</tabstop>
|
||||
<tabstop>rightSaveButton</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="companion.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
set(datamodels_SRCS
|
||||
rawitemdatamodels.cpp
|
||||
rawitemfilteredmodel.cpp
|
||||
)
|
||||
|
||||
set(datamodels_HDRS
|
||||
rawitemdatamodels.h
|
||||
rawitemfilteredmodel.h
|
||||
)
|
||||
|
||||
qt5_wrap_cpp(datamodels_SRCS ${datamodels_HDRS})
|
||||
|
||||
add_library(datamodels ${datamodels_SRCS} ${datamodels_HDRS})
|
||||
target_link_libraries(datamodels PRIVATE ${CPN_COMMON_LIB})
|
||||
|
||||
target_include_directories(datamodels
|
||||
PRIVATE
|
||||
"${CMAKE_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${COMPANION_SRC_DIRECTORY}"
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_LIST_DIR}"
|
||||
)
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rawitemdatamodels.h"
|
||||
#include "generalsettings.h"
|
||||
#include "eeprominterface.h"
|
||||
#include "modeldata.h"
|
||||
|
||||
RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
|
||||
AbstractRawItemDataModel(generalSettings, modelData, parent)
|
||||
{
|
||||
const Boards board = Boards(getCurrentBoard());
|
||||
Firmware * fw = getCurrentFirmware();
|
||||
const int anasCount = CPN_MAX_STICKS + board.getCapability(Board::Pots) + board.getCapability(Board::Sliders) + board.getCapability(Board::MouseAnalogs);
|
||||
|
||||
addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1);
|
||||
for (int i=0; i < fw->getCapability(LuaScripts); i++)
|
||||
addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, fw->getCapability(LuaOutputsPerScript), i * 16);
|
||||
addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, fw->getCapability(VirtualInputs));
|
||||
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, anasCount);
|
||||
addItems(SOURCE_TYPE_ROTARY_ENCODER, RawSource::SourcesGroup, fw->getCapability(RotaryEncoders));
|
||||
addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board.getCapability(Board::NumTrims));
|
||||
addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1);
|
||||
addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board.getCapability(Board::Switches));
|
||||
addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, fw->getCapability(LogicalSwitches));
|
||||
addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC);
|
||||
addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, fw->getCapability(TrainerInputs));
|
||||
addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, fw->getCapability(Outputs));
|
||||
addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5);
|
||||
addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, CPN_MAX_SENSORS * 3);
|
||||
addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, fw->getCapability(Gvars));
|
||||
}
|
||||
|
||||
void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const
|
||||
{
|
||||
Board::Type board = getCurrentBoard();
|
||||
item->setText(src.toString(modelData, generalSettings, board));
|
||||
item->setData(src.isAvailable(modelData, generalSettings, board), IsAvailableRole);
|
||||
}
|
||||
|
||||
void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start)
|
||||
{
|
||||
for (int i = start; i < start + count; i++) {
|
||||
const RawSource src = RawSource(type, i);
|
||||
QStandardItem * modelItem = new QStandardItem();
|
||||
modelItem->setData(src.toValue(), ItemIdRole);
|
||||
modelItem->setData(type, ItemTypeRole);
|
||||
modelItem->setData(group, ItemFlagsRole);
|
||||
setDynamicItemData(modelItem, src);
|
||||
appendRow(modelItem);
|
||||
}
|
||||
}
|
||||
|
||||
void RawSourceItemModel::update() const
|
||||
{
|
||||
for (int i=0; i < rowCount(); ++i)
|
||||
setDynamicItemData(item(i), RawSource(item(i)->data(ItemIdRole).toInt()));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// RawSwitchItemModel
|
||||
//
|
||||
|
||||
RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
|
||||
AbstractRawItemDataModel(generalSettings, modelData, parent)
|
||||
{
|
||||
Boards board = Boards(getCurrentBoard());
|
||||
Firmware * fw = getCurrentFirmware();
|
||||
|
||||
// Descending switch direction: NOT (!) switches
|
||||
addItems(SWITCH_TYPE_SENSOR, -CPN_MAX_SENSORS);
|
||||
addItems(SWITCH_TYPE_TELEMETRY, -1);
|
||||
addItems(SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes));
|
||||
addItems(SWITCH_TYPE_VIRTUAL, -fw->getCapability(LogicalSwitches));
|
||||
addItems(SWITCH_TYPE_ROTARY_ENCODER, -fw->getCapability(RotaryEncoders));
|
||||
addItems(SWITCH_TYPE_TRIM, -board.getCapability(Board::NumTrimSwitches));
|
||||
addItems(SWITCH_TYPE_MULTIPOS_POT, -(board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions)));
|
||||
addItems(SWITCH_TYPE_SWITCH, -board.getCapability(Board::SwitchPositions));
|
||||
|
||||
// Ascending switch direction (including zero)
|
||||
addItems(SWITCH_TYPE_TIMER_MODE, 5);
|
||||
addItems(SWITCH_TYPE_NONE, 1);
|
||||
addItems(SWITCH_TYPE_SWITCH, board.getCapability(Board::SwitchPositions));
|
||||
addItems(SWITCH_TYPE_MULTIPOS_POT, board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions));
|
||||
addItems(SWITCH_TYPE_TRIM, board.getCapability(Board::NumTrimSwitches));
|
||||
addItems(SWITCH_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders));
|
||||
addItems(SWITCH_TYPE_VIRTUAL, fw->getCapability(LogicalSwitches));
|
||||
addItems(SWITCH_TYPE_FLIGHT_MODE, fw->getCapability(FlightModes));
|
||||
addItems(SWITCH_TYPE_TELEMETRY, 1);
|
||||
addItems(SWITCH_TYPE_SENSOR, CPN_MAX_SENSORS);
|
||||
addItems(SWITCH_TYPE_ON, 1);
|
||||
addItems(SWITCH_TYPE_ONE, 1);
|
||||
}
|
||||
|
||||
void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const
|
||||
{
|
||||
const Board::Type board = getCurrentBoard();
|
||||
item->setText(rsw.toString(board, generalSettings, modelData));
|
||||
item->setData(rsw.isAvailable(modelData, generalSettings, board), IsAvailableRole);
|
||||
}
|
||||
|
||||
void RawSwitchItemModel::addItems(const RawSwitchType & type, int count)
|
||||
{
|
||||
// Most RawSwitch() indices are one-based (vs. typical zero); these are exceptions to the rule:
|
||||
const static QVector<int> rawSwitchIndexBaseZeroTypes = QVector<int>() << SWITCH_TYPE_NONE << SWITCH_TYPE_ON << SWITCH_TYPE_OFF << SWITCH_TYPE_TIMER_MODE;
|
||||
// handle exceptions in RawSwitch() index values
|
||||
const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0;
|
||||
|
||||
// determine cotext flags
|
||||
int context = RawSwitch::AllSwitchContexts;
|
||||
switch (type) {
|
||||
case SWITCH_TYPE_FLIGHT_MODE:
|
||||
context &= ~RawSwitch::MixesContext;
|
||||
// fallthrough
|
||||
case SWITCH_TYPE_VIRTUAL:
|
||||
case SWITCH_TYPE_SENSOR:
|
||||
context &= ~RawSwitch::GlobalFunctionsContext;
|
||||
break;
|
||||
|
||||
case SWITCH_TYPE_TIMER_MODE:
|
||||
context = RawSwitch::TimersContext;
|
||||
break;
|
||||
|
||||
case SWITCH_TYPE_NONE:
|
||||
context &= ~RawSwitch::TimersContext;
|
||||
break;
|
||||
|
||||
case SWITCH_TYPE_ON:
|
||||
case SWITCH_TYPE_ONE:
|
||||
context = RawSwitch::SpecialFunctionsContext | RawSwitch::GlobalFunctionsContext;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int i = (count < 0 ? count : 1);
|
||||
count = (i < 0 ? 0 : count + i);
|
||||
for ( ; i < count; ++i) {
|
||||
RawSwitch rs(type, i + rawIdxAdj);
|
||||
QStandardItem * modelItem = new QStandardItem();
|
||||
modelItem->setData(rs.toValue(), ItemIdRole);
|
||||
modelItem->setData(type, ItemTypeRole);
|
||||
modelItem->setData(context, ItemFlagsRole);
|
||||
setDynamicItemData(modelItem, rs);
|
||||
appendRow(modelItem);
|
||||
}
|
||||
}
|
||||
|
||||
void RawSwitchItemModel::update() const
|
||||
{
|
||||
for (int i=0; i < rowCount(); ++i)
|
||||
setDynamicItemData(item(i), RawSwitch(item(i)->data(ItemIdRole).toInt()));
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RAWITEMDATAMODELS_H
|
||||
#define RAWITEMDATAMODELS_H
|
||||
|
||||
#include "rawsource.h"
|
||||
#include "rawswitch.h"
|
||||
|
||||
#include <QStandardItemModel>
|
||||
|
||||
class GeneralSettings;
|
||||
class ModelData;
|
||||
|
||||
class AbstractRawItemDataModel: public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum DataRoles { ItemIdRole = Qt::UserRole, ItemTypeRole, ItemFlagsRole, IsAvailableRole };
|
||||
Q_ENUM(DataRoles)
|
||||
|
||||
explicit AbstractRawItemDataModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) :
|
||||
QStandardItemModel(parent),
|
||||
generalSettings(generalSettings),
|
||||
modelData(modelData)
|
||||
{}
|
||||
|
||||
public slots:
|
||||
virtual void update() const = 0;
|
||||
|
||||
protected:
|
||||
const GeneralSettings * generalSettings;
|
||||
const ModelData * modelData;
|
||||
};
|
||||
|
||||
|
||||
class RawSourceItemModel: public AbstractRawItemDataModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void update() const override;
|
||||
|
||||
protected:
|
||||
void setDynamicItemData(QStandardItem * item, const RawSource & src) const;
|
||||
void addItems(const RawSourceType & type, const int group, const int count, const int start = 0);
|
||||
};
|
||||
|
||||
|
||||
class RawSwitchItemModel: public AbstractRawItemDataModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void update() const override;
|
||||
|
||||
protected:
|
||||
void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const;
|
||||
void addItems(const RawSwitchType & type, int count);
|
||||
};
|
||||
|
||||
|
||||
#endif // RAWITEMDATAMODELS_H
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rawitemfilteredmodel.h"
|
||||
#include "rawitemdatamodels.h"
|
||||
|
||||
RawItemFilteredModel::RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent) :
|
||||
QSortFilterProxyModel(parent),
|
||||
filterFlags(0)
|
||||
{
|
||||
setFilterRole(AbstractRawItemDataModel::IsAvailableRole);
|
||||
setFilterKeyColumn(0);
|
||||
setFilterFlags(flags);
|
||||
setDynamicSortFilter(true);
|
||||
setSourceModel(sourceModel);
|
||||
}
|
||||
|
||||
void RawItemFilteredModel::setFilterFlags(int flags)
|
||||
{
|
||||
if (filterFlags != flags) {
|
||||
filterFlags = flags;
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
bool RawItemFilteredModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const
|
||||
{
|
||||
const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool())
|
||||
return false;
|
||||
|
||||
if (!filterFlags)
|
||||
return true;
|
||||
|
||||
bool ok;
|
||||
const int flags = sourceModel()->data(srcIdx, AbstractRawItemDataModel::ItemFlagsRole).toInt(&ok);
|
||||
return (ok && (!flags || (filterFlags & flags)));
|
||||
}
|
||||
|
||||
void RawItemFilteredModel::update() const
|
||||
{
|
||||
AbstractRawItemDataModel * model = qobject_cast<AbstractRawItemDataModel *>(sourceModel());
|
||||
if (model)
|
||||
model->update();
|
||||
}
|
||||
|
||||
|
||||
RawSourceFilterItemModel::RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent) :
|
||||
RawItemFilteredModel(new RawSourceItemModel(generalSettings, modelData, parent), flags, parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RawSwitchFilterItemModel::RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent) :
|
||||
RawItemFilteredModel(new RawSwitchItemModel(generalSettings, modelData, parent), context, parent)
|
||||
{
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RAWITEMFILTEREDMODEL_H
|
||||
#define RAWITEMFILTEREDMODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class GeneralSettings;
|
||||
class ModelData;
|
||||
class RawSourceItemModel;
|
||||
class RawSwitchItemModel;
|
||||
|
||||
class RawItemFilteredModel: public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent = nullptr);
|
||||
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, QObject * parent = nullptr) : RawItemFilteredModel(sourceModel, 0, parent) {}
|
||||
|
||||
public slots:
|
||||
void setFilterFlags(int flags);
|
||||
void update() const;
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override;
|
||||
|
||||
int filterFlags;
|
||||
};
|
||||
|
||||
|
||||
// The specialized "convenience" types below can go away once centralalized RawSource/RawSwitch item models are established.
|
||||
// These proxy classes will automatically create a source model of the corresponding type.
|
||||
|
||||
class RawSwitchFilterItemModel: public RawItemFilteredModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using RawItemFilteredModel::RawItemFilteredModel;
|
||||
|
||||
explicit RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent = nullptr);
|
||||
};
|
||||
|
||||
|
||||
class RawSourceFilterItemModel: public RawItemFilteredModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using RawItemFilteredModel::RawItemFilteredModel;
|
||||
|
||||
explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent = nullptr);
|
||||
|
||||
explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) :
|
||||
RawSourceFilterItemModel(generalSettings, modelData, 0, parent) {}
|
||||
};
|
||||
|
||||
#endif // RAWITEMFILTEREDMODEL_H
|
||||
@@ -1,502 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "filesyncdialog.h"
|
||||
|
||||
#include "autobitsetcheckbox.h"
|
||||
#include "autocheckbox.h"
|
||||
#include "autocombobox.h"
|
||||
#include "autolineedit.h"
|
||||
#include "constants.h"
|
||||
#include "helpers.h"
|
||||
#include "progresswidget.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QComboBox>
|
||||
#include <QCompleter>
|
||||
#include <QCheckBox>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QFileSystemModel>
|
||||
#include <QLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QMenu>
|
||||
#include <QSpinBox>
|
||||
|
||||
FileSyncDialog::FileSyncDialog(QWidget * parent, const SyncProcess::SyncOptions & syncOptions) :
|
||||
QDialog(parent),
|
||||
m_syncOptions(syncOptions),
|
||||
m_running(false)
|
||||
{
|
||||
setWindowTitle(tr("Synchronize Files"));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setSizeGripEnabled(true);
|
||||
|
||||
setupUi();
|
||||
toggleExtraOptions(false);
|
||||
validate();
|
||||
updateRunningState();
|
||||
}
|
||||
|
||||
void FileSyncDialog::reject()
|
||||
{
|
||||
// override close event via window system close or esc. key
|
||||
if (m_running) {
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Are you sure you wish to abort the sync?")) == QMessageBox::No)
|
||||
return;
|
||||
emit stopSync();
|
||||
// Force termination if the sync hasn't finished within 5s
|
||||
QElapsedTimer tim;
|
||||
tim.start();
|
||||
while (!tim.hasExpired(5000) && m_running)
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 10);
|
||||
if (m_running)
|
||||
qWarning() << "Terminating thread while Sync process was still running.";
|
||||
}
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
// Create a widget with a line edit and folder select button and handles all interactions. Features autosuggest
|
||||
// path hints while typing, invalid paths shown in red.
|
||||
// This should probably be moved some place more reusable, esp. the QFileSystemModel.
|
||||
static QWidget * folderSelectorWidget(QLineEdit * le, QWidget * parent)
|
||||
{
|
||||
static QFileSystemModel fileModel;
|
||||
static bool init = false;
|
||||
if (!init) {
|
||||
init = true;
|
||||
fileModel.setFilter(QDir::Dirs);
|
||||
fileModel.setRootPath("/");
|
||||
}
|
||||
|
||||
QWidget * fsw = new QWidget(parent);
|
||||
//le = new QLineEdit(parent);
|
||||
QCompleter * fsc = new QCompleter(fsw);
|
||||
fsc->setModel(&fileModel);
|
||||
//fsc->setCompletionMode(QCompleter::InlineCompletion);
|
||||
le->setCompleter(fsc);
|
||||
|
||||
QToolButton * btn = new QToolButton(fsw);
|
||||
btn->setIcon(CompanionIcon("open.png"));
|
||||
QHBoxLayout * l = new QHBoxLayout(fsw);
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
l->setSpacing(3);
|
||||
l->addWidget(le);
|
||||
l->addWidget(btn);
|
||||
|
||||
QObject::connect(btn, &QToolButton::clicked, [=]() {
|
||||
QString dir = QFileDialog::getExistingDirectory(parent, fsw->property("fileDialogTitle").toString(), le->text(), 0);
|
||||
if (!dir.isEmpty()) {
|
||||
le->setText(QDir::toNativeSeparators(dir));
|
||||
le->setFocus();
|
||||
}
|
||||
});
|
||||
|
||||
QObject::connect(le, &QLineEdit::textChanged, [=](const QString & text) {
|
||||
if (QFile::exists(text))
|
||||
le->setStyleSheet("");
|
||||
else
|
||||
le->setStyleSheet("QLineEdit {color: red;}");
|
||||
});
|
||||
|
||||
return fsw;
|
||||
}
|
||||
|
||||
void FileSyncDialog::setupUi()
|
||||
{
|
||||
const QString srcArw = CPN_STR_SW_INDICATOR_UP % " ";
|
||||
const QString dstArw = CPN_STR_SW_INDICATOR_DN % " ";
|
||||
int row = 0;
|
||||
|
||||
CompanionIcon playIcon("play.png");
|
||||
playIcon.addImage("stop.png", QIcon::Normal, QIcon::On);
|
||||
|
||||
QLabel * lblSrc = new QLabel(tr("Source Folder:"), this);
|
||||
AutoLineEdit * leSrc = new AutoLineEdit(this, true);
|
||||
leSrc->setField(m_syncOptions.folderA);
|
||||
leSrc->setText(QDir::toNativeSeparators(m_syncOptions.folderA));
|
||||
QWidget * wdgSrc = folderSelectorWidget(leSrc, this);
|
||||
|
||||
QLabel * lblDst = new QLabel(tr("Destination Folder:"), this);
|
||||
AutoLineEdit * leDst = new AutoLineEdit(this, true);
|
||||
leDst->setField(m_syncOptions.folderB);
|
||||
leDst->setText(QDir::toNativeSeparators(m_syncOptions.folderB));
|
||||
QWidget * wdgDst = folderSelectorWidget(leDst, this);
|
||||
|
||||
AutoComboBox * syncDir = new AutoComboBox(this);
|
||||
syncDir->addItem(tr("%1%2 Both directions, to destination folder first").arg(dstArw, srcArw), SyncProcess::SYNC_A2B_B2A);
|
||||
syncDir->addItem(tr("%1%2 Both directions, to source folder first").arg(srcArw, dstArw), SyncProcess::SYNC_B2A_A2B);
|
||||
syncDir->addItem(tr(" %1 Only from source folder to destination folder").arg(dstArw), SyncProcess::SYNC_A2B);
|
||||
syncDir->addItem(tr(" %1 Only from destination folder to source folder").arg(srcArw), SyncProcess::SYNC_B2A);
|
||||
syncDir->setCurrentIndex(-1); // we set the default option later
|
||||
|
||||
AutoComboBox * copyMode = new AutoComboBox(this);
|
||||
copyMode->setToolTip(tr("How to handle overwriting files which already exist in the destination folder."));
|
||||
copyMode->addItem(tr("Copy only if newer and different (compare contents)"), SyncProcess::OVERWR_NEWER_IF_DIFF);
|
||||
copyMode->addItem(tr("Copy only if newer (do not compare contents)"), SyncProcess::OVERWR_NEWER_ALWAYS);
|
||||
copyMode->addItem(tr("Copy only if different (ignore file time stamps)"), SyncProcess::OVERWR_IF_DIFF);
|
||||
copyMode->addItem(tr("Always copy (force overwite existing files)"), SyncProcess::OVERWR_ALWAYS);
|
||||
copyMode->setField(m_syncOptions.compareType);
|
||||
|
||||
QSpinBox * maxSize = new QSpinBox(this);
|
||||
maxSize->setRange(0, 100 * 1024);
|
||||
maxSize->setAccelerated(true);
|
||||
maxSize->setSpecialValueText(tr("Any size"));
|
||||
maxSize->setToolTip(tr("Skip files larger than this size. Enter zero for unlimited."));
|
||||
maxSize->setGroupSeparatorShown(true);
|
||||
maxSize->setValue(0); // we set the real default value later
|
||||
|
||||
AutoComboBox * logLevel = new AutoComboBox(this);
|
||||
logLevel->setToolTip(tr("Minimum reporting level. Events of this type and of higher importance are shown.\n" \
|
||||
"WARNING: High log rates may make the user interface temporarily unresponsive."));
|
||||
logLevel->addItem(tr("Skipped"), QtDebugMsg);
|
||||
logLevel->addItem(tr("Created"), QtInfoMsg);
|
||||
logLevel->addItem(tr("Updated"), QtWarningMsg);
|
||||
//logLevel->addItem(tr("Item Deleted"), QtCriticalMsg); // unused
|
||||
logLevel->addItem(tr("Errors Only"), QtFatalMsg);
|
||||
logLevel->setField(m_syncOptions.logLevel);
|
||||
|
||||
AutoBitsetCheckBox * testRun = new AutoBitsetCheckBox(m_syncOptions.flags, SyncProcess::OPT_DRY_RUN, tr("Test-run only"), this);
|
||||
testRun->setToolTip(tr("Run as normal but do not actually copy anything. Useful for verifying results before real sync."));
|
||||
|
||||
// layout to hold size spinbox and checkbox option(s)
|
||||
QHBoxLayout * hlay1 = new QHBoxLayout();
|
||||
hlay1->addWidget(maxSize, 1);
|
||||
hlay1->addWidget(testRun);
|
||||
hlay1->addWidget(new QLabel(tr("Log Level:"), this));
|
||||
hlay1->addWidget(logLevel);
|
||||
|
||||
// "extra" options
|
||||
|
||||
QLabel * lbFilter = new QLabel(tr("Filters:"), this);
|
||||
lbFilter->setToolTip(tr("The \"Include\" filter will only copy files which match the pattern(s).\n" \
|
||||
"The \"Exclude\" filter will skip files matching the filter pattern(s).\n" \
|
||||
"The Include filter is evaluated first."));
|
||||
|
||||
AutoLineEdit * leFiltExc = new AutoLineEdit(this, true);
|
||||
leFiltExc->setField(m_syncOptions.excludeFilter);
|
||||
leFiltExc->setToolTip(tr("One or more file pattern(s) to exclude, separated by commas.\n" "Blank means exclude none. ?, *, and [...] wildcards accepted."));
|
||||
|
||||
AutoLineEdit * leFiltInc = new AutoLineEdit(this, true);
|
||||
leFiltInc->setField(m_syncOptions.includeFilter);
|
||||
leFiltInc->setToolTip(tr("One or more file pattern(s) to include, separated by commas.\n" "Blank means include all. ?, *, and [...] wildcards accepted."));
|
||||
|
||||
// layout to hold filter options
|
||||
QHBoxLayout * filtLo = new QHBoxLayout();
|
||||
filtLo->addWidget(new QLabel(tr("Include:"), this));
|
||||
filtLo->addWidget(leFiltInc, 1);
|
||||
filtLo->addWidget(new QLabel(tr("Exclude:"), this));
|
||||
filtLo->addWidget(leFiltExc, 1);
|
||||
|
||||
// file options
|
||||
QHBoxLayout * filOptsLo = new QHBoxLayout();
|
||||
filOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::CaseSensitive, tr("Case sensitive"), this));
|
||||
filOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::NoSymLinks, true, tr("Follow links"), this));
|
||||
filOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::Hidden, tr("Include hidden"), this));
|
||||
|
||||
// folder options
|
||||
QHBoxLayout * dirOptsLo = new QHBoxLayout();
|
||||
dirOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.flags, SyncProcess::OPT_RECURSIVE, tr("Recursive"), this));
|
||||
dirOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.flags, SyncProcess::OPT_SKIP_DIR_LINKS, true, tr("Follow links"), this));
|
||||
dirOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::Dirs, true, tr("Skip empty"), this));
|
||||
dirOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::AllDirs, true, tr("Apply filters"), this));
|
||||
|
||||
// extra options container widget and layout
|
||||
ui_extraOptions = new QWidget(this);
|
||||
ui_extraOptions->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
|
||||
|
||||
QGridLayout * xOptsLay = new QGridLayout(ui_extraOptions);
|
||||
xOptsLay->setContentsMargins(0, 0, 0, 0);
|
||||
xOptsLay->addWidget(lbFilter, row, 0);
|
||||
xOptsLay->addLayout(filtLo, row++, 1);
|
||||
xOptsLay->addWidget(new QLabel(tr("Filter Options:"), this), row, 0);
|
||||
xOptsLay->addLayout(filOptsLo, row++, 1);
|
||||
xOptsLay->addWidget(new QLabel(tr("Folder Options:"), this), row, 0);
|
||||
xOptsLay->addLayout(dirOptsLo, row++, 1);
|
||||
|
||||
// status label
|
||||
ui_statusLabel = new QLabel(this);
|
||||
// progress widget
|
||||
ui_progress = new ProgressWidget(this);
|
||||
ui_progress->setMinimumWidth(0);
|
||||
ui_progress->setVisible(false);
|
||||
|
||||
// dialog buttons & menu
|
||||
|
||||
QMenu * optionsMenu = new QMenu(tr("Options"));
|
||||
QAction * xtrasAct = optionsMenu->addAction(CompanionIcon("fuses.png"), tr("Show extra options"), this, &FileSyncDialog::toggleExtraOptions);
|
||||
xtrasAct->setCheckable(true);
|
||||
connect(this, &FileSyncDialog::extraOptionsToggled, xtrasAct, &QAction::setChecked);
|
||||
optionsMenu->addAction(CompanionIcon("paintbrush.png"), tr("Reset to defaults"), this, &FileSyncDialog::resetOptions);
|
||||
|
||||
QToolButton * btnOpts = new QToolButton(this);
|
||||
btnOpts->setDefaultAction(xtrasAct);
|
||||
btnOpts->setMenu(optionsMenu);
|
||||
btnOpts->setToolButtonStyle(Qt::ToolButtonIconOnly);
|
||||
btnOpts->setPopupMode(QToolButton::MenuButtonPopup);
|
||||
btnOpts->setToolTip(xtrasAct->text());
|
||||
|
||||
ui_btnStartStop = new QToolButton(this);
|
||||
ui_btnStartStop->setCheckable(true);
|
||||
ui_btnStartStop->setIcon(playIcon);
|
||||
ui_btnStartStop->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
|
||||
ui_btnClose = new QToolButton(this);
|
||||
ui_btnClose->setText(tr("Close"));
|
||||
ui_btnClose->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
||||
ui_btnClose->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
|
||||
|
||||
ui_buttonBox = new QDialogButtonBox(this);
|
||||
ui_buttonBox->addButton(btnOpts, QDialogButtonBox::ActionRole);
|
||||
ui_buttonBox->addButton(ui_btnStartStop, QDialogButtonBox::ActionRole);
|
||||
ui_buttonBox->addButton(ui_btnClose, QDialogButtonBox::RejectRole);
|
||||
|
||||
// The options group box.
|
||||
ui_optionsPanel = new QGroupBox(tr("Options"), this);
|
||||
QGridLayout * optsLay = new QGridLayout(ui_optionsPanel);
|
||||
row = 0;
|
||||
optsLay->addWidget(lblSrc, row, 0);
|
||||
optsLay->addWidget(wdgSrc, row++, 1);
|
||||
optsLay->addWidget(lblDst, row, 0);
|
||||
optsLay->addWidget(wdgDst, row++, 1);
|
||||
optsLay->addWidget(new QLabel(tr("Sync. Direction:"), this), row, 0);
|
||||
optsLay->addWidget(syncDir, row++, 1);
|
||||
optsLay->addWidget(new QLabel(tr("Existing Files:"), this), row, 0);
|
||||
optsLay->addWidget(copyMode, row++, 1);
|
||||
optsLay->addWidget(new QLabel(tr("Max. File Size:"), this), row, 0);
|
||||
optsLay->addLayout(hlay1, row++, 1);
|
||||
optsLay->addWidget(ui_extraOptions, row, 0, 1, 2);
|
||||
|
||||
// layout to hold warning label and button box
|
||||
QHBoxLayout * hlay2 = new QHBoxLayout();
|
||||
hlay2->addWidget(ui_statusLabel, 1);
|
||||
hlay2->addWidget(ui_buttonBox);
|
||||
|
||||
// Create main layout and add options, progress, buttons.
|
||||
QVBoxLayout * dlgL = new QVBoxLayout(this);
|
||||
dlgL->addWidget(ui_optionsPanel, 0, Qt::AlignTop);
|
||||
dlgL->addLayout(hlay2);
|
||||
dlgL->addWidget(ui_progress, 1);
|
||||
|
||||
// Connect all signal handlers
|
||||
|
||||
// source path
|
||||
connect(leSrc, &AutoLineEdit::textChanged, this, &FileSyncDialog::validate);
|
||||
// destination path
|
||||
connect(leDst, &AutoLineEdit::textChanged, this, &FileSyncDialog::validate);
|
||||
|
||||
// function to dis/enable the OVERWR_ALWAYS option depending on sync direction
|
||||
connect(syncDir, &AutoComboBox::currentDataChanged, [=](int dir) {
|
||||
int idx = copyMode->findData(SyncProcess::OVERWR_ALWAYS);
|
||||
int flg = (dir == SyncProcess::SYNC_A2B || dir == SyncProcess::SYNC_B2A) ? 33 : 0;
|
||||
if (!flg && idx == copyMode->currentIndex())
|
||||
copyMode->setCurrentIndex(copyMode->findData(SyncProcess::OVERWR_NEWER_IF_DIFF));
|
||||
copyMode->setItemData(idx, flg, Qt::UserRole - 1);
|
||||
});
|
||||
|
||||
// function to set magnitude of file size spinbox, KB or MB
|
||||
connect(maxSize, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=](int value) {
|
||||
const QSignalBlocker blocker(maxSize);
|
||||
int multi = maxSize->property("multi").isValid() ? maxSize->property("multi").toInt() : 0;
|
||||
if (value >= 10 * 1024 && multi != 1024 * 1024) {
|
||||
// KB -> MB
|
||||
multi = 1024 * 1024;
|
||||
maxSize->setValue(value / 1024);
|
||||
maxSize->setMaximum(100);
|
||||
maxSize->setSingleStep(1);
|
||||
maxSize->setSuffix(tr(" MB"));
|
||||
}
|
||||
else if ((value < 10 && multi != 1024) || !multi) {
|
||||
// MB -> KB
|
||||
if (multi)
|
||||
value *= 1024;
|
||||
multi = 1024;
|
||||
if (value == 9 * 1024)
|
||||
value += 1024 - 32; // avoid large jump when stepping from 10MB to 10,208KB
|
||||
maxSize->setMaximum(100 * 1024);
|
||||
maxSize->setValue(value);
|
||||
maxSize->setSingleStep(32);
|
||||
maxSize->setSuffix(tr(" KB"));
|
||||
}
|
||||
maxSize->setProperty("multi", multi);
|
||||
m_syncOptions.maxFileSize = value * multi;
|
||||
});
|
||||
|
||||
// we set these after connections are made because we want the signal processors to run
|
||||
syncDir->setField(m_syncOptions.direction);
|
||||
maxSize->setValue(m_syncOptions.maxFileSize / 1024);
|
||||
|
||||
// connect Reset action to all fields
|
||||
for (AutoLineEdit * a : ui_optionsPanel->findChildren<AutoLineEdit *>())
|
||||
connect(this, &FileSyncDialog::optionsWereReset, a, &AutoLineEdit::updateValue);
|
||||
for (AutoComboBox * a : ui_optionsPanel->findChildren<AutoComboBox *>())
|
||||
connect(this, &FileSyncDialog::optionsWereReset, a, &AutoComboBox::updateValue);
|
||||
for (AutoBitsetCheckBox * a : ui_optionsPanel->findChildren<AutoBitsetCheckBox *>())
|
||||
connect(this, &FileSyncDialog::optionsWereReset, a, &AutoBitsetCheckBox::updateValue);
|
||||
connect(this, &FileSyncDialog::optionsWereReset, [=]() { maxSize->setValue(m_syncOptions.maxFileSize / 1024); });
|
||||
|
||||
// React to name changes for source and destination path labels
|
||||
connect(this, &FileSyncDialog::folderNameAChanged, [=](const QString &text) {
|
||||
lblSrc->setText(text % ":");
|
||||
wdgSrc->setProperty("fileDialogTitle", text);
|
||||
});
|
||||
connect(this, &FileSyncDialog::folderNameBChanged, [=](const QString &text) {
|
||||
lblDst->setText(text % ":");
|
||||
wdgDst->setProperty("fileDialogTitle", text);
|
||||
});
|
||||
|
||||
// button actions
|
||||
connect(ui_btnStartStop, &QPushButton::clicked, this, &FileSyncDialog::toggleSync);
|
||||
connect(ui_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
connect(ui_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui_progress, &ProgressWidget::detailsToggled, this, &FileSyncDialog::adjustSizeDelayed);
|
||||
}
|
||||
|
||||
void FileSyncDialog::toggleSync(bool)
|
||||
{
|
||||
if (m_running) {
|
||||
setCursor(Qt::WaitCursor);
|
||||
emit stopSync();
|
||||
return;
|
||||
}
|
||||
|
||||
ui_progress->clearDetails();
|
||||
ui_progress->setInfo("");
|
||||
SyncProcess * syncProcess = new SyncProcess(m_syncOptions);
|
||||
|
||||
// move sync process to separate thread, we only use signals/slots from here on...
|
||||
QThread * syncThread = new QThread(this);
|
||||
syncProcess->moveToThread(syncThread);
|
||||
|
||||
// ...and quite a few of them!
|
||||
connect(this, &FileSyncDialog::startSync, syncProcess, &SyncProcess::run);
|
||||
connect(this, &FileSyncDialog::stopSync, syncProcess, &SyncProcess::stop);
|
||||
connect(syncProcess, &SyncProcess::started, this, &FileSyncDialog::onSyncStarted);
|
||||
connect(syncProcess, &SyncProcess::finished, this, &FileSyncDialog::onSyncFinished);
|
||||
connect(syncProcess, &SyncProcess::statusMessage, this, &FileSyncDialog::setStatusText);
|
||||
connect(syncProcess, &SyncProcess::statusUpdate, this, &FileSyncDialog::onStatusUpdate);
|
||||
connect(syncProcess, &SyncProcess::fileCountChanged, ui_progress, &ProgressWidget::setMaximum);
|
||||
connect(syncProcess, &SyncProcess::progressMessage, ui_progress, &ProgressWidget::addMessage);
|
||||
connect(syncProcess, &SyncProcess::finished, syncThread, &QThread::quit);
|
||||
connect(syncThread, &QThread::finished, syncThread, &QThread::deleteLater);
|
||||
connect(syncThread, &QThread::destroyed, syncProcess, &SyncProcess::deleteLater);
|
||||
|
||||
// go
|
||||
syncThread->start(QThread::LowPriority);
|
||||
emit startSync();
|
||||
}
|
||||
|
||||
void FileSyncDialog::onSyncStarted()
|
||||
{
|
||||
m_running = true;
|
||||
updateRunningState();
|
||||
}
|
||||
|
||||
void FileSyncDialog::onSyncFinished()
|
||||
{
|
||||
m_running = false;
|
||||
updateRunningState();
|
||||
if (parentWidget())
|
||||
QApplication::alert(parentWidget());
|
||||
}
|
||||
|
||||
void FileSyncDialog::updateRunningState()
|
||||
{
|
||||
ui_btnStartStop->setChecked(m_running);
|
||||
ui_optionsPanel->setEnabled(!m_running);
|
||||
ui_btnClose->setEnabled(!m_running);
|
||||
ui_btnStartStop->setText(m_running ? tr("Abort") : tr("Start"));
|
||||
if (m_running) {
|
||||
ui_progress->setVisible(true); // don't hide after run
|
||||
}
|
||||
else {
|
||||
setCursor(Qt::ArrowCursor); // in case we set a wait cursor upon abort request
|
||||
}
|
||||
}
|
||||
|
||||
void FileSyncDialog::onStatusUpdate(const SyncProcess::SyncStatus & stat)
|
||||
{
|
||||
static const QString reportTemplate = tr("Total: <b>%1</b>; Created: <b>%2</b>; Updated: <b>%3</b>; Skipped: <b>%4</b>; Errors: <font color=%6><b>%5</b></font>;");
|
||||
ui_progress->setInfo((stat.index < stat.count ? tr("Current: <b>%1</b> of ").arg(stat.index) : "") % reportTemplate.arg(stat.count).arg(stat.created).arg(stat.updated).arg(stat.skipped).arg(stat.errored).arg(stat.errored ? "red" : "black"));
|
||||
ui_progress->setValue(stat.index);
|
||||
}
|
||||
|
||||
void FileSyncDialog::setSyncOptions(const SyncProcess::SyncOptions & syncOptions)
|
||||
{
|
||||
m_syncOptions = syncOptions;
|
||||
emit optionsWereReset();
|
||||
}
|
||||
|
||||
void FileSyncDialog::resetOptions()
|
||||
{
|
||||
m_syncOptions.reset();
|
||||
emit optionsWereReset();
|
||||
}
|
||||
|
||||
void FileSyncDialog::toggleExtraOptions(bool show)
|
||||
{
|
||||
ui_extraOptions->setVisible(show);
|
||||
if (!ui_progress->detailsVisible())
|
||||
adjustSizeDelayed();
|
||||
m_extraOptionsVisible = show;
|
||||
emit extraOptionsToggled(show);
|
||||
}
|
||||
|
||||
void FileSyncDialog::setFolderNameA(const QString & name)
|
||||
{
|
||||
if (m_folderNameA != name) {
|
||||
m_folderNameA = name;
|
||||
emit folderNameAChanged(name);
|
||||
}
|
||||
}
|
||||
|
||||
void FileSyncDialog::setFolderNameB(const QString & name)
|
||||
{
|
||||
if (m_folderNameB != name) {
|
||||
m_folderNameB = name;
|
||||
emit folderNameBChanged(name);
|
||||
}
|
||||
}
|
||||
|
||||
void FileSyncDialog::setStatusText(const QString & text, int type)
|
||||
{
|
||||
ui_statusLabel->setText(text);
|
||||
ui_statusLabel->setStyleSheet(type != QtInfoMsg && type >= QtWarningMsg ? "QLabel { color: red; }:" : "");
|
||||
}
|
||||
|
||||
bool FileSyncDialog::validate()
|
||||
{
|
||||
QString msg;
|
||||
if (m_syncOptions.folderA.isEmpty() || !QFileInfo(m_syncOptions.folderA).exists())
|
||||
msg = tr("Source folder not found.");
|
||||
else if (m_syncOptions.folderB.isEmpty() || !QFileInfo(m_syncOptions.folderB).exists())
|
||||
msg = tr("Destination folder not found.");
|
||||
else if (QFileInfo(m_syncOptions.folderA).canonicalFilePath() == QFileInfo(m_syncOptions.folderB).canonicalFilePath())
|
||||
msg = tr("Source and destination folders are the same.");
|
||||
|
||||
setStatusText(msg, QtCriticalMsg);
|
||||
ui_btnStartStop->setEnabled(msg.isEmpty());
|
||||
return msg.isEmpty();
|
||||
}
|
||||
|
||||
void FileSyncDialog::adjustSizeDelayed()
|
||||
{
|
||||
QTimer::singleShot(0, [=]() { adjustSize(); });
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef FILESYNCDIALOG_H
|
||||
#define FILESYNCDIALOG_H
|
||||
|
||||
#include "process_sync.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
|
||||
class ProgressWidget;
|
||||
|
||||
class FileSyncDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(SyncProcess::SyncOptions syncOptions READ syncOptions WRITE setSyncOptions RESET resetOptions NOTIFY optionsWereReset)
|
||||
Q_PROPERTY(bool extraOptionsVisible READ extraOptionsVisible WRITE toggleExtraOptions NOTIFY extraOptionsToggled)
|
||||
Q_PROPERTY(QString folderNameA READ folderNameA WRITE setFolderNameA NOTIFY folderNameAChanged)
|
||||
Q_PROPERTY(QString folderNameB READ folderNameB WRITE setFolderNameB NOTIFY folderNameBChanged)
|
||||
|
||||
public:
|
||||
FileSyncDialog(QWidget * parent = nullptr, const SyncProcess::SyncOptions & syncOptions = SyncProcess::SyncOptions());
|
||||
|
||||
inline SyncProcess::SyncOptions syncOptions() const { return m_syncOptions; }
|
||||
void setSyncOptions(const SyncProcess::SyncOptions & syncOptions);
|
||||
void resetOptions();
|
||||
|
||||
inline bool extraOptionsVisible() const { return m_extraOptionsVisible; }
|
||||
void toggleExtraOptions(bool show);
|
||||
|
||||
inline QString folderNameA() const { return m_folderNameA; }
|
||||
void setFolderNameA(const QString & name);
|
||||
|
||||
inline QString folderNameB() const { return m_folderNameB; }
|
||||
void setFolderNameB(const QString & name);
|
||||
|
||||
public slots:
|
||||
virtual void reject() override;
|
||||
void setStatusText(const QString & text, int type = QtWarningMsg);
|
||||
bool validate();
|
||||
|
||||
signals:
|
||||
void startSync();
|
||||
void stopSync();
|
||||
void folderNameAChanged(const QString & name);
|
||||
void folderNameBChanged(const QString & name);
|
||||
void extraOptionsToggled(bool show);
|
||||
void optionsWereReset();
|
||||
|
||||
private slots:
|
||||
void setupUi();
|
||||
void toggleSync(bool);
|
||||
void onSyncStarted();
|
||||
void onSyncFinished();
|
||||
void updateRunningState();
|
||||
void onStatusUpdate(const SyncProcess::SyncStatus & stat);
|
||||
void adjustSizeDelayed();
|
||||
|
||||
private:
|
||||
SyncProcess::SyncOptions m_syncOptions;
|
||||
QString m_folderNameA;
|
||||
QString m_folderNameB;
|
||||
bool m_running;
|
||||
bool m_extraOptionsVisible;
|
||||
|
||||
QGroupBox * ui_optionsPanel;
|
||||
QWidget * ui_extraOptions;
|
||||
ProgressWidget * ui_progress;
|
||||
QDialogButtonBox * ui_buttonBox;
|
||||
QToolButton * ui_btnStartStop;
|
||||
QToolButton * ui_btnClose;
|
||||
QLabel * ui_statusLabel;
|
||||
};
|
||||
|
||||
#endif // FILESYNCDIALOG_H
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "downloaddialog.h"
|
||||
#include "ui_downloaddialog.h"
|
||||
#include "constants.h"
|
||||
#include "helpers.h"
|
||||
|
||||
#include <QTime>
|
||||
|
||||
downloadDialog::downloadDialog(QWidget *parent, QString src, QString tgt):
|
||||
QDialog(parent),
|
||||
ui(new Ui::downloadDialog),
|
||||
reply(nullptr),
|
||||
file(nullptr),
|
||||
aborted(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowIcon(CompanionIcon("fwpreferences.png"));
|
||||
ui->progressBar->setValue(1);
|
||||
ui->progressBar->setMinimum(0);
|
||||
ui->progressBar->setMaximum(0);
|
||||
|
||||
if (tgt.isEmpty()) {
|
||||
setWindowTitle(src);
|
||||
return; // just show wait dialog.
|
||||
}
|
||||
|
||||
file = new QFile(tgt);
|
||||
if (!file->open(QIODevice::WriteOnly)) {
|
||||
QMessageBox::critical(this, CPN_STR_APP_NAME,
|
||||
tr("Unable to save the file %1: %2.")
|
||||
.arg(tgt).arg(file->errorString()));
|
||||
QTimer::singleShot(0, this, SLOT(fileError()));
|
||||
}
|
||||
else {
|
||||
reply = qnam.get(QNetworkRequest(QUrl(src)));
|
||||
connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
|
||||
connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead()));
|
||||
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDataReadProgress(qint64,qint64)));
|
||||
}
|
||||
}
|
||||
|
||||
downloadDialog::~downloadDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete file;
|
||||
}
|
||||
|
||||
void downloadDialog::reject()
|
||||
{
|
||||
if (reply && reply->isRunning()) {
|
||||
aborted = true;
|
||||
reply->abort(); // this will call QNetworkReply::finished()
|
||||
return;
|
||||
}
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void downloadDialog::httpFinished()
|
||||
{
|
||||
file->flush();
|
||||
file->close();
|
||||
|
||||
const bool ok = !(reply->error() || aborted);
|
||||
if (!ok) {
|
||||
file->remove();
|
||||
if (!aborted)
|
||||
QMessageBox::information(this, CPN_STR_APP_NAME, tr("Download failed: %1.").arg(reply->errorString()));
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
file->deleteLater();
|
||||
file = nullptr;
|
||||
|
||||
if (ok)
|
||||
accept();
|
||||
else
|
||||
reject();
|
||||
}
|
||||
|
||||
void downloadDialog::httpReadyRead()
|
||||
{
|
||||
if (file) {
|
||||
file->write(reply->readAll());
|
||||
}
|
||||
}
|
||||
|
||||
void downloadDialog::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
|
||||
{
|
||||
ui->progressBar->setMaximum(totalBytes);
|
||||
ui->progressBar->setValue(bytesRead);
|
||||
}
|
||||
|
||||
void downloadDialog::fileError()
|
||||
{
|
||||
delete file;
|
||||
file = NULL;
|
||||
reject();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void downloadDialog::closeEvent( QCloseEvent * event)
|
||||
{
|
||||
// Delay closing 2 seconds to avoid unpleasant flashing download dialogs
|
||||
QTime closeTime= QTime::currentTime().addSecs(2);
|
||||
while( QTime::currentTime() < closeTime )
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
||||
|
||||
event->accept();
|
||||
}
|
||||
#endif
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _DOWNLOADDIALOG_H_
|
||||
#define _DOWNLOADDIALOG_H_
|
||||
|
||||
#include <QtWidgets>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QFile>
|
||||
|
||||
namespace Ui {
|
||||
class downloadDialog;
|
||||
}
|
||||
|
||||
class downloadDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit downloadDialog(QWidget *parent = 0, QString src = "", QString tgt = "");
|
||||
~downloadDialog();
|
||||
|
||||
public slots:
|
||||
virtual void reject() override;
|
||||
|
||||
private slots:
|
||||
void fileError();
|
||||
void httpFinished();
|
||||
void httpReadyRead();
|
||||
void updateDataReadProgress(qint64 bytesRead, qint64 totalBytes);
|
||||
|
||||
private:
|
||||
#if 0
|
||||
void closeEvent( QCloseEvent * event);
|
||||
#endif
|
||||
Ui::downloadDialog *ui;
|
||||
|
||||
QNetworkAccessManager qnam;
|
||||
QNetworkReply *reply;
|
||||
QFile *file;
|
||||
bool aborted;
|
||||
};
|
||||
|
||||
#endif // _DOWNLOADDIALOG_H_
|
||||
@@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>downloadDialog</class>
|
||||
<widget class="QDialog" name="downloadDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>562</width>
|
||||
<height>82</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Downloading: </string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="companion.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>downloadDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>downloadDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
set(firmwares_SRCS
|
||||
boards.cpp
|
||||
curvereference.cpp
|
||||
customfunctiondata.cpp
|
||||
eeprominterface.cpp
|
||||
generalsettings.cpp
|
||||
gvardata.cpp
|
||||
io_data.cpp
|
||||
logicalswitchdata.cpp
|
||||
modeldata.cpp
|
||||
moduledata.cpp
|
||||
multiprotocols.cpp
|
||||
radiodata.cpp
|
||||
radiodataconversionstate.cpp
|
||||
rawsource.cpp
|
||||
rawswitch.cpp
|
||||
sensordata.cpp
|
||||
telem_data.cpp
|
||||
er9x/er9xeeprom.cpp
|
||||
er9x/er9xinterface.cpp
|
||||
ersky9x/ersky9xeeprom.cpp
|
||||
ersky9x/ersky9xinterface.cpp
|
||||
opentx/opentxeeprom.cpp
|
||||
opentx/opentxinterface.cpp
|
||||
)
|
||||
|
||||
string(REPLACE ".cpp" ".h" firmwares_HDRS "${firmwares_SRCS}")
|
||||
|
||||
list(APPEND firmwares_HDRS
|
||||
eepromimportexport.h
|
||||
moduledata.h
|
||||
)
|
||||
|
||||
add_library(firmwares ${firmwares_SRCS} ${firmwares_HDRS})
|
||||
target_link_libraries(firmwares ${CPN_COMMON_LIB} Qt5::Core Qt5::Xml Qt5::Widgets)
|
||||
target_include_directories(firmwares
|
||||
PRIVATE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_LIST_DIR}"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/er9x"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/ersky9x"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/opentx"
|
||||
)
|
||||
@@ -1,427 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "boards.h"
|
||||
#include "macros.h"
|
||||
|
||||
// TODO remove all those constants
|
||||
// Update: These are now all only used within this class.
|
||||
// External access is only via getEEpromSize() and getFlashSize()
|
||||
|
||||
#define EESIZE_STOCK 2048
|
||||
#define EESIZE_M128 4096
|
||||
#define EESIZE_GRUVIN9X 4096
|
||||
#define EESIZE_TARANIS (32*1024)
|
||||
#define EESIZE_SKY9X (128*4096)
|
||||
#define EESIZE_9XRPRO (128*4096)
|
||||
#define EESIZE_MAX EESIZE_9XRPRO
|
||||
|
||||
// getFlashSize() (and these macros) is only used by radiointerface::getDfuArgs (perhaps can find a better way?)
|
||||
#define FSIZE_STOCK (64*1024)
|
||||
#define FSIZE_M128 (128*1024)
|
||||
#define FSIZE_GRUVIN9X (256*1024)
|
||||
#define FSIZE_TARANIS (512*1024)
|
||||
#define FSIZE_SKY9X (256*1024)
|
||||
#define FSIZE_9XRPRO (512*1024)
|
||||
#define FSIZE_HORUS (2048*1024)
|
||||
#define FSIZE_MAX FSIZE_HORUS
|
||||
|
||||
using namespace Board;
|
||||
|
||||
void Boards::setBoardType(const Type & board)
|
||||
{
|
||||
if (board >= BOARD_UNKNOWN && board < BOARD_ENUM_COUNT)
|
||||
m_boardType = board;
|
||||
else
|
||||
m_boardType = BOARD_UNKNOWN;
|
||||
}
|
||||
|
||||
uint32_t Boards::getFourCC(Type board)
|
||||
{
|
||||
switch (board) {
|
||||
case BOARD_X12S:
|
||||
return 0x3478746F;
|
||||
case BOARD_X10:
|
||||
return 0x3778746F;
|
||||
case BOARD_TARANIS_XLITE:
|
||||
return 0x3978746F;
|
||||
case BOARD_TARANIS_X7:
|
||||
return 0x3678746F;
|
||||
case BOARD_TARANIS_X9E:
|
||||
return 0x3578746F;
|
||||
case BOARD_TARANIS_X9D:
|
||||
case BOARD_TARANIS_X9DP:
|
||||
return 0x3378746F;
|
||||
case BOARD_SKY9X:
|
||||
case BOARD_AR9X:
|
||||
case BOARD_9XRPRO:
|
||||
return 0x3278746F;
|
||||
case BOARD_MEGA2560:
|
||||
case BOARD_GRUVIN9X:
|
||||
return 0x3178746F;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const int Boards::getEEpromSize(Board::Type board)
|
||||
{
|
||||
switch (board) {
|
||||
case BOARD_STOCK:
|
||||
return EESIZE_STOCK;
|
||||
case BOARD_M128:
|
||||
return EESIZE_M128;
|
||||
case BOARD_MEGA2560:
|
||||
case BOARD_GRUVIN9X:
|
||||
return EESIZE_GRUVIN9X;
|
||||
case BOARD_SKY9X:
|
||||
return EESIZE_SKY9X;
|
||||
case BOARD_9XRPRO:
|
||||
case BOARD_AR9X:
|
||||
return EESIZE_9XRPRO;
|
||||
case BOARD_TARANIS_XLITE:
|
||||
case BOARD_TARANIS_X7:
|
||||
case BOARD_TARANIS_X9D:
|
||||
case BOARD_TARANIS_X9DP:
|
||||
case BOARD_TARANIS_X9E:
|
||||
return EESIZE_TARANIS;
|
||||
case BOARD_UNKNOWN:
|
||||
return EESIZE_MAX;
|
||||
default:
|
||||
return 0; // unlimited
|
||||
}
|
||||
}
|
||||
|
||||
const int Boards::getFlashSize(Type board)
|
||||
{
|
||||
switch (board) {
|
||||
case BOARD_STOCK:
|
||||
return FSIZE_STOCK;
|
||||
case BOARD_M128:
|
||||
return FSIZE_M128;
|
||||
case BOARD_MEGA2560:
|
||||
case BOARD_GRUVIN9X:
|
||||
return FSIZE_GRUVIN9X;
|
||||
case BOARD_SKY9X:
|
||||
return FSIZE_SKY9X;
|
||||
case BOARD_9XRPRO:
|
||||
case BOARD_AR9X:
|
||||
return FSIZE_9XRPRO;
|
||||
case BOARD_TARANIS_XLITE:
|
||||
case BOARD_TARANIS_X7:
|
||||
case BOARD_TARANIS_X9D:
|
||||
case BOARD_TARANIS_X9DP:
|
||||
case BOARD_TARANIS_X9E:
|
||||
return FSIZE_TARANIS;
|
||||
case BOARD_X12S:
|
||||
case BOARD_X10:
|
||||
return FSIZE_HORUS;
|
||||
case BOARD_UNKNOWN:
|
||||
return FSIZE_MAX;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return {SWITCH_NOT_AVAILABLE, CPN_STR_UNKNOWN_ITEM};
|
||||
|
||||
if (IS_TARANIS_XLITE(board)) {
|
||||
const Board::SwitchInfo switches[] = {
|
||||
{SWITCH_3POS, "SA"},
|
||||
{SWITCH_3POS, "SB"},
|
||||
{SWITCH_2POS, "SC"},
|
||||
{SWITCH_2POS, "SD"}
|
||||
};
|
||||
if (index < DIM(switches))
|
||||
return switches[index];
|
||||
}
|
||||
if (IS_TARANIS_X7(board)) {
|
||||
const Board::SwitchInfo switches[] = {
|
||||
{SWITCH_3POS, "SA"},
|
||||
{SWITCH_3POS, "SB"},
|
||||
{SWITCH_3POS, "SC"},
|
||||
{SWITCH_3POS, "SD"},
|
||||
{SWITCH_2POS, "SF"},
|
||||
{SWITCH_TOGGLE, "SH"}
|
||||
};
|
||||
if (index < DIM(switches))
|
||||
return switches[index];
|
||||
}
|
||||
else if (IS_HORUS_OR_TARANIS(board)) {
|
||||
const Board::SwitchInfo switches[] = {
|
||||
{SWITCH_3POS, "SA"},
|
||||
{SWITCH_3POS, "SB"},
|
||||
{SWITCH_3POS, "SC"},
|
||||
{SWITCH_3POS, "SD"},
|
||||
{SWITCH_3POS, "SE"},
|
||||
{SWITCH_2POS, "SF"},
|
||||
{SWITCH_3POS, "SG"},
|
||||
{SWITCH_TOGGLE, "SH"},
|
||||
{SWITCH_3POS, "SI"},
|
||||
{SWITCH_3POS, "SJ"},
|
||||
{SWITCH_3POS, "SK"},
|
||||
{SWITCH_3POS, "SL"},
|
||||
{SWITCH_3POS, "SM"},
|
||||
{SWITCH_3POS, "SN"},
|
||||
{SWITCH_3POS, "SO"},
|
||||
{SWITCH_3POS, "SP"},
|
||||
{SWITCH_3POS, "SQ"},
|
||||
{SWITCH_3POS, "SR"}
|
||||
};
|
||||
if (index < DIM(switches))
|
||||
return switches[index];
|
||||
}
|
||||
else {
|
||||
const Board::SwitchInfo switches[] = {
|
||||
{SWITCH_3POS, "3POS"},
|
||||
{SWITCH_2POS, "THR"},
|
||||
{SWITCH_2POS, "RUD"},
|
||||
{SWITCH_2POS, "ELE"},
|
||||
{SWITCH_2POS, "AIL"},
|
||||
{SWITCH_2POS, "GEA"},
|
||||
{SWITCH_TOGGLE, "TRN"}
|
||||
};
|
||||
if (index < DIM(switches))
|
||||
return switches[index];
|
||||
}
|
||||
|
||||
return {SWITCH_NOT_AVAILABLE, CPN_STR_UNKNOWN_ITEM};
|
||||
}
|
||||
|
||||
const int Boards::getCapability(Board::Type board, Board::Capability capability)
|
||||
{
|
||||
switch (capability) {
|
||||
case Sticks:
|
||||
return 4;
|
||||
|
||||
case Pots:
|
||||
if (IS_TARANIS_SMALL(board))
|
||||
return 2;
|
||||
else if (IS_TARANIS_X9E(board))
|
||||
return 4;
|
||||
else
|
||||
return 3;
|
||||
|
||||
case FactoryInstalledPots:
|
||||
if (IS_TARANIS_X9(board))
|
||||
return 2;
|
||||
else
|
||||
return getCapability(board, Pots);
|
||||
|
||||
case Sliders:
|
||||
if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board))
|
||||
return 4;
|
||||
else if (IS_TARANIS_X9D(board) || IS_HORUS_X10(board))
|
||||
return 2;
|
||||
else
|
||||
return 0;
|
||||
|
||||
case MouseAnalogs:
|
||||
if (IS_HORUS_X12S(board))
|
||||
return 2;
|
||||
else
|
||||
return 0;
|
||||
|
||||
case MaxAnalogs:
|
||||
return getCapability(board, Board::Sticks) + getCapability(board, Board::Pots) + getCapability(board, Board::Sliders) + getCapability(board, Board::MouseAnalogs);
|
||||
|
||||
case MultiposPots:
|
||||
return IS_HORUS_OR_TARANIS(board) ? 3 : 0;
|
||||
|
||||
case MultiposPotsPositions:
|
||||
return IS_HORUS_OR_TARANIS(board) ? 6 : 0;
|
||||
|
||||
case Switches:
|
||||
if (IS_TARANIS_X9E(board))
|
||||
return 18;
|
||||
else if (IS_TARANIS_X7(board))
|
||||
return 6;
|
||||
else if (IS_TARANIS_XLITE(board))
|
||||
return 4;
|
||||
else if (IS_HORUS_OR_TARANIS(board))
|
||||
return 8;
|
||||
else
|
||||
return 7;
|
||||
|
||||
case FactoryInstalledSwitches:
|
||||
if (IS_TARANIS_X9E(board))
|
||||
return 8;
|
||||
else
|
||||
return getCapability(board, Switches);
|
||||
|
||||
case SwitchPositions:
|
||||
if (IS_HORUS_OR_TARANIS(board))
|
||||
return getCapability(board, Switches) * 3;
|
||||
else
|
||||
return 9;
|
||||
|
||||
case NumTrims:
|
||||
if (IS_HORUS(board))
|
||||
return 6;
|
||||
else
|
||||
return 4;
|
||||
|
||||
case NumTrimSwitches:
|
||||
return getCapability(board, NumTrims) * 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QString Boards::getAxisName(int index)
|
||||
{
|
||||
const QString axes[] = {
|
||||
tr("Left Horizontal"),
|
||||
tr("Left Vertical"),
|
||||
tr("Right Vertical"),
|
||||
tr("Right Horizontal"),
|
||||
tr("Aux. 1"),
|
||||
tr("Aux. 2"),
|
||||
};
|
||||
if (index < (int)DIM(axes))
|
||||
return axes[index];
|
||||
else
|
||||
return tr("Unknown");
|
||||
}
|
||||
|
||||
const QString Boards::getAnalogInputName(Board::Type board, int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return CPN_STR_UNKNOWN_ITEM;
|
||||
|
||||
if (index < getBoardCapability(board, Board::Sticks)) {
|
||||
const QString sticks[] = {
|
||||
tr("Rud"),
|
||||
tr("Ele"),
|
||||
tr("Thr"),
|
||||
tr("Ail")
|
||||
};
|
||||
return sticks[index];
|
||||
}
|
||||
|
||||
index -= getCapability(board, Board::Sticks);
|
||||
|
||||
if (IS_9X(board) || IS_2560(board) || IS_SKY9X(board)) {
|
||||
const QString pots[] = {
|
||||
"P1",
|
||||
"P2",
|
||||
"P3"
|
||||
};
|
||||
if (index < DIM(pots))
|
||||
return pots[index];
|
||||
}
|
||||
else if (IS_TARANIS_X9E(board)) {
|
||||
const QString pots[] = {
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"S1",
|
||||
"S2",
|
||||
"LS",
|
||||
"RS"
|
||||
};
|
||||
if (index < DIM(pots))
|
||||
return pots[index];
|
||||
}
|
||||
else if (IS_TARANIS(board)) {
|
||||
const QString pots[] = {
|
||||
"S1",
|
||||
"S2",
|
||||
"S3",
|
||||
"LS",
|
||||
"RS"
|
||||
};
|
||||
if (index < DIM(pots))
|
||||
return pots[index];
|
||||
}
|
||||
else if (IS_HORUS_X12S(board)) {
|
||||
const QString pots[] = {
|
||||
"S1",
|
||||
"6P",
|
||||
"S2",
|
||||
"L1",
|
||||
"L2",
|
||||
"LS",
|
||||
"RS",
|
||||
"JSx",
|
||||
"JSy"
|
||||
};
|
||||
if (index < DIM(pots))
|
||||
return pots[index];
|
||||
}
|
||||
else if (IS_HORUS_X10(board)) {
|
||||
const QString pots[] = {
|
||||
"S1",
|
||||
"6P",
|
||||
"S2",
|
||||
"LS",
|
||||
"RS"
|
||||
};
|
||||
if (index < DIM(pots))
|
||||
return pots[index];
|
||||
}
|
||||
|
||||
return CPN_STR_UNKNOWN_ITEM;
|
||||
}
|
||||
|
||||
const bool Boards::isBoardCompatible(Type board1, Type board2)
|
||||
{
|
||||
return (getFourCC(board1) == getFourCC(board2));
|
||||
}
|
||||
|
||||
const QString Boards::getBoardName(Board::Type board)
|
||||
{
|
||||
switch (board) {
|
||||
case BOARD_STOCK:
|
||||
return "9X";
|
||||
case BOARD_M128:
|
||||
return "9X128";
|
||||
case BOARD_GRUVIN9X:
|
||||
return "Gruvin9x";
|
||||
case BOARD_MEGA2560:
|
||||
return "MEGA2560";
|
||||
case BOARD_TARANIS_X7:
|
||||
return "Taranis X7/X7S";
|
||||
case BOARD_TARANIS_XLITE:
|
||||
return "Taranis X-Lite";
|
||||
case BOARD_TARANIS_X9D:
|
||||
return "Taranis X9D";
|
||||
case BOARD_TARANIS_X9DP:
|
||||
return "Taranis X9D+";
|
||||
case BOARD_TARANIS_X9E:
|
||||
return "Taranis X9E";
|
||||
case BOARD_SKY9X:
|
||||
return "Sky9x";
|
||||
case BOARD_9XRPRO:
|
||||
return "9XR-PRO";
|
||||
case BOARD_AR9X:
|
||||
return "AR9X";
|
||||
case BOARD_X12S:
|
||||
return "Horus X12S";
|
||||
case BOARD_X10:
|
||||
return "Horus X10/X10S";
|
||||
default:
|
||||
return tr("Unknown");
|
||||
}
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _BOARDS_H_
|
||||
#define _BOARDS_H_
|
||||
|
||||
#include <QtCore>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
// TODO create a Board class with all these functions
|
||||
|
||||
namespace Board {
|
||||
|
||||
enum Type
|
||||
{
|
||||
BOARD_UNKNOWN = -1,
|
||||
BOARD_STOCK = 0,
|
||||
BOARD_M128,
|
||||
BOARD_MEGA2560,
|
||||
BOARD_GRUVIN9X,
|
||||
BOARD_SKY9X,
|
||||
BOARD_9XRPRO,
|
||||
BOARD_AR9X,
|
||||
BOARD_TARANIS_X7,
|
||||
BOARD_TARANIS_X9D,
|
||||
BOARD_TARANIS_X9DP,
|
||||
BOARD_TARANIS_X9E,
|
||||
BOARD_X12S,
|
||||
BOARD_X10,
|
||||
BOARD_TARANIS_XLITE,
|
||||
BOARD_ENUM_COUNT
|
||||
};
|
||||
|
||||
enum PotType
|
||||
{
|
||||
POT_NONE,
|
||||
POT_WITH_DETENT,
|
||||
POT_MULTIPOS_SWITCH,
|
||||
POT_WITHOUT_DETENT
|
||||
};
|
||||
|
||||
enum SliderType
|
||||
{
|
||||
SLIDER_NONE,
|
||||
SLIDER_WITH_DETENT
|
||||
};
|
||||
|
||||
enum SwitchType
|
||||
{
|
||||
SWITCH_NOT_AVAILABLE,
|
||||
SWITCH_TOGGLE,
|
||||
SWITCH_2POS,
|
||||
SWITCH_3POS
|
||||
};
|
||||
|
||||
enum StickAxes {
|
||||
STICK_AXIS_LH = 0,
|
||||
STICK_AXIS_LV,
|
||||
STICK_AXIS_RV,
|
||||
STICK_AXIS_RH,
|
||||
STICK_AXIS_COUNT
|
||||
};
|
||||
|
||||
enum TrimAxes {
|
||||
TRIM_AXIS_LH = 0,
|
||||
TRIM_AXIS_LV,
|
||||
TRIM_AXIS_RV,
|
||||
TRIM_AXIS_RH,
|
||||
TRIM_AXIS_T5,
|
||||
TRIM_AXIS_T6,
|
||||
TRIM_AXIS_COUNT
|
||||
};
|
||||
|
||||
enum TrimSwitches
|
||||
{
|
||||
TRIM_SW_LH_DEC,
|
||||
TRIM_SW_LH_INC,
|
||||
TRIM_SW_LV_DEC,
|
||||
TRIM_SW_LV_INC,
|
||||
TRIM_SW_RV_DEC,
|
||||
TRIM_SW_RV_INC,
|
||||
TRIM_SW_RH_DEC,
|
||||
TRIM_SW_RH_INC,
|
||||
TRIM_SW_T5_DEC,
|
||||
TRIM_SW_T5_INC,
|
||||
TRIM_SW_T6_DEC,
|
||||
TRIM_SW_T6_INC,
|
||||
TRIM_SW_COUNT
|
||||
};
|
||||
|
||||
enum Capability {
|
||||
Sticks,
|
||||
Pots,
|
||||
FactoryInstalledPots,
|
||||
Sliders,
|
||||
MouseAnalogs,
|
||||
MaxAnalogs,
|
||||
MultiposPots,
|
||||
MultiposPotsPositions,
|
||||
Switches,
|
||||
SwitchPositions,
|
||||
FactoryInstalledSwitches,
|
||||
NumTrims,
|
||||
NumTrimSwitches
|
||||
};
|
||||
|
||||
struct SwitchInfo
|
||||
{
|
||||
SwitchType config;
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct SwitchPosition {
|
||||
SwitchPosition(unsigned int index, unsigned int position):
|
||||
index(index),
|
||||
position(position)
|
||||
{
|
||||
}
|
||||
unsigned int index;
|
||||
unsigned int position;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class Boards
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Boards)
|
||||
|
||||
public:
|
||||
|
||||
Boards(Board::Type board)
|
||||
{
|
||||
setBoardType(board);
|
||||
}
|
||||
|
||||
void setBoardType(const Board::Type & board);
|
||||
Board::Type getBoardType() const { return m_boardType; }
|
||||
|
||||
const uint32_t getFourCC() const { return getFourCC(m_boardType); }
|
||||
const int getEEpromSize() const { return getEEpromSize(m_boardType); }
|
||||
const int getFlashSize() const { return getFlashSize(m_boardType); }
|
||||
const Board::SwitchInfo getSwitchInfo(int index) const { return getSwitchInfo(m_boardType, index); }
|
||||
const int getCapability(Board::Capability capability) const { return getCapability(m_boardType, capability); }
|
||||
const QString getAnalogInputName(int index) const { return getAnalogInputName(m_boardType, index); }
|
||||
const bool isBoardCompatible(Board::Type board2) const { return isBoardCompatible(m_boardType, board2); }
|
||||
|
||||
static uint32_t getFourCC(Board::Type board);
|
||||
static const int getEEpromSize(Board::Type board);
|
||||
static const int getFlashSize(Board::Type board);
|
||||
static const Board::SwitchInfo getSwitchInfo(Board::Type board, int index);
|
||||
static const int getCapability(Board::Type board, Board::Capability capability);
|
||||
static const QString getAxisName(int index);
|
||||
static const QString getAnalogInputName(Board::Type board, int index);
|
||||
static const bool isBoardCompatible(Board::Type board1, Board::Type board2);
|
||||
static const QString getBoardName(Board::Type board);
|
||||
|
||||
protected:
|
||||
|
||||
Board::Type m_boardType;
|
||||
};
|
||||
|
||||
// temporary aliases for transition period, use Boards class instead.
|
||||
#define getBoardCapability(b__, c__) Boards::getCapability(b__, c__)
|
||||
|
||||
#define IS_9X(board) (board==Board::BOARD_STOCK || board==Board::BOARD_M128)
|
||||
#define IS_STOCK(board) (board==Board::BOARD_STOCK)
|
||||
#define IS_M128(board) (board==Board::BOARD_M128)
|
||||
#define IS_2560(board) (board==Board::BOARD_GRUVIN9X || board==Board::BOARD_MEGA2560)
|
||||
#define IS_SKY9X(board) (board==Board::BOARD_SKY9X || board==Board::BOARD_9XRPRO || board==Board::BOARD_AR9X)
|
||||
#define IS_9XRPRO(board) (board==Board::BOARD_9XRPRO)
|
||||
#define IS_TARANIS_XLITE(board) (board==Board::BOARD_TARANIS_XLITE)
|
||||
#define IS_TARANIS_X7(board) (board==Board::BOARD_TARANIS_X7)
|
||||
#define IS_TARANIS_X9(board) (board==Board::BOARD_TARANIS_X9D || board==Board::BOARD_TARANIS_X9DP || board==Board::BOARD_TARANIS_X9E)
|
||||
#define IS_TARANIS_X9D(board) (board==Board::BOARD_TARANIS_X9D || board==Board::BOARD_TARANIS_X9DP)
|
||||
#define IS_TARANIS_PLUS(board) (board==Board::BOARD_TARANIS_X9DP || board==Board::BOARD_TARANIS_X9E)
|
||||
#define IS_TARANIS_X9E(board) (board==Board::BOARD_TARANIS_X9E)
|
||||
#define IS_TARANIS(board) (IS_TARANIS_X9(board) || IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board))
|
||||
#define IS_TARANIS_SMALL(board) (board==Board::BOARD_TARANIS_X7 || board==Board::BOARD_TARANIS_XLITE)
|
||||
#define IS_TARANIS_NOT_X9E(board) (IS_TARANIS(board) && !IS_TARANIS_X9E(board))
|
||||
#define IS_HORUS_X12S(board) (board==Board::BOARD_X12S)
|
||||
#define IS_HORUS_X10(board) (board==Board::BOARD_X10)
|
||||
#define IS_HORUS(board) (IS_HORUS_X12S(board) || IS_HORUS_X10(board))
|
||||
#define IS_HORUS_OR_TARANIS(board) (IS_HORUS(board) || IS_TARANIS(board))
|
||||
#define IS_STM32(board) (IS_TARANIS(board) || IS_HORUS(board))
|
||||
#define IS_ARM(board) (IS_STM32(board) || IS_SKY9X(board))
|
||||
#define HAS_LARGE_LCD(board) (IS_HORUS(board) || IS_TARANIS_X9(board))
|
||||
|
||||
#endif // _BOARDS_H_
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "curvereference.h"
|
||||
|
||||
#include "helpers.h" // for Helpers::getAdjustmentString()
|
||||
#include "radiodata.h" // for ModelData
|
||||
|
||||
QString CurveReference::toString(const ModelData * model, bool verbose) const
|
||||
{
|
||||
if (value == 0) {
|
||||
return "----";
|
||||
}
|
||||
|
||||
QString ret;
|
||||
unsigned idx = abs(value) - 1;
|
||||
|
||||
switch(type) {
|
||||
case CURVE_REF_DIFF:
|
||||
ret = tr("Diff(%1)").arg(Helpers::getAdjustmentString(value, model));
|
||||
break;
|
||||
|
||||
case CURVE_REF_EXPO:
|
||||
ret = tr("Expo(%1)").arg(Helpers::getAdjustmentString(value, model));
|
||||
break;
|
||||
|
||||
case CURVE_REF_FUNC:
|
||||
ret = QString("x>0" "x<0" "|x|" "f>0" "f<0" "|f|").mid(3*(value-1), 3);
|
||||
if (verbose)
|
||||
ret = tr("Function(%1)").arg(ret);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (model)
|
||||
ret = model->curves[idx].nameToString(idx);
|
||||
else
|
||||
ret = CurveData().nameToString(idx);
|
||||
if (verbose)
|
||||
ret = tr("Curve(%1)").arg(ret);
|
||||
if (value < 0)
|
||||
ret.prepend(CPN_STR_SW_INDICATOR_REV);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CURVEREFERENCE_H
|
||||
#define CURVEREFERENCE_H
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class ModelData;
|
||||
|
||||
class CurveReference {
|
||||
Q_DECLARE_TR_FUNCTIONS(CurveReference)
|
||||
|
||||
public:
|
||||
enum CurveRefType {
|
||||
CURVE_REF_DIFF,
|
||||
CURVE_REF_EXPO,
|
||||
CURVE_REF_FUNC,
|
||||
CURVE_REF_CUSTOM
|
||||
};
|
||||
|
||||
CurveReference() { clear(); }
|
||||
|
||||
CurveReference(CurveRefType type, int value):
|
||||
type(type),
|
||||
value(value)
|
||||
{
|
||||
}
|
||||
|
||||
void clear() { memset(this, 0, sizeof(CurveReference)); }
|
||||
|
||||
CurveRefType type;
|
||||
int value;
|
||||
|
||||
QString toString(const ModelData * model = NULL, bool verbose = true) const;
|
||||
};
|
||||
|
||||
#endif // CURVEREFERENCE_H
|
||||
@@ -1,264 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "customfunctiondata.h"
|
||||
|
||||
#include "eeprominterface.h"
|
||||
#include "radiodata.h"
|
||||
#include "radiodataconversionstate.h"
|
||||
|
||||
void CustomFunctionData::clear()
|
||||
{
|
||||
memset(reinterpret_cast<void *>(this), 0, sizeof(CustomFunctionData));
|
||||
if (!getCurrentFirmware()->getCapability(SafetyChannelCustomFunction)) {
|
||||
func = FuncTrainer;
|
||||
}
|
||||
}
|
||||
|
||||
bool CustomFunctionData::isEmpty() const
|
||||
{
|
||||
return (swtch.type == SWITCH_TYPE_NONE);
|
||||
}
|
||||
|
||||
QString CustomFunctionData::nameToString(int index, bool globalContext) const
|
||||
{
|
||||
return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index+1, 0, true);
|
||||
}
|
||||
|
||||
QString CustomFunctionData::funcToString(const ModelData * model) const
|
||||
{
|
||||
if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32)
|
||||
return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model));
|
||||
else if (func == FuncTrainer)
|
||||
return tr("Trainer");
|
||||
else if (func == FuncTrainerRUD)
|
||||
return tr("Trainer RUD");
|
||||
else if (func == FuncTrainerELE)
|
||||
return tr("Trainer ELE");
|
||||
else if (func == FuncTrainerTHR)
|
||||
return tr("Trainer THR");
|
||||
else if (func == FuncTrainerAIL)
|
||||
return tr("Trainer AIL");
|
||||
else if (func == FuncInstantTrim)
|
||||
return tr("Instant Trim");
|
||||
else if (func == FuncPlaySound)
|
||||
return tr("Play Sound");
|
||||
else if (func == FuncPlayHaptic)
|
||||
return tr("Haptic");
|
||||
else if (func == FuncReset)
|
||||
return tr("Reset");
|
||||
else if (func >= FuncSetTimer1 && func <= FuncSetTimer3)
|
||||
return tr("Set Timer %1").arg(func-FuncSetTimer1+1);
|
||||
else if (func == FuncVario)
|
||||
return tr("Vario");
|
||||
else if (func == FuncPlayPrompt)
|
||||
return tr("Play Track");
|
||||
else if (func == FuncPlayBoth)
|
||||
return tr("Play Both");
|
||||
else if (func == FuncPlayValue)
|
||||
return tr("Play Value");
|
||||
else if (func == FuncPlayScript)
|
||||
return tr("Play Script");
|
||||
else if (func == FuncLogs)
|
||||
return tr("SD Logs");
|
||||
else if (func == FuncVolume)
|
||||
return tr("Volume");
|
||||
else if (func == FuncBacklight)
|
||||
return tr("Backlight");
|
||||
else if (func == FuncScreenshot)
|
||||
return tr("Screenshot");
|
||||
else if (func == FuncBackgroundMusic)
|
||||
return tr("Background Music");
|
||||
else if (func == FuncBackgroundMusicPause)
|
||||
return tr("Background Music Pause");
|
||||
else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast)
|
||||
return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func-FuncAdjustGV1).toString(model));
|
||||
else if (func == FuncSetFailsafeInternalModule)
|
||||
return tr("SetFailsafe Int. Module");
|
||||
else if (func == FuncSetFailsafeExternalModule)
|
||||
return tr("SetFailsafe Ext. Module");
|
||||
else if (func == FuncRangeCheckInternalModule)
|
||||
return tr("RangeCheck Int. Module");
|
||||
else if (func == FuncRangeCheckExternalModule)
|
||||
return tr("RangeCheck Ext. Module");
|
||||
else if (func == FuncBindInternalModule)
|
||||
return tr("Bind Int. Module");
|
||||
else if (func == FuncBindExternalModule)
|
||||
return tr("Bind Ext. Module");
|
||||
else {
|
||||
return QString("???"); // Highlight unknown functions with output of question marks.(BTW should not happen that we do not know what a function is)
|
||||
}
|
||||
}
|
||||
|
||||
void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox * b, unsigned int value = 0)
|
||||
{
|
||||
int val = 0;
|
||||
Firmware * firmware = Firmware::getCurrentVariant();
|
||||
Board::Type board = firmware->getBoard();
|
||||
|
||||
b->addItem(tr("Timer1"), val++);
|
||||
b->addItem(tr("Timer2"), val++);
|
||||
if (IS_ARM(board)) {
|
||||
b->addItem( tr("Timer3"), val++);
|
||||
}
|
||||
b->addItem(tr("Flight"), val++);
|
||||
b->addItem(tr("Telemetry"), val++);
|
||||
int reCount = firmware->getCapability(RotaryEncoders);
|
||||
if (reCount == 1) {
|
||||
b->addItem(tr("Rotary Encoder"), val++);
|
||||
}
|
||||
else if (reCount == 2) {
|
||||
b->addItem(tr("REa"), val++);
|
||||
b->addItem(tr("REb"), val++);
|
||||
}
|
||||
if ((int)value < b->count()) {
|
||||
b->setCurrentIndex(value);
|
||||
}
|
||||
if (model && IS_ARM(board)) {
|
||||
for (int i=0; i<CPN_MAX_SENSORS; ++i) {
|
||||
if (model->sensorData[i].isAvailable()) {
|
||||
RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i);
|
||||
b->addItem(item.toString(model), val+i);
|
||||
if ((int)value == val+i) {
|
||||
b->setCurrentIndex(b->count()-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CustomFunctionData::populatePlaySoundParams(QStringList & qs)
|
||||
{
|
||||
qs <<"Beep 1" << "Beep 2" << "Beep 3" << "Warn1" << "Warn2" << "Cheep" << "Ratata" << "Tick" << "Siren" << "Ring" ;
|
||||
qs << "SciFi" << "Robot" << "Chirp" << "Tada" << "Crickt" << "AlmClk" ;
|
||||
}
|
||||
|
||||
void CustomFunctionData::populateHapticParams(QStringList & qs)
|
||||
{
|
||||
qs << "0" << "1" << "2" << "3";
|
||||
}
|
||||
|
||||
QString CustomFunctionData::paramToString(const ModelData * model) const
|
||||
{
|
||||
QStringList qs;
|
||||
if (func <= FuncInstantTrim) {
|
||||
return QString("%1").arg(param);
|
||||
}
|
||||
else if (func == FuncLogs) {
|
||||
return QString("%1").arg(param/10.0) + tr("s");
|
||||
}
|
||||
else if (func == FuncPlaySound) {
|
||||
CustomFunctionData::populatePlaySoundParams(qs);
|
||||
if (param>=0 && param<(int)qs.count())
|
||||
return qs.at(param);
|
||||
else
|
||||
return tr("<font color=red><b>Inconsistent parameter</b></font>");
|
||||
}
|
||||
else if (func == FuncPlayHaptic) {
|
||||
CustomFunctionData::populateHapticParams(qs);
|
||||
if (param>=0 && param<(int)qs.count())
|
||||
return qs.at(param);
|
||||
else
|
||||
return tr("<font color=red><b>Inconsistent parameter</b></font>");
|
||||
}
|
||||
else if (func == FuncReset) {
|
||||
QComboBox cb;
|
||||
CustomFunctionData::populateResetParams(model, &cb);
|
||||
int pos = cb.findData(param);
|
||||
if (pos >= 0)
|
||||
return cb.itemText(pos);
|
||||
else
|
||||
return tr("<font color=red><b>Inconsistent parameter</b></font>");
|
||||
}
|
||||
else if (func == FuncVolume || func == FuncPlayValue || func == FuncBacklight) {
|
||||
RawSource item(param);
|
||||
return item.toString(model);
|
||||
}
|
||||
else if (func == FuncPlayPrompt || func == FuncPlayBoth) {
|
||||
if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) {
|
||||
return QString("%1").arg(param);
|
||||
}
|
||||
else {
|
||||
return paramarm;
|
||||
}
|
||||
}
|
||||
else if (func >= FuncAdjustGV1 && func < FuncCount) {
|
||||
switch (adjustMode) {
|
||||
case FUNC_ADJUST_GVAR_CONSTANT:
|
||||
return tr("Value ")+QString("%1").arg(param);
|
||||
case FUNC_ADJUST_GVAR_SOURCE:
|
||||
case FUNC_ADJUST_GVAR_GVAR:
|
||||
return RawSource(param).toString();
|
||||
case FUNC_ADJUST_GVAR_INCDEC:
|
||||
float val;
|
||||
QString unit;
|
||||
if (IS_ARM(getCurrentBoard())) {
|
||||
val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet();
|
||||
unit = model->gvarData[func - FuncAdjustGV1].unitToString();
|
||||
}
|
||||
else {
|
||||
val = param;
|
||||
unit = "";
|
||||
}
|
||||
return QString("Increment: %1%2").arg(val).arg(unit);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
QString CustomFunctionData::repeatToString() const
|
||||
{
|
||||
if (repeatParam == -1) {
|
||||
return tr("played once, not during startup");
|
||||
}
|
||||
else if (repeatParam == 0) {
|
||||
return "";
|
||||
}
|
||||
else {
|
||||
unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10;
|
||||
return tr("repeat(%1s)").arg(step*repeatParam);
|
||||
}
|
||||
}
|
||||
|
||||
QString CustomFunctionData::enabledToString() const
|
||||
{
|
||||
if ((func >= FuncOverrideCH1 && func <= FuncOverrideCH32) ||
|
||||
(func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) ||
|
||||
(func == FuncReset) ||
|
||||
(func >= FuncSetTimer1 && func <= FuncSetTimer2) ||
|
||||
(func == FuncVolume) ||
|
||||
(func == FuncBacklight) ||
|
||||
(func <= FuncInstantTrim)) {
|
||||
if (!enabled) {
|
||||
return tr("DISABLED");
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void CustomFunctionData::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
cstate.setComponent(tr("CFN"), 8);
|
||||
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
|
||||
swtch.convert(cstate);
|
||||
if (func == FuncVolume || func == FuncBacklight || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) {
|
||||
param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue();
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CUSTOMFUNCTIONDATA_H
|
||||
#define CUSTOMFUNCTIONDATA_H
|
||||
|
||||
#include "boards.h"
|
||||
#include "constants.h"
|
||||
#include "rawswitch.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QComboBox>
|
||||
|
||||
class Firmware;
|
||||
class ModelData;
|
||||
class GeneralSettings;
|
||||
class RadioDataConversionState;
|
||||
|
||||
enum AssignFunc {
|
||||
FuncOverrideCH1 = 0,
|
||||
FuncOverrideCH32 = FuncOverrideCH1+CPN_MAX_CHNOUT-1,
|
||||
FuncTrainer,
|
||||
FuncTrainerRUD,
|
||||
FuncTrainerELE,
|
||||
FuncTrainerTHR,
|
||||
FuncTrainerAIL,
|
||||
FuncInstantTrim,
|
||||
FuncPlaySound,
|
||||
FuncPlayHaptic,
|
||||
FuncReset,
|
||||
FuncSetTimer1,
|
||||
FuncSetTimer2,
|
||||
FuncSetTimer3,
|
||||
FuncVario,
|
||||
FuncPlayPrompt,
|
||||
FuncPlayBoth,
|
||||
FuncPlayValue,
|
||||
FuncPlayScript,
|
||||
FuncLogs,
|
||||
FuncVolume,
|
||||
FuncBacklight,
|
||||
FuncScreenshot,
|
||||
FuncBackgroundMusic,
|
||||
FuncBackgroundMusicPause,
|
||||
FuncAdjustGV1,
|
||||
FuncAdjustGVLast = FuncAdjustGV1+CPN_MAX_GVARS-1,
|
||||
FuncSetFailsafeInternalModule,
|
||||
FuncSetFailsafeExternalModule,
|
||||
FuncRangeCheckInternalModule,
|
||||
FuncRangeCheckExternalModule,
|
||||
FuncBindInternalModule,
|
||||
FuncBindExternalModule,
|
||||
FuncCount,
|
||||
FuncReserve = -1
|
||||
};
|
||||
|
||||
enum GVarAdjustModes
|
||||
{
|
||||
FUNC_ADJUST_GVAR_CONSTANT,
|
||||
FUNC_ADJUST_GVAR_SOURCE,
|
||||
FUNC_ADJUST_GVAR_GVAR,
|
||||
FUNC_ADJUST_GVAR_INCDEC
|
||||
};
|
||||
|
||||
class CustomFunctionData {
|
||||
Q_DECLARE_TR_FUNCTIONS(CustomFunctionData)
|
||||
|
||||
public:
|
||||
CustomFunctionData(AssignFunc func=FuncOverrideCH1) { clear(); this->func = func; }
|
||||
RawSwitch swtch;
|
||||
AssignFunc func;
|
||||
int param;
|
||||
char paramarm[10];
|
||||
unsigned int enabled; // TODO perhaps not any more the right name
|
||||
unsigned int adjustMode;
|
||||
int repeatParam;
|
||||
|
||||
void clear();
|
||||
bool isEmpty() const;
|
||||
QString nameToString(int index, bool globalContext = false) const;
|
||||
QString funcToString(const ModelData * model = NULL) const;
|
||||
QString paramToString(const ModelData * model) const;
|
||||
QString repeatToString() const;
|
||||
QString enabledToString() const;
|
||||
|
||||
static void populateResetParams(const ModelData * model, QComboBox * b, unsigned int value);
|
||||
static void populatePlaySoundParams(QStringList & qs);
|
||||
static void populateHapticParams(QStringList & qs);
|
||||
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // CUSTOMFUNCTIONDATA_H
|
||||
@@ -1,805 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _EEPROMIMPORTEXPORT_H_
|
||||
#define _EEPROMIMPORTEXPORT_H_
|
||||
|
||||
#include "customdebug.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QBitArray>
|
||||
|
||||
class DataField {
|
||||
Q_DECLARE_TR_FUNCTIONS(DataField)
|
||||
|
||||
public:
|
||||
DataField(DataField * parent, const char * name=""):
|
||||
parent(parent),
|
||||
name(name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DataField()
|
||||
{
|
||||
}
|
||||
|
||||
virtual const QString & getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
virtual unsigned int size() = 0;
|
||||
virtual void ExportBits(QBitArray & output) = 0;
|
||||
virtual void ImportBits(const QBitArray & input) = 0;
|
||||
|
||||
QBitArray bytesToBits(QByteArray bytes)
|
||||
{
|
||||
QBitArray bits(bytes.count()*8);
|
||||
// Convert from QByteArray to QBitArray
|
||||
for (int i=0; i<bytes.count(); ++i)
|
||||
for (int b=0; b<8; ++b)
|
||||
bits.setBit(i*8+b, bytes.at(i)&(1<<b));
|
||||
return bits;
|
||||
}
|
||||
|
||||
QByteArray bitsToBytes(QBitArray bits, int offset=0)
|
||||
{
|
||||
QByteArray bytes;
|
||||
bytes.resize((offset+bits.count()+7)/8);
|
||||
bytes.fill(0);
|
||||
// Convert from QBitArray to QByteArray
|
||||
for (int b=0; b<bits.count(); ++b)
|
||||
bytes[(b+offset)/8] = ( bytes.at((b+offset)/8) | ((bits[b]?1:0)<<((b+offset)%8)));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int Export(QByteArray & output)
|
||||
{
|
||||
QBitArray result;
|
||||
ExportBits(result);
|
||||
output = bitsToBytes(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Import(const QByteArray & input)
|
||||
{
|
||||
QBitArray bits = bytesToBits(input);
|
||||
if ((unsigned int)bits.size() < size()) {
|
||||
qDebug() << QString("Error importing %1: size to small %2/%3").arg(getName()).arg(input.size()).arg(size());
|
||||
return -1;
|
||||
}
|
||||
ImportBits(bits);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int Dump(int level=0, int offset=0)
|
||||
{
|
||||
QBitArray bits;
|
||||
ExportBits(bits);
|
||||
QByteArray bytes = bitsToBytes(bits);
|
||||
int result = (offset+bits.count()) % 8;
|
||||
for (int i=0; i<level; i++) printf(" ");
|
||||
if (bits.count() % 8 == 0)
|
||||
printf("%s (%dbytes) ", getName().toLatin1().constData(), bytes.count());
|
||||
else
|
||||
printf("%s (%dbits) ", getName().toLatin1().constData(), bits.count());
|
||||
for (int i=0; i<bytes.count(); i++) {
|
||||
unsigned char c = bytes[i];
|
||||
if ((i==0 && offset) || (i==bytes.count()-1 && result!=0))
|
||||
printf("(%02x) ", c);
|
||||
else
|
||||
printf("%02x ", c);
|
||||
}
|
||||
printf("\n"); fflush(stdout);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void setError(const QString & error)
|
||||
{
|
||||
if (parent) {
|
||||
parent->setError(error);
|
||||
}
|
||||
else {
|
||||
qWarning() << qPrintable(error);
|
||||
}
|
||||
}
|
||||
|
||||
DataField * parent;
|
||||
QString name;
|
||||
};
|
||||
|
||||
class ProxyField: public DataField {
|
||||
public:
|
||||
explicit ProxyField(DataField * parent):
|
||||
DataField(parent, "Proxy")
|
||||
{
|
||||
}
|
||||
|
||||
virtual DataField * getField() = 0;
|
||||
|
||||
};
|
||||
|
||||
template<class container, int N>
|
||||
class BaseUnsignedField: public DataField {
|
||||
public:
|
||||
BaseUnsignedField(DataField * parent, container & field):
|
||||
DataField(parent, "Unsigned"),
|
||||
field(field),
|
||||
min(0),
|
||||
max(std::numeric_limits<container>::max())
|
||||
{
|
||||
}
|
||||
|
||||
BaseUnsignedField(DataField * parent, container & field, const char * name):
|
||||
DataField(parent, name),
|
||||
field(field),
|
||||
min(0),
|
||||
max(std::numeric_limits<container>::max())
|
||||
{
|
||||
}
|
||||
|
||||
BaseUnsignedField(DataField * parent, container & field, container min, container max, const char * name="Unsigned"):
|
||||
DataField(parent, name),
|
||||
field(field),
|
||||
min(min),
|
||||
max(max)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ExportBits(QBitArray & output)
|
||||
{
|
||||
container value = field;
|
||||
if (value > max) value = max;
|
||||
if (value < min) value = min;
|
||||
|
||||
output.resize(N);
|
||||
for (int i=0; i<N; i++) {
|
||||
if (value & ((container)1<<i)) {
|
||||
output.setBit(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ImportBits(const QBitArray & input)
|
||||
{
|
||||
field = 0;
|
||||
for (int i=0; i<N; i++) {
|
||||
if (input[i])
|
||||
field |= ((container)1<<i);
|
||||
}
|
||||
qCDebug(eepromImport) << QString("\timported %1<%2>: 0x%3(%4)").arg(name).arg(N).arg(field, 0, 16).arg(field);
|
||||
}
|
||||
|
||||
virtual unsigned int size()
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
protected:
|
||||
container & field;
|
||||
container min;
|
||||
container max;
|
||||
|
||||
private:
|
||||
BaseUnsignedField();
|
||||
};
|
||||
|
||||
template <int N>
|
||||
class UnsignedField : public BaseUnsignedField<unsigned int, N>
|
||||
{
|
||||
public:
|
||||
UnsignedField(DataField * parent, unsigned int & field):
|
||||
BaseUnsignedField<unsigned int, N>(parent, field)
|
||||
{
|
||||
}
|
||||
|
||||
UnsignedField(DataField * parent, unsigned int & field, const char *name):
|
||||
BaseUnsignedField<unsigned int, N>(parent, field, name)
|
||||
{
|
||||
}
|
||||
|
||||
UnsignedField(DataField * parent, unsigned int & field, unsigned int min, unsigned int max, const char *name="Unsigned"):
|
||||
BaseUnsignedField<unsigned int, N>(parent, field, min, max, name)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<int N>
|
||||
class BoolField: public DataField {
|
||||
public:
|
||||
explicit BoolField(DataField * parent, bool & field):
|
||||
DataField(parent, "Bool"),
|
||||
field(field)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ExportBits(QBitArray & output)
|
||||
{
|
||||
output.resize(N);
|
||||
if (field) {
|
||||
output.setBit(0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ImportBits(const QBitArray & input)
|
||||
{
|
||||
field = input[0] ? true : false;
|
||||
qCDebug(eepromImport) << QString("\timported %1<%2>: 0x%3(%4)").arg(name).arg(N).arg(field, 0, 16).arg(field);
|
||||
}
|
||||
|
||||
virtual unsigned int size()
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool & field;
|
||||
|
||||
private:
|
||||
BoolField();
|
||||
};
|
||||
|
||||
template<int N>
|
||||
class SignedField: public DataField {
|
||||
public:
|
||||
SignedField(DataField * parent, int & field):
|
||||
DataField(parent, "Signed"),
|
||||
field(field),
|
||||
min(INT_MIN),
|
||||
max(INT_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
SignedField(DataField * parent, int & field, const char *name):
|
||||
DataField(parent, name),
|
||||
field(field),
|
||||
min(INT_MIN),
|
||||
max(INT_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
SignedField(DataField * parent, int & field, int min, int max, const char *name="Signed"):
|
||||
DataField(parent, name),
|
||||
field(field),
|
||||
min(min),
|
||||
max(max)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ExportBits(QBitArray & output)
|
||||
{
|
||||
int value = field;
|
||||
if (value > max) value = max;
|
||||
if (value < min) value = min;
|
||||
|
||||
output.resize(N);
|
||||
for (int i=0; i<N; i++) {
|
||||
if (((unsigned int)value) & (1<<i))
|
||||
output.setBit(i);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ImportBits(const QBitArray & input)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
for (int i=0; i<N; i++) {
|
||||
if (input[i])
|
||||
value |= (1<<i);
|
||||
}
|
||||
|
||||
if (input[N-1]) {
|
||||
for (unsigned int i=N; i<8*sizeof(int); i++) {
|
||||
value |= (1<<i);
|
||||
}
|
||||
}
|
||||
|
||||
field = (int)value;
|
||||
qCDebug(eepromImport) << QString("\timported %1<%2>: 0x%3(%4)").arg(name).arg(N).arg(field, 0, 16).arg(field);
|
||||
}
|
||||
|
||||
virtual unsigned int size()
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
protected:
|
||||
int & field;
|
||||
int min;
|
||||
int max;
|
||||
};
|
||||
|
||||
template<int N>
|
||||
class SpareBitsField: public UnsignedField<N> {
|
||||
public:
|
||||
SpareBitsField(DataField * parent):
|
||||
UnsignedField<N>(parent, spare, 0, 0, "Spare"),
|
||||
spare(0)
|
||||
{
|
||||
}
|
||||
protected:
|
||||
unsigned int spare;
|
||||
};
|
||||
|
||||
template<int N>
|
||||
class CharField: public DataField {
|
||||
public:
|
||||
CharField(DataField * parent, char * field, bool truncate=true, const char * name="Char"):
|
||||
DataField(parent, name),
|
||||
field(field),
|
||||
truncate(truncate)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ExportBits(QBitArray & output)
|
||||
{
|
||||
output.resize(N*8);
|
||||
int b = 0;
|
||||
int len = truncate ? strlen(field) : N;
|
||||
for (int i=0; i<N; i++) {
|
||||
int idx = (i>=len ? 0 : field[i]);
|
||||
for (int j=0; j<8; j++, b++) {
|
||||
if (idx & (1<<j))
|
||||
output.setBit(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ImportBits(const QBitArray & input)
|
||||
{
|
||||
unsigned int b = 0;
|
||||
for (int i=0; i<N; i++) {
|
||||
int8_t idx = 0;
|
||||
for (int j=0; j<8; j++) {
|
||||
if (input[b++])
|
||||
idx |= (1<<j);
|
||||
}
|
||||
field[i] = idx;
|
||||
}
|
||||
qCDebug(eepromImport) << QString("\timported %1<%2>: '%3'").arg(name).arg(N).arg(field);
|
||||
}
|
||||
|
||||
virtual unsigned int size()
|
||||
{
|
||||
return 8*N;
|
||||
}
|
||||
|
||||
protected:
|
||||
char * field;
|
||||
bool truncate;
|
||||
};
|
||||
|
||||
static const char specialCharsTab[] = "_-.,";
|
||||
static inline int8_t char2idx(char c)
|
||||
{
|
||||
if (c==' ') return 0;
|
||||
if (c>='A' && c<='Z') return 1+c-'A';
|
||||
if (c>='a' && c<='z') return -1-c+'a';
|
||||
if (c>='0' && c<='9') return 27+c-'0';
|
||||
for (int8_t i=0;;i++) {
|
||||
char cc = specialCharsTab[i];
|
||||
if (cc==0) return 0;
|
||||
if (cc==c) return 37+i;
|
||||
}
|
||||
}
|
||||
|
||||
#define ZCHAR_MAX 40
|
||||
static inline char idx2char(int8_t idx)
|
||||
{
|
||||
if (idx == 0) return ' ';
|
||||
if (idx < 0) {
|
||||
if (idx > -27) return 'a' - idx - 1;
|
||||
idx = -idx;
|
||||
}
|
||||
if (idx < 27) return 'A' + idx - 1;
|
||||
if (idx < 37) return '0' + idx - 27;
|
||||
if (idx <= ZCHAR_MAX) return specialCharsTab[idx-37];
|
||||
return ' ';
|
||||
}
|
||||
|
||||
template<int N>
|
||||
class ZCharField: public DataField {
|
||||
public:
|
||||
ZCharField(DataField * parent, char * field, const char * name = "ZChar"):
|
||||
DataField(parent, name),
|
||||
field(field)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ExportBits(QBitArray & output)
|
||||
{
|
||||
output.resize(N*8);
|
||||
int b = 0;
|
||||
int len = strlen(field);
|
||||
for (int i=0; i<N; i++) {
|
||||
int idx = i>=len ? 0 : char2idx(field[i]);
|
||||
for (int j=0; j<8; j++, b++) {
|
||||
if (idx & (1<<j))
|
||||
output.setBit(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ImportBits(const QBitArray & input)
|
||||
{
|
||||
unsigned int b = 0;
|
||||
for (int i=0; i<N; i++) {
|
||||
int8_t idx = 0;
|
||||
for (int j=0; j<8; j++) {
|
||||
if (input[b++])
|
||||
idx |= (1<<j);
|
||||
}
|
||||
field[i] = idx2char(idx);
|
||||
}
|
||||
|
||||
field[N] = '\0';
|
||||
for (int i=N-1; i>=0; i--) {
|
||||
if (field[i] == ' ')
|
||||
field[i] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
qCDebug(eepromImport) << QString("\timported %1<%2>: '%3'").arg(name).arg(N).arg(field);
|
||||
}
|
||||
|
||||
virtual unsigned int size()
|
||||
{
|
||||
return 8*N;
|
||||
}
|
||||
|
||||
protected:
|
||||
char * field;
|
||||
};
|
||||
|
||||
class StructField: public DataField {
|
||||
public:
|
||||
StructField(DataField * parent, const char * name="Struct"):
|
||||
DataField(parent, name)
|
||||
{
|
||||
}
|
||||
|
||||
~StructField() {
|
||||
foreach(DataField * field, fields) {
|
||||
delete field;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Append(DataField * field) {
|
||||
//qCDebug(eepromImport) << QString("StructField(%1) appending field: %2").arg(name).arg(field->getName());
|
||||
fields.append(field);
|
||||
}
|
||||
|
||||
virtual void ExportBits(QBitArray & output)
|
||||
{
|
||||
int offset = 0;
|
||||
output.resize(size());
|
||||
foreach(DataField *field, fields) {
|
||||
QBitArray bits;
|
||||
field->ExportBits(bits);
|
||||
for (int i=0; i<bits.size(); i++)
|
||||
output[offset++] = bits[i];
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ImportBits(const QBitArray & input)
|
||||
{
|
||||
qCDebug(eepromImport) << QString("\timporting %1[%2]:").arg(name).arg(fields.size());
|
||||
int offset = 0;
|
||||
foreach(DataField *field, fields) {
|
||||
unsigned int size = field->size();
|
||||
QBitArray bits(size);
|
||||
for (unsigned int i=0; i<size; i++) {
|
||||
bits[i] = input[offset++];
|
||||
}
|
||||
field->ImportBits(bits);
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned int size()
|
||||
{
|
||||
unsigned int result = 0;
|
||||
foreach(DataField *field, fields) {
|
||||
result += field->size();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual int Dump(int level=0, int offset=0)
|
||||
{
|
||||
for (int i=0; i<level; i++) printf(" ");
|
||||
printf("%s (%d bytes)\n", getName().toLatin1().constData(), size()/8);
|
||||
foreach(DataField *field, fields) {
|
||||
offset = field->Dump(level+1, offset);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
protected:
|
||||
QList<DataField *> fields;
|
||||
};
|
||||
|
||||
class TransformedField: public DataField {
|
||||
public:
|
||||
TransformedField(DataField * parent, DataField & field):
|
||||
DataField(parent),
|
||||
field(field)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~TransformedField()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ExportBits(QBitArray & output)
|
||||
{
|
||||
beforeExport();
|
||||
field.ExportBits(output);
|
||||
}
|
||||
|
||||
virtual void ImportBits(const QBitArray & input)
|
||||
{
|
||||
qCDebug(eepromImport) << QString("\timporting TransformedField %1:").arg(field.getName());
|
||||
field.ImportBits(input);
|
||||
afterImport();
|
||||
}
|
||||
|
||||
|
||||
virtual const QString & getName()
|
||||
{
|
||||
return field.getName();
|
||||
}
|
||||
|
||||
virtual unsigned int size()
|
||||
{
|
||||
return field.size();
|
||||
}
|
||||
|
||||
virtual void beforeExport() = 0;
|
||||
|
||||
virtual void afterImport() = 0;
|
||||
|
||||
virtual int Dump(int level=0, int offset=0)
|
||||
{
|
||||
beforeExport();
|
||||
return field.Dump(level, offset);
|
||||
}
|
||||
|
||||
protected:
|
||||
DataField & field;
|
||||
};
|
||||
|
||||
class ConversionTable {
|
||||
|
||||
public:
|
||||
bool exportValue(const int before, int &after)
|
||||
{
|
||||
after = 0;
|
||||
|
||||
for (std::list<ConversionTuple>::iterator it=exportTable.begin(); it!=exportTable.end(); it++) {
|
||||
ConversionTuple & tuple = *it;
|
||||
if (before == tuple.a) {
|
||||
after = tuple.b;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool importValue(const int before, int &after)
|
||||
{
|
||||
after = 0;
|
||||
|
||||
for (std::list<ConversionTuple>::iterator it=importTable.begin(); it!=importTable.end(); it++) {
|
||||
ConversionTuple & tuple = *it;
|
||||
if (before == tuple.b) {
|
||||
after = tuple.a;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
class ConversionTuple {
|
||||
public:
|
||||
ConversionTuple(const int a, const int b):
|
||||
a(a),
|
||||
b(b)
|
||||
{
|
||||
}
|
||||
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
void addConversion(const int a, const int b)
|
||||
{
|
||||
ConversionTuple conversion(a, b);
|
||||
importTable.push_back(conversion);
|
||||
exportTable.push_back(conversion);
|
||||
}
|
||||
|
||||
void addImportConversion(const int a, const int b)
|
||||
{
|
||||
importTable.push_back(ConversionTuple(a, b));
|
||||
}
|
||||
|
||||
void addExportConversion(const int a, const int b)
|
||||
{
|
||||
exportTable.push_back(ConversionTuple(a, b));
|
||||
}
|
||||
|
||||
std::list<ConversionTuple> importTable;
|
||||
std::list<ConversionTuple> exportTable;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class ConversionField: public TransformedField {
|
||||
public:
|
||||
ConversionField(DataField * parent, int & field, ConversionTable *table, const char *name, const QString & error = ""):
|
||||
TransformedField(parent, internalField),
|
||||
internalField(this, _field, name),
|
||||
field(field),
|
||||
_field(0),
|
||||
table(table),
|
||||
shift(0),
|
||||
scale(1),
|
||||
min(INT_MIN),
|
||||
max(INT_MAX),
|
||||
exportFunc(NULL),
|
||||
importFunc(NULL),
|
||||
error(error)
|
||||
{
|
||||
}
|
||||
|
||||
ConversionField(DataField * parent, unsigned int & field, ConversionTable *table, const char *name, const QString & error = ""):
|
||||
TransformedField(parent, internalField),
|
||||
internalField(this, (unsigned int &)_field, name),
|
||||
field((int &)field),
|
||||
_field(0),
|
||||
table(table),
|
||||
shift(0),
|
||||
scale(0),
|
||||
min(INT_MIN),
|
||||
max(INT_MAX),
|
||||
exportFunc(NULL),
|
||||
importFunc(NULL),
|
||||
error(error)
|
||||
{
|
||||
}
|
||||
|
||||
ConversionField(DataField * parent, int & field, int (*exportFunc)(int), int (*importFunc)(int)):
|
||||
TransformedField(parent, internalField),
|
||||
internalField(this, _field),
|
||||
field(field),
|
||||
_field(0),
|
||||
table(NULL),
|
||||
shift(0),
|
||||
scale(0),
|
||||
min(INT_MIN),
|
||||
max(INT_MAX),
|
||||
exportFunc(exportFunc),
|
||||
importFunc(importFunc),
|
||||
error("")
|
||||
{
|
||||
}
|
||||
|
||||
ConversionField(DataField * parent, int & field, int shift, int scale=0, int min=INT_MIN, int max=INT_MAX, const char *name = "Signed shifted"):
|
||||
TransformedField(parent, internalField),
|
||||
internalField(this, _field, name),
|
||||
field(field),
|
||||
_field(0),
|
||||
table(NULL),
|
||||
shift(shift),
|
||||
scale(scale),
|
||||
min(min),
|
||||
max(max),
|
||||
exportFunc(NULL),
|
||||
importFunc(NULL),
|
||||
error("")
|
||||
{
|
||||
}
|
||||
|
||||
ConversionField(DataField * parent, unsigned int & field, int shift, int scale=0):
|
||||
TransformedField(parent, internalField),
|
||||
internalField(this, (unsigned int &)_field),
|
||||
field((int &)field),
|
||||
_field(0),
|
||||
table(NULL),
|
||||
shift(shift),
|
||||
scale(scale),
|
||||
min(INT_MIN),
|
||||
max(INT_MAX),
|
||||
exportFunc(NULL),
|
||||
importFunc(NULL),
|
||||
error("")
|
||||
{
|
||||
}
|
||||
|
||||
virtual void beforeExport()
|
||||
{
|
||||
_field = field;
|
||||
|
||||
if (scale) {
|
||||
_field /= scale;
|
||||
}
|
||||
|
||||
if (table) {
|
||||
if (!table->exportValue(_field, _field)) {
|
||||
setError(error.isEmpty() ? DataField::tr("Conversion error on field %1").arg(name) : error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (shift) {
|
||||
if (_field < min)
|
||||
_field = min + shift;
|
||||
else if (_field > max)
|
||||
_field = max + shift;
|
||||
else
|
||||
_field += shift;
|
||||
}
|
||||
|
||||
if (exportFunc) {
|
||||
_field = exportFunc(_field);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void afterImport()
|
||||
{
|
||||
field = _field;
|
||||
|
||||
if (table) {
|
||||
if (table->importValue(field, field))
|
||||
return;
|
||||
}
|
||||
|
||||
if (shift) {
|
||||
field -= shift;
|
||||
}
|
||||
|
||||
if (importFunc) {
|
||||
field = importFunc(field);
|
||||
}
|
||||
|
||||
if (scale) {
|
||||
field *= scale;
|
||||
}
|
||||
qCDebug(eepromImport) << QString("\timported ConversionField<%1>:").arg(internalField.getName()) << QString(" before: %1, after: %2").arg(_field).arg(field);
|
||||
}
|
||||
|
||||
protected:
|
||||
T internalField;
|
||||
int & field;
|
||||
int _field;
|
||||
ConversionTable * table;
|
||||
int shift;
|
||||
int scale;
|
||||
int min;
|
||||
int max;
|
||||
int (*exportFunc)(int);
|
||||
int (*importFunc)(int);
|
||||
const QString error;
|
||||
};
|
||||
|
||||
#endif // _EEPROMIMPORTEXPORT_H_
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "eeprominterface.h"
|
||||
#include "firmwares/opentx/opentxeeprom.h"
|
||||
#include "firmwareinterface.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QMessageBox>
|
||||
#include <bitset>
|
||||
|
||||
float ValToTim(int value)
|
||||
{
|
||||
return ((value < -109 ? 129+value : (value < 7 ? (113+value)*5 : (53+value)*10))/10.0);
|
||||
}
|
||||
|
||||
int TimToVal(float value)
|
||||
{
|
||||
int temp;
|
||||
if (value>60) {
|
||||
temp=136+round((value-60));
|
||||
}
|
||||
else if (value>2) {
|
||||
temp=20+round((value-2.0)*2.0);
|
||||
}
|
||||
else {
|
||||
temp=round(value*10.0);
|
||||
}
|
||||
return (temp-129);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* EEpromInterface globals
|
||||
*/
|
||||
|
||||
// TODO: No globals
|
||||
|
||||
QList<EEPROMInterface *> eepromInterfaces;
|
||||
|
||||
void unregisterEEpromInterfaces()
|
||||
{
|
||||
foreach(EEPROMInterface * intf, eepromInterfaces) {
|
||||
// qDebug() << "UnregisterEepromInterfaces(): deleting " << QString::number( reinterpret_cast<uint64_t>(intf), 16 );
|
||||
delete intf;
|
||||
}
|
||||
OpenTxEepromCleanup();
|
||||
}
|
||||
|
||||
#if 0 // TODO: remove if unused, currently commented out in mdiChild.cpp
|
||||
// TODO: No GUI here, e.g. return string list instead
|
||||
void EEPROMInterface::showEepromErrors(QWidget *parent, const QString &title, const QString &mainMessage, unsigned long errorsFound)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors((unsigned long long)errorsFound);
|
||||
QStringList errorsList;
|
||||
|
||||
errorsList << tr("Possible causes for this:");
|
||||
|
||||
if (errors.test(UNSUPPORTED_NEWER_VERSION)) { errorsList << tr("- Eeprom is from a newer version of OpenTX"); }
|
||||
if (errors.test(NOT_OPENTX)) { errorsList << tr("- Eeprom is not from OpenTX"); }
|
||||
if (errors.test(NOT_TH9X)) { errorsList << tr("- Eeprom is not from Th9X"); }
|
||||
if (errors.test(NOT_GRUVIN9X)) { errorsList << tr("- Eeprom is not from Gruvin9X"); }
|
||||
if (errors.test(NOT_ERSKY9X)) { errorsList << tr("- Eeprom is not from ErSky9X"); }
|
||||
if (errors.test(NOT_ER9X)) { errorsList << tr("- Eeprom is not from Er9X"); }
|
||||
if (errors.test(WRONG_SIZE)) { errorsList << tr("- Eeprom size is invalid"); }
|
||||
if (errors.test(WRONG_FILE_SYSTEM)) { errorsList << tr("- Eeprom file system is invalid"); }
|
||||
if (errors.test(UNKNOWN_BOARD)) { errorsList << tr("- Eeprom is from a unknown board"); }
|
||||
if (errors.test(WRONG_BOARD)) { errorsList << tr("- Eeprom is from the wrong board"); }
|
||||
if (errors.test(BACKUP_NOT_SUPPORTED)) { errorsList << tr("- Eeprom backup not supported"); }
|
||||
|
||||
if (errors.test(UNKNOWN_ERROR)) { errorsList << tr("- Something that couldn't be guessed, sorry"); }
|
||||
|
||||
if (errors.test(HAS_WARNINGS)) {
|
||||
errorsList << tr("Warning:");
|
||||
if (errors.test(WARNING_WRONG_FIRMWARE)) { errorsList << tr("- Your radio probably uses a wrong firmware,\n eeprom size is 4096 but only the first 2048 are used"); }
|
||||
}
|
||||
|
||||
QMessageBox msgBox(parent);
|
||||
msgBox.setWindowTitle(title);
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setText(mainMessage);
|
||||
msgBox.setInformativeText(errorsList.join("\n"));
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.exec();
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: No GUI here, e.g. return string list instead
|
||||
void EEPROMInterface::showEepromWarnings(QWidget *parent, const QString &title, unsigned long errorsFound)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors((unsigned long long)errorsFound);
|
||||
QStringList warningsList;
|
||||
if (errors.test(WARNING_WRONG_FIRMWARE)) { warningsList << tr("- Your radio probably uses a wrong firmware,\n eeprom size is 4096 but only the first 2048 are used"); }
|
||||
if (errors.test(OLD_VERSION)) { warningsList << tr("- Your eeprom is from an old version of OpenTX, upgrading!\n To keep your original file as a backup, please choose File -> Save As specifying a different name."); }
|
||||
|
||||
QMessageBox msgBox(parent);
|
||||
msgBox.setWindowTitle(title);
|
||||
msgBox.setIcon(QMessageBox::Warning);
|
||||
msgBox.setText(tr("Warnings!"));
|
||||
msgBox.setInformativeText(warningsList.join("\n"));
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Firmware
|
||||
*/
|
||||
|
||||
// static
|
||||
QVector<Firmware *> Firmware::registeredFirmwares;
|
||||
Firmware * Firmware::defaultVariant = NULL;
|
||||
Firmware * Firmware::currentVariant = NULL;
|
||||
|
||||
// static
|
||||
Firmware * Firmware::getFirmwareForId(const QString & id)
|
||||
{
|
||||
foreach(Firmware * firmware, registeredFirmwares) {
|
||||
Firmware * result = firmware->getFirmwareVariant(id);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultVariant;
|
||||
}
|
||||
|
||||
unsigned int Firmware::getVariantNumber()
|
||||
{
|
||||
unsigned int result = 0;
|
||||
const Firmware * base = getFirmwareBase();
|
||||
QStringList options = id.mid(base->getId().length()+1).split("-", QString::SkipEmptyParts);
|
||||
foreach(QString option, options) {
|
||||
foreach(OptionsGroup group, base->opts) {
|
||||
foreach(Option opt, group) {
|
||||
if (opt.name == option) {
|
||||
result += opt.variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Firmware::addLanguage(const char * lang)
|
||||
{
|
||||
languages.push_back(lang);
|
||||
}
|
||||
|
||||
//void Firmware::addTTSLanguage(const char * lang)
|
||||
//{
|
||||
// ttslanguages.push_back(lang);
|
||||
//}
|
||||
|
||||
void Firmware::addOption(const char * option, const QString & tooltip, unsigned variant)
|
||||
{
|
||||
addOption(Option(option, tooltip, variant));
|
||||
}
|
||||
|
||||
void Firmware::addOption(const Option & option)
|
||||
{
|
||||
addOptionsGroup({option});
|
||||
}
|
||||
|
||||
void Firmware::addOptionsGroup(const OptionsGroup & options)
|
||||
{
|
||||
this->opts.append(options);
|
||||
}
|
||||
@@ -1,424 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _EEPROMINTERFACE_H_
|
||||
#define _EEPROMINTERFACE_H_
|
||||
|
||||
#include "boards.h"
|
||||
#include "macros.h"
|
||||
#include "radiodata.h"
|
||||
#include "../../radio/src/definitions.h"
|
||||
#include "simulatorinterface.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QStringList>
|
||||
#include <QList>
|
||||
#include <QDebug>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
const uint8_t modn12x3[4][4]= {
|
||||
{1, 2, 3, 4},
|
||||
{1, 3, 2, 4},
|
||||
{4, 2, 3, 1},
|
||||
{4, 3, 2, 1} };
|
||||
|
||||
enum Capability {
|
||||
Models,
|
||||
ModelName,
|
||||
FlightModes,
|
||||
FlightModesName,
|
||||
FlightModesHaveFades,
|
||||
Imperial,
|
||||
Mixes,
|
||||
Timers,
|
||||
TimersName,
|
||||
VoicesAsNumbers,
|
||||
VoicesMaxLength,
|
||||
MultiLangVoice,
|
||||
ModelImage,
|
||||
CustomFunctions,
|
||||
SafetyChannelCustomFunction,
|
||||
LogicalSwitches,
|
||||
CustomAndSwitches,
|
||||
HasNegAndSwitches,
|
||||
LogicalSwitchesExt,
|
||||
RotaryEncoders,
|
||||
Outputs,
|
||||
ChannelsName,
|
||||
ExtraInputs,
|
||||
TrimsRange,
|
||||
ExtendedTrimsRange,
|
||||
NumCurves,
|
||||
NumCurvePoints,
|
||||
OffsetWeight,
|
||||
Simulation,
|
||||
SoundMod,
|
||||
SoundPitch,
|
||||
MaxVolume,
|
||||
MaxContrast,
|
||||
MinContrast,
|
||||
Haptic,
|
||||
HasBeeper,
|
||||
ModelTrainerEnable,
|
||||
HasExpoNames,
|
||||
HasNoExpo,
|
||||
HasMixerNames,
|
||||
HasCvNames,
|
||||
HasPxxCountry,
|
||||
HasPPMStart,
|
||||
HasGeneralUnits,
|
||||
HasFAIMode,
|
||||
OptrexDisplay,
|
||||
PPMExtCtrl,
|
||||
PPMFrameLength,
|
||||
Telemetry,
|
||||
TelemetryUnits,
|
||||
TelemetryBars,
|
||||
Heli,
|
||||
Gvars,
|
||||
GvarsInCS,
|
||||
GvarsAreNamed,
|
||||
GvarsFlightModes,
|
||||
GvarsName,
|
||||
NoTelemetryProtocol,
|
||||
TelemetryCustomScreens,
|
||||
TelemetryCustomScreensFieldsPerLine,
|
||||
TelemetryMaxMultiplier,
|
||||
HasVario,
|
||||
HasVarioSink,
|
||||
HasFailsafe,
|
||||
HasSoundMixer,
|
||||
NumModules,
|
||||
HasModuleR9MFlex,
|
||||
HasModuleR9MMini,
|
||||
PPMCenter,
|
||||
PPMUnitMicroseconds,
|
||||
SYMLimits,
|
||||
HastxCurrentCalibration,
|
||||
HasVolume,
|
||||
HasBrightness,
|
||||
PerModelTimers,
|
||||
SlowScale,
|
||||
SlowRange,
|
||||
PermTimers,
|
||||
HasSDLogs,
|
||||
CSFunc,
|
||||
LcdWidth,
|
||||
LcdHeight,
|
||||
LcdDepth,
|
||||
GetThrSwitch,
|
||||
HasDisplayText,
|
||||
HasTopLcd,
|
||||
GlobalFunctions,
|
||||
VirtualInputs,
|
||||
InputsLength,
|
||||
TrainerInputs,
|
||||
RtcTime,
|
||||
SportTelemetry,
|
||||
LuaScripts,
|
||||
LuaInputsPerScript,
|
||||
LuaOutputsPerScript,
|
||||
LimitsPer1000,
|
||||
EnhancedCurves,
|
||||
HasFasOffset,
|
||||
HasMahPersistent,
|
||||
SimulatorVariant,
|
||||
MavlinkTelemetry,
|
||||
HasInputDiff,
|
||||
HasMixerExpo,
|
||||
HasBatMeterRange,
|
||||
DangerousFunctions,
|
||||
HasModelCategories
|
||||
};
|
||||
|
||||
class EEPROMInterface
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(EEPROMInterface)
|
||||
|
||||
public:
|
||||
|
||||
EEPROMInterface(Board::Type board):
|
||||
board(board)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~EEPROMInterface() {}
|
||||
|
||||
inline Board::Type getBoard() { return board; }
|
||||
|
||||
virtual unsigned long load(RadioData &radioData, const uint8_t * eeprom, int size) = 0;
|
||||
|
||||
virtual unsigned long loadBackup(RadioData & radioData, const uint8_t * eeprom, int esize, int index) = 0;
|
||||
|
||||
virtual int save(uint8_t * eeprom, const RadioData & radioData, uint8_t version=0, uint32_t variant=0) = 0;
|
||||
|
||||
virtual int getSize(const ModelData &) = 0;
|
||||
|
||||
virtual int getSize(const GeneralSettings &) = 0;
|
||||
|
||||
//static void showEepromErrors(QWidget *parent, const QString &title, const QString &mainMessage, unsigned long errorsFound);
|
||||
static void showEepromWarnings(QWidget *parent, const QString &title, unsigned long errorsFound);
|
||||
|
||||
protected:
|
||||
|
||||
Board::Type board;
|
||||
|
||||
private:
|
||||
|
||||
EEPROMInterface();
|
||||
|
||||
};
|
||||
|
||||
/* EEPROM string conversion function (used only by er9xeeprom and ersky9xeeprom) */
|
||||
inline void getEEPROMString(char *dst, const char *src, int size)
|
||||
{
|
||||
memcpy(dst, src, size);
|
||||
dst[size] = '\0';
|
||||
for (int i=size-1; i>=0; i--) {
|
||||
if (dst[i] == ' ')
|
||||
dst[i] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// (used only by er9xeeprom and ersky9xeeprom)
|
||||
inline int applyStickMode(int stick, unsigned int mode)
|
||||
{
|
||||
if (mode == 0 || mode > 4) {
|
||||
std::cerr << "Incorrect stick mode" << mode;
|
||||
return stick;
|
||||
}
|
||||
|
||||
if (stick >= 1 && stick <= 4)
|
||||
return modn12x3[mode-1][stick-1];
|
||||
else
|
||||
return stick;
|
||||
}
|
||||
|
||||
float ValToTim(int value);
|
||||
int TimToVal(float value);
|
||||
|
||||
void registerEEpromInterfaces();
|
||||
void unregisterEEpromInterfaces();
|
||||
void registerOpenTxFirmwares();
|
||||
void unregisterOpenTxFirmwares();
|
||||
|
||||
enum EepromLoadErrors {
|
||||
ALL_OK,
|
||||
UNKNOWN_ERROR,
|
||||
UNSUPPORTED_NEWER_VERSION,
|
||||
WRONG_SIZE,
|
||||
WRONG_FILE_SYSTEM,
|
||||
NOT_OPENTX,
|
||||
NOT_TH9X,
|
||||
NOT_GRUVIN9X,
|
||||
NOT_ERSKY9X,
|
||||
NOT_ER9X,
|
||||
UNKNOWN_BOARD,
|
||||
WRONG_BOARD,
|
||||
BACKUP_NOT_SUPPORTED,
|
||||
|
||||
HAS_WARNINGS,
|
||||
OLD_VERSION,
|
||||
WARNING_WRONG_FIRMWARE,
|
||||
|
||||
NUM_ERRORS
|
||||
};
|
||||
|
||||
class Firmware
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Firmware)
|
||||
|
||||
public:
|
||||
struct Option {
|
||||
const char * name = nullptr;
|
||||
QString tooltip;
|
||||
unsigned variant = 0;
|
||||
|
||||
explicit Option(const char * name, const QString & description, unsigned variant = 0) :
|
||||
name(name), tooltip(description), variant(variant) { }
|
||||
};
|
||||
typedef QList<Option> OptionsGroup;
|
||||
typedef QList<OptionsGroup> OptionsList;
|
||||
|
||||
|
||||
explicit Firmware(const QString & id, const QString & name, Board::Type board) :
|
||||
Firmware(nullptr, id, name, board)
|
||||
{ }
|
||||
|
||||
explicit Firmware(Firmware * base, const QString & id, const QString & name, Board::Type board) :
|
||||
id(id),
|
||||
name(name),
|
||||
board(board),
|
||||
variantBase(0),
|
||||
base(base),
|
||||
eepromInterface(nullptr)
|
||||
{ }
|
||||
|
||||
virtual ~Firmware() { }
|
||||
|
||||
inline const Firmware * getFirmwareBase() const
|
||||
{
|
||||
return base ? base : this;
|
||||
}
|
||||
|
||||
virtual Firmware * getFirmwareVariant(const QString & id) { return NULL; }
|
||||
|
||||
unsigned int getVariantNumber();
|
||||
|
||||
virtual void addLanguage(const char * lang);
|
||||
|
||||
//virtual void addTTSLanguage(const char * lang);
|
||||
|
||||
virtual void addOption(const char * option, const QString & tooltip = QString(), unsigned variant = 0);
|
||||
|
||||
virtual void addOption(const Option & option);
|
||||
|
||||
virtual void addOptionsGroup(const OptionsGroup & options);
|
||||
|
||||
virtual QString getStampUrl() = 0;
|
||||
|
||||
virtual QString getReleaseNotesUrl() = 0;
|
||||
|
||||
virtual QString getFirmwareUrl() = 0;
|
||||
|
||||
Board::Type getBoard() const
|
||||
{
|
||||
return board;
|
||||
}
|
||||
|
||||
void setEEpromInterface(EEPROMInterface * eeprom)
|
||||
{
|
||||
eepromInterface = eeprom;
|
||||
}
|
||||
|
||||
EEPROMInterface * getEEpromInterface()
|
||||
{
|
||||
return eepromInterface;
|
||||
}
|
||||
|
||||
QString getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
QString getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
QList<const char *> languageList() const
|
||||
{
|
||||
return languages;
|
||||
}
|
||||
|
||||
OptionsList optionGroups() const
|
||||
{
|
||||
return opts;
|
||||
}
|
||||
|
||||
virtual int getCapability(Capability) = 0;
|
||||
|
||||
virtual QString getAnalogInputName(unsigned int index) = 0;
|
||||
|
||||
virtual QTime getMaxTimerStart() = 0;
|
||||
|
||||
virtual int isAvailable(PulsesProtocol proto, int port=0) = 0;
|
||||
|
||||
const int getFlashSize();
|
||||
|
||||
static Firmware * getFirmwareForId(const QString & id);
|
||||
|
||||
static QVector<Firmware *> getRegisteredFirmwares()
|
||||
{
|
||||
return registeredFirmwares;
|
||||
}
|
||||
|
||||
static void addRegisteredFirmware(Firmware * fw)
|
||||
{
|
||||
registeredFirmwares.append(fw);
|
||||
}
|
||||
|
||||
static Firmware * getDefaultVariant()
|
||||
{
|
||||
return defaultVariant;
|
||||
}
|
||||
static void setDefaultVariant(Firmware * value)
|
||||
{
|
||||
defaultVariant = value;
|
||||
}
|
||||
|
||||
static Firmware * getCurrentVariant()
|
||||
{
|
||||
return currentVariant;
|
||||
}
|
||||
|
||||
static void setCurrentVariant(Firmware * value)
|
||||
{
|
||||
currentVariant = value;
|
||||
}
|
||||
|
||||
protected:
|
||||
QString id;
|
||||
QString name;
|
||||
Board::Type board;
|
||||
unsigned int variantBase;
|
||||
Firmware * base;
|
||||
EEPROMInterface * eepromInterface;
|
||||
QList<const char *> languages;
|
||||
//QList<const char *> ttslanguages;
|
||||
OptionsList opts;
|
||||
|
||||
static QVector<Firmware *> registeredFirmwares;
|
||||
static Firmware * defaultVariant;
|
||||
static Firmware * currentVariant;
|
||||
};
|
||||
|
||||
inline Firmware * getCurrentFirmware()
|
||||
{
|
||||
return Firmware::getCurrentVariant();
|
||||
}
|
||||
|
||||
inline EEPROMInterface * getCurrentEEpromInterface()
|
||||
{
|
||||
return Firmware::getCurrentVariant()->getEEpromInterface();
|
||||
}
|
||||
|
||||
inline Board::Type getCurrentBoard()
|
||||
{
|
||||
return Firmware::getCurrentVariant()->getBoard();
|
||||
}
|
||||
|
||||
inline int divRoundClosest(const int n, const int d)
|
||||
{
|
||||
return ((n < 0) ^ (d < 0)) ? ((n - d/2)/d) : ((n + d/2)/d);
|
||||
}
|
||||
|
||||
inline int calcRESXto100(int x)
|
||||
{
|
||||
return divRoundClosest(x*100, 1024);
|
||||
}
|
||||
|
||||
extern QList<EEPROMInterface *> eepromInterfaces;
|
||||
|
||||
|
||||
#endif // _EEPROMINTERFACE_H_
|
||||
@@ -1,481 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include "er9xeeprom.h"
|
||||
#include "helpers.h"
|
||||
#include <QObject>
|
||||
|
||||
RawSwitch er9xToSwitch(int8_t sw)
|
||||
{
|
||||
uint8_t swa = abs(sw);
|
||||
if (swa == 0)
|
||||
return RawSwitch(SWITCH_TYPE_NONE);
|
||||
else if (swa <= 9)
|
||||
return RawSwitch(SWITCH_TYPE_SWITCH, sw);
|
||||
else if (swa <= 21)
|
||||
return RawSwitch(SWITCH_TYPE_VIRTUAL, sw > 0 ? sw-9 : sw+9);
|
||||
else if (sw == 22)
|
||||
return RawSwitch(SWITCH_TYPE_ON);
|
||||
else if (sw == -22)
|
||||
return RawSwitch(SWITCH_TYPE_OFF);
|
||||
else if (swa <= 22+9)
|
||||
return RawSwitch(SWITCH_TYPE_SWITCH, sw > 0 ? sw-22 : sw+22);
|
||||
else
|
||||
return RawSwitch(SWITCH_TYPE_VIRTUAL, sw > 0 ? sw-22-9 : sw+22+9);
|
||||
}
|
||||
|
||||
t_Er9xTrainerMix::t_Er9xTrainerMix()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Er9xTrainerMix));
|
||||
}
|
||||
|
||||
t_Er9xTrainerMix::operator TrainerMix()
|
||||
{
|
||||
TrainerMix c9x;
|
||||
c9x.src = srcChn;
|
||||
c9x.swtch = er9xToSwitch(swtch);
|
||||
c9x.weight = (25 * studWeight) / 8;
|
||||
c9x.mode = mode;
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Er9xTrainerData::t_Er9xTrainerData()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Er9xTrainerData));
|
||||
}
|
||||
|
||||
t_Er9xTrainerData::operator TrainerData ()
|
||||
{
|
||||
TrainerData c9x;
|
||||
for (int i=0; i<CPN_MAX_STICKS; i++) {
|
||||
c9x.calib[i] = calib[i];
|
||||
c9x.mix[i] = mix[i];
|
||||
}
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Er9xGeneral::t_Er9xGeneral()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Er9xGeneral));
|
||||
}
|
||||
|
||||
Er9xGeneral::operator GeneralSettings ()
|
||||
{
|
||||
GeneralSettings result;
|
||||
result.version = myVers;
|
||||
for (int i=0; i<CPN_MAX_STICKSnPOTS; i++) {
|
||||
result.calibMid[i] = calibMid[i];
|
||||
result.calibSpanNeg[i] = calibSpanNeg[i];
|
||||
result.calibSpanPos[i] = calibSpanPos[i];
|
||||
}
|
||||
|
||||
result.currModelIndex = currModel;
|
||||
result.contrast = contrast;
|
||||
result.vBatWarn = vBatWarn;
|
||||
result.txVoltageCalibration = txVoltageCalibration;
|
||||
result.trainer = trainer;
|
||||
|
||||
result.view = std::min((uint8_t)4, view);
|
||||
result.disableThrottleWarning = disableThrottleWarning;
|
||||
result.disableMemoryWarning = disableMemoryWarning;
|
||||
|
||||
switch (beeperVal) {
|
||||
case 0:
|
||||
result.beeperMode = GeneralSettings::BEEPER_QUIET;
|
||||
break;
|
||||
case 1:
|
||||
result.beeperMode = GeneralSettings::BEEPER_NOKEYS;
|
||||
break;
|
||||
default:
|
||||
result.beeperMode = GeneralSettings::BEEPER_ALL;
|
||||
result.beeperLength = beeperVal - 4;
|
||||
break;
|
||||
}
|
||||
|
||||
result.disableAlarmWarning = disableAlarmWarning;
|
||||
result.stickMode = std::max((uint8_t)0, std::min(stickMode, (uint8_t)3));
|
||||
result.inactivityTimer = inactivityTimer + 10;
|
||||
result.minuteBeep = minuteBeep;
|
||||
result.preBeep = preBeep;
|
||||
result.flashBeep = flashBeep;
|
||||
result.splashMode = disableSplashScreen;
|
||||
|
||||
result.backlightMode = 0;
|
||||
if (lightSw == 22) {
|
||||
result.backlightMode = 4;
|
||||
}
|
||||
else if (lightAutoOff) {
|
||||
result.backlightMode |= 1;
|
||||
result.backlightDelay = lightAutoOff;
|
||||
}
|
||||
else if (lightOnStickMove) {
|
||||
result.backlightMode |= 2;
|
||||
result.backlightDelay = lightOnStickMove;
|
||||
}
|
||||
|
||||
result.templateSetup = templateSetup;
|
||||
result.PPM_Multiplier = PPM_Multiplier;
|
||||
getEEPROMString(result.ownerName, ownerName, sizeof(ownerName));
|
||||
result.speakerPitch = speakerPitch;
|
||||
result.hapticStrength = hapticStrength - 3;
|
||||
result.speakerMode = speakerMode;
|
||||
return result;
|
||||
}
|
||||
|
||||
t_Er9xLimitData::t_Er9xLimitData()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Er9xLimitData));
|
||||
}
|
||||
|
||||
t_Er9xLimitData::operator LimitData ()
|
||||
{
|
||||
LimitData c9x;
|
||||
c9x.min = 10*(min-100);
|
||||
c9x.max = 10*(max+100);
|
||||
c9x.revert = revert;
|
||||
c9x.offset = offset;
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Er9xMixData::t_Er9xMixData()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Er9xMixData));
|
||||
}
|
||||
|
||||
t_Er9xMixData::operator MixData ()
|
||||
{
|
||||
MixData c9x;
|
||||
c9x.destCh = destCh;
|
||||
if (abs(weight)>125) {
|
||||
int gvar;
|
||||
if (weight>0) {
|
||||
gvar=weight-125;
|
||||
} else {
|
||||
gvar=weight+131;
|
||||
}
|
||||
gvar+=10000;
|
||||
c9x.weight=gvar;
|
||||
} else {
|
||||
c9x.weight = weight;
|
||||
}
|
||||
if (abs(sOffset)>125) {
|
||||
int gvar;
|
||||
if (sOffset>0) {
|
||||
gvar=sOffset-125;
|
||||
} else {
|
||||
gvar=sOffset+131;
|
||||
}
|
||||
gvar+=10000;
|
||||
c9x.sOffset=gvar;
|
||||
} else {
|
||||
c9x.sOffset=sOffset;
|
||||
}
|
||||
c9x.swtch = er9xToSwitch(swtch);
|
||||
|
||||
if (srcRaw == 0) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_NONE);
|
||||
}
|
||||
else if (srcRaw <= 7) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_STICK, srcRaw-1);
|
||||
}
|
||||
else if (srcRaw == 8) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
else if (srcRaw == 9) {
|
||||
if (swtch < 0) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, swtch < -3 ? -swtch-3 : -swtch);
|
||||
c9x.weight = -weight;
|
||||
}
|
||||
else if (swtch > 0) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, swtch > 3 ? swtch-3 : swtch);
|
||||
}
|
||||
else {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
if (mltpx != MLTPX_REP)
|
||||
c9x.swtch = RawSwitch(SWITCH_TYPE_NONE);
|
||||
}
|
||||
else if (srcRaw <= 12) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_CYC, srcRaw-10);
|
||||
}
|
||||
else if (srcRaw <= 20) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_PPM, srcRaw-13);
|
||||
}
|
||||
else if (srcRaw <=37) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_CH, srcRaw-21);
|
||||
}
|
||||
else {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_GVAR, srcRaw-38);
|
||||
}
|
||||
|
||||
if (differential==1) {
|
||||
c9x.curve.type = CurveReference::CURVE_REF_DIFF;
|
||||
c9x.curve.value = differential;
|
||||
}
|
||||
else if (curve > 6) {
|
||||
c9x.curve.type = CurveReference::CURVE_REF_CUSTOM;
|
||||
c9x.curve.value = curve - 6;
|
||||
}
|
||||
else if (curve > 0) {
|
||||
c9x.curve.type = CurveReference::CURVE_REF_FUNC;
|
||||
c9x.curve.value = curve;
|
||||
}
|
||||
|
||||
// c9x.lateOffset=lateOffset;
|
||||
c9x.delayUp = delayUp;
|
||||
c9x.delayDown = delayDown;
|
||||
c9x.speedUp = speedUp;
|
||||
c9x.speedDown = speedDown;
|
||||
c9x.carryTrim = carryTrim;
|
||||
c9x.mltpx = (MltpxValue)mltpx;
|
||||
c9x.mixWarn = mixWarn;
|
||||
// c9x.enableFmTrim=enableFmTrim;
|
||||
return c9x;
|
||||
}
|
||||
|
||||
RawSource er9xToSource(int8_t value)
|
||||
{
|
||||
if (value == 0) {
|
||||
return RawSource(SOURCE_TYPE_NONE);
|
||||
}
|
||||
else if (value <= 7) {
|
||||
return RawSource(SOURCE_TYPE_STICK, value - 1);
|
||||
}
|
||||
else if (value == 8) {
|
||||
return RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
else if (value == 9) {
|
||||
return RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
else if (value <= 12) {
|
||||
return RawSource(SOURCE_TYPE_CYC, value-10);
|
||||
}
|
||||
else if (value <= 20) {
|
||||
return RawSource(SOURCE_TYPE_PPM, value-13);
|
||||
}
|
||||
else if (value <= 36) {
|
||||
return RawSource(SOURCE_TYPE_CH, value-21);
|
||||
}
|
||||
else {
|
||||
return RawSource(SOURCE_TYPE_TELEMETRY, value-36);
|
||||
}
|
||||
}
|
||||
|
||||
Er9xLogicalSwitchData::operator LogicalSwitchData ()
|
||||
{
|
||||
LogicalSwitchData c9x;
|
||||
c9x.func = func;
|
||||
c9x.val1 = v1;
|
||||
c9x.val2 = v2;
|
||||
|
||||
if ((c9x.func >= LS_FN_VPOS && c9x.func <= LS_FN_ANEG) || c9x.func >= LS_FN_EQUAL) {
|
||||
c9x.val1 = er9xToSource(v1).toValue();
|
||||
}
|
||||
|
||||
if (c9x.func >= LS_FN_EQUAL) {
|
||||
c9x.val2 = er9xToSource(v2).toValue();
|
||||
}
|
||||
|
||||
if (c9x.func >= LS_FN_AND && c9x.func <= LS_FN_XOR) {
|
||||
c9x.val1 = er9xToSwitch(v1).toValue();
|
||||
c9x.val2 = er9xToSwitch(v2).toValue();
|
||||
}
|
||||
|
||||
return c9x;
|
||||
}
|
||||
|
||||
|
||||
t_Er9xSafetySwData::t_Er9xSafetySwData()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Er9xSafetySwData));
|
||||
}
|
||||
|
||||
t_Er9xFrSkyChannelData::t_Er9xFrSkyChannelData()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Er9xFrSkyChannelData));
|
||||
}
|
||||
|
||||
t_Er9xFrSkyChannelData::operator FrSkyChannelData ()
|
||||
{
|
||||
FrSkyChannelData c9x;
|
||||
c9x.ratio = ratio;
|
||||
c9x.alarms[0].value = alarms_value[0];
|
||||
c9x.alarms[0].level = alarms_level & 3;
|
||||
c9x.alarms[0].greater = alarms_greater & 1;
|
||||
c9x.alarms[1].value = alarms_value[1];
|
||||
c9x.alarms[1].level = (alarms_level >> 2) & 3;
|
||||
c9x.alarms[1].greater = (alarms_greater >> 1) & 1;
|
||||
if (type==2) {
|
||||
c9x.type = 0;
|
||||
c9x.multiplier=1;
|
||||
} else {
|
||||
c9x.type = type;
|
||||
}
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Er9xFrSkyData::t_Er9xFrSkyData()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Er9xFrSkyData));
|
||||
}
|
||||
|
||||
t_Er9xFrSkyData::operator FrSkyData ()
|
||||
{
|
||||
FrSkyData c9x;
|
||||
c9x.channels[0] = channels[0];
|
||||
c9x.channels[1] = channels[1];
|
||||
return c9x;
|
||||
}
|
||||
|
||||
RawSwitch getEr9xTimerMode(int mode)
|
||||
{
|
||||
/*
|
||||
if (mode <= -33)
|
||||
return TimerMode(TMRMODE_FIRST_NEG_SWITCH+(mode+33));
|
||||
else if (mode <= -1)
|
||||
return TimerMode(TMRMODE_FIRST_NEG_SWITCH+(mode+1));
|
||||
else if (mode < 16)
|
||||
return TimerMode(mode);
|
||||
else if (mode < 16+21)
|
||||
return TimerMode(TMRMODE_FIRST_SWITCH+(mode-16));
|
||||
else
|
||||
return TimerMode(TMRMODE_FIRST_SWITCH+(mode-16-21));
|
||||
*/
|
||||
return RawSwitch();
|
||||
}
|
||||
|
||||
t_Er9xModelData::operator ModelData ()
|
||||
{
|
||||
ModelData c9x;
|
||||
c9x.used = true;
|
||||
getEEPROMString(c9x.name, name, sizeof(name));
|
||||
c9x.timers[0].mode = getEr9xTimerMode(tmrMode);
|
||||
c9x.timers[0].val = tmrVal;
|
||||
switch(protocol) {
|
||||
case 1:
|
||||
c9x.moduleData[0].protocol = PULSES_PXX_DJT;
|
||||
break;
|
||||
case 2:
|
||||
c9x.moduleData[0].protocol = PULSES_DSM2;
|
||||
break;
|
||||
case 3:
|
||||
c9x.moduleData[0].protocol = PULSES_PPM16;
|
||||
break;
|
||||
default:
|
||||
c9x.moduleData[0].protocol = PULSES_PPM;
|
||||
break;
|
||||
}
|
||||
c9x.moduleData[0].ppm.frameLength=ppmFrameLength;
|
||||
c9x.moduleData[0].channelsCount = 8 + 2 * ppmNCH;
|
||||
c9x.thrTrim = thrTrim;
|
||||
c9x.trimInc = trimInc-2;
|
||||
c9x.moduleData[0].ppm.delay = 300 + 50 * ppmDelay;
|
||||
c9x.customFn[0].func = FuncInstantTrim;
|
||||
if (trimSw) {
|
||||
c9x.customFn[0].swtch = er9xToSwitch(trimSw);
|
||||
}
|
||||
c9x.beepANACenter = beepANACenter;
|
||||
c9x.moduleData[0].ppm.pulsePol = pulsePol;
|
||||
c9x.extendedLimits = extendedLimits;
|
||||
c9x.swashRingData.elevatorWeight = swashInvertELE ? -100 : 100;
|
||||
c9x.swashRingData.aileronWeight = swashInvertAIL ? -100 : 100;
|
||||
c9x.swashRingData.collectiveWeight = swashInvertCOL ? -100 : 100;
|
||||
c9x.swashRingData.type = swashType;
|
||||
c9x.swashRingData.collectiveSource = er9xToSource(swashCollectiveSource);
|
||||
c9x.swashRingData.value = swashRingValue;
|
||||
|
||||
for (int i=0; i<ER9X_MAX_MIXERS; i++) {
|
||||
Er9xMixData mix = mixData[i];
|
||||
c9x.mixData[i] = mix;
|
||||
}
|
||||
|
||||
for (int i=0; i<ER9X_NUM_CHNOUT; i++)
|
||||
c9x.limitData[i] = limitData[i];
|
||||
|
||||
// expoData
|
||||
int e = 0;
|
||||
for (int ch = 0; ch < 4 && e < CPN_MAX_EXPOS; ch++) {
|
||||
for (int dr = 0, pos = 0; dr < 3 && e < CPN_MAX_EXPOS; dr++, pos++) {
|
||||
if ((dr == 0 && !expoData[ch].drSw1) || (dr == 1 && !expoData[ch].drSw2))
|
||||
dr = 2;
|
||||
if (dr == 2 && !expoData[ch].expo[0][0][0] && !expoData[ch].expo[0][0][1] && !expoData[ch].expo[0][1][0] && !expoData[ch].expo[0][1][1])
|
||||
break;
|
||||
if (expoData[ch].drSw1 && !expoData[ch].drSw2) {
|
||||
c9x.expoData[e].swtch = er9xToSwitch(dr == 0 ? expoData[ch].drSw1 : 0);
|
||||
pos = dr == 0 ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
c9x.expoData[e].swtch = er9xToSwitch(dr == 0 ? -expoData[ch].drSw1 : (dr == 1 ? -expoData[ch].drSw2 : 0));
|
||||
}
|
||||
c9x.expoData[e].chn = ch;
|
||||
if (expoData[ch].expo[pos][0][0]) {
|
||||
c9x.expoData[e].curve.type = CurveReference::CURVE_REF_EXPO;
|
||||
c9x.expoData[e].curve.value = expoData[ch].expo[pos][0][0];
|
||||
}
|
||||
c9x.expoData[e].weight = 100 + expoData[ch].expo[pos][1][0];
|
||||
if (expoData[ch].expo[pos][0][0] == expoData[ch].expo[pos][0][1] && expoData[ch].expo[pos][1][0] == expoData[ch].expo[pos][1][1]) {
|
||||
c9x.expoData[e++].mode = 3;
|
||||
}
|
||||
else {
|
||||
c9x.expoData[e].mode = 2;
|
||||
if (e < CPN_MAX_EXPOS - 1) {
|
||||
c9x.expoData[e + 1].swtch = c9x.expoData[e].swtch;
|
||||
c9x.expoData[++e].chn = ch;
|
||||
c9x.expoData[e].mode = 1;
|
||||
if (expoData[ch].expo[pos][0][1]) {
|
||||
c9x.expoData[e].curve.type = CurveReference::CURVE_REF_EXPO;
|
||||
c9x.expoData[e].curve.value = expoData[ch].expo[pos][0][1];
|
||||
}
|
||||
c9x.expoData[e++].weight = 100 + expoData[ch].expo[pos][1][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_STICKS; i++)
|
||||
c9x.flightModeData[0].trim[i] = trim[i];
|
||||
|
||||
for (int i=0; i<ER9X_MAX_CURVE5; i++) {
|
||||
c9x.curves[i].count = 5;
|
||||
for (int j = 0; j < 5; j++) {
|
||||
c9x.curves[i].points[j].x = -100 + 50 * i;
|
||||
c9x.curves[i].points[j].y = curves5[i][j];
|
||||
}
|
||||
}
|
||||
for (int i=0; i<ER9X_MAX_CURVE9; i++) {
|
||||
c9x.curves[ER9X_MAX_CURVE5 + i].count = 9;
|
||||
for (int j = 0; j < 9; j++) {
|
||||
c9x.curves[ER9X_MAX_CURVE5 + i].points[j].x = -100 + 25 * i;
|
||||
c9x.curves[ER9X_MAX_CURVE5 + i].points[j].y = curves9[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<ER9X_NUM_CSW; i++)
|
||||
c9x.logicalSw[i] = logicalSw[i];
|
||||
|
||||
// for (int i=0; i<ER9X_NUM_CHNOUT; i++)
|
||||
// c9x.safetySw[i] = safetySw[i];
|
||||
|
||||
c9x.frsky = frsky;
|
||||
c9x.frsky.usrProto=FrSkyUsrProto;
|
||||
return c9x;
|
||||
}
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ER9XEEPROM_H_
|
||||
#define _ER9XEEPROM_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "eeprominterface.h"
|
||||
|
||||
//eeprom data
|
||||
#define ER9X_MAX_MIXERS 32
|
||||
#define ER9X_MAX_CURVE5 8
|
||||
#define ER9X_MAX_CURVE9 8
|
||||
#define ER9X_MAX_CSFUNC 13
|
||||
|
||||
#define MDVERS 10
|
||||
|
||||
#define ER9X_NUM_CHNOUT 16 //number of real outputchannels CH1-CH8
|
||||
#define ER9X_NUM_CSW 12 //number of custom switches
|
||||
#define CPN_MAX_STICKSnPOTS 7 //number of sticks and pots
|
||||
#define ER9X_MAX_GVARS 7
|
||||
|
||||
#define ER9X_MAX_MODES 4
|
||||
|
||||
PACK(typedef struct t_Er9xTrainerMix {
|
||||
uint8_t srcChn:3; //0-7 = ch1-8
|
||||
int8_t swtch:5;
|
||||
int8_t studWeight:6;
|
||||
uint8_t mode:2; // off, add-mode, subst-mode
|
||||
|
||||
operator TrainerMix();
|
||||
t_Er9xTrainerMix();
|
||||
}) Er9xTrainerMix; //
|
||||
|
||||
PACK(typedef struct t_Er9xTrainerData {
|
||||
int16_t calib[4];
|
||||
Er9xTrainerMix mix[4];
|
||||
|
||||
operator TrainerData();
|
||||
t_Er9xTrainerData();
|
||||
}) Er9xTrainerData;
|
||||
|
||||
PACK(typedef struct t_Er9xGeneral {
|
||||
uint8_t myVers;
|
||||
int16_t calibMid[CPN_MAX_STICKSnPOTS];
|
||||
int16_t calibSpanNeg[CPN_MAX_STICKSnPOTS];
|
||||
int16_t calibSpanPos[CPN_MAX_STICKSnPOTS];
|
||||
uint16_t chkSum;
|
||||
uint8_t currModel; //0..15
|
||||
uint8_t contrast;
|
||||
uint8_t vBatWarn;
|
||||
int8_t txVoltageCalibration;
|
||||
int8_t lightSw;
|
||||
Er9xTrainerData trainer;
|
||||
uint8_t view;
|
||||
uint8_t disableThrottleWarning:1;
|
||||
uint8_t disableSwitchWarning:1;
|
||||
uint8_t disableMemoryWarning:1;
|
||||
uint8_t beeperVal:3;
|
||||
uint8_t reserveWarning:1;
|
||||
uint8_t disableAlarmWarning:1;
|
||||
uint8_t stickMode;
|
||||
int8_t inactivityTimer;
|
||||
uint8_t throttleReversed:1;
|
||||
uint8_t minuteBeep:1;
|
||||
uint8_t preBeep:1;
|
||||
uint8_t flashBeep:1;
|
||||
uint8_t disableSplashScreen:1;
|
||||
uint8_t disablePotScroll:1;
|
||||
uint8_t disableBG:1;
|
||||
uint8_t frskyinternalalarm:1;
|
||||
uint8_t spare_filter ; // No longer needed, left for eepe compatibility for now
|
||||
uint8_t lightAutoOff;
|
||||
uint8_t templateSetup; //RETA order according to chout_ar array
|
||||
int8_t PPM_Multiplier;
|
||||
uint8_t unused1;
|
||||
uint8_t unused2:4;
|
||||
uint8_t hideNameOnSplash:1;
|
||||
uint8_t enablePpmsim:1;
|
||||
uint8_t blightinv:1;
|
||||
uint8_t stickScroll:1;
|
||||
uint8_t speakerPitch;
|
||||
uint8_t hapticStrength;
|
||||
uint8_t speakerMode;
|
||||
uint8_t lightOnStickMove;
|
||||
|
||||
char ownerName[10];
|
||||
uint8_t switchWarningStates;
|
||||
uint8_t volume ;
|
||||
uint8_t res[3];
|
||||
uint8_t crosstrim:1;
|
||||
uint8_t spare1:7;
|
||||
|
||||
operator GeneralSettings();
|
||||
t_Er9xGeneral();
|
||||
}) Er9xGeneral;
|
||||
|
||||
PACK(typedef struct t_Er9xExpoData {
|
||||
int8_t expo[3][2][2];
|
||||
int8_t drSw1;
|
||||
int8_t drSw2;
|
||||
|
||||
t_Er9xExpoData() { memset(this, 0, sizeof(t_Er9xExpoData)); }
|
||||
}) Er9xExpoData;
|
||||
|
||||
|
||||
PACK(typedef struct t_Er9xLimitData {
|
||||
int8_t min;
|
||||
int8_t max;
|
||||
bool revert;
|
||||
int16_t offset;
|
||||
|
||||
operator LimitData();
|
||||
t_Er9xLimitData();
|
||||
}) Er9xLimitData;
|
||||
|
||||
#define MLTPX_ADD 0
|
||||
#define MLTPX_MUL 1
|
||||
#define MLTPX_REP 2
|
||||
|
||||
PACK(typedef struct t_Er9xMixData {
|
||||
uint8_t destCh; // 1..CPN_MAX_CHNOUT
|
||||
uint8_t srcRaw; //
|
||||
int8_t weight;
|
||||
int8_t swtch;
|
||||
uint8_t curve; //0=symmetrisch 1=no neg 2=no pos
|
||||
uint8_t delayUp:4;
|
||||
uint8_t delayDown:4;
|
||||
uint8_t speedUp:4; // Servogeschwindigkeit aus Tabelle (10ms Cycle)
|
||||
uint8_t speedDown:4; // 0 nichts
|
||||
uint8_t carryTrim:1;
|
||||
uint8_t mltpx:2; // multiplex method 0=+ 1=* 2=replace
|
||||
uint8_t lateOffset:1; // Add offset later
|
||||
uint8_t mixWarn:2; // mixer warning
|
||||
uint8_t enableFmTrim:1;
|
||||
uint8_t differential:1;
|
||||
int8_t sOffset;
|
||||
int8_t res;
|
||||
|
||||
operator MixData();
|
||||
t_Er9xMixData();
|
||||
}) Er9xMixData;
|
||||
|
||||
|
||||
PACK(typedef struct t_Er9xLogicalSwitchData { // Custom Switches data
|
||||
int8_t v1; //input
|
||||
int8_t v2; //offset
|
||||
uint8_t func:4;
|
||||
uint8_t andsw:4;
|
||||
|
||||
operator LogicalSwitchData();
|
||||
t_Er9xLogicalSwitchData() { memset(this, 0, sizeof(t_Er9xLogicalSwitchData)); }
|
||||
}) Er9xLogicalSwitchData;
|
||||
|
||||
PACK(typedef struct t_Er9xSafetySwData { // Custom Switches data
|
||||
int8_t swtch;
|
||||
int8_t val;
|
||||
|
||||
t_Er9xSafetySwData();
|
||||
}) Er9xSafetySwData;
|
||||
|
||||
PACK(typedef struct t_Er9xFrSkyChannelData {
|
||||
uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
|
||||
uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
|
||||
uint8_t alarms_level:4;
|
||||
uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>)
|
||||
uint8_t type:2; // future use: 0=volts, ...
|
||||
|
||||
operator FrSkyChannelData();
|
||||
t_Er9xFrSkyChannelData();
|
||||
}) Er9xFrSkyChannelData;
|
||||
|
||||
PACK(typedef struct t_Er9xFrSkyData {
|
||||
Er9xFrSkyChannelData channels[2];
|
||||
|
||||
operator FrSkyData();
|
||||
t_Er9xFrSkyData();
|
||||
}) Er9xFrSkyData;
|
||||
|
||||
PACK(typedef struct t_gvar {
|
||||
int8_t gvar ;
|
||||
uint8_t gvsource ;
|
||||
// int8_t gvswitch ;
|
||||
}) Er9xGvarData ;
|
||||
|
||||
PACK(typedef struct t_FlightModeData {
|
||||
// Trim store as -1001 to -1, trim value-501, 0-5 use trim of phase 0-5
|
||||
int16_t trim[4]; // -500..500 => trim value, 501 => use trim of phase 0, 502, 503, 504 => use trim of modes 1|2|3|4 instead
|
||||
int8_t swtch; // Try 0-5 use trim of phase 0-5, 1000-2000, trim + 1500 ???
|
||||
uint8_t fadeIn:4;
|
||||
uint8_t fadeOut:4;
|
||||
}) Er9xFlightModeData;
|
||||
|
||||
PACK(typedef struct t_Er9xModelData {
|
||||
char name[10]; // 10 must be first for eeLoadModelName
|
||||
uint8_t modelVoice ; // Index to model name voice (260+value)
|
||||
int8_t tmrMode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
|
||||
uint8_t tmrDir:1; //0=>Count Down, 1=>Count Up
|
||||
uint8_t traineron:1; // 0 disable trainer, 1 allow trainer
|
||||
uint8_t t2throttle:1 ; // Start timer2 using throttle
|
||||
uint8_t FrSkyUsrProto:1 ; // Protocol in FrSky User Data, 0=FrSky Hub, 1=WS HowHigh
|
||||
uint8_t FrSkyGpsAlt:1 ; // Use Gps Altitude as main altitude reading
|
||||
uint8_t FrSkyImperial:1 ; // Convert FrSky values to imperial units
|
||||
uint8_t FrSkyAltAlarm:2;
|
||||
uint16_t tmrVal;
|
||||
uint8_t protocol;
|
||||
int8_t ppmNCH;
|
||||
uint8_t thrTrim:1; // Enable Throttle Trim
|
||||
uint8_t xnumBlades:2; // RPM scaling
|
||||
uint8_t spare10:1;
|
||||
uint8_t thrExpo:1; // Enable Throttle Expo
|
||||
uint8_t ppmStart:3 ; // Start channel for PPM
|
||||
int8_t trimInc; // Trim Increments
|
||||
int8_t ppmDelay;
|
||||
int8_t trimSw;
|
||||
uint8_t beepANACenter; // 1<<0->A1.. 1<<6->A7
|
||||
uint8_t pulsePol:1;
|
||||
uint8_t extendedLimits:1;
|
||||
uint8_t swashInvertELE:1;
|
||||
uint8_t swashInvertAIL:1;
|
||||
uint8_t swashInvertCOL:1;
|
||||
uint8_t swashType:3;
|
||||
uint8_t swashCollectiveSource;
|
||||
uint8_t swashRingValue;
|
||||
int8_t ppmFrameLength;
|
||||
Er9xMixData mixData[ER9X_MAX_MIXERS];
|
||||
Er9xLimitData limitData[ER9X_NUM_CHNOUT];
|
||||
Er9xExpoData expoData[4];
|
||||
int8_t trim[4];
|
||||
int8_t curves5[ER9X_MAX_CURVE5][5];
|
||||
int8_t curves9[ER9X_MAX_CURVE9][9];
|
||||
Er9xLogicalSwitchData logicalSw[ER9X_NUM_CSW];
|
||||
uint8_t frSkyVoltThreshold ;
|
||||
int8_t tmrModeB;
|
||||
uint8_t numVoice;
|
||||
Er9xSafetySwData safetySw[ER9X_NUM_CHNOUT];
|
||||
Er9xFrSkyData frsky;
|
||||
uint8_t numBlades ;
|
||||
uint8_t unused1[8] ;
|
||||
uint8_t CustomDisplayIndex[6] ;
|
||||
Er9xGvarData gvars[ER9X_MAX_GVARS] ;
|
||||
Er9xFlightModeData flightModeData[ER9X_MAX_MODES] ;
|
||||
|
||||
operator ModelData();
|
||||
t_Er9xModelData() { memset(this, 0, sizeof(t_Er9xModelData)); }
|
||||
}) Er9xModelData;
|
||||
|
||||
#endif // _ER9XEEPROM_H_
|
||||
@@ -1,336 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "er9xinterface.h"
|
||||
#include "er9xeeprom.h"
|
||||
#include "rlefile.h"
|
||||
// #include "appdata.h"
|
||||
// #include <iostream>
|
||||
#include <bitset>
|
||||
|
||||
#define FILE_TYP_GENERAL 1
|
||||
#define FILE_TYP_MODEL 2
|
||||
|
||||
#define FILE_GENERAL 0
|
||||
#define FILE_MODEL(n) (1+n)
|
||||
|
||||
Er9xInterface::Er9xInterface():
|
||||
EEPROMInterface(Board::BOARD_STOCK),
|
||||
efile(new RleFile())
|
||||
{
|
||||
}
|
||||
|
||||
Er9xInterface::~Er9xInterface()
|
||||
{
|
||||
delete efile;
|
||||
}
|
||||
|
||||
const char * Er9xInterface::getName()
|
||||
{
|
||||
return "Er9x";
|
||||
}
|
||||
|
||||
inline void applyStickModeToModel(Er9xModelData & model, unsigned int mode)
|
||||
{
|
||||
for (int i=0; i<2; i++) {
|
||||
int stick = applyStickMode(i+1, mode) - 1;
|
||||
{
|
||||
int tmp = model.trim[i];
|
||||
model.trim[i] = model.trim[stick];
|
||||
model.trim[stick] = tmp;
|
||||
}
|
||||
{
|
||||
Er9xExpoData tmp = model.expoData[i];
|
||||
model.expoData[i] = model.expoData[stick];
|
||||
model.expoData[stick] = tmp;
|
||||
}
|
||||
}
|
||||
for (int i=0; i<ER9X_MAX_MIXERS; i++)
|
||||
model.mixData[i].srcRaw = applyStickMode(model.mixData[i].srcRaw, mode);
|
||||
for (int i=0; i<ER9X_NUM_CSW; i++) {
|
||||
switch (LogicalSwitchData(model.logicalSw[i].func).getFunctionFamily()) {
|
||||
case LS_FAMILY_VCOMP:
|
||||
model.logicalSw[i].v2 = applyStickMode(model.logicalSw[i].v2, mode);
|
||||
// no break
|
||||
case LS_FAMILY_VOFS:
|
||||
model.logicalSw[i].v1 = applyStickMode(model.logicalSw[i].v1, mode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
model.swashCollectiveSource = applyStickMode(model.swashCollectiveSource, mode);
|
||||
}
|
||||
|
||||
#if 0
|
||||
unsigned long Er9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
|
||||
{
|
||||
QDebug dbg = qDebug();
|
||||
dbg.setAutoInsertSpaces(false);
|
||||
dbg << "trying er9x xml import... ";
|
||||
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
Er9xGeneral er9xGeneral;
|
||||
memset(&er9xGeneral,0,sizeof(er9xGeneral));
|
||||
if (!loadRadioSettingsDataXML(&doc, &er9xGeneral)) {
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
else {
|
||||
radioData.generalSettings=er9xGeneral;
|
||||
dbg << "version " << (unsigned int)er9xGeneral.myVers << " ";
|
||||
}
|
||||
for (int i=0; i<getCapability(Models); i++) {
|
||||
Er9xModelData er9xModel;
|
||||
memset(&er9xModel,0,sizeof(er9xModel));
|
||||
if(loadModelDataXML(&doc, &er9xModel, i)) {
|
||||
applyStickModeToModel(er9xModel, radioData.generalSettings.stickMode+1);
|
||||
radioData.models[i] = er9xModel;
|
||||
}
|
||||
}
|
||||
dbg << "ok";
|
||||
errors.set(ALL_OK);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long Er9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
|
||||
{
|
||||
QDebug dbg = qDebug();
|
||||
dbg.setAutoInsertSpaces(false);
|
||||
dbg << "trying er9x import... ";
|
||||
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
if (size != Boards::getEEpromSize(Board::BOARD_STOCK)) {
|
||||
dbg << "wrong size";
|
||||
errors.set(WRONG_SIZE);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
if (!efile->EeFsOpen((uint8_t *)eeprom, size, Board::BOARD_STOCK)) {
|
||||
dbg << "wrong file system";
|
||||
errors.set(WRONG_FILE_SYSTEM);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
efile->openRd(FILE_GENERAL);
|
||||
Er9xGeneral er9xGeneral;
|
||||
|
||||
if (efile->readRlc1((uint8_t*)&er9xGeneral, 1) != 1) {
|
||||
dbg << "no";
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
dbg << "version " << (unsigned int)er9xGeneral.myVers << " ";
|
||||
|
||||
switch(er9xGeneral.myVers) {
|
||||
case 3:
|
||||
dbg << "(old gruvin9x) ";
|
||||
case 4:
|
||||
// case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
break;
|
||||
default:
|
||||
dbg << "not er9x";
|
||||
errors.set(NOT_ER9X);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
efile->openRd(FILE_GENERAL);
|
||||
if (!efile->readRlc1((uint8_t*)&er9xGeneral, sizeof(Er9xGeneral))) {
|
||||
dbg << "ko";
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
|
||||
}
|
||||
radioData.generalSettings = er9xGeneral;
|
||||
|
||||
for (int i=0; i<getCapability(Models); i++) {
|
||||
Er9xModelData er9xModel;
|
||||
efile->openRd(FILE_MODEL(i));
|
||||
if (!efile->readRlc1((uint8_t*)&er9xModel, sizeof(Er9xModelData))) {
|
||||
radioData.models[i].clear();
|
||||
}
|
||||
else {
|
||||
applyStickModeToModel(er9xModel, radioData.generalSettings.stickMode+1);
|
||||
radioData.models[i] = er9xModel;
|
||||
}
|
||||
}
|
||||
|
||||
dbg << "ok";
|
||||
errors.set(ALL_OK);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
unsigned long Er9xInterface::loadBackup(RadioData &radioData, const uint8_t *eeprom, int esize, int index)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
int Er9xInterface::getSize(const ModelData &model)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Er9xInterface::getSize(const GeneralSettings &settings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Er9xInterface::isAvailable(PulsesProtocol prot, int port)
|
||||
{
|
||||
switch (prot) {
|
||||
case PULSES_PPM:
|
||||
case PULSES_DSM2:
|
||||
case PULSES_PXX_DJT:
|
||||
case PULSES_PPM16:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Er9xInterface::appendTextElement(QDomDocument * qdoc, QDomElement * pe, QString name, QString value)
|
||||
{
|
||||
QDomElement e = qdoc->createElement(name);
|
||||
QDomText t = qdoc->createTextNode(name);
|
||||
t.setNodeValue(value);
|
||||
e.appendChild(t);
|
||||
pe->appendChild(e);
|
||||
}
|
||||
|
||||
void Er9xInterface::appendNumberElement(QDomDocument * qdoc, QDomElement * pe,QString name, int value, bool forceZeroWrite)
|
||||
{
|
||||
if(value || forceZeroWrite) {
|
||||
QDomElement e = qdoc->createElement(name);
|
||||
QDomText t = qdoc->createTextNode(name);
|
||||
t.setNodeValue(QString("%1").arg(value));
|
||||
e.appendChild(t);
|
||||
pe->appendChild(e);
|
||||
}
|
||||
}
|
||||
|
||||
void Er9xInterface::appendCDATAElement(QDomDocument * qdoc, QDomElement * pe,QString name, const char * data, int size)
|
||||
{
|
||||
QDomElement e = qdoc->createElement(name);
|
||||
QDomCDATASection t = qdoc->createCDATASection(name);
|
||||
t.setData(QByteArray(data, size).toBase64());
|
||||
e.appendChild(t);
|
||||
pe->appendChild(e);
|
||||
}
|
||||
|
||||
QDomElement Er9xInterface::getGeneralDataXML(QDomDocument * qdoc, Er9xGeneral * tgen)
|
||||
{
|
||||
QDomElement gd = qdoc->createElement("GENERAL_DATA");
|
||||
appendNumberElement(qdoc, &gd, "Version", tgen->myVers, true); // have to write value here
|
||||
appendTextElement(qdoc, &gd, "Owner", QString::fromLatin1(tgen->ownerName,sizeof(tgen->ownerName)).trimmed());
|
||||
appendCDATAElement(qdoc, &gd, "Data", (const char *)tgen,sizeof(Er9xGeneral));
|
||||
return gd;
|
||||
}
|
||||
|
||||
QDomElement Er9xInterface::getModelDataXML(QDomDocument * qdoc, Er9xModelData * tmod, int modelNum, int mdver)
|
||||
{
|
||||
QDomElement md = qdoc->createElement("MODEL_DATA");
|
||||
md.setAttribute("number", modelNum);
|
||||
appendNumberElement(qdoc, &md, "Version", mdver, true); // have to write value here
|
||||
appendTextElement(qdoc, &md, "Name", QString::fromLatin1(tmod->name,sizeof(tmod->name)).trimmed());
|
||||
appendCDATAElement(qdoc, &md, "Data", (const char *)tmod,sizeof(Er9xModelData));
|
||||
return md;
|
||||
}
|
||||
|
||||
bool Er9xInterface::loadRadioSettingsDataXML(QDomDocument * qdoc, Er9xGeneral * tgen)
|
||||
{
|
||||
// look for "GENERAL_DATA" tag
|
||||
QDomElement gde = qdoc->elementsByTagName("GENERAL_DATA").at(0).toElement();
|
||||
|
||||
if(gde.isNull()) // couldn't find
|
||||
return false;
|
||||
|
||||
// load cdata into tgen
|
||||
QDomNode n = gde.elementsByTagName("Data").at(0).firstChild();// get all children in Data
|
||||
while (!n.isNull()) {
|
||||
if (n.isCDATASection()) {
|
||||
QString ds = n.toCDATASection().data();
|
||||
QByteArray ba = QByteArray::fromBase64(ds.toLatin1());
|
||||
const char * data = ba.data();
|
||||
memcpy(tgen, data, sizeof(Er9xGeneral));
|
||||
break;
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
// check version?
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Er9xInterface::loadModelDataXML(QDomDocument * qdoc, Er9xModelData * tmod, int modelNum)
|
||||
{
|
||||
// look for MODEL_DATA with modelNum attribute.
|
||||
// if modelNum = -1 then just pick the first one
|
||||
QDomNodeList ndl = qdoc->elementsByTagName("MODEL_DATA");
|
||||
|
||||
// cycle through nodes to find correct model number
|
||||
QDomNode k = ndl.at(0);
|
||||
if(modelNum>=0) {
|
||||
while(!k.isNull()) {
|
||||
int a = k.toElement().attribute("number").toInt();
|
||||
if(a==modelNum)
|
||||
break;
|
||||
k = k.nextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
if (k.isNull()) // couldn't find
|
||||
return false;
|
||||
|
||||
|
||||
// load cdata into tgen
|
||||
QDomNode n = k.toElement().elementsByTagName("Data").at(0).firstChild();// get all children in Data
|
||||
while (!n.isNull()) {
|
||||
if (n.isCDATASection()) {
|
||||
QString ds = n.toCDATASection().data();
|
||||
QByteArray ba = QByteArray::fromBase64(ds.toLatin1());
|
||||
const char * data = ba.data();
|
||||
memcpy(tmod, data, sizeof(Er9xModelData));
|
||||
break;
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
// check version?
|
||||
return true;
|
||||
}
|
||||
|
||||
int Er9xInterface::getCapability(Capability capability)
|
||||
{
|
||||
switch (capability) {
|
||||
case Models:
|
||||
return 16;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ER9XINTERFACE_H_
|
||||
#define _ER9XINTERFACE_H_
|
||||
|
||||
#include <QtXml>
|
||||
#include "eeprominterface.h"
|
||||
#include "er9xeeprom.h"
|
||||
|
||||
class RleFile;
|
||||
|
||||
class Er9xInterface : public EEPROMInterface
|
||||
{
|
||||
public:
|
||||
|
||||
Er9xInterface();
|
||||
|
||||
virtual ~Er9xInterface();
|
||||
|
||||
virtual const char * getName();
|
||||
|
||||
virtual unsigned long load(RadioData &, const uint8_t * eeprom, int size);
|
||||
|
||||
virtual unsigned long loadBackup(RadioData &, const uint8_t * eeprom, int esize, int index);
|
||||
|
||||
virtual unsigned long loadxml(RadioData &radioData, QDomDocument &doc);
|
||||
|
||||
virtual int save(uint8_t * eeprom, const RadioData & radioData, uint8_t version=0, uint32_t variant=0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int getSize(const ModelData &);
|
||||
|
||||
virtual int getSize(const GeneralSettings &settings);
|
||||
|
||||
virtual int isAvailable(PulsesProtocol proto, int port=0);
|
||||
|
||||
virtual int getCapability(Capability capability);
|
||||
|
||||
protected:
|
||||
|
||||
RleFile * efile;
|
||||
|
||||
private:
|
||||
void appendTextElement(QDomDocument * qdoc, QDomElement * pe, QString name, QString value);
|
||||
|
||||
void appendNumberElement(QDomDocument * qdoc, QDomElement * pe,QString name, int value, bool forceZeroWrite = false);
|
||||
|
||||
void appendCDATAElement(QDomDocument * qdoc, QDomElement * pe,QString name, const char * data, int size);
|
||||
|
||||
QDomElement getGeneralDataXML(QDomDocument * qdoc, Er9xGeneral * tgen); //parse out data to XML format
|
||||
|
||||
QDomElement getModelDataXML(QDomDocument * qdoc, Er9xModelData * tmod, int modelNum, int mdver); //parse out data to XML format
|
||||
|
||||
bool loadRadioSettingsDataXML(QDomDocument * qdoc, Er9xGeneral * tgen); // get data from XML
|
||||
|
||||
bool loadModelDataXML(QDomDocument * qdoc, Er9xModelData * tmod, int modelNum = -1); // get data from XML
|
||||
|
||||
};
|
||||
|
||||
#endif // _ER9XINTERFACE_H_
|
||||
@@ -1,730 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include "helpers.h"
|
||||
#include "ersky9xeeprom.h"
|
||||
#include <QObject>
|
||||
|
||||
extern RawSwitch er9xToSwitch(int8_t sw);
|
||||
|
||||
RawSwitch getErSky9xTimerMode(int mode)
|
||||
{
|
||||
if (mode<4)
|
||||
return RawSwitch(SWITCH_TYPE_TIMER_MODE, mode);
|
||||
else
|
||||
return RawSwitch();
|
||||
}
|
||||
|
||||
RawSwitch ersky9xToSwitch(int8_t sw)
|
||||
{
|
||||
uint8_t swa = abs(sw);
|
||||
if (swa == 0)
|
||||
return RawSwitch(SWITCH_TYPE_NONE);
|
||||
else if (swa <= 9)
|
||||
return RawSwitch(SWITCH_TYPE_SWITCH, sw);
|
||||
else if (swa <= 33)
|
||||
return RawSwitch(SWITCH_TYPE_VIRTUAL, sw > 0 ? sw-9 : sw+9);
|
||||
else if (sw == 34)
|
||||
return RawSwitch(SWITCH_TYPE_ON);
|
||||
else if (sw == -34)
|
||||
return RawSwitch(SWITCH_TYPE_OFF);
|
||||
else if (swa <= 34+9)
|
||||
return RawSwitch(SWITCH_TYPE_SWITCH, sw > 0 ? sw-34 : sw+34);
|
||||
else
|
||||
return RawSwitch(SWITCH_TYPE_VIRTUAL, sw > 0 ? sw-34-9 : sw+34+9);
|
||||
}
|
||||
|
||||
t_Ersky9xTrainerMix::t_Ersky9xTrainerMix()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xTrainerMix));
|
||||
}
|
||||
|
||||
t_Ersky9xTrainerMix::operator TrainerMix()
|
||||
{
|
||||
TrainerMix c9x;
|
||||
c9x.src = srcChn;
|
||||
c9x.swtch = er9xToSwitch(swtch);
|
||||
c9x.weight = (25 * studWeight) / 8;
|
||||
c9x.mode = mode;
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Ersky9xTrainerData::t_Ersky9xTrainerData()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xTrainerData));
|
||||
}
|
||||
|
||||
t_Ersky9xTrainerData::operator TrainerData ()
|
||||
{
|
||||
TrainerData c9x;
|
||||
for (int i=0; i<CPN_MAX_STICKS; i++) {
|
||||
c9x.calib[i] = calib[i];
|
||||
c9x.mix[i] = mix[i];
|
||||
}
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Ersky9xGeneral::t_Ersky9xGeneral()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xGeneral));
|
||||
}
|
||||
|
||||
Ersky9xGeneral::operator GeneralSettings ()
|
||||
{
|
||||
GeneralSettings result;
|
||||
|
||||
result.version = myVers;
|
||||
|
||||
for (int i=0; i<CPN_MAX_STICKSnPOTS; i++) {
|
||||
result.calibMid[i] = calibMid[i];
|
||||
result.calibSpanNeg[i] = calibSpanNeg[i];
|
||||
result.calibSpanPos[i] = calibSpanPos[i];
|
||||
}
|
||||
|
||||
result.currModelIndex = currModel;
|
||||
result.contrast = contrast;
|
||||
result.vBatWarn = vBatWarn;
|
||||
result.txVoltageCalibration = txVoltageCalibration;
|
||||
|
||||
result.backlightMode = 0;
|
||||
if (lightSw == 22) {
|
||||
result.backlightMode = 4;
|
||||
}
|
||||
else if (lightAutoOff) {
|
||||
result.backlightMode |= 1;
|
||||
result.backlightDelay = lightAutoOff;
|
||||
}
|
||||
else if (lightOnStickMove) {
|
||||
result.backlightMode |= 2;
|
||||
result.backlightDelay = lightOnStickMove;
|
||||
}
|
||||
|
||||
result.trainer = trainer;
|
||||
result.view = std::min((uint8_t)4, view);
|
||||
result.disableThrottleWarning = disableThrottleWarning;
|
||||
result.disableMemoryWarning = disableMemoryWarning;
|
||||
|
||||
switch (beeperVal) {
|
||||
case 0:
|
||||
result.beeperMode = GeneralSettings::BEEPER_QUIET;
|
||||
break;
|
||||
case 1:
|
||||
result.beeperMode = GeneralSettings::BEEPER_NOKEYS;
|
||||
break;
|
||||
default:
|
||||
result.beeperMode = GeneralSettings::BEEPER_ALL;
|
||||
result.beeperLength = beeperVal - 4;
|
||||
break;
|
||||
}
|
||||
|
||||
result.disableAlarmWarning = disableAlarmWarning;
|
||||
result.stickMode = std::max((uint8_t)0, std::min(stickMode, (uint8_t)3));
|
||||
result.inactivityTimer = inactivityTimer + 10;
|
||||
result.minuteBeep = minuteBeep;
|
||||
result.preBeep = preBeep;
|
||||
result.flashBeep = flashBeep;
|
||||
result.splashMode = disableSplashScreen;
|
||||
result.templateSetup = templateSetup;
|
||||
result.PPM_Multiplier = PPM_Multiplier;
|
||||
getEEPROMString(result.ownerName, ownerName, sizeof(ownerName));
|
||||
result.optrexDisplay = optrexDisplay;
|
||||
result.speakerPitch = speakerPitch;
|
||||
result.hapticStrength = hapticStrength - 3;
|
||||
result.speakerMode = speakerMode;
|
||||
result.speakerVolume = volume;
|
||||
result.backlightBright = bright ;
|
||||
result.txCurrentCalibration = current_calib;
|
||||
return result;
|
||||
}
|
||||
|
||||
t_Ersky9xLimitData::t_Ersky9xLimitData()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xLimitData));
|
||||
}
|
||||
|
||||
t_Ersky9xLimitData::operator LimitData ()
|
||||
{
|
||||
LimitData c9x;
|
||||
c9x.min = 10*(min-100);
|
||||
c9x.max = 10*(max+100);
|
||||
c9x.revert = revert;
|
||||
c9x.offset = offset;
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Ersky9xMixData_v10::t_Ersky9xMixData_v10()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xMixData_v10));
|
||||
}
|
||||
|
||||
t_Ersky9xMixData_v10::operator MixData ()
|
||||
{
|
||||
MixData c9x;
|
||||
c9x.destCh = destCh;
|
||||
c9x.weight = weight;
|
||||
c9x.swtch = er9xToSwitch(swtch);
|
||||
|
||||
if (srcRaw == 0) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_NONE);
|
||||
}
|
||||
else if (srcRaw <= 7) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_STICK, srcRaw-1);
|
||||
}
|
||||
else if (srcRaw == 8) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
else if (srcRaw == 9) {
|
||||
if (swtch < 0) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, swtch < -3 ? -swtch-3 : -swtch);
|
||||
c9x.weight = -weight;
|
||||
}
|
||||
else if (swtch > 0) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, swtch > 3 ? swtch-3 : swtch);
|
||||
}
|
||||
else {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
if (mltpx != MLTPX_REP)
|
||||
c9x.swtch = RawSwitch(SWITCH_TYPE_NONE);
|
||||
}
|
||||
else if (srcRaw == 37) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, 0);
|
||||
}
|
||||
else if (srcRaw <= 12) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_CYC, srcRaw-10);
|
||||
}
|
||||
else if (srcRaw <= 20) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_PPM, srcRaw-13);
|
||||
}
|
||||
else {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_CH, srcRaw-21);
|
||||
}
|
||||
|
||||
if (curve > 6) {
|
||||
c9x.curve.type = CurveReference::CURVE_REF_CUSTOM;
|
||||
c9x.curve.value = curve - 6;
|
||||
}
|
||||
else if (curve > 0) {
|
||||
c9x.curve.type = CurveReference::CURVE_REF_FUNC;
|
||||
c9x.curve.value = curve;
|
||||
}
|
||||
|
||||
c9x.delayUp = delayUp;
|
||||
c9x.delayDown = delayDown;
|
||||
c9x.speedUp = speedUp;
|
||||
c9x.speedDown = speedDown;
|
||||
c9x.carryTrim = carryTrim;
|
||||
c9x.mltpx = (MltpxValue)mltpx;
|
||||
c9x.mixWarn = mixWarn;
|
||||
// c9x.enableFmTrim=enableFmTrim;
|
||||
c9x.sOffset = sOffset;
|
||||
return c9x;
|
||||
}
|
||||
|
||||
|
||||
t_Ersky9xMixData_v11::t_Ersky9xMixData_v11()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xMixData_v11));
|
||||
}
|
||||
|
||||
t_Ersky9xMixData_v11::operator MixData ()
|
||||
{
|
||||
MixData c9x;
|
||||
c9x.destCh = destCh;
|
||||
c9x.weight = weight;
|
||||
c9x.swtch = ersky9xToSwitch(swtch);
|
||||
|
||||
if (srcRaw == 0) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_NONE);
|
||||
}
|
||||
else if (srcRaw <= 7) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_STICK, srcRaw-1);
|
||||
}
|
||||
else if (srcRaw == 8) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
else if (srcRaw == 9) {
|
||||
if (swtch < 0) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, swtch < -3 ? -swtch-3 : -swtch);
|
||||
c9x.weight = -weight;
|
||||
}
|
||||
else if (swtch > 0) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, swtch > 3 ? swtch-3 : swtch);
|
||||
}
|
||||
else {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
if (mltpx != MLTPX_REP)
|
||||
c9x.swtch = RawSwitch(SWITCH_TYPE_NONE);
|
||||
}
|
||||
else if (srcRaw == 45) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, 0);
|
||||
}
|
||||
else if (srcRaw > 45) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_GVAR, srcRaw-46);
|
||||
}
|
||||
else if (srcRaw <= 12) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_CYC, srcRaw-10);
|
||||
}
|
||||
else if (srcRaw <= 20) {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_PPM, srcRaw-13);
|
||||
}
|
||||
else {
|
||||
c9x.srcRaw = RawSource(SOURCE_TYPE_CH, srcRaw-21);
|
||||
}
|
||||
|
||||
if (curve > 6) {
|
||||
c9x.curve.type = CurveReference::CURVE_REF_CUSTOM;
|
||||
c9x.curve.value = curve - 6;
|
||||
}
|
||||
else if (curve > 0) {
|
||||
c9x.curve.type = CurveReference::CURVE_REF_FUNC;
|
||||
c9x.curve.value = curve;
|
||||
}
|
||||
|
||||
c9x.delayUp = delayUp;
|
||||
c9x.delayDown = delayDown;
|
||||
c9x.speedUp = speedUp;
|
||||
c9x.speedDown = speedDown;
|
||||
c9x.carryTrim = carryTrim;
|
||||
c9x.mltpx = (MltpxValue)mltpx;
|
||||
c9x.mixWarn = mixWarn;
|
||||
// c9x.enableFmTrim=enableFmTrim;
|
||||
c9x.sOffset = sOffset;
|
||||
return c9x;
|
||||
}
|
||||
|
||||
RawSource ersky9xToSource_v10(int8_t value)
|
||||
{
|
||||
if (value == 0) {
|
||||
return RawSource(SOURCE_TYPE_NONE);
|
||||
}
|
||||
else if (value <= 7) {
|
||||
return RawSource(SOURCE_TYPE_STICK, value - 1);
|
||||
}
|
||||
else if (value == 8) {
|
||||
return RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
else if (value == 9) {
|
||||
return RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
else if (value <= 12) {
|
||||
return RawSource(SOURCE_TYPE_CYC, value-10);
|
||||
}
|
||||
else if (value <= 20) {
|
||||
return RawSource(SOURCE_TYPE_PPM, value-13);
|
||||
}
|
||||
else if (value <= 36) {
|
||||
return RawSource(SOURCE_TYPE_CH, value-21);
|
||||
}
|
||||
else {
|
||||
return RawSource(SOURCE_TYPE_TELEMETRY, value-36);
|
||||
}
|
||||
}
|
||||
|
||||
RawSource ersky9xToSource_v11(int8_t value)
|
||||
{
|
||||
if (value == 0) {
|
||||
return RawSource(SOURCE_TYPE_NONE);
|
||||
}
|
||||
else if (value <= 7) {
|
||||
return RawSource(SOURCE_TYPE_STICK, value - 1);
|
||||
}
|
||||
else if (value == 8) {
|
||||
return RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
else if (value == 9) {
|
||||
return RawSource(SOURCE_TYPE_MAX);
|
||||
}
|
||||
else if (value <= 12) {
|
||||
return RawSource(SOURCE_TYPE_CYC, value-10);
|
||||
}
|
||||
else if (value <= 20) {
|
||||
return RawSource(SOURCE_TYPE_PPM, value-13);
|
||||
}
|
||||
else if (value <= 36) {
|
||||
return RawSource(SOURCE_TYPE_CH, value-21);
|
||||
}
|
||||
else {
|
||||
return RawSource(SOURCE_TYPE_TELEMETRY, value-36);
|
||||
}
|
||||
}
|
||||
|
||||
Ersky9xLogicalSwitchData_v10::operator LogicalSwitchData ()
|
||||
{
|
||||
LogicalSwitchData c9x;
|
||||
c9x.func = func;
|
||||
c9x.val1 = v1;
|
||||
c9x.val2 = v2;
|
||||
|
||||
if ((c9x.func >= LS_FN_VPOS && c9x.func <= LS_FN_ANEG) || c9x.func >= LS_FN_EQUAL) {
|
||||
c9x.val1 = ersky9xToSource_v10(v1).toValue();
|
||||
}
|
||||
|
||||
if (c9x.func >= LS_FN_EQUAL) {
|
||||
c9x.val2 = ersky9xToSource_v10(v2).toValue();
|
||||
}
|
||||
|
||||
if (c9x.func >= LS_FN_AND && c9x.func <= LS_FN_XOR) {
|
||||
c9x.val1 = er9xToSwitch(v1).toValue();
|
||||
c9x.val2 = er9xToSwitch(v2).toValue();
|
||||
}
|
||||
|
||||
return c9x;
|
||||
}
|
||||
|
||||
Ersky9xLogicalSwitchData_v11::operator LogicalSwitchData ()
|
||||
{
|
||||
LogicalSwitchData c9x;
|
||||
c9x.func = func;
|
||||
c9x.val1 = v1;
|
||||
c9x.val2 = v2;
|
||||
|
||||
if ((c9x.func >= LS_FN_VPOS && c9x.func <= LS_FN_ANEG) || c9x.func >= LS_FN_EQUAL) {
|
||||
c9x.val1 = ersky9xToSource_v11(v1).toValue();
|
||||
}
|
||||
|
||||
if (c9x.func >= LS_FN_EQUAL) {
|
||||
c9x.val2 = ersky9xToSource_v11(v2).toValue();
|
||||
}
|
||||
|
||||
if (c9x.func >= LS_FN_AND && c9x.func <= LS_FN_XOR) {
|
||||
c9x.val1 = er9xToSwitch(v1).toValue();
|
||||
c9x.val2 = er9xToSwitch(v2).toValue();
|
||||
}
|
||||
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Ersky9xSafetySwData_v10::t_Ersky9xSafetySwData_v10()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xSafetySwData_v10));
|
||||
}
|
||||
|
||||
t_Ersky9xSafetySwData_v11::t_Ersky9xSafetySwData_v11()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xSafetySwData_v11));
|
||||
}
|
||||
|
||||
t_Ersky9xFrSkyChannelData_v10::t_Ersky9xFrSkyChannelData_v10()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xFrSkyChannelData_v10));
|
||||
}
|
||||
|
||||
t_Ersky9xFrSkyChannelData_v10::operator FrSkyChannelData ()
|
||||
{
|
||||
FrSkyChannelData c9x;
|
||||
c9x.ratio = ratio;
|
||||
c9x.alarms[0].value = alarms_value[0];
|
||||
c9x.alarms[0].level = alarms_level & 3;
|
||||
c9x.alarms[0].greater = alarms_greater & 1;
|
||||
c9x.alarms[1].value = alarms_value[1];
|
||||
c9x.alarms[1].level = (alarms_level >> 2) & 3;
|
||||
c9x.alarms[1].greater = (alarms_greater >> 1) & 1;
|
||||
if (type==2) {
|
||||
c9x.type = 0;
|
||||
c9x.multiplier=1;
|
||||
} else {
|
||||
c9x.type = type;
|
||||
}
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Ersky9xFrSkyChannelData_v11::t_Ersky9xFrSkyChannelData_v11()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xFrSkyChannelData_v11));
|
||||
}
|
||||
|
||||
t_Ersky9xFrSkyChannelData_v11::operator FrSkyChannelData ()
|
||||
{
|
||||
FrSkyChannelData c9x;
|
||||
c9x.ratio = ratio;
|
||||
c9x.alarms[0].value = alarms_value[0];
|
||||
c9x.alarms[0].level = alarms_level & 3;
|
||||
c9x.alarms[0].greater = alarms_greater & 1;
|
||||
c9x.alarms[1].value = alarms_value[1];
|
||||
c9x.alarms[1].level = (alarms_level >> 2) & 3;
|
||||
c9x.alarms[1].greater = (alarms_greater >> 1) & 1;
|
||||
if (type==2) {
|
||||
c9x.type = 0;
|
||||
c9x.multiplier=1;
|
||||
} else {
|
||||
c9x.type = type;
|
||||
}
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Ersky9xFrSkyData_v10::t_Ersky9xFrSkyData_v10()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xFrSkyData_v10));
|
||||
}
|
||||
|
||||
t_Ersky9xFrSkyData_v10::operator FrSkyData ()
|
||||
{
|
||||
FrSkyData c9x;
|
||||
c9x.channels[0] = channels[0];
|
||||
c9x.channels[1] = channels[1];
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Ersky9xFrSkyData_v11::t_Ersky9xFrSkyData_v11()
|
||||
{
|
||||
memset(this, 0, sizeof(t_Ersky9xFrSkyData_v11));
|
||||
}
|
||||
|
||||
t_Ersky9xFrSkyData_v11::operator FrSkyData ()
|
||||
{
|
||||
FrSkyData c9x;
|
||||
c9x.channels[0] = channels[0];
|
||||
c9x.channels[1] = channels[1];
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Ersky9xModelData_v10::operator ModelData ()
|
||||
{
|
||||
ModelData c9x;
|
||||
c9x.used = true;
|
||||
getEEPROMString(c9x.name, name, sizeof(name));
|
||||
for (int i=0; i<2; i++) {
|
||||
c9x.timers[i].mode = getErSky9xTimerMode(timer[i].tmrModeA);
|
||||
c9x.timers[i].val = timer[i].tmrVal;
|
||||
}
|
||||
switch(protocol) {
|
||||
case 1:
|
||||
c9x.moduleData[0].protocol = PULSES_PXX_DJT;
|
||||
break;
|
||||
case 2:
|
||||
c9x.moduleData[0].protocol = PULSES_DSM2;
|
||||
break;
|
||||
case 3:
|
||||
c9x.moduleData[0].protocol = PULSES_PPM16;
|
||||
break;
|
||||
default:
|
||||
c9x.moduleData[0].protocol = PULSES_PPM;
|
||||
break;
|
||||
}
|
||||
c9x.moduleData[0].ppm.frameLength=ppmFrameLength;
|
||||
c9x.moduleData[0].channelsCount = 8 + 2 * ppmNCH;
|
||||
c9x.thrTrim = thrTrim;
|
||||
c9x.trimInc = trimInc-2;
|
||||
c9x.moduleData[0].ppm.delay = 300 + 50 * ppmDelay;
|
||||
c9x.customFn[0].func = FuncInstantTrim;
|
||||
if (trimSw) {
|
||||
c9x.customFn[0].swtch = er9xToSwitch(trimSw);
|
||||
}
|
||||
c9x.beepANACenter = beepANACenter;
|
||||
c9x.moduleData[0].ppm.pulsePol = pulsePol;
|
||||
c9x.extendedLimits = extendedLimits;
|
||||
c9x.swashRingData.elevatorWeight = swashInvertELE ? -100 : 100;
|
||||
c9x.swashRingData.aileronWeight = swashInvertAIL ? -100 : 100;
|
||||
c9x.swashRingData.collectiveWeight = swashInvertCOL ? -100 : 100;
|
||||
c9x.swashRingData.type = swashType;
|
||||
c9x.swashRingData.collectiveSource = ersky9xToSource_v10(swashCollectiveSource);
|
||||
c9x.swashRingData.value = swashRingValue;
|
||||
for (int i=0; i<ERSKY9X_MAX_MIXERS_V10; i++)
|
||||
c9x.mixData[i] = mixData[i];
|
||||
for (int i=0; i<ERSKY9X_NUM_CHNOUT_V10; i++)
|
||||
c9x.limitData[i] = limitData[i];
|
||||
|
||||
// expoData
|
||||
int e = 0;
|
||||
for (int ch = 0; ch < 4 && e < CPN_MAX_EXPOS; ch++) {
|
||||
for (int dr = 0, pos = 0; dr < 3 && e < CPN_MAX_EXPOS; dr++, pos++) {
|
||||
if ((dr == 0 && !expoData[ch].drSw1) || (dr == 1 && !expoData[ch].drSw2))
|
||||
dr = 2;
|
||||
if (dr == 2 && !expoData[ch].expo[0][0][0] && !expoData[ch].expo[0][0][1] && !expoData[ch].expo[0][1][0] && !expoData[ch].expo[0][1][1])
|
||||
break;
|
||||
if (expoData[ch].drSw1 && !expoData[ch].drSw2) {
|
||||
c9x.expoData[e].swtch = er9xToSwitch(dr == 0 ? expoData[ch].drSw1 : 0);
|
||||
pos = dr == 0 ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
c9x.expoData[e].swtch = er9xToSwitch(dr == 0 ? -expoData[ch].drSw1 : (dr == 1 ? -expoData[ch].drSw2 : 0));
|
||||
}
|
||||
c9x.expoData[e].chn = ch;
|
||||
if (expoData[ch].expo[pos][0][0]) {
|
||||
c9x.expoData[e].curve.type = CurveReference::CURVE_REF_EXPO;
|
||||
c9x.expoData[e].curve.value = expoData[ch].expo[pos][0][0];
|
||||
}
|
||||
c9x.expoData[e].weight = 100 + expoData[ch].expo[pos][1][0];
|
||||
if (expoData[ch].expo[pos][0][0] == expoData[ch].expo[pos][0][1] && expoData[ch].expo[pos][1][0] == expoData[ch].expo[pos][1][1]) {
|
||||
c9x.expoData[e++].mode = 3;
|
||||
}
|
||||
else {
|
||||
c9x.expoData[e].mode = 2;
|
||||
if (e < CPN_MAX_EXPOS - 1) {
|
||||
c9x.expoData[e + 1].swtch = c9x.expoData[e].swtch;
|
||||
c9x.expoData[++e].chn = ch;
|
||||
c9x.expoData[e].mode = 1;
|
||||
if (expoData[ch].expo[pos][0][1]) {
|
||||
c9x.expoData[e].curve.type = CurveReference::CURVE_REF_EXPO;
|
||||
c9x.expoData[e].curve.value = expoData[ch].expo[pos][0][1];
|
||||
}
|
||||
c9x.expoData[e++].weight = 100 + expoData[ch].expo[pos][1][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_STICKS; i++)
|
||||
c9x.flightModeData[0].trim[i] = trim[i];
|
||||
|
||||
for (int i=0; i<ERSKY9X_MAX_CURVE5; i++) {
|
||||
c9x.curves[i].count = 5;
|
||||
for (int j = 0; j < 5; j++) {
|
||||
c9x.curves[i].points[j].x = -100 + 50 * i;
|
||||
c9x.curves[i].points[j].y = curves5[i][j];
|
||||
}
|
||||
}
|
||||
for (int i=0; i<ERSKY9X_MAX_CURVE9; i++) {
|
||||
c9x.curves[ERSKY9X_MAX_CURVE5 + i].count = 9;
|
||||
for (int j = 0; j < 9; j++) {
|
||||
c9x.curves[ERSKY9X_MAX_CURVE5 + i].points[j].x = -100 + 25 * i;
|
||||
c9x.curves[ERSKY9X_MAX_CURVE5 + i].points[j].y = curves9[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<ERSKY9X_NUM_CSW_V10; i++)
|
||||
c9x.logicalSw[i] = logicalSw[i];
|
||||
|
||||
// for (int i=0; i<ERSKY9X_NUM_CHNOUT_V10; i++)
|
||||
// c9x.safetySw[i] = safetySw[i];
|
||||
|
||||
c9x.frsky = frsky;
|
||||
c9x.frsky.usrProto=FrSkyUsrProto;
|
||||
return c9x;
|
||||
}
|
||||
|
||||
t_Ersky9xModelData_v11::operator ModelData ()
|
||||
{
|
||||
ModelData c9x;
|
||||
c9x.used = true;
|
||||
getEEPROMString(c9x.name, name, sizeof(name));
|
||||
for (int i=0; i<2; i++) {
|
||||
c9x.timers[i].mode = getErSky9xTimerMode(timer[i].tmrModeA);
|
||||
c9x.timers[i].val = timer[i].tmrVal;
|
||||
}
|
||||
switch(protocol) {
|
||||
case 1:
|
||||
c9x.moduleData[0].protocol = PULSES_PXX_DJT;
|
||||
break;
|
||||
case 2:
|
||||
c9x.moduleData[0].protocol = PULSES_DSM2;
|
||||
break;
|
||||
case 3:
|
||||
c9x.moduleData[0].protocol = PULSES_PPM16;
|
||||
break;
|
||||
default:
|
||||
c9x.moduleData[0].protocol = PULSES_PPM;
|
||||
break;
|
||||
}
|
||||
c9x.moduleData[0].ppm.frameLength=ppmFrameLength;
|
||||
c9x.moduleData[0].channelsCount = 8 + 2 * ppmNCH;
|
||||
c9x.thrTrim = thrTrim;
|
||||
c9x.trimInc = trimInc-2;
|
||||
c9x.moduleData[0].ppm.delay = 300 + 50 * ppmDelay;
|
||||
c9x.customFn[0].func = FuncInstantTrim;
|
||||
if (trimSw) {
|
||||
c9x.customFn[0].swtch = er9xToSwitch(trimSw);
|
||||
}
|
||||
c9x.beepANACenter = beepANACenter;
|
||||
c9x.moduleData[0].ppm.pulsePol = pulsePol;
|
||||
c9x.extendedLimits = extendedLimits;
|
||||
c9x.swashRingData.elevatorWeight = swashInvertELE ? -100 : 100;
|
||||
c9x.swashRingData.aileronWeight = swashInvertAIL ? -100 : 100;
|
||||
c9x.swashRingData.collectiveWeight = swashInvertCOL ? -100 : 100;
|
||||
c9x.swashRingData.type = swashType;
|
||||
c9x.swashRingData.collectiveSource = ersky9xToSource_v11(swashCollectiveSource);
|
||||
c9x.swashRingData.value = swashRingValue;
|
||||
for (int i=0; i<ERSKY9X_MAX_MIXERS_V11; i++)
|
||||
c9x.mixData[i] = mixData[i];
|
||||
for (int i=0; i<ERSKY9X_NUM_CHNOUT_V11; i++)
|
||||
c9x.limitData[i] = limitData[i];
|
||||
|
||||
// expoData
|
||||
int e = 0;
|
||||
for (int ch = 0; ch < 4 && e < CPN_MAX_EXPOS; ch++) {
|
||||
for (int dr = 0, pos = 0; dr < 3 && e < CPN_MAX_EXPOS; dr++, pos++) {
|
||||
if ((dr == 0 && !expoData[ch].drSw1) || (dr == 1 && !expoData[ch].drSw2))
|
||||
dr = 2;
|
||||
if (dr == 2 && !expoData[ch].expo[0][0][0] && !expoData[ch].expo[0][0][1] && !expoData[ch].expo[0][1][0] && !expoData[ch].expo[0][1][1])
|
||||
break;
|
||||
if (expoData[ch].drSw1 && !expoData[ch].drSw2) {
|
||||
c9x.expoData[e].swtch = er9xToSwitch(dr == 0 ? expoData[ch].drSw1 : 0);
|
||||
pos = dr == 0 ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
c9x.expoData[e].swtch = er9xToSwitch(dr == 0 ? -expoData[ch].drSw1 : (dr == 1 ? -expoData[ch].drSw2 : 0));
|
||||
}
|
||||
c9x.expoData[e].chn = ch;
|
||||
if (expoData[ch].expo[pos][0][0]) {
|
||||
c9x.expoData[e].curve.type = CurveReference::CURVE_REF_EXPO;
|
||||
c9x.expoData[e].curve.value = expoData[ch].expo[pos][0][0];
|
||||
}
|
||||
c9x.expoData[e].weight = 100 + expoData[ch].expo[pos][1][0];
|
||||
if (expoData[ch].expo[pos][0][0] == expoData[ch].expo[pos][0][1] && expoData[ch].expo[pos][1][0] == expoData[ch].expo[pos][1][1]) {
|
||||
c9x.expoData[e++].mode = 3;
|
||||
}
|
||||
else {
|
||||
c9x.expoData[e].mode = 2;
|
||||
if (e < CPN_MAX_EXPOS - 1) {
|
||||
c9x.expoData[e + 1].swtch = c9x.expoData[e].swtch;
|
||||
c9x.expoData[++e].chn = ch;
|
||||
c9x.expoData[e].mode = 1;
|
||||
if (expoData[ch].expo[pos][0][1]) {
|
||||
c9x.expoData[e].curve.type = CurveReference::CURVE_REF_EXPO;
|
||||
c9x.expoData[e].curve.value = expoData[ch].expo[pos][0][1];
|
||||
}
|
||||
c9x.expoData[e++].weight = 100 + expoData[ch].expo[pos][1][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_STICKS; i++)
|
||||
c9x.flightModeData[0].trim[i] = trim[i];
|
||||
|
||||
for (int i=0; i<ERSKY9X_MAX_CURVE5; i++) {
|
||||
c9x.curves[i].count = 5;
|
||||
for (int j = 0; j < 5; j++) {
|
||||
c9x.curves[i].points[j].x = -100 + 50 * i;
|
||||
c9x.curves[i].points[j].y = curves5[i][j];
|
||||
}
|
||||
}
|
||||
for (int i=0; i<ERSKY9X_MAX_CURVE9; i++) {
|
||||
c9x.curves[ERSKY9X_MAX_CURVE5 + i].count = 9;
|
||||
for (int j = 0; j < 9; j++) {
|
||||
c9x.curves[ERSKY9X_MAX_CURVE5 + i].points[j].x = -100 + 25 * i;
|
||||
c9x.curves[ERSKY9X_MAX_CURVE5 + i].points[j].y = curves9[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<ERSKY9X_NUM_CSW_V11; i++)
|
||||
c9x.logicalSw[i] = logicalSw[i];
|
||||
|
||||
c9x.frsky = frsky;
|
||||
c9x.frsky.usrProto=FrSkyUsrProto;
|
||||
for (int i=0; i<5;i++) {
|
||||
c9x.flightModeData[0].gvars[i]=gvars[i].gvar;
|
||||
}
|
||||
return c9x;
|
||||
}
|
||||
|
||||
@@ -1,436 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ERSKY9XEEPROM_H_
|
||||
#define _ERSKY9XEEPROM_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "eeprominterface.h"
|
||||
|
||||
extern RawSwitch getEr9xTimerMode(int mode);
|
||||
|
||||
//eeprom data
|
||||
#define ERSKY9X_MAX_MIXERS_V10 32
|
||||
#define ERSKY9X_MAX_MIXERS_V11 48
|
||||
#define ERSKY9X_MAX_CURVE5 8
|
||||
#define ERSKY9X_MAX_CURVE9 8
|
||||
#define ERSKY9X_MAX_CSFUNC 13
|
||||
|
||||
#define ERSKY9X_MDVERS10 10
|
||||
#define ERSKY9X_MDVERS11 11
|
||||
|
||||
#define ERSKY9X_GENERAL_OWNER_NAME_LEN 10
|
||||
#define ERSKY9X_NUM_CHNOUT_V10 16 //number of real outputchannels CH1-CH8
|
||||
#define ERSKY9X_NUM_CHNOUT_V11 24 //number of real outputchannels CH1-CH8
|
||||
#define ERSKY9X_NUM_CSW_V10 12 //number of custom switches
|
||||
#define ERSKY9X_NUM_CSW_V11 24
|
||||
#define ERSKY9X_NUM_FSW 16
|
||||
#define ERSKY9X_NUM_VOICE 8
|
||||
#define ERSKY9X_MAX_GVARS 7
|
||||
|
||||
#define CPN_MAX_STICKSnPOTS 7 //number of sticks and pots
|
||||
|
||||
PACK(typedef struct t_Ersky9xTrainerMix {
|
||||
uint8_t srcChn:3; //0-7 = ch1-8
|
||||
int8_t swtch:5;
|
||||
int8_t studWeight:6;
|
||||
uint8_t mode:2; // off, add-mode, subst-mode
|
||||
|
||||
operator TrainerMix();
|
||||
t_Ersky9xTrainerMix();
|
||||
}) Ersky9xTrainerMix; //
|
||||
|
||||
PACK(typedef struct t_Ersky9xTrainerData {
|
||||
int16_t calib[4];
|
||||
Ersky9xTrainerMix mix[4];
|
||||
|
||||
operator TrainerData();
|
||||
t_Ersky9xTrainerData();
|
||||
}) Ersky9xTrainerData;
|
||||
|
||||
PACK(typedef struct t_Ersky9xGeneral {
|
||||
uint8_t myVers;
|
||||
int16_t calibMid[CPN_MAX_STICKSnPOTS];
|
||||
int16_t calibSpanNeg[CPN_MAX_STICKSnPOTS];
|
||||
int16_t calibSpanPos[CPN_MAX_STICKSnPOTS];
|
||||
uint16_t chkSum;
|
||||
uint8_t currModel; //0..15
|
||||
uint8_t contrast;
|
||||
uint8_t vBatWarn;
|
||||
int8_t txVoltageCalibration;
|
||||
int8_t lightSw;
|
||||
Ersky9xTrainerData trainer;
|
||||
uint8_t view;
|
||||
uint8_t disableThrottleWarning:1;
|
||||
uint8_t disableSwitchWarning:1;
|
||||
uint8_t disableMemoryWarning:1;
|
||||
uint8_t beeperVal:3;
|
||||
uint8_t reserveWarning:1;
|
||||
uint8_t disableAlarmWarning:1;
|
||||
uint8_t stickMode;
|
||||
int8_t inactivityTimer;
|
||||
uint8_t throttleReversed:1;
|
||||
uint8_t minuteBeep:1;
|
||||
uint8_t preBeep:1;
|
||||
uint8_t flashBeep:1;
|
||||
uint8_t disableSplashScreen:1;
|
||||
uint8_t disablePotScroll:1;
|
||||
uint8_t disableBG:1;
|
||||
uint8_t res1:1;
|
||||
uint8_t filterInput;
|
||||
uint8_t lightAutoOff;
|
||||
uint8_t templateSetup; //RETA order according to chout_ar array
|
||||
int8_t PPM_Multiplier;
|
||||
uint8_t FRSkyYellow:4;
|
||||
uint8_t FRSkyOrange:4;
|
||||
uint8_t FRSkyRed:4; //mike please check these are correct
|
||||
uint8_t hideNameOnSplash:1;
|
||||
uint8_t optrexDisplay:1;
|
||||
uint8_t spare:2;
|
||||
uint8_t speakerPitch;
|
||||
uint8_t hapticStrength;
|
||||
uint8_t speakerMode;
|
||||
uint8_t lightOnStickMove;
|
||||
|
||||
char ownerName[10];
|
||||
uint8_t switchWarningStates;
|
||||
uint8_t volume ;
|
||||
uint8_t bright ; // backlight
|
||||
uint8_t stickGain;
|
||||
uint8_t mAh_alarm ;
|
||||
uint16_t mAh_used ;
|
||||
uint16_t run_time ;
|
||||
int8_t current_calib ;
|
||||
uint8_t bt_baudrate ;
|
||||
uint8_t rotaryDivisor ;
|
||||
operator GeneralSettings();
|
||||
t_Ersky9xGeneral();
|
||||
}) Ersky9xGeneral;
|
||||
|
||||
PACK(typedef struct t_Ersky9xExpoData {
|
||||
int8_t expo[3][2][2];
|
||||
int8_t drSw1;
|
||||
int8_t drSw2;
|
||||
|
||||
t_Ersky9xExpoData() { memset(this, 0, sizeof(t_Ersky9xExpoData)); }
|
||||
}) Ersky9xExpoData;
|
||||
|
||||
|
||||
PACK(typedef struct t_Ersky9xLimitData {
|
||||
int8_t min;
|
||||
int8_t max;
|
||||
bool revert;
|
||||
int16_t offset;
|
||||
|
||||
operator LimitData();
|
||||
t_Ersky9xLimitData() ;
|
||||
}) Ersky9xLimitData;
|
||||
|
||||
#define MLTPX_ADD 0
|
||||
#define MLTPX_MUL 1
|
||||
#define MLTPX_REP 2
|
||||
|
||||
PACK(typedef struct t_Ersky9xMixData_v10 {
|
||||
uint8_t destCh; // 1..CPN_MAX_CHNOUT
|
||||
uint8_t srcRaw; //
|
||||
int8_t weight;
|
||||
int8_t swtch;
|
||||
uint8_t curve; //0=symmetrisch 1=no neg 2=no pos
|
||||
uint8_t delayUp:4;
|
||||
uint8_t delayDown:4;
|
||||
uint8_t speedUp:4; // Servogeschwindigkeit aus Tabelle (10ms Cycle)
|
||||
uint8_t speedDown:4; // 0 nichts
|
||||
uint8_t carryTrim:1;
|
||||
uint8_t mltpx:3; // multiplex method 0=+ 1=* 2=replace
|
||||
uint8_t mixWarn:2; // mixer warning
|
||||
uint8_t enableFmTrim:1;
|
||||
uint8_t mixres:1;
|
||||
int8_t sOffset;
|
||||
int8_t res;
|
||||
|
||||
operator MixData();
|
||||
t_Ersky9xMixData_v10();
|
||||
}) Ersky9xMixData_v10;
|
||||
|
||||
PACK(typedef struct t_Ersky9xMixData_v11 {
|
||||
uint8_t destCh; // 1..CPN_MAX_CHNOUT
|
||||
uint8_t srcRaw; //
|
||||
int8_t weight;
|
||||
int8_t swtch;
|
||||
uint8_t curve; //0=symmetrisch 1=no neg 2=no pos
|
||||
uint8_t delayUp;
|
||||
uint8_t delayDown;
|
||||
uint8_t speedUp; // Servogeschwindigkeit aus Tabelle (10ms Cycle)
|
||||
uint8_t speedDown; // 0 nichts
|
||||
uint8_t carryTrim:1;
|
||||
uint8_t mltpx:3; // multiplex method 0=+ 1=* 2=replace
|
||||
uint8_t mixWarn:2; // mixer warning
|
||||
uint8_t enableFmTrim:1;
|
||||
uint8_t mixres:1;
|
||||
int8_t sOffset;
|
||||
uint8_t res[4];
|
||||
operator MixData();
|
||||
t_Ersky9xMixData_v11();
|
||||
}) Ersky9xMixData_v11;
|
||||
|
||||
PACK(typedef struct t_Ersky9xLogicalSwitchData_v10 { // Custom Switches data
|
||||
int8_t v1; //input
|
||||
int8_t v2; //offset
|
||||
uint8_t func;
|
||||
|
||||
operator LogicalSwitchData();
|
||||
t_Ersky9xLogicalSwitchData_v10() { memset(this, 0, sizeof(t_Ersky9xLogicalSwitchData_v10)); }
|
||||
}) Ersky9xLogicalSwitchData_v10;
|
||||
|
||||
PACK(typedef struct t_Ersky9xLogicalSwitchData_v11 { // Custom Switches data
|
||||
int8_t v1; //input
|
||||
int8_t v2; //offset
|
||||
uint8_t func;
|
||||
uint8_t andsw;
|
||||
uint8_t res ;
|
||||
|
||||
operator LogicalSwitchData();
|
||||
t_Ersky9xLogicalSwitchData_v11() { memset(this, 0, sizeof(t_Ersky9xLogicalSwitchData_v11)); }
|
||||
}) Ersky9xLogicalSwitchData_v11;
|
||||
|
||||
PACK(typedef struct t_Ersky9xSafetySwData_v10 { // Custom Switches data
|
||||
int8_t swtch;
|
||||
int8_t val;
|
||||
|
||||
t_Ersky9xSafetySwData_v10();
|
||||
}) Ersky9xSafetySwData_v10;
|
||||
|
||||
PACK(typedef struct t_Ersky9xSafetySwData_v11 { // Custom Switches data
|
||||
union opt {
|
||||
struct ss {
|
||||
int8_t swtch ;
|
||||
uint8_t mode ;
|
||||
int8_t val ;
|
||||
uint8_t res ;
|
||||
} ss ;
|
||||
struct vs {
|
||||
uint8_t vswtch ;
|
||||
uint8_t vmode ; // ON, OFF, BOTH, 15Secs, 30Secs, 60Secs, Varibl
|
||||
uint8_t vval;
|
||||
uint8_t vres ;
|
||||
} vs ;
|
||||
} opt ;
|
||||
|
||||
t_Ersky9xSafetySwData_v11();
|
||||
}) Ersky9xSafetySwData_v11;
|
||||
|
||||
PACK(typedef struct t_Ersky9xgvar {
|
||||
int8_t gvar ;
|
||||
uint8_t gvsource ;
|
||||
// int8_t gvswitch ;
|
||||
}) Ersky9xGvarData ;
|
||||
|
||||
PACK(typedef struct t_Ersky9xFlightModeData {
|
||||
int16_t trim[4]; // -500..500 => trim value, 501 => use trim of phase 0, 502, 503, 504 => use trim of phases 1|2|3|4 instead
|
||||
int8_t swtch; // swtch of phase[0] is not used
|
||||
char name[6];
|
||||
uint8_t fadeIn:4;
|
||||
uint8_t fadeOut:4;
|
||||
uint16_t spare ; // Future expansion
|
||||
}) Ersky9xFlightModeData;
|
||||
|
||||
PACK(typedef struct t_Ersky9xCustomFunctionData { // Function Switches data
|
||||
int8_t swtch; //input
|
||||
uint8_t func;
|
||||
char param[6];
|
||||
uint8_t delay;
|
||||
uint8_t spare;
|
||||
}) Ersky9xCustomFunctionData;
|
||||
|
||||
PACK(typedef struct t_Ersky9xFrSkyChannelData_v10 {
|
||||
uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
|
||||
uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
|
||||
uint8_t alarms_level:4;
|
||||
uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>)
|
||||
uint8_t type:2; // future use: 0=volts, ...
|
||||
|
||||
operator FrSkyChannelData();
|
||||
t_Ersky9xFrSkyChannelData_v10();
|
||||
}) Ersky9xFrSkyChannelData_v10;
|
||||
|
||||
PACK(typedef struct t_Ersky9xFrSkyData_v10 {
|
||||
Ersky9xFrSkyChannelData_v10 channels[2];
|
||||
|
||||
operator FrSkyData();
|
||||
t_Ersky9xFrSkyData_v10();
|
||||
}) Ersky9xFrSkyData_v10;
|
||||
|
||||
PACK(typedef struct t_Ersky9xFrSkyChannelData_v11 {
|
||||
uint8_t ratio ; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
|
||||
uint8_t offset ; //
|
||||
uint8_t gain ; //
|
||||
uint8_t alarms_value[2] ; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
|
||||
uint8_t alarms_level ;
|
||||
uint8_t alarms_greater ; // 0=LT(<), 1=GT(>)
|
||||
uint8_t type ; // 0=volts, 1=raw, 2=volts*2, 3=Amps
|
||||
|
||||
operator FrSkyChannelData();
|
||||
t_Ersky9xFrSkyChannelData_v11();
|
||||
}) Ersky9xFrSkyChannelData_v11;
|
||||
|
||||
PACK(typedef struct t_Ersky9xFrSkyData_v11 {
|
||||
Ersky9xFrSkyChannelData_v11 channels[2];
|
||||
|
||||
operator FrSkyData();
|
||||
t_Ersky9xFrSkyData_v11();
|
||||
}) Ersky9xFrSkyData_v11;
|
||||
|
||||
PACK(typedef struct t_Ersky9xFrSkyalarms_v11 {
|
||||
uint8_t frskyAlarmType ;
|
||||
uint8_t frskyAlarmLimit ;
|
||||
uint8_t frskyAlarmSound ;
|
||||
}) Ersky9xFrSkyAlData_v11;
|
||||
|
||||
PACK(typedef struct t_Ersky9xFrSkyAlarmData_v11 {
|
||||
Ersky9xFrSkyAlData_v11 alarmData[8] ;
|
||||
}) Ersky9xFrSkyAlarmData_v11;
|
||||
|
||||
PACK(typedef struct t_Ersky9xTimerMode_v10 {
|
||||
uint8_t tmrModeA:7 ; // timer trigger source -> off, abs, stk, stk%, cx%
|
||||
uint8_t tmrDir:1 ; // Timer direction
|
||||
int8_t tmrModeB ; // timer trigger source -> !sw, none, sw, m_sw
|
||||
uint16_t tmrVal ;
|
||||
}) Ersky9xTimerMode_v10;
|
||||
|
||||
PACK(typedef struct t_Ersky9xTimerMode_v11 {
|
||||
uint8_t tmrModeA:7 ; // timer trigger source -> off, abs, stk, stk%, cx%
|
||||
uint8_t tmrDir:1 ; // Timer direction
|
||||
int8_t tmrModeB ; // timer trigger source -> !sw, none, sw, m_sw
|
||||
uint16_t tmrVal ;
|
||||
}) Ersky9xTimerMode_v11;
|
||||
|
||||
PACK(typedef struct te_Ersky9xswVoice {
|
||||
uint8_t swtch ;
|
||||
uint8_t mode ; // ON, OFF, BOTH, 15Secs, 30Secs, 60Secs
|
||||
uint8_t val ;
|
||||
uint8_t vres ;
|
||||
}) Ersky9xvoiceSwData ;
|
||||
|
||||
PACK(typedef struct t_Ersky9xModelData_v10 {
|
||||
char name[10]; // 10 must be first for eeLoadModelName
|
||||
uint8_t reserved_spare; //used to be MDVERS - now depreciated
|
||||
int8_t spare21; // was timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
|
||||
// uint8_t sparex:1; // was tmrDir, now use tmrVal>0 => count down
|
||||
uint8_t sparex:1; // was tmrDir, now use tmrVal>0 => count down
|
||||
// uint8_t tmrDir:1; // was tmrDir, now use tmrVal>0 => count down
|
||||
uint8_t traineron:1; // 0 disable trainer, 1 allow trainer
|
||||
uint8_t spare22:1 ; // Start timer2 using throttle
|
||||
uint8_t FrSkyUsrProto:1 ; // Protocol in FrSky User Data, 0=FrSky Hub, 1=WS HowHigh
|
||||
uint8_t FrSkyGpsAlt:1 ; // Use Gps Altitude as main altitude reading
|
||||
uint8_t FrSkyImperial:1 ; // Convert FrSky values to imperial units
|
||||
uint8_t FrSkyAltAlarm:2;
|
||||
uint16_t spare_u16 ; // Was timerval
|
||||
uint8_t protocol;
|
||||
int8_t ppmNCH;
|
||||
int8_t thrTrim:4; // Enable Throttle Trim
|
||||
int8_t thrExpo:4; // Enable Throttle Expo
|
||||
int8_t trimInc; // Trim Increments
|
||||
int8_t ppmDelay;
|
||||
int8_t trimSw;
|
||||
uint8_t beepANACenter; // 1<<0->A1.. 1<<6->A7
|
||||
uint8_t pulsePol:1;
|
||||
uint8_t extendedLimits:1;
|
||||
uint8_t swashInvertELE:1;
|
||||
uint8_t swashInvertAIL:1;
|
||||
uint8_t swashInvertCOL:1;
|
||||
uint8_t swashType:3;
|
||||
uint8_t swashCollectiveSource;
|
||||
uint8_t swashRingValue;
|
||||
int8_t ppmFrameLength; //0=22.5 (10msec-30msec) 0.5msec increments
|
||||
Ersky9xMixData_v10 mixData[ERSKY9X_MAX_MIXERS_V10];
|
||||
Ersky9xLimitData limitData[ERSKY9X_NUM_CHNOUT_V10];
|
||||
Ersky9xExpoData expoData[4];
|
||||
int8_t trim[4];
|
||||
int8_t curves5[ERSKY9X_MAX_CURVE5][5];
|
||||
int8_t curves9[ERSKY9X_MAX_CURVE9][9];
|
||||
Ersky9xLogicalSwitchData_v10 logicalSw[ERSKY9X_NUM_CSW_V10];
|
||||
uint8_t frSkyVoltThreshold ;
|
||||
uint8_t res3[2];
|
||||
Ersky9xSafetySwData_v10 safetySw[ERSKY9X_NUM_CHNOUT_V10];
|
||||
Ersky9xFrSkyData_v10 frsky;
|
||||
Ersky9xTimerMode_v10 timer[2] ;
|
||||
operator ModelData();
|
||||
t_Ersky9xModelData_v10() { memset(this, 0, sizeof(t_Ersky9xModelData_v10)); }
|
||||
}) Ersky9xModelData_v10;
|
||||
|
||||
PACK(typedef struct t_Ersky9xModelData_v11 {
|
||||
char name[10]; // 10 must be first for eeLoadModelName
|
||||
uint8_t modelVoice ; // Index to model name voice (261+value)
|
||||
uint8_t RxNum ; // was timer trigger source, now RxNum for model match
|
||||
uint8_t sparex:1; // was tmrDir, now use tmrVal>0 => count down
|
||||
uint8_t traineron:1; // 0 disable trainer, 1 allow trainer
|
||||
uint8_t spare22:1 ; // Start timer2 using throttle
|
||||
uint8_t FrSkyUsrProto:1 ; // Protocol in FrSky User Data, 0=FrSky Hub, 1=WS HowHigh
|
||||
uint8_t FrSkyGpsAlt:1 ; // Use Gps Altitude as main altitude reading
|
||||
uint8_t FrSkyImperial:1 ; // Convert FrSky values to imperial units
|
||||
uint8_t FrSkyAltAlarm:2;
|
||||
uint8_t version ;
|
||||
uint8_t protocol;
|
||||
int8_t ppmNCH;
|
||||
uint8_t thrTrim:1; // Enable Throttle Trim
|
||||
uint8_t numBlades:2; // RPM scaling
|
||||
uint8_t spare10:1;
|
||||
uint8_t thrExpo:1; // Enable Throttle Expo
|
||||
uint8_t spare11:3;
|
||||
int8_t trimInc; // Trim Increments
|
||||
int8_t ppmDelay;
|
||||
int8_t trimSw;
|
||||
uint8_t beepANACenter; // 1<<0->A1.. 1<<6->A7
|
||||
uint8_t pulsePol:1;
|
||||
uint8_t extendedLimits:1;
|
||||
uint8_t swashInvertELE:1;
|
||||
uint8_t swashInvertAIL:1;
|
||||
uint8_t swashInvertCOL:1;
|
||||
uint8_t swashType:3;
|
||||
uint8_t swashCollectiveSource;
|
||||
uint8_t swashRingValue;
|
||||
int8_t ppmFrameLength; //0=22.5 (10msec-30msec) 0.5msec increments
|
||||
Ersky9xMixData_v11 mixData[ERSKY9X_MAX_MIXERS_V11];
|
||||
Ersky9xLimitData limitData[ERSKY9X_NUM_CHNOUT_V11];
|
||||
Ersky9xExpoData expoData[4];
|
||||
int8_t trim[4];
|
||||
int8_t curves5[ERSKY9X_MAX_CURVE5][5];
|
||||
int8_t curves9[ERSKY9X_MAX_CURVE9][9];
|
||||
int8_t curvexy[18];
|
||||
Ersky9xLogicalSwitchData_v11 logicalSw[ERSKY9X_NUM_CSW_V11];
|
||||
uint8_t frSkyVoltThreshold ;
|
||||
uint8_t bt_telemetry;
|
||||
uint8_t numVoice; // 0-16, rest are Safety switches
|
||||
Ersky9xSafetySwData_v11 safetySw[ERSKY9X_NUM_CHNOUT_V11];
|
||||
Ersky9xvoiceSwData voiceSwitches[ERSKY9X_NUM_VOICE] ;
|
||||
Ersky9xFrSkyData_v11 frsky;
|
||||
Ersky9xTimerMode_v11 timer[2] ;
|
||||
Ersky9xFrSkyAlarmData_v11 frskyAlarms ;
|
||||
// Add 6 bytes for custom telemetry screen
|
||||
uint8_t customDisplayIndex[6] ;
|
||||
Ersky9xCustomFunctionData customFn[ERSKY9X_NUM_FSW];
|
||||
Ersky9xFlightModeData flightModeData[6] ;
|
||||
Ersky9xGvarData gvars[ERSKY9X_MAX_GVARS] ;
|
||||
|
||||
operator ModelData();
|
||||
t_Ersky9xModelData_v11() { memset(this, 0, sizeof(t_Ersky9xModelData_v11)); }
|
||||
}) Ersky9xModelData_v11;
|
||||
|
||||
#endif // _ERSKY9XEEPROM_H_
|
||||
@@ -1,389 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ersky9xinterface.h"
|
||||
#include "ersky9xeeprom.h"
|
||||
#include "rlefile.h"
|
||||
#include <iostream>
|
||||
#include <bitset>
|
||||
|
||||
#define FILE_TYP_GENERAL 1
|
||||
#define FILE_TYP_MODEL 2
|
||||
|
||||
/// fileId of general file
|
||||
#define FILE_GENERAL 0
|
||||
/// convert model number 0..MAX_MODELS-1 int fileId
|
||||
#define FILE_MODEL(n) (1+n)
|
||||
#define FILE_TMP (1+16)
|
||||
|
||||
Ersky9xInterface::Ersky9xInterface():
|
||||
EEPROMInterface(Board::BOARD_SKY9X),
|
||||
efile(new RleFile())
|
||||
{
|
||||
}
|
||||
|
||||
Ersky9xInterface::~Ersky9xInterface()
|
||||
{
|
||||
delete efile;
|
||||
}
|
||||
|
||||
const char * Ersky9xInterface::getName()
|
||||
{
|
||||
return "Ersky9x";
|
||||
}
|
||||
|
||||
inline void applyStickModeToModel(Ersky9xModelData_v10 & model, unsigned int mode)
|
||||
{
|
||||
for (int i=0; i<2; i++) {
|
||||
int stick = applyStickMode(i+1, mode) - 1;
|
||||
{
|
||||
int tmp = model.trim[i];
|
||||
model.trim[i] = model.trim[stick];
|
||||
model.trim[stick] = tmp;
|
||||
}
|
||||
{
|
||||
Ersky9xExpoData tmp = model.expoData[i];
|
||||
model.expoData[i] = model.expoData[stick];
|
||||
model.expoData[stick] = tmp;
|
||||
}
|
||||
}
|
||||
for (int i=0; i<ERSKY9X_MAX_MIXERS_V10; i++)
|
||||
model.mixData[i].srcRaw = applyStickMode(model.mixData[i].srcRaw, mode);
|
||||
for (int i=0; i<ERSKY9X_NUM_CSW_V10; i++) {
|
||||
switch (LogicalSwitchData(model.logicalSw[i].func).getFunctionFamily()) {
|
||||
case LS_FAMILY_VCOMP:
|
||||
model.logicalSw[i].v2 = applyStickMode(model.logicalSw[i].v2, mode);
|
||||
// no break
|
||||
case LS_FAMILY_VOFS:
|
||||
model.logicalSw[i].v1 = applyStickMode(model.logicalSw[i].v1, mode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
model.swashCollectiveSource = applyStickMode(model.swashCollectiveSource, mode);
|
||||
}
|
||||
|
||||
inline void applyStickModeToModel(Ersky9xModelData_v11 & model, unsigned int mode)
|
||||
{
|
||||
for (int i=0; i<2; i++) {
|
||||
int stick = applyStickMode(i+1, mode) - 1;
|
||||
{
|
||||
int tmp = model.trim[i];
|
||||
model.trim[i] = model.trim[stick];
|
||||
model.trim[stick] = tmp;
|
||||
}
|
||||
{
|
||||
Ersky9xExpoData tmp = model.expoData[i];
|
||||
model.expoData[i] = model.expoData[stick];
|
||||
model.expoData[stick] = tmp;
|
||||
}
|
||||
}
|
||||
for (int i=0; i<ERSKY9X_MAX_MIXERS_V11; i++)
|
||||
model.mixData[i].srcRaw = applyStickMode(model.mixData[i].srcRaw, mode);
|
||||
for (int i=0; i<ERSKY9X_NUM_CSW_V11; i++) {
|
||||
switch (LogicalSwitchData(model.logicalSw[i].func).getFunctionFamily()) {
|
||||
case LS_FAMILY_VCOMP:
|
||||
model.logicalSw[i].v2 = applyStickMode(model.logicalSw[i].v2, mode);
|
||||
// no break
|
||||
case LS_FAMILY_VOFS:
|
||||
model.logicalSw[i].v1 = applyStickMode(model.logicalSw[i].v1, mode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
model.swashCollectiveSource = applyStickMode(model.swashCollectiveSource, mode);
|
||||
}
|
||||
|
||||
#if 0
|
||||
unsigned long Ersky9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
|
||||
{
|
||||
QDebug dbg = qDebug();
|
||||
dbg.setAutoInsertSpaces(false);
|
||||
dbg << "trying ersky9x xml import... ";
|
||||
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
Ersky9xGeneral ersky9xGeneral;
|
||||
memset(&ersky9xGeneral,0,sizeof(ersky9xGeneral));
|
||||
if(!loadRadioSettingsDataXML(&doc, &ersky9xGeneral)) {
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
else {
|
||||
radioData.generalSettings=ersky9xGeneral;
|
||||
dbg << "version " << (unsigned int)ersky9xGeneral.myVers << " ";
|
||||
}
|
||||
for(int i=0; i<getCapability(Models); i++) {
|
||||
if (ersky9xGeneral.myVers == 10) {
|
||||
if (!loadModelDataXML<Ersky9xModelData_v10>(&doc, &radioData.models[i], i, radioData.generalSettings.stickMode+1)) {
|
||||
dbg << "ko";
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!loadModelDataXML<Ersky9xModelData_v11>(&doc, &radioData.models[i], i, radioData.generalSettings.stickMode+1)) {
|
||||
dbg << "ko";
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
}
|
||||
}
|
||||
dbg << "ok";
|
||||
errors.set(ALL_OK);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long Ersky9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
|
||||
{
|
||||
QDebug dbg = qDebug();
|
||||
dbg.setAutoInsertSpaces(false);
|
||||
dbg << "trying ersky9x import... ";
|
||||
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
if (size != Boards::getEEpromSize(Board::BOARD_SKY9X)) {
|
||||
dbg << "wrong size";
|
||||
errors.set(WRONG_SIZE);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
if (!efile->EeFsOpen((uint8_t *)eeprom, size, Board::BOARD_SKY9X)) {
|
||||
dbg << "wrong file system";
|
||||
errors.set(WRONG_FILE_SYSTEM);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
efile->openRd(FILE_GENERAL);
|
||||
Ersky9xGeneral ersky9xGeneral;
|
||||
|
||||
if (efile->readRlc2((uint8_t*)&ersky9xGeneral, 1) != 1) {
|
||||
dbg << "no";
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
dbg << "version " << (unsigned int)ersky9xGeneral.myVers << " ";
|
||||
|
||||
switch(ersky9xGeneral.myVers) {
|
||||
case 10:
|
||||
break;
|
||||
case 11:
|
||||
break;
|
||||
default:
|
||||
dbg << "not ersky9x";
|
||||
errors.set(NOT_ERSKY9X);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
efile->openRd(FILE_GENERAL);
|
||||
if (!efile->readRlc2((uint8_t*)&ersky9xGeneral, sizeof(Ersky9xGeneral))) {
|
||||
dbg << "ko";
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
radioData.generalSettings = ersky9xGeneral;
|
||||
|
||||
for (int i=0; i<getCapability(Models); i++) {
|
||||
uint8_t buffer[4096];
|
||||
uint size;
|
||||
memset(buffer,0,sizeof(buffer));
|
||||
efile->openRd(FILE_MODEL(i));
|
||||
|
||||
// if (!efile->readRlc2((uint8_t*)&ersky9xModel, sizeof(Ersky9xModelData))) {
|
||||
size = efile->readRlc2(buffer, 4096);
|
||||
if (!size) {
|
||||
radioData.models[i].clear();
|
||||
}
|
||||
else {
|
||||
if (size<720) {
|
||||
Ersky9xModelData_v10 ersky9xModel;
|
||||
memcpy(&ersky9xModel, buffer, sizeof(ersky9xModel));
|
||||
applyStickModeToModel(ersky9xModel, radioData.generalSettings.stickMode+1);
|
||||
radioData.models[i] = ersky9xModel;
|
||||
} else {
|
||||
Ersky9xModelData_v11 ersky9xModel;
|
||||
memcpy(&ersky9xModel, buffer, sizeof(ersky9xModel));
|
||||
applyStickModeToModel(ersky9xModel, radioData.generalSettings.stickMode+1);
|
||||
radioData.models[i] = ersky9xModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbg << "ok";
|
||||
errors.set(ALL_OK);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
unsigned long Ersky9xInterface::loadBackup(RadioData &radioData, const uint8_t *eeprom, int esize, int index)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
int Ersky9xInterface::getSize(const ModelData & model)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Ersky9xInterface::getSize(const GeneralSettings & settings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Ersky9xInterface::isAvailable(PulsesProtocol prot, int port)
|
||||
{
|
||||
switch (prot) {
|
||||
case PULSES_PPM:
|
||||
case PULSES_DSM2:
|
||||
case PULSES_PXX_DJT:
|
||||
case PULSES_PPM16:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Ersky9xInterface::appendTextElement(QDomDocument * qdoc, QDomElement * pe, QString name, QString value)
|
||||
{
|
||||
QDomElement e = qdoc->createElement(name);
|
||||
QDomText t = qdoc->createTextNode(name);
|
||||
t.setNodeValue(value);
|
||||
e.appendChild(t);
|
||||
pe->appendChild(e);
|
||||
}
|
||||
|
||||
void Ersky9xInterface::appendNumberElement(QDomDocument * qdoc, QDomElement * pe,QString name, int value, bool forceZeroWrite)
|
||||
{
|
||||
if(value || forceZeroWrite) {
|
||||
QDomElement e = qdoc->createElement(name);
|
||||
QDomText t = qdoc->createTextNode(name);
|
||||
t.setNodeValue(QString("%1").arg(value));
|
||||
e.appendChild(t);
|
||||
pe->appendChild(e);
|
||||
}
|
||||
}
|
||||
|
||||
void Ersky9xInterface::appendCDATAElement(QDomDocument * qdoc, QDomElement * pe,QString name, const char * data, int size)
|
||||
{
|
||||
QDomElement e = qdoc->createElement(name);
|
||||
QDomCDATASection t = qdoc->createCDATASection(name);
|
||||
t.setData(QByteArray(data, size).toBase64());
|
||||
e.appendChild(t);
|
||||
pe->appendChild(e);
|
||||
}
|
||||
|
||||
QDomElement Ersky9xInterface::getGeneralDataXML(QDomDocument * qdoc, Ersky9xGeneral * tgen)
|
||||
{
|
||||
QDomElement gd = qdoc->createElement("GENERAL_DATA");
|
||||
appendNumberElement(qdoc, &gd, "Version", tgen->myVers, true); // have to write value here
|
||||
appendTextElement(qdoc, &gd, "Owner", QString::fromLatin1(tgen->ownerName,sizeof(tgen->ownerName)).trimmed());
|
||||
appendCDATAElement(qdoc, &gd, "Data", (const char *)tgen,sizeof(Ersky9xGeneral));
|
||||
return gd;
|
||||
}
|
||||
|
||||
QDomElement Ersky9xInterface::getModelDataXML(QDomDocument * qdoc, Ersky9xModelData_v11 * tmod, int modelNum, int mdver)
|
||||
{
|
||||
QDomElement md = qdoc->createElement("MODEL_DATA");
|
||||
md.setAttribute("number", modelNum);
|
||||
appendNumberElement(qdoc, &md, "Version", mdver, true); // have to write value here
|
||||
appendTextElement(qdoc, &md, "Name", QString::fromLatin1(tmod->name,sizeof(tmod->name)).trimmed());
|
||||
appendCDATAElement(qdoc, &md, "Data", (const char *)tmod,sizeof(Ersky9xModelData_v11));
|
||||
return md;
|
||||
}
|
||||
|
||||
bool Ersky9xInterface::loadRadioSettingsDataXML(QDomDocument * qdoc, Ersky9xGeneral * tgen)
|
||||
{
|
||||
// look for "GENERAL_DATA" tag
|
||||
QDomElement gde = qdoc->elementsByTagName("GENERAL_DATA").at(0).toElement();
|
||||
|
||||
if(gde.isNull()) // couldn't find
|
||||
return false;
|
||||
|
||||
// load cdata into tgen
|
||||
QDomNode n = gde.elementsByTagName("Data").at(0).firstChild();// get all children in Data
|
||||
while (!n.isNull()) {
|
||||
if (n.isCDATASection()) {
|
||||
QString ds = n.toCDATASection().data();
|
||||
QByteArray ba = QByteArray::fromBase64(ds.toLatin1());
|
||||
const char * data = ba.data();
|
||||
memcpy(tgen, data, std::min((unsigned int)ba.size(), (unsigned int)sizeof(Ersky9xGeneral)));
|
||||
break;
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
// check version?
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool Ersky9xInterface::loadModelDataXML(QDomDocument * qdoc, ModelData *model, int modelNum, int stickMode)
|
||||
{
|
||||
T ersky9xModel;
|
||||
memset(&ersky9xModel, 0, sizeof(ersky9xModel));
|
||||
|
||||
// look for MODEL_DATA with modelNum attribute.
|
||||
//if modelNum = -1 then just pick the first one
|
||||
QDomNodeList ndl = qdoc->elementsByTagName("MODEL_DATA");
|
||||
|
||||
// cycle through nodes to find correct model number
|
||||
QDomNode k = ndl.at(0);
|
||||
if (modelNum>=0) {
|
||||
while(!k.isNull()) {
|
||||
int a = k.toElement().attribute("number").toInt();
|
||||
if(a==modelNum)
|
||||
break;
|
||||
k = k.nextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
if (k.isNull()) // couldn't find
|
||||
return false;
|
||||
|
||||
// load cdata into tgen
|
||||
QDomNode n = k.toElement().elementsByTagName("Data").at(0).firstChild();// get all children in Data
|
||||
while (!n.isNull()) {
|
||||
if (n.isCDATASection()) {
|
||||
QString ds = n.toCDATASection().data();
|
||||
QByteArray ba = QByteArray::fromBase64(ds.toLatin1());
|
||||
const char * data = ba.data();
|
||||
memcpy(&ersky9xModel, data, std::min(ba.size(), (int)sizeof(ersky9xModel)));
|
||||
break;
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
|
||||
applyStickModeToModel(ersky9xModel, stickMode);
|
||||
*model = ersky9xModel;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Ersky9xInterface::getCapability(Capability capability)
|
||||
{
|
||||
switch (capability) {
|
||||
case Models:
|
||||
return 20;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ERSKY9XINTERFACE_H_
|
||||
#define _ERSKY9XINTERFACE_H_
|
||||
|
||||
#include <QtXml>
|
||||
#include "eeprominterface.h"
|
||||
#include "ersky9xeeprom.h"
|
||||
|
||||
class RleFile;
|
||||
|
||||
class Ersky9xInterface : public EEPROMInterface
|
||||
{
|
||||
public:
|
||||
|
||||
Ersky9xInterface();
|
||||
|
||||
virtual ~Ersky9xInterface();
|
||||
|
||||
virtual const char * getName();
|
||||
|
||||
|
||||
virtual unsigned long load(RadioData &, const uint8_t * eeprom, int size);
|
||||
|
||||
virtual unsigned long loadBackup(RadioData &, const uint8_t * eeprom, int esize, int index);
|
||||
|
||||
virtual int save(uint8_t * eeprom, const RadioData & radioData, uint8_t version=0, uint32_t variant=0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int getSize(const ModelData &);
|
||||
|
||||
virtual int getSize(const GeneralSettings & settings);
|
||||
|
||||
virtual int isAvailable(PulsesProtocol proto, int port=0);
|
||||
|
||||
virtual int getCapability(Capability capability);
|
||||
|
||||
protected:
|
||||
|
||||
RleFile * efile;
|
||||
|
||||
private:
|
||||
void appendTextElement(QDomDocument * qdoc, QDomElement * pe, QString name, QString value);
|
||||
|
||||
void appendNumberElement(QDomDocument * qdoc, QDomElement * pe,QString name, int value, bool forceZeroWrite = false);
|
||||
|
||||
void appendCDATAElement(QDomDocument * qdoc, QDomElement * pe,QString name, const char * data, int size);
|
||||
|
||||
QDomElement getGeneralDataXML(QDomDocument * qdoc, Ersky9xGeneral * tgen); //parse out data to XML format
|
||||
|
||||
QDomElement getModelDataXML(QDomDocument * qdoc, Ersky9xModelData_v11 * tmod, int modelNum, int mdver); //parse out data to XML format
|
||||
|
||||
bool loadRadioSettingsDataXML(QDomDocument * qdoc, Ersky9xGeneral * tgen); // get data from XML
|
||||
|
||||
template <class T>
|
||||
bool loadModelDataXML(QDomDocument * qdoc, ModelData * model, int modelNum, int stickMode); // get data from XML
|
||||
|
||||
};
|
||||
|
||||
#endif // _ERSKY9XINTERFACE_H_
|
||||
@@ -1,353 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "generalsettings.h"
|
||||
|
||||
#include "appdata.h"
|
||||
#include "eeprominterface.h"
|
||||
#include "radiodataconversionstate.h"
|
||||
|
||||
const uint8_t chout_ar[] = { // First number is 0..23 -> template setup, Second is relevant channel out
|
||||
1,2,3,4 , 1,2,4,3 , 1,3,2,4 , 1,3,4,2 , 1,4,2,3 , 1,4,3,2,
|
||||
2,1,3,4 , 2,1,4,3 , 2,3,1,4 , 2,3,4,1 , 2,4,1,3 , 2,4,3,1,
|
||||
3,1,2,4 , 3,1,4,2 , 3,2,1,4 , 3,2,4,1 , 3,4,1,2 , 3,4,2,1,
|
||||
4,1,2,3 , 4,1,3,2 , 4,2,1,3 , 4,2,3,1 , 4,3,1,2 , 4,3,2,1
|
||||
};
|
||||
|
||||
bool GeneralSettings::switchPositionAllowedTaranis(int index) const
|
||||
{
|
||||
if (index == 0)
|
||||
return true;
|
||||
|
||||
div_t qr = div(abs(index)-1, 3);
|
||||
|
||||
if (index < 0 && switchConfig[qr.quot] != Board::SWITCH_3POS)
|
||||
return false;
|
||||
else if (qr.rem == 1)
|
||||
return switchConfig[qr.quot] == Board::SWITCH_3POS;
|
||||
else
|
||||
return switchConfig[qr.quot] != Board::SWITCH_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
bool GeneralSettings::switchSourceAllowedTaranis(int index) const
|
||||
{
|
||||
return switchConfig[index] != Board::SWITCH_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
bool GeneralSettings::isPotAvailable(int index) const
|
||||
{
|
||||
if (index<0 || index>getBoardCapability(getCurrentBoard(), Board::Pots)) return false;
|
||||
return potConfig[index] != Board::POT_NONE;
|
||||
}
|
||||
|
||||
bool GeneralSettings::isSliderAvailable(int index) const
|
||||
{
|
||||
if (index<0 || index>getBoardCapability(getCurrentBoard(), Board::Sliders)) return false;
|
||||
return sliderConfig[index] != Board::SLIDER_NONE;
|
||||
}
|
||||
|
||||
GeneralSettings::GeneralSettings()
|
||||
{
|
||||
memset(this, 0, sizeof(GeneralSettings));
|
||||
|
||||
contrast = 25;
|
||||
|
||||
for (int i=0; i < CPN_MAX_ANALOGS; ++i) {
|
||||
calibMid[i] = 0x200;
|
||||
calibSpanNeg[i] = 0x180;
|
||||
calibSpanPos[i] = 0x180;
|
||||
}
|
||||
|
||||
Firmware * firmware = Firmware::getCurrentVariant();
|
||||
Board::Type board = firmware->getBoard();
|
||||
|
||||
// vBatWarn is voltage in 100mV, vBatMin is in 100mV but with -9V offset, vBatMax has a -12V offset
|
||||
vBatWarn = 90;
|
||||
if (IS_TARANIS_X9E(board) || IS_HORUS_X12S(board)) {
|
||||
// NI-MH 9.6V
|
||||
vBatWarn = 87;
|
||||
vBatMin = -5; //8,5V
|
||||
vBatMax = -5; //11,5V
|
||||
}
|
||||
else if (IS_TARANIS_XLITE(board) || IS_HORUS_X10(board)) {
|
||||
// Lipo 2S
|
||||
vBatWarn = 66;
|
||||
vBatMin = -23; // 6.7V
|
||||
vBatMax = -37; // 8.3V
|
||||
}
|
||||
else if (IS_TARANIS(board)) {
|
||||
// NI-MH 7.2V, X9D, X9D+ and X7
|
||||
vBatWarn = 65;
|
||||
vBatMin = -30; //6V
|
||||
vBatMax = -40; //8V
|
||||
}
|
||||
|
||||
setDefaultControlTypes(board);
|
||||
|
||||
backlightMode = 3; // keys and sticks
|
||||
// backlightBright = 0; // 0 = 100%
|
||||
|
||||
if (IS_HORUS(board)) {
|
||||
backlightOffBright = 20;
|
||||
}
|
||||
|
||||
if (IS_ARM(board)) {
|
||||
speakerVolume = 12;
|
||||
}
|
||||
|
||||
if (IS_HORUS(board)) {
|
||||
strcpy(bluetoothName, "Horus");
|
||||
}
|
||||
else if (IS_TARANIS_X9E(board) || IS_TARANIS_SMALL(board)) {
|
||||
strcpy(bluetoothName, "Taranis");
|
||||
}
|
||||
|
||||
templateSetup = g.profile[g.sessionId()].channelOrder();
|
||||
stickMode = g.profile[g.sessionId()].defaultMode();
|
||||
|
||||
QString t_calib = g.profile[g.sessionId()].stickPotCalib();
|
||||
int potsnum = getBoardCapability(getCurrentBoard(), Board::Pots);
|
||||
if (!t_calib.isEmpty()) {
|
||||
QString t_trainercalib=g.profile[g.sessionId()].trainerCalib();
|
||||
int8_t t_txVoltageCalibration=(int8_t)g.profile[g.sessionId()].txVoltageCalibration();
|
||||
int8_t t_txCurrentCalibration=(int8_t)g.profile[g.sessionId()].txCurrentCalibration();
|
||||
int8_t t_PPM_Multiplier=(int8_t)g.profile[g.sessionId()].ppmMultiplier();
|
||||
uint8_t t_stickMode=(uint8_t)g.profile[g.sessionId()].gsStickMode();
|
||||
uint8_t t_vBatWarn=(uint8_t)g.profile[g.sessionId()].vBatWarn();
|
||||
QString t_DisplaySet=g.profile[g.sessionId()].display();
|
||||
QString t_BeeperSet=g.profile[g.sessionId()].beeper();
|
||||
QString t_HapticSet=g.profile[g.sessionId()].haptic();
|
||||
QString t_SpeakerSet=g.profile[g.sessionId()].speaker();
|
||||
QString t_CountrySet=g.profile[g.sessionId()].countryCode();
|
||||
|
||||
if ((t_calib.length()==(CPN_MAX_STICKS+potsnum)*12) && (t_trainercalib.length()==16)) {
|
||||
QString Byte;
|
||||
int16_t byte16;
|
||||
bool ok;
|
||||
for (int i=0; i<(CPN_MAX_STICKS+potsnum); i++) {
|
||||
Byte=t_calib.mid(i*12,4);
|
||||
byte16=(int16_t)Byte.toInt(&ok,16);
|
||||
if (ok)
|
||||
calibMid[i]=byte16;
|
||||
Byte=t_calib.mid(4+i*12,4);
|
||||
byte16=(int16_t)Byte.toInt(&ok,16);
|
||||
if (ok)
|
||||
calibSpanNeg[i]=byte16;
|
||||
Byte=t_calib.mid(8+i*12,4);
|
||||
byte16=(int16_t)Byte.toInt(&ok,16);
|
||||
if (ok)
|
||||
calibSpanPos[i]=byte16;
|
||||
}
|
||||
for (int i=0; i<4; i++) {
|
||||
Byte=t_trainercalib.mid(i*4,4);
|
||||
byte16=(int16_t)Byte.toInt(&ok,16);
|
||||
if (ok)
|
||||
trainer.calib[i]=byte16;
|
||||
}
|
||||
txCurrentCalibration=t_txCurrentCalibration;
|
||||
txVoltageCalibration=t_txVoltageCalibration;
|
||||
vBatWarn=t_vBatWarn;
|
||||
PPM_Multiplier=t_PPM_Multiplier;
|
||||
stickMode = t_stickMode;
|
||||
}
|
||||
if ((t_DisplaySet.length()==6) && (t_BeeperSet.length()==4) && (t_HapticSet.length()==6) && (t_SpeakerSet.length()==6)) {
|
||||
uint8_t byte8u;
|
||||
int8_t byte8;
|
||||
bool ok;
|
||||
byte8=(int8_t)t_DisplaySet.mid(0,2).toInt(&ok,16);
|
||||
if (ok)
|
||||
optrexDisplay=(byte8==1 ? true : false);
|
||||
byte8u=(uint8_t)t_DisplaySet.mid(2,2).toUInt(&ok,16);
|
||||
if (ok)
|
||||
contrast=byte8u;
|
||||
byte8u=(uint8_t)t_DisplaySet.mid(4,2).toUInt(&ok,16);
|
||||
if (ok)
|
||||
backlightBright=byte8u;
|
||||
byte8=(int8_t)t_BeeperSet.mid(0,2).toUInt(&ok,16);
|
||||
if (ok)
|
||||
beeperMode=(BeeperMode)byte8;
|
||||
byte8=(int8_t)t_BeeperSet.mid(2,2).toInt(&ok,16);
|
||||
if (ok)
|
||||
beeperLength=byte8;
|
||||
byte8=(int8_t)t_HapticSet.mid(0,2).toUInt(&ok,16);
|
||||
if (ok)
|
||||
hapticMode=(BeeperMode)byte8;
|
||||
byte8=(int8_t)t_HapticSet.mid(2,2).toInt(&ok,16);
|
||||
if (ok)
|
||||
hapticStrength=byte8;
|
||||
byte8=(int8_t)t_HapticSet.mid(4,2).toInt(&ok,16);
|
||||
if (ok)
|
||||
hapticLength=byte8;
|
||||
byte8u=(uint8_t)t_SpeakerSet.mid(0,2).toUInt(&ok,16);
|
||||
if (ok)
|
||||
speakerMode=byte8u;
|
||||
byte8u=(uint8_t)t_SpeakerSet.mid(2,2).toUInt(&ok,16);
|
||||
if (ok)
|
||||
speakerPitch=byte8u;
|
||||
byte8u=(uint8_t)t_SpeakerSet.mid(4,2).toUInt(&ok,16);
|
||||
if (ok)
|
||||
speakerVolume=byte8u;
|
||||
if (t_CountrySet.length()==6) {
|
||||
byte8u=(uint8_t)t_CountrySet.mid(0,2).toUInt(&ok,16);
|
||||
if (ok)
|
||||
countryCode=byte8u;
|
||||
byte8u=(uint8_t)t_CountrySet.mid(2,2).toUInt(&ok,16);
|
||||
if (ok)
|
||||
imperial=byte8u;
|
||||
QString chars = t_CountrySet.mid(4, 2);
|
||||
ttsLanguage[0] = chars[0].toLatin1();
|
||||
ttsLanguage[1] = chars[1].toLatin1();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strcpy(themeName, "default");
|
||||
ThemeOptionData option1 = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0 };
|
||||
memcpy(&themeOptionValue[0], option1, sizeof(ThemeOptionData));
|
||||
ThemeOptionData option2 = { 0x03, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0 };
|
||||
memcpy(&themeOptionValue[1], option2, sizeof(ThemeOptionData));
|
||||
}
|
||||
|
||||
void GeneralSettings::setDefaultControlTypes(Board::Type board)
|
||||
{
|
||||
for (int i=0; i<getBoardCapability(board, Board::FactoryInstalledSwitches); i++) {
|
||||
switchConfig[i] = Boards::getSwitchInfo(board, i).config;
|
||||
}
|
||||
|
||||
// TODO: move to Boards, like with switches
|
||||
if (IS_HORUS(board)) {
|
||||
potConfig[0] = Board::POT_WITH_DETENT;
|
||||
potConfig[1] = Board::POT_MULTIPOS_SWITCH;
|
||||
potConfig[2] = Board::POT_WITH_DETENT;
|
||||
}
|
||||
else if (IS_TARANIS_XLITE(board)) {
|
||||
potConfig[0] = Board::POT_WITHOUT_DETENT;
|
||||
potConfig[1] = Board::POT_WITHOUT_DETENT;
|
||||
}
|
||||
else if (IS_TARANIS_X7(board)) {
|
||||
potConfig[0] = Board::POT_WITHOUT_DETENT;
|
||||
potConfig[1] = Board::POT_WITH_DETENT;
|
||||
}
|
||||
else if (IS_TARANIS(board)) {
|
||||
potConfig[0] = Board::POT_WITH_DETENT;
|
||||
potConfig[1] = Board::POT_WITH_DETENT;
|
||||
}
|
||||
else {
|
||||
potConfig[0] = Board::POT_WITHOUT_DETENT;
|
||||
potConfig[1] = Board::POT_WITHOUT_DETENT;
|
||||
potConfig[2] = Board::POT_WITHOUT_DETENT;
|
||||
}
|
||||
|
||||
if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board)) {
|
||||
sliderConfig[0] = Board::SLIDER_WITH_DETENT;
|
||||
sliderConfig[1] = Board::SLIDER_WITH_DETENT;
|
||||
sliderConfig[2] = Board::SLIDER_WITH_DETENT;
|
||||
sliderConfig[3] = Board::SLIDER_WITH_DETENT;
|
||||
}
|
||||
else if (IS_TARANIS_X9(board) || IS_HORUS_X10(board)) {
|
||||
sliderConfig[0] = Board::SLIDER_WITH_DETENT;
|
||||
sliderConfig[1] = Board::SLIDER_WITH_DETENT;
|
||||
}
|
||||
}
|
||||
|
||||
int GeneralSettings::getDefaultStick(unsigned int channel) const
|
||||
{
|
||||
if (channel >= CPN_MAX_STICKS)
|
||||
return -1;
|
||||
else
|
||||
return chout_ar[4*templateSetup + channel] - 1;
|
||||
}
|
||||
|
||||
RawSource GeneralSettings::getDefaultSource(unsigned int channel) const
|
||||
{
|
||||
int stick = getDefaultStick(channel);
|
||||
if (stick >= 0)
|
||||
return RawSource(SOURCE_TYPE_STICK, stick);
|
||||
else
|
||||
return RawSource(SOURCE_TYPE_NONE);
|
||||
}
|
||||
|
||||
int GeneralSettings::getDefaultChannel(unsigned int stick) const
|
||||
{
|
||||
for (int i=0; i<4; i++){
|
||||
if (getDefaultStick(i) == (int)stick)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GeneralSettings::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
// Here we can add explicit conversions when moving from one board to another
|
||||
|
||||
cstate.setOrigin(tr("Radio Settings"));
|
||||
|
||||
setDefaultControlTypes(cstate.toType); // start with default switches/pots/sliders
|
||||
|
||||
// Try to intelligently copy any custom control names
|
||||
|
||||
// SE and SG are skipped on X7 board
|
||||
if (IS_TARANIS_X7(cstate.toType)) {
|
||||
if (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType)) {
|
||||
strncpy(switchName[4], switchName[5], sizeof(switchName[4]));
|
||||
strncpy(switchName[5], switchName[7], sizeof(switchName[5]));
|
||||
}
|
||||
}
|
||||
else if (IS_TARANIS_X7(cstate.fromType)) {
|
||||
if (IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) {
|
||||
strncpy(switchName[5], switchName[4], sizeof(switchName[5]));
|
||||
strncpy(switchName[7], switchName[5], sizeof(switchName[7]));
|
||||
}
|
||||
}
|
||||
|
||||
// LS and RS sliders are after 2 aux sliders on X12 and X9E
|
||||
if ((IS_HORUS_X12S(cstate.toType) || IS_TARANIS_X9E(cstate.toType)) && !IS_HORUS_X12S(cstate.fromType) && !IS_TARANIS_X9E(cstate.fromType)) {
|
||||
strncpy(sliderName[0], sliderName[2], sizeof(sliderName[0]));
|
||||
strncpy(sliderName[1], sliderName[3], sizeof(sliderName[1]));
|
||||
}
|
||||
else if (!IS_TARANIS_X9E(cstate.toType) && !IS_HORUS_X12S(cstate.toType) && (IS_HORUS_X12S(cstate.fromType) || IS_TARANIS_X9E(cstate.fromType))) {
|
||||
strncpy(sliderName[2], sliderName[0], sizeof(sliderName[2]));
|
||||
strncpy(sliderName[3], sliderName[1], sizeof(sliderName[3]));
|
||||
}
|
||||
|
||||
if (IS_HORUS(cstate.toType)) {
|
||||
// 6P switch is only on Horus (by default)
|
||||
if (cstate.fromBoard.getCapability(Board::FactoryInstalledPots) == 2) {
|
||||
strncpy(potName[2], potName[1], sizeof(potName[2]));
|
||||
potName[1][0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_TARANIS(cstate.toType)) {
|
||||
// No S3 pot on Taranis boards by default
|
||||
if (cstate.fromBoard.getCapability(Board::FactoryInstalledPots) > 2)
|
||||
strncpy(potName[1], potName[2], sizeof(potName[1]));
|
||||
|
||||
contrast = qBound<int>(getCurrentFirmware()->getCapability(MinContrast), contrast, getCurrentFirmware()->getCapability(MaxContrast));
|
||||
}
|
||||
|
||||
// TODO: Would be nice at this point to have GUI pause and ask the user to set up any custom hardware they have on the destination radio.
|
||||
|
||||
// Convert all global functions (do this after HW adjustments)
|
||||
for (int i=0; i<CPN_MAX_SPECIAL_FUNCTIONS; i++) {
|
||||
customFn[i].convert(cstate.withComponentIndex(i));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef GENERALSETTINGS_H
|
||||
#define GENERALSETTINGS_H
|
||||
|
||||
#include "boards.h"
|
||||
#include "constants.h"
|
||||
#include "customfunctiondata.h"
|
||||
#include "rawsource.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class Firmware;
|
||||
class ModelData;
|
||||
class GeneralSettings;
|
||||
class RadioDataConversionState;
|
||||
|
||||
enum UartModes {
|
||||
UART_MODE_NONE,
|
||||
UART_MODE_TELEMETRY_MIRROR,
|
||||
UART_MODE_TELEMETRY,
|
||||
UART_MODE_SBUS_TRAINER,
|
||||
UART_MODE_DEBUG
|
||||
};
|
||||
|
||||
class TrainerMix {
|
||||
public:
|
||||
TrainerMix() { clear(); }
|
||||
unsigned int src; // 0-7 = ch1-8
|
||||
RawSwitch swtch;
|
||||
int weight;
|
||||
unsigned int mode; // off, add-mode, subst-mode
|
||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TrainerMix)); }
|
||||
};
|
||||
|
||||
class TrainerData {
|
||||
public:
|
||||
TrainerData() { clear(); }
|
||||
int calib[4];
|
||||
TrainerMix mix[4];
|
||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TrainerData)); }
|
||||
};
|
||||
|
||||
class GeneralSettings {
|
||||
Q_DECLARE_TR_FUNCTIONS(GeneralSettings)
|
||||
|
||||
public:
|
||||
|
||||
enum BeeperMode {
|
||||
BEEPER_QUIET = -2,
|
||||
BEEPER_ALARMS_ONLY = -1,
|
||||
BEEPER_NOKEYS = 0,
|
||||
BEEPER_ALL = 1
|
||||
};
|
||||
|
||||
GeneralSettings();
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
|
||||
void setDefaultControlTypes(Board::Type board);
|
||||
int getDefaultStick(unsigned int channel) const;
|
||||
RawSource getDefaultSource(unsigned int channel) const;
|
||||
int getDefaultChannel(unsigned int stick) const;
|
||||
|
||||
unsigned int version;
|
||||
unsigned int variant;
|
||||
int calibMid[CPN_MAX_ANALOGS];
|
||||
int calibSpanNeg[CPN_MAX_ANALOGS];
|
||||
int calibSpanPos[CPN_MAX_ANALOGS];
|
||||
unsigned int currModelIndex;
|
||||
char currModelFilename[16+1];
|
||||
unsigned int contrast;
|
||||
unsigned int vBatWarn;
|
||||
int txVoltageCalibration;
|
||||
int txCurrentCalibration;
|
||||
int vBatMin;
|
||||
int vBatMax;
|
||||
int backlightMode;
|
||||
TrainerData trainer;
|
||||
unsigned int view; // main screen view // TODO enum
|
||||
bool disableThrottleWarning;
|
||||
bool fai;
|
||||
bool disableMemoryWarning;
|
||||
BeeperMode beeperMode;
|
||||
bool disableAlarmWarning;
|
||||
bool disableRssiPoweroffAlarm;
|
||||
unsigned int usbMode;
|
||||
BeeperMode hapticMode;
|
||||
unsigned int stickMode; // TODO enum
|
||||
int timezone;
|
||||
bool adjustRTC;
|
||||
bool optrexDisplay;
|
||||
unsigned int inactivityTimer;
|
||||
bool minuteBeep;
|
||||
bool preBeep;
|
||||
bool flashBeep;
|
||||
unsigned int splashMode;
|
||||
int splashDuration;
|
||||
unsigned int backlightDelay;
|
||||
unsigned int templateSetup; //RETA order according to chout_ar array
|
||||
int PPM_Multiplier;
|
||||
int hapticLength;
|
||||
unsigned int reNavigation;
|
||||
unsigned int stickReverse;
|
||||
unsigned int speakerPitch;
|
||||
int hapticStrength;
|
||||
unsigned int speakerMode;
|
||||
char ownerName[10+1];
|
||||
int beeperLength;
|
||||
unsigned int gpsFormat;
|
||||
int speakerVolume;
|
||||
unsigned int backlightBright;
|
||||
unsigned int backlightOffBright;
|
||||
int switchesDelay;
|
||||
int temperatureCalib;
|
||||
int temperatureWarn;
|
||||
unsigned int mAhWarn;
|
||||
unsigned int mAhUsed;
|
||||
unsigned int globalTimer;
|
||||
char bluetoothName[10+1];
|
||||
unsigned int bluetoothBaudrate;
|
||||
unsigned int bluetoothMode;
|
||||
unsigned int sticksGain;
|
||||
unsigned int rotarySteps;
|
||||
unsigned int countryCode;
|
||||
bool jitterFilter;
|
||||
unsigned int imperial;
|
||||
char ttsLanguage[2+1];
|
||||
int beepVolume;
|
||||
int wavVolume;
|
||||
int varioVolume;
|
||||
int varioPitch;
|
||||
int varioRange;
|
||||
int varioRepeat;
|
||||
int backgroundVolume;
|
||||
unsigned int mavbaud;
|
||||
unsigned int switchUnlockStates;
|
||||
unsigned int hw_uartMode; // UartModes
|
||||
unsigned int backlightColor;
|
||||
CustomFunctionData customFn[CPN_MAX_SPECIAL_FUNCTIONS];
|
||||
char switchName[CPN_MAX_SWITCHES][3+1];
|
||||
unsigned int switchConfig[CPN_MAX_SWITCHES];
|
||||
char stickName[CPN_MAX_STICKS][3+1];
|
||||
char potName[CPN_MAX_KNOBS][3+1];
|
||||
unsigned int potConfig[CPN_MAX_KNOBS];
|
||||
char sliderName[CPN_MAX_SLIDERS][3+1];
|
||||
unsigned int sliderConfig[CPN_MAX_SLIDERS];
|
||||
|
||||
char themeName[8+1];
|
||||
typedef uint8_t ThemeOptionData[8+1];
|
||||
ThemeOptionData themeOptionValue[5];
|
||||
|
||||
bool switchPositionAllowedTaranis(int index) const;
|
||||
bool switchSourceAllowedTaranis(int index) const;
|
||||
bool isPotAvailable(int index) const;
|
||||
bool isSliderAvailable(int index) const;
|
||||
};
|
||||
|
||||
|
||||
#endif // GENERALSETTINGS_H
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "gvardata.h"
|
||||
|
||||
#include "radiodata.h"
|
||||
|
||||
QString GVarData::unitToString() const
|
||||
{
|
||||
switch (unit) {
|
||||
case GVAR_UNIT_NUMBER:
|
||||
return tr("");
|
||||
case GVAR_UNIT_PERCENT:
|
||||
return tr("%");
|
||||
default:
|
||||
return tr("?"); // highlight unknown value
|
||||
}
|
||||
}
|
||||
|
||||
QString GVarData::precToString() const
|
||||
{
|
||||
switch (prec) {
|
||||
case GVAR_PREC_MUL10:
|
||||
return tr("0._");
|
||||
case GVAR_PREC_MUL1:
|
||||
return tr("0.0");
|
||||
default:
|
||||
return tr("?.?"); // highlight unknown value
|
||||
}
|
||||
}
|
||||
|
||||
QString GVarData::nameToString(int index) const
|
||||
{
|
||||
return RadioData::getElementName(tr("GV"), index + 1, name);
|
||||
}
|
||||
|
||||
int GVarData::multiplierSet()
|
||||
{
|
||||
return (prec == 0 ? 1 : 10);
|
||||
}
|
||||
|
||||
float GVarData::multiplierGet() const
|
||||
{
|
||||
return (prec == 0 ? 1 : 0.1);
|
||||
}
|
||||
|
||||
void GVarData::setMin(float val)
|
||||
{
|
||||
min = (val * multiplierSet()) - GVAR_MIN_VALUE;
|
||||
}
|
||||
|
||||
void GVarData::setMax(float val)
|
||||
{
|
||||
max = GVAR_MAX_VALUE - (val * multiplierSet());
|
||||
}
|
||||
|
||||
int GVarData::getMin() const
|
||||
{
|
||||
return GVAR_MIN_VALUE + min;
|
||||
}
|
||||
|
||||
int GVarData::getMax() const
|
||||
{
|
||||
return GVAR_MAX_VALUE - max;
|
||||
}
|
||||
|
||||
float GVarData::getMinPrec() const
|
||||
{
|
||||
return getMin() * multiplierGet();
|
||||
}
|
||||
|
||||
float GVarData::getMaxPrec() const
|
||||
{
|
||||
return getMax() * multiplierGet();
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef GVARDATA_H
|
||||
#define GVARDATA_H
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
#define GVAR_NAME_LEN 3
|
||||
#define GVAR_MAX_VALUE 1024
|
||||
#define GVAR_MIN_VALUE -GVAR_MAX_VALUE
|
||||
|
||||
class GVarData {
|
||||
Q_DECLARE_TR_FUNCTIONS(GVarData)
|
||||
|
||||
public:
|
||||
GVarData() { clear(); }
|
||||
|
||||
enum {
|
||||
GVAR_UNIT_NUMBER,
|
||||
GVAR_UNIT_PERCENT
|
||||
};
|
||||
|
||||
enum {
|
||||
GVAR_PREC_MUL10,
|
||||
GVAR_PREC_MUL1
|
||||
};
|
||||
|
||||
char name[GVAR_NAME_LEN+1];
|
||||
int min;
|
||||
int max;
|
||||
bool popup;
|
||||
unsigned int prec; // 0 0._ 1 0.0
|
||||
unsigned int unit; // 0 _ 1 %
|
||||
|
||||
void clear() {memset(this, 0, sizeof(GVarData)); }
|
||||
QString unitToString() const;
|
||||
QString precToString() const;
|
||||
QString nameToString(int index) const;
|
||||
int multiplierSet();
|
||||
float multiplierGet() const;
|
||||
void setMin(float val);
|
||||
void setMax(float val);
|
||||
int getMin() const;
|
||||
int getMax() const;
|
||||
float getMinPrec() const;
|
||||
float getMaxPrec() const;
|
||||
};
|
||||
|
||||
|
||||
#endif // GVARDATA_H
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "io_data.h"
|
||||
|
||||
#include "radiodata.h" // for RadioData::getElementName
|
||||
#include "radiodataconversionstate.h"
|
||||
|
||||
/*
|
||||
* ExpoData
|
||||
*/
|
||||
|
||||
void ExpoData::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
cstate.setComponent(tr("INP"), 3);
|
||||
cstate.setSubComp(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, chn).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
|
||||
srcRaw.convert(cstate);
|
||||
swtch.convert(cstate);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MixData
|
||||
*/
|
||||
|
||||
void MixData::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
cstate.setComponent(tr("MIX"), 4);
|
||||
cstate.setSubComp(RawSource(SOURCE_TYPE_CH, destCh-1).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
|
||||
srcRaw.convert(cstate);
|
||||
swtch.convert(cstate);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LimitData
|
||||
*/
|
||||
|
||||
QString LimitData::minToString() const
|
||||
{
|
||||
return QString::number((qreal)min/10);
|
||||
}
|
||||
|
||||
QString LimitData::maxToString() const
|
||||
{
|
||||
return QString::number((qreal)max/10);
|
||||
}
|
||||
|
||||
QString LimitData::revertToString() const
|
||||
{
|
||||
return revert ? tr("INV") : tr("NOR");
|
||||
}
|
||||
|
||||
QString LimitData::nameToString(int index) const
|
||||
{
|
||||
return RadioData::getElementName(tr("CH"), index + 1, name);
|
||||
}
|
||||
|
||||
QString LimitData::offsetToString() const
|
||||
{
|
||||
return QString::number((qreal)offset/10, 'f', 1);
|
||||
}
|
||||
|
||||
void LimitData::clear()
|
||||
{
|
||||
memset(reinterpret_cast<void *>(this), 0, sizeof(LimitData));
|
||||
min = -1000;
|
||||
max = +1000;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CurveData
|
||||
*/
|
||||
|
||||
CurveData::CurveData()
|
||||
{
|
||||
clear(5);
|
||||
}
|
||||
|
||||
void CurveData::clear(int count)
|
||||
{
|
||||
memset(this, 0, sizeof(CurveData));
|
||||
this->count = count;
|
||||
}
|
||||
|
||||
bool CurveData::isEmpty() const
|
||||
{
|
||||
for (int i=0; i<count; i++) {
|
||||
if (points[i].y != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString CurveData::nameToString(const int idx) const
|
||||
{
|
||||
return RadioData::getElementName(tr("CV"), idx + 1, name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FlightModeData
|
||||
*/
|
||||
|
||||
void FlightModeData::clear(const int phase)
|
||||
{
|
||||
memset(reinterpret_cast<void *>(this), 0, sizeof(FlightModeData));
|
||||
if (phase != 0) {
|
||||
for (int idx=0; idx<CPN_MAX_GVARS; idx++) {
|
||||
gvars[idx] = 1025;
|
||||
}
|
||||
for (int idx=0; idx<CPN_MAX_ENCODERS; idx++) {
|
||||
rotaryEncoders[idx] = 1025;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString FlightModeData::nameToString(int index) const
|
||||
{
|
||||
return RadioData::getElementName(tr("FM"), index, name); // names are zero-based, FM0, FM1, etc
|
||||
}
|
||||
|
||||
void FlightModeData::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
cstate.setComponent("FMD", 2);
|
||||
cstate.setSubComp(nameToString(cstate.subCompIdx));
|
||||
swtch.convert(cstate);
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef IO_DATA_H
|
||||
#define IO_DATA_H
|
||||
|
||||
#include "constants.h"
|
||||
#include "curvereference.h"
|
||||
#include "rawsource.h"
|
||||
#include "rawswitch.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class RadioDataConversionState;
|
||||
|
||||
enum InputMode {
|
||||
INPUT_MODE_NONE,
|
||||
INPUT_MODE_POS,
|
||||
INPUT_MODE_NEG,
|
||||
INPUT_MODE_BOTH
|
||||
};
|
||||
|
||||
class ExpoData {
|
||||
Q_DECLARE_TR_FUNCTIONS(ExpoData)
|
||||
|
||||
public:
|
||||
ExpoData() { clear(); }
|
||||
RawSource srcRaw;
|
||||
unsigned int scale;
|
||||
unsigned int mode; // InputMode
|
||||
unsigned int chn;
|
||||
RawSwitch swtch;
|
||||
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
|
||||
int weight;
|
||||
int offset;
|
||||
CurveReference curve;
|
||||
int carryTrim;
|
||||
char name[10+1];
|
||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
};
|
||||
|
||||
enum MltpxValue {
|
||||
MLTPX_ADD=0,
|
||||
MLTPX_MUL=1,
|
||||
MLTPX_REP=2
|
||||
};
|
||||
|
||||
#define MIXDATA_NAME_LEN 10
|
||||
|
||||
class MixData {
|
||||
Q_DECLARE_TR_FUNCTIONS(MixData)
|
||||
|
||||
public:
|
||||
MixData() { clear(); }
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
|
||||
unsigned int destCh; // 1..CPN_MAX_CHNOUT
|
||||
RawSource srcRaw;
|
||||
int weight;
|
||||
RawSwitch swtch;
|
||||
CurveReference curve; //0=symmetrisch
|
||||
unsigned int delayUp;
|
||||
unsigned int delayDown;
|
||||
unsigned int speedUp; // Servogeschwindigkeit aus Tabelle (10ms Cycle)
|
||||
unsigned int speedDown; // 0 nichts
|
||||
int carryTrim;
|
||||
bool noExpo;
|
||||
MltpxValue mltpx; // multiplex method 0=+ 1=* 2=replace
|
||||
unsigned int mixWarn; // mixer warning
|
||||
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
|
||||
int sOffset;
|
||||
char name[MIXDATA_NAME_LEN+1];
|
||||
|
||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
|
||||
};
|
||||
|
||||
class LimitData {
|
||||
Q_DECLARE_TR_FUNCTIONS(LimitData)
|
||||
|
||||
public:
|
||||
LimitData() { clear(); }
|
||||
int min;
|
||||
int max;
|
||||
bool revert;
|
||||
int offset;
|
||||
int ppmCenter;
|
||||
bool symetrical;
|
||||
char name[6+1];
|
||||
CurveReference curve;
|
||||
QString minToString() const;
|
||||
QString maxToString() const;
|
||||
QString offsetToString() const;
|
||||
QString revertToString() const;
|
||||
QString nameToString(int index) const;
|
||||
void clear();
|
||||
};
|
||||
|
||||
class CurvePoint {
|
||||
public:
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
};
|
||||
|
||||
class CurveData {
|
||||
Q_DECLARE_TR_FUNCTIONS(CurveData)
|
||||
|
||||
public:
|
||||
enum CurveType {
|
||||
CURVE_TYPE_STANDARD,
|
||||
CURVE_TYPE_CUSTOM,
|
||||
CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM
|
||||
};
|
||||
|
||||
CurveData();
|
||||
void clear(int count);
|
||||
bool isEmpty() const;
|
||||
QString nameToString(const int idx) const;
|
||||
|
||||
CurveType type;
|
||||
bool smooth;
|
||||
int count;
|
||||
CurvePoint points[CPN_MAX_POINTS];
|
||||
char name[6+1];
|
||||
};
|
||||
|
||||
class FlightModeData {
|
||||
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
|
||||
|
||||
public:
|
||||
FlightModeData() { clear(0); }
|
||||
int trimMode[CPN_MAX_TRIMS];
|
||||
int trimRef[CPN_MAX_TRIMS];
|
||||
int trim[CPN_MAX_TRIMS];
|
||||
RawSwitch swtch;
|
||||
char name[10+1];
|
||||
unsigned int fadeIn;
|
||||
unsigned int fadeOut;
|
||||
int rotaryEncoders[CPN_MAX_ENCODERS];
|
||||
int gvars[CPN_MAX_GVARS];
|
||||
void clear(const int phase);
|
||||
QString nameToString(int index) const;
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
};
|
||||
|
||||
class SwashRingData {
|
||||
Q_DECLARE_TR_FUNCTIONS(SwashRingData)
|
||||
|
||||
public:
|
||||
SwashRingData() { clear(); }
|
||||
int elevatorWeight;
|
||||
int aileronWeight;
|
||||
int collectiveWeight;
|
||||
unsigned int type;
|
||||
RawSource collectiveSource;
|
||||
RawSource aileronSource;
|
||||
RawSource elevatorSource;
|
||||
unsigned int value;
|
||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(SwashRingData)); }
|
||||
};
|
||||
|
||||
#endif // IO_DATA_H
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "logicalswitchdata.h"
|
||||
|
||||
#include "radiodata.h"
|
||||
#include "radiodataconversionstate.h"
|
||||
#include "rawsource.h"
|
||||
#include "rawswitch.h"
|
||||
|
||||
bool LogicalSwitchData::isEmpty() const
|
||||
{
|
||||
return (func == 0);
|
||||
}
|
||||
|
||||
CSFunctionFamily LogicalSwitchData::getFunctionFamily() const
|
||||
{
|
||||
if (func == LS_FN_EDGE)
|
||||
return LS_FAMILY_EDGE;
|
||||
else if (func == LS_FN_TIMER)
|
||||
return LS_FAMILY_TIMER;
|
||||
else if (func == LS_FN_STICKY)
|
||||
return LS_FAMILY_STICKY;
|
||||
else if (func < LS_FN_AND || func > LS_FN_ELESS)
|
||||
return LS_FAMILY_VOFS;
|
||||
else if (func < LS_FN_EQUAL)
|
||||
return LS_FAMILY_VBOOL;
|
||||
else
|
||||
return LS_FAMILY_VCOMP;
|
||||
}
|
||||
|
||||
unsigned int LogicalSwitchData::getRangeFlags() const
|
||||
{
|
||||
int f = 0;
|
||||
|
||||
if (func == LS_FN_DPOS || func == LS_FN_DAPOS)
|
||||
f |= RANGE_DELTA_FUNCTION;
|
||||
|
||||
if (func == LS_FN_DAPOS || func == LS_FN_APOS || func == LS_FN_ANEG)
|
||||
f |= RANGE_ABS_FUNCTION;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
QString LogicalSwitchData::funcToString() const
|
||||
{
|
||||
switch (func) {
|
||||
case LS_FN_OFF:
|
||||
return tr("---");
|
||||
case LS_FN_VPOS:
|
||||
return tr("a>x");
|
||||
case LS_FN_VNEG:
|
||||
return tr("a<x");
|
||||
case LS_FN_APOS:
|
||||
return tr("|a|>x");
|
||||
case LS_FN_ANEG:
|
||||
return tr("|a|<x");
|
||||
case LS_FN_AND:
|
||||
return tr("AND");
|
||||
case LS_FN_OR:
|
||||
return tr("OR");
|
||||
case LS_FN_XOR:
|
||||
return tr("XOR");
|
||||
case LS_FN_EQUAL:
|
||||
return tr("a=b");
|
||||
case LS_FN_NEQUAL:
|
||||
return tr("a!=b");
|
||||
case LS_FN_GREATER:
|
||||
return tr("a>b");
|
||||
case LS_FN_LESS:
|
||||
return tr("a<b");
|
||||
case LS_FN_EGREATER:
|
||||
return tr("a>=b");
|
||||
case LS_FN_ELESS:
|
||||
return tr("a<=b");
|
||||
case LS_FN_DPOS:
|
||||
return tr("d>=x");
|
||||
case LS_FN_DAPOS:
|
||||
return tr("|d|>=x");
|
||||
case LS_FN_VEQUAL:
|
||||
return tr("a=x");
|
||||
case LS_FN_VALMOSTEQUAL:
|
||||
return tr("a~x");
|
||||
case LS_FN_TIMER:
|
||||
return tr("Timer");
|
||||
case LS_FN_STICKY:
|
||||
return tr("Sticky");
|
||||
case LS_FN_EDGE:
|
||||
return tr("Edge");
|
||||
default:
|
||||
return tr("Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
QString LogicalSwitchData::nameToString(int index) const
|
||||
{
|
||||
return RadioData::getElementName(tr("L"), index + 1, NULL, true);
|
||||
}
|
||||
|
||||
void LogicalSwitchData::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
cstate.setComponent(tr("LSW"), 7);
|
||||
cstate.setSubComp(RawSwitch(SWITCH_TYPE_VIRTUAL, cstate.subCompIdx + 1).toString(cstate.fromType, cstate.fromGS(), cstate.fromModel()));
|
||||
CSFunctionFamily family = getFunctionFamily();
|
||||
switch(family) {
|
||||
case LS_FAMILY_VOFS:
|
||||
val1 = RawSource(val1).convert(cstate.withComponentField("V1")).toValue();
|
||||
break;
|
||||
case LS_FAMILY_STICKY:
|
||||
case LS_FAMILY_VBOOL:
|
||||
val1 = RawSwitch(val1).convert(cstate.withComponentField("V1")).toValue();
|
||||
val2 = RawSwitch(val2).convert(cstate.withComponentField("V2")).toValue();
|
||||
break;
|
||||
case LS_FAMILY_EDGE:
|
||||
val1 = RawSwitch(val1).convert(cstate.withComponentField("V1")).toValue();
|
||||
break;
|
||||
case LS_FAMILY_VCOMP:
|
||||
val1 = RawSource(val1).convert(cstate.withComponentField("V1")).toValue();
|
||||
val2 = RawSource(val2).convert(cstate.withComponentField("V2")).toValue();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
andsw = RawSwitch(andsw).convert(cstate.withComponentField("AND")).toValue();
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LOGICALSWITCHDATA_H
|
||||
#define LOGICALSWITCHDATA_H
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class RadioDataConversionState;
|
||||
|
||||
enum CSFunction {
|
||||
LS_FN_OFF,
|
||||
LS_FN_VPOS,
|
||||
LS_FN_VNEG,
|
||||
LS_FN_APOS,
|
||||
LS_FN_ANEG,
|
||||
LS_FN_AND,
|
||||
LS_FN_OR,
|
||||
LS_FN_XOR,
|
||||
LS_FN_EQUAL,
|
||||
LS_FN_NEQUAL,
|
||||
LS_FN_GREATER,
|
||||
LS_FN_LESS,
|
||||
LS_FN_EGREATER,
|
||||
LS_FN_ELESS,
|
||||
LS_FN_DPOS,
|
||||
LS_FN_DAPOS,
|
||||
LS_FN_VEQUAL, // added at the end to avoid everything renumbered
|
||||
LS_FN_VALMOSTEQUAL,
|
||||
LS_FN_TIMER,
|
||||
LS_FN_STICKY,
|
||||
LS_FN_EDGE,
|
||||
// later ... LS_FN_RANGE,
|
||||
LS_FN_MAX
|
||||
};
|
||||
|
||||
enum CSFunctionFamily {
|
||||
LS_FAMILY_VOFS,
|
||||
LS_FAMILY_VBOOL,
|
||||
LS_FAMILY_VCOMP,
|
||||
LS_FAMILY_TIMER,
|
||||
LS_FAMILY_STICKY,
|
||||
LS_FAMILY_EDGE,
|
||||
};
|
||||
|
||||
class LogicalSwitchData {
|
||||
Q_DECLARE_TR_FUNCTIONS(LogicalSwitchData)
|
||||
|
||||
public:
|
||||
LogicalSwitchData(unsigned int func=0)
|
||||
{
|
||||
clear();
|
||||
this->func = func;
|
||||
}
|
||||
unsigned int func;
|
||||
int val1;
|
||||
int val2;
|
||||
int val3;
|
||||
unsigned int delay;
|
||||
unsigned int duration;
|
||||
int andsw;
|
||||
|
||||
void clear() { memset(this, 0, sizeof(LogicalSwitchData)); }
|
||||
bool isEmpty() const;
|
||||
CSFunctionFamily getFunctionFamily() const;
|
||||
unsigned int getRangeFlags() const;
|
||||
QString funcToString() const;
|
||||
QString nameToString(int index) const;
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
};
|
||||
|
||||
#endif // LOGICALSWITCHDATA_H
|
||||
@@ -1,444 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "modeldata.h"
|
||||
|
||||
#include "eeprominterface.h"
|
||||
#include "generalsettings.h"
|
||||
#include "macros.h"
|
||||
#include "radiodataconversionstate.h"
|
||||
|
||||
|
||||
QString removeAccents(const QString & str)
|
||||
{
|
||||
// UTF-8 ASCII Table
|
||||
static const QHash<QString, QVariant> map = {
|
||||
{"a", QRegularExpression("[áâãàä]")},
|
||||
{"A", QRegularExpression("[ÁÂÃÀÄ]")},
|
||||
{"e", QRegularExpression("[éèêě]")},
|
||||
{"E", QRegularExpression("[ÉÈÊĚ]")},
|
||||
{"o", QRegularExpression("[óôõö]")},
|
||||
{"O", QRegularExpression("[ÓÔÕÖ]")},
|
||||
{"u", QRegularExpression("[úü]")},
|
||||
{"U", QRegularExpression("[ÚÜ]")},
|
||||
{"i", "í"}, {"I", "Í"},
|
||||
{"c", "ç"}, {"C", "Ç"},
|
||||
{"y", "ý"}, {"Y", "Ý"},
|
||||
{"s", "š"}, {"S", "Š"},
|
||||
{"r", "ř"}, {"R", "Ř"}
|
||||
};
|
||||
|
||||
QString result(str);
|
||||
for (QHash<QString, QVariant>::const_iterator it = map.cbegin(), en = map.cend(); it != en; ++it) {
|
||||
if (it.value().canConvert<QRegularExpression>())
|
||||
result.replace(it.value().toRegularExpression(), it.key());
|
||||
else
|
||||
result.replace(it.value().toString(), it.key());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TimerData
|
||||
*/
|
||||
|
||||
void TimerData::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
cstate.setComponent(tr("TMR"), 1);
|
||||
cstate.setSubComp(tr("Timer %1").arg(cstate.subCompIdx + 1));
|
||||
mode.convert(cstate);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ModelData
|
||||
*/
|
||||
|
||||
ModelData::ModelData()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
ModelData::ModelData(const ModelData & src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
ModelData & ModelData::operator = (const ModelData & src)
|
||||
{
|
||||
memcpy(reinterpret_cast<void *>(this), &src, sizeof(ModelData));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ExpoData * ModelData::insertInput(const int idx)
|
||||
{
|
||||
memmove(&expoData[idx+1], &expoData[idx], (CPN_MAX_EXPOS-(idx+1))*sizeof(ExpoData));
|
||||
expoData[idx].clear();
|
||||
return &expoData[idx];
|
||||
}
|
||||
|
||||
bool ModelData::isInputValid(const unsigned int idx) const
|
||||
{
|
||||
for (int i=0; i<CPN_MAX_EXPOS; i++) {
|
||||
const ExpoData * expo = &expoData[i];
|
||||
if (expo->mode == 0) break;
|
||||
if (expo->chn == idx)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModelData::hasExpos(uint8_t inputIdx) const
|
||||
{
|
||||
for (int i=0; i<CPN_MAX_EXPOS; i++) {
|
||||
const ExpoData & expo = expoData[i];
|
||||
if (expo.chn==inputIdx && expo.mode!=0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModelData::hasMixes(uint8_t channelIdx) const
|
||||
{
|
||||
channelIdx += 1;
|
||||
for (int i=0; i<CPN_MAX_MIXERS; i++) {
|
||||
if (mixData[i].destCh == channelIdx) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QVector<const ExpoData *> ModelData::expos(int input) const
|
||||
{
|
||||
QVector<const ExpoData *> result;
|
||||
for (int i=0; i<CPN_MAX_EXPOS; i++) {
|
||||
const ExpoData * ed = &expoData[i];
|
||||
if ((int)ed->chn==input && ed->mode!=0) {
|
||||
result << ed;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<const MixData *> ModelData::mixes(int channel) const
|
||||
{
|
||||
QVector<const MixData *> result;
|
||||
for (int i=0; i<CPN_MAX_MIXERS; i++) {
|
||||
const MixData * md = &mixData[i];
|
||||
if ((int)md->destCh == channel+1) {
|
||||
result << md;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ModelData::removeInput(const int idx, bool clearName)
|
||||
{
|
||||
unsigned int chn = expoData[idx].chn;
|
||||
|
||||
memmove(&expoData[idx], &expoData[idx+1], (CPN_MAX_EXPOS-(idx+1))*sizeof(ExpoData));
|
||||
expoData[CPN_MAX_EXPOS-1].clear();
|
||||
|
||||
//also remove input name if removing last line for this input
|
||||
if (clearName && !expos(chn).size())
|
||||
inputNames[chn][0] = 0;
|
||||
}
|
||||
|
||||
void ModelData::clearInputs()
|
||||
{
|
||||
for (int i=0; i<CPN_MAX_EXPOS; i++)
|
||||
expoData[i].clear();
|
||||
|
||||
//clear all input names
|
||||
if (getCurrentFirmware()->getCapability(VirtualInputs)) {
|
||||
for (int i=0; i<CPN_MAX_INPUTS; i++) {
|
||||
inputNames[i][0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelData::clearMixes()
|
||||
{
|
||||
for (int i=0; i<CPN_MAX_MIXERS; i++)
|
||||
mixData[i].clear();
|
||||
}
|
||||
|
||||
void ModelData::clear()
|
||||
{
|
||||
memset(reinterpret_cast<void *>(this), 0, sizeof(ModelData));
|
||||
modelIndex = -1; // an invalid index, this is managed by the TreeView data model
|
||||
moduleData[0].protocol = PULSES_OFF;
|
||||
moduleData[1].protocol = PULSES_OFF;
|
||||
moduleData[0].channelsCount = 8;
|
||||
moduleData[1].channelsStart = 0;
|
||||
moduleData[1].channelsCount = 8;
|
||||
moduleData[0].ppm.delay = 300;
|
||||
moduleData[1].ppm.delay = 300;
|
||||
moduleData[2].ppm.delay = 300; // Trainer PPM
|
||||
for (int i=0; i<CPN_MAX_FLIGHT_MODES; i++) {
|
||||
flightModeData[i].clear(i);
|
||||
}
|
||||
for (int i=0; i<CPN_MAX_GVARS; i++) {
|
||||
gvarData[i].clear();
|
||||
}
|
||||
clearInputs();
|
||||
clearMixes();
|
||||
for (int i=0; i<CPN_MAX_CHNOUT; i++)
|
||||
limitData[i].clear();
|
||||
for (int i=0; i<CPN_MAX_STICKS; i++)
|
||||
expoData[i].clear();
|
||||
for (int i=0; i<CPN_MAX_LOGICAL_SWITCHES; i++)
|
||||
logicalSw[i].clear();
|
||||
for (int i=0; i<CPN_MAX_SPECIAL_FUNCTIONS; i++)
|
||||
customFn[i].clear();
|
||||
for (int i=0; i<CPN_MAX_CURVES; i++)
|
||||
curves[i].clear(5);
|
||||
for (int i=0; i<CPN_MAX_TIMERS; i++)
|
||||
timers[i].clear();
|
||||
swashRingData.clear();
|
||||
frsky.clear();
|
||||
rssiAlarms.clear();
|
||||
for (int i=0; i<CPN_MAX_SENSORS; i++)
|
||||
sensorData[i].clear();
|
||||
|
||||
static const uint8_t blob[] = { 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x32, 0x50, 0x31, 0x00, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x42, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
memcpy(customScreenData[0], blob, sizeof(blob));
|
||||
}
|
||||
|
||||
bool ModelData::isEmpty() const
|
||||
{
|
||||
return !used;
|
||||
}
|
||||
|
||||
void ModelData::setDefaultInputs(const GeneralSettings & settings)
|
||||
{
|
||||
Board::Type board = getCurrentBoard();
|
||||
if (IS_ARM(board)) {
|
||||
for (int i=0; i<CPN_MAX_STICKS; i++) {
|
||||
ExpoData * expo = &expoData[i];
|
||||
expo->chn = i;
|
||||
expo->mode = INPUT_MODE_BOTH;
|
||||
expo->srcRaw = settings.getDefaultSource(i);
|
||||
expo->weight = 100;
|
||||
strncpy(inputNames[i], removeAccents(expo->srcRaw.toString(this)).toLatin1().constData(), sizeof(inputNames[i])-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelData::setDefaultMixes(const GeneralSettings & settings)
|
||||
{
|
||||
Board::Type board = getCurrentBoard();
|
||||
if (IS_ARM(board)) {
|
||||
setDefaultInputs(settings);
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_STICKS; i++) {
|
||||
MixData * mix = &mixData[i];
|
||||
mix->destCh = i+1;
|
||||
mix->weight = 100;
|
||||
if (IS_ARM(board)) {
|
||||
mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i);
|
||||
}
|
||||
else {
|
||||
mix->srcRaw = RawSource(SOURCE_TYPE_STICK, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelData::setDefaultValues(unsigned int id, const GeneralSettings & settings)
|
||||
{
|
||||
clear();
|
||||
used = true;
|
||||
sprintf(name, "MODEL%02d", id+1);
|
||||
for (int i=0; i<CPN_MAX_MODULES; i++) {
|
||||
moduleData[i].modelId = id+1;
|
||||
}
|
||||
setDefaultMixes(settings);
|
||||
}
|
||||
|
||||
int ModelData::getTrimValue(int phaseIdx, int trimIdx)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i=0; i<CPN_MAX_FLIGHT_MODES; i++) {
|
||||
FlightModeData & phase = flightModeData[phaseIdx];
|
||||
if (phase.trimMode[trimIdx] < 0) {
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
if (phase.trimRef[trimIdx] == phaseIdx || phaseIdx == 0) {
|
||||
return result + phase.trim[trimIdx];
|
||||
}
|
||||
else {
|
||||
phaseIdx = phase.trimRef[trimIdx];
|
||||
if (phase.trimMode[trimIdx] != 0)
|
||||
result += phase.trim[trimIdx];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ModelData::isGVarLinked(int phaseIdx, int gvarIdx)
|
||||
{
|
||||
return flightModeData[phaseIdx].gvars[gvarIdx] > 1024;
|
||||
}
|
||||
|
||||
int ModelData::getGVarFieldValue(int phaseIdx, int gvarIdx)
|
||||
{
|
||||
int idx = flightModeData[phaseIdx].gvars[gvarIdx];
|
||||
for (int i=0; idx>GVAR_MAX_VALUE && i<CPN_MAX_FLIGHT_MODES; i++) {
|
||||
int nextPhase = idx - GVAR_MAX_VALUE - 1;
|
||||
if (nextPhase >= phaseIdx) nextPhase += 1;
|
||||
phaseIdx = nextPhase;
|
||||
idx = flightModeData[phaseIdx].gvars[gvarIdx];
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
void ModelData::setTrimValue(int phaseIdx, int trimIdx, int value)
|
||||
{
|
||||
for (uint8_t i=0; i<CPN_MAX_FLIGHT_MODES; i++) {
|
||||
FlightModeData & phase = flightModeData[phaseIdx];
|
||||
int mode = phase.trimMode[trimIdx];
|
||||
int p = phase.trimRef[trimIdx];
|
||||
int & trim = phase.trim[trimIdx];
|
||||
if (mode < 0)
|
||||
return;
|
||||
if (p == phaseIdx || phaseIdx == 0) {
|
||||
trim = value;
|
||||
break;;
|
||||
}
|
||||
else if (mode == 0) {
|
||||
phaseIdx = p;
|
||||
}
|
||||
else {
|
||||
trim = value - getTrimValue(p, trimIdx);
|
||||
if (trim < -500)
|
||||
trim = -500;
|
||||
if (trim > 500)
|
||||
trim = 500;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelData::removeGlobalVar(int & var)
|
||||
{
|
||||
if (var >= 126 && var <= 130)
|
||||
var = flightModeData[0].gvars[var-126];
|
||||
else if (var <= -126 && var >= -130)
|
||||
var = - flightModeData[0].gvars[-126-var];
|
||||
}
|
||||
|
||||
ModelData ModelData::removeGlobalVars()
|
||||
{
|
||||
ModelData result = *this;
|
||||
|
||||
for (int i=0; i<CPN_MAX_MIXERS; i++) {
|
||||
removeGlobalVar(mixData[i].weight);
|
||||
removeGlobalVar(mixData[i].curve.value);
|
||||
removeGlobalVar(mixData[i].sOffset);
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_EXPOS; i++) {
|
||||
removeGlobalVar(expoData[i].weight);
|
||||
removeGlobalVar(expoData[i].curve.value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ModelData::getChannelsMax(bool forceExtendedLimits) const
|
||||
{
|
||||
if (forceExtendedLimits || extendedLimits)
|
||||
return IS_HORUS_OR_TARANIS(getCurrentBoard()) ? 150 : 125;
|
||||
else
|
||||
return 100;
|
||||
}
|
||||
|
||||
bool ModelData::isAvailable(const RawSwitch & swtch) const
|
||||
{
|
||||
unsigned index = abs(swtch.index) - 1;
|
||||
|
||||
if (swtch.type == SWITCH_TYPE_VIRTUAL) {
|
||||
return logicalSw[index].func != LS_FN_OFF;
|
||||
}
|
||||
else if (swtch.type == SWITCH_TYPE_FLIGHT_MODE) {
|
||||
return index == 0 || flightModeData[index].swtch.type != SWITCH_TYPE_NONE;
|
||||
}
|
||||
else if (swtch.type == SWITCH_TYPE_SENSOR) {
|
||||
return strlen(sensorData[index].label) > 0;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
float ModelData::getGVarFieldValuePrec(int phaseIdx, int gvarIdx)
|
||||
{
|
||||
return getGVarFieldValue(phaseIdx, gvarIdx) * gvarData[gvarIdx].multiplierGet();
|
||||
}
|
||||
|
||||
void ModelData::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
// Here we can add explicit conversions when moving from one board to another
|
||||
|
||||
QString origin = QString(name);
|
||||
if (origin.isEmpty())
|
||||
origin = QString::number(cstate.modelIdx+1);
|
||||
cstate.setOrigin(tr("Model: ") % origin);
|
||||
|
||||
cstate.setComponent("SET", 0);
|
||||
if (thrTraceSrc && (int)thrTraceSrc < cstate.fromBoard.getCapability(Board::Pots) + cstate.fromBoard.getCapability(Board::Sliders)) {
|
||||
cstate.setSubComp(tr("Throttle Source"));
|
||||
thrTraceSrc = RawSource(SOURCE_TYPE_STICK, (int)thrTraceSrc + 3).convert(cstate).index - 3;
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_TIMERS; i++) {
|
||||
timers[i].convert(cstate.withComponentIndex(i));
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_MIXERS; i++) {
|
||||
mixData[i].convert(cstate.withComponentIndex(i));
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_EXPOS; i++) {
|
||||
expoData[i].convert(cstate.withComponentIndex(i));
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_LOGICAL_SWITCHES; i++) {
|
||||
logicalSw[i].convert(cstate.withComponentIndex(i));
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_SPECIAL_FUNCTIONS; i++) {
|
||||
customFn[i].convert(cstate.withComponentIndex(i));
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_FLIGHT_MODES; i++) {
|
||||
flightModeData[i].convert(cstate.withComponentIndex(i));
|
||||
}
|
||||
|
||||
for (int i=0; i<CPN_MAX_MODULES; i++) {
|
||||
moduleData[i].convert(cstate.withComponentIndex(i));
|
||||
}
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MODELDATA_H
|
||||
#define MODELDATA_H
|
||||
|
||||
#include "constants.h"
|
||||
#include "customfunctiondata.h"
|
||||
#include "gvardata.h"
|
||||
#include "io_data.h"
|
||||
#include "logicalswitchdata.h"
|
||||
#include "moduledata.h"
|
||||
#include "sensordata.h"
|
||||
#include "telem_data.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class GeneralSettings;
|
||||
class RadioDataConversionState;
|
||||
|
||||
#define CHAR_FOR_NAMES " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."
|
||||
#define CHAR_FOR_NAMES_REGEX "[ A-Za-z0-9_.-,]*"
|
||||
|
||||
class RSSIAlarmData {
|
||||
public:
|
||||
RSSIAlarmData() { clear(); }
|
||||
unsigned int level[2]; // AVR Only
|
||||
int warning;
|
||||
int critical;
|
||||
bool disabled;
|
||||
void clear() {
|
||||
this->level[0] = 2;
|
||||
this->level[1] = 3;
|
||||
this->warning = 45;
|
||||
this->critical = 42;
|
||||
this->disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
#define TIMER_NAME_LEN 8
|
||||
|
||||
class TimerData {
|
||||
Q_DECLARE_TR_FUNCTIONS(TimerData)
|
||||
|
||||
public:
|
||||
enum CountDownMode {
|
||||
COUNTDOWN_SILENT,
|
||||
COUNTDOWN_BEEPS,
|
||||
COUNTDOWN_VOICE,
|
||||
COUNTDOWN_HAPTIC
|
||||
};
|
||||
TimerData() { clear(); }
|
||||
RawSwitch mode;
|
||||
char name[TIMER_NAME_LEN+1];
|
||||
bool minuteBeep;
|
||||
unsigned int countdownBeep;
|
||||
unsigned int val;
|
||||
unsigned int persistent;
|
||||
int pvalue;
|
||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TimerData)); mode = RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
};
|
||||
|
||||
#define CPN_MAX_SCRIPTS 9
|
||||
#define CPN_MAX_SCRIPT_INPUTS 10
|
||||
class ScriptData {
|
||||
public:
|
||||
ScriptData() { clear(); }
|
||||
char filename[10+1];
|
||||
char name[10+1];
|
||||
int inputs[CPN_MAX_SCRIPT_INPUTS];
|
||||
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ScriptData)); }
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO ...
|
||||
*/
|
||||
#if 0
|
||||
class CustomScreenOptionData {
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
class CustomScreenZoneData {
|
||||
public:
|
||||
char widgetName[10+1];
|
||||
WidgetOptionData widgetOptions[5];
|
||||
};
|
||||
|
||||
class CustomScreenData {
|
||||
public:
|
||||
CustomScreenData();
|
||||
|
||||
char layoutName[10+1];
|
||||
CustomScreenZoneData zones[];
|
||||
CustomScreenOptionData options[];
|
||||
};
|
||||
#else
|
||||
typedef char CustomScreenData[610+1];
|
||||
typedef char TopbarData[216+1];
|
||||
#endif
|
||||
|
||||
enum TrainerMode {
|
||||
TRAINER_MODE_MASTER_TRAINER_JACK,
|
||||
TRAINER_MODE_SLAVE,
|
||||
TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE,
|
||||
TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE,
|
||||
TRAINER_MODE_MASTER_BATTERY_COMPARTMENT,
|
||||
};
|
||||
|
||||
class ModelData {
|
||||
Q_DECLARE_TR_FUNCTIONS(ModelData)
|
||||
|
||||
public:
|
||||
ModelData();
|
||||
ModelData(const ModelData & src);
|
||||
ModelData & operator = (const ModelData & src);
|
||||
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
|
||||
ExpoData * insertInput(const int idx);
|
||||
void removeInput(const int idx, bool clearName = true);
|
||||
|
||||
bool isInputValid(const unsigned int idx) const;
|
||||
bool hasExpos(uint8_t inputIdx) const;
|
||||
bool hasMixes(uint8_t output) const;
|
||||
|
||||
QVector<const ExpoData *> expos(int input) const;
|
||||
QVector<const MixData *> mixes(int channel) const;
|
||||
|
||||
bool used;
|
||||
int category;
|
||||
char name[15+1];
|
||||
char filename[16+1];
|
||||
int modelIndex; // Companion only, temporary index position managed by data model.
|
||||
|
||||
TimerData timers[CPN_MAX_TIMERS];
|
||||
bool noGlobalFunctions;
|
||||
bool thrTrim; // Enable Throttle Trim
|
||||
int trimInc; // Trim Increments
|
||||
unsigned int trimsDisplay;
|
||||
bool disableThrottleWarning;
|
||||
|
||||
unsigned int beepANACenter; // 1<<0->A1.. 1<<6->A7
|
||||
|
||||
bool extendedLimits; // TODO xml
|
||||
bool extendedTrims;
|
||||
bool throttleReversed;
|
||||
FlightModeData flightModeData[CPN_MAX_FLIGHT_MODES];
|
||||
MixData mixData[CPN_MAX_MIXERS];
|
||||
LimitData limitData[CPN_MAX_CHNOUT];
|
||||
|
||||
char inputNames[CPN_MAX_INPUTS][4+1];
|
||||
ExpoData expoData[CPN_MAX_EXPOS];
|
||||
|
||||
CurveData curves[CPN_MAX_CURVES];
|
||||
LogicalSwitchData logicalSw[CPN_MAX_LOGICAL_SWITCHES];
|
||||
CustomFunctionData customFn[CPN_MAX_SPECIAL_FUNCTIONS];
|
||||
SwashRingData swashRingData;
|
||||
unsigned int thrTraceSrc;
|
||||
uint64_t switchWarningStates;
|
||||
unsigned int switchWarningEnable;
|
||||
unsigned int potsWarningMode;
|
||||
bool potsWarningEnabled[CPN_MAX_POTS];
|
||||
int potPosition[CPN_MAX_POTS];
|
||||
bool displayChecklist;
|
||||
GVarData gvarData[CPN_MAX_GVARS];
|
||||
MavlinkData mavlink;
|
||||
unsigned int telemetryProtocol;
|
||||
FrSkyData frsky;
|
||||
RSSIAlarmData rssiAlarms;
|
||||
|
||||
char bitmap[10+1];
|
||||
|
||||
unsigned int trainerMode; // TrainerMode
|
||||
|
||||
ModuleData moduleData[CPN_MAX_MODULES+1/*trainer*/];
|
||||
|
||||
ScriptData scriptData[CPN_MAX_SCRIPTS];
|
||||
|
||||
SensorData sensorData[CPN_MAX_SENSORS];
|
||||
|
||||
unsigned int toplcdTimer;
|
||||
|
||||
CustomScreenData customScreenData[5];
|
||||
|
||||
TopbarData topbarData;
|
||||
|
||||
void clear();
|
||||
bool isEmpty() const;
|
||||
void setDefaultInputs(const GeneralSettings & settings);
|
||||
void setDefaultMixes(const GeneralSettings & settings);
|
||||
void setDefaultValues(unsigned int id, const GeneralSettings & settings);
|
||||
|
||||
int getTrimValue(int phaseIdx, int trimIdx);
|
||||
void setTrimValue(int phaseIdx, int trimIdx, int value);
|
||||
|
||||
bool isGVarLinked(int phaseIdx, int gvarIdx);
|
||||
int getGVarFieldValue(int phaseIdx, int gvarIdx);
|
||||
float getGVarFieldValuePrec(int phaseIdx, int gvarIdx);
|
||||
|
||||
ModelData removeGlobalVars();
|
||||
|
||||
void clearMixes();
|
||||
void clearInputs();
|
||||
|
||||
int getChannelsMax(bool forceExtendedLimits=false) const;
|
||||
|
||||
bool isAvailable(const RawSwitch & swtch) const;
|
||||
|
||||
protected:
|
||||
void removeGlobalVar(int & var);
|
||||
};
|
||||
|
||||
#endif // MODELDATA_H
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "moduledata.h"
|
||||
#include "eeprominterface.h"
|
||||
#include "multiprotocols.h"
|
||||
#include "radiodataconversionstate.h"
|
||||
|
||||
void ModuleData::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
if (protocol == PULSES_PXX_R9M && (IS_TARANIS_XLITE(cstate.fromType) || IS_TARANIS_XLITE(cstate.toType))) {
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
QString ModuleData::rfProtocolToString() const
|
||||
{
|
||||
switch (protocol) {
|
||||
case PULSES_MULTIMODULE:
|
||||
return Multiprotocols::protocolToString((int)multi.rfProtocol, multi.customProto);
|
||||
|
||||
default:
|
||||
return CPN_STR_UNKNOWN_ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
QString ModuleData::subTypeToString(int type) const
|
||||
{
|
||||
static const char * strings[] = {
|
||||
"FCC",
|
||||
"EU",
|
||||
"868MHz",
|
||||
"915MHz"
|
||||
};
|
||||
|
||||
if (type < 0)
|
||||
type = subType;
|
||||
|
||||
switch (protocol) {
|
||||
case PULSES_MULTIMODULE:
|
||||
return Multiprotocols::subTypeToString(multi.customProto ? MM_RF_CUSTOM_SELECTED : (int)multi.rfProtocol, (unsigned)type);
|
||||
|
||||
case PULSES_PXX_R9M:
|
||||
return CHECK_IN_ARRAY(strings, type);
|
||||
|
||||
default:
|
||||
return CPN_STR_UNKNOWN_ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
QString ModuleData::powerValueToString(Firmware * fw) const
|
||||
{
|
||||
const QStringList & strRef = powerValueStrings(subType, fw);
|
||||
// EU module with telemetry can only be < 100/200mW.
|
||||
if (pxx.sport_out && subType == MODULE_SUBTYPE_R9M_EU && pxx.power > 1)
|
||||
return CPN_STR_UNKNOWN_ITEM;
|
||||
|
||||
return strRef.value(pxx.power, CPN_STR_UNKNOWN_ITEM);
|
||||
}
|
||||
|
||||
// static
|
||||
QString ModuleData::indexToString(int index, Firmware * fw)
|
||||
{
|
||||
if (index < 0)
|
||||
return tr("Trainer Port");
|
||||
|
||||
if (fw->getCapability(NumModules) > 1) {
|
||||
if (IS_HORUS_OR_TARANIS(fw->getBoard()))
|
||||
return index == 0 ? tr("Internal Radio System") : tr("External Radio Module");
|
||||
if (index > 0)
|
||||
return tr("Extra Radio System");
|
||||
}
|
||||
return tr("Radio System");
|
||||
}
|
||||
|
||||
// static
|
||||
QString ModuleData::protocolToString(unsigned protocol)
|
||||
{
|
||||
static const char * strings[] = {
|
||||
"OFF",
|
||||
"PPM",
|
||||
"Silverlit A", "Silverlit B", "Silverlit C",
|
||||
"CTP1009",
|
||||
"LP45", "DSM2", "DSMX",
|
||||
"PPM16", "PPMsim",
|
||||
"FrSky XJT (D16)", "FrSky XJT (D8)", "FrSky XJT (LR12)", "FrSky DJT",
|
||||
"Crossfire",
|
||||
"DIY Multiprotocol Module",
|
||||
"FrSky R9M Module",
|
||||
"SBUS output at VBat"
|
||||
};
|
||||
|
||||
return CHECK_IN_ARRAY(strings, protocol);
|
||||
}
|
||||
|
||||
// static
|
||||
QStringList ModuleData::powerValueStrings(int subType, Firmware * fw)
|
||||
{
|
||||
static const QStringList strings[] = {
|
||||
{ tr("10mW - 16CH"), tr("100mW - 16CH"), tr("500mW - 16CH"), tr("Auto <= 1W - 16CH") }, // full-size FCC
|
||||
{ tr("25mW - 8CH"), tr("25mW - 16CH"), tr("200mW - 16CH (no telemetry)"), tr("500mW - 16CH (no telemetry)") }, // full-size EU
|
||||
{ tr("100mW - 16CH") }, // mini FCC
|
||||
{ tr("25mW - 8CH"), tr("25mW - 16CH"), tr("100mW - 16CH (no telemetry)") } // mini EU
|
||||
};
|
||||
int strIdx = 0;
|
||||
if (subType == MODULE_SUBTYPE_R9M_EU)
|
||||
strIdx += 1;
|
||||
if (fw->getCapability(HasModuleR9MMini))
|
||||
strIdx += 2;
|
||||
return strings[strIdx];
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULEDATA_H
|
||||
#define MODULEDATA_H
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class Firmware;
|
||||
class RadioDataConversionState;
|
||||
|
||||
enum PulsesProtocol {
|
||||
PULSES_OFF,
|
||||
PULSES_PPM,
|
||||
PULSES_SILV_A,
|
||||
PULSES_SILV_B,
|
||||
PULSES_SILV_C,
|
||||
PULSES_CTP1009,
|
||||
PULSES_LP45,
|
||||
PULSES_DSM2,
|
||||
PULSES_DSMX,
|
||||
PULSES_PPM16,
|
||||
PULSES_PPMSIM,
|
||||
PULSES_PXX_XJT_X16,
|
||||
PULSES_PXX_XJT_D8,
|
||||
PULSES_PXX_XJT_LR12,
|
||||
PULSES_PXX_DJT,
|
||||
PULSES_CROSSFIRE,
|
||||
PULSES_MULTIMODULE,
|
||||
PULSES_PXX_R9M,
|
||||
PULSES_SBUS,
|
||||
PULSES_PROTOCOL_LAST
|
||||
};
|
||||
|
||||
enum MultiModuleRFProtocols {
|
||||
MM_RF_PROTO_FLYSKY=0,
|
||||
MM_RF_PROTO_FIRST=MM_RF_PROTO_FLYSKY,
|
||||
MM_RF_PROTO_HUBSAN,
|
||||
MM_RF_PROTO_FRSKY,
|
||||
MM_RF_PROTO_HISKY,
|
||||
MM_RF_PROTO_V2X2,
|
||||
MM_RF_PROTO_DSM2,
|
||||
MM_RF_PROTO_DEVO,
|
||||
MM_RF_PROTO_YD717,
|
||||
MM_RF_PROTO_KN,
|
||||
MM_RF_PROTO_SYMAX,
|
||||
MM_RF_PROTO_SLT,
|
||||
MM_RF_PROTO_CX10,
|
||||
MM_RF_PROTO_CG023,
|
||||
MM_RF_PROTO_BAYANG,
|
||||
MM_RF_PROTO_ESky,
|
||||
MM_RF_PROTO_MT99XX,
|
||||
MM_RF_PROTO_MJXQ,
|
||||
MM_RF_PROTO_SHENQI,
|
||||
MM_RF_PROTO_FY326,
|
||||
MM_RF_PROTO_SFHSS,
|
||||
MM_RF_PROTO_J6PRO,
|
||||
MM_RF_PROTO_FQ777,
|
||||
MM_RF_PROTO_ASSAN,
|
||||
MM_RF_PROTO_HONTAI,
|
||||
MM_RF_PROTO_OLRS,
|
||||
MM_RF_PROTO_FS_AFHDS2A,
|
||||
MM_RF_PROTO_Q2X2,
|
||||
MM_RF_PROTO_WK_2X01,
|
||||
MM_RF_PROTO_Q303,
|
||||
MM_RF_PROTO_GW008,
|
||||
MM_RF_PROTO_DM002,
|
||||
MM_RF_PROTO_CABELL,
|
||||
MM_RF_PROTO_ESKY150,
|
||||
MM_RF_PROTO_H83D,
|
||||
MM_RF_PROTO_CORONA,
|
||||
MM_RF_PROTO_CFLIE,
|
||||
MM_RF_PROTO_HITEC,
|
||||
MM_RF_PROTO_WFLY,
|
||||
MM_RF_PROTO_BUGS,
|
||||
MM_RF_PROTO_BUGS_MINI,
|
||||
MM_RF_PROTO_TRAXXAS,
|
||||
MM_RF_PROTO_NCC1701,
|
||||
MM_RF_PROTO_E01X,
|
||||
MM_RF_PROTO_V911S,
|
||||
MM_RF_PROTO_GD00X,
|
||||
MM_RF_PROTO_LAST = MM_RF_PROTO_GD00X
|
||||
};
|
||||
|
||||
enum TrainerProtocol {
|
||||
TRAINER_MASTER_JACK,
|
||||
TRAINER_SLAVE_JACK,
|
||||
TRAINER_MASTER_SBUS_MODULE,
|
||||
TRAINER_MASTER_CPPM_MODULE,
|
||||
TRAINER_MASTER_SBUS_BATT_COMPARTMENT
|
||||
};
|
||||
|
||||
enum R9MSubTypes {
|
||||
MODULE_SUBTYPE_R9M_FCC,
|
||||
MODULE_SUBTYPE_R9M_EU,
|
||||
MODULE_SUBTYPE_R9M_EUPLUS,
|
||||
MODULE_SUBTYPE_R9M_AUPLUS,
|
||||
MODULE_SUBTYPE_R9M_LAST=MODULE_SUBTYPE_R9M_AUPLUS
|
||||
};
|
||||
|
||||
class ModuleData {
|
||||
Q_DECLARE_TR_FUNCTIONS(ModuleData)
|
||||
|
||||
public:
|
||||
ModuleData() { clear(); }
|
||||
unsigned int modelId;
|
||||
int protocol;
|
||||
unsigned int subType;
|
||||
bool invertedSerial;
|
||||
unsigned int channelsStart;
|
||||
int channelsCount; // 0=8 channels
|
||||
unsigned int failsafeMode;
|
||||
int failsafeChannels[CPN_MAX_CHNOUT];
|
||||
|
||||
|
||||
struct {
|
||||
int delay;
|
||||
bool pulsePol; // false = positive
|
||||
bool outputType; // false = open drain, true = push pull
|
||||
int frameLength;
|
||||
} ppm;
|
||||
|
||||
struct {
|
||||
unsigned int rfProtocol;
|
||||
bool autoBindMode;
|
||||
bool lowPowerMode;
|
||||
bool customProto;
|
||||
int optionValue;
|
||||
} multi;
|
||||
|
||||
struct {
|
||||
int power; // 0 10 mW, 1 100 mW, 2 500 mW, 3 1W
|
||||
bool receiver_telem_off; // false = receiver telem enabled
|
||||
bool receiver_channel_9_16; // false = pwm out 1-8, true 9-16
|
||||
bool external_antenna; // false = internal antenna, true = external antenna
|
||||
bool sport_out;
|
||||
} pxx;
|
||||
|
||||
|
||||
void clear() { memset(this, 0, sizeof(ModuleData)); }
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
QString polarityToString() const { return ppm.pulsePol ? tr("Positive") : tr("Negative"); }
|
||||
QString rfProtocolToString() const;
|
||||
QString subTypeToString(int type = -1) const;
|
||||
QString powerValueToString(Firmware * fw) const;
|
||||
static QString indexToString(int index, Firmware * fw);
|
||||
static QString protocolToString(unsigned protocol);
|
||||
static QStringList powerValueStrings(int subType, Firmware * fw);
|
||||
};
|
||||
|
||||
#endif // MODULEDATA_H
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "multiprotocols.h"
|
||||
#include "radiodata.h"
|
||||
|
||||
#define STR_MULTI_SUBTYPE QT_TRANSLATE_NOOP("Multiprotocols", "Subtype")
|
||||
#define STR_MULTI_VIDFREQ QT_TRANSLATE_NOOP("Multiprotocols", "Video TX frequency")
|
||||
#define STR_MULTI_RFTUNE QT_TRANSLATE_NOOP("Multiprotocols", "CC2500 frequency fine tune")
|
||||
#define STR_MULTI_TELEMETRY QT_TRANSLATE_NOOP("Multiprotocols", "Telemetry")
|
||||
#define STR_MULTI_RFPOWER QT_TRANSLATE_NOOP("Multiprotocols", "Radio output power")
|
||||
#define STR_MULTI_SERVOFREQ QT_TRANSLATE_NOOP("Multiprotocols", "Servo output frequency")
|
||||
#define STR_MULTI_OPTION QT_TRANSLATE_NOOP("Multiprotocols", "Option value")
|
||||
#define STR_MULTI_DEFAULT QT_TRANSLATE_NOOP("Multiprotocols", "DEFAULT")
|
||||
|
||||
static const QStringList STR_SUBTYPE_CUSTOM ({
|
||||
STR_MULTI_SUBTYPE " 0", STR_MULTI_SUBTYPE " 1", STR_MULTI_SUBTYPE " 2", STR_MULTI_SUBTYPE " 3",
|
||||
STR_MULTI_SUBTYPE " 4", STR_MULTI_SUBTYPE " 5", STR_MULTI_SUBTYPE " 6", STR_MULTI_SUBTYPE " 7"
|
||||
});
|
||||
static const QStringList STR_SUBTYPE_FLYSKY {"Standard", "V9x9", "V6x6", "V912", "CX20"};
|
||||
static const QStringList STR_SUBTYPE_HUBSAN {"H107", "H301", "H501"};
|
||||
static const QStringList STR_SUBTYPE_FRSKY {"D16", "D8", "D16 8ch", "V8", "D16 EU-LBT", "D16 EU-LBT 8ch"};
|
||||
static const QStringList STR_SUBTYPE_HISKY {"Standard", "HK310"};
|
||||
static const QStringList STR_SUBTYPE_V2X2 {"Standard", "JXD506"};
|
||||
static const QStringList STR_SUBTYPE_DSM {"DSM2 22ms", "DSM2 11ms", "DSMX 22ms", "DSMX 11ms"};
|
||||
static const QStringList STR_SUBTYPE_YD717 {"Standard", "Skywalker", "Syma X4", "XINXUN", "NIHUI"};
|
||||
static const QStringList STR_SUBTYPE_KN {"WLtoys", "FeiLun"};
|
||||
static const QStringList STR_SUBTYPE_SYMAX {"Standard", "Syma X5C"};
|
||||
static const QStringList STR_SUBTYPE_SLT {"V1 (6 Channel)", "V2 (8 Channel)", "Q100", "Q200", "MR100"};
|
||||
static const QStringList STR_SUBTYPE_CX10 {"Green", "Blue", "DM007", "-", "JC3015a", "JC3015b", "MK33041"};
|
||||
static const QStringList STR_SUBTYPE_CG023 {"Standard", "YD829"};
|
||||
static const QStringList STR_SUBTYPE_BAYANG {"Standard", "H8S3D", "X16 AH", "IRDRONE"};
|
||||
static const QStringList STR_SUBTYPE_MT99 {"MT99", "H7", "YZ", "LS", "FY805"};
|
||||
static const QStringList STR_SUBTYPE_MJXQ {"WLH08", "X600", "X800", "H26D", "E010", "H26WH"};
|
||||
static const QStringList STR_SUBTYPE_FY326 {"Standard", "FY319"};
|
||||
static const QStringList STR_SUBTYPE_HONTAI {"Standard", "JJRC X1", "X5C1 Clone", "FQ777_951"};
|
||||
static const QStringList STR_SUBTYPE_AFHDS2A {"PWM and IBUS", "PPM and IBUS", "PWM and SBUS", "PPM and SBUS"};
|
||||
static const QStringList STR_SUBTYPE_Q2X2 {"Q222", "Q242", "Q282"};
|
||||
static const QStringList STR_SUBTYPE_WK2x01 {"WK2801", "WK2401", "W6_5_1", "W6_6_1", "W6_HEL", "W6_HEL_I"};
|
||||
static const QStringList STR_SUBTYPE_Q303 {"Standard", "CX35", "CX10D", "CX10WD"};
|
||||
static const QStringList STR_SUBTYPE_CABELL {"Cabell V3", "Cab V3 Telem", "-", "-", "-", "-", "Set FailSafe", "Unbind"};
|
||||
static const QStringList STR_SUBTYPE_H83D {"H8 Mini 3D", "H20H", "H20 Mini", "H30 Mini"};
|
||||
static const QStringList STR_SUBTYPE_CORONA {"V1", "V2", "Flydream V3"};
|
||||
static const QStringList STR_SUBTYPE_HITEC {"Optima", "Optima Hub Telem", "Minima"};
|
||||
static const QStringList STR_SUBTYPE_E01X {"E012", "E015"};
|
||||
|
||||
static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
|
||||
|
||||
|
||||
// Table is designed to be shared with gui_common_arm.cpp
|
||||
|
||||
const Multiprotocols multiProtocols {
|
||||
{MM_RF_PROTO_FLYSKY, 4, false, STR_SUBTYPE_FLYSKY, nullptr},
|
||||
{MM_RF_PROTO_HUBSAN, 2, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
|
||||
{MM_RF_PROTO_FRSKY, 5, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE},
|
||||
{MM_RF_PROTO_HISKY, 1, false, STR_SUBTYPE_HISKY, nullptr},
|
||||
{MM_RF_PROTO_V2X2, 1, false, STR_SUBTYPE_V2X2, nullptr},
|
||||
{MM_RF_PROTO_DSM2, 3, false, STR_SUBTYPE_DSM, nullptr},
|
||||
{MM_RF_PROTO_YD717, 4, false, STR_SUBTYPE_YD717, nullptr},
|
||||
{MM_RF_PROTO_KN, 1, false, STR_SUBTYPE_KN, nullptr},
|
||||
{MM_RF_PROTO_SYMAX, 1, false, STR_SUBTYPE_SYMAX, nullptr},
|
||||
{MM_RF_PROTO_SLT, 4, false, STR_SUBTYPE_SLT, nullptr},
|
||||
{MM_RF_PROTO_CX10, 6, false, STR_SUBTYPE_CX10, nullptr},
|
||||
{MM_RF_PROTO_CG023, 1, false, STR_SUBTYPE_CG023, nullptr},
|
||||
{MM_RF_PROTO_BAYANG, 3, false, STR_SUBTYPE_BAYANG, STR_MULTI_TELEMETRY},
|
||||
{MM_RF_PROTO_MT99XX, 4, false, STR_SUBTYPE_MT99, nullptr},
|
||||
{MM_RF_PROTO_MJXQ, 5, false, STR_SUBTYPE_MJXQ, nullptr},
|
||||
{MM_RF_PROTO_FY326, 1, false, STR_SUBTYPE_FY326, nullptr},
|
||||
{MM_RF_PROTO_SFHSS, 0, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
|
||||
{MM_RF_PROTO_HONTAI, 3, false, STR_SUBTYPE_HONTAI, nullptr},
|
||||
{MM_RF_PROTO_OLRS, 0, false, NO_SUBTYPE, STR_MULTI_RFPOWER},
|
||||
{MM_RF_PROTO_FS_AFHDS2A, 3, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
|
||||
{MM_RF_PROTO_Q2X2, 2, false, STR_SUBTYPE_Q2X2, nullptr},
|
||||
{MM_RF_PROTO_WK_2X01, 5, false, STR_SUBTYPE_WK2x01, nullptr},
|
||||
{MM_RF_PROTO_Q303, 3, false, STR_SUBTYPE_Q303, nullptr},
|
||||
{MM_RF_PROTO_CABELL, 7, false, STR_SUBTYPE_CABELL, STR_MULTI_OPTION},
|
||||
{MM_RF_PROTO_H83D, 3, false, STR_SUBTYPE_H83D, nullptr},
|
||||
{MM_RF_PROTO_CORONA, 2, false, STR_SUBTYPE_CORONA, STR_MULTI_RFTUNE},
|
||||
{MM_RF_PROTO_HITEC, 2, false, STR_SUBTYPE_HITEC, STR_MULTI_RFTUNE},
|
||||
{MM_RF_PROTO_E01X, 1, false, STR_SUBTYPE_E01X, nullptr},
|
||||
{MM_RF_CUSTOM_SELECTED, 7, true, STR_SUBTYPE_CUSTOM, STR_MULTI_OPTION},
|
||||
|
||||
// Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff)
|
||||
{ 0xfe, 0, false, NO_SUBTYPE, nullptr}
|
||||
};
|
||||
|
||||
int Multiprotocols::MultiProtocolDefinition::getOptionMin() const {
|
||||
if (optionsstr == STR_MULTI_RFPOWER)
|
||||
return -1;
|
||||
else if (optionsstr == STR_MULTI_SERVOFREQ)
|
||||
return 0;
|
||||
else
|
||||
return -128;
|
||||
}
|
||||
|
||||
int Multiprotocols::MultiProtocolDefinition::getOptionMax() const {
|
||||
if (optionsstr == STR_MULTI_RFPOWER)
|
||||
return 7;
|
||||
else if (optionsstr == STR_MULTI_SERVOFREQ)
|
||||
return 70;
|
||||
else
|
||||
return 127;
|
||||
}
|
||||
|
||||
const Multiprotocols::MultiProtocolDefinition & Multiprotocols::getProtocol(int protocol) const {
|
||||
for (const Multiprotocols::MultiProtocolDefinition & proto: protocols)
|
||||
if (proto.protocol == protocol)
|
||||
return proto;
|
||||
|
||||
// Protocol not found, return the default (last) proto
|
||||
Q_ASSERT(protocols.rbegin()->protocol == 0xfe);
|
||||
return *protocols.rbegin();
|
||||
}
|
||||
|
||||
// static
|
||||
QString Multiprotocols::protocolToString(int protocol, bool custom)
|
||||
{
|
||||
static const QStringList strings({
|
||||
"FlySky", "Hubsan", "FrSky", "Hisky", "V2x2", "DSM", "Devo", "YD717", "KN", "SymaX", "SLT", "CX10", "CG023",
|
||||
"Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "SFHSS", "J6 PRO","FQ777","Assan","Hontai","Open LRS",
|
||||
"FlySky AFHDS2A", "Q2x2", "Walkera", "Q303", "GW008", "DM002", "Cabell", "ESky 150", "H8 3D", "Corona", "CFlie",
|
||||
"Hitec", "Wfly", "Bugs", "Bugs Mini", "Traxxas", "NCC-1701-A", "E01X", "V911S", "GD00X"
|
||||
});
|
||||
|
||||
if (protocol == MM_RF_CUSTOM_SELECTED || custom)
|
||||
return tr("Custom - proto %1)").arg(protocol);
|
||||
else
|
||||
return strings.value(protocol, CPN_STR_UNKNOWN_ITEM);
|
||||
}
|
||||
|
||||
// static
|
||||
QString Multiprotocols::subTypeToString(int protocol, unsigned subType)
|
||||
{
|
||||
return tr(qPrintable(multiProtocols.getProtocol(protocol).subTypeStrings.value(subType, CPN_STR_UNKNOWN_ITEM)));
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef OPENTX_MULTI_H
|
||||
#define OPENTX_MULTI_H
|
||||
|
||||
#include <vector>
|
||||
#include <QtCore>
|
||||
|
||||
#define MM_RF_CUSTOM_SELECTED 0xff
|
||||
|
||||
class Multiprotocols
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Multiprotocols)
|
||||
|
||||
public:
|
||||
|
||||
struct radio_mm_definition {
|
||||
int protocol;
|
||||
unsigned int maxSubtype;
|
||||
bool hasFailsafe;
|
||||
QStringList protocols;
|
||||
QString optionsstr;
|
||||
};
|
||||
|
||||
struct MultiProtocolDefinition {
|
||||
const int protocol;
|
||||
const bool hasFailsafe;
|
||||
const QStringList subTypeStrings;
|
||||
const QString optionsstr;
|
||||
|
||||
unsigned int numSubTypes() const
|
||||
{
|
||||
return (unsigned int) subTypeStrings.length();
|
||||
}
|
||||
|
||||
int getOptionMin() const;
|
||||
|
||||
int getOptionMax() const;
|
||||
|
||||
MultiProtocolDefinition(const radio_mm_definition &rd) :
|
||||
protocol(rd.protocol),
|
||||
hasFailsafe(rd.hasFailsafe),
|
||||
subTypeStrings(rd.protocols),
|
||||
optionsstr(rd.optionsstr)
|
||||
{
|
||||
Q_ASSERT(rd.maxSubtype + 1 == (unsigned int) rd.protocols.length());
|
||||
}
|
||||
};
|
||||
|
||||
Multiprotocols(std::initializer_list<radio_mm_definition> l)
|
||||
{
|
||||
for (radio_mm_definition rd: l)
|
||||
protocols.push_back(MultiProtocolDefinition(rd));
|
||||
}
|
||||
|
||||
const MultiProtocolDefinition &getProtocol(int protocol) const;
|
||||
static QString protocolToString(int protocol, bool custom = false);
|
||||
static QString subTypeToString(int protocol, unsigned subType);
|
||||
|
||||
private:
|
||||
|
||||
std::vector<MultiProtocolDefinition> protocols;
|
||||
|
||||
};
|
||||
|
||||
extern const Multiprotocols multiProtocols;
|
||||
|
||||
#endif //OPENTX_MULTI_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _OPENTXEEPROM_H_
|
||||
#define _OPENTXEEPROM_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "eeprominterface.h"
|
||||
#include "eepromimportexport.h"
|
||||
#include <qbytearray.h>
|
||||
|
||||
#define GVARS_VARIANT 0x0001
|
||||
#define FRSKY_VARIANT 0x0002
|
||||
#define MAVLINK_VARIANT 0x0008
|
||||
#define M128_VARIANT 0x8000
|
||||
#define TARANIS_X9E_VARIANT 0x8000
|
||||
#define TARANIS_X7_VARIANT 0x4000
|
||||
#define TARANIS_XLITE_VARIANT 0x2000
|
||||
|
||||
#define SIMU_STOCK_VARIANTS (GVARS_VARIANT|FRSKY_VARIANT)
|
||||
#define SIMU_M128_VARIANTS (M128_VARIANT|SIMU_STOCK_VARIANTS)
|
||||
|
||||
class OpenTxGeneralData: public TransformedField {
|
||||
public:
|
||||
OpenTxGeneralData(GeneralSettings & generalData, Board::Type board, unsigned int version, unsigned int variant=0);
|
||||
|
||||
virtual const QString & getName() { return internalField.getName(); }
|
||||
|
||||
QStringList errors()
|
||||
{
|
||||
return _errors;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void beforeExport();
|
||||
virtual void afterImport();
|
||||
|
||||
virtual void setError(const QString & error)
|
||||
{
|
||||
qWarning() << error;
|
||||
_errors << error;
|
||||
}
|
||||
|
||||
StructField internalField;
|
||||
GeneralSettings & generalData;
|
||||
Board::Type board;
|
||||
unsigned int version;
|
||||
int inputsCount;
|
||||
unsigned int chkSum;
|
||||
QStringList _errors;
|
||||
};
|
||||
|
||||
class ProtocolsConversionTable: public ConversionTable
|
||||
{
|
||||
public:
|
||||
ProtocolsConversionTable(Board::Type board)
|
||||
{
|
||||
int val = 0;
|
||||
if (IS_ARM(board)) {
|
||||
addConversion(PULSES_OFF, val++);
|
||||
}
|
||||
addConversion(PULSES_PPM, val++);
|
||||
if (!IS_ARM(board)) {
|
||||
addConversion(PULSES_PPM16, val++);
|
||||
addConversion(PULSES_PPMSIM, val++);
|
||||
}
|
||||
if (IS_ARM(board)) {
|
||||
addConversion(PULSES_PXX_XJT_X16, val);
|
||||
addConversion(PULSES_PXX_XJT_D8, val);
|
||||
addConversion(PULSES_PXX_XJT_LR12, val++);
|
||||
}
|
||||
else {
|
||||
addConversion(PULSES_PXX_DJT, val++);
|
||||
}
|
||||
if (IS_ARM(board)) {
|
||||
addConversion(PULSES_LP45, val);
|
||||
addConversion(PULSES_DSM2, val);
|
||||
addConversion(PULSES_DSMX, val++);
|
||||
}
|
||||
else {
|
||||
addConversion(PULSES_LP45, val++);
|
||||
addConversion(PULSES_DSM2, val++);
|
||||
addConversion(PULSES_DSMX, val++);
|
||||
}
|
||||
if (IS_ARM(board)) {
|
||||
addConversion(PULSES_CROSSFIRE, val++);
|
||||
addConversion(PULSES_MULTIMODULE, val++);
|
||||
addConversion(PULSES_PXX_R9M, val++);
|
||||
addConversion(PULSES_SBUS, val++);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ChannelsConversionTable: public ConversionTable
|
||||
{
|
||||
public:
|
||||
ChannelsConversionTable()
|
||||
{
|
||||
for (int i=4; i<=16; i+= 2)
|
||||
addConversion(i, -4+i/2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class OpenTxModelData: public TransformedField {
|
||||
public:
|
||||
OpenTxModelData(ModelData & modelData, Board::Type board, unsigned int version, unsigned int variant);
|
||||
|
||||
virtual const QString & getName() { return internalField.getName(); }
|
||||
|
||||
QStringList errors()
|
||||
{
|
||||
return _errors;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void beforeExport();
|
||||
virtual void afterImport();
|
||||
|
||||
virtual void setError(const QString & error)
|
||||
{
|
||||
qWarning() << error;
|
||||
_errors << error;
|
||||
}
|
||||
|
||||
StructField internalField;
|
||||
ModelData & modelData;
|
||||
Board::Type board;
|
||||
unsigned int version;
|
||||
unsigned int variant;
|
||||
char name[256];
|
||||
int subprotocols[CPN_MAX_MODULES+1/*trainer*/];
|
||||
ProtocolsConversionTable protocolsConversionTable;
|
||||
ChannelsConversionTable channelsConversionTable;
|
||||
QStringList _errors;
|
||||
};
|
||||
|
||||
void OpenTxEepromCleanup(void);
|
||||
#endif // _OPENTXEEPROM_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _OPENTXINTERFACE_H_
|
||||
#define _OPENTXINTERFACE_H_
|
||||
|
||||
#include "eeprominterface.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class RleFile;
|
||||
class OpenTxFirmware;
|
||||
|
||||
class OpenTxEepromInterface : public EEPROMInterface
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(OpenTxEepromInterface)
|
||||
|
||||
public:
|
||||
|
||||
OpenTxEepromInterface(OpenTxFirmware * firmware);
|
||||
|
||||
virtual ~OpenTxEepromInterface();
|
||||
|
||||
virtual unsigned long load(RadioData &, const uint8_t * eeprom, int size);
|
||||
|
||||
bool loadModelFromBackup(ModelData & model, const uint8_t * data, unsigned int size, uint8_t version, uint32_t variant);
|
||||
|
||||
virtual unsigned long loadBackup(RadioData &, const uint8_t * eeprom, int esize, int index);
|
||||
|
||||
virtual int save(uint8_t * eeprom, const RadioData & radioData, uint8_t version=0, uint32_t variant=0);
|
||||
|
||||
virtual int getSize(const ModelData &);
|
||||
|
||||
virtual int getSize(const GeneralSettings &);
|
||||
|
||||
protected:
|
||||
|
||||
const char * getName();
|
||||
|
||||
EepromLoadErrors checkVersion(unsigned int version);
|
||||
|
||||
bool checkVariant(unsigned int version, unsigned int variant);
|
||||
|
||||
template <class T, class M>
|
||||
bool loadFromByteArray(T & dest, const QByteArray & data, uint8_t version, uint32_t variant=0);
|
||||
|
||||
public:
|
||||
template <class T, class M>
|
||||
bool loadFromByteArray(T & dest, const QByteArray & data);
|
||||
|
||||
template <class T, class M>
|
||||
bool saveToByteArray(const T & src, QByteArray & data, uint8_t version=0);
|
||||
|
||||
bool loadRadioSettingsFromRLE(GeneralSettings & settings, RleFile * rleFile, uint8_t version);
|
||||
|
||||
bool loadModelFromRLE(ModelData & model, RleFile * rleFile, unsigned int index, uint8_t version, uint32_t variant);
|
||||
|
||||
void showErrors(const QString & title, const QStringList & errors);
|
||||
|
||||
uint8_t getLastDataVersion(Board::Type board);
|
||||
|
||||
RleFile * efile;
|
||||
|
||||
OpenTxFirmware * firmware;
|
||||
|
||||
};
|
||||
|
||||
class OpenTxFirmware: public Firmware
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(OpenTxFirmware)
|
||||
|
||||
public:
|
||||
OpenTxFirmware(const QString & id, OpenTxFirmware * parent):
|
||||
Firmware(parent, id, parent->getName(), parent->getBoard())
|
||||
{
|
||||
setEEpromInterface(parent->getEEpromInterface());
|
||||
}
|
||||
|
||||
OpenTxFirmware(const QString & id, const QString & name, const Board::Type board):
|
||||
Firmware(id, name, board)
|
||||
{
|
||||
addLanguage("en");
|
||||
addLanguage("cz");
|
||||
addLanguage("de");
|
||||
addLanguage("es");
|
||||
addLanguage("fr");
|
||||
addLanguage("it");
|
||||
addLanguage("nl");
|
||||
addLanguage("pl");
|
||||
addLanguage("pt");
|
||||
addLanguage("se");
|
||||
}
|
||||
|
||||
virtual Firmware * getFirmwareVariant(const QString & id);
|
||||
|
||||
virtual QString getStampUrl();
|
||||
|
||||
virtual QString getReleaseNotesUrl();
|
||||
|
||||
virtual QString getFirmwareUrl();
|
||||
|
||||
virtual int getCapability(Capability);
|
||||
|
||||
virtual QString getAnalogInputName(unsigned int index);
|
||||
|
||||
virtual QTime getMaxTimerStart();
|
||||
|
||||
virtual int isAvailable(PulsesProtocol proto, int port=0);
|
||||
|
||||
protected:
|
||||
|
||||
QString getFirmwareBaseUrl();
|
||||
|
||||
};
|
||||
|
||||
void registerOpenTxFirmwares();
|
||||
void unregisterOpenTxFirmwares();
|
||||
|
||||
extern QList<OpenTxEepromInterface *> opentxEEpromInterfaces;
|
||||
|
||||
OpenTxEepromInterface * loadModelFromByteArray(ModelData & model, const QByteArray & data);
|
||||
OpenTxEepromInterface * loadRadioSettingsFromByteArray(GeneralSettings & settings, const QByteArray & data);
|
||||
|
||||
bool writeModelToByteArray(const ModelData & model, QByteArray & data);
|
||||
bool writeRadioSettingsToByteArray(const GeneralSettings & settings, QByteArray & data);
|
||||
|
||||
#endif // _OPENTXINTERFACE_H_
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "radiodata.h"
|
||||
#include "radiodataconversionstate.h"
|
||||
#include "eeprominterface.h"
|
||||
|
||||
// static
|
||||
QString RadioData::getElementName(const QString & prefix, unsigned int index, const char * name, bool padding)
|
||||
{
|
||||
QString result = prefix;
|
||||
if (padding)
|
||||
result += QString("%1").arg(index, 2, 10, QChar('0'));
|
||||
else
|
||||
result += QString("%1").arg(index);
|
||||
if (name) {
|
||||
QString trimmed = QString(name).trimmed();
|
||||
if (trimmed.length() > 0) {
|
||||
result += ":" + QString(name).trimmed();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
RadioData::RadioData()
|
||||
{
|
||||
models.resize(getCurrentFirmware()->getCapability(Models));
|
||||
}
|
||||
|
||||
void RadioData::setCurrentModel(unsigned int index)
|
||||
{
|
||||
generalSettings.currModelIndex = index;
|
||||
if (index < models.size()) {
|
||||
strcpy(generalSettings.currModelFilename, models[index].filename);
|
||||
}
|
||||
}
|
||||
|
||||
void RadioData::fixModelFilename(unsigned int index)
|
||||
{
|
||||
ModelData & model = models[index];
|
||||
QString filename(model.filename);
|
||||
bool ok = filename.endsWith(".bin");
|
||||
if (ok) {
|
||||
if (filename.startsWith("model") && filename.mid(5, filename.length()-9).toInt() > 0) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
for (unsigned i=0; i<index; i++) {
|
||||
if (strcmp(models[i].filename, model.filename) == 0) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
sprintf(model.filename, "model%d.bin", index+1);
|
||||
}
|
||||
}
|
||||
|
||||
void RadioData::fixModelFilenames()
|
||||
{
|
||||
for (unsigned int i=0; i<models.size(); i++) {
|
||||
fixModelFilename(i);
|
||||
}
|
||||
setCurrentModel(generalSettings.currModelIndex);
|
||||
}
|
||||
|
||||
QString RadioData::getNextModelFilename()
|
||||
{
|
||||
char filename[sizeof(ModelData::filename)];
|
||||
int index = 0;
|
||||
bool found = true;
|
||||
while (found) {
|
||||
sprintf(filename, "model%d.bin", ++index);
|
||||
found = false;
|
||||
for (unsigned int i=0; i<models.size(); i++) {
|
||||
if (strcmp(filename, models[i].filename) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
void RadioData::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
generalSettings.convert(cstate.withModelIndex(-1));
|
||||
|
||||
for (unsigned i=0; i<models.size(); i++) {
|
||||
models[i].convert(cstate.withModelIndex(i));
|
||||
}
|
||||
|
||||
if (categories.size() == 0) {
|
||||
categories.push_back(CategoryData(qPrintable(tr("Models"))));
|
||||
for (unsigned i=0; i<models.size(); i++) {
|
||||
models[i].category = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_HORUS(cstate.toType)) {
|
||||
fixModelFilenames();
|
||||
}
|
||||
|
||||
// ensure proper number of model slots
|
||||
if (getCurrentFirmware()->getCapability(Models) && getCurrentFirmware()->getCapability(Models) != (int)models.size()) {
|
||||
models.resize(getCurrentFirmware()->getCapability(Models));
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#ifndef _RADIODATA_H_
|
||||
#define _RADIODATA_H_
|
||||
|
||||
#include "generalsettings.h"
|
||||
#include "modeldata.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class RadioDataConversionState;
|
||||
|
||||
class CategoryData {
|
||||
public:
|
||||
CategoryData(const char * name) {
|
||||
strncpy(this->name, name, sizeof(CategoryData::name));
|
||||
}
|
||||
char name[15+1];
|
||||
};
|
||||
|
||||
class RadioData {
|
||||
Q_DECLARE_TR_FUNCTIONS(RadioData)
|
||||
|
||||
public:
|
||||
RadioData();
|
||||
|
||||
GeneralSettings generalSettings;
|
||||
std::vector<CategoryData> categories;
|
||||
std::vector<ModelData> models;
|
||||
|
||||
void convert(RadioDataConversionState & cstate);
|
||||
|
||||
void setCurrentModel(unsigned int index);
|
||||
void fixModelFilenames();
|
||||
QString getNextModelFilename();
|
||||
|
||||
static QString getElementName(const QString & prefix, unsigned int index, const char * name = 0, bool padding = false);
|
||||
|
||||
protected:
|
||||
void fixModelFilename(unsigned int index);
|
||||
};
|
||||
|
||||
#endif // _RADIODATA_H_
|
||||
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "radiodataconversionstate.h"
|
||||
#include "radiodata.h"
|
||||
|
||||
#include <QStandardItemModel>
|
||||
|
||||
RadioDataConversionState::RadioDataConversionState(Board::Type before, Board::Type after, RadioData * rdata) :
|
||||
fromType(before),
|
||||
toType(after),
|
||||
fromBoard(Boards(before)),
|
||||
toBoard(Boards(after)),
|
||||
rd(NULL),
|
||||
rdCopy(NULL),
|
||||
maxEventType(EVT_NONE),
|
||||
modelIdx(-1),
|
||||
subCompIdx(-1)
|
||||
{
|
||||
setRadioData(rdata);
|
||||
}
|
||||
|
||||
RadioDataConversionState::~RadioDataConversionState()
|
||||
{
|
||||
if (rdCopy)
|
||||
delete rdCopy;
|
||||
}
|
||||
|
||||
RadioDataConversionState & RadioDataConversionState::withModelIndex(int index)
|
||||
{
|
||||
modelIdx = index;
|
||||
subCompIdx = -1;
|
||||
setLogField(FLD_ORIGIN);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RadioDataConversionState & RadioDataConversionState::withComponentIndex(int index)
|
||||
{
|
||||
subCompIdx = index;
|
||||
setLogField(FLD_SUB_COMP);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RadioDataConversionState &RadioDataConversionState::withComponentField(const QString & name)
|
||||
{
|
||||
setLogField(FLD_COMP_FIELD, LogField(0, name));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool RadioDataConversionState::convert()
|
||||
{
|
||||
if (rd) {
|
||||
rd->convert(*this);
|
||||
return true;
|
||||
}
|
||||
|
||||
setErr(("No radio data to convert."));
|
||||
return false;
|
||||
}
|
||||
|
||||
void RadioDataConversionState::setRadioData(RadioData * rdata)
|
||||
{
|
||||
rd = rdata;
|
||||
if (rdCopy)
|
||||
delete rdCopy;
|
||||
rdCopy = new RadioData(*rdata);
|
||||
logCache = LogRecord();
|
||||
}
|
||||
|
||||
void RadioDataConversionState::setLogField(LogFieldType type, const LogField & data, bool clearRest)
|
||||
{
|
||||
if (type >= FLD_ENUM_COUNT)
|
||||
return;
|
||||
|
||||
logCache.fields[type].id = data.id;
|
||||
logCache.fields[type].name = data.name;
|
||||
if (clearRest && type + 1 < FLD_ENUM_COUNT)
|
||||
setLogField(LogFieldType(type + 1));
|
||||
}
|
||||
|
||||
void RadioDataConversionState::addLogEntry(EventType event, const QString & msg)
|
||||
{
|
||||
if (event != EVT_NONE) {
|
||||
setLogField(FLD_EVT_TYPE, LogField(event, eventTypeToString(event)), false);
|
||||
setLogField(FLD_MSG, LogField(event, msg), false);
|
||||
log.append(logCache);
|
||||
}
|
||||
maxEventType = qMax(event, maxEventType);
|
||||
logCache.fields[FLD_MSG].clear();
|
||||
}
|
||||
|
||||
void RadioDataConversionState::setInvalid(const LogField & item)
|
||||
{
|
||||
setLogField(FLD_ITM_BEFORE, item);
|
||||
addLogEntry(EVT_INV, tr("is invalid"));
|
||||
}
|
||||
|
||||
void RadioDataConversionState::setConverted(const LogField & from, const LogField & to)
|
||||
{
|
||||
setLogField(FLD_ITM_BEFORE, from);
|
||||
setLogField(FLD_ITM_AFTER, to);
|
||||
addLogEntry(EVT_CVRT, tr("converted to"));
|
||||
}
|
||||
|
||||
void RadioDataConversionState::setMoved(const LogField & from, const LogField & to)
|
||||
{
|
||||
setLogField(FLD_ITM_BEFORE, from);
|
||||
setLogField(FLD_ITM_AFTER, to);
|
||||
addLogEntry(EVT_INF, tr("verify is"));
|
||||
}
|
||||
|
||||
const ModelData * RadioDataConversionState::toModel() const
|
||||
{
|
||||
if (rd && modelIdx > -1 && modelIdx < (int)rd->models.size())
|
||||
return &rd->models[modelIdx];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const ModelData *RadioDataConversionState::fromModel() const
|
||||
{
|
||||
if (rdCopy && modelIdx > -1 && modelIdx < (int)rdCopy->models.size())
|
||||
return &rdCopy->models[modelIdx];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const GeneralSettings * RadioDataConversionState::toGS() const
|
||||
{
|
||||
if (rd)
|
||||
return &rd->generalSettings;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const GeneralSettings *RadioDataConversionState::fromGS() const
|
||||
{
|
||||
if (rdCopy)
|
||||
return &rdCopy->generalSettings;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool RadioDataConversionState::hasLogEntries(EventType logLevel) const
|
||||
{
|
||||
return (maxEventType >= logLevel);
|
||||
}
|
||||
|
||||
QString RadioDataConversionState::eventTypeToString(int type) const
|
||||
{
|
||||
// enum EventType { EVT_NONE, EVT_DBG, EVT_INF, EVT_WRN, EVT_CVRT, EVT_ERR, EVT_INV
|
||||
static const QStringList evtTypes = QStringList() << "" << tr("[DBG]") << tr("[NFO]") << tr("[WRN]") << tr("[CVT]") << tr("[ERR]") << tr("[INV]");
|
||||
return (type < evtTypes.size() ? evtTypes.at(type) : "");
|
||||
}
|
||||
|
||||
QString RadioDataConversionState::eventTypeToColor(int type) const
|
||||
{
|
||||
// enum EventType { EVT_NONE, EVT_DBG, EVT_INF, EVT_WRN, EVT_CVRT, EVT_ERR, EVT_INV
|
||||
static const QStringList evtColors = QStringList() << "black" << "dimgrey" << "black" << "#ea7104" << "#ea7104" << "red" << "red";
|
||||
return (type < evtColors.size() ? evtColors.at(type) : "black");
|
||||
}
|
||||
|
||||
QString RadioDataConversionState::getFieldName(int field) const
|
||||
{
|
||||
static const QStringList dataFields = QStringList() << tr("Event") << tr("Origin") << tr("Comp") << tr("Sub-Component") << tr("Field") << tr("Type") << tr("Old") << tr("Action") << tr("New");
|
||||
return (field < dataFields.size() ? dataFields.at(field) : "");
|
||||
}
|
||||
|
||||
QStandardItemModel * RadioDataConversionState::getLogModel(RadioDataConversionState::EventType logLevel, QObject * parent) const
|
||||
{
|
||||
QStandardItemModel * stdmdl = new QStandardItemModel(parent);
|
||||
const QString tooltip = "%1: %2 (ID: %3)";
|
||||
const int sortRole = Qt::UserRole + 1;
|
||||
const int seqdigits = floorf(logf(log.size()) / logf(10.0f)) + 1;
|
||||
|
||||
stdmdl->setSortRole(sortRole);
|
||||
|
||||
QStringList header;
|
||||
header << tr("Seq");
|
||||
for (int i=0; i < FLD_ENUM_COUNT; ++i)
|
||||
header << getFieldName(i);
|
||||
stdmdl->setHorizontalHeaderLabels(header);
|
||||
|
||||
QFont fnt("Courier");
|
||||
fnt.setStyleHint(QFont::TypeWriter);
|
||||
//fnt.setPointSize(fnt.pointSize()+1);
|
||||
|
||||
int row = 0;
|
||||
foreach (const LogRecord & lr, log) {
|
||||
if (lr.fields.at(FLD_EVT_TYPE).id < logLevel)
|
||||
continue;
|
||||
QBrush fg(QColor(eventTypeToColor(lr.fields.at(FLD_EVT_TYPE).id)));
|
||||
stdmdl->setItem(row, 0, new QStandardItem(QString("%1").arg(row+1, seqdigits, 10, QChar('0'))));
|
||||
stdmdl->item(row, 0)->setData(row, sortRole);
|
||||
stdmdl->item(row, 0)->setData(fnt, Qt::FontRole);
|
||||
for (int i=0; i < FLD_ENUM_COUNT; ++i) {
|
||||
QStandardItem * itm = new QStandardItem(lr.fields.at(i).name);
|
||||
itm->setData(lr.fields.at(i).id, sortRole);
|
||||
itm->setData(fnt, Qt::FontRole);
|
||||
itm->setData(tooltip.arg(getFieldName(i)).arg(lr.fields.at(i).name).arg(lr.fields.at(i).id), Qt::ToolTipRole);
|
||||
itm->setEditable(false);
|
||||
if (i == FLD_EVT_TYPE || i == FLD_MSG)
|
||||
itm->setForeground(fg);
|
||||
stdmdl->setItem(row, i+1, itm);
|
||||
}
|
||||
++row;
|
||||
}
|
||||
|
||||
return stdmdl;
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RADIODATACONVERSIONSTATE_H
|
||||
#define RADIODATACONVERSIONSTATE_H
|
||||
|
||||
#include "boards.h"
|
||||
#include <QtCore>
|
||||
|
||||
class ModelData;
|
||||
class GeneralSettings;
|
||||
class RadioData;
|
||||
class QStandardItemModel;
|
||||
|
||||
class RadioDataConversionState
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(RadioDataConversionState)
|
||||
|
||||
public:
|
||||
enum EventType {
|
||||
EVT_NONE, // does not get logged
|
||||
EVT_DBG, // debug
|
||||
EVT_INF, // misc. info
|
||||
EVT_WRN, // misc. warning, place warning-level events after this and before EVT_ERR
|
||||
EVT_CVRT, // something was converted (A->B)
|
||||
EVT_ERR, // misc. error, place error-level events after this
|
||||
EVT_INV, // invalid, control/etc not available on destination radio
|
||||
};
|
||||
|
||||
enum LogFieldType {
|
||||
FLD_EVT_TYPE, // EventType
|
||||
FLD_ORIGIN, // General Settings or Model with name
|
||||
FLD_COMP, // Input/Mix/LS/CF/etc
|
||||
FLD_SUB_COMP, // Mix channel/Input line/LS number/etc
|
||||
FLD_COMP_FIELD, // optional item within subcomponent, eg. LS V1/V2/AND, etc
|
||||
FLD_ITM_TYPE, // Source/Switch
|
||||
FLD_ITM_BEFORE, // item before conversion
|
||||
FLD_MSG, // conversion details
|
||||
FLD_ITM_AFTER, // item after conversion
|
||||
FLD_ENUM_COUNT
|
||||
};
|
||||
|
||||
struct LogField {
|
||||
LogField(int id = 0, const QString & name = QString()) : id(id), name(name) {}
|
||||
void clear() { id = 0; name.clear(); }
|
||||
int id;
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct LogRecord
|
||||
{
|
||||
LogRecord() { fields.resize(FLD_ENUM_COUNT); }
|
||||
QVector<LogField> fields; // collected data fields indexed by LogColumn value
|
||||
};
|
||||
|
||||
RadioDataConversionState(Board::Type before = Board::BOARD_UNKNOWN, Board::Type after = Board::BOARD_UNKNOWN, RadioData * rdata = NULL);
|
||||
~RadioDataConversionState();
|
||||
|
||||
RadioDataConversionState & withModelIndex(int index);
|
||||
RadioDataConversionState & withComponentIndex(int index);
|
||||
RadioDataConversionState & withComponentField(const QString & name);
|
||||
|
||||
bool convert();
|
||||
void setRadioData(RadioData * rdata);
|
||||
void setLogField(LogFieldType type, const LogField & data = LogField(), bool clearRest = true);
|
||||
inline void setOrigin(const QString & name = QString()) { setLogField(FLD_ORIGIN, LogField(modelIdx, name)); }
|
||||
inline void setSubComp(const QString & name = QString()) { setLogField(FLD_SUB_COMP, LogField(subCompIdx, name)); }
|
||||
inline void setComponent(const QString & name = QString(), int id = 0) { setLogField(FLD_COMP, LogField(id, name)); }
|
||||
inline void setItemType(const QString & name = QString(), int id = 0) { setLogField(FLD_ITM_TYPE, LogField(id, name)); }
|
||||
|
||||
void addLogEntry(EventType event, const QString & msg = QString());
|
||||
void setInvalid(const LogField & item);
|
||||
void setConverted(const LogField & from, const LogField & to);
|
||||
void setMoved(const LogField & from, const LogField & to);
|
||||
inline void setDbg(const QString & msg) { addLogEntry(EVT_DBG, msg); }
|
||||
inline void setInf(const QString & msg) { addLogEntry(EVT_INF, msg); }
|
||||
inline void setWrn(const QString & msg) { addLogEntry(EVT_WRN, msg); }
|
||||
inline void setErr(const QString & msg) { addLogEntry(EVT_ERR, msg); }
|
||||
|
||||
const ModelData * toModel() const;
|
||||
const ModelData * fromModel() const;
|
||||
const GeneralSettings * toGS() const;
|
||||
const GeneralSettings * fromGS() const;
|
||||
bool hasLogEntries(EventType logLevel = EVT_INF) const;
|
||||
|
||||
QString eventTypeToString(int type) const;
|
||||
QString eventTypeToColor(int type) const;
|
||||
QString getFieldName(int field) const;
|
||||
QStandardItemModel * getLogModel(EventType logLevel = EVT_INF, QObject *parent = Q_NULLPTR) const;
|
||||
|
||||
Board::Type fromType; // board type before conversion
|
||||
Board::Type toType; // board type after
|
||||
Boards fromBoard;
|
||||
Boards toBoard;
|
||||
RadioData * rd; // pointer to data struct being converted
|
||||
RadioData * rdCopy; // copy of original radio data before conversion
|
||||
QVector<LogRecord> log; // logged events
|
||||
LogRecord logCache; // buffer for holding event data before logging
|
||||
EventType maxEventType; // most severe event type recorded
|
||||
int modelIdx; // model index in radio data array, -1 if none
|
||||
int subCompIdx; // current row index within component (eg. model.mixData[componentIdx]), -1 if none
|
||||
};
|
||||
|
||||
#endif // RADIODATACONVERSIONSTATE_H
|
||||
@@ -1,644 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rawsource.h"
|
||||
|
||||
#include "eeprominterface.h"
|
||||
#include "radiodata.h"
|
||||
#include "radiodataconversionstate.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
/*
|
||||
* RawSourceRange
|
||||
*/
|
||||
|
||||
float RawSourceRange::getValue(int value)
|
||||
{
|
||||
if (IS_ARM(getCurrentBoard()))
|
||||
return float(value) * step;
|
||||
else
|
||||
return min + float(value) * step;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RawSource
|
||||
*/
|
||||
|
||||
RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSettings & settings, unsigned int flags) const
|
||||
{
|
||||
RawSourceRange result;
|
||||
|
||||
Firmware * firmware = Firmware::getCurrentVariant();
|
||||
int board = firmware->getBoard();
|
||||
|
||||
switch (type) {
|
||||
case SOURCE_TYPE_TELEMETRY:
|
||||
if (IS_ARM(board)) {
|
||||
div_t qr = div(index, 3);
|
||||
const SensorData & sensor = model->sensorData[qr.quot];
|
||||
if (sensor.prec == 2)
|
||||
result.step = 0.01;
|
||||
else if (sensor.prec == 1)
|
||||
result.step = 0.1;
|
||||
else
|
||||
result.step = 1;
|
||||
result.min = -30000 * result.step;
|
||||
result.max = +30000 * result.step;
|
||||
result.decimals = sensor.prec;
|
||||
result.unit = sensor.unitString();
|
||||
}
|
||||
else {
|
||||
result.offset = -DBL_MAX;
|
||||
|
||||
switch (index) {
|
||||
case TELEMETRY_SOURCE_TX_BATT:
|
||||
result.step = 0.1;
|
||||
result.decimals = 1;
|
||||
result.max = 25.5;
|
||||
result.unit = tr("V");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_TX_TIME:
|
||||
result.step = 60;
|
||||
result.max = 24 * 60 * result.step - 60; // 23:59:00 with 1-minute resolution
|
||||
result.unit = tr("s");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_TIMER1:
|
||||
case TELEMETRY_SOURCE_TIMER2:
|
||||
case TELEMETRY_SOURCE_TIMER3:
|
||||
result.step = 5;
|
||||
result.max = 255 * result.step;
|
||||
result.unit = tr("s");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_RSSI_TX:
|
||||
case TELEMETRY_SOURCE_RSSI_RX:
|
||||
result.max = 100;
|
||||
result.offset = 128;
|
||||
break;
|
||||
case TELEMETRY_SOURCE_A1_MIN:
|
||||
case TELEMETRY_SOURCE_A2_MIN:
|
||||
case TELEMETRY_SOURCE_A3_MIN:
|
||||
case TELEMETRY_SOURCE_A4_MIN:
|
||||
if (model) result = model->frsky.channels[index-TELEMETRY_SOURCE_A1_MIN].getRange();
|
||||
break;
|
||||
case TELEMETRY_SOURCE_A1:
|
||||
case TELEMETRY_SOURCE_A2:
|
||||
case TELEMETRY_SOURCE_A3:
|
||||
case TELEMETRY_SOURCE_A4:
|
||||
if (model) result = model->frsky.channels[index-TELEMETRY_SOURCE_A1].getRange();
|
||||
break;
|
||||
case TELEMETRY_SOURCE_ALT:
|
||||
case TELEMETRY_SOURCE_ALT_MIN:
|
||||
case TELEMETRY_SOURCE_ALT_MAX:
|
||||
case TELEMETRY_SOURCE_GPS_ALT:
|
||||
result.step = 8;
|
||||
result.min = -500;
|
||||
result.max = 1540;
|
||||
if (firmware->getCapability(Imperial) || settings.imperial) {
|
||||
result.step = (result.step * 105) / 32;
|
||||
result.min = (result.min * 105) / 32;
|
||||
result.max = (result.max * 105) / 32;
|
||||
result.unit = tr("ft");
|
||||
}
|
||||
else {
|
||||
result.unit = tr("m");
|
||||
}
|
||||
break;
|
||||
case TELEMETRY_SOURCE_T1:
|
||||
case TELEMETRY_SOURCE_T1_MAX:
|
||||
case TELEMETRY_SOURCE_T2:
|
||||
case TELEMETRY_SOURCE_T2_MAX:
|
||||
result.min = -30;
|
||||
result.max = 225;
|
||||
result.unit = trUtf8("°C");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_HDG:
|
||||
result.step = 2;
|
||||
result.max = 360;
|
||||
result.offset = 256;
|
||||
result.unit = trUtf8("°");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_RPM:
|
||||
case TELEMETRY_SOURCE_RPM_MAX:
|
||||
result.step = 50;
|
||||
result.max = 12750;
|
||||
break;
|
||||
case TELEMETRY_SOURCE_FUEL:
|
||||
result.max = 100;
|
||||
result.unit = tr("%");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_ASPEED:
|
||||
case TELEMETRY_SOURCE_ASPEED_MAX:
|
||||
result.decimals = 1;
|
||||
result.step = 2.0;
|
||||
result.max = (2*255);
|
||||
if (firmware->getCapability(Imperial) || settings.imperial) {
|
||||
result.step *= 1.150779;
|
||||
result.max *= 1.150779;
|
||||
result.unit = tr("mph");
|
||||
}
|
||||
else {
|
||||
result.step *= 1.852;
|
||||
result.max *= 1.852;
|
||||
result.unit = tr("km/h");
|
||||
}
|
||||
break;
|
||||
case TELEMETRY_SOURCE_SPEED:
|
||||
case TELEMETRY_SOURCE_SPEED_MAX:
|
||||
result.step = 2;
|
||||
result.max = (2*255);
|
||||
if (firmware->getCapability(Imperial) || settings.imperial) {
|
||||
result.step *= 1.150779;
|
||||
result.max *= 1.150779;
|
||||
result.unit = tr("mph");
|
||||
}
|
||||
else {
|
||||
result.step *= 1.852;
|
||||
result.max *= 1.852;
|
||||
result.unit = tr("km/h");
|
||||
}
|
||||
break;
|
||||
case TELEMETRY_SOURCE_VERTICAL_SPEED:
|
||||
result.step = 0.1;
|
||||
result.min = -12.5;
|
||||
result.max = 13.0;
|
||||
result.decimals = 1;
|
||||
result.unit = tr("m/s");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_DTE:
|
||||
result.max = 30000;
|
||||
break;
|
||||
case TELEMETRY_SOURCE_DIST:
|
||||
case TELEMETRY_SOURCE_DIST_MAX:
|
||||
result.step = 8;
|
||||
result.max = 2040;
|
||||
result.unit = tr("m");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_CELL:
|
||||
case TELEMETRY_SOURCE_CELL_MIN:
|
||||
result.step = 0.02;
|
||||
result.max = 5.1;
|
||||
result.decimals = 2;
|
||||
result.unit = tr("V");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_CELLS_SUM:
|
||||
case TELEMETRY_SOURCE_CELLS_MIN:
|
||||
case TELEMETRY_SOURCE_VFAS:
|
||||
case TELEMETRY_SOURCE_VFAS_MIN:
|
||||
result.step = 0.1;
|
||||
result.max = 25.5;
|
||||
result.decimals = 1;
|
||||
result.unit = tr("V");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_CURRENT:
|
||||
case TELEMETRY_SOURCE_CURRENT_MAX:
|
||||
result.step = 0.5;
|
||||
result.max = 127.5;
|
||||
result.decimals = 1;
|
||||
result.unit = tr("A");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_CONSUMPTION:
|
||||
result.step = 100;
|
||||
result.max = 25500;
|
||||
result.unit = tr("mAh");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_POWER:
|
||||
case TELEMETRY_SOURCE_POWER_MAX:
|
||||
result.step = 5;
|
||||
result.max = 1275;
|
||||
result.unit = tr("W");
|
||||
break;
|
||||
case TELEMETRY_SOURCE_ACCX:
|
||||
case TELEMETRY_SOURCE_ACCY:
|
||||
case TELEMETRY_SOURCE_ACCZ:
|
||||
result.step = 0.01;
|
||||
result.decimals = 2;
|
||||
result.max = 2.55;
|
||||
result.min = 0;
|
||||
result.unit = tr("g");
|
||||
break;
|
||||
default:
|
||||
result.max = 125;
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.offset == -DBL_MAX) {
|
||||
result.offset = result.max - (127*result.step);
|
||||
}
|
||||
|
||||
if (flags & (RANGE_DELTA_FUNCTION | RANGE_ABS_FUNCTION)) {
|
||||
result.offset = 0;
|
||||
result.min = result.step * -127;
|
||||
result.max = result.step * 127;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SOURCE_TYPE_LUA_OUTPUT:
|
||||
result.max = 30000;
|
||||
result.min = -result.max;
|
||||
break;
|
||||
|
||||
case SOURCE_TYPE_TRIM:
|
||||
result.max = (model && model->extendedTrims ? firmware->getCapability(ExtendedTrimsRange) : firmware->getCapability(TrimsRange));
|
||||
result.min = -result.max;
|
||||
break;
|
||||
|
||||
case SOURCE_TYPE_GVAR: {
|
||||
GVarData gv = model->gvarData[index];
|
||||
result.step = gv.multiplierGet();
|
||||
result.decimals = gv.prec;
|
||||
result.max = gv.getMaxPrec();
|
||||
result.min = gv.getMinPrec();
|
||||
result.unit = gv.unitToString();
|
||||
break;
|
||||
}
|
||||
|
||||
case SOURCE_TYPE_SPECIAL:
|
||||
if (index == 0) { //Batt
|
||||
result.step = 0.1;
|
||||
result.decimals = 1;
|
||||
result.max = 25.5;
|
||||
result.unit = tr("V");
|
||||
}
|
||||
else if (index == 1) { //Time
|
||||
result.step = 60;
|
||||
result.max = 24 * 60 * result.step - 60; // 23:59:00 with 1-minute resolution
|
||||
result.unit = tr("s");
|
||||
}
|
||||
else { // Timers 1 - 3
|
||||
result.step = 1;
|
||||
result.max = 9 * 60 * 60 - 1; // 8:59:59 (to match firmware)
|
||||
result.min = -result.max;
|
||||
result.unit = tr("s");
|
||||
}
|
||||
break;
|
||||
|
||||
case SOURCE_TYPE_CH:
|
||||
result.max = model->getChannelsMax(false);
|
||||
result.min = -result.max;
|
||||
break;
|
||||
|
||||
default:
|
||||
result.max = 100;
|
||||
result.min = -result.max;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & RANGE_ABS_FUNCTION) {
|
||||
result.min = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString RawSource::toString(const ModelData * model, const GeneralSettings * const generalSettings, Board::Type board) const
|
||||
{
|
||||
if (board == Board::BOARD_UNKNOWN) {
|
||||
board = getCurrentBoard();
|
||||
}
|
||||
|
||||
static const QString trims[] = {
|
||||
tr("TrmR"), tr("TrmE"), tr("TrmT"), tr("TrmA"), tr("Trm5"), tr("Trm6")
|
||||
};
|
||||
|
||||
static const QString trims2[] = {
|
||||
tr("TrmH"), tr("TrmV")
|
||||
};
|
||||
|
||||
static const QString special[] = {
|
||||
tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"),
|
||||
};
|
||||
|
||||
static const QString telemetry[] = {
|
||||
tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"),
|
||||
tr("RAS"), tr("RSSI Tx"), tr("RSSI Rx"),
|
||||
tr("A1"), tr("A2"), tr("A3"), tr("A4"),
|
||||
tr("Alt"), tr("Rpm"), tr("Fuel"), tr("T1"), tr("T2"),
|
||||
tr("Speed"), tr("Dist"), tr("GPS Alt"),
|
||||
tr("Cell"), tr("Cells"), tr("Vfas"), tr("Curr"), tr("Cnsp"), tr("Powr"),
|
||||
tr("AccX"), tr("AccY"), tr("AccZ"),
|
||||
tr("Hdg "), tr("VSpd"), tr("AirSpeed"), tr("dTE"),
|
||||
tr("A1-"), tr("A2-"), tr("A3-"), tr("A4-"),
|
||||
tr("Alt-"), tr("Alt+"), tr("Rpm+"), tr("T1+"), tr("T2+"), tr("Speed+"), tr("Dist+"), tr("AirSpeed+"),
|
||||
tr("Cell-"), tr("Cells-"), tr("Vfas-"), tr("Curr+"), tr("Powr+"),
|
||||
tr("ACC"), tr("GPS Time"),
|
||||
};
|
||||
|
||||
static const QString rotary[] = { tr("REa"), tr("REb") };
|
||||
|
||||
if (index<0) {
|
||||
return tr("???");
|
||||
}
|
||||
|
||||
QString result;
|
||||
int genAryIdx = 0;
|
||||
switch (type) {
|
||||
case SOURCE_TYPE_NONE:
|
||||
return tr("----");
|
||||
|
||||
case SOURCE_TYPE_VIRTUAL_INPUT:
|
||||
{
|
||||
const char * name = NULL;
|
||||
if (model)
|
||||
name = model->inputNames[index];
|
||||
return RadioData::getElementName(tr("I", "as in Input"), index + 1, name);
|
||||
}
|
||||
|
||||
case SOURCE_TYPE_LUA_OUTPUT:
|
||||
return tr("LUA%1%2").arg(index/16+1).arg(QChar('a'+index%16));
|
||||
|
||||
case SOURCE_TYPE_STICK:
|
||||
if (generalSettings) {
|
||||
if (isPot(&genAryIdx))
|
||||
result = QString(generalSettings->potName[genAryIdx]);
|
||||
else if (isSlider(&genAryIdx))
|
||||
result = QString(generalSettings->sliderName[genAryIdx]);
|
||||
else if (isStick(&genAryIdx))
|
||||
result = QString(generalSettings->stickName[genAryIdx]);
|
||||
}
|
||||
if (result.isEmpty())
|
||||
result = Boards::getAnalogInputName(board, index);
|
||||
return result;
|
||||
|
||||
case SOURCE_TYPE_TRIM:
|
||||
return (Boards::getCapability(board, Board::NumTrims) == 2 ? CHECK_IN_ARRAY(trims2, index) : CHECK_IN_ARRAY(trims, index));
|
||||
|
||||
case SOURCE_TYPE_ROTARY_ENCODER:
|
||||
return CHECK_IN_ARRAY(rotary, index);
|
||||
|
||||
case SOURCE_TYPE_MAX:
|
||||
return tr("MAX");
|
||||
|
||||
case SOURCE_TYPE_SWITCH:
|
||||
if (generalSettings)
|
||||
result = QString(generalSettings->switchName[index]);
|
||||
if (result.isEmpty())
|
||||
result = Boards::getSwitchInfo(board, index).name;
|
||||
return result;
|
||||
|
||||
case SOURCE_TYPE_CUSTOM_SWITCH:
|
||||
return RawSwitch(SWITCH_TYPE_VIRTUAL, index+1).toString();
|
||||
|
||||
case SOURCE_TYPE_CYC:
|
||||
return tr("CYC%1").arg(index+1);
|
||||
|
||||
case SOURCE_TYPE_PPM:
|
||||
return RadioData::getElementName(tr("TR", "as in Trainer"), index + 1);
|
||||
|
||||
case SOURCE_TYPE_CH:
|
||||
if (model)
|
||||
return model->limitData[index].nameToString(index);
|
||||
else
|
||||
return LimitData().nameToString(index);
|
||||
|
||||
case SOURCE_TYPE_SPECIAL:
|
||||
return CHECK_IN_ARRAY(special, index);
|
||||
|
||||
case SOURCE_TYPE_TELEMETRY:
|
||||
if (IS_ARM(board)) {
|
||||
div_t qr = div(index, 3);
|
||||
if (model)
|
||||
result = model->sensorData[qr.quot].nameToString(qr.quot);
|
||||
else
|
||||
result = SensorData().nameToString(qr.quot);
|
||||
if (qr.rem)
|
||||
result += (qr.rem == 1 ? "-" : "+");
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return CHECK_IN_ARRAY(telemetry, index);
|
||||
}
|
||||
|
||||
case SOURCE_TYPE_GVAR:
|
||||
if (model)
|
||||
return model->gvarData[index].nameToString(index);
|
||||
else
|
||||
return GVarData().nameToString(index);
|
||||
|
||||
default:
|
||||
return tr("???");
|
||||
}
|
||||
}
|
||||
|
||||
bool RawSource::isStick(int * stickIndex, Board::Type board) const
|
||||
{
|
||||
if (board == Board::BOARD_UNKNOWN)
|
||||
board = getCurrentBoard();
|
||||
|
||||
if (type == SOURCE_TYPE_STICK && index < Boards::getCapability(board, Board::Sticks)) {
|
||||
if (stickIndex)
|
||||
*stickIndex = index;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RawSource::isPot(int * potsIndex, Board::Type board) const
|
||||
{
|
||||
if (board == Board::BOARD_UNKNOWN)
|
||||
board = getCurrentBoard();
|
||||
|
||||
Boards b(board);
|
||||
if (type == SOURCE_TYPE_STICK &&
|
||||
index >= b.getCapability(Board::Sticks) &&
|
||||
index < b.getCapability(Board::Sticks) + b.getCapability(Board::Pots)) {
|
||||
if (potsIndex)
|
||||
*potsIndex = index - b.getCapability(Board::Sticks);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RawSource::isSlider(int * sliderIndex, Board::Type board) const
|
||||
{
|
||||
if (board == Board::BOARD_UNKNOWN)
|
||||
board = getCurrentBoard();
|
||||
|
||||
Boards b(board);
|
||||
if (type == SOURCE_TYPE_STICK &&
|
||||
index >= b.getCapability(Board::Sticks) + b.getCapability(Board::Pots) &&
|
||||
index < b.getCapability(Board::Sticks) + b.getCapability(Board::Pots) + b.getCapability(Board::Sliders)) {
|
||||
if (sliderIndex)
|
||||
*sliderIndex = index - b.getCapability(Board::Sticks) - b.getCapability(Board::Pots);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RawSource::isTimeBased(Board::Type board) const
|
||||
{
|
||||
if (board == Board::BOARD_UNKNOWN)
|
||||
board = getCurrentBoard();
|
||||
|
||||
if (IS_ARM(board))
|
||||
return (type == SOURCE_TYPE_SPECIAL && index > 0);
|
||||
else
|
||||
return (type==SOURCE_TYPE_TELEMETRY && (index==TELEMETRY_SOURCE_TX_TIME || index==TELEMETRY_SOURCE_TIMER1 || index==TELEMETRY_SOURCE_TIMER2 || index==TELEMETRY_SOURCE_TIMER3));
|
||||
}
|
||||
|
||||
bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings * const gs, Board::Type board) const
|
||||
{
|
||||
if (board == Board::BOARD_UNKNOWN)
|
||||
board = getCurrentBoard();
|
||||
|
||||
Boards b(board);
|
||||
|
||||
if (type == SOURCE_TYPE_STICK && index >= b.getCapability(Board::MaxAnalogs))
|
||||
return false;
|
||||
|
||||
if (type == SOURCE_TYPE_SWITCH && index >= b.getCapability(Board::Switches))
|
||||
return false;
|
||||
|
||||
if (model) {
|
||||
if (type == SOURCE_TYPE_VIRTUAL_INPUT && !model->isInputValid(index))
|
||||
return false;
|
||||
|
||||
if (type == SOURCE_TYPE_CUSTOM_SWITCH && model->logicalSw[index].isEmpty())
|
||||
return false;
|
||||
|
||||
if (type == SOURCE_TYPE_TELEMETRY) {
|
||||
if (IS_ARM(board) && !model->sensorData[div(index, 3).quot].isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
else if (!IS_ARM(board)) {
|
||||
Firmware * fw = getCurrentFirmware();
|
||||
if (type == (int)TELEMETRY_SOURCE_TX_TIME && !fw->getCapability(RtcTime))
|
||||
return false;
|
||||
|
||||
if (type == (int)TELEMETRY_SOURCE_RAS && !fw->getCapability(SportTelemetry))
|
||||
return false;
|
||||
|
||||
if (type == (int)TELEMETRY_SOURCE_TIMER3 && fw->getCapability(Timers) < 3)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gs) {
|
||||
int gsIdx = 0;
|
||||
if (type == SOURCE_TYPE_STICK && ((isPot(&gsIdx) && !gs->isPotAvailable(gsIdx)) || (isSlider(&gsIdx) && !gs->isSliderAvailable(gsIdx))))
|
||||
return false;
|
||||
|
||||
if (type == SOURCE_TYPE_SWITCH && IS_HORUS_OR_TARANIS(board) && !gs->switchSourceAllowedTaranis(index))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == SOURCE_TYPE_TRIM && index >= b.getCapability(Board::NumTrims))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RawSource RawSource::convert(RadioDataConversionState & cstate)
|
||||
{
|
||||
cstate.setItemType(tr("SRC"), 1);
|
||||
RadioDataConversionState::EventType evt = RadioDataConversionState::EVT_NONE;
|
||||
RadioDataConversionState::LogField oldData(index, toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType));
|
||||
|
||||
if (type == SOURCE_TYPE_STICK) {
|
||||
if (cstate.toBoard.getCapability(Board::Sliders)) {
|
||||
if (index >= cstate.fromBoard.getCapability(Board::Sticks) + cstate.fromBoard.getCapability(Board::Pots)) {
|
||||
// 1st slider alignment
|
||||
index += cstate.toBoard.getCapability(Board::Pots) - cstate.fromBoard.getCapability(Board::Pots);
|
||||
}
|
||||
|
||||
if (isSlider(0, cstate.fromType)) {
|
||||
// LS and RS sliders are after 2 aux sliders on X12 and X9E
|
||||
if ((IS_HORUS_X12S(cstate.toType) || IS_TARANIS_X9E(cstate.toType)) && !IS_HORUS_X12S(cstate.fromType) && !IS_TARANIS_X9E(cstate.fromType)) {
|
||||
if (index >= 7) {
|
||||
index += 2; // LS/RS to LS/RS
|
||||
}
|
||||
}
|
||||
else if (!IS_TARANIS_X9E(cstate.toType) && !IS_HORUS_X12S(cstate.toType) && (IS_HORUS_X12S(cstate.fromType) || IS_TARANIS_X9E(cstate.fromType))) {
|
||||
if (index >= 7 && index <= 8) {
|
||||
index += 2; // aux sliders to spare analogs (which may not exist, this is validated later)
|
||||
evt = RadioDataConversionState::EVT_CVRT;
|
||||
}
|
||||
else if (index >= 9 && index <= 10) {
|
||||
index -= 2; // LS/RS to LS/RS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_TARANIS(cstate.toType) && IS_HORUS(cstate.fromType)) {
|
||||
if (index == 6)
|
||||
index = 5; // pot S2 to S2
|
||||
else if (index == 5)
|
||||
index = -1; // 6P on Horus doesn't exist on Taranis
|
||||
}
|
||||
else if (IS_HORUS(cstate.toType) && IS_TARANIS(cstate.fromType) && index == 5)
|
||||
{
|
||||
index = 6; // pot S2 to S2
|
||||
}
|
||||
|
||||
} // SOURCE_TYPE_STICK
|
||||
|
||||
if (type == SOURCE_TYPE_SWITCH) {
|
||||
// SWI to SWR don't exist on !X9E board
|
||||
if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) {
|
||||
if (index >= 8) {
|
||||
index = index % 8;
|
||||
evt = RadioDataConversionState::EVT_CVRT;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType))) {
|
||||
// No SE and SG on X7 board
|
||||
if (index == 4 || index == 6) {
|
||||
index = 3; // SG and SE to SD
|
||||
evt = RadioDataConversionState::EVT_CVRT;
|
||||
}
|
||||
else if (index == 5) {
|
||||
index = 4; // SF to SF
|
||||
}
|
||||
else if (index == 7) {
|
||||
index = 5; // SH to SH
|
||||
}
|
||||
}
|
||||
// Compensate for SE and SG on X9/Horus board if converting from X7
|
||||
else if ((IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) {
|
||||
if (index == 4) {
|
||||
index = 5; // SF to SF
|
||||
}
|
||||
else if (index == 5) {
|
||||
index = 7; // SH to SH
|
||||
}
|
||||
}
|
||||
} // SOURCE_TYPE_SWITCH
|
||||
|
||||
// final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted)
|
||||
if (!isAvailable(NULL, cstate.toGS(), cstate.toType)) {
|
||||
cstate.setInvalid(oldData);
|
||||
index = -1; // TODO: better way to flag invalid sources?
|
||||
type = MAX_SOURCE_TYPE;
|
||||
}
|
||||
else if (evt == RadioDataConversionState::EVT_CVRT) {
|
||||
cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toModel(), cstate.toGS(), cstate.toType)));
|
||||
}
|
||||
else if (oldData.id != index) {
|
||||
// provide info by default if anything changed
|
||||
cstate.setMoved(oldData, RadioDataConversionState::LogField(index, toString(cstate.toModel(), cstate.toGS(), cstate.toType)));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RAWSOURCE_H
|
||||
#define RAWSOURCE_H
|
||||
|
||||
#include "boards.h"
|
||||
#include "constants.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class Firmware;
|
||||
class ModelData;
|
||||
class GeneralSettings;
|
||||
class RadioDataConversionState;
|
||||
|
||||
enum Switches {
|
||||
SWITCH_NONE,
|
||||
|
||||
SWITCH_THR = SWITCH_NONE+1,
|
||||
SWITCH_RUD,
|
||||
SWITCH_ELE,
|
||||
SWITCH_ID0,
|
||||
SWITCH_ID1,
|
||||
SWITCH_ID2,
|
||||
SWITCH_AIL,
|
||||
SWITCH_GEA,
|
||||
SWITCH_TRN,
|
||||
|
||||
SWITCH_SA0 = SWITCH_NONE+1,
|
||||
SWITCH_SA1,
|
||||
SWITCH_SA2,
|
||||
SWITCH_SB0,
|
||||
SWITCH_SB1,
|
||||
SWITCH_SB2,
|
||||
SWITCH_SC0,
|
||||
SWITCH_SC1,
|
||||
SWITCH_SC2,
|
||||
SWITCH_SD0,
|
||||
SWITCH_SD1,
|
||||
SWITCH_SD2,
|
||||
SWITCH_SE0,
|
||||
SWITCH_SE1,
|
||||
SWITCH_SE2,
|
||||
SWITCH_SF0,
|
||||
SWITCH_SF1,
|
||||
SWITCH_SG0,
|
||||
SWITCH_SG1,
|
||||
SWITCH_SG2,
|
||||
SWITCH_SH0,
|
||||
SWITCH_SH2,
|
||||
SWITCH_SI0,
|
||||
SWITCH_SI2,
|
||||
SWITCH_SJ0,
|
||||
SWITCH_SJ2,
|
||||
SWITCH_SK0,
|
||||
SWITCH_SK2,
|
||||
};
|
||||
|
||||
enum TimerModes {
|
||||
TMRMODE_NONE,
|
||||
TMRMODE_ABS,
|
||||
TMRMODE_THR,
|
||||
TMRMODE_THR_REL,
|
||||
TMRMODE_THR_TRG,
|
||||
TMRMODE_FIRST_SWITCH
|
||||
};
|
||||
|
||||
enum FailsafeModes {
|
||||
FAILSAFE_NOT_SET,
|
||||
FAILSAFE_HOLD,
|
||||
FAILSAFE_CUSTOM,
|
||||
FAILSAFE_NOPULSES,
|
||||
FAILSAFE_RECEIVER,
|
||||
FAILSAFE_LAST = FAILSAFE_RECEIVER
|
||||
};
|
||||
|
||||
enum HeliSwashTypes {
|
||||
HELI_SWASH_TYPE_NONE=0,
|
||||
HELI_SWASH_TYPE_120,
|
||||
HELI_SWASH_TYPE_120X,
|
||||
HELI_SWASH_TYPE_140,
|
||||
HELI_SWASH_TYPE_90
|
||||
};
|
||||
|
||||
enum TelemetrySource {
|
||||
TELEMETRY_SOURCE_TX_BATT,
|
||||
TELEMETRY_SOURCE_TX_TIME,
|
||||
TELEMETRY_SOURCE_TIMER1,
|
||||
TELEMETRY_SOURCE_TIMER2,
|
||||
TELEMETRY_SOURCE_TIMER3,
|
||||
TELEMETRY_SOURCE_RAS,
|
||||
TELEMETRY_SOURCE_RSSI_TX,
|
||||
TELEMETRY_SOURCE_RSSI_RX,
|
||||
TELEMETRY_SOURCE_A1,
|
||||
TELEMETRY_SOURCE_A2,
|
||||
TELEMETRY_SOURCE_A3,
|
||||
TELEMETRY_SOURCE_A4,
|
||||
TELEMETRY_SOURCE_ALT,
|
||||
TELEMETRY_SOURCE_RPM,
|
||||
TELEMETRY_SOURCE_FUEL,
|
||||
TELEMETRY_SOURCE_T1,
|
||||
TELEMETRY_SOURCE_T2,
|
||||
TELEMETRY_SOURCE_SPEED,
|
||||
TELEMETRY_SOURCE_DIST,
|
||||
TELEMETRY_SOURCE_GPS_ALT,
|
||||
TELEMETRY_SOURCE_CELL,
|
||||
TELEMETRY_SOURCE_CELLS_SUM,
|
||||
TELEMETRY_SOURCE_VFAS,
|
||||
TELEMETRY_SOURCE_CURRENT,
|
||||
TELEMETRY_SOURCE_CONSUMPTION,
|
||||
TELEMETRY_SOURCE_POWER,
|
||||
TELEMETRY_SOURCE_ACCX,
|
||||
TELEMETRY_SOURCE_ACCY,
|
||||
TELEMETRY_SOURCE_ACCZ,
|
||||
TELEMETRY_SOURCE_HDG,
|
||||
TELEMETRY_SOURCE_VERTICAL_SPEED,
|
||||
TELEMETRY_SOURCE_ASPEED,
|
||||
TELEMETRY_SOURCE_DTE,
|
||||
TELEMETRY_SOURCE_A1_MIN,
|
||||
TELEMETRY_SOURCE_A2_MIN,
|
||||
TELEMETRY_SOURCE_A3_MIN,
|
||||
TELEMETRY_SOURCE_A4_MIN,
|
||||
TELEMETRY_SOURCE_ALT_MIN,
|
||||
TELEMETRY_SOURCE_ALT_MAX,
|
||||
TELEMETRY_SOURCE_RPM_MAX,
|
||||
TELEMETRY_SOURCE_T1_MAX,
|
||||
TELEMETRY_SOURCE_T2_MAX,
|
||||
TELEMETRY_SOURCE_SPEED_MAX,
|
||||
TELEMETRY_SOURCE_DIST_MAX,
|
||||
TELEMETRY_SOURCE_ASPEED_MAX,
|
||||
TELEMETRY_SOURCE_CELL_MIN,
|
||||
TELEMETRY_SOURCE_CELLS_MIN,
|
||||
TELEMETRY_SOURCE_VFAS_MIN,
|
||||
TELEMETRY_SOURCE_CURRENT_MAX,
|
||||
TELEMETRY_SOURCE_POWER_MAX,
|
||||
TELEMETRY_SOURCE_ACC,
|
||||
TELEMETRY_SOURCE_GPS_TIME,
|
||||
TELEMETRY_SOURCES_STATUS_COUNT = TELEMETRY_SOURCE_GPS_TIME+1,
|
||||
TELEMETRY_SOURCES_DISPLAY_COUNT = TELEMETRY_SOURCE_POWER_MAX+1,
|
||||
TELEMETRY_SOURCES_COUNT = TELEMETRY_SOURCE_POWER_MAX+1,
|
||||
TELEMETRY_SOURCE_RESERVE = -1
|
||||
};
|
||||
|
||||
#define TM_HASTELEMETRY 0x01
|
||||
#define TM_HASOFFSET 0x02
|
||||
#define TM_HASWSHH 0x04
|
||||
|
||||
enum RawSourceType {
|
||||
SOURCE_TYPE_NONE,
|
||||
SOURCE_TYPE_VIRTUAL_INPUT,
|
||||
SOURCE_TYPE_LUA_OUTPUT,
|
||||
SOURCE_TYPE_STICK, // and POTS
|
||||
SOURCE_TYPE_ROTARY_ENCODER,
|
||||
SOURCE_TYPE_TRIM,
|
||||
SOURCE_TYPE_MAX,
|
||||
SOURCE_TYPE_SWITCH,
|
||||
SOURCE_TYPE_CUSTOM_SWITCH,
|
||||
SOURCE_TYPE_CYC,
|
||||
SOURCE_TYPE_PPM,
|
||||
SOURCE_TYPE_CH,
|
||||
SOURCE_TYPE_GVAR,
|
||||
SOURCE_TYPE_SPECIAL,
|
||||
SOURCE_TYPE_TELEMETRY,
|
||||
MAX_SOURCE_TYPE
|
||||
};
|
||||
|
||||
class RawSourceRange
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(RawSourceRange)
|
||||
|
||||
public:
|
||||
RawSourceRange():
|
||||
decimals(0),
|
||||
min(0.0),
|
||||
max(0.0),
|
||||
step(1.0),
|
||||
offset(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
float getValue(int value);
|
||||
|
||||
int decimals;
|
||||
double min;
|
||||
double max;
|
||||
double step;
|
||||
double offset;
|
||||
QString unit;
|
||||
};
|
||||
|
||||
#define RANGE_DELTA_FUNCTION 1
|
||||
#define RANGE_ABS_FUNCTION 2
|
||||
|
||||
class RawSource {
|
||||
Q_DECLARE_TR_FUNCTIONS(RawSource)
|
||||
|
||||
public:
|
||||
enum SourceGroups {
|
||||
NoneGroup = 0x001,
|
||||
SourcesGroup = 0x002,
|
||||
TrimsGroup = 0x004,
|
||||
SwitchesGroup = 0x008,
|
||||
GVarsGroup = 0x010,
|
||||
TelemGroup = 0x020,
|
||||
InputsGroup = 0x040,
|
||||
ScriptsGroup = 0x080,
|
||||
|
||||
InputSourceGroups = NoneGroup | SourcesGroup | TrimsGroup | SwitchesGroup | InputsGroup,
|
||||
AllSourceGroups = InputSourceGroups | GVarsGroup | TelemGroup | ScriptsGroup
|
||||
};
|
||||
|
||||
RawSource():
|
||||
type(SOURCE_TYPE_NONE),
|
||||
index(0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit RawSource(int value):
|
||||
type(RawSourceType(abs(value)/65536)),
|
||||
index(value >= 0 ? abs(value)%65536 : -(abs(value)%65536))
|
||||
{
|
||||
}
|
||||
|
||||
RawSource(RawSourceType type, int index=0):
|
||||
type(type),
|
||||
index(index)
|
||||
{
|
||||
}
|
||||
|
||||
inline const int toValue() const
|
||||
{
|
||||
return index >= 0 ? (type * 65536 + index) : -(type * 65536 - index);
|
||||
}
|
||||
|
||||
RawSource convert(RadioDataConversionState & cstate);
|
||||
QString toString(const ModelData * model = NULL, const GeneralSettings * const generalSettings = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||
RawSourceRange getRange(const ModelData * model, const GeneralSettings & settings, unsigned int flags=0) const;
|
||||
bool isStick(int * potsIndex = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||
bool isPot(int * potsIndex = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||
bool isSlider(int * sliderIndex = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||
bool isTimeBased(Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
|
||||
|
||||
bool operator == ( const RawSource & other) {
|
||||
return (this->type == other.type) && (this->index == other.index);
|
||||
}
|
||||
|
||||
bool operator != ( const RawSource & other) {
|
||||
return (this->type != other.type) || (this->index != other.index);
|
||||
}
|
||||
|
||||
RawSourceType type;
|
||||
int index;
|
||||
};
|
||||
|
||||
#endif // RAWSOURCE_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user