diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 000000000..fdb7dc9f4
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: ['PayPal.Me/opentx']
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fafd8c537..18d2bc919 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,11 +2,11 @@ project(OpenTX)
set(VERSION_MAJOR "2")
set(VERSION_MINOR "3")
-set(VERSION_REVISION "3")
+set(VERSION_REVISION "10")
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 "0025")
+set(SDCARD_REVISION "0029")
set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
cmake_minimum_required(VERSION 2.8)
diff --git a/CREDITS.txt b/CREDITS.txt
index 25c8f1344..9a6bc797e 100644
--- a/CREDITS.txt
+++ b/CREDITS.txt
@@ -8,9 +8,11 @@ Romolo Manfredini (romoloman)
Martin Hotař (mhotar)
Maxim (Max) Paperno (mpaperno)
Arne Schwabe (schwabe)
+Daniel Gorbea (dgatf)
[Translators]
[fr] Sebastien Charpentier (LapinFou)
+[es] Daniel Gorbea (dgatf)
[Other contributors]
Rob Thomson
@@ -29,6 +31,7 @@ Michael Byrne
FrSky (monthly)
FlySky (monthly)
JumperRC (monthly)
+RadioMaster (monthly)
Aloft Hobbies
Jonathan Modellismo
WsTech
@@ -421,7 +424,6 @@ Pablo Gomez Martinez
Alan Thoren
Jack Clodfelter
William Simon
-James Houck
Peter Fithern
Thomas Svedman
TechFixPros
@@ -686,7 +688,6 @@ Shaun Currier
Danilo Schiara
John Hennig
RK Custom Homes
-James Houck
Piet Teekens
Tommy Widenflycht
Johan Petrus Theophilus
@@ -1666,3 +1667,174 @@ Justin Farnsworth
James Snodgrass
Peter Schneider
Norman Schenck
+Boris Hemmer
+Gilles Arbona
+Patrice Germain
+Mart Rogers
+Stefan Möst
+John Beech
+John Rodgers
+Stanton Sweet
+Peter Suphan
+FGS
+Outward Ideas
+Sylvie Le Madec
+James Houck (monthly)
+Frank Steinmetz
+Gary Garland
+Stefano Boggia
+Jean-Jacques Pointel
+Ferenc Kunkli
+Sven Müller
+Taavi Tuisk
+Thomas Floyd
+Matthew LePard
+Peter Schneider
+Michel Garbarino
+Achim Stolze
+Fernando Rimoldi
+Bernard Delpy
+Daniel Dubovsky
+Jonathan Starch
+Coolwind
+Benoit Pichereau
+Darko Perković
+Burt Pickard-Richardson
+Roland Nittby
+Frank Barbas
+Scott McCoy
+Fabrice Debonnet
+James Laver
+Kevin Bowens
+David Frech
+Udo Kastenholz
+Julio Margarido
+Uwe Muendelein
+James Jewitt
+Daniel Ferreira
+Michael Charlston
+Leopoldo Cicero
+Tom Van Driel
+Karl Vetter
+Johannes Janssen
+François Blondé
+Precision Aero
+Thomas Håkansson
+Gordon Evans
+Benny Simonsen
+George Kennedy
+Stefano Boggia
+Maksym Arshynkin
+Tomas Sodergren
+Jörg Lemnitz
+TMac FPV
+Josef Schaeffler
+Mike Frizell
+MeCodeGoodSomeday
+Timothy Fry
+John Beech
+Wojciech Winiarski
+Armin Kuepfer
+Alain Bregand
+James Thompson
+Dautremépuis Benoit
+Adriano Emanuele Figliola
+Stefano Bortolotti
+Gerald Zierer
+Alessio Noto
+Walter Fowler
+Robert Black
+Klaus Kernstock
+Michael Wittich
+AG-Software
+Dietmar Drees
+Winfried Goers
+Steve Schoonover
+N. Haasnoot (monthly)
+Wolfram Bahmann
+Florian Reck
+Gary Bancroft
+Karl-Heinz Behn
+Stuart Godsmark
+Josko Povse
+David Reese
+Paul Pearson
+Stuart Olson
+Pierre Connan
+Henk Eeltink
+Robert Miller
+George Walker
+Александр Щитов
+Heiko Polig
+Gary Wild
+Peter Sarcher
+Steve Schoonover
+Francisco Orcera Exposito
+Alan Powell
+Martin Eriksson
+Wayne J Podaima
+Tom Wilkinson
+Fred Ceratt
+Stefan Grunenberg
+Aram Parsamyan
+Wolfgang Rauser
+John Wall
+Martin Haggas
+Denis Kelly
+James Houck
+Brian Stephanik
+William McNeice
+Sven De Boeck
+SB Europe Ltd
+Evening Shade Pottery
+D van Oostveen
+Michael Grosso
+Carlos Marcal
+d@taweb
+Justin Digby
+Hermann Vocat
+Michael Francini
+Michael Chambers
+Harold H Youngren
+Yann Orselli
+Dieter Schaad
+Ernst Camenzind
+Ciobanu Rivelino Costel
+David Jolly
+Aram Parsamyan
+Stewart Davies
+Karsten Schwarz
+Robert Mckay
+Michael Oeschger
+Randy Ling
+Jonathan Wise
+David Gardner
+Christophe Judas
+Lachlan Peters
+Patrick C Kutschke
+Thomas Halenbeck
+Barry Wright
+Nicolas Ducher
+Giampiero Sintoni
+Sidney B Harden
+John Moody
+Sylvain Cubizolles
+Adam Kouse
+FCG Kas
+Dennis Marinus
+James Donelson
+Stefan Hassler
+Reinhard Prix
+Jeffrey Johnson
+Michael Conway
+Ryan Buffington
+Thomas Horns
+Michael Carnes
+William Hallman
+James Snodgrass
+Michal Mesaros
+James Lindner
+Laurence Gerrard
+Nico Wagner
+Christoph Rössner
+Ruben Flores
diff --git a/README.md b/README.md
index ddf9e4e4b..64e672a51 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
## OpenTX 2.3 Branch
[](https://travis-ci.org/opentx/opentx)
-[](https://chat.open-tx.org)
+[](https://discord.gg/CZCwVx2)
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DJ9MASSKVW8WN)
The ongoing development on 2.3.x is done in this branch.
diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt
index 16245c848..3cf15d85f 100644
--- a/companion/src/CMakeLists.txt
+++ b/companion/src/CMakeLists.txt
@@ -24,8 +24,6 @@ set(COMPANION_OSX_APP_BUNDLE_NAME "OpenTX Companion ${VERSION_MAJOR}.${VERSION_M
# 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)
@@ -123,7 +121,7 @@ configure_file(${COMPANION_SRC_DIRECTORY}/simulator.desktop.in ${CMAKE_CURRENT_B
### 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 ja)
+set(LANGUAGES cs de en es fi fr it pl ru sv zh_CN ja)
foreach(language ${LANGUAGES})
list(APPEND companion_TS translations/companion_${language}.ts)
endforeach(language)
@@ -239,7 +237,6 @@ set(companion_SRCS
flasheepromdialog.cpp
printdialog.cpp
modelprinter.cpp
- fusesdialog.cpp
logsdialog.cpp
downloaddialog.cpp
splashlibrarydialog.cpp
@@ -250,6 +247,7 @@ set(companion_SRCS
wizarddialog.cpp
styleeditdialog.cpp
dialogs/filesyncdialog.cpp # TODO move to own lib with other dialogs
+ profilechooser.cpp
)
set(companion_MOC_HDRS
@@ -258,7 +256,6 @@ set(companion_MOC_HDRS
burnconfigdialog.h
comparedialog.h
printdialog.h
- fusesdialog.h
logsdialog.h
creditsdialog.h
releasenotesdialog.h
@@ -284,12 +281,12 @@ set(companion_MOC_HDRS
styleeditdialog.h
helpers_html.h
dialogs/filesyncdialog.h
+ profilechooser.h
)
set(companion_UIS
mdichild.ui
comparedialog.ui
- fusesdialog.ui
logsdialog.ui
apppreferencesdialog.ui
fwpreferencesdialog.ui
@@ -305,6 +302,7 @@ set(companion_UIS
flasheepromdialog.ui
radionotfound.ui
styleeditdialog.ui
+ profilechooser.ui
)
if(WIN32)
@@ -341,7 +339,9 @@ endif()
# the current flavour is not automatically added if build in the current cmake iteration, so always
# add its library name to be sure
-if(PCB STREQUAL X7 AND PCBREV STREQUAL T12)
+if(PCB STREQUAL X7 AND PCBREV STREQUAL ACCESS)
+ set(FLAVOUR x7access)
+elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T12)
set(FLAVOUR t12)
elseif(PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019)
set(FLAVOUR x9d+2019)
@@ -349,6 +349,10 @@ elseif(PCB STREQUAL X10 AND PCBREV STREQUAL EXPRESS)
set(FLAVOUR x10express)
elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T16)
set(FLAVOUR t16)
+elseif(PCB STREQUAL X10 AND PCBREV STREQUAL TX16S)
+ set(FLAVOUR tx16s)
+elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T18)
+ set(FLAVOUR t18)
else()
string(TOLOWER ${PCB} FLAVOUR)
endif()
@@ -400,7 +404,7 @@ elseif(WIN32)
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)
+ set(INSTALL_TEMP_FILES 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()
@@ -547,14 +551,11 @@ IF(APPLE)
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
+ # Copy dfu-util, 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)
+ install(PROGRAMS ${DFU_UTIL_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")
+ set(bundle_tools_path "\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/dfu-util;")
# Include depencies (adding frameworks, fixing the embbeded libraries)
diff --git a/companion/src/apppreferencesdialog.cpp b/companion/src/apppreferencesdialog.cpp
index c17d5c88d..c235788df 100644
--- a/companion/src/apppreferencesdialog.cpp
+++ b/companion/src/apppreferencesdialog.cpp
@@ -73,6 +73,7 @@ void AppPreferencesDialog::accept()
g.OpenTxBranch(AppData::DownloadBranchType(ui->OpenTxBranch->currentIndex()));
g.autoCheckFw(ui->autoCheckFirmware->isChecked());
g.showSplash(ui->showSplash->isChecked());
+ g.promptProfile(ui->chkPromptProfile->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);
@@ -185,6 +186,7 @@ void AppPreferencesDialog::initSettings()
ui->autoCheckCompanion->setChecked(g.autoCheckApp());
ui->autoCheckFirmware->setChecked(g.autoCheckFw());
ui->showSplash->setChecked(g.showSplash());
+ ui->chkPromptProfile->setChecked(g.promptProfile());
ui->historySize->setValue(g.historySize());
ui->backLightColor->setCurrentIndex(g.backLight());
ui->volumeGain->setValue(profile.volumeGain() / 10.0);
@@ -352,6 +354,13 @@ void AppPreferencesDialog::on_ge_pathButton_clicked()
}
}
+void AppPreferencesDialog::on_btnClearPos_clicked()
+{
+ SimulatorOptions opts = g.profile[g.sessionId()].simulatorOptions();
+ opts.controlsState.clear();
+ g.profile[g.sessionId()].simulatorOptions(opts);
+}
+
#if defined(JOYSTICKS)
void AppPreferencesDialog::on_joystickChkB_clicked() {
if (ui->joystickChkB->isChecked()) {
@@ -541,7 +550,7 @@ void AppPreferencesDialog::populateFirmwareOptions(const Firmware * firmware)
// 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())) {
+ if (IS_FAMILY_HORUS_OR_T16(baseFw->getBoard())) {
ui->widget_splashImage->hide();
ui->SplashFileName->setText("");
}
diff --git a/companion/src/apppreferencesdialog.h b/companion/src/apppreferencesdialog.h
index 8c796cf7f..7e3f6f234 100644
--- a/companion/src/apppreferencesdialog.h
+++ b/companion/src/apppreferencesdialog.h
@@ -66,6 +66,7 @@ class AppPreferencesDialog : public QDialog
void on_SplashSelect_clicked();
void on_clearImageButton_clicked();
void on_btn_appLogsDir_clicked();
+ void on_btnClearPos_clicked();
#if defined(JOYSTICKS)
void on_joystickChkB_clicked();
diff --git a/companion/src/apppreferencesdialog.ui b/companion/src/apppreferencesdialog.ui
index ca015d2dc..80301223d 100644
--- a/companion/src/apppreferencesdialog.ui
+++ b/companion/src/apppreferencesdialog.ui
@@ -6,7 +6,7 @@
0
0
- 741
+ 864
668
@@ -45,7 +45,7 @@
- 1
+ 0
@@ -61,22 +61,40 @@
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
5
4
-
- 0
-
-
-
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
0
@@ -704,29 +722,90 @@ Mode 4:
6
-
-
-
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Enable automatic backup before writing firmware
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Google Earth Executable
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
-
-
-
- Automatic check for OpenTX firmware updates
-
-
- true
-
-
+
+ Releases (stable)
+
-
-
-
- Automatic check for Companion updates
-
-
- true
-
-
+
+ Release candidates (testing)
+
-
+ -
+
+ Nightly builds (unstable)
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
-
+
+ Only show user splash images
+
+
+ -
+
+ Show user and companion splash images
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
-
@@ -764,120 +843,27 @@ Mode 4:
- -
-
-
-
- 0
- 0
-
-
-
- Startup Settings
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Google Earth Executable
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
-
- Show splash screen when Companion starts
+ Show splash screen
true
- -
-
-
-
- 0
- 0
-
-
-
- Automatic Backup Folder
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Remember
-
-
-
- -
-
+
-
+
-
-
+
- false
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Select Folder
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
-
-
-
true
-
- false
-
-
-
+
0
@@ -885,49 +871,13 @@ Mode 4:
- Select Folder
+ Select Executable
-
-
-
- <html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html>
-
-
- Remove empty model slots when deleting models (only applies for radios w/out categories)
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Output Logs Folder
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Debug Output Logging
-
-
-
- -
-
@@ -962,90 +912,22 @@ Mode 4:
-
-
-
-
- 0
- 0
-
-
-
- Enable automatic backup before writing firmware
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
-
- 0
- 0
-
-
+
-
-
- Only show user splash images
-
-
- -
-
- Show user and companion splash images
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
-
-
+
- true
+ false
-
-
+
0
0
-
- Select Executable
-
-
-
-
-
- -
-
-
-
-
-
- true
-
-
- false
-
-
-
- -
-
Select Folder
@@ -1053,14 +935,56 @@ Mode 4:
- -
-
-
- Qt::Horizontal
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Remember
- -
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Output Logs Folder
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Startup Settings
+
+
+
+ -
+
+
+ <html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html>
+
+
+ Remove empty model slots when deleting models (only applies for radios w/out categories)
+
+
+
+ -
@@ -1073,33 +997,7 @@ Mode 4:
- -
-
-
-
- 0
- 0
-
-
-
- Splash Screen Library
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Action on New Model
-
-
-
- -
+
-
-
@@ -1123,36 +1021,163 @@ Mode 4:
- -
+
-
+
+
-
+
+
+ true
+
+
+ false
+
+
+
+ -
+
+
+ Select Folder
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Action on New Model
+
+
+
+ -
+
+
-
+
+
+ true
+
+
+ false
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Select Folder
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Splash Screen Library
+
+
+
+ -
Release channel
- -
-
+
-
+
+
+ Qt::Horizontal
+
+
+
+ -
+
-
+
0
0
+
+ Debug Output Logging
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Automatic Backup Folder
+
+
+
+ -
+
-
-
- Releases (stable)
-
+
+
+ Automatic check for OpenTX firmware updates
+
+
+ true
+
+
-
-
- Release candidates (testing)
-
-
- -
-
- Nightly builds (unstable)
-
+
+
+ Automatic check for Companion updates
+
+
+ true
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Prompt for radio profile
+
@@ -1180,7 +1205,38 @@ Mode 4:
6
- -
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 16777215
+
+
+
+ 1
+
+
+ 0.500000000000000
+
+
+ 3.000000000000000
+
+
+ 0.100000000000000
+
+
+ 1.000000000000000
+
+
+
+ -
@@ -1193,14 +1249,20 @@ Mode 4:
- -
-
+
-
+
+
+
+ 0
+ 0
+
+
- Calibrate
+ Screenshot capture folder
- -
+
-
@@ -1235,31 +1297,22 @@ Mode 4:
- -
-
-
-
- 0
- 0
-
-
+
-
+
- Screenshot capture folder
+ Calibrate
- -
-
-
- Qt::Vertical
+
-
+
+
+ Select Folder
-
-
- 20
- 5
-
+
+ false
-
+
-
@@ -1274,7 +1327,7 @@ Mode 4:
- -
+
-
@@ -1287,17 +1340,20 @@ Mode 4:
- -
-
-
- Select Folder
+
-
+
+
+ Qt::Vertical
-
- false
+
+
+ 20
+ 5
+
-
+
- -
+
-
@@ -1310,7 +1366,20 @@ Mode 4:
- -
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Simulator Volume Gain
+
+
+
+ -
@@ -1348,60 +1417,30 @@ Mode 4:
- -
+
-
+
+
+ Simulator controls
+
+
+
+ -
-
+
0
0
- Remember simulator switch values
+ Save switch/pot positions on simulator exit
- -
-
-
-
- 0
- 0
-
-
+
-
+
- Simulator Volume Gain
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 50
- 16777215
-
-
-
- 1
-
-
- 0.500000000000000
-
-
- 3.000000000000000
-
-
- 0.100000000000000
-
-
- 1.000000000000000
+ Clear saved positions
diff --git a/companion/src/burnconfigdialog.cpp b/companion/src/burnconfigdialog.cpp
index 0fe22be03..43a60c7ea 100644
--- a/companion/src/burnconfigdialog.cpp
+++ b/companion/src/burnconfigdialog.cpp
@@ -36,61 +36,23 @@ burnConfigDialog::burnConfigDialog(QWidget *parent) :
{
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();
+ setWindowTitle(tr("SAM-BA Configuration"));
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();
@@ -105,46 +67,26 @@ 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())
@@ -152,45 +94,22 @@ void burnConfigDialog::getSettings()
#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 );
@@ -198,73 +117,6 @@ void burnConfigDialog::putSettings()
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();
@@ -280,17 +132,6 @@ 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());
@@ -322,27 +163,6 @@ 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();
@@ -351,31 +171,20 @@ void burnConfigDialog::on_advCtrChkB_toggled(bool checked)
ui->label_dfu2->show();
ui->dfuArgs->show();
}
- else if (IS_SKY9X(board)) {
+ else {
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("WARNING!
Normally CPU type is automatically selected according to the chosen firmware.
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)) {
+ else {
ui->label_sb2->hide();
ui->arm_mcu->hide();
}
- else {
- ui->label_av3->hide();
- ui->avrdude_mcu->hide();
- }
}
QTimer::singleShot(0, this, SLOT(shrink()));
}
diff --git a/companion/src/burnconfigdialog.h b/companion/src/burnconfigdialog.h
index 5cf7bb375..06810bbd2 100644
--- a/companion/src/burnconfigdialog.h
+++ b/companion/src/burnconfigdialog.h
@@ -39,45 +39,25 @@ 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 );
diff --git a/companion/src/burnconfigdialog.ui b/companion/src/burnconfigdialog.ui
index 36d343884..e52aaf797 100644
--- a/companion/src/burnconfigdialog.ui
+++ b/companion/src/burnconfigdialog.ui
@@ -45,615 +45,7 @@
-
-
-
-
-
- Location of sam-ba executable
-
-
- The location of the AVRDUDE executable.
-
-
- dfu-util
-
-
-
- -
-
-
- DFU-Util Location
-
-
-
- -
-
-
- Location of AVRDUDE executable
-
-
- The location of the AVRDUDE executable.
-
-
-
-
-
-
- -
-
-
- Use this button to browse and look for the AVRDUDE executable file.
-
-
- Browse...
-
-
-
- -
-
-
- Programmer
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
-
-
- -
-
-
- Programmer used for communicating with the controller.
-Please consult the programmer's documentation and the AVRDUDE documentation to select the appropriate programmer.
-
-
- QComboBox::InsertAlphabetically
-
-
-
-
- c2n232i
-
-
- -
-
- dasa3
-
-
- -
-
- dasa
-
-
- -
-
- siprog
-
-
- -
-
- ponyser
-
-
- -
-
- 89isp
-
-
- -
-
- frank-stk200
-
-
- -
-
- blaster
-
-
- -
-
- ere-isp-avr
-
-
- -
-
- atisp
-
-
- -
-
- dapa
-
-
- -
-
- xil
-
-
- -
-
- futurlec
-
-
- -
-
- abcmini
-
-
- -
-
- picoweb
-
-
- -
-
- sp12
-
-
- -
-
- alf
-
-
- -
-
- bascom
-
-
- -
-
- dt006
-
-
- -
-
- pony-stk200
-
-
- -
-
- stk200
-
-
- -
-
- bsd
-
-
- -
-
- pavr
-
-
- -
-
- dragon_pdi
-
-
- -
-
- dragon_dw
-
-
- -
-
- dragon_hvsp
-
-
- -
-
- dragon_pp
-
-
- -
-
- dragon_isp
-
-
- -
-
- dragon_jtag
-
-
- -
-
- jtag2pdi
-
-
- -
-
- jtag2avr32
-
-
- -
-
- jtagmkII_avr32
-
-
- -
-
- jtag2dw
-
-
- -
-
- jtag2isp
-
-
- -
-
- jtag2
-
-
- -
-
- jtag2fast
-
-
- -
-
- jtag2slow
-
-
- -
-
- jtagmkII
-
-
- -
-
- jtag1slow
-
-
- -
-
- jtag1
-
-
- -
-
- jtagmkI
-
-
- -
-
- avr911
-
-
- -
-
- avr109
-
-
- -
-
- butterfly
-
-
- -
-
- usbtiny
-
-
- -
-
- usbasp
-
-
- -
-
- avr910
-
-
- -
-
- stk600hvsp
-
-
- -
-
- stk600pp
-
-
- -
-
- stk600
-
-
- -
-
- stk500hvsp
-
-
- -
-
- stk500pp
-
-
- -
-
- stk500v2
-
-
- -
-
- mib510
-
-
- -
-
- stk500v1
-
-
- -
-
- stk500
-
-
- -
-
- buspirate
-
-
- -
-
- avrisp2
-
-
- -
-
- avrispmkII
-
-
- -
-
- avrispv2
-
-
- -
-
- avrisp
-
-
- -
-
- arduino
-
-
-
-
- -
-
-
- List all available programmers.
-
-
- List Available
-
-
-
- -
-
-
- Extra arguments that will be passed to AVRDUDE on every call
-
-
- 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.
-
-
-
-
-
-
- -
-
-
- Extra Arguments
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
-
-
- -
-
-
- Show AVRDUDE help
-
-
- Show Help
-
-
-
- -
-
-
- Communication port to the programmer.
-
-
-
-
-
-
-
-
- -
-
- usb
-
-
- -
-
- com1
-
-
- -
-
- com2
-
-
- -
-
- com3
-
-
- -
-
- com4
-
-
- -
-
- com5
-
-
- -
-
- com6
-
-
- -
-
- com7
-
-
- -
-
- com8
-
-
- -
-
- com9
-
-
- -
-
- com10
-
-
- -
-
- com11
-
-
- -
-
- com12
-
-
- -
-
- com13
-
-
- -
-
- com14
-
-
- -
-
- com15
-
-
- -
-
- lpt1
-
-
- -
-
- lpt2
-
-
- -
-
- lpt3
-
-
- -
-
- lpt4
-
-
- -
-
- avrdoper
-
-
- -
-
- /dev/ttyUSB0
-
-
- -
-
- /dev/ttyUSB1
-
-
-
-
- -
-
-
- Port
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
-
-
- -
-
-
- AVRDUDE Location
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
-
-
- -
-
-
- MCU
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
-
-
- -
-
-
- CPU of your TX
-
-
- CPU present on your 9x radio
-Should be m64 for stock radios
-m2560 for v4.1 boards
-
-
- QComboBox::InsertAlphabetically
-
-
-
-
- m64
-
-
- -
-
- m128
-
-
- -
-
- m2560
-
-
-
-
- -
+
-
CPU of your TX
@@ -678,7 +70,27 @@ m2560 for v4.1 boards
- -
+
-
+
+
+ Location of sam-ba executable
+
+
+ The location of the AVRDUDE executable.
+
+
+ dfu-util
+
+
+
+ -
+
+
+ DFU-Util Location
+
+
+
+ -
SAM-BA Location
@@ -688,7 +100,7 @@ m2560 for v4.1 boards
- -
+
-
Location of sam-ba executable
@@ -701,7 +113,7 @@ m2560 for v4.1 boards
- -
+
-
ARM MCU
@@ -711,7 +123,7 @@ m2560 for v4.1 boards
- -
+
-
Port
@@ -721,7 +133,7 @@ m2560 for v4.1 boards
- -
+
-
sam-ba serial port
@@ -734,14 +146,14 @@ m2560 for v4.1 boards
- -
+
-
Alternate device
- -
+
-
Extra arguments that will be passed to AVRDUDE on every call
@@ -757,7 +169,7 @@ Please only use this if you know what you are doing. There are no error checks
- -
+
-
Use this button to browse and look for the AVRDUDE executable file.
@@ -767,7 +179,7 @@ Please only use this if you know what you are doing. There are no error checks
- -
+
-
Use this button to browse and look for the AVRDUDE executable file.
@@ -777,14 +189,14 @@ Please only use this if you know what you are doing. There are no error checks
- -
+
-
- -
+
-
Use advanced controls
@@ -809,14 +221,6 @@ Please only use this if you know what you are doing. There are no error checks
- avrdude_location
- pushButton
- avrdude_programmer
- pushButton_3
- avrdude_mcu
- avrdude_port
- avrArgs
- pushButton_4
samba_location
sb_browse
arm_mcu
diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc
index f91782c50..cddc2fa3e 100644
--- a/companion/src/companion.qrc
+++ b/companion/src/companion.qrc
@@ -190,6 +190,27 @@
images/simulator/JumperT16/left_tele.png
images/simulator/JumperT16/right_ent.png
images/simulator/JumperT16/right_rtn.png
+ images/simulator/JumperT18/left.png
+ images/simulator/JumperT18/right.png
+ images/simulator/JumperT18/top.png
+ images/simulator/JumperT18/bottom.png
+ images/simulator/JumperT18/left_mdl.png
+ images/simulator/JumperT18/left_page.png
+ images/simulator/JumperT18/left_sys.png
+ images/simulator/JumperT18/left_tele.png
+ images/simulator/JumperT18/right_ent.png
+ images/simulator/JumperT18/right_rtn.png
+ images/simulator/TX16S/left.png
+ images/simulator/TX16S/right.png
+ images/simulator/TX16S/top.png
+ images/simulator/TX16S/bottom.png
+ images/simulator/TX16S/left_page.png
+ images/simulator/TX16S/left_page2.png
+ images/simulator/TX16S/left_rtn.png
+ images/simulator/TX16S/left_sys.png
+ images/simulator/TX16S/left_tele.png
+ images/simulator/TX16S/right_ent.png
+ images/simulator/TX16S/right_mdl.png
images/wizard/ailerons.png
images/wizard/airbrakes.png
images/wizard/elevons.png
diff --git a/companion/src/downloaddialog.cpp b/companion/src/downloaddialog.cpp
index 3f70e6529..5b9b2dfa0 100644
--- a/companion/src/downloaddialog.cpp
+++ b/companion/src/downloaddialog.cpp
@@ -54,7 +54,7 @@ DownloadDialog::DownloadDialog(QWidget *parent, QString src, QString tgt):
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)));
+ connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(updateDataReadProgress(qint64, qint64)));
}
}
@@ -114,7 +114,7 @@ void DownloadDialog::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
void DownloadDialog::fileError()
{
delete file;
- file = NULL;
+ file = nullptr;
reject();
}
diff --git a/companion/src/firmwares/CMakeLists.txt b/companion/src/firmwares/CMakeLists.txt
index b6b8fcaba..1b99964fa 100644
--- a/companion/src/firmwares/CMakeLists.txt
+++ b/companion/src/firmwares/CMakeLists.txt
@@ -1,5 +1,6 @@
set(firmwares_SRCS
+ adjustmentreference.cpp
boards.cpp
curvereference.cpp
customfunctiondata.cpp
@@ -17,8 +18,7 @@ set(firmwares_SRCS
rawswitch.cpp
sensordata.cpp
telem_data.cpp
- er9x/er9xeeprom.cpp
- er9x/er9xinterface.cpp
+ afhds3.cpp
ersky9x/ersky9xeeprom.cpp
ersky9x/ersky9xinterface.cpp
opentx/opentxeeprom.cpp
diff --git a/companion/src/firmwares/adjustmentreference.cpp b/companion/src/firmwares/adjustmentreference.cpp
new file mode 100644
index 000000000..7181e15dd
--- /dev/null
+++ b/companion/src/firmwares/adjustmentreference.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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 "adjustmentreference.h"
+#include "radiodata.h" // for ModelData
+
+AdjustmentReference::AdjustmentReference(int value)
+{
+ int val = value;
+ if (abs(val) > ADJUST_REF_GVAR_BASE && abs(val) <= ADJUST_REF_GVAR_BASE + CPN_MAX_GVARS) {
+ type = ADJUST_REF_GVAR;
+ val = val >= 0 ? val - ADJUST_REF_GVAR_BASE : val + ADJUST_REF_GVAR_BASE;
+ }
+ else
+ this->type = ADJUST_REF_VALUE;
+
+ this->value = val;
+}
+
+AdjustmentReference::AdjustmentReference(AdjustRefType type, int value)
+{
+ this->type = type;
+ if (isValid(value))
+ this->value = value;
+ else
+ clear();
+}
+
+bool AdjustmentReference::isValid(const int value) const
+{
+ switch (type) {
+ case ADJUST_REF_VALUE:
+ return abs(value) < ADJUST_REF_GVAR_BASE;
+
+ case ADJUST_REF_GVAR:
+ return abs(value) > 0 && abs(value) <= CPN_MAX_GVARS;
+ }
+ return false;
+}
+
+QString AdjustmentReference::toString(const ModelData * model, const bool sign) const
+{
+ QString ret;
+
+ switch(type) {
+ case ADJUST_REF_GVAR:
+ ret = RawSource(SOURCE_TYPE_GVAR, abs(value) - 1).toString(model);
+ if (value < 0)
+ ret.prepend("-");
+ else if (sign)
+ ret.prepend("+");
+ break;
+ default:
+ ret = "%1%";
+ if (sign && value > 0)
+ ret.prepend("+");
+ ret = ret.arg(value);
+ break;
+ }
+ return ret;
+}
diff --git a/companion/src/firmwares/adjustmentreference.h b/companion/src/firmwares/adjustmentreference.h
new file mode 100644
index 000000000..2a7b7e141
--- /dev/null
+++ b/companion/src/firmwares/adjustmentreference.h
@@ -0,0 +1,69 @@
+/*
+ * 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 ADJUSTMENTREFERENCE_H
+#define ADJUSTMENTREFERENCE_H
+
+#include
+
+class ModelData;
+
+constexpr int ADJUST_REF_GVAR_BASE { 10000 };
+
+class AdjustmentReference {
+ Q_DECLARE_TR_FUNCTIONS(AdjustmentReference)
+
+ public:
+ enum AdjustRefType {
+ ADJUST_REF_VALUE,
+ ADJUST_REF_GVAR,
+ };
+
+ AdjustmentReference() { clear(); }
+ explicit AdjustmentReference(int value);
+ AdjustmentReference(const AdjustRefType type, const int value);
+
+ void clear() { memset(this, 0, sizeof(AdjustmentReference)); }
+
+ bool isSet() const { return type != ADJUST_REF_VALUE || value != 0; }
+ bool isValid(const int value) const;
+ QString toString(const ModelData * model = nullptr, const bool sign = false) const;
+
+ inline const int toValue() const
+ {
+ if (type == ADJUST_REF_GVAR)
+ return value >= 0 ? value + ADJUST_REF_GVAR_BASE : value - ADJUST_REF_GVAR_BASE;
+ else
+ return value;
+ }
+
+ bool operator== ( const AdjustmentReference & other) const {
+ return (this->type == other.type) && (this->value == other.value);
+ }
+
+ bool operator!= ( const AdjustmentReference & other) const {
+ return (this->type != other.type) || (this->value != other.value);
+ }
+
+ AdjustRefType type;
+ int value;
+};
+
+#endif // ADJUSTMENTREFERENCE_H
diff --git a/companion/src/firmwares/afhds3.cpp b/companion/src/firmwares/afhds3.cpp
new file mode 100644
index 000000000..000fb252c
--- /dev/null
+++ b/companion/src/firmwares/afhds3.cpp
@@ -0,0 +1,12 @@
+#include "afhds3.h"
+#include "macros.h"
+
+QString Afhds3Data::protocolToString(unsigned int protocol) {
+ const char * const afhds3Protocols[] = {
+ "PWM/IBUS",
+ "PWM/SBUS",
+ "PPM/IBUS",
+ "PPM/SBUS",
+ };
+ return CHECK_IN_ARRAY(afhds3Protocols, protocol);
+}
diff --git a/companion/src/firmwares/afhds3.h b/companion/src/firmwares/afhds3.h
new file mode 100644
index 000000000..ea4257fba
--- /dev/null
+++ b/companion/src/firmwares/afhds3.h
@@ -0,0 +1,12 @@
+#ifndef AFHDS3_H
+#define AFHDS3_H
+
+#include
+
+class Afhds3Data
+{
+ Q_DECLARE_TR_FUNCTIONS(Afhds3)
+public:
+ static QString protocolToString(unsigned int protocol);
+};
+#endif // AFHDS3_H
diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp
index 726cae256..a39fe3369 100644
--- a/companion/src/firmwares/boards.cpp
+++ b/companion/src/firmwares/boards.cpp
@@ -25,18 +25,13 @@
// 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)
@@ -66,6 +61,7 @@ uint32_t Boards::getFourCC(Type board)
case BOARD_TARANIS_XLITES:
return 0x3B78746F;
case BOARD_TARANIS_X7:
+ case BOARD_TARANIS_X7_ACCESS:
return 0x3678746F;
case BOARD_TARANIS_X9E:
return 0x3578746F;
@@ -81,16 +77,14 @@ uint32_t Boards::getFourCC(Type board)
case BOARD_AR9X:
case BOARD_9XRPRO:
return 0x3278746F;
- case BOARD_MEGA2560:
- case BOARD_GRUVIN9X:
- return 0x3178746F;
- case BOARD_9X_M64:
- case BOARD_9X_M128:
- return 0;
case BOARD_JUMPER_T12:
return 0x3D78746F;
case BOARD_JUMPER_T16:
return 0x3F78746F;
+ case BOARD_JUMPER_T18:
+ return 0x4078746F;
+ case BOARD_RADIOMASTER_TX16S:
+ return 0x3878746F;
case BOARD_UNKNOWN:
break;
}
@@ -101,13 +95,6 @@ uint32_t Boards::getFourCC(Type board)
int Boards::getEEpromSize(Board::Type board)
{
switch (board) {
- case BOARD_9X_M64:
- return EESIZE_STOCK;
- case BOARD_9X_M128:
- return EESIZE_M128;
- case BOARD_MEGA2560:
- case BOARD_GRUVIN9X:
- return EESIZE_GRUVIN9X;
case BOARD_SKY9X:
return EESIZE_SKY9X;
case BOARD_9XRPRO:
@@ -116,6 +103,7 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_TARANIS_XLITES:
case BOARD_TARANIS_XLITE:
case BOARD_TARANIS_X7:
+ case BOARD_TARANIS_X7_ACCESS:
case BOARD_TARANIS_X9LITE:
case BOARD_TARANIS_X9LITES:
case BOARD_TARANIS_X9D:
@@ -130,6 +118,8 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_X10:
case BOARD_X10_EXPRESS:
case BOARD_JUMPER_T16:
+ case BOARD_JUMPER_T18:
+ case BOARD_RADIOMASTER_TX16S:
return 0;
}
@@ -139,13 +129,6 @@ int Boards::getEEpromSize(Board::Type board)
int Boards::getFlashSize(Type board)
{
switch (board) {
- case BOARD_9X_M64:
- return FSIZE_STOCK;
- case BOARD_9X_M128:
- return FSIZE_M128;
- case BOARD_MEGA2560:
- case BOARD_GRUVIN9X:
- return FSIZE_GRUVIN9X;
case BOARD_SKY9X:
return FSIZE_SKY9X;
case BOARD_9XRPRO:
@@ -154,6 +137,7 @@ int Boards::getFlashSize(Type board)
case BOARD_TARANIS_XLITES:
case BOARD_TARANIS_XLITE:
case BOARD_TARANIS_X7:
+ case BOARD_TARANIS_X7_ACCESS:
case BOARD_TARANIS_X9LITE:
case BOARD_TARANIS_X9LITES:
case BOARD_TARANIS_X9D:
@@ -166,6 +150,8 @@ int Boards::getFlashSize(Type board)
case BOARD_X10:
case BOARD_X10_EXPRESS:
case BOARD_JUMPER_T16:
+ case BOARD_JUMPER_T18:
+ case BOARD_RADIOMASTER_TX16S:
return FSIZE_HORUS;
case BOARD_UNKNOWN:
return FSIZE_MAX;
@@ -281,7 +267,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 2;
else if (IS_TARANIS_X9E(board))
return 4;
- else if (IS_HORUS_X10(board) || IS_JUMPER_T16(board))
+ else if (IS_HORUS_X10(board) || IS_FAMILY_T16(board))
return 5;
else if (IS_HORUS_X12S(board))
return 3;
@@ -297,13 +283,13 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case Sliders:
if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board))
return 4;
- else if (IS_TARANIS_X9D(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board))
+ else if (IS_TARANIS_X9D(board) || IS_HORUS_X10(board) || IS_FAMILY_T16(board))
return 2;
else
return 0;
case MouseAnalogs:
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 2;
else
return 0;
@@ -326,8 +312,10 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case Switches:
if (IS_TARANIS_X9E(board))
return 18;
- else if (IS_TARANIS_X9LITE(board))
+ else if (board == Board::BOARD_TARANIS_X9LITE)
return 5;
+ else if (board == Board::BOARD_TARANIS_X9LITES)
+ return 7;
else if (IS_TARANIS_X7(board))
return 8;
else if (IS_JUMPER_T12(board))
@@ -338,7 +326,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 9;
else if (IS_TARANIS(board))
return 8;
- else if (IS_HORUS(board))
+ else if (IS_FAMILY_HORUS_OR_T16(board))
return 10;
else
return 7;
@@ -358,7 +346,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 9;
case NumTrims:
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 6;
else
return 4;
@@ -403,7 +391,7 @@ QString Boards::getAnalogInputName(Board::Type board, int index)
index -= getCapability(board, Board::Sticks);
- if (IS_9X(board) || IS_2560(board) || IS_SKY9X(board)) {
+ if (IS_SKY9X(board)) {
const QString pots[] = {
"P1",
"P2",
@@ -452,8 +440,8 @@ QString Boards::getAnalogInputName(Board::Type board, int index)
"S1",
"6P",
"S2",
- "S3",
- "S4",
+ "L1",
+ "L2",
"LS",
"RS",
"JSx",
@@ -462,7 +450,7 @@ QString Boards::getAnalogInputName(Board::Type board, int index)
if (index < DIM(pots))
return pots[index];
}
- else if (IS_HORUS_X10(board) || IS_JUMPER_T16(board)) {
+ else if (IS_HORUS_X10(board) || IS_FAMILY_T16(board)) {
const QString pots[] = {
"S1",
"6P",
@@ -487,16 +475,10 @@ bool Boards::isBoardCompatible(Type board1, Type board2)
QString Boards::getBoardName(Board::Type board)
{
switch (board) {
- case BOARD_9X_M64:
- return "9X";
- case BOARD_9X_M128:
- return "9X128";
- case BOARD_GRUVIN9X:
- return "Gruvin9x";
- case BOARD_MEGA2560:
- return "MEGA2560";
case BOARD_TARANIS_X7:
return "Taranis X7/X7S";
+ case BOARD_TARANIS_X7_ACCESS:
+ return "Taranis X7/X7S Access";
case BOARD_JUMPER_T12:
return "Jumper T12";
case BOARD_TARANIS_XLITE:
@@ -529,6 +511,10 @@ QString Boards::getBoardName(Board::Type board)
return "Horus X10/X10S Express";
case BOARD_JUMPER_T16:
return "Jumper T16";
+ case BOARD_JUMPER_T18:
+ return "Jumper T18";
+ case BOARD_RADIOMASTER_TX16S:
+ return "Radiomaster TX16S";
default:
return tr("Unknown");
}
diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h
index c3cd3ff59..2ecf3c2fe 100644
--- a/companion/src/firmwares/boards.h
+++ b/companion/src/firmwares/boards.h
@@ -32,14 +32,11 @@ namespace Board {
enum Type
{
BOARD_UNKNOWN = -1,
- BOARD_9X_M64 = 0,
- BOARD_9X_M128,
- BOARD_MEGA2560,
- BOARD_GRUVIN9X,
BOARD_SKY9X,
BOARD_9XRPRO,
BOARD_AR9X,
BOARD_TARANIS_X7,
+ BOARD_TARANIS_X7_ACCESS,
BOARD_TARANIS_X9D,
BOARD_TARANIS_X9DP,
BOARD_TARANIS_X9DP_2019,
@@ -53,9 +50,11 @@ namespace Board {
BOARD_TARANIS_X9LITES,
BOARD_JUMPER_T12,
BOARD_JUMPER_T16,
+ BOARD_RADIOMASTER_TX16S,
+ BOARD_JUMPER_T18,
};
- constexpr int BOARD_TYPE_MAX = BOARD_JUMPER_T16 ;
+ constexpr int BOARD_TYPE_MAX = BOARD_JUMPER_T18;
enum PotType
{
@@ -189,26 +188,6 @@ class Boards
// temporary aliases for transition period, use Boards class instead.
#define getBoardCapability(b__, c__) Boards::getCapability(b__, c__)
-inline bool IS_9X(Board::Type board)
-{
- return board == Board::BOARD_9X_M64 || board == Board::BOARD_9X_M128;
-}
-
-inline bool IS_STOCK(Board::Type board)
-{
- return board == Board::BOARD_9X_M64;
-}
-
-inline bool IS_M128(Board::Type board)
-{
- return board == Board::BOARD_9X_M128;
-}
-
-inline bool IS_2560(Board::Type board)
-{
- return board == Board::BOARD_GRUVIN9X || board == Board::BOARD_MEGA2560;
-}
-
inline bool IS_SKY9X(Board::Type board)
{
return board == Board::BOARD_SKY9X || board == Board::BOARD_9XRPRO || board == Board::BOARD_AR9X;
@@ -229,6 +208,21 @@ inline bool IS_JUMPER_T16(Board::Type board)
return board == Board::BOARD_JUMPER_T16;
}
+inline bool IS_JUMPER_T18(Board::Type board)
+{
+ return board == Board::BOARD_JUMPER_T18;
+}
+
+inline bool IS_RADIOMASTER_TX16S(Board::Type board)
+{
+ return board == Board::BOARD_RADIOMASTER_TX16S;
+}
+
+inline bool IS_FAMILY_T16(Board::Type board)
+{
+ return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S || board == Board::BOARD_JUMPER_T18;
+}
+
inline bool IS_TARANIS_XLITE(Board::Type board)
{
return board == Board::BOARD_TARANIS_XLITE || board == Board::BOARD_TARANIS_XLITES;
@@ -241,7 +235,12 @@ inline bool IS_TARANIS_XLITES(Board::Type board)
inline bool IS_TARANIS_X7(Board::Type board)
{
- return board == Board::BOARD_TARANIS_X7;
+ return board == Board::BOARD_TARANIS_X7 || board == Board::BOARD_TARANIS_X7_ACCESS;
+}
+
+inline bool IS_TARANIS_X7_ACCESS(Board::Type board)
+{
+ return board == Board::BOARD_TARANIS_X7_ACCESS;
}
inline bool IS_TARANIS_X9LITE(Board::Type board)
@@ -249,6 +248,11 @@ inline bool IS_TARANIS_X9LITE(Board::Type board)
return board == Board::BOARD_TARANIS_X9LITE || board == Board::BOARD_TARANIS_X9LITES;
}
+inline bool IS_TARANIS_X9LITES(Board::Type board)
+{
+ return board == Board::BOARD_TARANIS_X9LITES;
+}
+
inline bool IS_TARANIS_X9(Board::Type board)
{
return board==Board::BOARD_TARANIS_X9D || board==Board::BOARD_TARANIS_X9DP || board==Board::BOARD_TARANIS_X9DP_2019 || board==Board::BOARD_TARANIS_X9E;
@@ -289,19 +293,24 @@ inline bool IS_HORUS_X12S(Board::Type board)
return board == Board::BOARD_HORUS_X12S;
}
-inline bool IS_HORUS(Board::Type board)
+inline bool IS_FAMILY_HORUS(Board::Type board)
{
- return IS_HORUS_X12S(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board);
+ return IS_HORUS_X12S(board) || IS_HORUS_X10(board);
+}
+
+inline bool IS_FAMILY_HORUS_OR_T16(Board::Type board)
+{
+ return IS_FAMILY_HORUS(board) || IS_FAMILY_T16(board);
}
inline bool IS_HORUS_OR_TARANIS(Board::Type board)
{
- return IS_HORUS(board) || IS_TARANIS(board);
+ return IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS(board);
}
inline bool IS_STM32(Board::Type board)
{
- return IS_TARANIS(board) || IS_HORUS(board);
+ return IS_TARANIS(board) || IS_FAMILY_HORUS_OR_T16(board);
}
inline bool IS_ARM(Board::Type board)
@@ -311,7 +320,7 @@ inline bool IS_ARM(Board::Type board)
inline bool HAS_LARGE_LCD(Board::Type board)
{
- return IS_HORUS(board) || IS_TARANIS_X9(board);
+ return IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board);
}
inline bool HAS_EXTERNAL_ANTENNA(Board::Type board)
@@ -319,10 +328,15 @@ inline bool HAS_EXTERNAL_ANTENNA(Board::Type board)
return (board == Board::BOARD_X10 || board == Board::BOARD_HORUS_X12S || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board)));
}
-inline bool IS_ACCESS_RADIO(Board::Type board, QString &id)
+inline bool IS_TARANIS_X9DP_2019(Board::Type board)
{
- return (IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || board == Board::BOARD_TARANIS_X9DP_2019 || board == Board::BOARD_X10_EXPRESS ||
- (IS_HORUS(board) && id.contains("internalaccess")));
+ return (board == Board::BOARD_TARANIS_X9DP_2019);
+}
+
+inline bool IS_ACCESS_RADIO(Board::Type board, const QString & id)
+{
+ return (IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || board == Board::BOARD_TARANIS_X9DP_2019 || board == Board::BOARD_X10_EXPRESS || IS_TARANIS_X7_ACCESS(board) ||
+ (IS_FAMILY_HORUS_OR_T16(board) && id.contains("internalaccess")));
}
#endif // _BOARDS_H_
diff --git a/companion/src/firmwares/curvereference.h b/companion/src/firmwares/curvereference.h
index ff5571bb5..cb5be4e73 100644
--- a/companion/src/firmwares/curvereference.h
+++ b/companion/src/firmwares/curvereference.h
@@ -50,6 +50,7 @@ class CurveReference {
int value;
QString toString(const ModelData * model = NULL, bool verbose = true) const;
+ bool isSet() const { return type != CURVE_REF_DIFF || value != 0; }
};
#endif // CURVEREFERENCE_H
diff --git a/companion/src/firmwares/customfunctiondata.cpp b/companion/src/firmwares/customfunctiondata.cpp
index c93e0965b..3248f1fa4 100644
--- a/companion/src/firmwares/customfunctiondata.cpp
+++ b/companion/src/firmwares/customfunctiondata.cpp
@@ -55,6 +55,8 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
return tr("Trainer THR");
else if (func == FuncTrainerAIL)
return tr("Trainer AIL");
+ else if (func == FuncTrainerChannels)
+ return tr("Trainer Channels");
else if (func == FuncInstantTrim)
return tr("Instant Trim");
else if (func == FuncPlaySound)
@@ -110,13 +112,10 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox
{
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("Timer3"), val++);
b->addItem(tr("Flight"), val++);
b->addItem(tr("Telemetry"), val++);
int reCount = firmware->getCapability(RotaryEncoders);
@@ -130,7 +129,7 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox
if ((int)value < b->count()) {
b->setCurrentIndex(value);
}
- if (model && IS_ARM(board)) {
+ if (model) {
for (unsigned i=0; isensorData[i].isAvailable()) {
RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i);
@@ -208,14 +207,8 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
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 = "";
- }
+ val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet();
+ unit = model->gvarData[func - FuncAdjustGV1].unitToString();
return QString("Increment: %1%2").arg(val).arg(unit);
}
}
@@ -231,7 +224,7 @@ QString CustomFunctionData::repeatToString() const
return "";
}
else {
- unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10;
+ unsigned int step = 1;
return tr("repeat(%1s)").arg(step*repeatParam);
}
}
diff --git a/companion/src/firmwares/customfunctiondata.h b/companion/src/firmwares/customfunctiondata.h
index 2ffce6688..9150035c5 100644
--- a/companion/src/firmwares/customfunctiondata.h
+++ b/companion/src/firmwares/customfunctiondata.h
@@ -41,6 +41,7 @@ enum AssignFunc {
FuncTrainerELE,
FuncTrainerTHR,
FuncTrainerAIL,
+ FuncTrainerChannels,
FuncInstantTrim,
FuncPlaySound,
FuncPlayHaptic,
diff --git a/companion/src/firmwares/eeprominterface.cpp b/companion/src/firmwares/eeprominterface.cpp
index d4121a8a4..90272d0ad 100644
--- a/companion/src/firmwares/eeprominterface.cpp
+++ b/companion/src/firmwares/eeprominterface.cpp
@@ -75,10 +75,7 @@ void EEPROMInterface::showEepromErrors(QWidget *parent, const QString &title, co
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"); }
diff --git a/companion/src/firmwares/eeprominterface.h b/companion/src/firmwares/eeprominterface.h
index 9632af1ac..b3680b4ba 100644
--- a/companion/src/firmwares/eeprominterface.h
+++ b/companion/src/firmwares/eeprominterface.h
@@ -100,6 +100,8 @@ enum Capability {
GvarsName,
NoTelemetryProtocol,
TelemetryCustomScreens,
+ TelemetryCustomScreensBars,
+ TelemetryCustomScreensLines,
TelemetryCustomScreensFieldsPerLine,
TelemetryMaxMultiplier,
HasVario,
@@ -149,7 +151,8 @@ enum Capability {
DangerousFunctions,
HasModelCategories,
HasSwitchableJack,
- PwrButtonPress
+ PwrButtonPress,
+ Sensors
};
class EEPROMInterface
@@ -232,10 +235,7 @@ enum EepromLoadErrors {
WRONG_SIZE,
WRONG_FILE_SYSTEM,
NOT_OPENTX,
- NOT_TH9X,
- NOT_GRUVIN9X,
NOT_ERSKY9X,
- NOT_ER9X,
UNKNOWN_BOARD,
WRONG_BOARD,
BACKUP_NOT_SUPPORTED,
diff --git a/companion/src/firmwares/generalsettings.cpp b/companion/src/firmwares/generalsettings.cpp
index 22934cf57..f307dbf26 100644
--- a/companion/src/firmwares/generalsettings.cpp
+++ b/companion/src/firmwares/generalsettings.cpp
@@ -88,7 +88,7 @@ GeneralSettings::GeneralSettings()
vBatMin = -5; //8,5V
vBatMax = -5; //11,5V
}
- else if (IS_TARANIS_XLITE(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board)) {
+ else if (IS_TARANIS_XLITE(board) || IS_HORUS_X10(board) || IS_FAMILY_T16(board)) {
// Lipo 2S
vBatWarn = 66;
vBatMin = -23; // 6.7V
@@ -106,19 +106,25 @@ GeneralSettings::GeneralSettings()
backlightMode = 3; // keys and sticks
// backlightBright = 0; // 0 = 100%
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
backlightOffBright = 20;
}
- if (IS_ARM(board)) {
- speakerVolume = 12;
- }
+ speakerVolume = 12;
- if (IS_HORUS(board)) {
- strcpy(bluetoothName, "Horus");
+ if (IS_JUMPER_T16(board))
+ strcpy(bluetoothName, "t16");
+ else if (IS_FAMILY_HORUS_OR_T16(board)) {
+ strcpy(bluetoothName, "horus");
}
else if (IS_TARANIS_X9E(board) || IS_TARANIS_SMALL(board)) {
- strcpy(bluetoothName, "Taranis");
+ strcpy(bluetoothName, "taranis");
+ }
+
+ for (uint8_t i = 0; i < 4; i++) {
+ trainer.mix[i].mode = 2; // replace (:=)
+ trainer.mix[i].src = i;
+ trainer.mix[i].weight = 100;
}
templateSetup = g.profile[g.sessionId()].channelOrder();
@@ -234,7 +240,7 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board)
}
// TODO: move to Boards, like with switches
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
potConfig[0] = Board::POT_WITH_DETENT;
potConfig[1] = Board::POT_MULTIPOS_SWITCH;
potConfig[2] = Board::POT_WITH_DETENT;
@@ -267,7 +273,7 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board)
sliderConfig[2] = Board::SLIDER_WITH_DETENT;
sliderConfig[3] = Board::SLIDER_WITH_DETENT;
}
- else if (IS_TARANIS_X9(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board)) {
+ else if (IS_TARANIS_X9(board) || IS_HORUS_X10(board) || IS_FAMILY_T16(board)) {
sliderConfig[0] = Board::SLIDER_WITH_DETENT;
sliderConfig[1] = Board::SLIDER_WITH_DETENT;
}
@@ -311,27 +317,27 @@ void GeneralSettings::convert(RadioDataConversionState & cstate)
// SE and SG are skipped on X7 board
if (IS_TARANIS_X7(cstate.toType)) {
- if (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType)) {
+ if (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(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)) {
+ if (IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) {
strncpy(switchName[5], switchName[4], sizeof(switchName[5]));
strncpy(switchName[7], switchName[5], sizeof(switchName[7]));
}
}
if (IS_JUMPER_T12(cstate.toType)) {
- if (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType)) {
+ if (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType)) {
strncpy(switchName[4], switchName[5], sizeof(switchName[0]));
strncpy(switchName[5], switchName[7], sizeof(switchName[0]));
}
}
else if (IS_JUMPER_T12(cstate.fromType)) {
- if (IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) {
+ if (IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) {
strncpy(switchName[5], switchName[4], sizeof(switchName[0]));
strncpy(switchName[7], switchName[5], sizeof(switchName[0]));
}
@@ -347,7 +353,7 @@ void GeneralSettings::convert(RadioDataConversionState & cstate)
strncpy(sliderName[3], sliderName[1], sizeof(sliderName[3]));
}
- if (IS_HORUS(cstate.toType)) {
+ if (IS_FAMILY_HORUS_OR_T16(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]));
diff --git a/companion/src/firmwares/generalsettings.h b/companion/src/firmwares/generalsettings.h
index a111cac1e..cdb72d9c8 100644
--- a/companion/src/firmwares/generalsettings.h
+++ b/companion/src/firmwares/generalsettings.h
@@ -142,6 +142,7 @@ class GeneralSettings {
unsigned int countryCode;
bool jitterFilter;
bool rtcCheckDisable;
+ bool keysBacklight;
unsigned int imperial;
char ttsLanguage[2+1];
int beepVolume;
diff --git a/companion/src/firmwares/gvardata.cpp b/companion/src/firmwares/gvardata.cpp
index 23c90cd2a..6ee1712d0 100644
--- a/companion/src/firmwares/gvardata.cpp
+++ b/companion/src/firmwares/gvardata.cpp
@@ -90,3 +90,8 @@ float GVarData::getMaxPrec() const
{
return getMax() * multiplierGet();
}
+
+bool GVarData::isEmpty() const
+{
+ return (name[0] == '\0' && min == 0 && max == 0 && (!popup) && prec == 0 && unit == 0);
+}
diff --git a/companion/src/firmwares/gvardata.h b/companion/src/firmwares/gvardata.h
index 7718c5b21..e0d2da882 100644
--- a/companion/src/firmwares/gvardata.h
+++ b/companion/src/firmwares/gvardata.h
@@ -43,7 +43,7 @@ class GVarData {
GVAR_PREC_MUL1
};
- char name[GVAR_NAME_LEN+1];
+ char name[GVAR_NAME_LEN + 1];
int min;
int max;
bool popup;
@@ -62,6 +62,7 @@ class GVarData {
int getMax() const;
float getMinPrec() const;
float getMaxPrec() const;
+ bool isEmpty() const;
};
diff --git a/companion/src/firmwares/io_data.cpp b/companion/src/firmwares/io_data.cpp
index b0201d3d5..a958750d8 100644
--- a/companion/src/firmwares/io_data.cpp
+++ b/companion/src/firmwares/io_data.cpp
@@ -35,6 +35,10 @@ void ExpoData::convert(RadioDataConversionState & cstate)
swtch.convert(cstate);
}
+bool ExpoData::isEmpty() const
+{
+ return (chn == 0 && mode == INPUT_MODE_NONE);
+}
/*
* MixData
@@ -48,6 +52,10 @@ void MixData::convert(RadioDataConversionState & cstate)
swtch.convert(cstate);
}
+bool MixData::isEmpty() const
+{
+ return (destCh == 0);
+}
/*
* LimitData
@@ -87,17 +95,16 @@ void LimitData::clear()
bool LimitData::isEmpty() const
{
- return (min == -1000 && max == 1000 && !revert && !offset && !ppmCenter && !symetrical && name[0] == '\0');
+ return (min == -1000 && max == 1000 && !revert && !offset && !ppmCenter && !symetrical && name[0] == '\0' && !curve.isSet());
}
-
/*
* CurveData
*/
CurveData::CurveData()
{
- clear(5);
+ clear();
}
void CurveData::clear(int count)
@@ -126,22 +133,20 @@ QString CurveData::nameToString(const int idx) const
* FlightModeData
*/
-void FlightModeData::clear(const int phase)
+void FlightModeData::clear(const int phaseIdx)
{
memset(reinterpret_cast(this), 0, sizeof(FlightModeData));
- if (phase != 0) {
- for (int idx=0; idx(this), 0, sizeof(ExpoData)); }
void convert(RadioDataConversionState & cstate);
+ bool isEmpty() const;
};
enum MltpxValue {
@@ -90,8 +93,11 @@ class MixData {
char name[MIXDATA_NAME_LEN+1];
void clear() { memset(reinterpret_cast(this), 0, sizeof(MixData)); }
+ bool isEmpty() const;
};
+#define LIMITDATA_NAME_LEN 6
+
class LimitData {
Q_DECLARE_TR_FUNCTIONS(LimitData)
@@ -103,7 +109,8 @@ class LimitData {
int offset;
int ppmCenter;
bool symetrical;
- char name[6+1];
+ int failsafe;
+ char name[LIMITDATA_NAME_LEN + 1];
CurveReference curve;
QString minToString() const;
QString maxToString() const;
@@ -120,6 +127,8 @@ class CurvePoint {
int8_t y;
};
+#define CURVEDATA_NAME_LEN 6
+
class CurveData {
Q_DECLARE_TR_FUNCTIONS(CurveData)
@@ -131,7 +140,7 @@ class CurveData {
};
CurveData();
- void clear(int count);
+ void clear(int count = 5);
bool isEmpty() const;
QString nameToString(const int idx) const;
@@ -139,9 +148,13 @@ class CurveData {
bool smooth;
int count;
CurvePoint points[CPN_MAX_POINTS];
- char name[6+1];
+ char name[CURVEDATA_NAME_LEN+1];
};
+#define FLIGHTMODE_NAME_LEN 10
+#define RENC_MAX_VALUE 1024
+#define RENC_MIN_VALUE -RENC_MAX_VALUE
+
class FlightModeData {
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
@@ -151,14 +164,20 @@ class FlightModeData {
int trimRef[CPN_MAX_TRIMS];
int trim[CPN_MAX_TRIMS];
RawSwitch swtch;
- char name[10+1];
+ char name[FLIGHTMODE_NAME_LEN+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 clear(const int phaseIdx);
+ QString nameToString(int phaseIdx) const;
void convert(RadioDataConversionState & cstate);
+ bool isEmpty(int phaseIdx) const;
+ bool isGVarEmpty(int phaseIdx, int gvIdx) const;
+ bool isREncEmpty(int phaseIdx, int reIdx) const;
+ int linkedFlightModeZero(int phaseIdx, int maxOwnValue) const;
+ int linkedGVarFlightModeZero(int phaseIdx) const;
+ int linkedREncFlightModeZero(int phaseIdx) const;
};
class SwashRingData {
diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp
index a2fdb4981..3add6de8b 100644
--- a/companion/src/firmwares/modeldata.cpp
+++ b/companion/src/firmwares/modeldata.cpp
@@ -25,6 +25,7 @@
#include "macros.h"
#include "radiodataconversionstate.h"
#include "helpers.h"
+#include "adjustmentreference.h"
/*
* TimerData
@@ -37,6 +38,10 @@ void TimerData::convert(RadioDataConversionState & cstate)
mode.convert(cstate);
}
+bool TimerData::isEmpty()
+{
+ return (mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0) && name[0] == '\0' && minuteBeep == 0 && countdownBeep == COUNTDOWN_SILENT && val == 0 && persistent == 0 /*&& pvalue == 0*/);
+}
/*
* ModelData
@@ -60,16 +65,16 @@ ModelData & ModelData::operator = (const ModelData & src)
ExpoData * ModelData::insertInput(const int idx)
{
- memmove(&expoData[idx+1], &expoData[idx], (CPN_MAX_EXPOS-(idx+1))*sizeof(ExpoData));
+ 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; imode == 0) break;
+ if (expo->mode == INPUT_MODE_NONE) break;
if (expo->chn == idx)
return true;
}
@@ -78,9 +83,9 @@ bool ModelData::isInputValid(const unsigned int idx) const
bool ModelData::hasExpos(uint8_t inputIdx) const
{
- for (int i=0; i ModelData::expos(int input) const
{
QVector result;
- for (int i=0; ichn==input && ed->mode!=0) {
+ if ((int)ed->chn == input && ed->mode != INPUT_MODE_NONE) {
result << ed;
}
}
@@ -113,9 +118,9 @@ QVector ModelData::expos(int input) const
QVector ModelData::mixes(int channel) const
{
QVector result;
- for (int i=0; idestCh == channel+1) {
+ if ((int)md->destCh == channel + 1) {
result << md;
}
}
@@ -126,8 +131,8 @@ 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();
+ 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())
@@ -136,12 +141,12 @@ void ModelData::removeInput(const int idx, bool clearName)
void ModelData::clearInputs()
{
- for (int i=0; igetCapability(VirtualInputs)) {
- for (int i=0; ichn = i;
- expo->mode = INPUT_MODE_BOTH;
- expo->srcRaw = settings.getDefaultSource(i);
- expo->weight = 100;
- strncpy(inputNames[i], Helpers::removeAccents(expo->srcRaw.toString(this)).toLatin1().constData(), sizeof(inputNames[i])-1);
- }
+ 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], Helpers::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);
- }
+ setDefaultInputs(settings);
- for (int i=0; idestCh = i+1;
+ 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);
- }
+ mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i);
}
}
@@ -240,8 +234,8 @@ void ModelData::setDefaultValues(unsigned int id, const GeneralSettings & settin
clear();
used = true;
sprintf(name, "MODEL%02d", id+1);
- for (int i=0; i 1024;
+ return flightModeData[phaseIdx].gvars[gvarIdx] > GVAR_MAX_VALUE;
}
-int ModelData::getGVarFieldValue(int phaseIdx, int gvarIdx)
+bool ModelData::isGVarLinkedCircular(int phaseIdx, int gvarIdx)
{
- int idx = flightModeData[phaseIdx].gvars[gvarIdx];
- for (int i=0; idx>GVAR_MAX_VALUE && i= phaseIdx) nextPhase += 1;
+ for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
+ int val = flightModeData[phaseIdx].gvars[gvarIdx];
+ if (phaseIdx == 0 || val <= GVAR_MAX_VALUE)
+ return false;
+ int nextPhase = val - (GVAR_MAX_VALUE + 1);
+ if (nextPhase >= phaseIdx)
+ nextPhase += 1;
phaseIdx = nextPhase;
- idx = flightModeData[phaseIdx].gvars[gvarIdx];
}
- return idx;
+ return true;
+}
+
+int ModelData::getGVarValue(int phaseIdx, int gvarIdx)
+{
+ for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
+ int val = flightModeData[phaseIdx].gvars[gvarIdx];
+ if (phaseIdx == 0 || val <= GVAR_MAX_VALUE)
+ return val;
+ int nextPhase = val - (GVAR_MAX_VALUE + 1);
+ if (nextPhase >= phaseIdx)
+ nextPhase += 1;
+ phaseIdx = nextPhase;
+ }
+ return flightModeData[0].gvars[gvarIdx]; // circular linked so return FM0 value
+}
+
+bool ModelData::isREncLinked(int phaseIdx, int reIdx)
+{
+ return flightModeData[phaseIdx].rotaryEncoders[reIdx] > RENC_MAX_VALUE;
+}
+
+bool ModelData::isREncLinkedCircular(int phaseIdx, int reIdx)
+{
+ for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
+ int val = flightModeData[phaseIdx].rotaryEncoders[reIdx];
+ if (phaseIdx == 0 || val <= RENC_MAX_VALUE)
+ return false;
+ int nextPhase = val - (RENC_MAX_VALUE + 1);
+ if (nextPhase >= phaseIdx)
+ nextPhase += 1;
+ phaseIdx = nextPhase;
+ }
+ return true;
+}
+
+int ModelData::getREncValue(int phaseIdx, int reIdx)
+{
+ for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
+ int val = flightModeData[phaseIdx].rotaryEncoders[reIdx];
+ if (phaseIdx == 0 || val <= RENC_MAX_VALUE)
+ return val;
+ int nextPhase = val - (RENC_MAX_VALUE + 1);
+ if (nextPhase >= phaseIdx)
+ nextPhase += 1;
+ phaseIdx = nextPhase;
+ }
+ return flightModeData[0].rotaryEncoders[reIdx]; // circular linked so return FM0 value
}
void ModelData::setTrimValue(int phaseIdx, int trimIdx, int value)
{
- for (uint8_t i=0; i= 126 && var <= 130)
- var = flightModeData[0].gvars[var-126];
+ var = flightModeData[0].gvars[var - 126];
else if (var <= -126 && var >= -130)
- var = - flightModeData[0].gvars[-126-var];
+ var = - flightModeData[0].gvars[-126 - var];
}
ModelData ModelData::removeGlobalVars()
{
ModelData result = *this;
- for (int i=0; isize() <= MAX_REF_UPDATES)
+ updRefList->append(UpdateReferenceParams(type, action, index1, index2, shift));
+ else
+ qDebug() << "Warning: Update ignored as the list of updates exceeds " << MAX_REF_UPDATES;
+ }
+}
+
+int ModelData::updateAllReferences(const ReferenceUpdateType type, const ReferenceUpdateAction action, const int index1, const int index2, const int shift)
+{
+ //Stopwatch s1("ModelData::updateAllReferences");
+ //s1.report("Start");
+
+ int loopcnt = 0;
+ int updcnt = 0;
+ updRefList = nullptr;
+ QVector updRefParams; // declaring this variable in ModelData class crashes program on opening model file
+ updRefList = &updRefParams; // so declare pointer variable in ModelData class and pass it the address of the local array
+
+ if (updRefList) {
+ appendUpdateReferenceParams(type, action, index1, index2, shift);
+
+ while (!updRefList->isEmpty())
+ {
+ if (++loopcnt > MAX_REF_UPDATES) {
+ qDebug() << "Warning: Update iterations terminated early as the list exceeded " << MAX_REF_UPDATES;
+ break;
+ }
+ //qDebug() << "Start of iteration:" << loopcnt;
+ updcnt += updateReference();
+ updRefList->removeFirst();
+ }
+ }
+
+ qDebug() << "Iterations:" << loopcnt << " References updated:" << updcnt;
+ //s1.report("Finish");
+
+ return updcnt;
+}
+
+int ModelData::updateReference()
+{
+ UpdateReferenceParams p = updRefList->first();
+
+ if (p.action < REF_UPD_ACT_CLEAR || p.action > REF_UPD_ACT_SWAP || p.type < REF_UPD_TYPE_CHANNEL || p.type > REF_UPD_TYPE_TIMER) {
+ qDebug() << "Error - invalid parameters" << " > type:" << p.type << " action:" << p.action << " index1:" << p.index1 << " index2:" << p.index2 << " shift:" << p.shift;
+ return 0;
+ }
+
+ memset(&updRefInfo, 0, sizeof(updRefInfo));
+ updRefInfo.type = p.type;
+ updRefInfo.action = p.action;
+ updRefInfo.index1 = abs(p.index1);
+ updRefInfo.index2 = abs(p.index2);
+ updRefInfo.shift = p.shift;
+
+ if ((updRefInfo.action == REF_UPD_ACT_SWAP && updRefInfo.index1 == updRefInfo.index2) || (updRefInfo.action == REF_UPD_ACT_SHIFT && updRefInfo.shift == 0)) {
+ qDebug() << "Warning - nothing to do" << " > type:" << updRefInfo.type << " action:" << updRefInfo.action << " index1:" << updRefInfo.index1 << " index2:" << updRefInfo.index2 << " shift:" << updRefInfo.shift;
+ return 0;
+ }
+
+ //Stopwatch s1("ModelData::updateReference");
+ //s1.report("Start");
+
+ Firmware *fw = getCurrentFirmware();
+
+ switch (updRefInfo.type)
+ {
+ case REF_UPD_TYPE_CHANNEL:
+ updRefInfo.srcType = SOURCE_TYPE_CH;
+ updRefInfo.maxindex = fw->getCapability(Outputs);
+ break;
+ case REF_UPD_TYPE_CURVE:
+ updRefInfo.maxindex = fw->getCapability(NumCurves);
+ break;
+ case REF_UPD_TYPE_FLIGHT_MODE:
+ updRefInfo.swtchType = SWITCH_TYPE_FLIGHT_MODE;
+ updRefInfo.maxindex = fw->getCapability(FlightModes);
+ break;
+ case REF_UPD_TYPE_GLOBAL_VARIABLE:
+ updRefInfo.srcType = SOURCE_TYPE_GVAR;
+ updRefInfo.maxindex = fw->getCapability(Gvars);
+ break;
+ case REF_UPD_TYPE_INPUT:
+ updRefInfo.srcType = SOURCE_TYPE_VIRTUAL_INPUT;
+ updRefInfo.maxindex = fw->getCapability(VirtualInputs);
+ break;
+ case REF_UPD_TYPE_LOGICAL_SWITCH:
+ updRefInfo.srcType = SOURCE_TYPE_CUSTOM_SWITCH;
+ updRefInfo.swtchType = SWITCH_TYPE_VIRTUAL;
+ updRefInfo.maxindex = fw->getCapability(LogicalSwitches);
+ break;
+ case REF_UPD_TYPE_SCRIPT:
+ updRefInfo.srcType = SOURCE_TYPE_LUA_OUTPUT;
+ updRefInfo.maxindex = fw->getCapability(LuaScripts);
+ break;
+ case REF_UPD_TYPE_SENSOR:
+ updRefInfo.srcType = SOURCE_TYPE_TELEMETRY;
+ updRefInfo.swtchType = SWITCH_TYPE_SENSOR;
+ updRefInfo.maxindex = fw->getCapability(Sensors);
+ break;
+ case REF_UPD_TYPE_TIMER:
+ updRefInfo.srcType = SOURCE_TYPE_SPECIAL;
+ updRefInfo.maxindex = fw->getCapability(Timers);
+ // rawsource index offset TODO refactor timers so be own category
+ updRefInfo.index1 += 2;
+ updRefInfo.index2 += 2;
+ updRefInfo.maxindex += 2;
+ break;
+ default:
+ qDebug() << "Error - unhandled reference type:" << updRefInfo.type;
+ return 0;
+ }
+
+ updRefInfo.maxindex--; // getCapabilities and constants are 1 based
+
+ //qDebug() << "updRefInfo - type:" << updRefInfo.type << " action:" << updRefInfo.action << " index1:" << updRefInfo.index1 << " index2:" << updRefInfo.index2 << " shift:" << updRefInfo.shift;
+ //qDebug() << "maxindex:" << updRefInfo.maxindex << "updRefInfo - srcType:" << updRefInfo.srcType << " swtchType:" << updRefInfo.swtchType;
+
+ //s1.report("Initialise");
+
+ for (int i = fw->getCapability(NumFirstUsableModule); i < fw->getCapability(NumModules); i++) {
+ ModuleData *md = &moduleData[i];
+ if (md->protocol != PULSES_OFF && md->failsafeMode == FAILSAFE_CUSTOM && md->hasFailsafes(fw))
+ updateModuleFailsafes(md);
+ }
+ //s1.report("Modules");
+
+ for (int i = 0; i < CPN_MAX_TIMERS; i++) {
+ TimerData *td = &timers[i];
+ if (!td->isModeOff()) {
+ updateTimerMode(td->mode);
+ if (td->isModeOff())
+ appendUpdateReferenceParams(REF_UPD_TYPE_TIMER, REF_UPD_ACT_CLEAR, i);
+ }
+ }
+ //s1.report("Timers");
+
+ for (int i = 1; i < CPN_MAX_FLIGHT_MODES; i++) { // skip FM0 as switch not used
+ FlightModeData *fmd = &flightModeData[i];
+ if (fmd->swtch.isSet()) {
+ updateSwitchRef(fmd->swtch);
+ if(!fmd->swtch.isSet())
+ appendUpdateReferenceParams(REF_UPD_TYPE_FLIGHT_MODE, REF_UPD_ACT_CLEAR, i);
+ }
+ }
+ //s1.report("Flight Modes");
+
+ for (int i = 0; i < CPN_MAX_EXPOS; i++) {
+ ExpoData *ed = &expoData[i];
+ if (!ed->isEmpty()) {
+ updateSourceRef(ed->srcRaw);
+ if (ed->srcRaw.isSet()) {
+ updateSwitchRef(ed->swtch);
+ updateCurveRef(ed->curve);
+ updateAdjustRef(ed->weight);
+ updateAdjustRef(ed->offset);
+ updateFlightModeFlags(ed->flightModes);
+ }
+ else {
+ unsigned int chnsave = ed->chn;
+ removeInput(i);
+ i--;
+ if (!hasExpos(chnsave))
+ appendUpdateReferenceParams(REF_UPD_TYPE_INPUT, REF_UPD_ACT_CLEAR, chnsave);
+ }
+ }
+ }
+ //s1.report("Inputs");
+
+ for (int i = 0; i < CPN_MAX_MIXERS; i++) {
+ MixData *md = &mixData[i];
+ if (!md->isEmpty()) {
+ updateDestCh(md);
+ if (!md->isEmpty()) {
+ updateSourceRef(md->srcRaw);
+ if (md->srcRaw.isSet()) {
+ updateSwitchRef(md->swtch);
+ updateCurveRef(md->curve);
+ updateAdjustRef(md->weight);
+ updateAdjustRef(md->sOffset);
+ updateFlightModeFlags(md->flightModes);
+ }
+ else {
+ removeMix(i);
+ i--;
+ }
+ }
+ }
+ }
+ //s1.report("Mixes");
+
+ for (int i = 0; i < CPN_MAX_CHNOUT; i++) {
+ LimitData *ld = &limitData[i];
+ if (!ld->isEmpty()) {
+ updateAdjustRef(ld->min);
+ updateAdjustRef(ld->max);
+ updateAdjustRef(ld->offset);
+ updateLimitCurveRef(ld->curve);
+ }
+ }
+ //s1.report("Outputs");
+
+ for (int i = 0; i < CPN_MAX_LOGICAL_SWITCHES; i++) {
+ LogicalSwitchData *lsd = &logicalSw[i];
+ if (!lsd->isEmpty()) {
+ bool clearlsd = false;
+ CSFunctionFamily family = lsd->getFunctionFamily();
+ switch(family) {
+ case LS_FAMILY_VOFS:
+ updateSourceIntRef(lsd->val1);
+ if (lsd->val1 == 0)
+ clearlsd = true;
+ break;
+ case LS_FAMILY_STICKY:
+ case LS_FAMILY_VBOOL:
+ updateSwitchIntRef(lsd->val1);
+ updateSwitchIntRef(lsd->val2);
+ if (lsd->val1 == 0 && lsd->val2 == 0)
+ clearlsd = true;
+ break;
+ case LS_FAMILY_EDGE:
+ updateSwitchIntRef(lsd->val1);
+ if (lsd->val1 == 0)
+ clearlsd = true;
+ break;
+ case LS_FAMILY_VCOMP:
+ updateSourceIntRef(lsd->val1);
+ updateSourceIntRef(lsd->val2);
+ if (lsd->val1 == 0 && lsd->val2 == 0)
+ clearlsd = true;
+ break;
+ default:
+ break;
+ }
+ if (clearlsd) {
+ lsd->clear();
+ appendUpdateReferenceParams(REF_UPD_TYPE_LOGICAL_SWITCH, REF_UPD_ACT_CLEAR, i);
+ }
+ else {
+ updateSwitchIntRef(lsd->andsw);
+ }
+ }
+ }
+ //s1.report("Logical Switches");
+
+ for (int i = 0; i < CPN_MAX_SPECIAL_FUNCTIONS; i++) {
+ CustomFunctionData *cfd = &customFn[i];
+ if (!cfd->isEmpty()) {
+ updateAssignFunc(cfd);
+ if (!cfd->isEmpty()) {
+ updateSwitchRef(cfd->swtch);
+ if (cfd->func == FuncVolume || cfd->func == FuncPlayValue || (cfd->func >= FuncAdjustGV1 && cfd->func <= FuncAdjustGVLast && (cfd->adjustMode == FUNC_ADJUST_GVAR_GVAR || cfd->adjustMode == FUNC_ADJUST_GVAR_SOURCE))) {
+ updateSourceIntRef(cfd->param);
+ if (cfd->param == 0)
+ cfd->clear();
+ }
+ }
+ }
+ }
+ //s1.report("Special Functions");
+
+ if (fw->getCapability(Heli)) {
+ updateSourceRef(swashRingData.aileronSource);
+ updateSourceRef(swashRingData.collectiveSource);
+ updateSourceRef(swashRingData.elevatorSource);
+ //s1.report("Heli");
+ }
+
+ if (fw->getCapability(Telemetry)) {
+ updateTelemetryRef(frsky.voltsSource);
+ updateTelemetryRef(frsky.altitudeSource);
+ updateTelemetryRef(frsky.currentSource);
+ updateTelemetryRef(frsky.varioSource);
+ for (int i = 0; i < fw->getCapability(TelemetryCustomScreens); i++) {
+ switch(frsky.screens[i].type) {
+ case TELEMETRY_SCREEN_BARS:
+ for (int j = 0; j < fw->getCapability(TelemetryCustomScreensBars); j++) {
+ FrSkyBarData *fbd = &frsky.screens[i].body.bars[j];
+ updateSourceRef(fbd->source);
+ if (!fbd->source.isSet()) {
+ fbd->barMin = 0;
+ fbd->barMax = 0;
+ }
+ }
+ break;
+ case TELEMETRY_SCREEN_NUMBERS:
+ for (int j = 0; j < fw->getCapability(TelemetryCustomScreensLines); j++) {
+ FrSkyLineData *fld = &frsky.screens[i].body.lines[j];
+ for (int k = 0; k < fw->getCapability(TelemetryCustomScreensFieldsPerLine); k++) {
+ updateSourceRef(fld->source[k]);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ //s1.report("Telemetry");
+ }
+
+ // TODO maybe less risk to leave it up to the user??
+ /*
+ for (int i = 0; i < CPN_MAX_SENSORS; i++) {
+ SensorData *sd = &sensorData[i];
+ if (sd->isAvailable() && sd->type == SensorData::TELEM_TYPE_CALCULATED) {
+ }
+ }
+ s1.report("Telemetry Sensors");
+ */
+
+ // TODO needs lua incorporated into Companion as script needs to be parsed to determine if input field is source or value
+ /*
+ for (int i=0; i < CPN_MAX_SCRIPTS; i++) {
+ ScriptData *sd = &scriptData[i];
+ if (sd->filename[0] != '\0') {
+ for (int j = 0; j < CPN_MAX_SCRIPT_INPUTS; j++) {
+ // get input parameters and for each one where type is SOURCE
+ if(inputtype = "SOURCE")
+ updateSourceIntRef(sd->inputs[j]);
+ }
+ }
+ }
+ s1.report("Custom Scripts");
+ */
+
+ // TODO Horus CustomScreenData and TopBarData will need checking for updates but Companion does not current handle ie just data blobs refer modeldata.h
+
+ qDebug() << "References updated this iteration:" << updRefInfo.updcnt;
+ //s1.report("Finish");
+
+ return updRefInfo.updcnt;
+}
+
+template
+void ModelData::updateTypeIndexRef(R & curRef, const T type, const int idxAdj, const bool defClear, const int defType, const int defIndex)
+{
+ //qDebug() << "Raw value: " << curRef.toValue() << " String:" << curRef.toString() << " Type: " << curRef.type << " Index:" << curRef.index << " idxAdj:" << idxAdj << " defClear:" << defClear << " defType:" << defType << " defIndex:" << defIndex;
+ if (!curRef.isSet() || curRef.type != type)
+ return;
+
+ R newRef;
+ newRef.type = curRef.type;
+ newRef.index = abs(curRef.index);
+
+ switch (updRefInfo.action)
+ {
+ case REF_UPD_ACT_CLEAR:
+ if (newRef.index != (updRefInfo.index1 + idxAdj))
+ return;
+ if (defClear)
+ newRef.clear();
+ else {
+ newRef.type = (T)defType;
+ newRef.index = defIndex;
+ }
+ break;
+ case REF_UPD_ACT_SHIFT:
+ if (newRef.index < (updRefInfo.index1 + idxAdj))
+ return;
+
+ newRef.index += updRefInfo.shift;
+
+ if (newRef.index < (updRefInfo.index1 + idxAdj) || newRef.index > (updRefInfo.maxindex + idxAdj)) {
+ if (defClear)
+ newRef.clear();
+ else {
+ newRef.type = (T)defType;
+ newRef.index = defIndex;
+ }
+ }
+ break;
+ case REF_UPD_ACT_SWAP:
+ if (newRef.index == updRefInfo.index1 + idxAdj)
+ newRef.index = updRefInfo.index2 + idxAdj;
+ else if (newRef.index == updRefInfo.index2 + idxAdj)
+ newRef.index = updRefInfo.index1 + idxAdj;
+ break;
+ default:
+ qDebug() << "Error - unhandled action:" << updRefInfo.action;
+ return;
+ }
+
+ if (curRef.type != newRef.type || abs(curRef.index) != newRef.index) {
+ newRef.index = curRef.index < 0 ? -newRef.index : newRef.index;
+ //qDebug() << "Updated reference: " << curRef.toString() << " -> " << newRef.toString();
+ curRef = newRef;
+ updRefInfo.updcnt++;
+ }
+}
+
+template
+void ModelData::updateTypeValueRef(R & curRef, const T type, const int idxAdj, const bool defClear, const int defType, const int defValue)
+{
+ //qDebug() << " String:" << curRef.toString() << " Type: " << curRef.type << " Value:" << curRef.value;
+ if (!curRef.isSet() || curRef.type != type)
+ return;
+
+ R newRef;
+ newRef.type = curRef.type;
+ newRef.value = abs(curRef.value);
+
+ switch (updRefInfo.action)
+ {
+ case REF_UPD_ACT_CLEAR:
+ if (newRef.value != (updRefInfo.index1 + idxAdj))
+ return;
+ if (defClear)
+ newRef.clear();
+ else {
+ newRef.type = (T)defType;
+ newRef.value = defValue;
+ }
+ break;
+ case REF_UPD_ACT_SHIFT:
+ if (newRef.value < (updRefInfo.index1 + idxAdj))
+ return;
+
+ newRef.value += updRefInfo.shift;
+
+ if (newRef.value < (updRefInfo.index1 + idxAdj) || newRef.value > (updRefInfo.maxindex + idxAdj)) {
+ if (defClear)
+ newRef.clear();
+ else {
+ newRef.type = (T)defType;
+ newRef.value = defValue;
+ }
+ }
+ break;
+ case REF_UPD_ACT_SWAP:
+ if (newRef.value == updRefInfo.index1 + idxAdj)
+ newRef.value = updRefInfo.index2 + idxAdj;
+ else if (newRef.value == updRefInfo.index2 + idxAdj)
+ newRef.value = updRefInfo.index1 + idxAdj;
+ break;
+ default:
+ qDebug() << "Error - unhandled action:" << updRefInfo.action;
+ return;
+ }
+
+ if (curRef.type != newRef.type || abs(curRef.value) != newRef.value) {
+ newRef.value = curRef.value < 0 ? -newRef.value : newRef.value;
+ //qDebug() << "Updated reference: " << curRef.toString() << " -> " << newRef.toString();
+ curRef = newRef;
+ updRefInfo.updcnt++;
+ }
+}
+
+void ModelData::updateCurveRef(CurveReference & crv)
+{
+ if (updRefInfo.type == REF_UPD_TYPE_GLOBAL_VARIABLE && (crv.type == CurveReference::CURVE_REF_DIFF || crv.type == CurveReference::CURVE_REF_EXPO))
+ updateAdjustRef(crv.value);
+ else if (updRefInfo.type == REF_UPD_TYPE_CURVE && crv.type == CurveReference::CURVE_REF_CUSTOM)
+ updateTypeValueRef(crv, CurveReference::CURVE_REF_CUSTOM, 1);
+}
+
+void ModelData::updateLimitCurveRef(CurveReference & crv)
+{
+ CurveReference src = CurveReference(CurveReference::CURVE_REF_CUSTOM, crv.value);
+ updateCurveRef(src);
+ if (crv.value != src.value)
+ crv.value = src.value;
+}
+
+void ModelData::updateAdjustRef(int & value)
+{
+ if (updRefInfo.type != REF_UPD_TYPE_GLOBAL_VARIABLE)
+ return;
+
+ AdjustmentReference adj = AdjustmentReference(value);
+ updateTypeValueRef(adj, AdjustmentReference::ADJUST_REF_GVAR, 1);
+ if (value != adj.toValue())
+ value = adj.toValue();
+}
+
+void ModelData::updateAssignFunc(CustomFunctionData * cfd)
+{
+ const int invalidateRef = -1;
+ int newRef = (int)cfd->func;
+ int idxAdj;
+
+ switch (updRefInfo.type)
+ {
+ case REF_UPD_TYPE_CHANNEL:
+ if(cfd->func < FuncOverrideCH1 || cfd->func > FuncOverrideCH32) // TODO refactor to FuncOverrideCHLast
+ return;
+ idxAdj = FuncOverrideCH1;
+ break;
+ case REF_UPD_TYPE_GLOBAL_VARIABLE:
+ if (cfd->func < FuncAdjustGV1 || cfd->func > FuncAdjustGVLast)
+ return;
+ idxAdj = FuncAdjustGV1;
+ break;
+ case REF_UPD_TYPE_TIMER:
+ if (cfd->func < FuncSetTimer1 || cfd->func > FuncSetTimer3) // TODO refactor to FuncSetTimerLast
+ return;
+ idxAdj = FuncSetTimer1 - 2; // reverse earlier offset requiured for rawsource
+ break;
+ default:
+ return;
+ }
+
+ switch (updRefInfo.action)
+ {
+ case REF_UPD_ACT_CLEAR:
+ if (newRef != (updRefInfo.index1 + idxAdj))
+ return;
+ newRef = invalidateRef;
+ break;
+ case REF_UPD_ACT_SHIFT:
+ if (newRef < (updRefInfo.index1 + idxAdj))
+ return;
+
+ newRef += updRefInfo.shift;
+
+ if (newRef < (updRefInfo.index1 + idxAdj) || newRef > (updRefInfo.maxindex + idxAdj))
+ newRef = invalidateRef;
+ break;
+ case REF_UPD_ACT_SWAP:
+ if (newRef == updRefInfo.index1 + idxAdj)
+ newRef = updRefInfo.index2 + idxAdj;
+ else if (newRef == updRefInfo.index2 + idxAdj)
+ newRef = updRefInfo.index1 + idxAdj;
+ break;
+ default:
+ qDebug() << "Error - unhandled action:" << updRefInfo.action;
+ return;
+ }
+
+ if (newRef == invalidateRef) {
+ cfd->clear();
+ //qDebug() << "Function cleared";
+ updRefInfo.updcnt++;
+ }
+ else if (cfd->func != (AssignFunc)newRef) {
+ //qDebug() << "Updated reference:" << cfd->func << " -> " << newRef;
+ cfd->func = (AssignFunc)newRef;
+ updRefInfo.updcnt++;
+ }
+}
+
+void ModelData::updateDestCh(MixData * md)
+{
+ if (updRefInfo.type != REF_UPD_TYPE_CHANNEL)
+ return;
+
+ const int invalidateRef = -1;
+ const int idxAdj = 1;
+ int newRef = md->destCh;
+ switch (updRefInfo.action)
+ {
+ case REF_UPD_ACT_CLEAR:
+ if (newRef != (updRefInfo.index1 + idxAdj))
+ return;
+ newRef = invalidateRef;
+ break;
+ case REF_UPD_ACT_SHIFT:
+ if (newRef < (updRefInfo.index1 + idxAdj))
+ return;
+
+ newRef += updRefInfo.shift;
+
+ if (newRef < (updRefInfo.index1 + idxAdj) || newRef > (updRefInfo.maxindex + idxAdj))
+ newRef = invalidateRef;
+ break;
+ case REF_UPD_ACT_SWAP:
+ if (newRef == updRefInfo.index1 + idxAdj)
+ newRef = updRefInfo.index2 + idxAdj;
+ else if (newRef == updRefInfo.index2 + idxAdj)
+ newRef = updRefInfo.index1 + idxAdj;
+ break;
+ default:
+ qDebug() << "Error - unhandled action:" << updRefInfo.action;
+ return;
+ }
+
+ if (newRef == invalidateRef) {
+ md->clear();
+ //qDebug() << "Mix cleared";
+ updRefInfo.updcnt++;
+ }
+ else if (md->destCh != static_cast(newRef)) {
+ //qDebug() << "Updated reference:" << md->destCh << " -> " << newRef;
+ md->destCh = newRef;
+ updRefInfo.updcnt++;
+ }
+}
+
+void ModelData::updateFlightModeFlags(unsigned int & curRef)
+{
+ if (updRefInfo.type != REF_UPD_TYPE_FLIGHT_MODE || curRef == 0 /*all selected*/ || curRef == 511 /*all deselected*/)
+ return;
+
+ if (updRefInfo.index1 > CPN_MAX_FLIGHT_MODES || updRefInfo.index2 > CPN_MAX_FLIGHT_MODES)
+ return;
+
+ unsigned int newRef = curRef;
+ bool flag[CPN_MAX_FLIGHT_MODES];
+ bool f;
+
+ int mask = 1;
+ for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
+ flag[i] = curRef & mask;
+ mask <<= 1;
+ }
+
+ switch (updRefInfo.action)
+ {
+ case REF_UPD_ACT_CLEAR:
+ flag[updRefInfo.index1] = false;
+ break;
+ case REF_UPD_ACT_SHIFT:
+ if(updRefInfo.shift < 0) {
+ for (int i = updRefInfo.index1; i < CPN_MAX_FLIGHT_MODES; i++) {
+ if (i - updRefInfo.shift <= updRefInfo.maxindex)
+ flag[i] = flag[i - updRefInfo.shift];
+ else
+ flag[i] = false;
+ }
+ }
+ else {
+ for (int i = CPN_MAX_FLIGHT_MODES - 1; i >= updRefInfo.index1; i--) {
+ if (i - updRefInfo.shift >= updRefInfo.index1)
+ flag[i] = flag[i - updRefInfo.shift];
+ else
+ flag[i] = false;
+ }
+ }
+ break;
+ case REF_UPD_ACT_SWAP:
+ f = flag[updRefInfo.index1];
+ flag[updRefInfo.index1] = flag[updRefInfo.index2];
+ flag[updRefInfo.index2] = f;
+ break;
+ default:
+ qDebug() << "Error - unhandled action:" << updRefInfo.action;
+ return;
+ }
+
+ newRef = 0;
+ for (int i = CPN_MAX_FLIGHT_MODES - 1; i >= 0 ; i--) {
+ if (flag[i])
+ newRef++;
+ newRef <<= 1;
+ }
+ newRef >>= 1;
+
+ if (curRef != newRef) {
+ //qDebug() << "Updated reference:" << curRef << " -> " << newRef;
+ curRef = newRef;
+ updRefInfo.updcnt++;
+ }
+}
+
+void ModelData::updateTelemetryRef(unsigned int & curRef)
+{
+ if (updRefInfo.type != REF_UPD_TYPE_SENSOR)
+ return;
+
+ const int idxAdj = 1;
+ int newRef = curRef;
+ switch (updRefInfo.action)
+ {
+ case REF_UPD_ACT_CLEAR:
+ if (newRef != (updRefInfo.index1 + idxAdj))
+ return;
+ newRef = 0;
+ break;
+ case REF_UPD_ACT_SHIFT:
+ if (newRef < (updRefInfo.index1 + idxAdj))
+ return;
+
+ newRef += updRefInfo.shift;
+
+ if (newRef < (updRefInfo.index1 + idxAdj) || newRef > (updRefInfo.maxindex + idxAdj))
+ newRef = 0;
+ break;
+ case REF_UPD_ACT_SWAP:
+ if (newRef == updRefInfo.index1 + idxAdj)
+ newRef = updRefInfo.index2 + idxAdj;
+ else if (newRef == updRefInfo.index2 + idxAdj)
+ newRef = updRefInfo.index1 + idxAdj;
+ break;
+ default:
+ qDebug() << "Error - unhandled action:" << updRefInfo.action;
+ return;
+ }
+
+ if (curRef != static_cast(newRef)) {
+ //qDebug() << "Updated reference:" << curRef << " -> " << newRef;
+ curRef = newRef;
+ updRefInfo.updcnt++;
+ }
+}
+
+void ModelData::updateModuleFailsafes(ModuleData * md)
+{
+ if (updRefInfo.type != REF_UPD_TYPE_CHANNEL)
+ return;
+
+ bool updated = false;
+
+ switch (updRefInfo.action) {
+ case REF_UPD_ACT_CLEAR:
+ break;
+ case REF_UPD_ACT_SHIFT:
+ if (updRefInfo.shift == 0 || updRefInfo.index1 < 0 || updRefInfo.index1 > CPN_MAX_CHNOUT - 1)
+ return;
+
+ if (updRefInfo.shift > 0) {
+ for (int i = CPN_MAX_CHNOUT - 1; i > updRefInfo.index1; i--) {
+ limitData[i].failsafe = limitData[i - 1].failsafe;
+ }
+ limitData[updRefInfo.index1].failsafe = 0;
+ }
+ else {
+ for (int i = updRefInfo.index1 + 1; i < CPN_MAX_CHNOUT - 1; i++) {
+ limitData[i - 1].failsafe = limitData[i].failsafe;
+ }
+ limitData[CPN_MAX_CHNOUT - 1].failsafe = 0;
+ }
+ updated = true;
+ break;
+ case REF_UPD_ACT_SWAP:
+ int tmp;
+ if (updRefInfo.index1 >= 0 && updRefInfo.index1 < CPN_MAX_CHNOUT) {
+ updated = true;
+ tmp = limitData[updRefInfo.index1].failsafe;
+ if (updRefInfo.index2 >= 0 && updRefInfo.index2 < CPN_MAX_CHNOUT)
+ limitData[updRefInfo.index1].failsafe = limitData[updRefInfo.index2].failsafe;
+ else
+ limitData[updRefInfo.index1].failsafe = 0;
+ }
+ else
+ tmp = 0;
+ if (updRefInfo.index2 >= 0 && updRefInfo.index2 < CPN_MAX_CHNOUT) {
+ updated = true;
+ limitData[updRefInfo.index2].failsafe = tmp;
+ }
+ break;
+ default:
+ qDebug() << "Error - unhandled action:" << updRefInfo.action;
+ return;
+ }
+
+ if (updated) {
+ //qDebug() << "Updated module failsafes";
+ updRefInfo.updcnt++;
+ }
+}
+
+int ModelData::linkedFlightModeIndexToValue(const int phaseIdx, const int useFmIdx, const int maxOwnValue)
+{
+ int val;
+
+ if (phaseIdx == useFmIdx || phaseIdx < 0 || phaseIdx > (CPN_MAX_FLIGHT_MODES - 1) || useFmIdx < 0 || useFmIdx > (CPN_MAX_FLIGHT_MODES - 1))
+ val = flightModeData[phaseIdx].linkedFlightModeZero(phaseIdx, maxOwnValue);
+ else
+ val = maxOwnValue + useFmIdx + (useFmIdx >= phaseIdx ? 0 : 1);
+
+ return val;
+}
+
+int ModelData::linkedFlightModeValueToIndex(const int phaseIdx, const int val, const int maxOwnValue)
+{
+ int idx = val - maxOwnValue - 1;
+ if (idx >= phaseIdx)
+ idx += 1;
+ return idx;
+}
+
+int ModelData::getGVarFlightModeIndex(const int phaseIdx, const int gvarIdx)
+{
+ if (!isGVarLinked(phaseIdx, gvarIdx))
+ return -1;
+ return (linkedFlightModeValueToIndex(phaseIdx, flightModeData[phaseIdx].gvars[gvarIdx], GVAR_MAX_VALUE));
+}
+
+void ModelData::setGVarFlightModeIndexToValue(const int phaseIdx, const int gvarIdx, const int useFmIdx)
+{
+ flightModeData[phaseIdx].gvars[gvarIdx] = linkedFlightModeIndexToValue(phaseIdx, useFmIdx, GVAR_MAX_VALUE);
+}
+
+int ModelData::getREncFlightModeIndex(const int phaseIdx, const int reIdx)
+{
+ if (!isREncLinked(phaseIdx, reIdx))
+ return -1;
+ return (linkedFlightModeValueToIndex(phaseIdx, flightModeData[phaseIdx].rotaryEncoders[reIdx], RENC_MAX_VALUE));
+}
+
+void ModelData::setREncFlightModeIndexToValue(const int phaseIdx, const int reIdx, const int useFmIdx)
+{
+ flightModeData[phaseIdx].rotaryEncoders[reIdx] = linkedFlightModeIndexToValue(phaseIdx, useFmIdx, RENC_MAX_VALUE);
+}
+
+bool ModelData::isExpoParent(const int index)
+{
+ const ExpoData &ed = expoData[index];
+ const QVector chexpos = expos(ed.chn);
+ return chexpos.constFirst() == &ed;
+}
+
+bool ModelData::isExpoChild(const int index)
+{
+ const ExpoData &ed = expoData[index];
+ const QVector chexpos = expos(ed.chn);
+ return chexpos.constFirst() != &ed;
+}
+
+bool ModelData::hasExpoChildren(const int index)
+{
+ const ExpoData &ed = expoData[index];
+ const QVector chexpos = expos(ed.chn);
+ return chexpos.constFirst() == &ed && chexpos.constLast() != &ed;
+}
+
+bool ModelData::hasExpoSiblings(const int index)
+{
+ const ExpoData &ed = expoData[index];
+ const QVector chexpos = expos(ed.chn);
+ return !isExpoParent(index) && chexpos.size() > 2;
+}
+
+void ModelData::removeMix(const int idx)
+{
+ memmove(&mixData[idx], &mixData[idx + 1], (CPN_MAX_MIXERS - (idx + 1)) * sizeof(MixData));
+ mixData[CPN_MAX_MIXERS - 1].clear();
+}
diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h
index c4959d456..df5c6d33d 100644
--- a/companion/src/firmwares/modeldata.h
+++ b/companion/src/firmwares/modeldata.h
@@ -41,13 +41,10 @@ class RadioDataConversionState;
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;
@@ -76,6 +73,8 @@ class TimerData {
int pvalue;
void clear() { memset(reinterpret_cast(this), 0, sizeof(TimerData)); mode = RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
void convert(RadioDataConversionState & cstate);
+ bool isEmpty();
+ bool isModeOff() { return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
};
#define CPN_MAX_SCRIPTS 9
@@ -128,6 +127,8 @@ enum TrainerMode {
TRAINER_MODE_MULTI
};
+#define INPUT_NAME_LEN 4
+
class ModelData {
Q_DECLARE_TR_FUNCTIONS(ModelData)
@@ -170,7 +171,7 @@ class ModelData {
MixData mixData[CPN_MAX_MIXERS];
LimitData limitData[CPN_MAX_CHNOUT];
- char inputNames[CPN_MAX_INPUTS][4+1];
+ char inputNames[CPN_MAX_INPUTS][INPUT_NAME_LEN+1];
ExpoData expoData[CPN_MAX_EXPOS];
CurveData curves[CPN_MAX_CURVES];
@@ -219,11 +220,23 @@ class ModelData {
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);
+ bool isGVarLinkedCircular(int phaseIdx, int gvarIdx);
+ int getGVarValue(int phaseIdx, int gvarIdx);
+ float getGVarValuePrec(int phaseIdx, int gvarIdx);
+ int getGVarFlightModeIndex(const int phaseIdx, const int gvarIdx);
+ void setGVarFlightModeIndexToValue(const int phaseIdx, const int gvarIdx, const int useFmIdx);
+
+ bool isREncLinked(int phaseIdx, int reIdx);
+ bool isREncLinkedCircular(int phaseIdx, int reIdx);
+ int getREncValue(int phaseIdx, int reIdx);
+ int getREncFlightModeIndex(const int phaseIdx, const int reIdx);
+ void setREncFlightModeIndexToValue(const int phaseIdx, const int reIdx, const int useFmIdx);
ModelData removeGlobalVars();
+ int linkedFlightModeIndexToValue(const int phaseIdx, const int useFmIdx, const int maxOwnValue);
+ int linkedFlightModeValueToIndex(const int phaseIdx, const int val, const int maxOwnValue);
+
void clearMixes();
void clearInputs();
@@ -231,8 +244,95 @@ class ModelData {
bool isAvailable(const RawSwitch & swtch) const;
+ enum ReferenceUpdateAction {
+ REF_UPD_ACT_CLEAR,
+ REF_UPD_ACT_SHIFT,
+ REF_UPD_ACT_SWAP,
+ };
+
+ enum ReferenceUpdateType {
+ REF_UPD_TYPE_CHANNEL,
+ REF_UPD_TYPE_CURVE,
+ REF_UPD_TYPE_FLIGHT_MODE,
+ REF_UPD_TYPE_GLOBAL_VARIABLE,
+ REF_UPD_TYPE_INPUT,
+ REF_UPD_TYPE_LOGICAL_SWITCH,
+ REF_UPD_TYPE_SCRIPT,
+ REF_UPD_TYPE_SENSOR,
+ REF_UPD_TYPE_TIMER,
+ };
+
+ struct UpdateReferenceParams
+ {
+ ReferenceUpdateType type;
+ ReferenceUpdateAction action;
+ int index1;
+ int index2;
+ int shift;
+
+ UpdateReferenceParams() {}
+ UpdateReferenceParams(ReferenceUpdateType t, ReferenceUpdateAction a, int i1, int i2 = 0, int s = 0) :
+ type(t), action(a), index1(i1), index2(i2), shift(s) {}
+ };
+
+ int updateAllReferences(const ReferenceUpdateType type, const ReferenceUpdateAction action, const int index1, const int index2 = 0, const int shift = 0);
+ bool isExpoParent(const int index);
+ bool isExpoChild(const int index);
+ bool hasExpoChildren(const int index);
+ bool hasExpoSiblings(const int index);
+ void removeMix(const int idx);
+
protected:
void removeGlobalVar(int & var);
+
+ private:
+ QVector *updRefList = nullptr;
+
+ struct UpdateReferenceInfo
+ {
+ ReferenceUpdateType type;
+ ReferenceUpdateAction action;
+ int index1;
+ int index2;
+ int shift;
+ int updcnt;
+ int maxindex;
+ RawSourceType srcType;
+ RawSwitchType swtchType;
+ };
+ UpdateReferenceInfo updRefInfo;
+
+ int updateReference();
+ void appendUpdateReferenceParams(const ReferenceUpdateType type, const ReferenceUpdateAction action, const int index1, const int index2 = 0, const int shift = 0);
+ template
+ void updateTypeIndexRef(R & curref, const T type, const int idxAdj = 0, const bool defClear = true, const int defType = 0, const int defIndex = 0);
+ template
+ void updateTypeValueRef(R & curref, const T type, const int idxAdj = 0, const bool defClear = true, const int defType = 0, const int defValue = 0);
+ void updateAdjustRef(int & adj);
+ void updateAssignFunc(CustomFunctionData * cfd);
+ void updateCurveRef(CurveReference & crv);
+ void updateDestCh(MixData * md);
+ void updateLimitCurveRef(CurveReference & crv);
+ void updateFlightModeFlags(unsigned int & flags);
+ void updateTelemetryRef(unsigned int & idx);
+ void updateModuleFailsafes(ModuleData * md);
+ inline void updateSourceRef(RawSource & src) { updateTypeIndexRef(src, updRefInfo.srcType); }
+ inline void updateSwitchRef(RawSwitch & swtch) { updateTypeIndexRef(swtch, updRefInfo.swtchType, 1); }
+ inline void updateTimerMode(RawSwitch & swtch) { updateTypeIndexRef(swtch, updRefInfo.swtchType, 1, false, (int)SWITCH_TYPE_TIMER_MODE, 0); }
+ inline void updateSourceIntRef(int & value)
+ {
+ RawSource src = RawSource(value);
+ updateTypeIndexRef(src, updRefInfo.srcType);
+ if (value != src.toValue())
+ value = src.toValue();
+ }
+ inline void updateSwitchIntRef(int & value)
+ {
+ RawSwitch swtch = RawSwitch(value);
+ updateTypeIndexRef(swtch, updRefInfo.swtchType, 1);
+ if (value != swtch.toValue())
+ value = swtch.toValue();
+ }
};
#endif // MODELDATA_H
diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp
index a227dd5b8..c899632af 100644
--- a/companion/src/firmwares/moduledata.cpp
+++ b/companion/src/firmwares/moduledata.cpp
@@ -21,6 +21,7 @@
#include "moduledata.h"
#include "eeprominterface.h"
#include "multiprotocols.h"
+#include "afhds3.h"
#include "radiodataconversionstate.h"
void ModuleData::convert(RadioDataConversionState & cstate)
@@ -87,7 +88,6 @@ QString ModuleData::rfProtocolToString() const
switch (protocol) {
case PULSES_MULTIMODULE:
return Multiprotocols::protocolToString((int)multi.rfProtocol);
-
default:
return CPN_STR_UNKNOWN_ITEM;
}
@@ -108,10 +108,10 @@ QString ModuleData::subTypeToString(int type) const
switch (protocol) {
case PULSES_MULTIMODULE:
return Multiprotocols::subTypeToString((int)multi.rfProtocol, (unsigned)type);
-
case PULSES_PXX_R9M:
return CHECK_IN_ARRAY(strings, type);
-
+ case PULSES_AFHDS3:
+ return Afhds3Data::protocolToString(type);
default:
return CPN_STR_UNKNOWN_ITEM;
}
@@ -119,8 +119,8 @@ QString ModuleData::subTypeToString(int type) const
QString ModuleData::powerValueToString(Firmware * fw) const
{
- const QStringList & strRef = powerValueStrings(subType, fw);
- return strRef.value(pxx.power, CPN_STR_UNKNOWN_ITEM);
+ const QStringList & strRef = powerValueStrings((enum PulsesProtocol)protocol, subType, fw);
+ return strRef.value(protocol == PULSES_AFHDS3 ? afhds3.rfPower : pxx.power, CPN_STR_UNKNOWN_ITEM);
}
// static
@@ -159,14 +159,15 @@ QString ModuleData::protocolToString(unsigned protocol)
"FrSky ACCESS R9M 2019",
"FrSky ACCESS R9M Lite",
"FrSky ACCESS R9M Lite Pro",
- "FrSky XJT lite (D16)", "FrSky XJT lite (D8)", "FrSky XJT lite (LR12)"
+ "FrSky XJT lite (D16)", "FrSky XJT lite (D8)", "FrSky XJT lite (LR12)",
+ "AFHDS3"
};
return CHECK_IN_ARRAY(strings, protocol);
}
// static
-QStringList ModuleData::powerValueStrings(int subType, Firmware * fw)
+QStringList ModuleData::powerValueStrings(enum PulsesProtocol protocol, int subType, Firmware * fw)
{
static const QStringList strings[] = {
{ tr("10mW - 16CH"), tr("100mW - 16CH"), tr("500mW - 16CH"), tr("Auto <= 1W - 16CH") }, // full-size FCC
@@ -174,10 +175,78 @@ QStringList ModuleData::powerValueStrings(int subType, Firmware * fw)
{ 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];
+ static const QStringList afhds3Strings = {
+ tr("25 mW"), tr("100 mW"), tr("500 mW"), tr("1 W"), tr("2 W")
+ };
+
+ switch(protocol) {
+ case PULSES_AFHDS3:
+ return afhds3Strings;
+ default:
+ int strIdx = 0;
+ if (subType == MODULE_SUBTYPE_R9M_EU)
+ strIdx += 1;
+ if (fw->getCapability(HasModuleR9MMini))
+ strIdx += 2;
+ return strings[strIdx];
+ }
+}
+
+bool ModuleData::hasFailsafes(Firmware * fw) const
+{
+ return fw->getCapability(HasFailsafe) && (
+ protocol == PULSES_ACCESS_ISRM ||
+ protocol == PULSES_ACCST_ISRM_D16 ||
+ protocol == PULSES_PXX_XJT_X16 ||
+ protocol == PULSES_PXX_R9M ||
+ protocol == PULSES_ACCESS_R9M ||
+ protocol == PULSES_ACCESS_R9M_LITE ||
+ protocol == PULSES_ACCESS_R9M_LITE_PRO ||
+ protocol == PULSES_XJT_LITE_X16 ||
+ protocol == PULSES_MULTIMODULE ||
+ protocol == PULSES_AFHDS3
+ );
+}
+
+int ModuleData::getMaxChannelCount()
+{
+ switch (protocol) {
+ case PULSES_ACCESS_ISRM:
+ return 24;
+ case PULSES_PXX_R9M:
+ case PULSES_ACCESS_R9M:
+ case PULSES_ACCESS_R9M_LITE:
+ case PULSES_ACCESS_R9M_LITE_PRO:
+ case PULSES_ACCST_ISRM_D16:
+ case PULSES_XJT_LITE_X16:
+ case PULSES_PXX_XJT_X16:
+ case PULSES_CROSSFIRE:
+ case PULSES_SBUS:
+ case PULSES_PPM:
+ return 16;
+ case PULSES_XJT_LITE_LR12:
+ case PULSES_PXX_XJT_LR12:
+ return 12;
+ case PULSES_PXX_DJT:
+ case PULSES_XJT_LITE_D8:
+ case PULSES_PXX_XJT_D8:
+ return 8;
+ case PULSES_LP45:
+ case PULSES_DSM2:
+ case PULSES_DSMX:
+ return 6;
+ case PULSES_MULTIMODULE:
+ if (multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2)
+ return 12;
+ else
+ return 16;
+ break;
+ case PULSES_AFHDS3:
+ return 18;
+ case PULSES_OFF:
+ break;
+ default:
+ break;
+ }
+ return 8;
}
diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h
index 6d6795c58..d3e851879 100644
--- a/companion/src/firmwares/moduledata.h
+++ b/companion/src/firmwares/moduledata.h
@@ -58,6 +58,7 @@ enum PulsesProtocol {
PULSES_XJT_LITE_X16,
PULSES_XJT_LITE_D8,
PULSES_XJT_LITE_LR12,
+ PULSES_AFHDS3,
PULSES_PROTOCOL_LAST
};
@@ -117,7 +118,23 @@ enum MultiModuleRFProtocols {
MODULE_SUBTYPE_MULTI_SCANNER,
MODULE_SUBTYPE_MULTI_FRSKYX_RX,
MODULE_SUBTYPE_MULTI_AFHDS2A_RX,
- MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_AFHDS2A_RX
+ MODULE_SUBTYPE_MULTI_HOTT,
+ MODULE_SUBTYPE_MULTI_FX816,
+ MODULE_SUBTYPE_MULTI_BAYANG_RX,
+ MODULE_SUBTYPE_MULTI_PELIKAN,
+ MODULE_SUBTYPE_MULTI_TIGER,
+ MODULE_SUBTYPE_MULTI_XK,
+ MODULE_SUBTYPE_MULTI_XN297DUMP,
+ MODULE_SUBTYPE_MULTI_FRSKYX2,
+ MODULE_SUBTYPE_MULTI_FRSKY_R9,
+ MODULE_SUBTYPE_MULTI_PROPEL,
+ MODULE_SUBTYPE_MULTI_FRSKYL,
+ MODULE_SUBTYPE_MULTI_SKYARTEC,
+ MODULE_SUBTYPE_MULTI_ESKY150V2,
+ MODULE_SUBTYPE_MULTI_DSM_RX,
+ MODULE_SUBTYPE_MULTI_JJRC345,
+ MODULE_SUBTYPE_MULTI_Q90C,
+ MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_Q90C
};
enum TrainerProtocol {
@@ -143,17 +160,20 @@ class ModuleData {
Q_DECLARE_TR_FUNCTIONS(ModuleData)
public:
- ModuleData() { clear(); }
+ ModuleData()
+ {
+ clear();
+ }
+
unsigned int modelId;
unsigned int protocol; // type in datastructs.h
int rfProtocol; // rfProtocol in datastructs.h
-
+
unsigned int subType;
bool invertedSerial;
unsigned int channelsStart;
int channelsCount; // 0=8 channels
unsigned int failsafeMode;
- int failsafeChannels[CPN_MAX_CHNOUT];
struct PPM {
int delay;
@@ -171,6 +191,11 @@ class ModuleData {
int optionValue;
} multi;
+ struct Afhds3 {
+ unsigned int rxFreq;
+ unsigned int rfPower;
+ } afhds3;
+
struct PXX {
unsigned int power; // 0 10 mW, 1 100 mW, 2 500 mW, 3 1W
bool receiverTelemetryOff; // false = receiver telem enabled
@@ -194,7 +219,9 @@ class ModuleData {
QString powerValueToString(Firmware * fw) const;
static QString indexToString(int index, Firmware * fw);
static QString protocolToString(unsigned protocol);
- static QStringList powerValueStrings(int subType, Firmware * fw);
+ static QStringList powerValueStrings(enum PulsesProtocol protocol, int subType, Firmware * fw);
+ bool hasFailsafes(Firmware * fw) const;
+ int getMaxChannelCount();
};
#endif // MODULEDATA_H
diff --git a/companion/src/firmwares/multiprotocols.cpp b/companion/src/firmwares/multiprotocols.cpp
index f1b37bae0..c8c18e6e5 100644
--- a/companion/src/firmwares/multiprotocols.cpp
+++ b/companion/src/firmwares/multiprotocols.cpp
@@ -26,8 +26,8 @@
#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_RFPOWER QT_TRANSLATE_NOOP("Multiprotocols", "RF power")
#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_FIXEDID QT_TRANSLATE_NOOP("Multiprotocols", "Fixed ID value")
@@ -39,10 +39,10 @@ static const QStringList STR_SUBTYPE_CUSTOM ({
});
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_FRSKY {"D16", "D8", "D16 8ch", "V8", "D16 EU-LBT", "D16 EU-LBT 8ch", "D8 Cloned", "D16 Cloned"};
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_V2X2 {"Standard", "JXD506", "MR101"};
+static const QStringList STR_SUBTYPE_DSM {"DSM2 1F", "DSM2 2F", "DSMX 1F", "DSMX 2F"};
static const QStringList STR_SUBTYPE_DEVO {"8 Channel", "10 Channel", "12 Channel", "6 Channel", "7 Channel"};
static const QStringList STR_SUBTYPE_YD717 {"Standard", "Skywalker", "Syma X4", "XINXUN", "NIHUI"};
static const QStringList STR_SUBTYPE_KN {"WLtoys", "FeiLun"};
@@ -50,7 +50,8 @@ 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", "DHD D4"};
+static const QStringList STR_SUBTYPE_BAYANG {"Standard", "H8S3D", "X16 AH", "IRDRONE", "DHD D4", "QX100"};
+static const QStringList STR_SUBTYPE_ESky {"Standard", "ET4"};
static const QStringList STR_SUBTYPE_MT99 {"MT99", "H7", "YZ", "LS", "FY805"};
static const QStringList STR_SUBTYPE_MJXQ {"WLH08", "X600", "X800", "H26D", "E010", "H26WH", "Phoenix"};
static const QStringList STR_SUBTYPE_FY326 {"Standard", "FY319"};
@@ -60,18 +61,32 @@ 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_ESKY150 {"4 Channel", "7 Channel"};
static const QStringList STR_SUBTYPE_H83D {"H8 Mini 3D", "H20H", "H20 Mini", "H30 Mini"};
static const QStringList STR_SUBTYPE_CORONA {"Corona V1", "Corona V2", "Flydream V3"};
static const QStringList STR_SUBTYPE_HITEC {"Optima", "Optima Hub Telem", "Minima"};
-static const QStringList STR_SUBTYPE_TRAXXAS {"6519 RX"};
+static const QStringList STR_SUBTYPE_WFLY {"WFR0xS"};
static const QStringList STR_SUBTYPE_BUGS_MINI {"Standard", "Bugs 3H"};
+static const QStringList STR_SUBTYPE_TRAXXAS {"6519 RX"};
static const QStringList STR_SUBTYPE_E01X {"E012", "E015", "E016H"};
+static const QStringList STR_SUBTYPE_V911S {"Standard", "E119"};
static const QStringList STR_SUBTYPE_GD00X {"GD V1", "GD V2"};
+static const QStringList STR_SUBTYPE_V761 {"3 Channel", "4 Channel"};
static const QStringList STR_SUBTYPE_REDPINE {"Fast", "Slow"};
static const QStringList STR_SUBTYPE_POTENSIC {"A20 Firefly"};
static const QStringList STR_SUBTYPE_ZSX {"JJRC ZSX-280"};
static const QStringList STR_SUBTYPE_FLYZONE {"FZ-410 TX"};
-static const QStringList STR_SUBTYPE_FRSKYX_RX {"D16 FCC", "D16 LBT"};
+static const QStringList STR_SUBTYPE_FRSKYX_RX {"RX", "Clone TX"};
+static const QStringList STR_SUBTYPE_HOTT {"Sync", "No_Sync"};
+static const QStringList STR_SUBTYPE_FX816 {"P38"};
+static const QStringList STR_SUBTYPE_PELIKAN {"Pro", "Lite"};
+static const QStringList STR_SUBTYPE_XK {"X450", "X420"};
+static const QStringList STR_SUBTYPE_XN297DUMP {"250K", "1M", "2M", "AUTO", "NRF"};
+static const QStringList STR_SUBTYPE_FRSKYX2 {"D16", "D16 8ch", "D16 EU-LBT", "D16 EU-LBT 8ch", "D16 Cloned"};
+static const QStringList STR_SUBTYPE_FRSKYR9 {"915 MHz", "868 MHz", "915 MHz 8-Channel", "868 MHz 8-Channel"};
+static const QStringList STR_SUBTYPE_PROPEL {"74-Z"};
+static const QStringList STR_SUBTYPE_FRSKYL {"LR12", "LR12 6-Channel"};
+static const QStringList STR_SUBTYPE_ESKY150V2 {"150 V2"};
static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
@@ -81,22 +96,24 @@ static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
const Multiprotocols multiProtocols {
{MODULE_SUBTYPE_MULTI_FLYSKY, 4, false, STR_SUBTYPE_FLYSKY, nullptr},
{MODULE_SUBTYPE_MULTI_HUBSAN, 2, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
- {MODULE_SUBTYPE_MULTI_FRSKY, 5, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_FRSKY, 7, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_HISKY, 1, false, STR_SUBTYPE_HISKY, nullptr},
- {MODULE_SUBTYPE_MULTI_V2X2, 1, false, STR_SUBTYPE_V2X2, nullptr},
+ {MODULE_SUBTYPE_MULTI_V2X2, 2, false, STR_SUBTYPE_V2X2, nullptr},
{MODULE_SUBTYPE_MULTI_DSM2, 3, false, STR_SUBTYPE_DSM, nullptr},
{MODULE_SUBTYPE_MULTI_DEVO, 4, false, STR_SUBTYPE_DEVO, STR_MULTI_FIXEDID},
{MODULE_SUBTYPE_MULTI_YD717, 4, false, STR_SUBTYPE_YD717, nullptr},
{MODULE_SUBTYPE_MULTI_KN, 1, false, STR_SUBTYPE_KN, nullptr},
{MODULE_SUBTYPE_MULTI_SYMAX, 1, false, STR_SUBTYPE_SYMAX, nullptr},
- {MODULE_SUBTYPE_MULTI_SLT, 4, false, STR_SUBTYPE_SLT, nullptr},
+ {MODULE_SUBTYPE_MULTI_SLT, 4, false, STR_SUBTYPE_SLT, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_CX10, 6, false, STR_SUBTYPE_CX10, nullptr},
{MODULE_SUBTYPE_MULTI_CG023, 1, false, STR_SUBTYPE_CG023, nullptr},
- {MODULE_SUBTYPE_MULTI_BAYANG, 4, false, STR_SUBTYPE_BAYANG, STR_MULTI_TELEMETRY},
+ {MODULE_SUBTYPE_MULTI_BAYANG, 5, false, STR_SUBTYPE_BAYANG, STR_MULTI_TELEMETRY},
+ {MODULE_SUBTYPE_MULTI_ESky, 1, false, STR_SUBTYPE_ESky, nullptr},
{MODULE_SUBTYPE_MULTI_MT99XX, 4, false, STR_SUBTYPE_MT99, nullptr},
{MODULE_SUBTYPE_MULTI_MJXQ, 6, false, STR_SUBTYPE_MJXQ, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FY326, 1, false, STR_SUBTYPE_FY326, nullptr},
{MODULE_SUBTYPE_MULTI_SFHSS, 0, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_J6PRO, 0, false, NO_SUBTYPE, nullptr},
{MODULE_SUBTYPE_MULTI_HONTAI, 3, false, STR_SUBTYPE_HONTAI, nullptr},
{MODULE_SUBTYPE_MULTI_OLRS, 0, false, NO_SUBTYPE, STR_MULTI_RFPOWER},
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 3, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
@@ -104,20 +121,35 @@ const Multiprotocols multiProtocols {
{MODULE_SUBTYPE_MULTI_WK_2X01, 5, false, STR_SUBTYPE_WK2x01, nullptr},
{MODULE_SUBTYPE_MULTI_Q303, 3, false, STR_SUBTYPE_Q303, nullptr},
{MODULE_SUBTYPE_MULTI_CABELL, 7, false, STR_SUBTYPE_CABELL, STR_MULTI_OPTION},
+ {MODULE_SUBTYPE_MULTI_ESKY150, 1, false, STR_SUBTYPE_ESKY150, nullptr},
{MODULE_SUBTYPE_MULTI_H83D, 3, false, STR_SUBTYPE_H83D, nullptr},
{MODULE_SUBTYPE_MULTI_CORONA, 2, false, STR_SUBTYPE_CORONA, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_HITEC, 2, false, STR_SUBTYPE_HITEC, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_WFLY, 0, false, STR_SUBTYPE_WFLY, nullptr},
{MODULE_SUBTYPE_MULTI_BUGS_MINI, 1, false, STR_SUBTYPE_BUGS_MINI, nullptr},
{MODULE_SUBTYPE_MULTI_TRAXXAS, 0, false, STR_SUBTYPE_TRAXXAS, nullptr},
{MODULE_SUBTYPE_MULTI_E01X, 2, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION},
- {MODULE_SUBTYPE_MULTI_V911S, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
- {MODULE_SUBTYPE_MULTI_GD00X, 1, false, STR_SUBTYPE_GD00X, nullptr},
+ {MODULE_SUBTYPE_MULTI_V911S, 1, false, STR_SUBTYPE_V911S, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_GD00X, 1, false, STR_SUBTYPE_GD00X, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_V761, 1, false, STR_SUBTYPE_V761, nullptr},
{MODULE_SUBTYPE_MULTI_KF606, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_REDPINE, 1, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, STR_SUBTYPE_POTENSIC, nullptr},
{MODULE_SUBTYPE_MULTI_ZSX, 0, false, STR_SUBTYPE_ZSX, nullptr},
{MODULE_SUBTYPE_MULTI_FLYZONE, 0, false, STR_SUBTYPE_FLYZONE, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_HOTT, 1, true, STR_SUBTYPE_HOTT, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_FX816, 0, false, STR_SUBTYPE_FX816, nullptr},
+ {MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, STR_SUBTYPE_PELIKAN, nullptr},
+ {MODULE_SUBTYPE_MULTI_XK, 1, false, STR_SUBTYPE_XK, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_XN297DUMP, 4, false, STR_SUBTYPE_XN297DUMP, nullptr},
+ {MODULE_SUBTYPE_MULTI_FRSKYX2, 4, true, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, STR_SUBTYPE_FRSKYR9, nullptr},
+ {MODULE_SUBTYPE_MULTI_PROPEL, 0, false, STR_SUBTYPE_PROPEL, nullptr},
+ {MODULE_SUBTYPE_MULTI_FRSKYL, 1, false, STR_SUBTYPE_FRSKYL, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_SKYARTEC, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_ESKY150V2, 0, false, STR_SUBTYPE_ESKY150V2, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_Q90C, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{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)
@@ -158,15 +190,14 @@ 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",
+ "FlySky AFHDS2A", "Q2x2", "WK2x01", "Q303", "GW008", "DM002", "Cabell", "ESky 150", "H8 3D", "Corona", "CFlie",
"Hitec", "Wfly", "Bugs", "Bugs Mini", "Traxxas", "NCC-1701-A", "E01X", "WL Heli V911S", "GD00X", "Volantex V761",
- "KFPlan KF606", "Redpine", "Potensic", "ZXS", "FlyZone", "Scanner", "FrSky RX", "FlySky AFHDS2A RX"
+ "KFPlan KF606", "Redpine", "Potensic", "ZSX", "FlyZone", "Scanner", "FrSky RX", "FlySky AFHDS2A RX", "HoTT", "Fx816",
+ "Bayang RX", "Pelikan", "Tiger", "XK", "XN297 Dump", "FrSky X 2.1", "FrSky R9", "Propel", "FrSky L", "Skyartec",
+ "ESky 150v2", "DSM RX", "JJRC345", "Q90C"
});
- if (protocol == MM_RF_CUSTOM_SELECTED || custom)
- return tr("Custom - proto %1)").arg(protocol);
- else
- return strings.value(protocol, CPN_STR_UNKNOWN_ITEM);
+ return strings.value(protocol, CPN_STR_UNKNOWN_ITEM);
}
// static
diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp
index 10df6d7a3..b7e4d8644 100644
--- a/companion/src/firmwares/opentx/opentxeeprom.cpp
+++ b/companion/src/firmwares/opentx/opentxeeprom.cpp
@@ -36,7 +36,7 @@ inline int MAX_SWITCHES(Board::Type board, int version)
if (version <= 218) {
if (IS_TARANIS_X7(board))
return 6;
- if (IS_TARANIS_X9D(board) || IS_HORUS(board))
+ if (IS_TARANIS_X9D(board) || IS_FAMILY_HORUS_OR_T16(board))
return 8;
if (IS_TARANIS_XLITE(board))
return 4;
@@ -63,7 +63,7 @@ inline int MAX_SWITCHES_POSITION(Board::Type board, int version)
inline int POTS_CONFIG_SIZE(Board::Type board, int version)
{
- if (version >= 219 && IS_HORUS(board))
+ if (version >= 219 && IS_FAMILY_HORUS_OR_T16(board))
return 16;
return 8;
@@ -71,44 +71,44 @@ inline int POTS_CONFIG_SIZE(Board::Type board, int version)
inline int MAX_POTS(Board::Type board, int version)
{
- if (version <= 218 && IS_HORUS(board))
+ if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
return 3;
return Boards::getCapability(board, Board::Pots);
}
inline int MAX_POTS_STORAGE(Board::Type board, int version)
{
- if (version <= 218 && IS_HORUS(board))
+ if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
return 3;
- if (version >= 219 && IS_HORUS(board))
+ if (version >= 219 && IS_FAMILY_HORUS_OR_T16(board))
return 5;
return Boards::getCapability(board, Board::Pots);
}
inline int MAX_POTS_SOURCES(Board::Type board, int version)
{
- if (version <= 218 && IS_HORUS(board))
+ if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
return 5;
return Boards::getCapability(board, Board::Pots);
}
inline int MAX_SLIDERS_STORAGE(Board::Type board, int version)
{
- if (version >= 219 && IS_HORUS(board))
+ if (version >= 219 && IS_FAMILY_HORUS_OR_T16(board))
return 4;
return Boards::getCapability(board, Board::Sliders);
}
inline int MAX_SLIDERS_SOURCES(Board::Type board, int version)
{
- if (version <= 218 && IS_HORUS(board))
+ if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
return 2;
return Boards::getCapability(board, Board::Sliders);
}
inline int SLIDERS_CONFIG_SIZE(Board::Type board, int version)
{
- if (version >= 219 && IS_HORUS(board))
+ if (version >= 219 && IS_FAMILY_HORUS_OR_T16(board))
return 8;
return 4;
@@ -119,7 +119,7 @@ inline int SWITCHES_CONFIG_SIZE(Board::Type board, int version)
if (IS_TARANIS_X9E(board))
return 64;
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 32;
if (version >= 219 && IS_TARANIS_X9D(board))
@@ -128,7 +128,7 @@ inline int SWITCHES_CONFIG_SIZE(Board::Type board, int version)
return 16;
}
-#define MAX_ROTARY_ENCODERS(board) (IS_SKY9X(board) ? 1 : 0)
+#define MAX_ROTARY_ENCODERS(board) 0
#define MAX_FLIGHT_MODES(board, version) 9
#define MAX_TIMERS(board, version) 3
#define MAX_MIXERS(board, version) 64
@@ -139,11 +139,11 @@ inline int SWITCHES_CONFIG_SIZE(Board::Type board, int version)
#define MAX_CUSTOM_FUNCTIONS(board, version) 64
#define MAX_CURVES(board, version) ((version >= 219 || HAS_LARGE_LCD(board)) ? 32 : 16)
#define MAX_GVARS(board, version) 9
-#define MAX_SCRIPTS(board) (IS_HORUS(board) ? 9 : 7)
-#define MAX_TELEMETRY_SENSORS(board, version) (version <= 218 ? 32 : ((IS_HORUS(board) || IS_TARANIS_X9(board)) ? 60 : 40))
+#define MAX_SCRIPTS(board) (IS_FAMILY_HORUS_OR_T16(board) ? 9 : 7)
+#define MAX_TELEMETRY_SENSORS(board, version) (version <= 218 ? 32 : ((IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board)) ? 60 : 40))
#define NUM_PPM_INPUTS(board, version) 16
#define ROTENC_COUNT(board, version) ((IS_STM32(board) && version >= 218) ? 0 : 1)
-#define MAX_AUX_TRIMS(board) (IS_HORUS(board) ? 2 : 0)
+#define MAX_AUX_TRIMS(board) (IS_FAMILY_HORUS_OR_T16(board) ? 2 : 0)
inline int switchIndex(int i, Board::Type board, unsigned int version)
{
@@ -693,11 +693,13 @@ class FlightModeField: public TransformedField {
internalField.Append(new UnsignedField<8>(this, phase.fadeIn));
internalField.Append(new UnsignedField<8>(this, phase.fadeOut));
- for (int i=0; i(this, phase.rotaryEncoders[i]));
+ if (version < 219) {
+ for (int i = 0; i < rotencCount; i++) {
+ internalField.Append(new SignedField<16>(this, phase.rotaryEncoders[i]));
+ }
}
- for (int i=0; i(this, phase.gvars[i]));
}
}
@@ -719,13 +721,7 @@ class FlightModeField: public TransformedField {
trim = 501 + phase.trimRef[i] - (phase.trimRef[i] > index ? 1 : 0);
else
trim = std::max(-500, std::min(500, phase.trim[i]));
- if (board == BOARD_9X_M64 || (board == BOARD_9X_M128 && version >= 215)) {
- trimBase[i] = trim >> 2;
- trimExt[i] = (trim & 0x03);
- }
- else {
- trimBase[i] = trim;
- }
+ trimBase[i] = trim;
}
}
}
@@ -749,11 +745,7 @@ class FlightModeField: public TransformedField {
phase.trim[i] = 0;
}
else {
- int trim;
- if (board == BOARD_9X_M64 || (board == BOARD_9X_M128 && version >= 215))
- trim = ((trimBase[i]) << 2) + (trimExt[i] & 0x03);
- else
- trim = trimBase[i];
+ int trim = trimBase[i];
if (trim > 500) {
phase.trimRef[i] = trim - 501;
if (phase.trimRef[i] >= index)
@@ -810,7 +802,7 @@ class MixField: public TransformedField {
internalField.Append(new UnsignedField<8>(this, mix.delayDown));
internalField.Append(new UnsignedField<8>(this, mix.speedUp));
internalField.Append(new UnsignedField<8>(this, mix.speedDown));
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
internalField.Append(new ZCharField<6>(this, mix.name));
else if (HAS_LARGE_LCD(board) && version <= 218)
internalField.Append(new ZCharField<8>(this, mix.name));
@@ -946,7 +938,7 @@ class InputField: public TransformedField {
internalField.Append(new UnsignedField<9>(this, expo.flightModes));
internalField.Append(new SignedField<8>(this, _weight, "Weight"));
internalField.Append(new SpareBitsField<1>(this));
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
internalField.Append(new ZCharField<6>(this, expo.name));
else if (HAS_LARGE_LCD(board) && version <= 218)
internalField.Append(new ZCharField<8>(this, expo.name));
@@ -1392,6 +1384,7 @@ class CustomFunctionsConversionTable: public ConversionTable {
addConversion(FuncTrainerELE, val);
addConversion(FuncTrainerTHR, val);
addConversion(FuncTrainerAIL, val);
+ addConversion(FuncTrainerChannels, val);
val++;
addConversion(FuncInstantTrim, val++);
@@ -1512,7 +1505,7 @@ class ArmCustomFunctionField: public TransformedField {
*((uint16_t *)_param) = fn.param;
*((uint8_t *)(_param+3)) = fn.func - FuncOverrideCH1;
}
- else if (fn.func >= FuncTrainer && fn.func <= FuncTrainerAIL) {
+ else if (fn.func >= FuncTrainer && fn.func <= FuncTrainerChannels) {
*((uint8_t *)(_param+3)) = fn.func - FuncTrainer;
}
else if (fn.func >= FuncSetTimer1 && fn.func <= FuncSetTimer3) {
@@ -1579,7 +1572,7 @@ class ArmCustomFunctionField: public TransformedField {
fn.func = AssignFunc(fn.func + index);
fn.param = (int)value;
}
- else if (fn.func >= FuncTrainer && fn.func <= FuncTrainerAIL) {
+ else if (fn.func >= FuncTrainer && fn.func <= FuncTrainerChannels) {
fn.func = AssignFunc(fn.func + index);
fn.param = value;
}
@@ -1808,7 +1801,7 @@ class Frsky218Field: public StructField {
rssiConversionTable[0] = RSSIConversionTable(0);
rssiConversionTable[1] = RSSIConversionTable(1);
- if (!IS_HORUS(board)) {
+ if (!IS_FAMILY_HORUS_OR_T16(board)) {
Append(new UnsignedField<8>(this, frsky.voltsSource, "Volts Source"));
Append(new UnsignedField<8>(this, frsky.altitudeSource, "Altitude Source"));
@@ -1877,7 +1870,7 @@ class CustomScreenField: public StructField {
class SensorField: public TransformedField {
public:
- SensorField(DataField * parent, const ModelData& model, SensorData & sensor, Board::Type board, unsigned int version):
+ SensorField(DataField * parent, const ModelData & model, SensorData & sensor, Board::Type board, unsigned int version):
TransformedField(parent, internalField),
internalField(this, "Sensor"),
sensor(sensor),
@@ -1913,7 +1906,7 @@ class SensorField: public TransformedField {
internalField.Append(new UnsignedField<32>(this, _param, "param"));
}
- virtual void beforeExport()
+ void beforeExport() override
{
if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) {
_id = sensor.id;
@@ -1945,16 +1938,9 @@ class SensorField: public TransformedField {
else {
sensor.id = _id;
sensor.subid = _subid;
- if (model.moduleData[0].isPxx1Module() || model.moduleData[1].isPxx1Module()) {
- sensor.instance = (_instance & 0x1F) + (version <= 218 ? 0 : 1); // 5 bits instance
- sensor.rxIdx = 0x03; // 2 bits Rx idx
- sensor.moduleIdx = 0x01; // 1 bit module idx
- }
- else {
- sensor.instance = (_instance & 0x1F) + 1;
- sensor.rxIdx = (_instance >> 5) & 0x03; // 2 bits Rx idx
- sensor.moduleIdx = (_instance >> 7) & 0x1; // 1 bit module idx
- }
+ sensor.instance = (_instance & 0x1F) + (version <= 218 ? 0 : 1); // 5 bits instance
+ sensor.rxIdx = (_instance >> 5) & 0x03; // 2 bits Rx idx
+ sensor.moduleIdx = (_instance >> 7) & 0x1; // 1 bit module idx
sensor.ratio = _ratio;
sensor.offset = _offset;
}
@@ -1980,6 +1966,12 @@ class SensorField: public TransformedField {
sensor.unit++;
}
+ if (version < 219) {
+ if (sensor.unit > SensorData::UNIT_FLOZ) {
+ sensor.unit += 11;
+ }
+ }
+
qCDebug(eepromImport) << QString("imported %1").arg(internalField.getName());
}
@@ -2036,7 +2028,7 @@ class ModuleUnionField: public UnionField {
module(module),
rfProtExtra(0)
{
- ModuleData::Multi& multi = module.multi;
+ ModuleData::Multi & multi = module.multi;
internalField.Append(new UnsignedField<3>(this, rfProtExtra));
internalField.Append(new BoolField<1>(this, multi.disableTelemetry));
internalField.Append(new BoolField<1>(this, multi.disableMapping));
@@ -2053,22 +2045,17 @@ class ModuleUnionField: public UnionField {
void beforeExport() override
{
- if (module.multi.rfProtocol > MODULE_SUBTYPE_MULTI_LAST)
- module.multi.rfProtocol += 3;
rfProtExtra = (module.multi.rfProtocol & 0x70) >> 4;
- module.multi.rfProtocol &= 0x0f;
}
void afterImport() override
{
module.multi.rfProtocol = (rfProtExtra << 4) + (module.rfProtocol & 0xf);
- if (module.multi.rfProtocol > MODULE_SUBTYPE_MULTI_LAST)
- module.multi.rfProtocol -= 3;
}
private:
StructField internalField;
- ModuleData& module;
+ ModuleData & module;
unsigned int rfProtExtra;
};
@@ -2116,6 +2103,40 @@ class ModuleUnionField: public UnionField {
unsigned int version;
};
+ class Afhds3Field: public UnionField::TransformedMember {
+ public:
+ Afhds3Field(DataField * parent, ModuleData& module):
+ UnionField::TransformedMember(parent, internalField),
+ internalField(this, "AFHDS3")
+ {
+ ModuleData::Afhds3& afhds3 = module.afhds3;
+ internalField.Append(new UnsignedField<3>(this, minBindPower));
+ internalField.Append(new UnsignedField<3>(this, afhds3.rfPower));
+ internalField.Append(new UnsignedField<1>(this, emissionFCC));
+ internalField.Append(new BoolField<1>(this, operationModeUnicast));
+ internalField.Append(new BoolField<1>(this, operationModeUnicast));
+ internalField.Append(new UnsignedField<16>(this, defaultFailSafeTimout));
+ internalField.Append(new UnsignedField<16>(this, afhds3.rxFreq));
+ }
+
+ bool select(const unsigned int& attr) const override {
+ return attr == PULSES_AFHDS3;
+ }
+
+ void beforeExport() override {}
+
+ void afterImport() override {}
+
+ private:
+ StructField internalField;
+
+ unsigned int minBindPower = 0;
+ unsigned int emissionFCC = 0;
+ unsigned int defaultFailSafeTimout = 1000;
+ bool operationModeUnicast = true;
+ };
+
+
class AccessField: public UnionField::TransformedMember {
public:
AccessField(DataField * parent, ModuleData& module):
@@ -2132,7 +2153,8 @@ class ModuleUnionField: public UnionField {
memset(receiverName, 0, sizeof(receiverName));
}
- bool select(const unsigned int& attr) const override {
+ bool select(const unsigned int& attr) const override
+ {
return attr >= PULSES_ACCESS_ISRM && attr <= PULSES_ACCESS_R9M_LITE_PRO;
}
@@ -2140,7 +2162,6 @@ class ModuleUnionField: public UnionField {
{
for (int i=0; i {
ModuleUnionField(DataField * parent, ModuleData & module, Board::Type board, unsigned int version):
UnionField(parent, module.protocol)
{
- if (version >= 219)
+ if (version >= 219) {
Append(new AccessField(parent, module));
+ Append(new Afhds3Field(parent, module));
+ }
Append(new PxxField(parent, module, version));
Append(new MultiField(parent, module));
Append(new PPMField(parent, module.ppm));
@@ -2187,7 +2210,7 @@ class ModuleUnionField: public UnionField {
class ModuleField: public TransformedField {
public:
- ModuleField(DataField * parent, ModuleData & module, Board::Type board, unsigned int version):
+ ModuleField(DataField * parent, ModuleData & module, ModelData & model, Board::Type board, unsigned int version):
TransformedField(parent, internalField),
internalField(this, "Module"),
module(module),
@@ -2201,8 +2224,8 @@ class ModuleField: public TransformedField {
internalField.Append(new UnsignedField<3>(this, module.subType));
internalField.Append(new BoolField<1>(this, module.invertedSerial));
if (version <= 218) {
- for (int i=0; i<32; i++) {
- internalField.Append(new SignedField<16>(this, module.failsafeChannels[i]));
+ for (int i = 0; i < 32; i++) {
+ internalField.Append(new SignedField<16>(this, model.limitData[i].failsafe));
}
}
@@ -2221,7 +2244,7 @@ class ModuleField: public TransformedField {
module.subType = module.protocol - PULSES_PXX_XJT_X16;
}
else if (module.protocol == PULSES_MULTIMODULE) {
- module.rfProtocol = module.multi.rfProtocol & 0xf;
+ module.rfProtocol = module.multi.rfProtocol & 0x0F;
}
}
@@ -2250,7 +2273,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
qDebug() << QString("OpenTxModelData::OpenTxModelData(name: %1, board: %2, ver: %3, var: %4)").arg(name).arg(board).arg(version).arg(variant);
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
internalField.Append(new ZCharField<15>(this, modelData.name, "Model name"));
else if (HAS_LARGE_LCD(board))
internalField.Append(new ZCharField<12>(this, modelData.name, "Model name"));
@@ -2261,7 +2284,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new UnsignedField<8>(this, modelData.moduleData[1].modelId));
if (HAS_LARGE_LCD(board)) {
- if (version >= 219 && IS_HORUS(board))
+ if (version >= 219 && IS_FAMILY_HORUS_OR_T16(board))
internalField.Append(new CharField<14>(this, modelData.bitmap, true, "Model bitmap"));
else
internalField.Append(new CharField<10>(this, modelData.bitmap, true, "Model bitmap"));
@@ -2329,7 +2352,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new UnsignedField<8>(this, modelData.thrTraceSrc, "Throttle Source"));
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
internalField.Append(new SwitchesWarningField<32>(this, modelData.switchWarningStates, board, version));
else if (IS_TARANIS_X9E(board))
internalField.Append(new SwitchesWarningField<64>(this, modelData.switchWarningStates, board, version));
@@ -2344,7 +2367,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new UnsignedField<32>(this, modelData.switchWarningEnable));
else if (version >= 219 && IS_TARANIS_X9D(board))
internalField.Append(new UnsignedField<16>(this, modelData.switchWarningEnable));
- else if (!IS_HORUS(board))
+ else if (!IS_FAMILY_HORUS_OR_T16(board))
internalField.Append(new UnsignedField<8>(this, modelData.switchWarningEnable));
for (int i=0; i= 219) {
for (int i = 0; i < 32; i++) {
- internalField.Append(new SignedField<16>(this, modelData.moduleData[0].failsafeChannels[i]));
+ internalField.Append(new SignedField<16>(this, modelData.limitData[i].failsafe));
}
}
@@ -2481,7 +2504,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new UnsignedField<8>(this, modelData.toplcdTimer));
}
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
for (int i = 0; i < 5; i++) {
internalField.Append(new CharField<610>(this, modelData.customScreenData[i], false, "Custom screen blob"));
}
@@ -2507,7 +2530,7 @@ void OpenTxModelData::beforeExport()
{
// qDebug() << QString("before export model") << modelData.name;
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
uint32_t newSwitchWarningStates = 0;
for (int i = 0; i < MAX_SWITCHES(board, version); i++) {
uint8_t value = (modelData.switchWarningStates >> (2*i)) & 0x03;
@@ -2523,7 +2546,7 @@ void OpenTxModelData::afterImport()
{
qCDebug(eepromImport) << QString("OpenTxModelData::afterImport()") << modelData.name;
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
uint32_t newSwitchWarningStates = 0;
for (int i = 0; i < MAX_SWITCHES(board, version); i++) {
uint8_t value = (modelData.switchWarningStates >> (3*i)) & 0x07;
@@ -2571,7 +2594,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
internalField.Append(new UnsignedField<16>(this, chkSum));
- if (!IS_HORUS(board)) {
+ if (!IS_FAMILY_HORUS_OR_T16(board)) {
internalField.Append(new UnsignedField<8>(this, generalData.currModelIndex));
internalField.Append(new UnsignedField<8>(this, generalData.contrast));
}
@@ -2584,7 +2607,13 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
else
internalField.Append(new SpareBitsField<2>(this));
internalField.Append(new BoolField<1>(this, generalData.rtcCheckDisable));
- internalField.Append(new SpareBitsField<2>(this));
+ if (IS_JUMPER_T18(board)) {
+ internalField.Append(new BoolField<1>(this, generalData.keysBacklight));
+ internalField.Append(new SpareBitsField<1>(this));
+ }
+ else {
+ internalField.Append(new SpareBitsField<2>(this));
+ }
for (int i=0; i<4; i++) {
internalField.Append(new SignedField<16>(this, generalData.trainer.calib[i]));
@@ -2616,7 +2645,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
internalField.Append(new UnsignedField<8>(this, generalData.inactivityTimer));
internalField.Append(new UnsignedField<3>(this, generalData.telemetryBaudrate));
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
internalField.Append(new SpareBitsField<3>(this));
else if (IS_TARANIS(board))
internalField.Append(new SignedField<3>(this, generalData.splashDuration));
@@ -2631,11 +2660,11 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
internalField.Append(new SignedField<8>(this, generalData.PPM_Multiplier));
internalField.Append(new SignedField<8>(this, generalData.hapticLength));
- if (version < 218 || (!IS_TARANIS(board) && !IS_HORUS(board))) {
+ if (version < 218 || (!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board))) {
internalField.Append(new UnsignedField<8>(this, generalData.reNavigation));
}
- if (!IS_TARANIS(board) && !IS_HORUS(board)) {
+ if (!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board)) {
internalField.Append(new UnsignedField<8>(this, generalData.stickReverse));
}
@@ -2714,7 +2743,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
if (IS_STM32(board)) {
if (version >= 218) {
internalField.Append(new UnsignedField<4>(this, generalData.auxSerialMode));
- if (IS_HORUS(board) && version >= 219) {
+ if (IS_FAMILY_HORUS_OR_T16(board) && version >= 219) {
internalField.Append(new SpareBitsField<4>(this));
}
else {
@@ -2734,7 +2763,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
}
}
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
for (int i=0; i(this, generalData.switchConfig[i]));
@@ -2746,7 +2775,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
for (int i=0; i= 3))
+ if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board) && (i >= 3))
offset += 2;
if (i < MAX_POTS_STORAGE(board, version))
@@ -2755,7 +2784,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
internalField.Append(new SpareBitsField<2>(this));
}
- if (IS_HORUS(board) && version >= 219) {
+ if (IS_FAMILY_HORUS_OR_T16(board) && version >= 219) {
for (int i=0; i(this, generalData.sliderConfig[i]));
@@ -2764,7 +2793,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
}
}
- if (!IS_HORUS(board)) {
+ if (!IS_FAMILY_HORUS_OR_T16(board)) {
internalField.Append(new UnsignedField<8>(this, generalData.backlightColor));
}
}
@@ -2792,7 +2821,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
}
}
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
for (int i=0; i(this, generalData.switchName[i], "Switch name"));
}
@@ -2831,7 +2860,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
}
}
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
internalField.Append(new SpareBitsField<1>(this));
internalField.Append(new UnsignedField<7>(this, generalData.backlightOffBright));
internalField.Append(new ZCharField<10>(this, generalData.bluetoothName, "Bluetooth name"));
@@ -2841,7 +2870,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
internalField.Append(new ZCharField<10>(this, generalData.bluetoothName, "Bluetooth name"));
}
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
internalField.Append(new CharField<8>(this, generalData.themeName, true, "Theme name"));
for (int i=0; i<5; i++) {
internalField.Append(new CharField<8>(this, (char *)generalData.themeOptionValue[i], true, "Theme blob"));
diff --git a/companion/src/firmwares/opentx/opentxeeprom.h b/companion/src/firmwares/opentx/opentxeeprom.h
index 95f75ce19..29d5b0b93 100644
--- a/companion/src/firmwares/opentx/opentxeeprom.h
+++ b/companion/src/firmwares/opentx/opentxeeprom.h
@@ -28,18 +28,15 @@
#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 TARANIS_XLITES_VARIANT 0x1000
#define TARANIS_X9LITE_VARIANT 0x0800
+#define TARANIS_X9LITES_VARIANT 0x0801
#define JUMPER_T12_VARIANT 0x4001
-#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);
@@ -107,6 +104,9 @@ class ProtocolsConversionTable: public ConversionTable
addConversion(PULSES_XJT_LITE_X16, val);
addConversion(PULSES_XJT_LITE_D8, val);
addConversion(PULSES_XJT_LITE_LR12, val++);
+ if (version >= 219) {
+ addConversion(PULSES_AFHDS3, val++);
+ }
}
};
diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp
index 9509c3c28..75aab7b64 100644
--- a/companion/src/firmwares/opentx/opentxinterface.cpp
+++ b/companion/src/firmwares/opentx/opentxinterface.cpp
@@ -58,18 +58,14 @@ OpenTxEepromInterface::~OpenTxEepromInterface()
const char * OpenTxEepromInterface::getName()
{
switch (board) {
- case BOARD_9X_M64:
- return "OpenTX for 9X board";
- case BOARD_9X_M128:
- return "OpenTX for M128 / 9X board";
- case BOARD_MEGA2560:
- return "OpenTX for MEGA2560 board";
- case BOARD_GRUVIN9X:
- return "OpenTX for Gruvin9x board / 9X";
case BOARD_JUMPER_T12:
return "OpenTX for Jumper T12";
case BOARD_JUMPER_T16:
return "OpenTX for Jumper T16";
+ case BOARD_JUMPER_T18:
+ return "OpenTX for Jumper T18";
+ case BOARD_RADIOMASTER_TX16S:
+ return "OpenTX for Radiomaster TX16S";
case BOARD_TARANIS_X9D:
return "OpenTX for FrSky Taranis X9D";
case BOARD_TARANIS_X9DP:
@@ -80,6 +76,8 @@ const char * OpenTxEepromInterface::getName()
return "OpenTX for FrSky Taranis X9E";
case BOARD_TARANIS_X7:
return "OpenTX for FrSky Taranis X7";
+ case BOARD_TARANIS_X7_ACCESS:
+ return "OpenTX for FrSky Taranis X7 Access";
case BOARD_TARANIS_X9LITES:
return "OpenTX for FrSky Taranis X9-Lite S";
case BOARD_TARANIS_X9LITE:
@@ -173,7 +171,7 @@ bool OpenTxEepromInterface::loadFromByteArray(T & dest, const QByteArray & data)
{
uint32_t fourcc = *((uint32_t*)&data.data()[0]);
if (Boards::getFourCC(board) != fourcc) {
- if (IS_HORUS(board) && fourcc == 0x3178396F) {
+ if (IS_FAMILY_HORUS_OR_T16(board) && fourcc == 0x3178396F) {
qDebug() << QString().sprintf("%s: Deprecated fourcc used %x vs %x", getName(), fourcc, Boards::getFourCC(board));
}
else {
@@ -276,16 +274,7 @@ unsigned long OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *
uint8_t OpenTxEepromInterface::getLastDataVersion(Board::Type board)
{
- switch (board) {
- case BOARD_9X_M64:
- return 216;
- case BOARD_GRUVIN9X:
- case BOARD_MEGA2560:
- case BOARD_9X_M128:
- return 217;
- default:
- return 219;
- }
+ return 219;
}
void OpenTxEepromInterface::showErrors(const QString & title, const QStringList & errors)
@@ -321,15 +310,18 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u
efile->EeFsCreate(eeprom, size, board, version);
- if (board == BOARD_9X_M128) {
- variant |= M128_VARIANT;
- }
- else if (IS_TARANIS_X9E(board)) {
+ if (IS_TARANIS_X9E(board)) {
variant |= TARANIS_X9E_VARIANT;
}
+ else if (IS_TARANIS_X9LITES(board)) {
+ variant |= TARANIS_X9LITES_VARIANT;
+ }
else if (IS_TARANIS_X9LITE(board)) {
variant |= TARANIS_X9LITE_VARIANT;
}
+ else if (IS_TARANIS_X7_ACCESS(board)) {
+ variant |= TARANIS_X7_VARIANT;
+ }
else if (IS_TARANIS_X7(board)) {
variant |= TARANIS_X7_VARIANT;
}
@@ -433,45 +425,28 @@ int OpenTxFirmware::getCapability(::Capability capability)
{
switch (capability) {
case Models:
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 0;
- else if (IS_ARM(board))
+ else
return 60;
- else if (board == BOARD_9X_M128)
- return 30;
- else if (IS_2560(board))
- return 30;
- else
- return 16;
case Imperial:
- if (IS_ARM(board))
- return 0;
- else
- return id.contains("imperial") ? 1 : 0;
+ return 0;
case ModelImage:
- return (board == BOARD_TARANIS_X9D || IS_TARANIS_PLUS(board) || board == BOARD_TARANIS_X9DP_2019 || IS_HORUS(board));
+ return (board == BOARD_TARANIS_X9D || IS_TARANIS_PLUS(board) || board == BOARD_TARANIS_X9DP_2019 || IS_FAMILY_HORUS_OR_T16(board));
case HasBeeper:
- return (!IS_ARM(board));
+ return false;
case HasPxxCountry:
return 1;
case HasGeneralUnits:
- if (IS_ARM(board))
- return 1;
- else
- return 0;
+ return true;
case HasNegAndSwitches:
- return IS_ARM(board);
+ return true;
case PPMExtCtrl:
return 1;
case PPMFrameLength:
return 40;
case FlightModes:
- if (IS_ARM(board))
- return 9;
- else if (IS_2560(board))
- return 6;
- else
- return 5;
+ return 9;
case FlightModesHaveFades:
return 1;
case Heli:
@@ -483,85 +458,67 @@ int OpenTxFirmware::getCapability(::Capability capability)
if (IS_HORUS_OR_TARANIS(board))
return id.contains("nogvars") ? 0 : 9;
else if (id.contains("gvars"))
- return IS_ARM(board) ? 9 : 5;
+ return 9;
else
return 0;
case ModelName:
- return (IS_HORUS(board) ? 15 : (HAS_LARGE_LCD(board) ? 12 : 10));
+ return (IS_FAMILY_HORUS_OR_T16(board) ? 15 : (HAS_LARGE_LCD(board) ? 12 : 10));
case FlightModesName:
return (IS_HORUS_OR_TARANIS(board) ? 10 : 6);
case GvarsName:
- return (IS_9X(board) ? 0 : 3);
+ return 3;
case GvarsInCS:
case HasFAIMode:
return 1;
case GvarsAreNamed:
case GvarsFlightModes:
- return ((IS_ARM(board) || IS_2560(board)) ? 1 : 0);
+ return 1;
case Mixes:
- return (IS_ARM(board) ? 64 : 32);
+ return 64;
case OffsetWeight:
- return (IS_ARM(board) ? 500 : 245);
+ return 500;
case Timers:
- return (IS_ARM(board) ? 3 : 2);
+ return 3;
case TimersName:
if (HAS_LARGE_LCD(board))
return 8;
- else if (IS_ARM(board))
+ else
return 3;
- else
- return 0;
case PermTimers:
- return (IS_2560(board) || IS_ARM(board));
+ return true;
case CustomFunctions:
- if (IS_ARM(board))
- return 64;
- else if (IS_2560(board) || board == BOARD_9X_M128)
- return 24;
- else
- return 16;
+ return 64;
case SafetyChannelCustomFunction:
return id.contains("nooverridech") ? 0 : 1;
case LogicalSwitches:
- if (IS_ARM(board))
- return 64;
- else
- return 12;
+ return 64;
case CustomAndSwitches:
- if (IS_ARM(board))
- return getCapability(LogicalSwitches);
- else
- return 15/*4bits*/- 9/*sw positions*/;
+ return getCapability(LogicalSwitches);
case LogicalSwitchesExt:
- return (IS_ARM(board) ? true : false);
+ return true;
case RotaryEncoders:
- if (board == BOARD_GRUVIN9X)
- return 2;
- else if (IS_SKY9X(board))
- return 1;
- else
return 0;
case Outputs:
- return (IS_ARM(board) ? 32 : 16);
+ return 32;
case NumCurvePoints:
- return (IS_ARM(board) ? 512 : 104);
+ return 512;
case VoicesAsNumbers:
- return (IS_ARM(board) ? 0 : 1);
+ return 0;
case VoicesMaxLength:
- return (IS_ARM(board) ? (IS_TARANIS_X9(board) ? 8 : 6) : 0);
+ return (IS_TARANIS_X9(board) ? 8 : 6);
case MultiLangVoice:
- return (IS_ARM(board) ? 1 : 0);
+ return 1;
case SoundPitch:
return 1;
case Haptic:
- return (IS_2560(board) || IS_SKY9X(board) || IS_TARANIS_PLUS(board) || IS_TARANIS_SMALL(board) || IS_TARANIS_X9E(board) || IS_HORUS(board) || IS_JUMPER_T12(board) || id.contains("haptic"));
+ return board != Board::BOARD_TARANIS_X9D || id.contains("haptic");
case ModelTrainerEnable:
if (IS_HORUS_OR_TARANIS(board) && board!=Board::BOARD_TARANIS_XLITE)
return 1;
else
return 0;
case MaxVolume:
- return (IS_ARM(board) ? 23 : 7);
+ return 23;
case MaxContrast:
if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board))
return 30;
@@ -573,7 +530,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
else
return 10;
case HasSoundMixer:
- return (IS_ARM(board) ? 1 : 0);
+ return 1;
case ExtraInputs:
return 1;
case TrimsRange:
@@ -583,29 +540,30 @@ int OpenTxFirmware::getCapability(::Capability capability)
case Simulation:
return 1;
case NumCurves:
- return (HAS_LARGE_LCD(board) ? 32 : (IS_ARM(board) ? 16 : 8));
+ return (HAS_LARGE_LCD(board) ? 32 : 16);
case HasMixerNames:
- return (IS_ARM(board) ? (IS_TARANIS_X9(board) ? 8 : 6) : false);
+ return (IS_TARANIS_X9(board) ? 8 : 6);
case HasExpoNames:
- return (IS_ARM(board) ? (IS_TARANIS_X9(board) ? 8 : 6) : false);
+ return (IS_TARANIS_X9(board) ? 8 : 6);
case HasNoExpo:
return (IS_HORUS_OR_TARANIS(board) ? false : true);
case ChannelsName:
- return (IS_ARM(board) ? (HAS_LARGE_LCD(board) ? 6 : 4) : 0);
+ return (HAS_LARGE_LCD(board) ? 6 : 4);
case HasCvNames:
- return (IS_ARM(board) ? 1 : 0);
+ return 1;
case Telemetry:
- if (IS_2560(board) || IS_ARM(board) || id.contains("frsky") || id.contains("telemetrez"))
- return TM_HASTELEMETRY | TM_HASOFFSET | TM_HASWSHH;
- else
- return 0;
+ return 1;
case TelemetryBars:
return 1;
case TelemetryCustomScreens:
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 0;
else
- return IS_ARM(board) ? 4 : 2;
+ return 4;
+ case TelemetryCustomScreensBars:
+ return (getCapability(TelemetryCustomScreens) ? 4 : 0);
+ case TelemetryCustomScreensLines:
+ return (getCapability(TelemetryCustomScreens) ? 4 : 0);
case TelemetryCustomScreensFieldsPerLine:
return HAS_LARGE_LCD(board) ? 3 : 2;
case NoTelemetryProtocol:
@@ -613,7 +571,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case TelemetryUnits:
return 0;
case TelemetryMaxMultiplier:
- return (IS_ARM(board) ? 32 : 8);
+ return 32;
case PPMCenter:
return (IS_HORUS_OR_TARANIS(board) ? 500 : (id.contains("ppmca") ? 125 : 0));
case PPMUnitMicroseconds:
@@ -625,37 +583,37 @@ int OpenTxFirmware::getCapability(::Capability capability)
case HasVario:
return 1;
case HasVarioSink:
- return ((IS_2560(board) || IS_ARM(board)) ? true : false);
+ return true;
case HasFailsafe:
- return (IS_ARM(board) ? 32 : 0);
+ return 32;
case NumModules:
- return (IS_ARM(board) ? 2 : 1);
+ return 2;
case NumFirstUsableModule:
- return (IS_JUMPER_T12(board) ? 1 : 0);
+ return (IS_JUMPER_T12(board) && !id.contains("internalmulti") ? 1 : 0);
case HasModuleR9MFlex:
return id.contains("flexr9m");
case HasModuleR9MMini:
return IS_TARANIS_XLITE(board) && !id.contains("stdr9m");
case HasPPMStart:
- return (IS_ARM(board) ? true : false);
+ return true;
case HastxCurrentCalibration:
return (IS_SKY9X(board) ? true : false);
case HasVolume:
- return (IS_ARM(board) ? true : false);
+ return true;
case HasBrightness:
- return (IS_ARM(board) ? true : false);
+ return true;
case PerModelTimers:
return 1;
case SlowScale:
- return (IS_ARM(board) ? 10 : 2);
+ return 10;
case SlowRange:
- return (IS_ARM(board) ? 250 : 15);
+ return 250;
case CSFunc:
return 18;
case HasSDLogs:
- return ((IS_2560(board) || IS_ARM(board)) ? true : false);
+ return true;
case LcdWidth:
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 480;
else if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board))
return 128;
@@ -664,12 +622,12 @@ int OpenTxFirmware::getCapability(::Capability capability)
else
return 128;
case LcdHeight:
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 272;
else
return 64;
case LcdDepth:
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 16;
else if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board))
return 1;
@@ -680,19 +638,19 @@ int OpenTxFirmware::getCapability(::Capability capability)
case GetThrSwitch:
return (IS_HORUS_OR_TARANIS(board) ? SWITCH_SF1 : SWITCH_THR);
case HasDisplayText:
- return IS_ARM(board) ? 1 : 0;
+ return 1;
case HasTopLcd:
return IS_TARANIS_X9E(board) ? 1 : 0;
case GlobalFunctions:
- return IS_ARM(board) ? 64 : 0;
+ return 64;
case VirtualInputs:
- return IS_ARM(board) ? 32 : 0;
+ return 32;
case InputsLength:
return HAS_LARGE_LCD(board) ? 4 : 3;
case TrainerInputs:
- return IS_ARM(board) ? 16 : 8;
+ return 16;
case RtcTime:
- return IS_ARM(board) || IS_2560(board) ? 1 : 0;
+ return 1;
case LuaScripts:
return IS_HORUS_OR_TARANIS(board) && id.contains("lua") ? 7 : 0;
case LuaInputsPerScript:
@@ -701,18 +659,16 @@ int OpenTxFirmware::getCapability(::Capability capability)
return IS_HORUS_OR_TARANIS(board) ? 6 : 0;
case LimitsPer1000:
case EnhancedCurves:
- return IS_ARM(board);
+ return 1;
case HasFasOffset:
- return (IS_STOCK(board) ? false : true);
+ return true;
case HasMahPersistent:
- return (IS_ARM(board) ? true : false);
+ return true;
case SimulatorVariant:
- if (board == BOARD_9X_M64)
- return SIMU_STOCK_VARIANTS;
- else if (board == BOARD_9X_M128)
- return SIMU_M128_VARIANTS;
- else if (IS_TARANIS_X9E(board))
+ if (IS_TARANIS_X9E(board))
return TARANIS_X9E_VARIANT;
+ else if (IS_TARANIS_X9LITES(board))
+ return TARANIS_X9LITES_VARIANT;
else if (IS_TARANIS_X9LITE(board))
return TARANIS_X9LITE_VARIANT;
else if (IS_TARANIS_X7(board))
@@ -728,7 +684,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case MavlinkTelemetry:
return id.contains("mavlink") ? 1 : 0;
case SportTelemetry:
- return IS_ARM(board) ? 1 : 0;
+ return 1;
case HasInputDiff:
case HasMixerExpo:
return (IS_HORUS_OR_TARANIS(board) ? true : false);
@@ -737,11 +693,16 @@ int OpenTxFirmware::getCapability(::Capability capability)
case DangerousFunctions:
return id.contains("danger") ? 1 : 0;
case HasModelCategories:
- return IS_HORUS(board);
+ return IS_FAMILY_HORUS_OR_T16(board);
case HasSwitchableJack:
return IS_TARANIS_XLITES(board);
case PwrButtonPress:
return IS_HORUS_OR_TARANIS(board) && (board!=Board::BOARD_TARANIS_X9D) && (board!=Board::BOARD_TARANIS_X9DP);
+ case Sensors:
+ if (IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board))
+ return 60;
+ else
+ return 40;
default:
return 0;
}
@@ -756,10 +717,8 @@ QTime OpenTxFirmware::getMaxTimerStart()
{
if (IS_HORUS_OR_TARANIS(board))
return QTime(23, 59, 59);
- else if (IS_ARM(board))
- return QTime(8, 59, 59);
else
- return QTime(0, 59, 59);
+ return QTime(8, 59, 59);
}
bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
@@ -772,16 +731,14 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
return true;
case PULSES_PXX_XJT_X16:
case PULSES_PXX_XJT_LR12:
- return !IS_ACCESS_RADIO(board, id) && board != BOARD_JUMPER_T16;
+ return !IS_ACCESS_RADIO(board, id) && !IS_FAMILY_T16(board) && !IS_JUMPER_T12(board);
case PULSES_PXX_XJT_D8:
- return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")) && board != BOARD_JUMPER_T16;
- case PULSES_PPM:
- return id.contains("internalppm");
+ return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")) && !IS_FAMILY_T16(board) && !IS_JUMPER_T12(board);
case PULSES_ACCESS_ISRM:
case PULSES_ACCST_ISRM_D16:
return IS_ACCESS_RADIO(board, id);
case PULSES_MULTIMODULE:
- return id.contains("internalmulti");
+ return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board) || IS_JUMPER_T18(board);
default:
return false;
}
@@ -802,16 +759,17 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
case PULSES_SBUS:
case PULSES_MULTIMODULE:
case PULSES_CROSSFIRE:
+ case PULSES_AFHDS3:
return true;
case PULSES_ACCESS_R9M:
- return IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || board == BOARD_TARANIS_X9DP_2019 || board == BOARD_X10_EXPRESS || (IS_HORUS(board) && id.contains("internalaccess"));
+ return IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || board == BOARD_TARANIS_X9DP_2019 || board == BOARD_X10_EXPRESS || (IS_FAMILY_HORUS_OR_T16(board) && id.contains("internalaccess"));
case PULSES_PXX_R9M_LITE:
case PULSES_ACCESS_R9M_LITE:
case PULSES_ACCESS_R9M_LITE_PRO:
case PULSES_XJT_LITE_X16:
case PULSES_XJT_LITE_D8:
case PULSES_XJT_LITE_LR12:
- return (IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board));
+ return (IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board));
default:
return false;
}
@@ -925,14 +883,9 @@ EepromLoadErrors OpenTxEepromInterface::checkVersion(unsigned int version)
// M128 revert because too much RAM used!
case 216:
// A lot of things (first github release)
- if (IS_2560(board) || IS_M128(board)) {
- return OLD_VERSION;
- }
case 217:
// 3 logical switches removed on M128 / gruvin9x boards
- if (IS_ARM(board)) {
return OLD_VERSION;
- }
case 218:
// ACCESS
// switches add for X7/X10/X12S
@@ -952,21 +905,7 @@ EepromLoadErrors OpenTxEepromInterface::checkVersion(unsigned int version)
bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int variant)
{
bool variantError = false;
- if (board == BOARD_9X_M128 && !(variant & M128_VARIANT)) {
- if (version == 212) {
- uint8_t tmp[1000];
- for (int i = 1; i < 31; i++) {
- efile->openRd(i);
- int sz = efile->readRlc2(tmp, sizeof(tmp));
- if (sz == 849) {
- qWarning() << " warning: M128 variant not set (but model size seems ok)";
- return true;
- }
- }
- }
- variantError = true;
- }
- else if (IS_TARANIS_X9E(board)) {
+ if (IS_TARANIS_X9E(board)) {
if (variant != TARANIS_X9E_VARIANT) {
variantError = true;
}
@@ -986,6 +925,11 @@ bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int vari
variantError = true;
}
}
+ else if (IS_TARANIS_X9LITES(board)) {
+ if (variant != TARANIS_X9LITES_VARIANT) {
+ variantError = true;
+ }
+ }
else if (IS_TARANIS_X9LITE(board)) {
if (variant != TARANIS_X9LITE_VARIANT) {
variantError = true;
@@ -1053,9 +997,6 @@ unsigned long OpenTxEepromInterface::loadBackup(RadioData &radioData, const uint
case 0x32:
backupBoard = BOARD_SKY9X;
break;
- case 0x31:
- backupBoard = BOARD_GRUVIN9X;
- break;
default:
dbg << " unknown board";
errors.set(UNKNOWN_BOARD);
@@ -1155,14 +1096,28 @@ void addOpenTxCommonOptions(OpenTxFirmware * firmware)
firmware->addOption("nooverridech", Firmware::tr("No OverrideCH functions available"));
}
-void addOpenTxRfOptions(OpenTxFirmware * firmware, bool flex = true)
+enum RfOptions {
+ NONE = 0,
+ EU = 1 << 0,
+ FLEX = 1 << 1,
+ AFHDS3 = 1 << 2
+};
+
+void addOpenTxRfOptions(OpenTxFirmware * firmware, uint8_t options)
{
static const Firmware::Option opt_eu("eu", Firmware::tr("Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015"));
static const Firmware::Option opt_fl("flexr9m", Firmware::tr("Enable non certified firmwares"));
- if (flex)
+ static const Firmware::Option opt_afhds3("afhds3", Firmware::tr("Enable AFHDS3 support"));
+
+
+ if ((options & (EU + FLEX)) == EU + FLEX)
firmware->addOptionsGroup({opt_eu, opt_fl});
- else
+ else if ((options & EU) != 0)
firmware->addOption(opt_eu);
+ else if ((options & FLEX) != 0)
+ firmware->addOption(opt_fl);
+ if ((options & AFHDS3) != 0)
+ firmware->addOption(opt_afhds3);
}
void addOpenTxFontOptions(OpenTxFirmware * firmware)
@@ -1176,7 +1131,6 @@ void addOpenTxFrskyOptions(OpenTxFirmware * firmware)
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
- addOpenTxRfOptions(firmware);
}
void addOpenTxTaranisOptions(OpenTxFirmware * firmware)
@@ -1185,11 +1139,6 @@ void addOpenTxTaranisOptions(OpenTxFirmware * firmware)
addOpenTxFontOptions(firmware);
}
-void addPPMInternalModuleHack(OpenTxFirmware * firmware)
-{
- firmware->addOption("internalppm", Firmware::tr("Support for PPM internal module hack"));
-}
-
void addOpenTxArm9xOptions(OpenTxFirmware * firmware, bool dblkeys = true)
{
addOpenTxCommonOptions(firmware);
@@ -1205,7 +1154,7 @@ void addOpenTxArm9xOptions(OpenTxFirmware * firmware, bool dblkeys = true)
if (dblkeys)
firmware->addOption("dblkeys", Firmware::tr("Enable resetting values by pressing up and down at the same time"));
addOpenTxFontOptions(firmware);
- addOpenTxRfOptions(firmware, true);
+ addOpenTxRfOptions(firmware, FLEX);
}
void registerOpenTxFirmwares()
@@ -1216,65 +1165,80 @@ void registerOpenTxFirmwares()
firmware = new OpenTxFirmware("opentx-x9d+", Firmware::tr("FrSky Taranis X9D+"), BOARD_TARANIS_X9DP);
firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)"));
addOpenTxTaranisOptions(firmware);
- addPPMInternalModuleHack(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3);
/* FrSky Taranis X9D+ 2019 board */
firmware = new OpenTxFirmware("opentx-x9d+2019", Firmware::tr("FrSky Taranis X9D+ 2019"), BOARD_TARANIS_X9DP_2019);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, FLEX);
/* FrSky Taranis X9D board */
firmware = new OpenTxFirmware("opentx-x9d", Firmware::tr("FrSky Taranis X9D"), BOARD_TARANIS_X9D);
+ firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)"));
firmware->addOption("haptic", Firmware::tr("Haptic module installed"));
addOpenTxTaranisOptions(firmware);
- addPPMInternalModuleHack(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3);
/* FrSky Taranis X9E board */
firmware = new OpenTxFirmware("opentx-x9e", Firmware::tr("FrSky Taranis X9E"), BOARD_TARANIS_X9E);
firmware->addOption("shutdownconfirm", Firmware::tr("Confirmation before radio shutdown"));
firmware->addOption("horussticks", Firmware::tr("Horus gimbals installed (Hall sensors)"));
addOpenTxTaranisOptions(firmware);
- addPPMInternalModuleHack(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3);
/* FrSky X9-Lite board */
firmware = new OpenTxFirmware("opentx-x9lite", Firmware::tr("FrSky Taranis X9-Lite"), BOARD_TARANIS_X9LITE);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* FrSky X9-LiteS board */
firmware = new OpenTxFirmware("opentx-x9lites", Firmware::tr("FrSky Taranis X9-Lite S"), BOARD_TARANIS_X9LITES);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* FrSky X7 board */
firmware = new OpenTxFirmware("opentx-x7", Firmware::tr("FrSky Taranis X7 / X7S"), BOARD_TARANIS_X7);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, EU + FLEX);
+
+ /* FrSky X7 Access board */
+ firmware = new OpenTxFirmware("opentx-x7access", Firmware::tr("FrSky Taranis X7 / X7S Access"), BOARD_TARANIS_X7_ACCESS);
+ addOpenTxTaranisOptions(firmware);
+ registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, FLEX);
/* FrSky X-Lite S/PRO board */
firmware = new OpenTxFirmware("opentx-xlites", Firmware::tr("FrSky Taranis X-Lite S/PRO"), BOARD_TARANIS_XLITES);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* FrSky X-Lite board */
firmware = new OpenTxFirmware("opentx-xlite", Firmware::tr("FrSky Taranis X-Lite"), BOARD_TARANIS_XLITE);
// firmware->addOption("stdr9m", Firmware::tr("Use JR-sized R9M module"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, EU + FLEX);
/* FrSky X10 board */
firmware = new OpenTxFirmware("opentx-x10", Firmware::tr("FrSky Horus X10 / X10S"), BOARD_X10);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalaccess", Firmware::tr("Support for ACCESS internal module replacement"));
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, EU + FLEX);
/* FrSky X10 Express board */
firmware = new OpenTxFirmware("opentx-x10express", Firmware::tr("FrSky Horus X10 Express / X10S Express"), BOARD_X10_EXPRESS);
addOpenTxFrskyOptions(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, FLEX);
/* FrSky X12 (Horus) board */
firmware = new OpenTxFirmware("opentx-x12s", Firmware::tr("FrSky Horus X12S"), BOARD_HORUS_X12S);
@@ -1282,6 +1246,7 @@ void registerOpenTxFirmwares()
firmware->addOption("internalaccess", Firmware::tr("Support for ACCESS internal module replacement"));
firmware->addOption("pcbdev", Firmware::tr("Use ONLY with first DEV pcb version"));
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, EU + FLEX);
/* Jumper T12 board */
firmware = new OpenTxFirmware("opentx-t12", QCoreApplication::translate("Firmware", "Jumper T12 / T12 Pro"), BOARD_JUMPER_T12);
@@ -1289,18 +1254,35 @@ void registerOpenTxFirmwares()
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
- firmware->addOption("flexr9m", Firmware::tr("Enable non certified R9M firmwares"));
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* Jumper T16 board */
firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module"));
+ addOpenTxRfOptions(firmware, FLEX);
registerOpenTxFirmware(firmware);
+ /* Radiomaster TX16S board */
+ firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16s / TX16s Hall / TX16s Masterfire"), BOARD_RADIOMASTER_TX16S);
+ addOpenTxFrskyOptions(firmware);
+ addOpenTxRfOptions(firmware, FLEX);
+ static const Firmware::Option opt_bt("bluetooth", Firmware::tr("Support for bluetooth module"));
+ static const Firmware::Option opt_internal_gps("internalgps", Firmware::tr("Support internal GPS"));
+ firmware->addOptionsGroup({opt_bt, opt_internal_gps});
+ registerOpenTxFirmware(firmware);
+
+ /* Jumper T18 board */
+ firmware = new OpenTxFirmware("opentx-t18", Firmware::tr("Jumper T18"), BOARD_JUMPER_T18);
+ addOpenTxFrskyOptions(firmware);
+ firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module"));
+ registerOpenTxFirmware(firmware);
+ addOpenTxRfOptions(firmware, FLEX);
+
/* 9XR-Pro */
firmware = new OpenTxFirmware("opentx-9xrpro", Firmware::tr("Turnigy 9XR-PRO"), BOARD_9XRPRO);
addOpenTxArm9xOptions(firmware, false);
@@ -1318,14 +1300,6 @@ void registerOpenTxFirmwares()
addOpenTxArm9xOptions(firmware);
registerOpenTxFirmware(firmware);
- // These are kept only for import purposes, marked as deprecated to hide from UI.
- registerOpenTxFirmware(new OpenTxFirmware("opentx-9xr", Firmware::tr("Turnigy 9XR"), BOARD_9X_M64), true);
- registerOpenTxFirmware(new OpenTxFirmware("opentx-9xr128", Firmware::tr("Turnigy 9XR with m128 chip"), BOARD_9X_M128), true);
- registerOpenTxFirmware(new OpenTxFirmware("opentx-9x", Firmware::tr("9X with stock board"), BOARD_9X_M64), true);
- registerOpenTxFirmware(new OpenTxFirmware("opentx-9x128", Firmware::tr("9X with stock board and m128 chip"), BOARD_9X_M128), true);
- registerOpenTxFirmware(new OpenTxFirmware("opentx-gruvin9x", Firmware::tr("9X with Gruvin9x board"), BOARD_GRUVIN9X), true);
- registerOpenTxFirmware(new OpenTxFirmware("opentx-mega2560", Firmware::tr("DIY MEGA2560 radio"), BOARD_MEGA2560), true);
-
Firmware::setDefaultVariant(Firmware::getFirmwareForId("opentx-x9d+"));
Firmware::setCurrentVariant(Firmware::getDefaultVariant());
}
diff --git a/companion/src/firmwares/radiodata.cpp b/companion/src/firmwares/radiodata.cpp
index 0710910a0..8054e5b1a 100644
--- a/companion/src/firmwares/radiodata.cpp
+++ b/companion/src/firmwares/radiodata.cpp
@@ -116,7 +116,7 @@ void RadioData::convert(RadioDataConversionState & cstate)
}
}
- if (IS_HORUS(cstate.toType)) {
+ if (IS_FAMILY_HORUS_OR_T16(cstate.toType)) {
fixModelFilenames();
}
diff --git a/companion/src/firmwares/rawsource.cpp b/companion/src/firmwares/rawsource.cpp
index 47171c29f..1cb5bcfbb 100644
--- a/companion/src/firmwares/rawsource.cpp
+++ b/companion/src/firmwares/rawsource.cpp
@@ -32,10 +32,7 @@
float RawSourceRange::getValue(int value)
{
- if (IS_ARM(getCurrentBoard()))
- return float(value) * step;
- else
- return min + float(value) * step;
+ return float(value) * step;
}
@@ -48,11 +45,10 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting
RawSourceRange result;
Firmware * firmware = Firmware::getCurrentVariant();
- Board::Type 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)
@@ -65,192 +61,8 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting
result.max = +30000 * result.step;
result.decimals = sensor.prec;
result.unit = sensor.unitString();
+ break;
}
- 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 = tr("°C");
- break;
- case TELEMETRY_SOURCE_HDG:
- result.step = 2;
- result.max = 360;
- result.offset = 256;
- result.unit = tr("°");
- 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;
@@ -414,7 +226,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
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);
@@ -424,9 +236,6 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
result += (qr.rem == 1 ? "-" : "+");
return result;
}
- else {
- return CHECK_IN_ARRAY(telemetry, index);
- }
case SOURCE_TYPE_GVAR:
if (model)
@@ -486,13 +295,7 @@ bool RawSource::isSlider(int * sliderIndex, Board::Type board) const
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));
+ return (type == SOURCE_TYPE_SPECIAL && index > 0);
}
bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings * const gs, Board::Type board) const
@@ -516,20 +319,9 @@ bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings
return false;
if (type == SOURCE_TYPE_TELEMETRY) {
- if (IS_ARM(board) && !model->sensorData[div(index, 3).quot].isAvailable()) {
+ if (!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;
- }
}
}
@@ -580,13 +372,13 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
}
}
- if (IS_TARANIS(cstate.toType) && IS_HORUS(cstate.fromType)) {
+ if (IS_TARANIS(cstate.toType) && IS_FAMILY_HORUS_OR_T16(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)
+ else if (IS_FAMILY_HORUS_OR_T16(cstate.toType) && IS_TARANIS(cstate.fromType) && index == 5)
{
index = 6; // pot S2 to S2
}
@@ -602,7 +394,7 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
}
}
- if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType))) {
+ if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
// No SE and SG on X7 board
if (index == 4 || index == 6) {
index = 3; // SG and SE to SD
@@ -615,7 +407,7 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
index = 5; // SH to SH
}
}
- else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType))) {
+ else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
// No SE and SG on T12 board
if (index == 4 || index == 6) {
index = 3; // SG and SE to SD
@@ -629,7 +421,7 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
}
}
// 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)) {
+ else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) {
if (index == 4) {
index = 5; // SF to SF
}
@@ -637,7 +429,7 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
index = 7; // SH to SH
}
}
- else if ((IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) {
+ else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) {
if (index == 4) {
index = 5; // SF to SF
}
@@ -645,7 +437,7 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
index = 7; // SH to SH
}
}
- else if ((IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) {
+ else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) {
if (index == 4) {
index = 5; // SF to SF
}
diff --git a/companion/src/firmwares/rawsource.h b/companion/src/firmwares/rawsource.h
index e9273d399..b3220dbd3 100644
--- a/companion/src/firmwares/rawsource.h
+++ b/companion/src/firmwares/rawsource.h
@@ -159,10 +159,6 @@ enum TelemetrySource {
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,
@@ -227,11 +223,7 @@ class RawSource {
AllSourceGroups = InputSourceGroups | GVarsGroup | TelemGroup | ScriptsGroup
};
- RawSource():
- type(SOURCE_TYPE_NONE),
- index(0)
- {
- }
+ RawSource() { clear(); }
explicit RawSource(int value):
type(RawSourceType(abs(value)/65536)),
@@ -258,6 +250,8 @@ class RawSource {
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 isSet() const { return type != SOURCE_TYPE_NONE || index != 0; }
+ void clear() { type = SOURCE_TYPE_NONE; index = 0; }
bool operator == ( const RawSource & other) const {
return (this->type == other.type) && (this->index == other.index);
diff --git a/companion/src/firmwares/rawswitch.cpp b/companion/src/firmwares/rawswitch.cpp
index 1d91f242a..a689ceea7 100644
--- a/companion/src/firmwares/rawswitch.cpp
+++ b/companion/src/firmwares/rawswitch.cpp
@@ -197,7 +197,7 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
}
// No SE and SG on X7 board
- if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType))) {
+ if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
if (srcIdx == 4 || srcIdx == 5) {
delta = 3; // SE to SD & SF to SF
if (srcIdx == 4)
@@ -211,7 +211,7 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
delta = 6; // SH to SH
}
}
- else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType))) {
+ else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
if (srcIdx == 4 || srcIdx == 5) {
delta = 3; // SE to SD & SF to SF
if (srcIdx == 4)
@@ -226,7 +226,7 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
}
}
// 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)) {
+ else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) {
if (srcIdx == 4) {
delta = -3; // SF to SF
}
@@ -234,7 +234,7 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
delta = -6; // SH to SH
}
}
- else if ((IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) {
+ else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) {
if (srcIdx == 4) {
delta = -3; // SF to SF
}
diff --git a/companion/src/firmwares/rawswitch.h b/companion/src/firmwares/rawswitch.h
index af49156c0..d79ac0aa6 100644
--- a/companion/src/firmwares/rawswitch.h
+++ b/companion/src/firmwares/rawswitch.h
@@ -65,11 +65,7 @@ class RawSwitch {
AllSwitchContexts = AllModelContexts | GlobalFunctionsContext
};
- RawSwitch():
- type(SWITCH_TYPE_NONE),
- index(0)
- {
- }
+ RawSwitch() { clear(); }
explicit RawSwitch(int value):
type(RawSwitchType(abs(value)/256)),
@@ -91,6 +87,8 @@ class RawSwitch {
RawSwitch convert(RadioDataConversionState & cstate);
QString toString(Board::Type board = Board::BOARD_UNKNOWN, const GeneralSettings * const generalSettings = NULL, const ModelData * const modelData = NULL) const;
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
+ bool isSet() const { return type != SWITCH_TYPE_NONE || index != 0; }
+ void clear() { type = SWITCH_TYPE_NONE; index = 0; }
bool operator== ( const RawSwitch& other) const {
return (this->type == other.type) && (this->index == other.index);
@@ -100,7 +98,6 @@ class RawSwitch {
return (this->type != other.type) || (this->index != other.index);
}
-
RawSwitchType type;
int index;
};
diff --git a/companion/src/firmwares/sensordata.cpp b/companion/src/firmwares/sensordata.cpp
index 8d677ed50..0a7e7eada 100644
--- a/companion/src/firmwares/sensordata.cpp
+++ b/companion/src/firmwares/sensordata.cpp
@@ -82,6 +82,8 @@ QString SensorData::unitString() const
return tr("seconds");
case UNIT_CELLS:
return tr("V");
+ case UNIT_MILLILITERS_PER_MINUTE:
+ return tr("ml/minute");
default:
return "";
}
diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h
index a5cdb4957..3f995ea3e 100644
--- a/companion/src/firmwares/sensordata.h
+++ b/companion/src/firmwares/sensordata.h
@@ -74,10 +74,13 @@ class SensorData {
UNIT_METERS_PER_SECOND,
UNIT_FEET_PER_SECOND,
UNIT_KMH,
+ UNIT_SPEED = UNIT_KMH,
UNIT_MPH,
UNIT_METERS,
+ UNIT_DIST = UNIT_METERS,
UNIT_FEET,
UNIT_CELSIUS,
+ UNIT_TEMPERATURE = UNIT_CELSIUS,
UNIT_FAHRENHEIT,
UNIT_PERCENT,
UNIT_MAH,
@@ -90,18 +93,31 @@ class SensorData {
UNIT_RADIANS,
UNIT_MILLILITERS,
UNIT_FLOZ,
+ UNIT_MILLILITERS_PER_MINUTE,
+ UNIT_MAX = UNIT_MILLILITERS_PER_MINUTE,
+ UNIT_SPARE1,
+ UNIT_SPARE2,
+ UNIT_SPARE3,
+ UNIT_SPARE4,
+ UNIT_SPARE5,
+ UNIT_SPARE6,
+ UNIT_SPARE7,
+ UNIT_SPARE8,
+ UNIT_SPARE9,
+ UNIT_SPARE10,
UNIT_HOURS,
UNIT_MINUTES,
UNIT_SECONDS,
// FrSky format used for these fields, could be another format in the future
- UNIT_FIRST_VIRTUAL,
+ UNIT_FIRST_VIRTUAL,
UNIT_CELLS = UNIT_FIRST_VIRTUAL,
UNIT_DATETIME,
UNIT_GPS,
+ UNIT_BITFIELD,
+ UNIT_TEXT,
+ // Internal units (not stored in sensor unit)
UNIT_GPS_LONGITUDE,
UNIT_GPS_LATITUDE,
- UNIT_GPS_LONGITUDE_EW,
- UNIT_GPS_LATITUDE_NS,
UNIT_DATETIME_YEAR,
UNIT_DATETIME_DAY_MONTH,
UNIT_DATETIME_HOUR_MIN,
diff --git a/companion/src/firmwares/telem_data.cpp b/companion/src/firmwares/telem_data.cpp
index af31f3b38..99743c7e2 100644
--- a/companion/src/firmwares/telem_data.cpp
+++ b/companion/src/firmwares/telem_data.cpp
@@ -48,9 +48,6 @@ RawSourceRange FrSkyChannelData::getRange() const
void FrSkyScreenData::clear()
{
memset(reinterpret_cast(this), 0, sizeof(FrSkyScreenData));
- if (!IS_ARM(getCurrentBoard())) {
- type = TELEMETRY_SCREEN_NUMBERS;
- }
}
void FrSkyData::clear()
diff --git a/companion/src/flashfirmwaredialog.cpp b/companion/src/flashfirmwaredialog.cpp
index 9a2b688ab..4650cd4c0 100644
--- a/companion/src/flashfirmwaredialog.cpp
+++ b/companion/src/flashfirmwaredialog.cpp
@@ -21,7 +21,6 @@
#include "flashfirmwaredialog.h"
#include "ui_flashfirmwaredialog.h"
#include "appdata.h"
-#include "process_flash.h"
#include "helpers.h"
#include "progressdialog.h"
#include "radiointerface.h"
@@ -112,7 +111,7 @@ void FlashFirmwareDialog::updateUI()
}
QImage image;
- switch(imageSource) {
+ switch (imageSource) {
case FIRMWARE:
ui->useFirmwareSplash->setChecked(true);
image = firmware.getSplash();
@@ -202,7 +201,7 @@ void FlashFirmwareDialog::on_useExternalSplash_clicked()
void FlashFirmwareDialog::on_useLibrarySplash_clicked()
{
QString fileName;
- SplashLibraryDialog *ld = new SplashLibraryDialog(this, &fileName);
+ auto ld = new SplashLibraryDialog(this, &fileName);
ld->exec();
if (!fileName.isEmpty()) {
QImage image(fileName);
diff --git a/companion/src/generaledit/generaledit.cpp b/companion/src/generaledit/generaledit.cpp
index 7b424ec02..34d090e65 100644
--- a/companion/src/generaledit/generaledit.cpp
+++ b/companion/src/generaledit/generaledit.cpp
@@ -56,9 +56,7 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir
}
addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup"));
- if (IS_ARM(firmware->getBoard())) {
- addTab(new CustomFunctionsPanel(this, NULL, generalSettings, firmware), tr("Global Functions"));
- }
+ addTab(new CustomFunctionsPanel(this, NULL, generalSettings, firmware), tr("Global Functions"));
addTab(new TrainerPanel(this, generalSettings, firmware), tr("Trainer"));
addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware"));
addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration"));
diff --git a/companion/src/generaledit/generalsetup.cpp b/companion/src/generaledit/generalsetup.cpp
index 5e1bcd13c..16ef5b271 100644
--- a/companion/src/generaledit/generalsetup.cpp
+++ b/companion/src/generaledit/generalsetup.cpp
@@ -191,12 +191,18 @@ ui(new Ui::GeneralSetup)
ui->label_BLBright->hide();
}
- if (!IS_HORUS(firmware->getBoard())) {
+ if (!IS_FAMILY_HORUS_OR_T16(firmware->getBoard())) {
ui->OFFBright_SB->hide();
ui->OFFBright_SB->setDisabled(true);
ui->label_OFFBright->hide();
}
+ if (!IS_JUMPER_T18(firmware->getBoard())) {
+ ui->keysBl_ChkB->hide();
+ ui->keysBl_ChkB->setDisabled(true);
+ ui->label_KeysBl->hide();
+ }
+
if (!firmware->getCapability(SoundMod)) {
ui->soundModeCB->setDisabled(true);
ui->label_soundMode->hide();
@@ -234,14 +240,9 @@ ui(new Ui::GeneralSetup)
ui->memwarnChkB->setChecked(!generalSettings.disableMemoryWarning); // Default is zero=checked
ui->alarmwarnChkB->setChecked(!generalSettings.disableAlarmWarning); // Default is zero=checked
- if (IS_ARM(firmware->getBoard())) {
- ui->rssiPowerOffWarnChkB->setChecked(!generalSettings.disableRssiPoweroffAlarm); // Default is zero=checked
- }
- else {
- ui->rssiPowerOffWarnChkB->hide();
- }
+ ui->rssiPowerOffWarnChkB->setChecked(!generalSettings.disableRssiPoweroffAlarm); // Default is zero=checked
- if (IS_HORUS(firmware->getBoard())) {
+ if (IS_FAMILY_HORUS_OR_T16(firmware->getBoard())) {
ui->splashScreenChkB->hide();
ui->splashScreenDuration->hide();
ui->splashScreenLabel->hide();
@@ -302,13 +303,7 @@ ui(new Ui::GeneralSetup)
ui->backlightColor2_label->hide();
}
- if (IS_ARM(firmware->getBoard())) {
- ui->switchesDelay->setValue(10*(generalSettings.switchesDelay+15));
- }
- else {
- ui->switchesDelay->hide();
- ui->switchesDelayLabel->hide();
- }
+ ui->switchesDelay->setValue(10*(generalSettings.switchesDelay+15));
ui->blAlarm_ChkB->setChecked(generalSettings.flashBeep);
if (!firmware->getCapability(HasBatMeterRange)) {
@@ -750,11 +745,11 @@ void GeneralSetupPanel::on_blAlarm_ChkB_stateChanged()
emit modified();
}
-void GeneralSetupPanel::on_ownerID_editingFinished()
+void GeneralSetupPanel::on_registrationId_editingFinished()
{
//copy ownerID back to generalSettings.registrationId
QByteArray array = ui->registrationId->text().toLocal8Bit();
- strncpy(generalSettings.registrationId, "pafleraf", 9);
+ strncpy(generalSettings.registrationId, array, 8);
generalSettings.registrationId[8] = '\0';
emit modified();
}
diff --git a/companion/src/generaledit/generalsetup.h b/companion/src/generaledit/generalsetup.h
index 53a1286eb..34aeaaa71 100644
--- a/companion/src/generaledit/generalsetup.h
+++ b/companion/src/generaledit/generalsetup.h
@@ -87,7 +87,7 @@ class GeneralSetupPanel : public GeneralPanel
void on_vBatMinDSB_editingFinished();
void on_vBatMaxDSB_editingFinished();
void on_contrastSB_editingFinished();
- void on_ownerID_editingFinished();
+ void on_registrationId_editingFinished();
void on_pwrOnDelay_valueChanged();
void on_pwrOffDelay_valueChanged();
diff --git a/companion/src/generaledit/generalsetup.ui b/companion/src/generaledit/generalsetup.ui
index d4e9bff01..7353b9c4b 100644
--- a/companion/src/generaledit/generalsetup.ui
+++ b/companion/src/generaledit/generalsetup.ui
@@ -554,348 +554,13 @@
-
-
-
-
-
-
- 0
- 0
-
-
-
- 23
-
-
-
- -
-
-
- RotEnc Navigation
-
-
-
- -
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Stick reverse
-
-
-
- -
-
-
-
-
-
-
-
-
- This is the switch selectrion for turning on the backlight (if installed).
-
-
-
-
- -1
-
-
-
- -
-
-
- Backlight flash on alarm
-
-
-
- -
-
-
- Backlight Auto OFF after
-
-
-
- -
-
-
- Backlight Switch
-
-
-
- -
-
-
- ms
-
-
- 200
-
-
- 1000
-
-
- 10
-
-
- 500
-
-
-
-
-
-
- Voice Language
-
-
-
- -
-
-
- Hz
-
-
- 300
-
-
- 1100
-
-
- 10
-
-
- 700
-
-
-
- -
-
-
-
-
-
- 1
-
-
-
- -
-
-
- 2
-
-
-
- -
-
-
- 3
-
-
-
- -
-
-
- 4
-
-
-
-
-
- -
-
-
- Vario repeat at zero
-
-
-
- -
-
-
- Vario pitch at zero
-
-
-
- -
-
-
- FAI Mode
-
-
-
- -
-
-
- Backlight OFF Brightness
-
-
-
- -
-
-
- 100
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
-
- If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds.
-
-
- sec
-
-
- 600
-
-
- 5
-
-
-
- -
-
-
-
-
-
-
-
-
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html>
-
-
- 1
-
-
- 20
-
-
- 1
-
-
-
- -
-
-
- Hz
-
-
- 1300
-
-
- 2900
-
-
- 10
-
-
- 1700
-
-
-
- -
Timeshift from UTC
- -
-
-
- 5
-
-
- 100
-
-
-
- -
-
-
-
-
- America
-
-
- -
-
- Japan
-
-
- -
-
- Europe
-
-
-
-
- -
-
-
- If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio.
-
-
-
-
-
-
- -
-
-
-
-
- Beeper
-
-
- -
-
- Speaker
-
-
- -
-
- BeeperVoice
-
-
- -
-
- SpeakerVoice
-
-
-
-
- -
-
-
- Backlight Brightness
-
-
-
-
-
@@ -992,24 +657,288 @@ p, li { white-space: pre-wrap; }
- -
-
+
-
+
+
+ -
+
- Backlight color
+ Sound Mode
- -
-
+
-
+
- Vario pitch at max
+
- -
-
+
-
+
+
-
+
+
+ 1
+
+
+
+ -
+
+
+ 2
+
+
+
+ -
+
+
+ 3
+
+
+
+ -
+
+
+ 4
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ This is the switch selectrion for turning on the backlight (if installed).
+
+
+
+
+ -1
+
+
+
+ -
+
+
+ Hz
+
+
+ 300
+
+
+ 1100
+
+
+ 10
+
+
+ 700
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ ms
+
+
+ 200
+
+
+ 1000
+
+
+ 10
+
+
+ 500
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
- Speaker Pitch (spkr only)
+ Stick reverse
+
+
+
+ -
+
+
+ nnnnnnNN
+
+
+ 8
+
+
+
+ -
+
+
-
+
+ Beeper
+
+
+ -
+
+ Speaker
+
+
+ -
+
+ BeeperVoice
+
+
+ -
+
+ SpeakerVoice
+
+
+
+
+ -
+
+
+ Backlight OFF Brightness
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 23
+
+
+
+ -
+
+
+ RotEnc Navigation
+
+
+
+ -
+
+
+ 5
+
+
+ 100
+
+
+
+ -
+
+
+ Backlight Switch
+
+
+
+ -
+
+
-
+
+ America
+
+
+ -
+
+ Japan
+
+
+ -
+
+ Europe
+
+
+
+
+ -
+
+
+ Vario pitch at zero
+
+
+
+ -
+
+
+ If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio.
+
+
+
+
+
+
+ -
+
+
+ Backlight Auto OFF after
+
+
+
+ -
+
+
+ Hz
+
+
+ 1300
+
+
+ 2900
+
+
+ 10
+
+
+ 1700
+
+
+
+ -
+
+
+ 100
+
+
+
+ -
+
+
+ FAI Mode
@@ -1044,31 +973,56 @@ p, li { white-space: pre-wrap; }
- -
+
-
+
+
+ Backlight color
+
+
+
+ -
+
+
+ Owner Registration ID
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+ If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds.
+
+
+ sec
+
+
+ 600
+
+
+ 5
+
+
+
+ -
Country Code
- -
-
-
- -
-
-
- Sound Mode
-
-
-
- -
-
-
- Speaker Volume
-
-
-
- -
+
-
-
@@ -1098,36 +1052,96 @@ p, li { white-space: pre-wrap; }
- -
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
+
-
+
- Owner Registration ID
+ Backlight Brightness
- -
-
-
- aaaaaaAA
+
-
+
+
+ Vario repeat at zero
-
- 8
+
+
+ -
+
+
+ Voice Language
+
+
+
+ -
+
+
+ Backlight flash on alarm
+
+
+
+ -
+
+
+ Vario pitch at max
+
+
+
+ -
+
+
+ -
+
+
+ Speaker Pitch (spkr only)
+
+
+
+ -
+
+
+ Speaker Volume
+
+
+
+ -
+
+
+
+
+
+
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html>
+
+
+ 1
+
+
+ 20
+
+
+ 1
+
+
+
+ -
+
+
+ Keys Backlight
+
+
+
+ -
+
+
+
diff --git a/companion/src/generaledit/hardware.cpp b/companion/src/generaledit/hardware.cpp
index 737882d78..78d0ec75d 100644
--- a/companion/src/generaledit/hardware.cpp
+++ b/companion/src/generaledit/hardware.cpp
@@ -172,7 +172,7 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
ui->txCurrentCalibrationLabel->hide();
}
- if (IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board)|| IS_TARANIS_X9E(board) || IS_HORUS(board)) {
+ if (IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board)|| IS_TARANIS_X9E(board) || IS_TARANIS_X9DP_2019(board) || IS_FAMILY_HORUS_OR_T16(board)) {
ui->bluetoothMode->addItem(tr("OFF"), 0);
if (IS_TARANIS_X9E(board)) {
ui->bluetoothMode->addItem(tr("Enabled"), 1);
@@ -189,7 +189,7 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
ui->bluetoothWidget->hide();
}
- if ((IS_HORUS(board) && board != Board::BOARD_X10_EXPRESS) || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board))) {
+ if ((IS_FAMILY_HORUS_OR_T16(board) && board != Board::BOARD_X10_EXPRESS) || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board))) {
ui->antennaMode->addItem(tr("Internal"), -2);
ui->antennaMode->addItem(tr("Ask"), -1);
ui->antennaMode->addItem(tr("Per model"), 0);
diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp
index eb594b9b6..2b0f62503 100644
--- a/companion/src/helpers.cpp
+++ b/companion/src/helpers.cpp
@@ -565,7 +565,6 @@ QPixmap makePixMap(const QImage & image)
return QPixmap::fromImage(result);
}
-
int version2index(const QString & version)
{
int result = 999;
@@ -581,6 +580,10 @@ int version2index(const QString & version)
result = parts[1].toInt(); // nightly build up to 899
mainVersion = parts[0];
}
+ else if (version.contains("-")) {
+ parts = version.split("-");
+ mainVersion = parts[0];
+ }
parts = mainVersion.split('.');
if (parts.size() > 2)
result += 1000 * parts[2].toInt();
diff --git a/companion/src/images/simulator/JumperT18/bottom.png b/companion/src/images/simulator/JumperT18/bottom.png
new file mode 100644
index 000000000..8f0d29f7e
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/bottom.png differ
diff --git a/companion/src/images/simulator/JumperT18/left.png b/companion/src/images/simulator/JumperT18/left.png
new file mode 100755
index 000000000..4683595ec
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left.png differ
diff --git a/companion/src/images/simulator/JumperT18/left_mdl.png b/companion/src/images/simulator/JumperT18/left_mdl.png
new file mode 100755
index 000000000..8260dad5d
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left_mdl.png differ
diff --git a/companion/src/images/simulator/JumperT18/left_page.png b/companion/src/images/simulator/JumperT18/left_page.png
new file mode 100755
index 000000000..5fbeafbde
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left_page.png differ
diff --git a/companion/src/images/simulator/JumperT18/left_sys.png b/companion/src/images/simulator/JumperT18/left_sys.png
new file mode 100755
index 000000000..777f996e4
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left_sys.png differ
diff --git a/companion/src/images/simulator/JumperT18/left_tele.png b/companion/src/images/simulator/JumperT18/left_tele.png
new file mode 100755
index 000000000..3867d3eed
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/left_tele.png differ
diff --git a/companion/src/images/simulator/JumperT18/right.png b/companion/src/images/simulator/JumperT18/right.png
new file mode 100644
index 000000000..fced173dd
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/right.png differ
diff --git a/companion/src/images/simulator/JumperT18/right_ent.png b/companion/src/images/simulator/JumperT18/right_ent.png
new file mode 100644
index 000000000..eaf7c6acc
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/right_ent.png differ
diff --git a/companion/src/images/simulator/JumperT18/right_rtn.png b/companion/src/images/simulator/JumperT18/right_rtn.png
new file mode 100644
index 000000000..bf3d51d7d
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/right_rtn.png differ
diff --git a/companion/src/images/simulator/JumperT18/top.png b/companion/src/images/simulator/JumperT18/top.png
new file mode 100644
index 000000000..3bc1784ee
Binary files /dev/null and b/companion/src/images/simulator/JumperT18/top.png differ
diff --git a/companion/src/images/simulator/TX16S/bottom.png b/companion/src/images/simulator/TX16S/bottom.png
new file mode 100644
index 000000000..8f0d29f7e
Binary files /dev/null and b/companion/src/images/simulator/TX16S/bottom.png differ
diff --git a/companion/src/images/simulator/TX16S/left.png b/companion/src/images/simulator/TX16S/left.png
new file mode 100644
index 000000000..602017e44
Binary files /dev/null and b/companion/src/images/simulator/TX16S/left.png differ
diff --git a/companion/src/images/simulator/TX16S/left_page.png b/companion/src/images/simulator/TX16S/left_page.png
new file mode 100644
index 000000000..9ea20a59f
Binary files /dev/null and b/companion/src/images/simulator/TX16S/left_page.png differ
diff --git a/companion/src/images/simulator/TX16S/left_page2.png b/companion/src/images/simulator/TX16S/left_page2.png
new file mode 100644
index 000000000..6ef922970
Binary files /dev/null and b/companion/src/images/simulator/TX16S/left_page2.png differ
diff --git a/companion/src/images/simulator/TX16S/left_rtn.png b/companion/src/images/simulator/TX16S/left_rtn.png
new file mode 100644
index 000000000..4fa7d04ff
Binary files /dev/null and b/companion/src/images/simulator/TX16S/left_rtn.png differ
diff --git a/companion/src/images/simulator/TX16S/left_sys.png b/companion/src/images/simulator/TX16S/left_sys.png
new file mode 100644
index 000000000..da6b6e939
Binary files /dev/null and b/companion/src/images/simulator/TX16S/left_sys.png differ
diff --git a/companion/src/images/simulator/TX16S/left_tele.png b/companion/src/images/simulator/TX16S/left_tele.png
new file mode 100644
index 000000000..a51f18bd1
Binary files /dev/null and b/companion/src/images/simulator/TX16S/left_tele.png differ
diff --git a/companion/src/images/simulator/TX16S/right.png b/companion/src/images/simulator/TX16S/right.png
new file mode 100644
index 000000000..f07ca05bf
Binary files /dev/null and b/companion/src/images/simulator/TX16S/right.png differ
diff --git a/companion/src/images/simulator/TX16S/right_ent.png b/companion/src/images/simulator/TX16S/right_ent.png
new file mode 100644
index 000000000..9f407a2cf
Binary files /dev/null and b/companion/src/images/simulator/TX16S/right_ent.png differ
diff --git a/companion/src/images/simulator/TX16S/right_mdl.png b/companion/src/images/simulator/TX16S/right_mdl.png
new file mode 100644
index 000000000..67ca5a0d3
Binary files /dev/null and b/companion/src/images/simulator/TX16S/right_mdl.png differ
diff --git a/companion/src/images/simulator/TX16S/top.png b/companion/src/images/simulator/TX16S/top.png
new file mode 100644
index 000000000..3bc1784ee
Binary files /dev/null and b/companion/src/images/simulator/TX16S/top.png differ
diff --git a/companion/src/imgpreferences.ui b/companion/src/imgpreferences.ui
deleted file mode 100644
index 1ba680d4d..000000000
--- a/companion/src/imgpreferences.ui
+++ /dev/null
@@ -1,500 +0,0 @@
-
-
- preferencesDialog
-
-
-
- 0
- 0
- 685
- 432
-
-
-
-
- 0
- 0
-
-
-
-
- 685
- 0
-
-
-
- Preferences
-
-
-
- QLayout::SetMinimumSize
-
-
- 2
-
-
- 4
-
- -
-
-
- 8
-
-
-
-
-
-
-
-
- true
-
-
- true
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Simu BackLight
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
-
-
- -
-
-
- Simulator capture folder
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Joystick
-
-
-
- -
-
-
- Remember simulator switches
-
-
-
- -
-
-
-
-
-
-
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
- Enable
-
-
-
-
-
- -
-
-
- Use clipboard only
-
-
-
- -
-
-
- Calibrate
-
-
-
- -
-
-
-
-
-
-
-
- Blue
-
-
- -
-
- Green
-
-
- -
-
- Red
-
-
- -
-
- Orange
-
-
- -
-
- Yellow
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
- Open Folder
-
-
- false
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
- Personal splash library
-
-
-
- -
-
-
-
-
-
- true
-
-
- true
-
-
-
- -
-
-
- Open Folder
-
-
-
-
-
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
-
-
- Include companion splashes
-
-
- -
-
- Only user defined splashes
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Splash library behaviour
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
- Custom TX splash screen
-
-
-
- -
-
-
-
-
-
- true
-
-
- true
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Open Image
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- ...
-
-
-
- -
-
-
- ...
-
-
-
- -
-
-
- false
-
-
- Invert Pixels
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 128
- 64
-
-
-
-
- 128
- 64
-
-
-
- QFrame::Panel
-
-
- QFrame::Raised
-
-
-
-
-
- true
-
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
-
-
-
-
-
-
- backLightColor
- joystickCB
- joystickChkB
- joystickcalButton
- simuSW
- snapshotPath
- snapshotPathButton
- snapshotClipboardCKB
- libraryPath
- libraryPathButton
- splashincludeCB
- SplashFileName
- SplashSelect
- SplashLibraryDialogButton
- clearImageButton
- InvertPixels
- buttonBox
-
-
-
-
-
-
- buttonBox
- accepted()
- preferencesDialog
- accept()
-
-
- 370
- 49
-
-
- 157
- 274
-
-
-
-
- buttonBox
- rejected()
- preferencesDialog
- reject()
-
-
- 390
- 55
-
-
- 286
- 274
-
-
-
-
-
diff --git a/companion/src/logsdialog.cpp b/companion/src/logsdialog.cpp
index e60318c69..b7fa54f16 100644
--- a/companion/src/logsdialog.cpp
+++ b/companion/src/logsdialog.cpp
@@ -761,7 +761,7 @@ void LogsDialog::setFlightSessions()
int noSesions = sessions.size()-1;
QString label = QString("%1 ").arg(noSesions);
label += tr(noSesions > 1 ? "sessions" : "session");
- label += " <" + tr("total duration ") + generateDuration(getRecordTimeStamp(1), getRecordTimeStamp(n-1)) + ">";
+ label += " <" + tr("time span") + generateDuration(getRecordTimeStamp(1), getRecordTimeStamp(n-1)) + ">";
ui->sessions_CB->addItem(label);
// add individual sessions
diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp
index e795594cb..50574ecd5 100644
--- a/companion/src/mainwindow.cpp
+++ b/companion/src/mainwindow.cpp
@@ -26,7 +26,6 @@
#include "apppreferencesdialog.h"
#include "fwpreferencesdialog.h"
#include "firmwareinterface.h"
-#include "fusesdialog.h"
#include "downloaddialog.h"
#include "printdialog.h"
#include "version.h"
@@ -49,6 +48,7 @@
#include "translations.h"
#include "dialogs/filesyncdialog.h"
+#include "profilechooser.h"
#include
#include
@@ -130,10 +130,16 @@ MainWindow::MainWindow():
else {
if (!g.previousVersion().isEmpty())
g.warningId(g.warningId() | AppMessages::MSG_UPGRADED);
- if (checkProfileRadioExists(g.sessionId()))
- QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates()));
- else
- g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
+ if (g.promptProfile()) {
+ QTimer::singleShot(updateDelay, this, SLOT(chooseProfile())); // add an extra second to give mainwindow time to load
+ updateDelay += 5000; // give user time to select profile before warnings
+ }
+ else {
+ if (checkProfileRadioExists(g.sessionId()))
+ QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates()));
+ else
+ g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
+ }
}
QTimer::singleShot(updateDelay, this, SLOT(displayWarnings()));
@@ -353,7 +359,6 @@ void MainWindow::checkForCompanionUpdateFinished(QNetworkReply * reply)
return onUpdatesError(tr("Companion update check failed, new version information not found."));
int webVersion = version2index(version);
-
int ownVersion = version2index(VERSION);
if (ownVersion < webVersion) {
@@ -468,7 +473,7 @@ void MainWindow::checkForFirmwareUpdateFinished(QNetworkReply * reply)
const QString errorString = seekCodeString(qba, "ERROR");
const QString blockedRadios = seekCodeString(qba, "BLOCK");
long version;
-
+
if (errorString == "NO_RC")
return onUpdatesError(tr("No firmware release candidates are currently being served for this version, please switch release channel"));
else if (errorString == "NO_NIGHTLY")
@@ -481,7 +486,7 @@ void MainWindow::checkForFirmwareUpdateFinished(QNetworkReply * reply)
msgbox.setText(tr("Release candidate builds are now available for this version, would you like to switch to using them?"));
msgbox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgbox.setDefaultButton(QMessageBox::Yes);
-
+
if(msgbox.exec() == QMessageBox::Yes) {
g.OpenTxBranch(AppData::DownloadBranchType(AppData::BRANCH_RC_TESTING));
return onUpdatesError(tr("Channel changed to RC, please restart the download process"));
@@ -493,7 +498,7 @@ void MainWindow::checkForFirmwareUpdateFinished(QNetworkReply * reply)
msgbox.setText(tr("Official release builds are now available for this version, would you like to switch to using them?"));
msgbox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgbox.setDefaultButton(QMessageBox::Yes);
-
+
if(msgbox.exec() == QMessageBox::Yes) {
g.OpenTxBranch(AppData::DownloadBranchType(AppData::BRANCH_RELEASE_STABLE));
return onUpdatesError(tr("Channel changed to Release, please restart the download process"));
@@ -916,26 +921,25 @@ void MainWindow::changelog()
void MainWindow::customizeSplash()
{
- CustomizeSplashDialog * dialog = new CustomizeSplashDialog(this);
+ auto * dialog = new CustomizeSplashDialog(this);
dialog->exec();
dialog->deleteLater();
}
void MainWindow::writeEeprom()
{
- if (activeMdiChild()) activeMdiChild()->writeEeprom();
+ if (activeMdiChild())
+ activeMdiChild()->writeEeprom();
}
void MainWindow::readEeprom()
{
Board::Type board = getCurrentBoard();
QString tempFile;
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
tempFile = generateProcessUniqueTempFileName("temp.otx");
- else if (IS_ARM(board))
- tempFile = generateProcessUniqueTempFileName("temp.bin");
else
- tempFile = generateProcessUniqueTempFileName("temp.hex");
+ tempFile = generateProcessUniqueTempFileName("temp.bin");
qDebug() << "MainWindow::readEeprom(): using temp file: " << tempFile;
@@ -975,7 +979,7 @@ bool MainWindow::readEepromFromRadio(const QString & filename)
void MainWindow::writeBackup()
{
- if (IS_HORUS(getCurrentBoard())) {
+ if (IS_FAMILY_HORUS_OR_T16(getCurrentBoard())) {
QMessageBox::information(this, CPN_STR_APP_NAME, tr("This function is not yet implemented"));
return;
// TODO implementation
@@ -992,7 +996,7 @@ void MainWindow::writeFlash(QString fileToFlash)
void MainWindow::readBackup()
{
- if (IS_HORUS(getCurrentBoard())) {
+ if (IS_FAMILY_HORUS_OR_T16(getCurrentBoard())) {
QMessageBox::information(this, CPN_STR_APP_NAME, tr("This function is not yet implemented"));
return;
// TODO implementation
@@ -1022,14 +1026,6 @@ void MainWindow::burnConfig()
void MainWindow::burnList()
{
burnConfigDialog bcd(this);
- bcd.listAvrdudeProgrammers();
-}
-
-void MainWindow::burnFuses()
-{
- FusesDialog *fd = new FusesDialog(this);
- fd->exec();
- delete fd;
}
void MainWindow::compare()
@@ -1058,7 +1054,7 @@ void MainWindow::about()
aboutStr.append("
");
aboutStr.append(QString("Version %1, %2").arg(VERSION).arg(__DATE__));
aboutStr.append("
");
- aboutStr.append(tr("Copyright OpenTX Team") + "
© 2011-2019
");
+ aboutStr.append(tr("Copyright OpenTX Team") + QString("
© 2011-%1
").arg(QString(__DATE__).right(4)));
QMessageBox msgBox(this);
msgBox.setWindowIcon(CompanionIcon("information.png"));
msgBox.setWindowTitle(tr("About Companion"));
@@ -1078,9 +1074,15 @@ void MainWindow::updateMenus()
compareAct->setEnabled(activeChild);
writeEepromAct->setEnabled(activeChild);
readEepromAct->setEnabled(true);
- writeBUToRadioAct->setEnabled(true);
- readBUToFileAct->setEnabled(true);
- editSplashAct->setDisabled(IS_HORUS(getCurrentBoard()));
+ if (IS_FAMILY_HORUS_OR_T16(getCurrentBoard())) {
+ writeBUToRadioAct->setEnabled(false);
+ readBUToFileAct->setEnabled(false);
+ }
+ else {
+ writeBUToRadioAct->setEnabled(true);
+ readBUToFileAct->setEnabled(true);
+ }
+ editSplashAct->setDisabled(IS_FAMILY_HORUS_OR_T16(getCurrentBoard()));
foreach (QAction * act, fileWindowActions) {
if (!act)
@@ -1219,8 +1221,6 @@ void MainWindow::retranslateUi(bool showMsg)
trAct(changelogAct, tr("Release notes..."), tr("Show release notes"));
trAct(compareAct, tr("Compare Models..."), tr("Compare models"));
trAct(editSplashAct, tr("Edit Radio Splash Image..."), tr("Edit the splash image of your Radio"));
- trAct(burnListAct, tr("List programmers..."), tr("List available programmers"));
- trAct(burnFusesAct, tr("Fuses..."), tr("Show fuses dialog"));
trAct(readFlashAct, tr("Read Firmware from Radio"), tr("Read firmware from Radio"));
trAct(writeFlashAct, tr("Write Firmware to Radio"), tr("Write firmware to Radio"));
trAct(sdsyncAct, tr("Synchronize SD"), tr("SD card synchronization"));
@@ -1282,14 +1282,14 @@ void MainWindow::createActions()
editSplashAct = addAct("paintbrush.png", SLOT(customizeSplash()));
burnListAct = addAct("list.png", SLOT(burnList()));
- burnFusesAct = addAct("fuses.png", SLOT(burnFuses()));
readFlashAct = addAct("read_flash.png", SLOT(readFlash()));
writeFlashAct = addAct("write_flash.png", SLOT(writeFlash()));
writeEepromAct = addAct("write_eeprom.png", SLOT(writeEeprom()));
readEepromAct = addAct("read_eeprom.png", SLOT(readEeprom()));
burnConfigAct = addAct("configure.png", SLOT(burnConfig()));
- writeBUToRadioAct = addAct("write_eeprom_file.png", SLOT(writeBackup()));
- readBUToFileAct = addAct("read_eeprom_file.png", SLOT(readBackup()));
+
+ writeBUToRadioAct = addAct("write_eeprom_file.png", SLOT(writeBackup()));
+ readBUToFileAct = addAct("read_eeprom_file.png", SLOT(readBackup()));
createProfileAct = addAct("new.png", SLOT(createProfile()));
copyProfileAct = addAct("copy.png", SLOT(copyProfile()));
@@ -1386,10 +1386,6 @@ void MainWindow::createMenus()
burnMenu->addAction(readFlashAct);
burnMenu->addSeparator();
burnMenu->addSeparator();
- if (!IS_ARM(getCurrentBoard())) {
- burnMenu->addAction(burnFusesAct);
- burnMenu->addAction(burnListAct);
- }
windowMenu = menuBar()->addMenu("");
windowMenu->addAction(actTabbedWindows);
@@ -1799,3 +1795,20 @@ void MainWindow::autoClose()
{
this->close();
}
+
+void MainWindow::chooseProfile()
+{
+ QMap active;
+ active = g.getActiveProfiles();
+ if (active.size() > 1) {
+ ProfileChooserDialog *pcd = new ProfileChooserDialog(this);
+ connect(pcd, &ProfileChooserDialog::profileChanged, this, &MainWindow::loadProfileId);
+ pcd->exec();
+ delete pcd;
+ // doi here as need to wait until dialog dismissed and current radio type is set
+ if (checkProfileRadioExists(g.sessionId()))
+ doAutoUpdates();
+ else
+ g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
+ }
+}
diff --git a/companion/src/mainwindow.h b/companion/src/mainwindow.h
index 222c047e0..0be249f04 100644
--- a/companion/src/mainwindow.h
+++ b/companion/src/mainwindow.h
@@ -111,7 +111,6 @@ class MainWindow : public QMainWindow
void readBackup();
void burnConfig();
void burnList();
- void burnFuses();
void contributors();
void sdsync();
void changelog();
@@ -128,6 +127,7 @@ class MainWindow : public QMainWindow
void exportSettings();
void importSettings();
void autoClose();
+ void chooseProfile();
void openUpdatesWaitDialog();
void closeUpdatesWaitDialog();
@@ -209,7 +209,6 @@ class MainWindow : public QMainWindow
QAction *readEepromAct;
QAction *burnConfigAct;
QAction *burnListAct;
- QAction *burnFusesAct;
QAction *writeFlashAct;
QAction *readFlashAct;
QAction *writeBUToRadioAct;
diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp
index a5f25d1ca..1a85aafb7 100644
--- a/companion/src/mdichild.cpp
+++ b/companion/src/mdichild.cpp
@@ -534,7 +534,7 @@ void MdiChild::initModelsList()
connect(modelsListModel, &QAbstractItemModel::dataChanged, this, &MdiChild::onDataChanged);
ui->modelsList->setModel(modelsListModel);
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
ui->modelsList->setIndentation(20);
// ui->modelsList->resetIndentation(); // introduced in next Qt versions ...
}
@@ -1490,18 +1490,18 @@ bool MdiChild::convertStorage(Board::Type from, Board::Type to, bool newFile)
isUntitled = true;
if (cstate.hasLogEntries(RadioDataConversionState::EVT_INF)) {
- QDialog * msgBox = new QDialog(Q_NULLPTR, Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
+ auto * msgBox = new QDialog(Q_NULLPTR, Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
- ExportableTableView * tv = new ExportableTableView(msgBox);
+ auto * tv = new ExportableTableView(msgBox);
tv->setSortingEnabled(true);
tv->verticalHeader()->hide();
tv->setModel(cstate.getLogModel(RadioDataConversionState::EVT_INF, tv));
tv->resizeColumnsToContents();
tv->resizeRowsToContents();
- QDialogButtonBox * btnBox = new QDialogButtonBox(QDialogButtonBox::Ok, this);
+ auto * btnBox = new QDialogButtonBox(QDialogButtonBox::Ok, this);
- QVBoxLayout * lo = new QVBoxLayout(msgBox);
+ auto * lo = new QVBoxLayout(msgBox);
lo->addWidget(new QLabel(tr("The conversion generated some important messages, please review them below.")));
lo->addWidget(tv);
lo->addWidget(btnBox);
@@ -1531,12 +1531,12 @@ int MdiChild::askQuestion(const QString & msg, QMessageBox::StandardButtons butt
void MdiChild::writeEeprom() // write to Tx
{
Board::Type board = getCurrentBoard();
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
QString radioPath = findMassstoragePath("RADIO", true);
qDebug() << "Searching for SD card, found" << radioPath;
if (radioPath.isEmpty()) {
qDebug() << "MdiChild::writeEeprom(): Horus radio not found";
- QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Unable to find Horus radio SD card!"));
+ QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Unable to find radio SD card!"));
return;
}
if (saveFile(radioPath, false)) {
diff --git a/companion/src/modeledit/CMakeLists.txt b/companion/src/modeledit/CMakeLists.txt
index 300fb27cc..31e727081 100644
--- a/companion/src/modeledit/CMakeLists.txt
+++ b/companion/src/modeledit/CMakeLists.txt
@@ -42,7 +42,6 @@ set(modeledit_UIS
setup_timer.ui
setup_module.ui
flightmode.ui
- telemetry_analog.ui
telemetry_customscreen.ui
telemetry_sensor.ui
)
diff --git a/companion/src/modeledit/channels.cpp b/companion/src/modeledit/channels.cpp
index 593121d83..0cde45109 100644
--- a/companion/src/modeledit/channels.cpp
+++ b/companion/src/modeledit/channels.cpp
@@ -45,7 +45,7 @@ LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row
spinbox->setSuffix("%");
}
- if (IS_ARM(board) || deflt == 0 /*it's the offset*/) {
+ if (deflt == 0 /*it's the offset*/) {
spinbox->setDecimals(1);
}
else {
@@ -120,7 +120,7 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera
s1.report("header");
- for (int i=0; isetContextMenuPolicy(Qt::CustomContextMenu);
label->setToolTip(tr("Popup menu available"));
label->setMouseTracking(true);
- connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(chn_customContextMenuRequested(QPoint)));
+ connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint)));
tableLayout->addWidget(i, col++, label);
// Channel name
@@ -204,7 +204,7 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera
Channels::~Channels()
{
// compiler warning if delete[]
- for (int i=0; igetChannelsMax();
- for (int i=0 ; iupdateMinMax(10 * channelMax);
chnMin[i]->updateMinMax(10 * channelMax);
chnMax[i]->updateMinMax(10 * channelMax);
@@ -280,7 +280,7 @@ void Channels::ppmcenterEdited()
void Channels::update()
{
- for (int i=0; igetBoard())) {
int numcurves = firmware->getCapability(NumCurves);
curveCB[i]->clear();
- for (int j=-numcurves; j<=numcurves; j++) {
+ for (int j = -numcurves; j <= numcurves; j++) {
curveCB[i]->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, j).toString(model, false), j);
}
curveCB[i]->setCurrentIndex(model->limitData[i].curve.value + numcurves);
@@ -312,118 +312,140 @@ void Channels::updateLine(int i)
lock = false;
}
-void Channels::chnPaste()
+void Channels::cmPaste()
{
- const QClipboard *clipboard = QApplication::clipboard();
- const QMimeData *mimeData = clipboard->mimeData();
- if (mimeData->hasFormat(MIMETYPE_CHN)) {
- QByteArray chnData = mimeData->data(MIMETYPE_CHN);
- LimitData *chn = &model->limitData[selectedChannel];
- memcpy(chn, chnData.constData(), sizeof(LimitData));
- updateLine(selectedChannel);
+ QByteArray data;
+ if (hasClipboardData(&data)) {
+ memcpy(&model->limitData[selectedIndex], data.constData(), sizeof(LimitData));
+ updateLine(selectedIndex);
emit modified();
}
}
-void Channels::chnDelete()
+void Channels::cmDelete()
{
- int maxidx = chnCapability - 1;
- for (int i=selectedChannel; ilimitData[i].isEmpty() || !model->limitData[i+1].isEmpty()) {
- LimitData *chn1 = &model->limitData[i];
- LimitData *chn2 = &model->limitData[i+1];
- memcpy(chn1, chn2, sizeof(LimitData));
- updateLine(i);
- }
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ memmove(&model->limitData[selectedIndex], &model->limitData[selectedIndex + 1], (CPN_MAX_CHNOUT - (selectedIndex + 1)) * sizeof(LimitData));
+ model->limitData[chnCapability - 1].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
+
+ for (int i = selectedIndex; i < chnCapability; i++) {
+ updateLine(i);
}
- model->limitData[maxidx].clear();
- updateLine(maxidx);
+
emit modified();
}
-void Channels::chnCopy()
+void Channels::cmCopy()
{
- QByteArray chnData;
- chnData.append((char*)&model->limitData[selectedChannel],sizeof(LimitData));
+ QByteArray data;
+ data.append((char*)&model->limitData[selectedIndex], sizeof(LimitData));
QMimeData *mimeData = new QMimeData;
- mimeData->setData(MIMETYPE_CHN, chnData);
+ mimeData->setData(MIMETYPE_CHANNEL, data);
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
}
-void Channels::chnCut()
+void Channels::cmCut()
{
- chnCopy();
- chnClear();
+ cmCopy();
+ cmClear();
}
-void Channels::chn_customContextMenuRequested(QPoint pos)
+void Channels::onCustomContextMenuRequested(QPoint pos)
{
QLabel *label = (QLabel *)sender();
- selectedChannel = label->property("index").toInt();
-
+ selectedIndex = label->property("index").toInt();
QPoint globalPos = label->mapToGlobal(pos);
- const QClipboard *clipboard = QApplication::clipboard();
- const QMimeData *mimeData = clipboard->mimeData();
- bool hasData = mimeData->hasFormat(MIMETYPE_CHN);
- bool moveUpAllowed = (selectedChannel > 0);
- bool moveDownAllowed = (selectedChannel < (chnCapability - 1));
- bool insertAllowed = (selectedChannel < (chnCapability - 1)) && (model->limitData[chnCapability - 1].isEmpty());
-
QMenu contextMenu;
- contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(chnCopy()));
- contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(chnCut()));
- contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(chnPaste()))->setEnabled(hasData);
- contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(chnClear()));
+ contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(cmCopy()));
+ contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(cmCut()));
+ contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData());
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear()));
contextMenu.addSeparator();
- contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(chnInsert()))->setEnabled(insertAllowed);
- contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(chnDelete()));
- contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(chnMoveUp()))->setEnabled(moveUpAllowed);
- contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(chnMoveDown()))->setEnabled(moveDownAllowed);
+ contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(cmInsert()))->setEnabled(insertAllowed());
+ contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(cmDelete()));
+ contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
+ contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
contextMenu.addSeparator();
- contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(chnClearAll()));
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll()));
contextMenu.exec(globalPos);
}
-void Channels::chnMoveUp()
+bool Channels::hasClipboardData(QByteArray * data) const
{
- swapChnData(selectedChannel, selectedChannel - 1);
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat(MIMETYPE_CHANNEL)) {
+ if (data)
+ data->append(mimeData->data(MIMETYPE_CHANNEL));
+ return true;
+ }
+ return false;
}
-void Channels::chnMoveDown()
+bool Channels::insertAllowed() const
{
- swapChnData(selectedChannel, selectedChannel + 1);
+ return ((selectedIndex < chnCapability - 1) && (model->limitData[chnCapability - 1].isEmpty()));
}
-void Channels::chnClear()
+bool Channels::moveDownAllowed() const
{
- model->limitData[selectedChannel].clear();
- updateLine(selectedChannel);
+ return selectedIndex < chnCapability - 1;
+}
+
+bool Channels::moveUpAllowed() const
+{
+ return selectedIndex > 0;
+}
+
+void Channels::cmMoveUp()
+{
+ swapData(selectedIndex, selectedIndex - 1);
+}
+
+void Channels::cmMoveDown()
+{
+ swapData(selectedIndex, selectedIndex + 1);
+}
+
+void Channels::cmClear()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ model->limitData[selectedIndex].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
+ updateLine(selectedIndex);
emit modified();
}
-void Channels::chnClearAll()
+void Channels::cmClearAll()
{
- for (int i=0; ilimitData[i].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, i);
updateLine(i);
}
emit modified();
}
-void Channels::chnInsert()
+void Channels::cmInsert()
{
- for (int i=(chnCapability - 1); i>selectedChannel; i--) {
- if (!model->limitData[i].isEmpty() || !model->limitData[i-1].isEmpty()) {
- memcpy(&model->limitData[i], &model->limitData[i-1], sizeof(LimitData));
- updateLine(i);
- }
- }
- chnClear();
+ memmove(&model->limitData[selectedIndex + 1], &model->limitData[selectedIndex], (CPN_MAX_CHNOUT - (selectedIndex + 1)) * sizeof(LimitData));
+ model->limitData[selectedIndex].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
+ update();
+ emit modified();
}
-void Channels::swapChnData(int idx1, int idx2)
+void Channels::swapData(int idx1, int idx2)
{
if ((idx1 != idx2) && (!model->limitData[idx1].isEmpty() || !model->limitData[idx2].isEmpty())) {
LimitData chntmp = model->limitData[idx2];
@@ -431,6 +453,7 @@ void Channels::swapChnData(int idx1, int idx2)
LimitData *chn2 = &model->limitData[idx2];
memcpy(chn2, chn1, sizeof(LimitData));
memcpy(chn1, &chntmp, sizeof(LimitData));
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
updateLine(idx1);
updateLine(idx2);
emit modified();
diff --git a/companion/src/modeledit/channels.h b/companion/src/modeledit/channels.h
index f50c72b89..caa0fca38 100644
--- a/companion/src/modeledit/channels.h
+++ b/companion/src/modeledit/channels.h
@@ -26,7 +26,7 @@
#include
-constexpr char MIMETYPE_CHN[] = "application/x-companion-chn";
+constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel";
class GVarGroup;
@@ -68,19 +68,23 @@ class Channels : public ModelPanel
void ppmcenterEdited();
void update();
void updateLine(int index);
- void chnDelete();
- void chnCopy();
- void chnPaste();
- void chnCut();
- void chnMoveUp();
- void chnMoveDown();
- void chnInsert();
- void chnClear();
- void chnClearAll();
- void chn_customContextMenuRequested(QPoint pos);
+ void cmDelete();
+ void cmCopy();
+ void cmPaste();
+ void cmCut();
+ void cmMoveUp();
+ void cmMoveDown();
+ void cmInsert();
+ void cmClear();
+ void cmClearAll();
+ void onCustomContextMenuRequested(QPoint pos);
private:
- void swapChnData(int idx1, int idx2);
+ bool hasClipboardData(QByteArray * data = nullptr) const;
+ bool insertAllowed() const;
+ bool moveDownAllowed() const;
+ bool moveUpAllowed() const;
+ void swapData(int idx1, int idx2);
QLineEdit *name[CPN_MAX_CHNOUT];
LimitsGroup *chnOffset[CPN_MAX_CHNOUT];
LimitsGroup *chnMin[CPN_MAX_CHNOUT];
@@ -89,7 +93,7 @@ class Channels : public ModelPanel
QComboBox *curveCB[CPN_MAX_CHNOUT];
QSpinBox *centerSB[CPN_MAX_CHNOUT];
QCheckBox *symlimitsChk[CPN_MAX_CHNOUT];
- int selectedChannel;
+ int selectedIndex;
int chnCapability;
};
diff --git a/companion/src/modeledit/curves.cpp b/companion/src/modeledit/curves.cpp
index cf3eb9e71..5759e60e6 100644
--- a/companion/src/modeledit/curves.cpp
+++ b/companion/src/modeledit/curves.cpp
@@ -117,7 +117,12 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
lock = true;
- if (!firmware->getCapability(HasCvNames)) {
+ maxCurves = firmware->getCapability(NumCurves);
+ hasNames = firmware->getCapability(HasCvNames);
+ hasEnhanced = firmware->getCapability(EnhancedCurves);
+ maxPoints = firmware->getCapability(NumCurvePoints);
+
+ if (!hasNames) {
ui->curveName->hide();
ui->curveNameLabel->hide();
}
@@ -127,14 +132,14 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
connect(scene, SIGNAL(newPoint(int, int)), this, SLOT(onSceneNewPoint(int, int)));
ui->curvePreview->setScene(scene);
- int numcurves=firmware->getCapability(NumCurves);
+
int limit;
- if (numcurves>16) {
- limit=numcurves/2;
+ if (maxCurves > 16) {
+ limit = maxCurves / 2;
} else {
- limit=numcurves;
+ limit = maxCurves;
}
- for (int i=0; isetStyleSheet(QString("background-color: %1; color: white; padding: 2px 3px; border-style: outset; border-width: 1px; border-radius: 2px; border-color: inherit;").arg(colors[i].name()));
#endif
edit->setPalette(palette);
- edit->setText(tr("Curve %1").arg(i+1));
+ edit->setText(tr("Curve %1").arg(i + 1));
edit->setContextMenuPolicy(Qt::CustomContextMenu);
edit->setToolTip(tr("Popup menu available"));
- connect(edit, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ShowContextMenu(const QPoint&)));
+ connect(edit, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onCustomContextMenuRequested(const QPoint&)));
connect(edit, SIGNAL(clicked()), this, SLOT(editCurve()));
- if (icurvesLayout->addWidget(edit, i, 1, 1, 1);
} else {
- ui->curvesLayout2->addWidget(edit, i-limit, 2, 1, 1);
+ ui->curvesLayout2->addWidget(edit, i - limit, 2, 1, 1);
}
// The curve plot checkbox
@@ -167,7 +172,7 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
plot->setProperty("index", i);
plot->setPalette(palette);
connect(plot, SIGNAL(toggled(bool)), this, SLOT(plotCurve(bool)));
- if (icurvesLayout->addWidget(plot, i, 2, 1, 1);
} else {
ui->curvesLayout2->addWidget(plot, i-limit, 1, 1, 1);
@@ -175,13 +180,13 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
}
QSpacerItem * item = new QSpacerItem(1,1, QSizePolicy::Fixed, QSizePolicy::Expanding);
- ui->curvesLayout->addItem(item,limit+1,1,1,1,0);
- if (limit!=numcurves) {
+ ui->curvesLayout->addItem(item,limit + 1, 1, 1, 1, 0);
+ if (limit != maxCurves) {
QSpacerItem * item2 = new QSpacerItem(1,1, QSizePolicy::Fixed, QSizePolicy::Expanding);
- ui->curvesLayout2->addItem(item2,limit+1,1,1,1,0);
+ ui->curvesLayout2->addItem(item2,limit + 1, 1, 1, 1, 0);
}
- for (int i=0; isetProperty("index", i);
spnx[i]->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
@@ -199,14 +204,14 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet
ui->pointsLayout->addWidget(spny[i], i, 1, 1, 1);
bool insert;
- if (firmware->getCapability(EnhancedCurves)) {
+ if (hasEnhanced) {
insert = (i >= 1);
}
else {
- insert = (i==2 || i==4 || i==8 || i==16);
+ insert = (i == 2 || i == 4 || i ==8 || i == 16);
}
if (insert) {
- ui->curvePoints->addItem(tr("%1 points").arg(i+1), i+1);
+ ui->curvePoints->addItem(tr("%1 points").arg(i + 1), i + 1);
}
}
@@ -250,7 +255,7 @@ void Curves::update()
{
lock = true;
- if (firmware->getCapability(HasCvNames)) {
+ if (hasNames) {
ui->curveName->setText(model->curves[currentCurve].name);
}
@@ -272,7 +277,7 @@ void Curves::updateCurveType()
int index = 0;
- if (firmware->getCapability(EnhancedCurves)) {
+ if (hasEnhanced) {
index = model->curves[currentCurve].count - 2;
}
else {
@@ -305,35 +310,34 @@ void Curves::updateCurve()
qreal width = scene->sceneRect().width();
qreal height = scene->sceneRect().height();
- qreal centerX = scene->sceneRect().left() + width/2;
- qreal centerY = scene->sceneRect().top() + height/2;
+ qreal centerX = scene->sceneRect().left() + width / 2;
+ qreal centerY = scene->sceneRect().top() + height / 2;
- QGraphicsSimpleTextItem *ti = scene->addSimpleText(tr("Editing curve %1").arg(currentCurve+1));
+ QGraphicsSimpleTextItem *ti = scene->addSimpleText(tr("Editing curve %1").arg(currentCurve + 1));
ti->setPos(3, 3);
- scene->addLine(centerX, GFX_MARGIN, centerX, height+GFX_MARGIN);
- scene->addLine(GFX_MARGIN, centerY, width+GFX_MARGIN, centerY);
+ scene->addLine(centerX, GFX_MARGIN, centerX, height + GFX_MARGIN);
+ scene->addLine(GFX_MARGIN, centerY, width + GFX_MARGIN, centerY);
QPen pen;
pen.setWidth(1);
pen.setStyle(Qt::SolidLine);
- int numcurves = firmware->getCapability(NumCurves);
- for (int k=0; kcurves[k].count;
- for (int i=0; icurves[k].type == CurveData::CURVE_TYPE_CUSTOM)
- scene->addLine(centerX + (qreal)model->curves[k].points[i].x*width/200,centerY - (qreal)model->curves[k].points[i].y*height/200,centerX + (qreal)model->curves[k].points[i+1].x*width/200,centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen);
+ scene->addLine(centerX + (qreal)model->curves[k].points[i].x*width/200, centerY - (qreal)model->curves[k].points[i].y*height/200,centerX + (qreal)model->curves[k].points[i+1].x*width/200,centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen);
else
- scene->addLine(GFX_MARGIN + i*width/(numpoints-1),centerY - (qreal)model->curves[k].points[i].y*height/200,GFX_MARGIN + (i+1)*width/(numpoints-1),centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen);
+ scene->addLine(GFX_MARGIN + i*width/(numpoints-1), centerY - (qreal)model->curves[k].points[i].y*height/200,GFX_MARGIN + (i+1)*width/(numpoints-1),centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen);
}
}
}
int numpoints = model->curves[currentCurve].count;
- for (int i=0; isetProperty("index", i);
@@ -341,26 +345,27 @@ void Curves::updateCurve()
nodex->setBallSize(ui->pointSize->value());
nodex->setBallHeight(0);
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) {
- if (i>0 && i 0 && i < numpoints - 1) {
nodex->setFixedX(false);
- nodex->setMinX(model->curves[currentCurve].points[i-1].x);
- nodex->setMaxX(model->curves[currentCurve].points[i+1].x);
+ nodex->setMinX(model->curves[currentCurve].points[i - 1].x);
+ nodex->setMaxX(model->curves[currentCurve].points[i + 1].x);
}
else {
nodex->setFixedX(true);
}
- nodex->setPos(centerX + (qreal)model->curves[currentCurve].points[i].x*width/200,centerY - (qreal)model->curves[currentCurve].points[i].y*height/200);
+ nodex->setPos(centerX + (qreal)model->curves[currentCurve].points[i].x * width / 200, centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200);
}
else {
nodex->setFixedX(true);
- nodex->setPos(GFX_MARGIN + i*width/(numpoints-1), centerY - (qreal)model->curves[currentCurve].points[i].y*height/200);
+ nodex->setPos(GFX_MARGIN + i * width / (numpoints - 1), centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200);
}
connect(nodex, SIGNAL(moved(int, int)), this, SLOT(onNodeMoved(int, int)));
connect(nodex, SIGNAL(focus()), this, SLOT(onNodeFocus()));
connect(nodex, SIGNAL(unfocus()), this, SLOT(onNodeUnfocus()));
connect(nodex, SIGNAL(deleteMe()), this, SLOT(onNodeDelete()));
scene->addItem(nodex);
- if (i>0) scene->addItem(new Edge(nodel, nodex));
+ if (i > 0)
+ scene->addItem(new Edge(nodel, nodex));
}
lock = false;
@@ -371,20 +376,20 @@ void Curves::updateCurvePoints()
lock = true;
int count = model->curves[currentCurve].count;
- for (int i=0; ishow();
spny[i]->setValue(model->curves[currentCurve].points[i].y);
if (model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) {
spnx[i]->show();
- if (i==0 || i==model->curves[currentCurve].count-1) {
+ if (i == 0 || i == model->curves[currentCurve].count - 1) {
spnx[i]->setDisabled(true);
spnx[i]->setMaximum(+100);
spnx[i]->setMinimum(-100);
}
else {
spnx[i]->setDisabled(false);
- spnx[i]->setMaximum(model->curves[currentCurve].points[i+1].x);
- spnx[i]->setMinimum(model->curves[currentCurve].points[i-1].x);
+ spnx[i]->setMaximum(model->curves[currentCurve].points[i + 1].x);
+ spnx[i]->setMinimum(model->curves[currentCurve].points[i - 1].x);
}
spnx[i]->setValue(model->curves[currentCurve].points[i].x);
}
@@ -392,7 +397,7 @@ void Curves::updateCurvePoints()
spnx[i]->hide();
}
}
- for (int i=count; ihide();
spnx[i]->hide();
}
@@ -421,9 +426,9 @@ void Curves::onNodeMoved(int x, int y)
spnx[index]->setValue(x);
spny[index]->setValue(y);
if (index > 0)
- spnx[index-1]->setMaximum(x);
- if (index < model->curves[currentCurve].count-1)
- spnx[index+1]->setMinimum(x);
+ spnx[index - 1]->setMaximum(x);
+ if (index < model->curves[currentCurve].count - 1)
+ spnx[index + 1]->setMinimum(x);
emit modified();
lock = false;
}
@@ -444,17 +449,14 @@ void Curves::onNodeUnfocus()
bool Curves::allowCurveType(int points, CurveData::CurveType type)
{
- int numcurves = firmware->getCapability(NumCurves);
-
int totalpoints = 0;
- for (int i=0; icurves[i].count);
- CurveData::CurveType cvType = (i==currentCurve ? type : model->curves[i].type);
- totalpoints += cvPoints + (cvType==CurveData::CURVE_TYPE_CUSTOM ? cvPoints-2 : 0);
+ for (int i = 0; i < maxCurves; i++) {
+ int cvPoints = (i == currentCurve ? points : model->curves[i].count);
+ CurveData::CurveType cvType = (i == currentCurve ? type : model->curves[i].type);
+ totalpoints += cvPoints + (cvType == CurveData::CURVE_TYPE_CUSTOM ? cvPoints - 2 : 0);
}
- int fwpoints = firmware->getCapability(NumCurvePoints);
- if (totalpoints > fwpoints) {
+ if (totalpoints > maxPoints) {
QMessageBox::warning(this, "companion", tr("Not enough free points in EEPROM to store the curve."));
return false;
}
@@ -472,8 +474,8 @@ void Curves::on_curvePoints_currentIndexChanged(int index)
model->curves[currentCurve].count = numpoints;
// TODO something better + reuse!
- for (int i=0; icurves[currentCurve].points[i].x = (i >= numpoints-1 ? +100 : -100 + (200*i)/(numpoints-1));
+ for (int i = 0; i < CPN_MAX_POINTS; i++) {
+ model->curves[currentCurve].points[i].x = (i >= numpoints - 1 ? +100 : -100 + (200 * i) / (numpoints - 1));
model->curves[currentCurve].points[i].y = 0;
}
@@ -491,12 +493,13 @@ void Curves::on_curveCustom_currentIndexChanged(int index)
if (!lock) {
CurveData::CurveType type = (CurveData::CurveType)index;
int numpoints = ui->curvePoints->itemData(ui->curvePoints->currentIndex()).toInt();
+
if (allowCurveType(model->curves[currentCurve].count, type)) {
model->curves[currentCurve].type = type;
// TODO something better + reuse!
- for (int i=0; icurves[currentCurve].points[i].x = (i >= numpoints-1 ? +100 : -100 + (200*i)/(numpoints-1));
+ for (int i = 0; i < CPN_MAX_POINTS; i++) {
+ model->curves[currentCurve].points[i].x = (i >= numpoints - 1 ? +100 : -100 + (200 * i) / (numpoints - 1));
model->curves[currentCurve].points[i].y = 0;
}
@@ -525,7 +528,7 @@ void Curves::on_curveName_editingFinished()
void Curves::resizeEvent(QResizeEvent *event)
{
QRect qr = ui->curvePreview->contentsRect();
- ui->curvePreview->scene()->setSceneRect(GFX_MARGIN, GFX_MARGIN, qr.width()-GFX_MARGIN*2, qr.height()-GFX_MARGIN*2);
+ ui->curvePreview->scene()->setSceneRect(GFX_MARGIN, GFX_MARGIN, qr.width() - GFX_MARGIN * 2, qr.height() - GFX_MARGIN * 2);
updateCurve();
ModelPanel::resizeEvent(event);
}
@@ -559,12 +562,12 @@ void Curves::on_curveApply_clicked()
int index = ui->curveType->currentIndex();
int numpoints = model->curves[currentCurve].count;
- for (int i=0; icurves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM)
x = model->curves[currentCurve].points[i].x;
else
- x = -100.0 + (200.0/(numpoints-1))*i;
+ x = -100.0 + (200.0 / (numpoints - 1)) * i;
bool apply = false;
switch (ui->curveSide->currentIndex()) {
@@ -572,11 +575,11 @@ void Curves::on_curveApply_clicked()
apply = true;
break;
case 1:
- if (x>=0)
+ if (x >= 0)
apply = true;
break;
case 2:
- if (x<0)
+ if (x < 0)
apply = true;
break;
}
@@ -591,68 +594,6 @@ void Curves::on_curveApply_clicked()
emit modified();
}
-void Curves::ShowContextMenu(const QPoint& pos) // this is a slot
-{
- QPushButton *button = (QPushButton *)sender();
- int index = button->property("index").toInt();
- const QClipboard *clipboard = QApplication::clipboard();
- const QMimeData *mimeData = clipboard->mimeData();
- QPoint globalPos = button->mapToGlobal(pos);
- QMenu myMenu;
- QAction *action;
- action = myMenu.addAction(CompanionIcon("copy.png"),tr("Copy"));
- action->setProperty("index", CURVE_COPY);
-
- action = myMenu.addAction(CompanionIcon("paste.png"),tr("Paste"));
- if (!mimeData->hasFormat("application/x-companion-curve-item")) {
- action->setEnabled(false);
- }
- action->setProperty("index", CURVE_PASTE);
-
- action = myMenu.addAction(CompanionIcon("clear.png"),tr("Clear"));
- action->setProperty("index", CURVE_RESET);
- action = myMenu.addAction(CompanionIcon("clear.png"),tr("Clear all curves"));
- action->setProperty("index", CURVE_RESETALL);
-
- QAction* selectedItem = myMenu.exec(globalPos);
- if (selectedItem) {
- int action=selectedItem->property("index").toInt();
- if (action==CURVE_COPY) {
- QByteArray curveData;
- QMimeData *mimeData2 = new QMimeData;
- curveData.append((char*)&model->curves[index], sizeof(CurveData));
- mimeData2->setData("application/x-companion-curve-item", curveData);
- QApplication::clipboard()->setMimeData(mimeData2, QClipboard::Clipboard);
- }
- else if (action==CURVE_PASTE) {
- QByteArray curveData = mimeData->data("application/x-companion-curve-item");
- CurveData *curve = &model->curves[index];
- memcpy(curve, curveData.constData(), sizeof(CurveData));
- update();
- emit modified();
- }
- else if (action==CURVE_RESET) {
- int res = QMessageBox::question(this, "companion", tr("Are you sure you want to reset curve %1?").arg(index+1), QMessageBox::Yes | QMessageBox::No);
- if (res == QMessageBox::Yes) {
- model->curves[index].clear(5);
- update();
- emit modified();
- }
- }
- else if (action==CURVE_RESETALL) {
- int res = QMessageBox::question(this, "companion", tr("Are you sure you want to reset all curves?"), QMessageBox::Yes | QMessageBox::No);
- if (res == QMessageBox::Yes) {
- int numcurves = firmware->getCapability(NumCurves);
- for (int i=0; icurves[i].clear(5);
- }
- update();
- emit modified();
- }
- }
- }
-}
-
void Curves::onPointSizeEdited()
{
if (!lock) {
@@ -690,7 +631,7 @@ void Curves::onSceneNewPoint(int x, int y)
newidx = numpoints;
}
else {
- for (int i=0; icurves[currentCurve].points[i].x) {
newidx = i;
break;
@@ -699,8 +640,8 @@ void Curves::onSceneNewPoint(int x, int y)
}
numpoints++;
model->curves[currentCurve].count = numpoints;
- for (int idx=(numpoints-1); idx>(newidx); idx--) {
- model->curves[currentCurve].points[idx] = model->curves[currentCurve].points[idx-1];
+ for (int idx = (numpoints - 1); idx > newidx; idx--) {
+ model->curves[currentCurve].points[idx] = model->curves[currentCurve].points[idx - 1];
}
model->curves[currentCurve].points[newidx].x = x;
model->curves[currentCurve].points[newidx].y = y;
@@ -709,6 +650,150 @@ void Curves::onSceneNewPoint(int x, int y)
}
}
+void Curves::onCustomContextMenuRequested(QPoint pos)
+{
+ QPushButton *button = (QPushButton *)sender();
+ selectedIndex = button->property("index").toInt();
+ QPoint globalPos = button->mapToGlobal(pos);
+
+ QMenu contextMenu;
+ contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(cmCopy()));
+ contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(cmCut()));
+ contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(cmPaste()))->setEnabled(hasClipboardData());
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmClear()));
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmInsert()))->setEnabled(insertAllowed());
+ contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmDelete()));
+ contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
+ contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(cmClearAll()));
+
+ contextMenu.exec(globalPos);
+}
+
+bool Curves::hasClipboardData(QByteArray * data) const
+{
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat(MIMETYPE_CURVE)) {
+ if (data)
+ data->append(mimeData->data(MIMETYPE_CURVE));
+ return true;
+ }
+ return false;
+}
+
+bool Curves::insertAllowed() const
+{
+ return ((selectedIndex < maxCurves - 1) && (model->curves[maxCurves - 1].isEmpty()));
+}
+
+bool Curves::moveDownAllowed() const
+{
+ return selectedIndex < maxCurves - 1;
+}
+
+bool Curves::moveUpAllowed() const
+{
+ return selectedIndex > 0;
+}
+
+void Curves::cmClear()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ model->curves[selectedIndex].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
+ update();
+ emit modified();
+}
+
+void Curves::cmClearAll()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Curves. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ for (int i = 0; i < maxCurves; i++) {
+ model->curves[i].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, i);
+ }
+ update();
+ emit modified();
+}
+
+void Curves::cmCopy()
+{
+ QByteArray data;
+ data.append((char*)&model->curves[selectedIndex], sizeof(CurveData));
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData(MIMETYPE_CURVE, data);
+ QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
+}
+
+void Curves::cmCut()
+{
+ cmCopy();
+ cmClear();
+}
+
+void Curves::cmDelete()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ memmove(&model->curves[selectedIndex], &model->curves[selectedIndex + 1], (CPN_MAX_CURVES - (selectedIndex + 1)) * sizeof(CurveData));
+ model->curves[maxCurves - 1].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
+ update();
+ emit modified();
+}
+
+void Curves::cmInsert()
+{
+ memmove(&model->curves[selectedIndex + 1], &model->curves[selectedIndex], (CPN_MAX_CURVES - (selectedIndex + 1)) * sizeof(CurveData));
+ model->curves[selectedIndex].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
+ update();
+ emit modified();
+}
+
+void Curves::cmMoveDown()
+{
+ swapData(selectedIndex, selectedIndex + 1);
+}
+
+void Curves::cmMoveUp()
+{
+ swapData(selectedIndex, selectedIndex - 1);
+}
+
+void Curves::cmPaste()
+{
+ QByteArray data;
+ if (hasClipboardData(&data)) {
+ CurveData *cd = &model->curves[selectedIndex];
+ memcpy(cd, data.constData(), sizeof(CurveData));
+ update();
+ emit modified();
+ }
+}
+
+void Curves::swapData(int idx1, int idx2)
+{
+ if ((idx1 != idx2) && (!model->curves[idx1].isEmpty() || !model->curves[idx2].isEmpty())) {
+ CurveData cdtmp = model->curves[idx2];
+ CurveData *cd1 = &model->curves[idx1];
+ CurveData *cd2 = &model->curves[idx2];
+ memcpy(cd2, cd1, sizeof(CurveData));
+ memcpy(cd1, &cdtmp, sizeof(CurveData));
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
+ update();
+ emit modified();
+ }
+}
+
CustomScene::CustomScene(QGraphicsView * view) :
QGraphicsScene(view)
{
diff --git a/companion/src/modeledit/curves.h b/companion/src/modeledit/curves.h
index a65ba8872..d9a5364a6 100644
--- a/companion/src/modeledit/curves.h
+++ b/companion/src/modeledit/curves.h
@@ -26,12 +26,7 @@
#include
#include
-enum CopyAction {
- CURVE_COPY,
- CURVE_PASTE,
- CURVE_RESET,
- CURVE_RESETALL
-};
+constexpr char MIMETYPE_CURVE[] = "application/x-companion-curve";
namespace Ui {
class Curves;
@@ -71,7 +66,6 @@ class Curves : public ModelPanel
private slots:
void editCurve();
- void ShowContextMenu(const QPoint& pos);
void plotCurve(bool checked);
void on_curveName_editingFinished();
void on_curvePoints_currentIndexChanged(int index);
@@ -86,6 +80,16 @@ class Curves : public ModelPanel
void onSceneNewPoint(int x, int y);
void onPointSizeEdited();
void onNodeDelete();
+ void onCustomContextMenuRequested(QPoint pos);
+ void cmClear();
+ void cmClearAll();
+ void cmCopy();
+ void cmCut();
+ void cmDelete();
+ void cmInsert();
+ void cmPaste();
+ void cmMoveDown();
+ void cmMoveUp();
protected:
virtual void resizeEvent(QResizeEvent *event);
@@ -105,6 +109,16 @@ class Curves : public ModelPanel
bool allowCurveType(int points, CurveData::CurveType type);
void setPointY(int i, int x, int y);
CustomScene * scene;
+ int maxCurves;
+ int hasNames;
+ int hasEnhanced;
+ int maxPoints;
+ int selectedIndex;
+ bool hasClipboardData(QByteArray * data = nullptr) const;
+ bool insertAllowed() const;
+ bool moveDownAllowed() const;
+ bool moveUpAllowed() const;
+ void swapData(int idx1, int idx2);
};
#endif // _CURVES_H_
diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp
index c30454bdc..6b8456eb2 100644
--- a/companion/src/modeledit/customfunctions.cpp
+++ b/companion/src/modeledit/customfunctions.cpp
@@ -29,7 +29,7 @@ RepeatComboBox::RepeatComboBox(QWidget *parent, int & repeatParam):
QComboBox(parent),
repeatParam(repeatParam)
{
- unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10;
+ unsigned int step = 1;
int value = repeatParam/step;
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
@@ -58,7 +58,7 @@ void RepeatComboBox::onIndexChanged(int index)
void RepeatComboBox::update()
{
- unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10;
+ unsigned int step = 1;
int value = repeatParam/step;
if (step == 1) {
value++;
@@ -70,7 +70,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
GenericPanel(parent, model, generalSettings, firmware),
functions(model ? model->customFn : generalSettings.customFn),
mediaPlayerCurrent(-1),
- mediaPlayer(NULL)
+ mediaPlayer(nullptr)
{
Stopwatch s1("CustomFunctionsPanel - populate");
lock = true;
@@ -84,7 +84,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
if (!firmware->getCapability(VoicesAsNumbers)) {
tracksSet = getFilesSet(getSoundsPath(generalSettings), QStringList() << "*.wav" << "*.WAV", firmware->getCapability(VoicesMaxLength));
for (int i=0; igetBoard())) {
scriptsSet = getFilesSet(g.profile[g.id()].sdPath() + "/SCRIPTS/FUNCTIONS", QStringList() << "*.lua", firmware->getCapability(VoicesMaxLength));
for (int i=0; isetText(tr("GF%1").arg(i+1));
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
- connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(fsw_customContextMenuRequested(QPoint)));
+ connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint)));
tableLayout->addWidget(i, 0, label);
// s1.report("label");
@@ -389,7 +389,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
if (!cfn.isEmpty()) {
widgetsMask |= CUSTOM_FUNCTION_SHOW_FUNC;
- if (func>=FuncOverrideCH1 && func<=FuncOverrideCH32) {
+ if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) {
if (model) {
int channelsMax = model->getChannelsMax(true);
fswtchParam[i]->setDecimals(0);
@@ -403,7 +403,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_ENABLE;
}
}
- else if (func==FuncLogs) {
+ else if (func == FuncLogs) {
fswtchParam[i]->setDecimals(1);
fswtchParam[i]->setMinimum(0);
fswtchParam[i]->setMaximum(25.5);
@@ -413,38 +413,29 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
fswtchParam[i]->setValue(cfn.param/10.0);
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM;
}
- else if (func>=FuncAdjustGV1 && func<=FuncAdjustGVLast) {
+ else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) {
int gvidx = func - FuncAdjustGV1;
if (modified)
cfn.adjustMode = fswtchGVmode[i]->currentIndex();
fswtchGVmode[i]->setCurrentIndex(cfn.adjustMode);
widgetsMask |= CUSTOM_FUNCTION_GV_MODE | CUSTOM_FUNCTION_ENABLE;
- if (cfn.adjustMode==FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode==FUNC_ADJUST_GVAR_INCDEC) {
+ if (cfn.adjustMode == FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) {
if (modified)
cfn.param = fswtchParam[i]->value() * model->gvarData[gvidx].multiplierSet();
- if (IS_ARM(getCurrentBoard())) {
- fswtchParam[i]->setDecimals(model->gvarData[gvidx].prec);
- fswtchParam[i]->setSingleStep(model->gvarData[gvidx].multiplierGet());
- fswtchParam[i]->setSuffix(model->gvarData[gvidx].unitToString());
- if (cfn.adjustMode==FUNC_ADJUST_GVAR_INCDEC) {
- double rng = abs(model->gvarData[gvidx].getMax() - model->gvarData[gvidx].getMin());
- rng *= model->gvarData[gvidx].multiplierGet();
- fswtchParam[i]->setMinimum(-rng);
- fswtchParam[i]->setMaximum(rng);
- }
- else {
- fswtchParam[i]->setMinimum(model->gvarData[gvidx].getMinPrec());
- fswtchParam[i]->setMaximum(model->gvarData[gvidx].getMaxPrec());
- }
- fswtchParam[i]->setValue(cfn.param * model->gvarData[gvidx].multiplierGet());
+ fswtchParam[i]->setDecimals(model->gvarData[gvidx].prec);
+ fswtchParam[i]->setSingleStep(model->gvarData[gvidx].multiplierGet());
+ fswtchParam[i]->setSuffix(model->gvarData[gvidx].unitToString());
+ if (cfn.adjustMode==FUNC_ADJUST_GVAR_INCDEC) {
+ double rng = abs(model->gvarData[gvidx].getMax() - model->gvarData[gvidx].getMin());
+ rng *= model->gvarData[gvidx].multiplierGet();
+ fswtchParam[i]->setMinimum(-rng);
+ fswtchParam[i]->setMaximum(rng);
}
else {
- fswtchParam[i]->setDecimals(0);
- fswtchParam[i]->setSingleStep(1);
- fswtchParam[i]->setMinimum(-125);
- fswtchParam[i]->setMaximum(125);
- fswtchParam[i]->setValue(cfn.param);
+ fswtchParam[i]->setMinimum(model->gvarData[gvidx].getMinPrec());
+ fswtchParam[i]->setMaximum(model->gvarData[gvidx].getMaxPrec());
}
+ fswtchParam[i]->setValue(cfn.param * model->gvarData[gvidx].multiplierGet());
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM;
}
else {
@@ -454,13 +445,13 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM;
}
}
- else if (func==FuncReset) {
+ else if (func == FuncReset) {
if (modified)
cfn.param = fswtchParamT[i]->currentData().toInt();
populateFuncParamCB(fswtchParamT[i], func, cfn.param);
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_ENABLE;
}
- else if (func>=FuncSetTimer1 && func<=FuncSetTimer3) {
+ else if (func >= FuncSetTimer1 && func <= FuncSetTimer3) {
if (modified)
cfn.param = fswtchParamTime[i]->timeInSeconds();
RawSourceRange range = RawSource(SOURCE_TYPE_SPECIAL, func - FuncSetTimer1 + 2).getRange(model, generalSettings);
@@ -468,39 +459,39 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
fswtchParamTime[i]->setTime(cfn.param);
widgetsMask |= CUSTOM_FUNCTION_TIME_PARAM | CUSTOM_FUNCTION_ENABLE;
}
- else if (func>=FuncSetFailsafeInternalModule && func<=FuncBindExternalModule) {
+ else if (func >= FuncSetFailsafeInternalModule && func <= FuncBindExternalModule) {
widgetsMask |= CUSTOM_FUNCTION_ENABLE;
}
- else if (func==FuncVolume) {
+ else if (func == FuncVolume) {
if (modified)
cfn.param = fswtchParamT[i]->currentData().toInt();
populateFuncParamCB(fswtchParamT[i], func, cfn.param);
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_ENABLE;
}
- else if (func==FuncPlaySound || func==FuncPlayHaptic || func==FuncPlayValue || func==FuncPlayPrompt || func==FuncPlayBoth || func==FuncBackgroundMusic) {
+ else if (func == FuncPlaySound || func == FuncPlayHaptic || func == FuncPlayValue || func == FuncPlayPrompt || func == FuncPlayBoth || func == FuncBackgroundMusic) {
if (func != FuncBackgroundMusic) {
widgetsMask |= CUSTOM_FUNCTION_REPEAT;
fswtchRepeat[i]->update();
}
- if (func==FuncPlayValue) {
+ if (func == FuncPlayValue) {
if (modified)
cfn.param = fswtchParamT[i]->currentData().toInt();
populateFuncParamCB(fswtchParamT[i], func, cfn.param);
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_REPEAT;
}
- else if (func==FuncPlayPrompt || func==FuncPlayBoth) {
+ else if (func == FuncPlayPrompt || func == FuncPlayBoth) {
if (firmware->getCapability(VoicesAsNumbers)) {
fswtchParam[i]->setDecimals(0);
fswtchParam[i]->setSingleStep(1);
fswtchParam[i]->setMinimum(0);
- if (func==FuncPlayPrompt) {
+ if (func == FuncPlayPrompt) {
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_REPEAT | CUSTOM_FUNCTION_GV_TOOGLE;
}
else {
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_REPEAT;
fswtchParamGV[i]->setChecked(false);
}
- fswtchParam[i]->setMaximum(func==FuncPlayBoth ? 254 : 255);
+ fswtchParam[i]->setMaximum(func == FuncPlayBoth ? 254 : 255);
if (modified) {
if (fswtchParamGV[i]->isChecked()) {
fswtchParam[i]->setMinimum(1);
@@ -533,7 +524,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
}
}
}
- else if (func==FuncBackgroundMusic) {
+ else if (func == FuncBackgroundMusic) {
widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM;
if (modified) {
Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, firmware->getCapability(VoicesMaxLength));
@@ -543,27 +534,27 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
widgetsMask |= CUSTOM_FUNCTION_PLAY;
}
}
- else if (func==FuncPlaySound) {
+ else if (func == FuncPlaySound) {
if (modified)
cfn.param = (uint8_t)fswtchParamT[i]->currentIndex();
populateFuncParamCB(fswtchParamT[i], func, cfn.param);
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM;
}
- else if (func==FuncPlayHaptic) {
+ else if (func == FuncPlayHaptic) {
if (modified)
cfn.param = (uint8_t)fswtchParamT[i]->currentIndex();
populateFuncParamCB(fswtchParamT[i], func, cfn.param);
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM;
}
}
- else if (func==FuncPlayScript) {
+ else if (func == FuncPlayScript) {
widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM;
if (modified) {
Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, 8);
}
Helpers::populateFileComboBox(fswtchParamArmT[i], scriptsSet, cfn.paramarm);
}
- else if (func==FuncBacklight && IS_TARANIS_PLUS(getCurrentBoard())) {
+ else if (func == FuncBacklight && IS_TARANIS_PLUS(getCurrentBoard())) {
if (modified)
cfn.param = (uint8_t)fswtchBLcolor[i]->value();
fswtchBLcolor[i]->setValue(cfn.param);
@@ -608,76 +599,63 @@ void CustomFunctionsPanel::update()
lock = false;
}
-void CustomFunctionsPanel::fswPaste()
+void CustomFunctionsPanel::cmPaste()
{
- const QClipboard *clipboard = QApplication::clipboard();
- const QMimeData *mimeData = clipboard->mimeData();
- if (mimeData->hasFormat(MIMETYPE_FSW)) {
- QByteArray fswData = mimeData->data(MIMETYPE_FSW);
- CustomFunctionData *fsw = &functions[selectedFunction];
- memcpy(fsw, fswData.constData(), sizeof(CustomFunctionData));
- resetCBsAndRefresh(selectedFunction);
+ QByteArray data;
+ if (hasClipboardData(&data)) {
+ memcpy(&functions[selectedIndex], data.constData(), sizeof(CustomFunctionData));
+ resetCBsAndRefresh(selectedIndex);
emit modified();
}
}
-void CustomFunctionsPanel::fswDelete()
+void CustomFunctionsPanel::cmDelete()
{
- int maxidx = fswCapability - 1;
- for (int i=selectedFunction; isetData(MIMETYPE_FSW, fswData);
+ mimeData->setData(MIMETYPE_CUSTOM_FUNCTION, data);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
}
-void CustomFunctionsPanel::fswCut()
+void CustomFunctionsPanel::cmCut()
{
- fswCopy();
- fswClear();
+ cmCopy();
+ cmClear();
}
-void CustomFunctionsPanel::fsw_customContextMenuRequested(QPoint pos)
+void CustomFunctionsPanel::onCustomContextMenuRequested(QPoint pos)
{
QLabel *label = (QLabel *)sender();
- selectedFunction = label->property("index").toInt();
-
+ selectedIndex = label->property("index").toInt();
QPoint globalPos = label->mapToGlobal(pos);
- const QClipboard *clipboard = QApplication::clipboard();
- const QMimeData *mimeData = clipboard->mimeData();
- bool hasData = mimeData->hasFormat(MIMETYPE_FSW);
- bool moveUpAllowed = (selectedFunction > 0);
- bool moveDownAllowed = (selectedFunction < (fswCapability - 1));
- bool insertAllowed = (selectedFunction < (fswCapability - 1)) && (functions[fswCapability - 1].isEmpty());
-
QMenu contextMenu;
- contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(fswCopy()));
- contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(fswCut()));
- contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(fswPaste()))->setEnabled(hasData);
- contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(fswClear()));
+ contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(cmCopy()));
+ contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(cmCut()));
+ contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData());
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear()));
contextMenu.addSeparator();
- contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(fswInsert()))->setEnabled(insertAllowed);
- contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(fswDelete()));
- contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(fswMoveUp()))->setEnabled(moveUpAllowed);
- contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(fswMoveDown()))->setEnabled(moveDownAllowed);
+ contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(cmInsert()))->setEnabled(insertAllowed());
+ contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(cmDelete()));
+ contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
+ contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
contextMenu.addSeparator();
- contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(fswClearAll()));
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll()));
contextMenu.exec(globalPos);
}
@@ -692,7 +670,6 @@ void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value)
((i==FuncPlayHaptic) && !firmware->getCapability(Haptic)) ||
((i==FuncPlayBoth) && !firmware->getCapability(HasBeeper)) ||
((i==FuncLogs) && !firmware->getCapability(HasSDLogs)) ||
- ((i==FuncSetTimer1 || i==FuncSetTimer2) && !IS_ARM(firmware->getBoard())) ||
((i==FuncSetTimer3) && firmware->getCapability(Timers) < 3) ||
((i==FuncScreenshot) && !IS_HORUS_OR_TARANIS(firmware->getBoard())) ||
((i>=FuncRangeCheckInternalModule && i<=FuncBindExternalModule) && (!model || !firmware->getCapability(DangerousFunctions))) ||
@@ -762,25 +739,31 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi
}
}
-void CustomFunctionsPanel::fswMoveUp()
+void CustomFunctionsPanel::cmMoveUp()
{
- swapFuncData(selectedFunction, selectedFunction - 1);
+ swapData(selectedIndex, selectedIndex - 1);
}
-void CustomFunctionsPanel::fswMoveDown()
+void CustomFunctionsPanel::cmMoveDown()
{
- swapFuncData(selectedFunction, selectedFunction + 1);
+ swapData(selectedIndex, selectedIndex + 1);
}
-void CustomFunctionsPanel::fswClear()
+void CustomFunctionsPanel::cmClear()
{
- functions[selectedFunction].clear();
- resetCBsAndRefresh(selectedFunction);
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Special Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ functions[selectedIndex].clear();
+ resetCBsAndRefresh(selectedIndex);
emit modified();
}
-void CustomFunctionsPanel::fswClearAll()
+void CustomFunctionsPanel::cmClearAll()
{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Special Functions. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
for (int i=0; iselectedFunction; i--) {
- if (!functions[i].isEmpty() || !functions[i-1].isEmpty()) {
- memcpy(&functions[i], &functions[i-1], sizeof(CustomFunctionData));
- resetCBsAndRefresh(i);
- }
+ memmove(&functions[selectedIndex + 1], &functions[selectedIndex], (CPN_MAX_SPECIAL_FUNCTIONS - (selectedIndex + 1)) * sizeof(CustomFunctionData));
+ functions[selectedIndex].clear();
+
+ for (int i = selectedIndex; i < (fswCapability - 1); i++) {
+ resetCBsAndRefresh(i);
}
- fswClear();
}
-void CustomFunctionsPanel::swapFuncData(int idx1, int idx2)
+void CustomFunctionsPanel::swapData(int idx1, int idx2)
{
if ((idx1 != idx2) && (!functions[idx1].isEmpty() || !functions[idx2].isEmpty())) {
CustomFunctionData fswtmp = functions[idx2];
@@ -823,3 +805,30 @@ void CustomFunctionsPanel::resetCBsAndRefresh(int idx)
refreshCustomFunction(idx);
lock = false;
}
+
+bool CustomFunctionsPanel::hasClipboardData(QByteArray * data) const
+{
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat(MIMETYPE_CUSTOM_FUNCTION)) {
+ if (data)
+ data->append(mimeData->data(MIMETYPE_CUSTOM_FUNCTION));
+ return true;
+ }
+ return false;
+}
+
+bool CustomFunctionsPanel::insertAllowed() const
+{
+ return ((selectedIndex < fswCapability - 1) && (model->curves[fswCapability - 1].isEmpty()));
+}
+
+bool CustomFunctionsPanel::moveDownAllowed() const
+{
+ return selectedIndex < fswCapability - 1;
+}
+
+bool CustomFunctionsPanel::moveUpAllowed() const
+{
+ return selectedIndex > 0;
+}
diff --git a/companion/src/modeledit/customfunctions.h b/companion/src/modeledit/customfunctions.h
index fd257ce98..1c93f3e96 100644
--- a/companion/src/modeledit/customfunctions.h
+++ b/companion/src/modeledit/customfunctions.h
@@ -30,7 +30,7 @@ class RawSourceFilterItemModel;
class RawSwitchFilterItemModel;
class TimerEdit;
-constexpr char MIMETYPE_FSW[] = "application/x-companion-fsw";
+constexpr char MIMETYPE_CUSTOM_FUNCTION[] = "application/x-companion-custom-function";
class RepeatComboBox: public QComboBox
{
@@ -67,7 +67,7 @@ class CustomFunctionsPanel : public GenericPanel
void updateDataModels();
void customFunctionEdited();
void functionEdited();
- void fsw_customContextMenuRequested(QPoint pos);
+ void onCustomContextMenuRequested(QPoint pos);
void refreshCustomFunction(int index, bool modified=false);
void onChildModified();
bool playSound(int index);
@@ -75,21 +75,25 @@ class CustomFunctionsPanel : public GenericPanel
void toggleSound(bool play);
void onMediaPlayerStateChanged(QMediaPlayer::State state);
void onMediaPlayerError(QMediaPlayer::Error error);
- void fswDelete();
- void fswCopy();
- void fswPaste();
- void fswCut();
- void fswMoveUp();
- void fswMoveDown();
- void fswInsert();
- void fswClear();
- void fswClearAll();
+ void cmDelete();
+ void cmCopy();
+ void cmPaste();
+ void cmCut();
+ void cmMoveUp();
+ void cmMoveDown();
+ void cmInsert();
+ void cmClear();
+ void cmClearAll();
private:
void populateFuncCB(QComboBox *b, unsigned int value);
void populateGVmodeCB(QComboBox *b, unsigned int value);
void populateFuncParamCB(QComboBox *b, uint function, unsigned int value, unsigned int adjustmode=0);
- void swapFuncData(int idx1, int idx2);
+ bool hasClipboardData(QByteArray * data = nullptr) const;
+ bool insertAllowed() const;
+ bool moveDownAllowed() const;
+ bool moveUpAllowed() const;
+ void swapData(int idx1, int idx2);
void resetCBsAndRefresh(int idx);
RawSwitchFilterItemModel * rawSwitchItemModel;
RawSourceFilterItemModel * rawSrcAllItemModel;
@@ -113,7 +117,7 @@ class CustomFunctionsPanel : public GenericPanel
QSlider * fswtchBLcolor[CPN_MAX_SPECIAL_FUNCTIONS];
QMediaPlayer * mediaPlayer;
- int selectedFunction;
+ int selectedIndex;
int fswCapability;
};
diff --git a/companion/src/modeledit/expodialog.cpp b/companion/src/modeledit/expodialog.cpp
index 0745f5c84..95aaeca66 100644
--- a/companion/src/modeledit/expodialog.cpp
+++ b/companion/src/modeledit/expodialog.cpp
@@ -46,18 +46,8 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
setWindowTitle(tr("Edit %1").arg(RawSource(srcType, ed->chn).toString(&model, &generalSettings)));
QRegExp rx(CHAR_FOR_NAMES_REGEX);
- if (IS_ARM(getCurrentBoard())) {
- gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100);
- gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100);
- }
- else {
- gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, 0, 100);
- gvOffsetGroup = NULL;
- ui->offsetLabel->hide();
- ui->offsetGV->hide();
- ui->offsetSB->hide();
- ui->offsetCB->hide();
- }
+ gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100);
+ gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100);
curveGroup = new CurveGroup(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB, ed->curve, model,
firmware->getCapability(HasInputDiff) ? 0 : (HIDE_DIFF | HIDE_NEGATIVE_CURVES));
diff --git a/companion/src/modeledit/flightmode.ui b/companion/src/modeledit/flightmode.ui
index ab279a437..f3dff650e 100644
--- a/companion/src/modeledit/flightmode.ui
+++ b/companion/src/modeledit/flightmode.ui
@@ -58,7 +58,7 @@
- -
+
-
Qt::Horizontal
@@ -85,24 +85,18 @@
-
-
-
-
-
-
- 0
- 0
-
-
+
-
+
Qt::Horizontal
-
- QSlider::TicksBothSides
+
+
+ 40
+ 20
+
-
- 25
-
-
+
-
@@ -136,25 +130,6 @@
- -
-
-
-
- 0
- 0
-
-
-
- Qt::Horizontal
-
-
- QSlider::TicksBothSides
-
-
- 25
-
-
-
-
@@ -166,16 +141,6 @@
-
-
-
-
-
- trim1
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
-
@@ -284,11 +249,59 @@
+ -
+
+
+ trim1
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBothSides
+
+
+ 25
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBothSides
+
+
+ 25
+
+
+
-
@@ -299,7 +312,7 @@
-
-
+
-
@@ -310,65 +323,6 @@
- -
-
-
- trim3
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- -
-
-
- Qt::AlignCenter
-
-
- true
-
-
- -896
-
-
- 896
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
@@ -418,23 +372,201 @@
+ -
+
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ -
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+ -896
+
+
+ 896
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+ -
+
+
+ trim3
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
- -
-
+
-
+
+
-
+
+
+ trim6
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
-
+
+
+ -
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+ -896
+
+
+ 896
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Minimum
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+ -
+
Qt::Horizontal
-
-
- 40
- 20
-
+
+ QSlider::TicksBothSides
-
+
+ 25
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBothSides
+
+
+ 25
+
+
+
+ -
+
+
-
+
+
+ trim5
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
-
+
+
+ -
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+ -896
+
+
+ 896
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Minimum
+
+
+
+ 20
+ 40
+
+
+
+
+
diff --git a/companion/src/modeledit/flightmodes.cpp b/companion/src/modeledit/flightmodes.cpp
index e1b01c1a9..1634aed3a 100644
--- a/companion/src/modeledit/flightmodes.cpp
+++ b/companion/src/modeledit/flightmodes.cpp
@@ -29,21 +29,23 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
ui(new Ui::FlightMode),
phaseIdx(phaseIdx),
phase(model.flightModeData[phaseIdx]),
- reCount(firmware->getCapability(RotaryEncoders)),
- gvCount(firmware->getCapability(Gvars)),
rawSwitchItemModel(NULL)
{
ui->setupUi(this);
ui->labelName->setContextMenuPolicy(Qt::CustomContextMenu);
ui->labelName->setToolTip(tr("Popup menu available"));
- connect(ui->labelName, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(name_customContextMenuRequested(const QPoint &)));
+ connect(ui->labelName, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onCustomContextMenuRequested(const QPoint &)));
- int modesCount = firmware->getCapability(FlightModes);
+ board = getCurrentBoard();
+ fmCount = firmware->getCapability(FlightModes);
+ gvCount = firmware->getCapability(Gvars);
+ reCount = firmware->getCapability(RotaryEncoders);
+ trimCount = Boards::getCapability(board, Board::NumTrims);
// Flight mode name
QRegExp rx(CHAR_FOR_NAMES_REGEX);
- if (modesCount) {
+ if (fmCount) {
ui->name->setValidator(new QRegExpValidator(rx, this));
ui->name->setMaxLength(firmware->getCapability(FlightModesName));
connect(ui->name, SIGNAL(editingFinished()), this, SLOT(phaseName_editingFinished()));
@@ -65,13 +67,13 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
if (firmware->getCapability(FlightModesHaveFades)) {
int scale = firmware->getCapability(SlowScale);
int range = firmware->getCapability(SlowRange);
- ui->fadeIn->setMaximum(float(range)/scale);
- ui->fadeIn->setSingleStep(1.0/scale);
- ui->fadeIn->setDecimals((scale==1 ? 0 :1) );
+ ui->fadeIn->setMaximum(float(range) / scale);
+ ui->fadeIn->setSingleStep(1.0 / scale);
+ ui->fadeIn->setDecimals((scale == 1 ? 0 :1) );
connect(ui->fadeIn, SIGNAL(editingFinished()), this, SLOT(phaseFadeIn_editingFinished()));
- ui->fadeOut->setMaximum(float(range)/scale);
- ui->fadeOut->setSingleStep(1.0/scale);
- ui->fadeOut->setDecimals((scale==1 ? 0 :1));
+ ui->fadeOut->setMaximum(float(range) / scale);
+ ui->fadeOut->setSingleStep(1.0 / scale);
+ ui->fadeOut->setDecimals((scale == 1 ? 0 :1));
connect(ui->fadeOut, SIGNAL(editingFinished()), this, SLOT(phaseFadeOut_editingFinished()));
}
else {
@@ -80,71 +82,83 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
}
// The trims
- QString labels[CPN_MAX_STICKS];
- for(int i=0; i < CPN_MAX_STICKS; i++) {
+ QString labels[CPN_MAX_TRIMS];
+ for(int i = 0; i < CPN_MAX_STICKS; i++) {
labels[i] = firmware->getAnalogInputName(i);
}
+ labels[4] = "T5"; // TODO firmware function
+ labels[5] = "T6"; // TODO firmware function
+ trimsLabel << ui->trim1Label << ui->trim2Label << ui->trim3Label << ui->trim4Label << ui->trim5Label << ui->trim6Label;
+ trimsUse << ui->trim1Use << ui->trim2Use << ui->trim3Use << ui->trim4Use << ui->trim5Use << ui->trim6Use;
+ trimsValue << ui->trim1Value << ui->trim2Value << ui->trim3Value << ui->trim4Value << ui->trim5Value << ui->trim6Value;
+ trimsSlider << ui->trim1Slider << ui->trim2Slider << ui->trim3Slider << ui->trim4Slider << ui->trim5Slider << ui->trim6Slider;
- trimsLabel << ui->trim1Label << ui->trim2Label << ui->trim3Label << ui->trim4Label;
- trimsUse << ui->trim1Use << ui->trim2Use << ui->trim3Use << ui->trim4Use;
- trimsValue << ui->trim1Value << ui->trim2Value << ui->trim3Value << ui->trim4Value;
- trimsSlider << ui->trim1Slider << ui->trim2Slider << ui->trim3Slider << ui->trim4Slider;
-
- Board::Type board = firmware->getBoard();
-
- for (int i=0; i<4; i++) {
- trimsLabel[i]->setText(labels[CONVERT_MODE(i+1)-1]);
+ for (int i = trimCount; i < CPN_MAX_TRIMS; i++) {
+ trimsLabel[i]->hide();
+ trimsUse[i]->hide();
+ trimsValue[i]->hide();
+ trimsSlider[i]->hide();
+ }
+ for (int i = 0; i < trimCount; i++) {
+ trimsLabel[i]->setText(labels[CONVERT_MODE(i + 1) - 1]);
QComboBox * cb = trimsUse[i];
cb->setProperty("index", i);
if (IS_HORUS_OR_TARANIS(board)) {
cb->addItem(tr("Trim disabled"), -1);
}
- for (int m=0; maddItem(tr("Own Trim"), m*2);
+ cb->addItem(tr("Own Trim"), m * 2);
}
else if (phaseIdx > 0) {
- cb->addItem(tr("Use Trim from Flight mode %1").arg(m), m*2);
+ cb->addItem(tr("Use Trim from Flight mode %1").arg(m), m * 2);
if (IS_HORUS_OR_TARANIS(board)) {
- cb->addItem(tr("Use Trim from Flight mode %1 + Own Trim as an offset").arg(m), m*2+1);
+ cb->addItem(tr("Use Trim from Flight mode %1 + Own Trim as an offset").arg(m), m * 2 + 1);
}
}
}
connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(phaseTrimUse_currentIndexChanged(int)));
+ int trimsMax = firmware->getCapability(ExtendedTrimsRange);
+ if (trimsMax == 0 || !model.extendedTrims) {
+ trimsMax = firmware->getCapability(TrimsRange);
+ }
+
trimsValue[i]->setProperty("index", i);
+ trimsValue[i]->setRange(-trimsMax, +trimsMax);
connect(trimsValue[i], SIGNAL(valueChanged(int)), this, SLOT(phaseTrim_valueChanged()));
trimsSlider[i]->setProperty("index", i);
+ trimsSlider[i]->setRange(-trimsMax, +trimsMax);
+ int chn = CONVERT_MODE(i + 1) - 1;
+ if (chn == 2/*TODO constant*/ && model.throttleReversed)
+ trimsSlider[i]->setInvertedAppearance(true);
connect(trimsSlider[i], SIGNAL(valueChanged(int)), this, SLOT(phaseTrimSlider_valueChanged()));
}
// Rotary encoders
if (reCount > 0) {
QGridLayout *reLayout = new QGridLayout(ui->reGB);
- for (int i=0; ireGB);
- label->setText(tr("Rotary Encoder %1").arg(i+1));
+ label->setText(tr("Rotary Encoder %1").arg(i + 1));
reLayout->addWidget(label, i, 0, 1, 1);
if (phaseIdx > 0) {
// RE link to another RE
reUse[i] = new QComboBox(ui->reGB);
reUse[i]->setProperty("index", i);
Helpers::populateGvarUseCB(reUse[i], phaseIdx);
- if (phase.rotaryEncoders[i] > 1024) {
- reUse[i]->setCurrentIndex(phase.rotaryEncoders[i] - 1024);
- }
connect(reUse[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseREUse_currentIndexChanged(int)));
reLayout->addWidget(reUse[i], i, 1, 1, 1);
}
// RE value
reValues[i] = new QSpinBox(ui->reGB);
reValues[i]->setProperty("index", i);
- reValues[i]->setMinimum(-1024);
- reValues[i]->setMaximum(1024);
+ reValues[i]->setMinimum(RENC_MIN_VALUE);
+ reValues[i]->setMaximum(RENC_MAX_VALUE);
connect(reValues[i], SIGNAL(editingFinished()), this, SLOT(phaseREValue_editingFinished()));
reLayout->addWidget(reValues[i], i, 2, 1, 1);
}
@@ -198,15 +212,16 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
gvLayout->addWidget(popupLabel, 0, headerCol++, 1, 1);
}
- for (int i=0; igvGB);
- label->setText(tr("GVAR%1").arg(i+1));
+ label->setText(tr("GVAR%1").arg(i + 1));
label->setProperty("index", i);
label->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(label, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(gvLabel_customContextMenuRequested(const QPoint &)));
- gvLayout->addWidget(label, i+1, col++, 1, 1);
+ label->setToolTip(tr("Popup menu available"));
+ connect(label, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(gvOnCustomContextMenuRequested(const QPoint &)));
+ gvLayout->addWidget(label, i + 1, col++, 1, 1);
// GVar name
int nameLen = firmware->getCapability(GvarsName);
if (nameLen > 0) {
@@ -214,24 +229,21 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
gvNames[i]->setProperty("index", i);
gvNames[i]->setMaxLength(nameLen);
connect(gvNames[i], SIGNAL(editingFinished()), this, SLOT(GVName_editingFinished()));
- gvLayout->addWidget(gvNames[i], i+1, col++, 1, 1);
+ gvLayout->addWidget(gvNames[i], i + 1, col++, 1, 1);
}
if (phaseIdx > 0) {
// GVar link to another GVar
gvUse[i] = new QComboBox(ui->gvGB);
gvUse[i]->setProperty("index", i);
Helpers::populateGvarUseCB(gvUse[i], phaseIdx);
- if (phase.gvars[i] > GVAR_MAX_VALUE) {
- gvUse[i]->setCurrentIndex(phase.gvars[i] - GVAR_MAX_VALUE);
- }
connect(gvUse[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVUse_currentIndexChanged(int)));
- gvLayout->addWidget(gvUse[i], i+1, col++, 1, 1);
+ gvLayout->addWidget(gvUse[i], i + 1, col++, 1, 1);
}
// GVar value
gvValues[i] = new QDoubleSpinBox(ui->gvGB);
gvValues[i]->setProperty("index", i);
connect(gvValues[i], SIGNAL(editingFinished()), this, SLOT(phaseGVValue_editingFinished()));
- gvLayout->addWidget(gvValues[i], i+1, col++, 1, 1);
+ gvLayout->addWidget(gvValues[i], i + 1, col++, 1, 1);
if (IS_HORUS_OR_TARANIS(board) && phaseIdx == 0) {
// GVar unit
@@ -239,33 +251,33 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
gvUnit[i]->setProperty("index", i);
populateGvarUnitCB(gvUnit[i]);
connect(gvUnit[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVUnit_currentIndexChanged(int)));
- gvLayout->addWidget(gvUnit[i], i+1, col++, 1, 1);
+ gvLayout->addWidget(gvUnit[i], i + 1, col++, 1, 1);
// GVar precision
gvPrec[i] = new QComboBox(ui->gvGB);
gvPrec[i]->setProperty("index", i);
populateGvarPrecCB(gvPrec[i]);
connect(gvPrec[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVPrec_currentIndexChanged(int)));
- gvLayout->addWidget(gvPrec[i], i+1, col++, 1, 1);
+ gvLayout->addWidget(gvPrec[i], i + 1, col++, 1, 1);
// GVar min
gvMin[i] = new QDoubleSpinBox(ui->gvGB);
gvMin[i]->setProperty("index", i);
connect(gvMin[i], SIGNAL(editingFinished()), this, SLOT(phaseGVMin_editingFinished()));
- gvLayout->addWidget(gvMin[i], i+1, col++, 1, 1);
+ gvLayout->addWidget(gvMin[i], i + 1, col++, 1, 1);
// GVar max
gvMax[i] = new QDoubleSpinBox(ui->gvGB);
gvMax[i]->setProperty("index", i);
connect(gvMax[i], SIGNAL(editingFinished()), this, SLOT(phaseGVMax_editingFinished()));
- gvLayout->addWidget(gvMax[i], i+1, col++, 1, 1);
+ gvLayout->addWidget(gvMax[i], i + 1, col++, 1, 1);
// Popups
gvPopups[i] = new QCheckBox(ui->gvGB);
gvPopups[i]->setProperty("index", i);
//gvPopups[i]->setText(tr("Popup enabled"));
connect(gvPopups[i], SIGNAL(toggled(bool)), this, SLOT(phaseGVPopupToggled(bool)));
- gvLayout->addWidget(gvPopups[i], i+1, col++, 1, 1);
+ gvLayout->addWidget(gvPopups[i], i + 1, col++, 1, 1);
}
}
}
@@ -293,46 +305,36 @@ void FlightModePanel::update()
ui->fadeIn->setValue(float(phase.fadeIn)/scale);
ui->fadeOut->setValue(float(phase.fadeOut)/scale);
- for (int i=0; i<4; i++) {
- int trimsMax = firmware->getCapability(ExtendedTrimsRange);
- if (trimsMax == 0 || !model->extendedTrims) {
- trimsMax = firmware->getCapability(TrimsRange);
- }
- trimsSlider[i]->setRange(-trimsMax, +trimsMax);
- trimsValue[i]->setRange(-trimsMax, +trimsMax);
- int chn = CONVERT_MODE(i+1)-1;
- if (chn == 2/*TODO constant*/ && model->throttleReversed)
- trimsSlider[i]->setInvertedAppearance(true);
+ for (int i = 0; i < getBoardCapability(firmware->getBoard(), Board::NumTrims); i++) {
trimUpdate(i);
}
- for (int i=0; isetDisabled(false);
- int idx = phase.rotaryEncoders[i];
- FlightModeData *phasere = &phase;
- while (idx > 1024) {
- int nextPhase = idx - 1025;
- if (nextPhase >= phaseIdx) nextPhase += 1;
- phasere = &model->flightModeData[nextPhase];
- idx = phasere->rotaryEncoders[i];
- reValues[i]->setDisabled(true);
- }
- reValues[i]->setValue(phasere->rotaryEncoders[i]);
+ for (int i = 0; i < reCount; i++) {
+ updateRotaryEncoder(i);
}
+
+ emit nameModified();
}
+
void FlightModePanel::updateGVar(int index)
{
lock = true;
if (firmware->getCapability(GvarsName) > 0) {
gvNames[index]->setText(model->gvarData[index].name);
}
+ if (phaseIdx > 0) {
+ if (model->isGVarLinked(phaseIdx, index))
+ gvUse[index]->setCurrentIndex(phase.gvars[index] - GVAR_MAX_VALUE);
+ else
+ gvUse[index]->setCurrentIndex(0);
+ }
gvValues[index]->setDisabled(model->isGVarLinked(phaseIdx, index));
- setGVSB(gvValues[index], model->gvarData[index].getMin(), model->gvarData[index].getMax(), model->getGVarFieldValue(phaseIdx, index));
- if (IS_HORUS_OR_TARANIS(getCurrentBoard()) && phaseIdx == 0) {
+ setGVSB(gvValues[index], model->gvarData[index].getMin(), model->gvarData[index].getMax(), model->getGVarValue(phaseIdx, index));
+ if (IS_HORUS_OR_TARANIS(board) && phaseIdx == 0) {
gvUnit[index]->setCurrentIndex(model->gvarData[index].unit);
gvPrec[index]->setCurrentIndex(model->gvarData[index].prec);
setGVSB(gvMin[index], GVAR_MIN_VALUE, model->gvarData[index].getMax(), model->gvarData[index].getMin());
@@ -354,6 +356,20 @@ void FlightModePanel::setGVSB(QDoubleSpinBox * sb, int min, int max, int val)
sb->setValue(val * mul);
}
+void FlightModePanel::updateRotaryEncoder(int index)
+{
+ lock = true;
+ if (phaseIdx > 0) {
+ if (model->isREncLinked(phaseIdx, index))
+ reUse[index]->setCurrentIndex(phase.rotaryEncoders[index] - RENC_MAX_VALUE);
+ else
+ reUse[index]->setCurrentIndex(0);
+ }
+ reValues[index]->setDisabled(model->isREncLinked(phaseIdx, index));
+ reValues[index]->setValue(model->getREncValue(phaseIdx, index));
+ lock = false;
+}
+
// TODO: pull units from GVarData
void FlightModePanel::populateGvarUnitCB(QComboBox * cb)
{
@@ -372,45 +388,44 @@ void FlightModePanel::populateGvarPrecCB(QComboBox * cb)
void FlightModePanel::phaseName_editingFinished()
{
- QLineEdit *lineEdit = qobject_cast(sender());
- strcpy(phase.name, lineEdit->text().toLatin1());
- emit modified();
- emit nameModified();
+ QLineEdit *lineEdit = qobject_cast(sender());
+ strcpy(phase.name, lineEdit->text().toLatin1());
+ emit modified();
+ emit nameModified();
}
void FlightModePanel::phaseSwitchChanged(int index)
{
- if (lock)
- return;
-
- bool ok;
- const RawSwitch rs(ui->swtch->itemData(index).toInt(&ok));
- if (ok && phase.swtch.toValue() != rs.toValue()) {
- phase.swtch = rs;
- emit modified();
+ if (!lock) {
+ bool ok;
+ const RawSwitch rs(ui->swtch->itemData(index).toInt(&ok));
+ if (ok && phase.swtch.toValue() != rs.toValue()) {
+ phase.swtch = rs;
+ emit modified();
+ }
}
}
void FlightModePanel::phaseFadeIn_editingFinished()
{
- QDoubleSpinBox *spinBox = qobject_cast(sender());
- int scale = firmware->getCapability(SlowScale);
- phase.fadeIn = round(spinBox->value()*scale);
- emit modified();
+ QDoubleSpinBox *spinBox = qobject_cast(sender());
+ int scale = firmware->getCapability(SlowScale);
+ phase.fadeIn = round(spinBox->value()*scale);
+ emit modified();
}
void FlightModePanel::phaseFadeOut_editingFinished()
{
- QDoubleSpinBox *spinBox = qobject_cast(sender());
- int scale = firmware->getCapability(SlowScale);
- phase.fadeOut = round(spinBox->value()*scale);
- emit modified();
+ QDoubleSpinBox *spinBox = qobject_cast(sender());
+ int scale = firmware->getCapability(SlowScale);
+ phase.fadeOut = round(spinBox->value()*scale);
+ emit modified();
}
void FlightModePanel::trimUpdate(unsigned int trim)
{
lock = true;
- int chn = CONVERT_MODE(trim+1)-1;
+ int chn = CONVERT_MODE(trim + 1) - 1;
int value = model->getTrimValue(phaseIdx, chn);
trimsSlider[trim]->setValue(value);
trimsValue[trim]->setValue(value);
@@ -420,9 +435,8 @@ void FlightModePanel::trimUpdate(unsigned int trim)
trimsSlider[trim]->setEnabled(false);
}
else {
- Board::Type board = firmware->getBoard();
if (IS_HORUS_OR_TARANIS(board))
- trimsUse[trim]->setCurrentIndex(1 + 2*phase.trimRef[chn] + phase.trimMode[chn] - (phase.trimRef[chn] > phaseIdx ? 1 : 0));
+ trimsUse[trim]->setCurrentIndex(1 + 2 * phase.trimRef[chn] + phase.trimMode[chn] - (phase.trimRef[chn] > phaseIdx ? 1 : 0));
else
trimsUse[trim]->setCurrentIndex(phase.trimRef[chn]);
if (phaseIdx == 0 || phase.trimRef[chn] == phaseIdx || (IS_HORUS_OR_TARANIS(board) && phase.trimMode[chn] != 0)) {
@@ -443,6 +457,7 @@ void FlightModePanel::phaseGVValue_editingFinished()
QDoubleSpinBox *spinBox = qobject_cast(sender());
int gvar = spinBox->property("index").toInt();
phase.gvars[gvar] = spinBox->value() * model->gvarData[gvar].multiplierSet();
+ emit datachanged();
emit modified();
}
}
@@ -454,6 +469,7 @@ void FlightModePanel::GVName_editingFinished()
int gvar = lineedit->property("index").toInt();
memset(&model->gvarData[gvar].name, 0, sizeof(model->gvarData[gvar].name));
strcpy(model->gvarData[gvar].name, lineedit->text().toLatin1());
+ emit datachanged();
emit modified();
}
}
@@ -470,7 +486,9 @@ void FlightModePanel::phaseGVUse_currentIndexChanged(int index)
else {
phase.gvars[gvar] = GVAR_MAX_VALUE + index;
}
- updateGVar(gvar);
+ if (model->isGVarLinkedCircular(phaseIdx, gvar))
+ QMessageBox::warning(this, "Companion", tr("Warning: Global variable links back to itself. Flight Mode 0 value used."));
+ emit datachanged();
emit modified();
lock = false;
}
@@ -482,8 +500,8 @@ void FlightModePanel::phaseGVUnit_currentIndexChanged(int index)
QComboBox *comboBox = qobject_cast(sender());
int gvar = comboBox->property("index").toInt();
model->gvarData[gvar].unit = index;
+ emit datachanged();
emit modified();
- updateGVar(gvar);
}
}
@@ -493,8 +511,8 @@ void FlightModePanel::phaseGVPrec_currentIndexChanged(int index)
QComboBox *comboBox = qobject_cast(sender());
int gvar = comboBox->property("index").toInt();
model->gvarData[gvar].prec = index;
+ emit datachanged();
emit modified();
- updateGVar(gvar);
}
}
@@ -505,19 +523,19 @@ void FlightModePanel::phaseGVMin_editingFinished()
int gvar = spinBox->property("index").toInt();
model->gvarData[gvar].setMin(spinBox->value());
if (!model->isGVarLinked(phaseIdx, gvar)) {
- if (model->getGVarFieldValuePrec(phaseIdx, gvar) < spinBox->value()) {
+ if (model->getGVarValuePrec(phaseIdx, gvar) < spinBox->value()) {
phase.gvars[gvar] = model->gvarData[gvar].getMin();
}
}
- for (int x=1; xgetCapability(FlightModes); x++) {
+ for (int x = 1; x < fmCount; x++) {
if (!model->isGVarLinked(x, gvar)) {
if (model->flightModeData[x].gvars[gvar] < model->gvarData[gvar].getMin()) {
model->flightModeData[x].gvars[gvar] = model->gvarData[gvar].getMin();
}
}
}
+ emit datachanged();
emit modified();
- updateGVar(gvar);
}
}
@@ -528,19 +546,19 @@ void FlightModePanel::phaseGVMax_editingFinished()
int gvar = spinBox->property("index").toInt();
model->gvarData[gvar].setMax(spinBox->value());
if (!model->isGVarLinked(phaseIdx, gvar)) {
- if (model->getGVarFieldValuePrec(phaseIdx, gvar) > spinBox->value()) {
+ if (model->getGVarValuePrec(phaseIdx, gvar) > spinBox->value()) {
phase.gvars[gvar] = model->gvarData[gvar].getMax();
}
}
- for (int x=1; xgetCapability(FlightModes); x++) {
+ for (int x = 1; x < fmCount; x++) {
if (!model->isGVarLinked(x, gvar)) {
if (model->flightModeData[x].gvars[gvar] > model->gvarData[gvar].getMax()) {
model->flightModeData[x].gvars[gvar] = model->gvarData[gvar].getMax();
}
}
}
+ emit datachanged();
emit modified();
- updateGVar(gvar);
}
}
@@ -574,11 +592,13 @@ void FlightModePanel::phaseREUse_currentIndexChanged(int index)
phase.rotaryEncoders[re] = 0;
}
else {
- phase.rotaryEncoders[re] = 1024 + index; ;
+ phase.rotaryEncoders[re] = RENC_MAX_VALUE + index; ;
}
update();
- lock = false;
+ if (model->isREncLinkedCircular(phaseIdx, re))
+ QMessageBox::warning(this, "Companion", tr("Warning: Rotary encoder links back to itself. Flight Mode 0 value used."));
emit modified();
+ lock = false;
}
}
@@ -587,7 +607,7 @@ void FlightModePanel::phaseTrimUse_currentIndexChanged(int index)
if (!lock) {
QComboBox *comboBox = qobject_cast(sender());
int trim = comboBox->property("index").toInt();
- int chn = CONVERT_MODE(trim+1)-1;
+ int chn = CONVERT_MODE(trim + 1) - 1;
int data = comboBox->itemData(index).toInt();
if (data < 0) {
phase.trimMode[chn] = -1;
@@ -595,7 +615,6 @@ void FlightModePanel::phaseTrimUse_currentIndexChanged(int index)
phase.trim[chn] = 0;
}
else {
- Board::Type board = firmware->getBoard();
if (IS_HORUS_OR_TARANIS(board)) {
phase.trimMode[chn] = data % 2;
phase.trimRef[chn] = data / 2;
@@ -616,7 +635,7 @@ void FlightModePanel::phaseTrim_valueChanged()
if (!lock) {
QSpinBox *spinBox = qobject_cast(sender());
int trim = spinBox->property("index").toInt();
- int chn = CONVERT_MODE(trim+1)-1;
+ int chn = CONVERT_MODE(trim + 1) - 1;
int value = spinBox->value();
model->setTrimValue(phaseIdx, chn, value);
lock = true;
@@ -631,7 +650,7 @@ void FlightModePanel::phaseTrimSlider_valueChanged()
if (!lock) {
QSlider *slider = qobject_cast(sender());
int trim = slider->property("index").toInt();
- int chn = CONVERT_MODE(trim+1)-1;
+ int chn = CONVERT_MODE(trim + 1) - 1;
int value = slider->value();
model->setTrimValue(phaseIdx, chn, value);
lock = true;
@@ -641,78 +660,638 @@ void FlightModePanel::phaseTrimSlider_valueChanged()
}
}
-void FlightModePanel::name_customContextMenuRequested(const QPoint & pos)
+void FlightModePanel::onCustomContextMenuRequested(QPoint pos)
{
QLabel *label = (QLabel *)sender();
QPoint globalPos = label->mapToGlobal(pos);
+
QMenu contextMenu;
- contextMenu.addAction(CompanionIcon("clear.png"), tr("&Clear"),this,SLOT(fmClear()),tr("Clear"));
+ contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(cmCopy()));
+ contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(cmCut()));
+ contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(cmPaste()))->setEnabled(hasClipboardData());
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmClear()));
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmInsert()))->setEnabled(insertAllowed());
+ contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmDelete()));
+ contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
+ contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(cmClearAll()))->setEnabled(phaseIdx == 0);
+
contextMenu.exec(globalPos);
}
-void FlightModePanel::fmClear()
+bool FlightModePanel::hasClipboardData(QByteArray * data) const
{
- int res = QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all current Flight Mode properties?"), QMessageBox::Yes | QMessageBox::No);
- if (res == QMessageBox::Yes) {
- phase.clear(phaseIdx);
- if (phaseIdx == 0) {
- if (IS_HORUS_OR_TARANIS(getCurrentBoard())) {
- for (int i=0; i < gvCount; ++i) {
- model->gvarData[i].clear();
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat(MIMETYPE_FLIGHTMODE)) {
+ if (data)
+ data->append(mimeData->data(MIMETYPE_FLIGHTMODE));
+ return true;
+ }
+ return false;
+}
+
+bool FlightModePanel::insertAllowed() const
+{
+ return ((phaseIdx < fmCount - 1) && (model->flightModeData[fmCount - 1].isEmpty(fmCount - 1)));
+}
+
+bool FlightModePanel::moveDownAllowed() const
+{
+ return phaseIdx < fmCount - 1;
+}
+
+bool FlightModePanel::moveUpAllowed() const
+{
+ return phaseIdx > 0;
+}
+
+void FlightModePanel::cmClear()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ phase.clear(phaseIdx);
+
+ if (phaseIdx == 0) {
+ for (int i = 0; i < gvCount; i++) {
+ model->gvarData[i].clear();
+ for (int j = 0; j < fmCount; j++) {
+ FlightModeData *fm = &model->flightModeData[j];
+ fm->gvars[i] = fm->linkedGVarFlightModeZero(j);
+ }
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i);
+ }
+ }
+ else {
+ QComboBox * pswtch = ui->swtch;
+ RawSwitch item = RawSwitch(SWITCH_TYPE_NONE);
+ pswtch->setCurrentIndex(pswtch->findText(item.toString()));
+ for (int i = 0; i < gvCount; i++) {
+ phase.gvars[i] = phase.linkedGVarFlightModeZero(phaseIdx);
+ }
+ for (int i = 0; i < reCount; i++) {
+ phase.rotaryEncoders[i] = phase.linkedREncFlightModeZero(phaseIdx);
+ }
+ }
+
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_CLEAR, phaseIdx);
+
+ emit datachanged();
+ emit modified();
+}
+
+void FlightModePanel::cmClearAll()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ for (int j = 0; j < fmCount; j++) {
+ FlightModeData *fm = &model->flightModeData[j];
+ fm->clear(j);
+ for (int i = 0; i < gvCount; i++) {
+ fm->gvars[i] = fm->linkedGVarFlightModeZero(j);
+ }
+ for (int i = 0; i < reCount; i++) {
+ fm->rotaryEncoders[i] = fm->linkedREncFlightModeZero(j);
+ }
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_CLEAR, j);
+ }
+
+ for (int i = 0; i < gvCount; i++) {
+ model->gvarData[i].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i);
+ }
+
+ emit datachanged();
+ emit modified();
+}
+
+void FlightModePanel::cmCopy()
+{
+ QByteArray data;
+ data.append((char*)&model->flightModeData[phaseIdx], sizeof(FlightModeData));
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData(MIMETYPE_FLIGHTMODE, data);
+ QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
+}
+
+void FlightModePanel::cmCut()
+{
+ cmCopy();
+ cmClear();
+}
+
+void FlightModePanel::cmDelete()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ const int maxidx = fmCount - 1;
+
+ memmove(&model->flightModeData[phaseIdx], &model->flightModeData[phaseIdx + 1], (CPN_MAX_FLIGHT_MODES - (phaseIdx + 1)) * sizeof(FlightModeData));
+ model->flightModeData[maxidx].clear(maxidx);
+
+ for (int j = 0; j < maxidx; j++) {
+ FlightModeData *fm = &model->flightModeData[j];
+
+ if (phaseIdx == 0 && j == 0)
+ fm->swtch = RawSwitch(0);
+
+ for (int i = 0; i < trimCount; i++) {
+ if (phaseIdx == 0 && j == 0) {
+ fm->trimMode[i] = 0;
+ fm->trimRef[i] = 0;
+ }
+ else if (fm->trimRef[i] > phaseIdx && fm->trimMode[i] > -1) {
+ fm->trimRef[i]--;
+ }
+ else if (fm->trimRef[i] == phaseIdx) {
+ fm->trimMode[i] = 0;
+ fm->trimRef[i] = 0;
+ fm->trim[i] = 0;
+ }
+ }
+
+ for (int i = 0; i < gvCount; i++) {
+ if (model->isGVarLinked(j, i)) {
+ int idx = model->getGVarFlightModeIndex(j, i);
+ if (phaseIdx == 0 && j == 0)
+ model->setGVarFlightModeIndexToValue(j, i, j);
+ else if (idx > phaseIdx)
+ model->setGVarFlightModeIndexToValue(j, i, idx - 1);
+ else if (idx == phaseIdx)
+ model->setGVarFlightModeIndexToValue(j, i, 0);
+ }
+ }
+
+ for (int i = 0; i < reCount; i++) {
+ if (model->isREncLinked(j, i)) {
+ int idx = model->getREncFlightModeIndex(j, i);
+ if (phaseIdx == 0 && j == 0)
+ model->setREncFlightModeIndexToValue(j, i, j);
+ else if (idx > phaseIdx)
+ model->setREncFlightModeIndexToValue(j, i, idx - 1);
+ else if (idx == phaseIdx)
+ model->setREncFlightModeIndexToValue(j, i, 0);
+ }
+ }
+ }
+
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, -1);
+
+ emit datachanged();
+ emit modified();
+}
+
+void FlightModePanel::cmInsert()
+{
+ const int maxidx = fmCount - 1;
+
+ memmove(&model->flightModeData[phaseIdx + 1], &model->flightModeData[phaseIdx], (CPN_MAX_FLIGHT_MODES - (phaseIdx + 1)) * sizeof(FlightModeData));
+ model->flightModeData[phaseIdx].clear(phaseIdx);
+
+ for (int j = maxidx; j > 0; j--) {
+ FlightModeData *fm = &model->flightModeData[j];
+
+ for (int i = 0; i < trimCount; i++) {
+ if (phaseIdx == 0 && j == 1)
+ fm->trimRef[i] = j;
+ else if (fm->trimRef[i] >= phaseIdx) {
+ if (fm->trimRef[i] < maxidx)
+ fm->trimRef[i]++;
+ else {
+ fm->trimMode[i] = 0;
+ fm->trimRef[i] = 0;
+ fm->trim[i] = 0;
}
}
}
- else {
- lock = true;
- QComboBox * pswtch = ui->swtch;
- RawSwitch item = RawSwitch(SWITCH_TYPE_NONE);
- pswtch->setCurrentIndex(pswtch->findText(item.toString()));
- if (gvCount > 0 && (firmware->getCapability(GvarsFlightModes))) {
- for (int i=0; isetCurrentIndex((phase.gvars[i] > GVAR_MAX_VALUE ? (phase.gvars[i] - GVAR_MAX_VALUE) : 0));
- }
+
+ for (int i = 0; i < gvCount; i++) {
+ if (model->isGVarLinked(j, i)) {
+ int idx = model->getGVarFlightModeIndex(j, i);
+ if (phaseIdx == 0 && j == 1)
+ model->setGVarFlightModeIndexToValue(j, i, j);
+ else if (idx >= phaseIdx)
+ model->setGVarFlightModeIndexToValue(j, i, idx + 1);
}
- for (int i=0; isetCurrentIndex((phase.rotaryEncoders[i] > GVAR_MAX_VALUE ? (phase.rotaryEncoders[i] - GVAR_MAX_VALUE) : 0));
- }
- lock = false;
}
- update();
+
+ for (int i = 0; i < reCount; i++) {
+ if (model->isREncLinked(j, i)) {
+ int idx = model->getREncFlightModeIndex(j, i);
+ if (phaseIdx == 0 && j == 1)
+ model->setREncFlightModeIndexToValue(j, i, j);
+ else if (idx >= phaseIdx)
+ model->setREncFlightModeIndexToValue(j, i, idx + 1);
+ }
+ }
+ }
+
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, 1);
+
+ emit datachanged();
+ emit modified();
+}
+
+void FlightModePanel::cmMoveDown()
+{
+ swapData(phaseIdx, phaseIdx + 1);
+}
+
+void FlightModePanel::cmMoveUp()
+{
+ swapData(phaseIdx, phaseIdx - 1);
+}
+
+void FlightModePanel::cmPaste()
+{
+ QByteArray data;
+ if (hasClipboardData(&data)) {
+ FlightModeData *fm = &model->flightModeData[phaseIdx];
+ memcpy(fm, data.constData(), sizeof(FlightModeData));
+
+ if (phaseIdx == 0)
+ fm->swtch = RawSwitch(0);
+
+ for (int i = 0; i < trimCount; i++) {
+ if (phaseIdx == 0) {
+ fm->trimMode[i] = 0;
+ fm->trimRef[i] = 0;
+ }
+ }
+
+ // TODO fix up linked GVs but need to know source FM index to make adjustments
+ for (int i = 0; i < gvCount; i++) {
+ if (model->isGVarLinked(phaseIdx, i)) {
+ int linkedidx = model->getGVarFlightModeIndex(phaseIdx, i);
+ if (phaseIdx == 0 || linkedidx == phaseIdx)
+ model->setGVarFlightModeIndexToValue(phaseIdx, i, phaseIdx);
+ }
+ }
+
+ // TODO fix up linked REs but need to know source FM index to make adjustments
+ for (int i = 0; i < reCount; i++) {
+ if (model->isREncLinked(phaseIdx, i)) {
+ int linkedidx = model->getREncFlightModeIndex(phaseIdx, i);
+ if (phaseIdx == 0 || linkedidx == phaseIdx)
+ model->setREncFlightModeIndexToValue(phaseIdx, i, phaseIdx);
+ }
+ }
+
+ emit datachanged();
emit modified();
- emit nameModified();
}
}
-void FlightModePanel::gvLabel_customContextMenuRequested(const QPoint & pos)
+void FlightModePanel::swapData(int idx1, int idx2)
+{
+ if (idx1 == idx2)
+ return;
+
+ const int shift = idx2 - idx1;
+
+ FlightModeData fmdtmp = model->flightModeData[idx2];
+ FlightModeData *fmd1 = &model->flightModeData[idx1];
+ FlightModeData *fmd2 = &model->flightModeData[idx2];
+ memcpy(fmd2, fmd1, sizeof(FlightModeData));
+ memcpy(fmd1, &fmdtmp, sizeof(FlightModeData));
+
+ if (idx1 == 0)
+ fmd1->swtch = RawSwitch(0);
+ else if (idx2 == 0)
+ fmd2->swtch = RawSwitch(0);
+
+ for (int i = 0; i < trimCount; i++) {
+ if (fmd1->trimRef[i] == idx1)
+ fmd1->trimRef[i] = idx2;
+ else if (fmd1->trimRef[i] == idx2)
+ fmd1->trimRef[i] = idx1;
+
+ if (fmd2->trimRef[i] == idx1)
+ fmd2->trimRef[i] = idx2;
+ else if (fmd2->trimRef[i] == idx2)
+ fmd2->trimRef[i] = idx1;
+
+ if (idx1 == 0) {
+ fmd1->trimMode[i] = 0;
+ fmd1->trimRef[i] = 0;
+ }
+ else if (idx2 == 0) {
+ fmd2->trimMode[i] = 0;
+ fmd2->trimRef[i] = 0;
+ }
+ }
+
+ for (int i = 0; i < gvCount; i++) {
+ if (model->isGVarLinked(idx1, i)) {
+ int linkedidx = model->getGVarFlightModeIndex(idx1, i);
+ if (linkedidx == idx1)
+ model->setGVarFlightModeIndexToValue(idx1, i, idx2 - shift);
+ else if (linkedidx == idx2)
+ model->setGVarFlightModeIndexToValue(idx1, i, idx1 + shift);
+ else
+ model->setGVarFlightModeIndexToValue(idx1, i, linkedidx);
+ }
+
+ if (model->isGVarLinked(idx2, i)) {
+ int linkedidx = model->getGVarFlightModeIndex(idx2, i);
+ if (linkedidx == idx1)
+ model->setGVarFlightModeIndexToValue(idx2, i, idx2 - shift);
+ else if (linkedidx == idx2)
+ model->setGVarFlightModeIndexToValue(idx2, i, idx1 + shift);
+ else
+ model->setGVarFlightModeIndexToValue(idx2, i, linkedidx);
+ }
+ }
+
+ for (int i = 0; i < reCount; i++) {
+ if (model->isREncLinked(idx1, i)) {
+ int linkedidx = model->getREncFlightModeIndex(idx1, i);
+ if (linkedidx == idx1)
+ model->setREncFlightModeIndexToValue(idx1, i, idx2 - shift);
+ else if (linkedidx == idx2)
+ model->setREncFlightModeIndexToValue(idx1, i, idx1 + shift);
+ else
+ model->setREncFlightModeIndexToValue(idx1, i, linkedidx);
+ }
+
+ if (model->isREncLinked(idx2, i)) {
+ int linkedidx = model->getREncFlightModeIndex(idx2, i);
+ if (linkedidx == idx1)
+ model->setREncFlightModeIndexToValue(idx2, i, idx2 - shift);
+ else if (linkedidx == idx2)
+ model->setREncFlightModeIndexToValue(idx2, i, idx1 + shift);
+ else
+ model->setREncFlightModeIndexToValue(idx2, i, linkedidx);
+ }
+ }
+
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
+ emit datachanged();
+ emit modified();
+}
+
+void FlightModePanel::gvOnCustomContextMenuRequested(QPoint pos)
{
QLabel *label = (QLabel *)sender();
gvIdx = label->property("index").toInt();
QPoint globalPos = label->mapToGlobal(pos);
+
QMenu contextMenu;
- contextMenu.addAction(CompanionIcon("clear.png"), tr("&Clear"),this,SLOT(gvClear()),tr("Clear"));
+ contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(gvCmCopy()));
+ contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(gvCmCut()));
+ contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(gvCmPaste()))->setEnabled(gvHasClipboardData());
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(gvCmClear()));
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(gvCmInsert()))->setEnabled(gvInsertAllowed());
+ contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(gvCmDelete()))->setEnabled(gvDeleteAllowed());
+ contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(gvCmMoveUp()))->setEnabled(gvMoveUpAllowed());
+ contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(gvCmMoveDown()))->setEnabled(gvMoveDownAllowed());
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(gvCmClearAll()));
+
contextMenu.exec(globalPos);
}
-void FlightModePanel::gvClear()
+bool FlightModePanel::gvHasClipboardData() const
+{
+ if (gvHasDefnClipboardData() || gvHasValueClipboardData())
+ return true;
+ return false;
+}
+
+bool FlightModePanel::gvHasDefnClipboardData(QByteArray * data) const
+{
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (phaseIdx == 0 && mimeData->hasFormat(MIMETYPE_GVAR_PARAMS)) {
+ if (data) {
+ data->clear();
+ data->append(mimeData->data(MIMETYPE_GVAR_PARAMS));
+ }
+ return true;
+ }
+ return false;
+}
+
+bool FlightModePanel::gvHasValueClipboardData(QByteArray * data) const
+{
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat(MIMETYPE_GVAR_VALUE)) {
+ if (data) {
+ data->clear();
+ data->append(mimeData->data(MIMETYPE_GVAR_VALUE));
+ }
+ return true;
+ }
+ return false;
+}
+
+bool FlightModePanel::gvDeleteAllowed() const
+{
+ return phaseIdx == 0;
+}
+
+bool FlightModePanel::gvInsertAllowed() const
+{
+ bool ret = true;
+ if (phaseIdx == 0) {
+ if (!model->gvarData[gvCount - 1].isEmpty())
+ ret = false;
+ for (int i = 0; i < fmCount; i++) {
+ if (model->flightModeData[i].gvars[gvCount - 1] != phase.linkedGVarFlightModeZero(i))
+ ret = false;
+ }
+ }
+ else
+ ret = false;
+
+ return ret;
+}
+
+bool FlightModePanel::gvMoveDownAllowed() const
+{
+ return (phaseIdx == 0 && gvIdx < gvCount - 1);
+}
+
+bool FlightModePanel::gvMoveUpAllowed() const
+{
+ return (phaseIdx == 0 && gvIdx > 0);
+}
+
+void FlightModePanel::gvCmClear()
{
if (phaseIdx == 0) {
- if (IS_HORUS_OR_TARANIS(getCurrentBoard())) {
- model->gvarData[gvIdx].clear();
- phase.gvars[gvIdx] = 0;
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear selected Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+ model->gvarData[gvIdx].clear();
+ for (int i = 0; i < fmCount; i++) {
+ model->flightModeData[i].gvars[gvIdx] = model->flightModeData[i].linkedGVarFlightModeZero(i);
+ }
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, gvIdx);
+ }
+ else {
+ phase.gvars[gvIdx] = phase.linkedGVarFlightModeZero(phaseIdx);
+ }
+ emit datachanged();
+ emit modified();
+}
+
+void FlightModePanel::gvCmClearAll()
+{
+ if (phaseIdx == 0) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Global Variables for all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+ for (int i = 0; i < gvCount; i++) {
+ model->gvarData[i].clear();
+ for (int j = 0; j < fmCount; j++) {
+ model->flightModeData[j].gvars[i] = model->flightModeData[j].linkedGVarFlightModeZero(j);
+ }
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i);
}
}
else {
- lock = true;
- if (gvCount > 0 && (firmware->getCapability(GvarsFlightModes))) {
- phase.gvars[gvIdx] = GVAR_MAX_VALUE + 1;
- gvUse[gvIdx]->setCurrentIndex(1);
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Global Variables for this Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+ for (int i = 0; i < gvCount; i++) {
+ phase.gvars[i] = phase.linkedGVarFlightModeZero(phaseIdx);
}
- lock = false;
}
- update();
+ emit datachanged();
emit modified();
}
+void FlightModePanel::gvCmCopy()
+{
+ QMimeData *mimeData = new QMimeData;
+ QByteArray data;
+ if (phaseIdx == 0) {
+ data.append((char*)&model->gvarData[gvIdx], sizeof(GVarData));
+ mimeData->setData(MIMETYPE_GVAR_PARAMS, data);
+ }
+ else {
+ mimeData->removeFormat(MIMETYPE_GVAR_PARAMS);
+ }
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+ int val = phase.gvars[gvIdx];
+ if (model->isGVarLinked(phaseIdx, gvIdx))
+ val = GVAR_MAX_VALUE + 1 + model->getGVarFlightModeIndex(phaseIdx, gvIdx); // store index in case paste is to another flight mode
+ data.setNum(val);
+ mimeData->setData(MIMETYPE_GVAR_VALUE, data);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+}
+
+void FlightModePanel::gvCmCut()
+{
+ gvCmCopy();
+ if (phaseIdx > 0) {
+ gvCmClear();
+ }
+ else {
+ model->gvarData[gvIdx].clear();
+ phase.gvars[gvIdx] = 0;
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, gvIdx);
+ emit datachanged();
+ emit modified();
+ }
+}
+
+void FlightModePanel::gvCmDelete()
+{
+ if (phaseIdx > 0)
+ return;
+ int maxidx = gvCount - 1;
+ for (int i = gvIdx; i < maxidx; i++) {
+ memcpy(&model->gvarData[i], &model->gvarData[i + 1], sizeof(GVarData));
+ for (int j = 0; j < fmCount; j++) {
+ model->flightModeData[j].gvars[i] = model->flightModeData[j].gvars[i + 1];
+ }
+ }
+
+ model->gvarData[maxidx].clear();
+ for (int j = 0; j < fmCount; j++) {
+ model->flightModeData[j].gvars[maxidx] = model->flightModeData[j].linkedGVarFlightModeZero(j);
+ }
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, -1);
+ emit datachanged();
+ emit modified();
+}
+
+void FlightModePanel::gvCmInsert()
+{
+ for (int i = (gvCount - 1); i > gvIdx; i--) {
+ memcpy(&model->gvarData[i], &model->gvarData[i - 1], sizeof(GVarData));
+ for (int j = 0; j < fmCount; j++) {
+ model->flightModeData[j].gvars[i] = model->flightModeData[j].gvars[i - 1];
+ }
+ }
+ model->gvarData[gvIdx].clear();
+ for (int j = 0; j < fmCount; j++) {
+ model->flightModeData[j].gvars[gvIdx] = model->flightModeData[j].linkedGVarFlightModeZero(j);
+ }
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, 1);
+ emit datachanged();
+ emit modified();
+}
+
+void FlightModePanel::gvCmMoveDown()
+{
+ if (phaseIdx == 0)
+ gvSwapData(gvIdx, gvIdx + 1);
+}
+
+void FlightModePanel::gvCmMoveUp()
+{
+ if (phaseIdx == 0)
+ gvSwapData(gvIdx, gvIdx - 1);
+}
+
+void FlightModePanel::gvCmPaste()
+{
+ QByteArray data;
+ if (phaseIdx == 0 && gvHasDefnClipboardData(&data)) {
+ GVarData *gvd = &model->gvarData[gvIdx];
+ memcpy(gvd, data.constData(), sizeof(GVarData));
+ }
+ if (gvHasValueClipboardData(&data)) {
+ int val = data.toInt();
+ if (val > GVAR_MAX_VALUE) {
+ if (phaseIdx > 0)
+ model->setGVarFlightModeIndexToValue(phaseIdx, gvIdx, val - (GVAR_MAX_VALUE + 1)); // index stored in clipboard
+ else
+ phase.gvars[gvIdx] = 0;
+ }
+ else
+ phase.gvars[gvIdx] = val;
+ }
+ emit datachanged();
+ emit modified();
+}
+
+void FlightModePanel::gvSwapData(int idx1, int idx2)
+{
+ if (phaseIdx == 0 && idx1 != idx2) {
+ GVarData datatmp = model->gvarData[idx2];
+ GVarData *data1 = &model->gvarData[idx1];
+ GVarData *data2 = &model->gvarData[idx2];
+ memcpy(data2, data1, sizeof(GVarData));
+ memcpy(data1, &datatmp, sizeof(GVarData));
+ for (int j = 0; j < fmCount; j++) {
+ int valtmp = model->flightModeData[j].gvars[idx2];
+ model->flightModeData[j].gvars[idx2] = model->flightModeData[j].gvars[idx1];
+ model->flightModeData[j].gvars[idx1] = valtmp;
+ }
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
+ emit datachanged();
+ emit modified();
+ }
+}
+
/**********************************************************/
FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
@@ -725,16 +1304,16 @@ FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralS
QGridLayout * gridLayout = new QGridLayout(this);
tabWidget = new QTabWidget(this);
- for (int i=0; isetProperty("index", i);
+ connect(tab, &FlightModePanel::datachanged, this, &FlightModesPanel::update);
connect(tab, &FlightModePanel::modified, this, &FlightModesPanel::modified);
connect(tab, &FlightModePanel::nameModified, this, &FlightModesPanel::onPhaseNameChanged);
connect(this, &FlightModesPanel::updated, tab, &FlightModePanel::update);
tabWidget->addTab(tab, getTabName(i));
}
gridLayout->addWidget(tabWidget, 0, 0, 1, 1);
- connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(on_tabWidget_currentChanged(int)));
}
FlightModesPanel::~FlightModesPanel()
diff --git a/companion/src/modeledit/flightmodes.h b/companion/src/modeledit/flightmodes.h
index c5aa434fb..1986f1e46 100644
--- a/companion/src/modeledit/flightmodes.h
+++ b/companion/src/modeledit/flightmodes.h
@@ -26,6 +26,10 @@
class RawSwitchFilterItemModel;
+constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode";
+constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params";
+constexpr char MIMETYPE_GVAR_VALUE[] = "application/x-companion-gvar-value";
+
namespace Ui {
class FlightMode;
}
@@ -42,6 +46,7 @@ class FlightModePanel : public ModelPanel
signals:
void nameModified();
+ void datachanged();
private slots:
void phaseName_editingFinished();
@@ -61,18 +66,36 @@ class FlightModePanel : public ModelPanel
void phaseGVMax_editingFinished();
void phaseREValue_editingFinished();
void phaseREUse_currentIndexChanged(int index);
- void name_customContextMenuRequested(const QPoint & pos);
- void fmClear();
- void gvLabel_customContextMenuRequested(const QPoint & pos);
- void gvClear();
+ void onCustomContextMenuRequested(QPoint pos);
+ void cmClear();
+ void cmClearAll();
+ void cmCopy();
+ void cmCut();
+ void cmDelete();
+ void cmInsert();
+ void cmPaste();
+ void cmMoveDown();
+ void cmMoveUp();
+ void gvOnCustomContextMenuRequested(QPoint pos);
+ void gvCmClear();
+ void gvCmClearAll();
+ void gvCmCopy();
+ void gvCmCut();
+ void gvCmDelete();
+ void gvCmInsert();
+ void gvCmPaste();
+ void gvCmMoveDown();
+ void gvCmMoveUp();
private:
Ui::FlightMode *ui;
int phaseIdx;
FlightModeData & phase;
+ int fmCount;
int reCount;
int gvCount;
int gvIdx;
+ int trimCount;
QVector trimsLabel;
QLineEdit * gvNames[CPN_MAX_GVARS];
QDoubleSpinBox * gvValues[CPN_MAX_GVARS];
@@ -88,12 +111,27 @@ class FlightModePanel : public ModelPanel
QVector trimsValue;
QVector trimsSlider;
RawSwitchFilterItemModel * rawSwitchItemModel;
+ Board::Type board;
void trimUpdate(unsigned int trim);
void updateGVar(int index);
+ void updateRotaryEncoder(int index);
void setGVSB(QDoubleSpinBox * spinBox, int min, int max, int val);
void populateGvarUnitCB(QComboBox * cb);
void populateGvarPrecCB(QComboBox * cb);
+ bool hasClipboardData(QByteArray * data = nullptr) const;
+ bool insertAllowed() const;
+ bool moveDownAllowed() const;
+ bool moveUpAllowed() const;
+ void swapData(int idx1, int idx2);
+ bool gvHasClipboardData() const;
+ bool gvHasDefnClipboardData(QByteArray * data = nullptr) const;
+ bool gvHasValueClipboardData(QByteArray * data = nullptr) const;
+ bool gvDeleteAllowed() const;
+ bool gvInsertAllowed() const;
+ bool gvMoveDownAllowed() const;
+ bool gvMoveUpAllowed() const;
+ void gvSwapData(int idx1, int idx2);
};
class FlightModesPanel : public ModelPanel
diff --git a/companion/src/modeledit/inputs.cpp b/companion/src/modeledit/inputs.cpp
index 27ca4c42f..806de54fc 100644
--- a/companion/src/modeledit/inputs.cpp
+++ b/companion/src/modeledit/inputs.cpp
@@ -47,18 +47,18 @@ InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & g
qbClear->setText(tr("Clear All Inputs"));
qbClear->setIcon(CompanionIcon("clear.png"));
- exposLayout->addWidget(ExposlistWidget,1,1,1,3);
- exposLayout->addWidget(qbUp,2,1);
- exposLayout->addWidget(qbClear,2,2);
- exposLayout->addWidget(qbDown,2,3);
+ exposLayout->addWidget(ExposlistWidget, 1, 1, 1, 3);
+ exposLayout->addWidget(qbUp, 2, 1);
+ exposLayout->addWidget(qbClear, 2, 2);
+ exposLayout->addWidget(qbDown, 2, 3);
connect(ExposlistWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(expolistWidget_customContextMenuRequested(QPoint)));
connect(ExposlistWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(expolistWidget_doubleClicked(QModelIndex)));
- connect(ExposlistWidget, SIGNAL(mimeDropped(int,const QMimeData*,Qt::DropAction)), this, SLOT(mimeExpoDropped(int, const QMimeData*, Qt::DropAction)));
+ connect(ExposlistWidget, SIGNAL(mimeDropped(int, const QMimeData*,Qt::DropAction)), this, SLOT(mimeExpoDropped(int, const QMimeData*, Qt::DropAction)));
- connect(qbUp, SIGNAL(pressed()),SLOT(moveExpoUp()));
- connect(qbDown, SIGNAL(pressed()),SLOT(moveExpoDown()));
- connect(qbClear, SIGNAL(pressed()),SLOT(clearExpos()));
+ connect(qbUp, SIGNAL(pressed()), SLOT(moveExpoUp()));
+ connect(qbDown, SIGNAL(pressed()), SLOT(moveExpoDown()));
+ connect(qbClear, SIGNAL(pressed()), SLOT(clearExpos()));
connect(ExposlistWidget, SIGNAL(keyWasPressed(QKeyEvent*)), this, SLOT(expolistWidget_KeyPress(QKeyEvent*)));
}
@@ -71,9 +71,9 @@ void InputsPanel::update()
{
lock = true;
ExposlistWidget->clear();
- for (int i=0; i < inputsCount; ++i) {
+ for (int i = 0; i < inputsCount; ++i) {
bool filled = false;
- for (uint j=0; j < CPN_MAX_EXPOS; ++j) {
+ for (uint j = 0; j < CPN_MAX_EXPOS; ++j) {
const ExpoData & ed = model->expoData[j];
if ((int)ed.chn == i && ed.mode) {
AddInputLine(j);
@@ -81,7 +81,7 @@ void InputsPanel::update()
}
}
if (!filled) {
- AddInputLine(-i-1);
+ AddInputLine(-i - 1);
}
}
lock = false;
@@ -108,9 +108,8 @@ void InputsPanel::AddInputLine(int dest)
const ExpoData &md = model->expoData[dest];
qba.append((const char*)&md, sizeof(ExpoData));
destId = md.chn + 1;
- const QVector expos = model->expos(md.chn);
- newChan = (expos.constFirst() == &md);
- hasSibs = (expos.constLast() != &md);
+ newChan = model->isExpoParent(dest);
+ hasSibs = (model->hasExpoChildren(dest) || model->hasExpoSiblings(dest));
}
QListWidgetItem *itm = new QListWidgetItem(getInputText(dest, newChan));
itm->setData(Qt::UserRole, qba);
@@ -133,10 +132,10 @@ QString InputsPanel::getInputText(int dest, bool newChan)
{
QString str;
if (dest < 0) {
- str = modelPrinter.printInputName(-dest-1);
+ str = modelPrinter.printInputName(-dest - 1);
}
else {
- const ExpoData & input = model->expoData[dest];
+ const ExpoData &input = model->expoData[dest];
const int nameChars = (firmware->getCapability(VirtualInputs) ? 10 : 4);
if (newChan)
str = QString("%1").arg(modelPrinter.printInputName(input.chn), -nameChars, QChar(' '));
@@ -150,14 +149,14 @@ QString InputsPanel::getInputText(int dest, bool newChan)
bool InputsPanel::gm_insertExpo(int idx)
{
- if (idx<0 || idx>=CPN_MAX_EXPOS || model->expoData[CPN_MAX_EXPOS-1].mode > 0) {
- QMessageBox::information(this, CPN_STR_APP_NAME, tr("Not enough available inputs!"));
+ if (idx < 0 || idx >= CPN_MAX_EXPOS || model->expoData[CPN_MAX_EXPOS-1].mode > 0) {
+ QMessageBox::information(this, CPN_STR_APP_NAME, tr("Not enough available Inputs!"));
return false;
}
int chn = model->expoData[idx].chn;
- ExpoData * newExpo = model->insertInput(idx);
+ ExpoData *newExpo = model->insertInput(idx);
newExpo->chn = chn;
newExpo->weight = 100;
newExpo->mode = INPUT_MODE_BOTH;
@@ -172,107 +171,107 @@ void InputsPanel::gm_deleteExpo(int index, bool clearName)
void InputsPanel::gm_openExpo(int index)
{
- if(index<0 || index>=CPN_MAX_EXPOS) return;
+ if (index < 0 || index >= CPN_MAX_EXPOS)
+ return;
- ExpoData mixd(model->expoData[index]);
+ ExpoData ed(model->expoData[index]);
- QString inputName;
+ QString inputName;
+ if (firmware->getCapability(VirtualInputs))
+ inputName = model->inputNames[ed.chn];
+
+ ExpoDialog *g = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName);
+ if (g->exec()) {
+ model->expoData[index] = ed;
if (firmware->getCapability(VirtualInputs))
- inputName = model->inputNames[mixd.chn];
-
- ExpoDialog *g = new ExpoDialog(this, *model, &mixd, generalSettings, firmware, inputName);
- if (g->exec()) {
- model->expoData[index] = mixd;
- if (firmware->getCapability(VirtualInputs))
- strncpy(model->inputNames[mixd.chn], inputName.toLatin1().data(), 4);
- emit modified();
- update();
- }
- else {
- if (expoInserted) {
- gm_deleteExpo(index);
- }
- expoInserted=false;
- update();
+ strncpy(model->inputNames[ed.chn], inputName.toLatin1().data(), INPUT_NAME_LEN);
+ emit modified();
+ update();
+ }
+ else {
+ if (expoInserted) {
+ gm_deleteExpo(index);
}
+ expoInserted=false;
+ update();
+ }
}
int InputsPanel::getExpoIndex(unsigned int dch)
{
- unsigned int i = 0;
- while (model->expoData[i].chn<=dch && model->expoData[i].mode && iexpoData[i].chn <= dch && model->expoData[i].mode && i < CPN_MAX_EXPOS)
+ i++;
+ if (i == CPN_MAX_EXPOS)
+ return -1;
+ return i;
}
-
QList InputsPanel::createExpoListFromSelected()
{
- QList list;
- foreach(QListWidgetItem *item, ExposlistWidget->selectedItems()) {
- int idx= item->data(Qt::UserRole).toByteArray().at(0);
- if(idx>=0 && idx list;
+ foreach (QListWidgetItem *item, ExposlistWidget->selectedItems()) {
+ int idx = item->data(Qt::UserRole).toByteArray().at(0);
+ if (idx >= 0 && idx < CPN_MAX_EXPOS)
+ list << idx;
+ }
+ return list;
}
-
void InputsPanel::setSelectedByExpoList(QList list)
{
- for(int i=0; icount(); i++) {
- int t = ExposlistWidget->item(i)->data(Qt::UserRole).toByteArray().at(0);
- if(list.contains(t))
- ExposlistWidget->item(i)->setSelected(true);
- }
+ for (int i = 0; i < ExposlistWidget->count(); i++) {
+ int t = ExposlistWidget->item(i)->data(Qt::UserRole).toByteArray().at(0);
+ if (list.contains(t))
+ ExposlistWidget->item(i)->setSelected(true);
+ }
}
void InputsPanel::exposDelete(bool ask)
{
- QList list = createExpoListFromSelected();
- if(list.isEmpty()) return;
+ QList list = createExpoListFromSelected();
+ if (list.isEmpty())
+ return;
- QMessageBox::StandardButton ret = QMessageBox::No;
+ QMessageBox::StandardButton ret = QMessageBox::No;
- if(ask)
- ret = QMessageBox::warning(this, "companion",
- tr("Delete Selected Inputs?"),
- QMessageBox::Yes | QMessageBox::No);
+ if (ask)
+ ret = QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Delete selected Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No);
-
- if ((ret == QMessageBox::Yes) || (!ask)) {
- exposDeleteList(list, ask);
- emit modified();
- update();
- }
+ if ((ret == QMessageBox::Yes) || (!ask)) {
+ exposDeleteList(list, ask);
+ emit modified();
+ update();
+ }
}
void InputsPanel::exposCut()
{
- exposCopy();
- exposDelete(false);
+ exposCopy();
+ exposDelete(false);
}
void InputsPanel::exposCopy()
{
- QList list = createExpoListFromSelected();
+ QList list = createExpoListFromSelected();
- QByteArray mxData;
- foreach(int idx, list) {
- mxData.append((char*)&model->expoData[idx], sizeof(ExpoData));
- }
+ QByteArray exData;
+ foreach (int idx, list) {
+ exData.append((char*)&model->expoData[idx], sizeof(ExpoData));
+ }
- QMimeData *mimeData = new QMimeData;
- mimeData->setData("application/x-companion-expo", mxData);
- QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData(MIMETYPE_EXPO, exData);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
}
void InputsPanel::mimeExpoDropped(int index, const QMimeData *data, Qt::DropAction action)
{
int idx = ExposlistWidget->item(index)->data(Qt::UserRole).toByteArray().at(0);
- if (action==Qt::CopyAction) {
+ if (action == Qt::CopyAction) {
pasteExpoMimeData(data, idx);
}
- else if (action==Qt::MoveAction) {
+ else if (action == Qt::MoveAction) {
QList list = createExpoListFromSelected();
exposDeleteList(list, false);
foreach (const int del, list) {
@@ -285,30 +284,31 @@ void InputsPanel::mimeExpoDropped(int index, const QMimeData *data, Qt::DropActi
void InputsPanel::pasteExpoMimeData(const QMimeData * mimeData, int destIdx)
{
- if (mimeData->hasFormat("application/x-companion-expo")) {
- int idx; // mixer index
+ if (mimeData->hasFormat(MIMETYPE_EXPO)) {
+ int idx; // expo index
int dch;
if (destIdx < 0) {
dch = -destIdx - 1;
idx = getExpoIndex(dch) - 1; //get expo index to insert
- } else {
+ }
+ else {
idx = destIdx;
dch = model->expoData[idx].chn;
}
- QByteArray mxData = mimeData->data("application/x-companion-expo");
+ QByteArray exData = mimeData->data(MIMETYPE_EXPO);
int i = 0;
- while (i < mxData.size()) {
+ while (i < exData.size()) {
idx++;
if (!gm_insertExpo(idx))
break;
- ExpoData *md = &model->expoData[idx];
- memcpy(md, mxData.mid(i, sizeof(ExpoData)).constData(), sizeof(ExpoData));
- const int oldChan = md->chn;
- md->chn = dch;
- maybeCopyInputName(oldChan, md->chn);
+ ExpoData *ed = &model->expoData[idx];
+ memcpy(ed, exData.mid(i, sizeof(ExpoData)).constData(), sizeof(ExpoData));
+ const int oldChan = ed->chn;
+ ed->chn = dch;
+ maybeCopyInputName(oldChan, ed->chn);
i += sizeof(ExpoData);
}
@@ -334,83 +334,104 @@ void InputsPanel::exposDuplicate()
exposPaste();
}
-
void InputsPanel::expoOpen(QListWidgetItem *item)
{
- if (!item)
- item = ExposlistWidget->currentItem();
+ if (!item)
+ item = ExposlistWidget->currentItem();
- int idx = item->data(Qt::UserRole).toByteArray().at(0);
- if (idx<0) {
- int ch = -idx-1;
- idx = getExpoIndex(ch); // get expo index to insert
- if (!gm_insertExpo(idx))
- return;
- model->expoData[idx].chn = ch;
- expoInserted=true;
- } else {
- expoInserted=false;
- }
- gm_openExpo(idx);
+ int idx = item->data(Qt::UserRole).toByteArray().at(0);
+ if (idx < 0) {
+ int ch = -idx - 1;
+ idx = getExpoIndex(ch); // get expo index to insert
+ if (!gm_insertExpo(idx))
+ return;
+ model->expoData[idx].chn = ch;
+ expoInserted = true;
+ }
+ else {
+ expoInserted = false;
+ }
+ gm_openExpo(idx);
}
void InputsPanel::expoAdd()
{
- int index = ExposlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
+ int index = ExposlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
- if(index<0) { // if empty then return relevant index
- expoOpen();
- } else {
- index++;
- if (!gm_insertExpo(index))
- return;
- model->expoData[index].chn = model->expoData[index-1].chn;
- expoInserted=true;
- }
- gm_openExpo(index);
+ if (index < 0) { // if empty then return relevant index
+ expoOpen();
+ }
+ else {
+ index++;
+ if (!gm_insertExpo(index))
+ return;
+ model->expoData[index].chn = model->expoData[index-1].chn;
+ expoInserted = true;
+ }
+ gm_openExpo(index);
}
void InputsPanel::expolistWidget_customContextMenuRequested(QPoint pos)
{
- QPoint globalPos = ExposlistWidget->mapToGlobal(pos);
+ QPoint globalPos = ExposlistWidget->mapToGlobal(pos);
- const QClipboard *clipboard = QApplication::clipboard();
- const QMimeData *mimeData = clipboard->mimeData();
- bool hasData = mimeData->hasFormat("application/x-companion-expo");
+ const QClipboard *clipboard = QApplication::clipboard();
+ const QMimeData *mimeData = clipboard->mimeData();
+ bool hasData = mimeData->hasFormat(MIMETYPE_EXPO);
- QMenu contextMenu;
- contextMenu.addAction(CompanionIcon("add.png"), tr("&Add"),this,SLOT(expoAdd()),tr("Ctrl+A"));
- contextMenu.addAction(CompanionIcon("edit.png"), tr("&Edit"),this,SLOT(expoOpen()),tr("Enter"));
- contextMenu.addSeparator();
- contextMenu.addAction(CompanionIcon("clear.png"), tr("&Delete"),this,SLOT(exposDelete()),tr("Delete"));
- contextMenu.addAction(CompanionIcon("copy.png"), tr("&Copy"),this,SLOT(exposCopy()),tr("Ctrl+C"));
- contextMenu.addAction(CompanionIcon("cut.png"), tr("&Cut"),this,SLOT(exposCut()),tr("Ctrl+X"));
- contextMenu.addAction(CompanionIcon("paste.png"), tr("&Paste"),this,SLOT(exposPaste()),tr("Ctrl+V"))->setEnabled(hasData);
- contextMenu.addAction(CompanionIcon("duplicate.png"), tr("Du&plicate"),this,SLOT(exposDuplicate()),tr("Ctrl+U"));
- contextMenu.addSeparator();
- contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(moveExpoUp()),tr("Ctrl+Up"));
- contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(moveExpoDown()),tr("Ctrl+Down"));
- contextMenu.addSeparator();
- contextMenu.addActions(ExposlistWidget->actions());
+ selectedIdx = getIndexFromSelected();
+ inputIdx = getInputIndexFromSelected();
- contextMenu.exec(globalPos);
+ QMenu contextMenu;
+ QMenu *contextMenuLines = contextMenu.addMenu(tr("Lines"));
+ contextMenuLines->addAction(CompanionIcon("add.png"), tr("&Add"), this, SLOT(expoAdd()), tr("Ctrl+A"));
+ contextMenuLines->addAction(CompanionIcon("edit.png"), tr("&Edit"), this, SLOT(expoOpen()), tr("Enter"));
+ contextMenuLines->addSeparator();
+ contextMenuLines->addAction(CompanionIcon("clear.png"), tr("&Delete"), this, SLOT(exposDelete()), tr("Delete"));
+ contextMenuLines->addAction(CompanionIcon("copy.png"), tr("&Copy"), this, SLOT(exposCopy()), tr("Ctrl+C"));
+ contextMenuLines->addAction(CompanionIcon("cut.png"), tr("&Cut"), this, SLOT(exposCut()), tr("Ctrl+X"));
+ contextMenuLines->addAction(CompanionIcon("paste.png"), tr("&Paste"), this, SLOT(exposPaste()), tr("Ctrl+V"))->setEnabled(hasData);
+ contextMenuLines->addAction(CompanionIcon("duplicate.png"), tr("Du&plicate"), this, SLOT(exposDuplicate()), tr("Ctrl+U"));
+ contextMenuLines->addSeparator();
+ contextMenuLines->addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(moveExpoUp()), tr("Ctrl+Up"));
+ contextMenuLines->addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(moveExpoDown()), tr("Ctrl+Down"));
+
+ QMenu *contextMenuInputs = contextMenu.addMenu(tr("Input"));
+ contextMenuInputs->addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmInputInsert()))->setEnabled(cmInputInsertAllowed());
+ contextMenuInputs->addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmInputDelete()));
+ contextMenuInputs->addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(cmInputMoveUp()))->setEnabled(cmInputMoveUpAllowed());
+ contextMenuInputs->addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(cmInputMoveDown()))->setEnabled(cmInputMoveDownAllowed());
+ contextMenuInputs->addSeparator();
+ contextMenuInputs->addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmInputClear()))->setEnabled(isExpoIndex(selectedIdx));
+
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(clearExpos()));
+ contextMenu.addSeparator();
+ contextMenu.addActions(ExposlistWidget->actions());
+ contextMenu.exec(globalPos);
}
-
void InputsPanel::expolistWidget_KeyPress(QKeyEvent *event)
{
- if(event->matches(QKeySequence::SelectAll)) expoAdd(); //Ctrl A
- if(event->matches(QKeySequence::Delete)) exposDelete();
- if(event->matches(QKeySequence::Copy)) exposCopy();
- if(event->matches(QKeySequence::Cut)) exposCut();
- if(event->matches(QKeySequence::Paste)) exposPaste();
- if(event->matches(QKeySequence::Underline)) exposDuplicate();
+ if (event->matches(QKeySequence::SelectAll))
+ expoAdd(); //Ctrl A
+ if (event->matches(QKeySequence::Delete))
+ exposDelete();
+ if (event->matches(QKeySequence::Copy))
+ exposCopy();
+ if (event->matches(QKeySequence::Cut))
+ exposCut();
+ if (event->matches(QKeySequence::Paste))
+ exposPaste();
+ if (event->matches(QKeySequence::Underline))
+ exposDuplicate();
- if(event->key()==Qt::Key_Return || event->key()==Qt::Key_Enter) expoOpen();
- if(event->matches(QKeySequence::MoveToNextLine))
- ExposlistWidget->setCurrentRow(ExposlistWidget->currentRow()+1);
- if(event->matches(QKeySequence::MoveToPreviousLine))
- ExposlistWidget->setCurrentRow(ExposlistWidget->currentRow()-1);
+ if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
+ expoOpen();
+ if (event->matches(QKeySequence::MoveToNextLine))
+ ExposlistWidget->setCurrentRow(ExposlistWidget->currentRow() + 1);
+ if (event->matches(QKeySequence::MoveToPreviousLine))
+ ExposlistWidget->setCurrentRow(ExposlistWidget->currentRow() - 1);
}
int InputsPanel::gm_moveExpo(int idx, bool dir) //true=inc=down false=dec=up
@@ -418,7 +439,7 @@ int InputsPanel::gm_moveExpo(int idx, bool dir) //true=inc=down false=dec=up
if (idx >= CPN_MAX_EXPOS || idx < 0 || (dir && idx >= CPN_MAX_EXPOS - 1) || (!dir && !idx))
return -1;
- const int tdx = dir ? idx+1 : idx-1;
+ const int tdx = dir ? idx + 1 : idx-1;
ExpoData temp;
ExpoData &src = model->expoData[idx];
ExpoData &tgt = model->expoData[tdx];
@@ -432,7 +453,7 @@ int InputsPanel::gm_moveExpo(int idx, bool dir) //true=inc=down false=dec=up
if (tgt.chn != src.chn || tgtempty) {
const int oldChan = src.chn;
- if (dir && src.chn < unsigned(inputsCount-1))
+ if (dir && src.chn < unsigned(inputsCount - 1))
src.chn++;
else if (!dir && src.chn > 0)
src.chn--;
@@ -452,7 +473,7 @@ void InputsPanel::moveExpoList(bool down)
QList list = createExpoListFromSelected();
QList highlightList;
bool mod = false;
- foreach(int idx, list) {
+ foreach (int idx, list) {
const int newIdx = gm_moveExpo(idx, down);
if (newIdx > -1) {
highlightList << newIdx;
@@ -483,19 +504,22 @@ void InputsPanel::expolistWidget_doubleClicked(QModelIndex index)
void InputsPanel::exposDeleteList(QList list, bool clearName)
{
- std::sort(list.begin(), list.end());
+ std::sort(list.begin(), list.end());
- int iDec = 0;
- foreach(int idx, list) {
- gm_deleteExpo(idx-iDec, clearName);
- iDec++;
- }
+ int iDec = 0;
+ foreach (int idx, list) {
+ gm_deleteExpo(idx-iDec, clearName);
+ iDec++;
+ }
}
void InputsPanel::clearExpos()
{
- if (QMessageBox::question(this, tr("Clear Inputs?"), tr("Really clear all the inputs?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
model->clearInputs();
+ for (int i = 0; i < inputsCount; i++) {
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, i);
+ }
emit modified();
update();
}
@@ -512,8 +536,172 @@ void InputsPanel::maybeCopyInputName(int srcChan, int destChan)
if (srcEmpty) {
// if destination input name is empty, copy it from source expo input
if (!strlen(model->inputNames[destChan]))
- strncpy(model->inputNames[destChan], model->inputNames[srcChan], 5);
+ strncpy(model->inputNames[destChan], model->inputNames[srcChan], INPUT_NAME_LEN);
// clear the emptry source channel name
model->inputNames[srcChan][0] = 0;
}
}
+
+bool InputsPanel::cmInputInsertAllowed() const
+{
+ return ((!model->hasExpos(inputsCount - 1)) && (inputIdx < inputsCount - 1));
+}
+
+bool InputsPanel::cmInputMoveDownAllowed() const
+{
+ return (inputIdx >= 0 && (inputIdx < inputsCount - 1));
+}
+
+bool InputsPanel::cmInputMoveUpAllowed() const
+{
+ return inputIdx > 0;
+}
+
+void InputsPanel::cmInputClear()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ for (int i = CPN_MAX_EXPOS - 1; i >= 0; i--) {
+ ExpoData *ed = &model->expoData[i];
+ if ((int)ed->chn == inputIdx)
+ model->removeInput(i);
+ }
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, inputIdx);
+ update();
+ emit modified();
+}
+
+void InputsPanel::cmInputDelete()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ for (int i = 0; i < CPN_MAX_EXPOS; i++) {
+ ExpoData *ed = &model->expoData[i];
+ if ((int)ed->chn == inputIdx)
+ model->removeInput(i);
+ else if ((int)ed->chn > inputIdx)
+ ed->chn--;
+ }
+
+ for (int i = inputIdx; i < inputsCount; i++) {
+ strncpy(model->inputNames[i], model->inputNames[i + 1], sizeof(model->inputNames[i]) - 1);
+ }
+ model->inputNames[inputsCount - 1][0] = 0;
+
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_SHIFT, inputIdx, 0, -1);
+ update();
+ emit modified();
+}
+
+void InputsPanel::cmInputInsert()
+{
+ for (int i = 0; i < CPN_MAX_EXPOS; i++) {
+ ExpoData *ed = &model->expoData[i];
+ if ((int)ed->chn >= inputIdx)
+ ed->chn++;
+ }
+
+ for (int i = inputsCount - 1; i > inputIdx; i--) {
+ strncpy(model->inputNames[i], model->inputNames[i - 1], sizeof(model->inputNames[i]) - 1);
+ }
+ model->inputNames[inputIdx][0] = 0;
+
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_SHIFT, inputIdx, 0, 1);
+ update();
+ emit modified();
+}
+
+void InputsPanel::cmInputMoveDown()
+{
+ cmInputSwapData(inputIdx, inputIdx + 1);
+}
+
+void InputsPanel::cmInputMoveUp()
+{
+ cmInputSwapData(inputIdx - 1, inputIdx);
+}
+
+void InputsPanel::cmInputSwapData(int idx1, int idx2)
+{
+ if (idx1 >= idx2 || (!model->hasExpos(idx1) && !model->hasExpos(idx2)))
+ return;
+ // save expos
+ int expoidx = -1;
+ QVector edtmp;
+ int i;
+ for (i = 0; i < CPN_MAX_EXPOS; i++) {
+ ExpoData *ed = &model->expoData[i];
+ if ((int)ed->chn == idx1) {
+ edtmp << model->expoData[i];
+ if (expoidx < 0)
+ expoidx = i;
+ }
+ else if ((int)ed->chn > idx1)
+ break;
+ }
+ // move expos up
+ const int offset = i - expoidx;
+ int expocnt = 0;
+ for (int j = i; j < CPN_MAX_EXPOS; j++) {
+ ExpoData *ed = &model->expoData[j];
+ if ((int)ed->chn == idx2) {
+ ExpoData *dest = &model->expoData[j - offset];
+ memcpy(dest, &model->expoData[j], sizeof(ExpoData));
+ dest->chn = idx1;
+ expocnt++;
+ }
+ else if ((int)ed->chn > idx2)
+ break;
+ }
+ // copy back saved expos
+ int cnt = 0;
+ foreach (ExpoData ed, edtmp) {
+ ExpoData *dest = &model->expoData[expoidx + expocnt + cnt];
+ memcpy(dest, &ed, sizeof(ExpoData));
+ dest->chn = idx2;
+ cnt++;
+ }
+
+ // swap names
+ QByteArray *tname = new QByteArray(model->inputNames[idx2]);
+ strncpy(model->inputNames[idx2], model->inputNames[idx1], sizeof(model->inputNames[idx2]) - 1);
+ strncpy(model->inputNames[idx1], tname->data(), sizeof(model->inputNames[idx1]) - 1);
+
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
+ update();
+ emit modified();
+}
+
+bool InputsPanel::isInputIndex(const int index)
+{
+ if (index < 0)
+ return true;
+ else
+ return false;
+}
+
+bool InputsPanel::isExpoIndex(const int index)
+{
+ return !isInputIndex(index);
+}
+
+int InputsPanel::getIndexFromSelected()
+{
+ return ExposlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
+}
+
+int InputsPanel::getInputIndexFromSelected()
+{
+ const int selidx = getIndexFromSelected();
+ int idx;
+
+ if (isInputIndex(selidx))
+ idx = -selidx - 1;
+ else {
+ const ExpoData *ed = &model->expoData[selidx];
+ idx = ed->chn;
+ }
+ return idx;
+}
diff --git a/companion/src/modeledit/inputs.h b/companion/src/modeledit/inputs.h
index 939d0a647..884573fef 100644
--- a/companion/src/modeledit/inputs.h
+++ b/companion/src/modeledit/inputs.h
@@ -25,6 +25,8 @@
#include "mixerslistwidget.h"
#include "modelprinter.h"
+constexpr char MIMETYPE_EXPO[] = "application/x-companion-expo";
+
class InputsPanel : public ModelPanel
{
Q_OBJECT
@@ -52,12 +54,19 @@ class InputsPanel : public ModelPanel
void expoOpen(QListWidgetItem *item = NULL);
void expoAdd();
void maybeCopyInputName(int srcChan, int destChan);
+ void cmInputClear();
+ void cmInputDelete();
+ void cmInputInsert();
+ void cmInputMoveDown();
+ void cmInputMoveUp();
private:
bool expoInserted;
MixersListWidget *ExposlistWidget;
int inputsCount;
ModelPrinter modelPrinter;
+ int selectedIdx;
+ int inputIdx;
int getExpoIndex(unsigned int dch);
bool gm_insertExpo(int idx);
@@ -70,7 +79,14 @@ class InputsPanel : public ModelPanel
void pasteExpoMimeData(const QMimeData * mimeData, int destIdx);
void AddInputLine(int dest);
QString getInputText(int dest, bool newChan);
-
+ bool cmInputInsertAllowed() const;
+ bool cmInputMoveDownAllowed() const;
+ bool cmInputMoveUpAllowed() const;
+ void cmInputSwapData(int idx1, int idx2);
+ bool isInputIndex(const int index);
+ bool isExpoIndex(const int index);
+ int getIndexFromSelected();
+ int getInputIndexFromSelected();
};
#endif // _INPUTS_H_
diff --git a/companion/src/modeledit/logicalswitches.cpp b/companion/src/modeledit/logicalswitches.cpp
index 81f2f52e7..63a2ae22f 100644
--- a/companion/src/modeledit/logicalswitches.cpp
+++ b/companion/src/modeledit/logicalswitches.cpp
@@ -26,7 +26,7 @@
LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
ModelPanel(parent, model, generalSettings, firmware),
- selectedSwitch(0)
+ selectedIndex(0)
{
Stopwatch s1("LogicalSwitchesPanel");
@@ -35,19 +35,22 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
const int srcGroups = firmware->getCapability(GvarsInCS) ? 0 : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup);
rawSourceItemModel = new RawSourceFilterItemModel(&generalSettings, &model, srcGroups, this);
+ lsCapability = firmware->getCapability(LogicalSwitches);
+ lsCapabilityExt = firmware->getCapability(LogicalSwitchesExt);
+
QStringList headerLabels;
headerLabels << "#" << tr("Function") << tr("V1") << tr("V2") << tr("AND Switch");
- if (firmware->getCapability(LogicalSwitchesExt)) {
+ if (lsCapabilityExt) {
headerLabels << tr("Duration") << tr("Delay");
}
- TableLayout * tableLayout = new TableLayout(this, firmware->getCapability(LogicalSwitches), headerLabels);
+ TableLayout * tableLayout = new TableLayout(this, lsCapability, headerLabels);
s1.report("header");
const int channelsMax = model.getChannelsMax(true);
lock = true;
- for (int i=0; igetCapability(LogicalSwitches); i++) {
+ for (int i=0; isetProperty("index", i);
@@ -56,96 +59,96 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
label->setToolTip(tr("Popup menu available"));
label->setMouseTracking(true);
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
- connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(csw_customContextMenuRequested(QPoint)));
+ connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint)));
tableLayout->addWidget(i, 0, label);
// The function
- csw[i] = new QComboBox(this);
- csw[i]->setProperty("index", i);
- populateCSWCB(csw[i]);
- connect(csw[i], SIGNAL(currentIndexChanged(int)), this, SLOT(functionChanged()));
- tableLayout->addWidget(i, 1, csw[i]);
+ cbFunction[i] = new QComboBox(this);
+ cbFunction[i]->setProperty("index", i);
+ populateFunctionCB(cbFunction[i]);
+ connect(cbFunction[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onFunctionChanged()));
+ tableLayout->addWidget(i, 1, cbFunction[i]);
// V1
QHBoxLayout *v1Layout = new QHBoxLayout();
- cswitchSource1[i] = new QComboBox(this);
- cswitchSource1[i]->setProperty("index",i);
- connect(cswitchSource1[i], SIGNAL(currentIndexChanged(int)), this, SLOT(v1Edited(int)));
- v1Layout->addWidget(cswitchSource1[i]);
- cswitchSource1[i]->setVisible(false);
- cswitchValue[i] = new QDoubleSpinBox(this);
- cswitchValue[i]->setMaximum(channelsMax);
- cswitchValue[i]->setMinimum(-channelsMax);
- cswitchValue[i]->setAccelerated(true);
- cswitchValue[i]->setDecimals(0);
- cswitchValue[i]->setProperty("index", i);
- connect(cswitchValue[i], SIGNAL(editingFinished()), this, SLOT(offsetEdited()));
- v1Layout->addWidget(cswitchValue[i]);
- cswitchValue[i]->setVisible(false);
+ cbSource1[i] = new QComboBox(this);
+ cbSource1[i]->setProperty("index",i);
+ connect(cbSource1[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onV1Changed(int)));
+ v1Layout->addWidget(cbSource1[i]);
+ cbSource1[i]->setVisible(false);
+ dsbValue[i] = new QDoubleSpinBox(this);
+ dsbValue[i]->setMaximum(channelsMax);
+ dsbValue[i]->setMinimum(-channelsMax);
+ dsbValue[i]->setAccelerated(true);
+ dsbValue[i]->setDecimals(0);
+ dsbValue[i]->setProperty("index", i);
+ connect(dsbValue[i], SIGNAL(editingFinished()), this, SLOT(onOffsetChanged()));
+ v1Layout->addWidget(dsbValue[i]);
+ dsbValue[i]->setVisible(false);
tableLayout->addLayout(i, 2, v1Layout);
// V2
QHBoxLayout *v2Layout = new QHBoxLayout();
- cswitchSource2[i] = new QComboBox(this);
- cswitchSource2[i]->setProperty("index", i);
- connect(cswitchSource2[i], SIGNAL(currentIndexChanged(int)), this, SLOT(v2Edited(int)));
- v2Layout->addWidget(cswitchSource2[i]);
- cswitchSource2[i]->setVisible(false);
- cswitchOffset[i] = new QDoubleSpinBox(this);
- cswitchOffset[i]->setProperty("index",i);
- cswitchOffset[i]->setMaximum(channelsMax);
- cswitchOffset[i]->setMinimum(-channelsMax);
- cswitchOffset[i]->setAccelerated(true);
- cswitchOffset[i]->setDecimals(0);
- connect(cswitchOffset[i], SIGNAL(editingFinished()), this, SLOT(offsetEdited()));
- cswitchOffset[i]->setVisible(false);
- v2Layout->addWidget(cswitchOffset[i]);
- cswitchOffset2[i] = new QDoubleSpinBox(this);
- cswitchOffset2[i]->setProperty("index",i);
- cswitchOffset2[i]->setMaximum(channelsMax);
- cswitchOffset2[i]->setMinimum(-channelsMax);
- cswitchOffset2[i]->setAccelerated(true);
- cswitchOffset2[i]->setDecimals(0);
- cswitchOffset2[i]->setSpecialValueText(" " + tr("(instant)"));
- connect(cswitchOffset2[i], SIGNAL(editingFinished()), this, SLOT(offsetEdited()));
- cswitchOffset2[i]->setVisible(false);
- v2Layout->addWidget(cswitchOffset2[i]);
- cswitchTOffset[i] = new TimerEdit(this);
- cswitchTOffset[i]->setProperty("index",i);
- connect(cswitchTOffset[i],SIGNAL(editingFinished()),this,SLOT(offsetEdited()));
- v2Layout->addWidget(cswitchTOffset[i]);
- cswitchTOffset[i]->setVisible(false);
+ cbSource2[i] = new QComboBox(this);
+ cbSource2[i]->setProperty("index", i);
+ connect(cbSource2[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onV2Changed(int)));
+ v2Layout->addWidget(cbSource2[i]);
+ cbSource2[i]->setVisible(false);
+ dsbOffset[i] = new QDoubleSpinBox(this);
+ dsbOffset[i]->setProperty("index",i);
+ dsbOffset[i]->setMaximum(channelsMax);
+ dsbOffset[i]->setMinimum(-channelsMax);
+ dsbOffset[i]->setAccelerated(true);
+ dsbOffset[i]->setDecimals(0);
+ connect(dsbOffset[i], SIGNAL(editingFinished()), this, SLOT(onOffsetChanged()));
+ dsbOffset[i]->setVisible(false);
+ v2Layout->addWidget(dsbOffset[i]);
+ dsbOffset2[i] = new QDoubleSpinBox(this);
+ dsbOffset2[i]->setProperty("index",i);
+ dsbOffset2[i]->setMaximum(channelsMax);
+ dsbOffset2[i]->setMinimum(-channelsMax);
+ dsbOffset2[i]->setAccelerated(true);
+ dsbOffset2[i]->setDecimals(0);
+ dsbOffset2[i]->setSpecialValueText(" " + tr("(instant)"));
+ connect(dsbOffset2[i], SIGNAL(editingFinished()), this, SLOT(onOffsetChanged()));
+ dsbOffset2[i]->setVisible(false);
+ v2Layout->addWidget(dsbOffset2[i]);
+ teOffset[i] = new TimerEdit(this);
+ teOffset[i]->setProperty("index",i);
+ connect(teOffset[i],SIGNAL(editingFinished()),this,SLOT(onOffsetChanged()));
+ v2Layout->addWidget(teOffset[i]);
+ teOffset[i]->setVisible(false);
tableLayout->addLayout(i, 3, v2Layout);
// AND
- cswitchAnd[i] = new QComboBox(this);
- cswitchAnd[i]->setProperty("index", i);
- populateAndSwitchCB(cswitchAnd[i]);
- connect(cswitchAnd[i], SIGNAL(currentIndexChanged(int)), this, SLOT(andEdited(int)));
- tableLayout->addWidget(i, 4, cswitchAnd[i]);
+ cbAndSwitch[i] = new QComboBox(this);
+ cbAndSwitch[i]->setProperty("index", i);
+ populateAndSwitchCB(cbAndSwitch[i]);
+ connect(cbAndSwitch[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onAndSwitchChanged(int)));
+ tableLayout->addWidget(i, 4, cbAndSwitch[i]);
- if (firmware->getCapability(LogicalSwitchesExt)) {
+ if (lsCapabilityExt) {
// Duration
- cswitchDuration[i] = new QDoubleSpinBox(this);
- cswitchDuration[i]->setProperty("index", i);
- cswitchDuration[i]->setSingleStep(0.1);
- cswitchDuration[i]->setMaximum(25);
- cswitchDuration[i]->setMinimum(0);
- cswitchDuration[i]->setAccelerated(true);
- cswitchDuration[i]->setDecimals(1);
- connect(cswitchDuration[i], SIGNAL(valueChanged(double)), this, SLOT(durationEdited(double)));
- tableLayout->addWidget(i, 5, cswitchDuration[i]);
+ dsbDuration[i] = new QDoubleSpinBox(this);
+ dsbDuration[i]->setProperty("index", i);
+ dsbDuration[i]->setSingleStep(0.1);
+ dsbDuration[i]->setMaximum(25);
+ dsbDuration[i]->setMinimum(0);
+ dsbDuration[i]->setAccelerated(true);
+ dsbDuration[i]->setDecimals(1);
+ connect(dsbDuration[i], SIGNAL(valueChanged(double)), this, SLOT(onDurationChanged(double)));
+ tableLayout->addWidget(i, 5, dsbDuration[i]);
// Delay
- cswitchDelay[i] = new QDoubleSpinBox(this);
- cswitchDelay[i]->setProperty("index", i);
- cswitchDelay[i]->setSingleStep(0.1);
- cswitchDelay[i]->setMaximum(25);
- cswitchDelay[i]->setMinimum(0);
- cswitchDelay[i]->setAccelerated(true);
- cswitchDelay[i]->setDecimals(1);
- connect(cswitchDelay[i], SIGNAL(valueChanged(double)), this, SLOT(delayEdited(double)));
- tableLayout->addWidget(i, 6, cswitchDelay[i]);
+ dsbDelay[i] = new QDoubleSpinBox(this);
+ dsbDelay[i]->setProperty("index", i);
+ dsbDelay[i]->setSingleStep(0.1);
+ dsbDelay[i]->setMaximum(25);
+ dsbDelay[i]->setMinimum(0);
+ dsbDelay[i]->setAccelerated(true);
+ dsbDelay[i]->setDecimals(1);
+ connect(dsbDelay[i], SIGNAL(valueChanged(double)), this, SLOT(onDelayChanged(double)));
+ tableLayout->addWidget(i, 6, dsbDelay[i]);
}
}
@@ -155,7 +158,7 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
lock = false;
update();
tableLayout->resizeColumnsToContents();
- tableLayout->pushRowsUp(firmware->getCapability(LogicalSwitches)+1);
+ tableLayout->pushRowsUp(lsCapability+1);
s1.report("end");
}
@@ -172,10 +175,10 @@ void LogicalSwitchesPanel::updateDataModels()
lock = oldLock;
}
-void LogicalSwitchesPanel::functionChanged()
+void LogicalSwitchesPanel::onFunctionChanged()
{
int i = sender()->property("index").toInt();
- unsigned newFunc = csw[i]->currentData().toUInt();
+ unsigned newFunc = cbFunction[i]->currentData().toUInt();
if (model->logicalSw[i].func == newFunc)
return;
@@ -204,13 +207,13 @@ void LogicalSwitchesPanel::functionChanged()
emit modified();
}
-void LogicalSwitchesPanel::v1Edited(int value)
+void LogicalSwitchesPanel::onV1Changed(int value)
{
if (!lock) {
int i = sender()->property("index").toInt();
- model->logicalSw[i].val1 = cswitchSource1[i]->itemData(value).toInt();
+ model->logicalSw[i].val1 = cbSource1[i]->itemData(value).toInt();
if (model->logicalSw[i].getFunctionFamily() == LS_FAMILY_VOFS) {
- if (!offsetEditedAt(i))
+ if (!offsetChangedAt(i))
updateLine(i);
}
else {
@@ -219,25 +222,25 @@ void LogicalSwitchesPanel::v1Edited(int value)
}
}
-void LogicalSwitchesPanel::v2Edited(int value)
+void LogicalSwitchesPanel::onV2Changed(int value)
{
if (!lock) {
int i = sender()->property("index").toInt();
- model->logicalSw[i].val2 = cswitchSource2[i]->itemData(value).toInt();
+ model->logicalSw[i].val2 = cbSource2[i]->itemData(value).toInt();
emit modified();
}
}
-void LogicalSwitchesPanel::andEdited(int value)
+void LogicalSwitchesPanel::onAndSwitchChanged(int value)
{
if (!lock) {
int index = sender()->property("index").toInt();
- model->logicalSw[index].andsw = cswitchAnd[index]->itemData(value).toInt();
+ model->logicalSw[index].andsw = cbAndSwitch[index]->itemData(value).toInt();
emit modified();
}
}
-void LogicalSwitchesPanel::durationEdited(double duration)
+void LogicalSwitchesPanel::onDurationChanged(double duration)
{
if (!lock) {
int index = sender()->property("index").toInt();
@@ -246,7 +249,7 @@ void LogicalSwitchesPanel::durationEdited(double duration)
}
}
-void LogicalSwitchesPanel::delayEdited(double delay)
+void LogicalSwitchesPanel::onDelayChanged(double delay)
{
if (!lock) {
int index = sender()->property("index").toInt();
@@ -255,12 +258,12 @@ void LogicalSwitchesPanel::delayEdited(double delay)
}
}
-void LogicalSwitchesPanel::offsetEdited()
+void LogicalSwitchesPanel::onOffsetChanged()
{
- offsetEditedAt(sender()->property("index").toInt());
+ offsetChangedAt(sender()->property("index").toInt());
}
-bool LogicalSwitchesPanel::offsetEditedAt(int index)
+bool LogicalSwitchesPanel::offsetChangedAt(int index)
{
if (lock)
return false;
@@ -275,7 +278,7 @@ bool LogicalSwitchesPanel::offsetEditedAt(int index)
{
RawSource source = RawSource(model->logicalSw[index].val1);
RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[index].getRangeFlags());
- double currVal = source.isTimeBased() ? cswitchTOffset[index]->timeInSeconds() : cswitchOffset[index]->value();
+ double currVal = source.isTimeBased() ? teOffset[index]->timeInSeconds() : dsbOffset[index]->value();
value = round((currVal - range.offset) / range.step);
mod = (mod || value != model->logicalSw[index].val2);
model->logicalSw[index].val2 = value;
@@ -283,22 +286,22 @@ bool LogicalSwitchesPanel::offsetEditedAt(int index)
}
case LS_FAMILY_TIMER:
- value = TimToVal(cswitchValue[index]->value());
+ value = TimToVal(dsbValue[index]->value());
mod = (mod || value != model->logicalSw[index].val1);
model->logicalSw[index].val1 = value;
- value = TimToVal(cswitchOffset[index]->value());
+ value = TimToVal(dsbOffset[index]->value());
mod = (mod || value != model->logicalSw[index].val2);
model->logicalSw[index].val2 = value;
break;
case LS_FAMILY_EDGE:
- if (sender() == cswitchOffset[index]) {
- value = TimToVal(cswitchOffset[index]->value());
+ if (sender() == dsbOffset[index]) {
+ value = TimToVal(dsbOffset[index]->value());
mod = (mod || value != model->logicalSw[index].val2);
model->logicalSw[index].val2 = value;
}
else {
- value = TimToVal(cswitchOffset2[index]->value()) - model->logicalSw[index].val2;
+ value = TimToVal(dsbOffset2[index]->value()) - model->logicalSw[index].val2;
mod = (mod || value != model->logicalSw[index].val3);
model->logicalSw[index].val3 = value;
}
@@ -347,8 +350,8 @@ void LogicalSwitchesPanel::updateLine(int i)
lock = true;
unsigned int mask;
- csw[i]->setCurrentIndex(csw[i]->findData(model->logicalSw[i].func));
- cswitchAnd[i]->setCurrentIndex(cswitchAnd[i]->findData(RawSwitch(model->logicalSw[i].andsw).toValue()));
+ cbFunction[i]->setCurrentIndex(cbFunction[i]->findData(model->logicalSw[i].func));
+ cbAndSwitch[i]->setCurrentIndex(cbAndSwitch[i]->findData(RawSwitch(model->logicalSw[i].andsw).toValue()));
if (!model->logicalSw[i].func) {
mask = 0;
@@ -364,27 +367,27 @@ void LogicalSwitchesPanel::updateLine(int i)
RawSource source = RawSource(model->logicalSw[i].val1);
RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[i].getRangeFlags());
double value = range.step * model->logicalSw[i].val2 + range.offset; /* TODO+source.getRawOffset(model)*/
- cswitchSource1[i]->setModel(rawSourceItemModel);
- cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(source.toValue()));
+ cbSource1[i]->setModel(rawSourceItemModel);
+ cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(source.toValue()));
if (source.isTimeBased()) {
mask |= VALUE_TO_VISIBLE;
- cswitchTOffset[i]->setTimeRange(range.min, range.max);
- cswitchTOffset[i]->setSingleStep(range.step);
- cswitchTOffset[i]->setPageStep(range.step * 60);
- cswitchTOffset[i]->setShowSeconds(range.step != 60);
- cswitchTOffset[i]->setTime((int)value);
+ teOffset[i]->setTimeRange(range.min, range.max);
+ teOffset[i]->setSingleStep(range.step);
+ teOffset[i]->setPageStep(range.step * 60);
+ teOffset[i]->setShowSeconds(range.step != 60);
+ teOffset[i]->setTime((int)value);
}
else {
mask |= VALUE2_VISIBLE;
if (range.unit.isEmpty())
- cswitchOffset[i]->setSuffix("");
+ dsbOffset[i]->setSuffix("");
else
- cswitchOffset[i]->setSuffix(" " + range.unit);
- cswitchOffset[i]->setDecimals(range.decimals);
- cswitchOffset[i]->setMinimum(range.min);
- cswitchOffset[i]->setMaximum(range.max);
- cswitchOffset[i]->setSingleStep(range.step);
- cswitchOffset[i]->setValue(value);
+ dsbOffset[i]->setSuffix(" " + range.unit);
+ dsbOffset[i]->setDecimals(range.decimals);
+ dsbOffset[i]->setMinimum(range.min);
+ dsbOffset[i]->setMaximum(range.max);
+ dsbOffset[i]->setSingleStep(range.step);
+ dsbOffset[i]->setValue(value);
}
break;
@@ -393,58 +396,58 @@ void LogicalSwitchesPanel::updateLine(int i)
case LS_FAMILY_STICKY: // no break
case LS_FAMILY_VBOOL:
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
- cswitchSource1[i]->setModel(rawSwitchItemModel);
- cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(model->logicalSw[i].val1));
- cswitchSource2[i]->setModel(rawSwitchItemModel);
- cswitchSource2[i]->setCurrentIndex(cswitchSource2[i]->findData(model->logicalSw[i].val2));
+ cbSource1[i]->setModel(rawSwitchItemModel);
+ cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1));
+ cbSource2[i]->setModel(rawSwitchItemModel);
+ cbSource2[i]->setCurrentIndex(cbSource2[i]->findData(model->logicalSw[i].val2));
break;
case LS_FAMILY_EDGE:
mask |= SOURCE1_VISIBLE | VALUE2_VISIBLE | VALUE3_VISIBLE;
mask &= ~DELAY_ENABLED;
- cswitchSource1[i]->setModel(rawSwitchItemModel);
- cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(model->logicalSw[i].val1));
- updateTimerParam(cswitchOffset[i], model->logicalSw[i].val2, 0.0);
- updateTimerParam(cswitchOffset2[i], model->logicalSw[i].val2+model->logicalSw[i].val3, ValToTim(TimToVal(cswitchOffset[i]->value())-1));
- cswitchOffset2[i]->setSuffix((model->logicalSw[i].val3) ? "" : tr(" (infinite)"));
+ cbSource1[i]->setModel(rawSwitchItemModel);
+ cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1));
+ updateTimerParam(dsbOffset[i], model->logicalSw[i].val2, 0.0);
+ updateTimerParam(dsbOffset2[i], model->logicalSw[i].val2+model->logicalSw[i].val3, ValToTim(TimToVal(dsbOffset[i]->value())-1));
+ dsbOffset2[i]->setSuffix((model->logicalSw[i].val3) ? "" : tr(" (infinite)"));
break;
case LS_FAMILY_VCOMP:
mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE;
- cswitchSource1[i]->setModel(rawSourceItemModel);
- cswitchSource1[i]->setCurrentIndex(cswitchSource1[i]->findData(model->logicalSw[i].val1));
- cswitchSource2[i]->setModel(rawSourceItemModel);
- cswitchSource2[i]->setCurrentIndex(cswitchSource2[i]->findData(model->logicalSw[i].val2));
+ cbSource1[i]->setModel(rawSourceItemModel);
+ cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1));
+ cbSource2[i]->setModel(rawSourceItemModel);
+ cbSource2[i]->setCurrentIndex(cbSource2[i]->findData(model->logicalSw[i].val2));
break;
case LS_FAMILY_TIMER:
mask |= VALUE1_VISIBLE | VALUE2_VISIBLE;
- updateTimerParam(cswitchValue[i], model->logicalSw[i].val1, 0.1);
- updateTimerParam(cswitchOffset[i], model->logicalSw[i].val2, 0.1);
+ updateTimerParam(dsbValue[i], model->logicalSw[i].val1, 0.1);
+ updateTimerParam(dsbOffset[i], model->logicalSw[i].val2, 0.1);
break;
}
}
- cswitchSource1[i]->setVisible(mask & SOURCE1_VISIBLE);
- cswitchSource2[i]->setVisible(mask & SOURCE2_VISIBLE);
- cswitchValue[i]->setVisible(mask & VALUE1_VISIBLE);
- cswitchOffset[i]->setVisible(mask & VALUE2_VISIBLE);
- cswitchOffset2[i]->setVisible(mask & VALUE3_VISIBLE);
- cswitchTOffset[i]->setVisible(mask & VALUE_TO_VISIBLE);
- cswitchAnd[i]->setVisible(mask & LINE_ENABLED);
- if (firmware->getCapability(LogicalSwitchesExt)) {
- cswitchDuration[i]->setVisible(mask & DURATION_ENABLED);
- cswitchDelay[i]->setVisible(mask & DELAY_ENABLED);
+ cbSource1[i]->setVisible(mask & SOURCE1_VISIBLE);
+ cbSource2[i]->setVisible(mask & SOURCE2_VISIBLE);
+ dsbValue[i]->setVisible(mask & VALUE1_VISIBLE);
+ dsbOffset[i]->setVisible(mask & VALUE2_VISIBLE);
+ dsbOffset2[i]->setVisible(mask & VALUE3_VISIBLE);
+ teOffset[i]->setVisible(mask & VALUE_TO_VISIBLE);
+ cbAndSwitch[i]->setVisible(mask & LINE_ENABLED);
+ if (lsCapabilityExt) {
+ dsbDuration[i]->setVisible(mask & DURATION_ENABLED);
+ dsbDelay[i]->setVisible(mask & DELAY_ENABLED);
if (mask & DURATION_ENABLED)
- cswitchDuration[i]->setValue(model->logicalSw[i].duration/10.0);
+ dsbDuration[i]->setValue(model->logicalSw[i].duration/10.0);
if (mask & DELAY_ENABLED)
- cswitchDelay[i]->setValue(model->logicalSw[i].delay/10.0);
+ dsbDelay[i]->setValue(model->logicalSw[i].delay/10.0);
}
lock = false;
}
-void LogicalSwitchesPanel::populateCSWCB(QComboBox *b)
+void LogicalSwitchesPanel::populateFunctionCB(QComboBox *b)
{
int order[] = {
LS_FN_OFF,
@@ -476,10 +479,6 @@ void LogicalSwitchesPanel::populateCSWCB(QComboBox *b)
int func = order[i];
if (func == LS_FN_NEQUAL || func == LS_FN_EGREATER || func == LS_FN_ELESS)
continue;
- if (!IS_ARM(firmware->getBoard())) {
- if (func == LS_FN_VEQUAL || func == LS_FN_EDGE)
- continue;
- }
b->addItem(LogicalSwitchData(func).funcToString(), func);
}
b->setMaxVisibleItems(10);
@@ -487,90 +486,157 @@ void LogicalSwitchesPanel::populateCSWCB(QComboBox *b)
void LogicalSwitchesPanel::populateAndSwitchCB(QComboBox *b)
{
- if (IS_ARM(firmware->getBoard())) {
- b->setModel(rawSwitchItemModel);
- }
- else {
- RawSwitch item;
-
- b->clear();
-
- item = RawSwitch(SWITCH_TYPE_NONE);
- b->addItem(item.toString(), item.toValue());
-
- for (int i=1; i <= Boards::getCapability(firmware->getBoard(), Board::SwitchPositions); i++) {
- item = RawSwitch(SWITCH_TYPE_SWITCH, i);
- b->addItem(item.toString(), item.toValue());
- }
-
- for (int i=1; i<=6; i++) {
- item = RawSwitch(SWITCH_TYPE_VIRTUAL, i);
- b->addItem(item.toString(), item.toValue());
- }
- }
+ b->setModel(rawSwitchItemModel);
b->setVisible(true);
}
void LogicalSwitchesPanel::update()
{
updateDataModels();
- for (int i=0; igetCapability(LogicalSwitches); i++) {
+ for (int i=0; imimeData();
- if (mimeData->hasFormat("application/x-companion-csw")) {
- QByteArray cswData = mimeData->data("application/x-companion-csw");
- LogicalSwitchData *csw = &model->logicalSw[selectedSwitch];
- memcpy(csw, cswData.constData(), sizeof(LogicalSwitchData));
- update();
+ QByteArray data;
+ if (hasClipboardData(&data)) {
+ memcpy(&model->logicalSw[selectedIndex], data.constData(), sizeof(LogicalSwitchData));
+ updateDataModels();
+ updateLine(selectedIndex);
emit modified();
}
}
-void LogicalSwitchesPanel::cswDelete()
+void LogicalSwitchesPanel::cmDelete()
{
- model->logicalSw[selectedSwitch].clear();
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Logical Switch. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ memmove(&model->logicalSw[selectedIndex], &model->logicalSw[selectedIndex + 1], (CPN_MAX_LOGICAL_SWITCHES - (selectedIndex + 1)) * sizeof(LogicalSwitchData));
+ model->logicalSw[lsCapability - 1].clear();
+
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
+ update();
emit modified();
- updateLine(selectedSwitch);
}
-void LogicalSwitchesPanel::cswCopy()
+void LogicalSwitchesPanel::cmCopy()
{
- QByteArray cswData;
- cswData.append((char*)&model->logicalSw[selectedSwitch],sizeof(LogicalSwitchData));
+ QByteArray data;
+ data.append((char*)&model->logicalSw[selectedIndex], sizeof(LogicalSwitchData));
QMimeData *mimeData = new QMimeData;
- mimeData->setData("application/x-companion-csw", cswData);
+ mimeData->setData(MIMETYPE_LOGICAL_SWITCH, data);
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
}
-void LogicalSwitchesPanel::cswCut()
+void LogicalSwitchesPanel::cmCut()
{
- cswCopy();
- cswDelete();
+ cmCopy();
+ cmClear();
}
// TODO make something generic here!
-void LogicalSwitchesPanel::csw_customContextMenuRequested(QPoint pos)
+void LogicalSwitchesPanel::onCustomContextMenuRequested(QPoint pos)
{
- QLabel *label = (QLabel *)sender();
- selectedSwitch = label->property("index").toInt();
+ QLabel *label = (QLabel *)sender();
+ selectedIndex = label->property("index").toInt();
+ QPoint globalPos = label->mapToGlobal(pos);
- QPoint globalPos = label->mapToGlobal(pos);
+ QMenu contextMenu;
+ contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(cmCopy()));
+ contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(cmCut()));
+ contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData());
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear()));
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"),this,SLOT(cmInsert()))->setEnabled(insertAllowed());
+ contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"),this,SLOT(cmDelete()));
+ contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"),this,SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
+ contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"),this,SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll()));
- const QClipboard * clipboard = QApplication::clipboard();
- const QMimeData * mimeData = clipboard->mimeData();
- bool hasData = mimeData->hasFormat("application/x-companion-csw");
+ contextMenu.exec(globalPos);
+}
- QMenu contextMenu;
- contextMenu.addAction(CompanionIcon("copy.png"), tr("&Copy"),this,SLOT(cswCopy()));
- contextMenu.addAction(CompanionIcon("cut.png"), tr("&Cut"),this,SLOT(cswCut()));
- contextMenu.addAction(CompanionIcon("paste.png"), tr("&Paste"),this,SLOT(cswPaste()))->setEnabled(hasData);
- contextMenu.addAction(CompanionIcon("clear.png"), tr("&Delete"),this,SLOT(cswDelete()));
+bool LogicalSwitchesPanel::hasClipboardData(QByteArray * data) const
+{
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat(MIMETYPE_LOGICAL_SWITCH)) {
+ if (data)
+ data->append(mimeData->data(MIMETYPE_LOGICAL_SWITCH));
+ return true;
+ }
+ return false;
+}
- contextMenu.exec(globalPos);
+bool LogicalSwitchesPanel::insertAllowed() const
+{
+ return ((selectedIndex < lsCapability - 1) && (model->logicalSw[lsCapability - 1].isEmpty()));
+}
+
+bool LogicalSwitchesPanel::moveDownAllowed() const
+{
+ return selectedIndex < lsCapability - 1;
+}
+
+bool LogicalSwitchesPanel::moveUpAllowed() const
+{
+ return selectedIndex > 0;
+}
+
+void LogicalSwitchesPanel::cmMoveUp()
+{
+ swapData(selectedIndex, selectedIndex - 1);
+}
+
+void LogicalSwitchesPanel::cmMoveDown()
+{
+ swapData(selectedIndex, selectedIndex + 1);
+}
+
+void LogicalSwitchesPanel::cmClear()
+{
+ model->logicalSw[selectedIndex].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
+ update();
+ emit modified();
+}
+
+void LogicalSwitchesPanel::cmClearAll()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Logical Switches. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ for (int i=0; ilogicalSw[i].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, i);
+ }
+ update();
+ emit modified();
+}
+
+void LogicalSwitchesPanel::cmInsert()
+{
+ memmove(&model->logicalSw[selectedIndex + 1], &model->logicalSw[selectedIndex], (CPN_MAX_LOGICAL_SWITCHES - (selectedIndex + 1)) * sizeof(LogicalSwitchData));
+ model->logicalSw[selectedIndex].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
+ update();
+ emit modified();
+}
+
+void LogicalSwitchesPanel::swapData(int idx1, int idx2)
+{
+ if ((idx1 != idx2) && (!model->logicalSw[idx1].isEmpty() || !model->logicalSw[idx2].isEmpty())) {
+ LogicalSwitchData lstmp = model->logicalSw[idx2];
+ LogicalSwitchData *lsw1 = &model->logicalSw[idx1];
+ LogicalSwitchData *lsw2 = &model->logicalSw[idx2];
+ memcpy(lsw2, lsw1, sizeof(LogicalSwitchData));
+ memcpy(lsw1, &lstmp, sizeof(LogicalSwitchData));
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
+ update();
+ emit modified();
+ }
}
diff --git a/companion/src/modeledit/logicalswitches.h b/companion/src/modeledit/logicalswitches.h
index fde3df0f4..2aea300c5 100644
--- a/companion/src/modeledit/logicalswitches.h
+++ b/companion/src/modeledit/logicalswitches.h
@@ -28,6 +28,8 @@ class RawSwitchFilterItemModel;
class RawSourceFilterItemModel;
class TimerEdit;
+constexpr char MIMETYPE_LOGICAL_SWITCH[] = "application/x-companion-logical-switch";
+
class LogicalSwitchesPanel : public ModelPanel
{
Q_OBJECT
@@ -40,40 +42,50 @@ class LogicalSwitchesPanel : public ModelPanel
private slots:
void updateDataModels();
- void functionChanged();
- void v1Edited(int value);
- void v2Edited(int value);
- void andEdited(int value);
- void durationEdited(double duration);
- void delayEdited(double delay);
- void offsetEdited();
- bool offsetEditedAt(int index);
+ void onFunctionChanged();
+ void onV1Changed(int value);
+ void onV2Changed(int value);
+ void onAndSwitchChanged(int value);
+ void onDurationChanged(double duration);
+ void onDelayChanged(double delay);
+ void onOffsetChanged();
+ bool offsetChangedAt(int index);
void updateLine(int index);
- void csw_customContextMenuRequested(QPoint pos);
- void cswDelete();
- void cswCopy();
- void cswPaste();
- void cswCut();
+ void onCustomContextMenuRequested(QPoint pos);
+ void cmDelete();
+ void cmCopy();
+ void cmPaste();
+ void cmCut();
+ void cmMoveUp();
+ void cmMoveDown();
+ void cmInsert();
+ void cmClear();
+ void cmClearAll();
private:
- QComboBox * csw[CPN_MAX_LOGICAL_SWITCHES];
- QDoubleSpinBox * cswitchValue[CPN_MAX_LOGICAL_SWITCHES];
- QDoubleSpinBox * cswitchOffset[CPN_MAX_LOGICAL_SWITCHES];
- QDoubleSpinBox * cswitchOffset2[CPN_MAX_LOGICAL_SWITCHES];
- TimerEdit * cswitchTOffset[CPN_MAX_LOGICAL_SWITCHES];
- QComboBox * cswitchAnd[CPN_MAX_LOGICAL_SWITCHES];
- QDoubleSpinBox * cswitchDuration[CPN_MAX_LOGICAL_SWITCHES];
- QDoubleSpinBox * cswitchDelay[CPN_MAX_LOGICAL_SWITCHES];
- QComboBox * cswitchSource1[CPN_MAX_LOGICAL_SWITCHES];
- QComboBox * cswitchSource2[CPN_MAX_LOGICAL_SWITCHES];
+ QComboBox * cbFunction[CPN_MAX_LOGICAL_SWITCHES];
+ QDoubleSpinBox * dsbValue[CPN_MAX_LOGICAL_SWITCHES];
+ QDoubleSpinBox * dsbOffset[CPN_MAX_LOGICAL_SWITCHES];
+ QDoubleSpinBox * dsbOffset2[CPN_MAX_LOGICAL_SWITCHES];
+ TimerEdit * teOffset[CPN_MAX_LOGICAL_SWITCHES];
+ QComboBox * cbAndSwitch[CPN_MAX_LOGICAL_SWITCHES];
+ QDoubleSpinBox * dsbDuration[CPN_MAX_LOGICAL_SWITCHES];
+ QDoubleSpinBox * dsbDelay[CPN_MAX_LOGICAL_SWITCHES];
+ QComboBox * cbSource1[CPN_MAX_LOGICAL_SWITCHES];
+ QComboBox * cbSource2[CPN_MAX_LOGICAL_SWITCHES];
RawSwitchFilterItemModel * rawSwitchItemModel;
RawSourceFilterItemModel * rawSourceItemModel;
- int selectedSwitch;
-
- void populateCSWCB(QComboBox *b);
+ int selectedIndex;
+ void populateFunctionCB(QComboBox *b);
void populateAndSwitchCB(QComboBox *b);
void updateTimerParam(QDoubleSpinBox *sb, int timer, double minimum=0);
-
+ int lsCapability;
+ int lsCapabilityExt;
+ void swapData(int idx1, int idx2);
+ bool hasClipboardData(QByteArray * data = nullptr) const;
+ bool insertAllowed() const;
+ bool moveDownAllowed() const;
+ bool moveUpAllowed() const;
};
#endif // _LOGICALSWITCHES_H_
diff --git a/companion/src/modeledit/modeledit.cpp b/companion/src/modeledit/modeledit.cpp
index 59fb408c4..af3166c7f 100644
--- a/companion/src/modeledit/modeledit.cpp
+++ b/companion/src/modeledit/modeledit.cpp
@@ -65,7 +65,7 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw
s1.report("LS");
addTab(new CustomFunctionsPanel(this, &radioData.models[modelId], radioData.generalSettings, firmware), tr("Special Functions"));
s1.report("CF");
- if (firmware->getCapability(Telemetry) & TM_HASTELEMETRY)
+ if (firmware->getCapability(Telemetry))
addTab(new TelemetryPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Telemetry"));
onTabIndexChanged(ui->tabWidget->currentIndex()); // make sure to trigger update on default tab panel
diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp
index 77988a2e7..898596a6c 100644
--- a/companion/src/modeledit/setup.cpp
+++ b/companion/src/modeledit/setup.cpp
@@ -36,7 +36,6 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
timer(timer),
ui(new Ui::Timer)
{
- Board::Type board = firmware->getBoard();
ui->setupUi(this);
@@ -49,7 +48,7 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
}
else {
ui->name->setMaxLength(length);
- ui->name->setText(timer.name);
+ //ui->name->setText(timer.name);
}
// Mode
@@ -65,10 +64,8 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
ui->countdownBeep->setField(timer.countdownBeep, this);
ui->countdownBeep->addItem(tr("Silent"), TimerData::COUNTDOWN_SILENT);
ui->countdownBeep->addItem(tr("Beeps"), TimerData::COUNTDOWN_BEEPS);
- if (IS_ARM(board) || IS_2560(board)) {
- ui->countdownBeep->addItem(tr("Voice"), TimerData::COUNTDOWN_VOICE);
- ui->countdownBeep->addItem(tr("Haptic"), TimerData::COUNTDOWN_HAPTIC);
- }
+ ui->countdownBeep->addItem(tr("Voice"), TimerData::COUNTDOWN_VOICE);
+ ui->countdownBeep->addItem(tr("Haptic"), TimerData::COUNTDOWN_HAPTIC);
ui->value->setMaximumTime(firmware->getMaxTimerStart());
@@ -85,6 +82,7 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
QWidget::setTabOrder(ui->countdownBeep, ui->minuteBeep);
QWidget::setTabOrder(ui->minuteBeep, ui->persistent);
+ update();
lock = false;
}
@@ -95,6 +93,9 @@ TimerPanel::~TimerPanel()
void TimerPanel::update()
{
+ lock = true;
+ ui->name->setText(timer.name);
+
int hour = timer.val / 3600;
int min = (timer.val - (hour * 3600)) / 60;
int sec = (timer.val - (hour * 3600)) % 60;
@@ -116,7 +117,10 @@ void TimerPanel::update()
ui->persistentValue->setText(QString(" %1(%2:%3:%4)").arg(sign<0 ? "-" :" ").arg(hours, 2, 10, QLatin1Char('0')).arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0')));
}
+ ui->countdownBeep->updateValue();
ui->minuteBeep->setChecked(timer.minuteBeep);
+ ui->persistent->updateValue();
+ lock = false;
}
QWidget * TimerPanel::getLastFocus()
@@ -126,38 +130,43 @@ QWidget * TimerPanel::getLastFocus()
void TimerPanel::on_value_editingFinished()
{
- unsigned val = ui->value->time().hour()*3600 + ui->value->time().minute()*60 + ui->value->time().second();
- if (timer.val != val) {
- timer.val = val;
- emit modified();
+ if (!lock) {
+ unsigned val = ui->value->time().hour()*3600 + ui->value->time().minute()*60 + ui->value->time().second();
+ if (timer.val != val) {
+ timer.val = val;
+ emit modified();
+ }
}
}
void TimerPanel::onModeChanged(int index)
{
- if (lock)
- return;
-
- bool ok;
- const RawSwitch rs(ui->mode->itemData(index).toInt(&ok));
- if (ok && timer.mode.toValue() != rs.toValue()) {
- timer.mode = rs;
- emit modified();
+ if (!lock) {
+ bool ok;
+ const RawSwitch rs(ui->mode->itemData(index).toInt(&ok));
+ if (ok && timer.mode.toValue() != rs.toValue()) {
+ timer.mode = rs;
+ emit modified();
+ }
}
}
void TimerPanel::on_minuteBeep_toggled(bool checked)
{
- timer.minuteBeep = checked;
- emit modified();
+ if (!lock) {
+ timer.minuteBeep = checked;
+ emit modified();
+ }
}
void TimerPanel::on_name_editingFinished()
{
- if (QString(timer.name) != ui->name->text()) {
- int length = ui->name->maxLength();
- strncpy(timer.name, ui->name->text().toLatin1(), length);
- emit modified();
+ if (!lock) {
+ if (QString(timer.name) != ui->name->text()) {
+ int length = ui->name->maxLength();
+ strncpy(timer.name, ui->name->text().toLatin1(), length);
+ emit modified();
+ }
}
}
@@ -180,6 +189,8 @@ void TimerPanel::on_name_editingFinished()
#define MASK_SBUSPPM_FIELDS (1<<11)
#define MASK_SUBTYPES (1<<12)
#define MASK_ACCESS (1<<13)
+#define MASK_RX_FREQ (1<<14)
+#define MASK_RF_POWER (1<<15)
quint8 ModulePanel::failsafesValueDisplayType = ModulePanel::FAILSAFE_DISPLAY_PERCENT;
@@ -195,7 +206,7 @@ ModulePanel::ModulePanel(QWidget * parent, ModelData & model, ModuleData & modul
ui->label_module->setText(ModuleData::indexToString(moduleIdx, firmware));
if (moduleIdx < 0) {
- if (!IS_TARANIS(firmware->getBoard())) {
+ if (!IS_TARANIS(firmware->getBoard()) || IS_ACCESS_RADIO(firmware->getBoard(), Firmware::getCurrentVariant()->getId())) {
ui->trainerMode->setItemData(TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, 0, Qt::UserRole - 1);
ui->trainerMode->setItemData(TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE, 0, Qt::UserRole - 1);
ui->trainerMode->setItemData(TRAINER_MODE_MASTER_BATTERY_COMPARTMENT, 0, Qt::UserRole - 1);
@@ -209,7 +220,7 @@ ModulePanel::ModulePanel(QWidget * parent, ModelData & model, ModuleData & modul
ui->trainerMode->setItemData(TRAINER_MODE_SLAVE_BLUETOOTH, 0, Qt::UserRole - 1);
}
- if (!IS_JUMPER_T16(firmware->getBoard())) {
+ if (!IS_FAMILY_T16(firmware->getBoard())) {
ui->trainerMode->setItemData(TRAINER_MODE_MULTI, 0, Qt::UserRole - 1);
}
@@ -259,7 +270,7 @@ ModulePanel::ModulePanel(QWidget * parent, ModelData & model, ModuleData & modul
connect(ui->multiProtocol, static_cast(&QComboBox::currentIndexChanged), this, &ModulePanel::onMultiProtocolChanged);
connect(this, &ModulePanel::channelsRangeChanged, this, &ModulePanel::setupFailsafes);
connect(ui->btnGrpValueType, static_cast(&QButtonGroup::buttonClicked), this, &ModulePanel::onFailsafesDisplayValueTypeChanged);
-
+ connect(ui->rxFreq, static_cast(&QSpinBox::valueChanged), this, &ModulePanel::onRfFreqChanged);
connect(ui->clearRx1, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked()));
connect(ui->clearRx2, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked()));
connect(ui->clearRx3, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked()));
@@ -273,27 +284,12 @@ ModulePanel::~ModulePanel()
delete ui;
}
-bool ModulePanel::moduleHasFailsafes()
-{
- return firmware->getCapability(HasFailsafe) && (
- (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_ISRM ||
- (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCST_ISRM_D16 ||
- (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_XJT_X16 ||
- (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_R9M ||
- (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_R9M ||
- (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_R9M_LITE ||
- (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_R9M_LITE_PRO ||
- (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_XJT_LITE_X16 ||
- (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_MULTIMODULE
- );
-}
-
void ModulePanel::setupFailsafes()
{
ChannelFailsafeWidgetsGroup grp;
const int start = module.channelsStart;
const int end = start + module.channelsCount;
- const bool hasFailsafe = moduleHasFailsafes();
+ const bool hasFailsafe = module.hasFailsafes(firmware);
lock = true;
@@ -382,48 +378,6 @@ void ModulePanel::setupFailsafes()
lock = false;
}
-int ModulePanel::getMaxChannelCount()
-{
- const PulsesProtocol protocol = (PulsesProtocol)module.protocol;
- switch (protocol) {
- case PULSES_ACCESS_ISRM:
- return 24;
- case PULSES_PXX_R9M:
- case PULSES_ACCESS_R9M:
- case PULSES_ACCESS_R9M_LITE:
- case PULSES_ACCESS_R9M_LITE_PRO:
- case PULSES_ACCST_ISRM_D16:
- case PULSES_XJT_LITE_X16:
- case PULSES_PXX_XJT_X16:
- case PULSES_CROSSFIRE:
- case PULSES_SBUS:
- case PULSES_PPM:
- return 16;
- case PULSES_XJT_LITE_LR12:
- case PULSES_PXX_XJT_LR12:
- return 12;
- case PULSES_PXX_DJT:
- case PULSES_XJT_LITE_D8:
- case PULSES_PXX_XJT_D8:
- return 8;
- case PULSES_LP45:
- case PULSES_DSM2:
- case PULSES_DSMX:
- return 6;
- case PULSES_MULTIMODULE:
- if (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2)
- return 12;
- else
- return 16;
- break;
- case PULSES_OFF:
- break;
- default:
- break;
- }
- return 8;
-}
-
void ModulePanel::update()
{
const PulsesProtocol protocol = (PulsesProtocol)module.protocol;
@@ -436,7 +390,7 @@ void ModulePanel::update()
mask |= MASK_PROTOCOL;
switch (protocol) {
case PULSES_PXX_R9M:
- mask |= MASK_R9M | MASK_SUBTYPES;
+ mask |= MASK_R9M | MASK_RF_POWER | MASK_SUBTYPES;
case PULSES_ACCESS_R9M:
case PULSES_ACCESS_R9M_LITE:
case PULSES_ACCESS_R9M_LITE_PRO:
@@ -495,6 +449,11 @@ void ModulePanel::update()
if (pdef.hasFailsafe || (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_FRSKY && (module.subType == 0 || module.subType == 2 || module.subType > 3 )))
mask |= MASK_FAILSAFES;
break;
+ case PULSES_AFHDS3:
+ module.channelsCount = 18;
+ mask |= MASK_CHANNELS_RANGE| MASK_CHANNELS_COUNT | MASK_FAILSAFES;
+ mask |= MASK_SUBTYPES | MASK_RX_FREQ | MASK_RF_POWER;
+ break;
case PULSES_OFF:
break;
default:
@@ -510,7 +469,7 @@ void ModulePanel::update()
mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
}
- if (moduleHasFailsafes()) {
+ if (module.hasFailsafes(firmware)) {
mask |= MASK_FAILSAFES;
}
@@ -527,7 +486,7 @@ void ModulePanel::update()
ui->label_channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
ui->channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
ui->channelsCount->setEnabled(mask & MASK_CHANNELS_COUNT);
- ui->channelsCount->setMaximum(getMaxChannelCount());
+ ui->channelsCount->setMaximum(module.getMaxChannelCount());
ui->channelsCount->setValue(module.channelsCount);
ui->channelsCount->setSingleStep(firmware->getCapability(HasPPMStart) ? 1 : 2);
@@ -561,16 +520,16 @@ void ModulePanel::update()
}
// R9M options
- ui->r9mPower->setVisible(mask & MASK_R9M);
- ui->label_r9mPower->setVisible(mask & MASK_R9M);
+ ui->r9mPower->setVisible(mask & MASK_RF_POWER);
+ ui->label_r9mPower->setVisible(mask & MASK_RF_POWER);
ui->warning_r9mPower->setVisible((mask & MASK_R9M) && module.subType == MODULE_SUBTYPE_R9M_EU);
ui->warning_r9mFlex->setVisible((mask & MASK_R9M) && module.subType > MODULE_SUBTYPE_R9M_EU);
- if (mask & MASK_R9M) {
+ if (mask & MASK_RF_POWER) {
const QSignalBlocker blocker(ui->r9mPower);
ui->r9mPower->clear();
- ui->r9mPower->addItems(ModuleData::powerValueStrings(module.subType, firmware));
- ui->r9mPower->setCurrentIndex(module.pxx.power);
+ ui->r9mPower->addItems(ModuleData::powerValueStrings(protocol, module.subType, firmware));
+ ui->r9mPower->setCurrentIndex(mask & MASK_R9M ? module.pxx.power : module.afhds3.rfPower);
}
// module subtype
@@ -587,6 +546,9 @@ void ModulePanel::update()
if (firmware->getCapability(HasModuleR9MFlex))
i = 2;
break;
+ case PULSES_AFHDS3:
+ numEntries = 4;
+ break;
default:
break;
}
@@ -608,7 +570,7 @@ void ModulePanel::update()
ui->lowPower->setVisible(mask & MASK_MULTIMODULE);
ui->autoBind->setVisible(mask & MASK_MULTIMODULE);
if (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2)
- ui->autoBind->setText(tr("Autodetect Format"));
+ ui->autoBind->setVisible(false);
else
ui->autoBind->setText(tr("Bind on channel"));
@@ -651,6 +613,8 @@ void ModulePanel::update()
// Failsafes
ui->label_failsafeMode->setVisible(mask & MASK_FAILSAFES);
ui->failsafeMode->setVisible(mask & MASK_FAILSAFES);
+ //hide reciever mode for afhds3
+ qobject_cast(ui->failsafeMode->view())->setRowHidden(FAILSAFE_RECEIVER, protocol == PULSES_AFHDS3);
if ((mask & MASK_FAILSAFES) && module.failsafeMode == FAILSAFE_CUSTOM) {
if (ui->failsafesGroupBox->isHidden()) {
@@ -680,6 +644,9 @@ void ModulePanel::update()
}
}
}
+
+ ui->label_rxFreq->setVisible((mask & MASK_RX_FREQ));
+ ui->rxFreq->setVisible((mask & MASK_RX_FREQ));
}
void ModulePanel::on_trainerMode_currentIndexChanged(int index)
@@ -695,7 +662,7 @@ void ModulePanel::onProtocolChanged(int index)
{
if (!lock && module.protocol != ui->protocol->itemData(index).toUInt()) {
module.protocol = ui->protocol->itemData(index).toInt();
- module.channelsCount = getMaxChannelCount();
+ module.channelsCount = module.getMaxChannelCount();
update();
emit modified();
}
@@ -711,9 +678,14 @@ void ModulePanel::on_ppmPolarity_currentIndexChanged(int index)
void ModulePanel::on_r9mPower_currentIndexChanged(int index)
{
- if (!lock && module.pxx.power != (unsigned int)index) {
- module.pxx.power = index;
- emit modified();
+ if (!lock) {
+
+ if (module.protocol == PULSES_AFHDS3 && module.afhds3.rfPower != (unsigned int)index) {
+ module.afhds3.rfPower = index;
+ emit modified();
+ }
+ else if(module.pxx.power != (unsigned int)index)
+ module.pxx.power = index;
}
}
@@ -790,7 +762,7 @@ void ModulePanel::onMultiProtocolChanged(int index)
if (rfProtocol > MODULE_SUBTYPE_MULTI_LAST)
maxSubTypes=8;
module.subType = std::min(module.subType, maxSubTypes -1);
- module.channelsCount = getMaxChannelCount();
+ module.channelsCount = module.getMaxChannelCount();
update();
emit modified();
lock = false;
@@ -811,12 +783,21 @@ void ModulePanel::onSubTypeChanged()
if (!lock && module.subType != type) {
lock=true;
module.subType = type;
- update();
+ if (module.protocol != PULSES_AFHDS3) {
+ update();
+ }
emit modified();
lock = false;
}
}
+void ModulePanel::onRfFreqChanged(int freq) {
+ if (module.afhds3.rxFreq != (unsigned int)freq) {
+ module.afhds3.rxFreq = (unsigned int)freq;
+ emit modified();
+ }
+}
+
void ModulePanel::on_disableTelem_stateChanged(int state)
{
module.multi.disableTelemetry = (state == Qt::Checked);
@@ -837,18 +818,22 @@ void ModulePanel::on_lowPower_stateChanged(int state)
module.multi.lowPowerMode = (state == Qt::Checked);
}
-// updtSb (update spin box(es)): 0=none or bitmask of FailsafeValueDisplayTypes
-void ModulePanel::setChannelFailsafeValue(const int channel, const int value, quint8 updtSb)
+void ModulePanel::onFailsafeModified(unsigned channel)
{
- if (channel < 0 || channel >= CPN_MAX_CHNOUT)
- return;
+ updateFailsafeUI(channel, FAILSAFE_DISPLAY_PERCENT | FAILSAFE_DISPLAY_USEC);
+}
- module.failsafeChannels[channel] = value;
+void ModulePanel::updateFailsafeUI(unsigned channel, quint8 updtSb)
+{
+ int value = model->limitData[channel].failsafe;
double pctVal = divRoundClosest(value * 1000, 1024) / 10.0;
- // qDebug() << value << pctVal;
if (failsafeGroupsMap.contains(channel)) {
const ChannelFailsafeWidgetsGroup & grp = failsafeGroupsMap.value(channel);
+ bool disable = (value == FAILSAFE_CHANNEL_HOLD || value == FAILSAFE_CHANNEL_NOPULSE);
+ if (grp.combo) {
+ grp.combo->setCurrentIndex(grp.combo->findData(disable ? value : 0));
+ }
if ((updtSb & FAILSAFE_DISPLAY_PERCENT) && grp.sbPercent) {
grp.sbPercent->blockSignals(true);
grp.sbPercent->setValue(pctVal);
@@ -860,8 +845,21 @@ void ModulePanel::setChannelFailsafeValue(const int channel, const int value, qu
grp.sbUsec->blockSignals(false);
}
}
- if (!lock)
+}
+
+// updtSb (update spin box(es)): 0=none or bitmask of FailsafeValueDisplayTypes
+void ModulePanel::setChannelFailsafeValue(const int channel, const int value, quint8 updtSb)
+{
+ if (channel < 0 || channel >= CPN_MAX_CHNOUT)
+ return;
+
+ model->limitData[channel].failsafe = value;
+ updateFailsafeUI(channel, updtSb);
+
+ if (!lock) {
+ emit failsafeModified(channel);
emit modified();
+ }
}
void ModulePanel::onFailsafeUsecChanged(int value)
@@ -898,8 +896,9 @@ void ModulePanel::onFailsafeComboIndexChanged(int index)
bool ok = false;
int channel = sender()->property("index").toInt(&ok);
if (ok) {
- module.failsafeChannels[channel] = cb->itemData(index).toInt();
+ model->limitData[channel].failsafe = cb->itemData(index).toInt();
updateFailsafe(channel);
+ emit failsafeModified(channel);
emit modified();
}
lock = false;
@@ -931,12 +930,12 @@ void ModulePanel::onExtendedLimitsToggled()
}
}
-void ModulePanel::updateFailsafe(int channel)
+void ModulePanel::updateFailsafe(unsigned channel)
{
if (channel >= CPN_MAX_CHNOUT || !failsafeGroupsMap.contains(channel))
return;
- const int failsafeValue = module.failsafeChannels[channel];
+ const int failsafeValue = model->limitData[channel].failsafe;
const ChannelFailsafeWidgetsGroup & grp = failsafeGroupsMap.value(channel);
const bool valDisable = (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE);
@@ -948,7 +947,7 @@ void ModulePanel::updateFailsafe(int channel)
grp.sbUsec->setDisabled(valDisable);
if (!valDisable)
- setChannelFailsafeValue(channel, failsafeValue, (FAILSAFE_DISPLAY_PERCENT | FAILSAFE_DISPLAY_USEC));
+ setChannelFailsafeValue(channel, failsafeValue, FAILSAFE_DISPLAY_PERCENT | FAILSAFE_DISPLAY_USEC);
}
void ModulePanel::onClearAccessRxClicked()
@@ -1001,7 +1000,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
QDir qd(path);
if (qd.exists()) {
QStringList filters;
- if(IS_HORUS(board)) {
+ if(IS_FAMILY_HORUS_OR_T16(board)) {
filters << "*.bmp" << "*.jpg" << "*.png";
foreach ( QString file, qd.entryList(filters, QDir::Files) ) {
QFileInfo fi(file);
@@ -1032,17 +1031,17 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
ui->image->setCurrentIndex(ui->image->count()-1);
QString fileName = path;
fileName.append(model.bitmap);
- if (!IS_HORUS(board))
+ if (!IS_FAMILY_HORUS_OR_T16(board))
fileName.append(".bmp");
QImage image(fileName);
- if (image.isNull() && !IS_HORUS(board)) {
+ if (image.isNull() && !IS_FAMILY_HORUS_OR_T16(board)) {
fileName = path;
fileName.append(model.bitmap);
fileName.append(".BMP");
image.load(fileName);
}
if (!image.isNull()) {
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
ui->imagePreview->setFixedSize(QSize(192, 114));
ui->imagePreview->setPixmap(QPixmap::fromImage(image.scaled(192, 114)));
}
@@ -1064,16 +1063,28 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
RawSwitchFilterItemModel * swModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::TimersContext, this);
connect(this, &SetupPanel::updated, swModel, &RawSwitchFilterItemModel::update);
- for (int i=0; igetCapability(Timers)) {
+ timersCount = firmware->getCapability(Timers);
+
+ for (int i = 0; i < CPN_MAX_TIMERS; i++) {
+ if (i < timersCount) {
timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus, swModel);
ui->gridLayout->addWidget(timers[i], 1+i, 1);
connect(timers[i], &TimerPanel::modified, this, &SetupPanel::modified);
connect(this, &SetupPanel::updated, timers[i], &TimerPanel::update);
+ connect(this, &SetupPanel::timerUpdated, timers[i], &TimerPanel::update);
prevFocus = timers[i]->getLastFocus();
+ // TODO more reliable method required
+ QLabel *label = findChild(QString("label_timer%1").arg(i + 1));
+ if (label) { // to stop crashing if not found
+ label->setProperty("index", i);
+ label->setContextMenuPolicy(Qt::CustomContextMenu);
+ label->setToolTip(tr("Popup menu available"));
+ label->setMouseTracking(true);
+ connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onTimerCustomContextMenuRequested(QPoint)));
+ }
}
else {
- foreach(QLabel *label, findChildren(QRegularExpression(QString("label_timer%1").arg(i+1)))) {
+ foreach(QLabel *label, findChildren(QRegularExpression(QString("label_timer%1").arg(i + 1 )))) { //TODO more reliable method required
label->hide();
}
}
@@ -1081,9 +1092,9 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
if (firmware->getCapability(HasTopLcd)) {
ui->toplcdTimer->setField(model.toplcdTimer, this);
- for (int i=0; igetCapability(Timers)) {
- ui->toplcdTimer->addItem(tr("Timer %1").arg(i+1), i);
+ for (int i = 0; i < CPN_MAX_TIMERS; i++) {
+ if (itoplcdTimer->addItem(tr("Timer %1").arg(i + 1), i);
}
}
}
@@ -1191,21 +1202,23 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
ui->potWarningMode->hide();
}
- if (IS_ARM(board)) {
- ui->trimsDisplay->setField(model.trimsDisplay, this);
- }
- else {
- ui->labelTrimsDisplay->hide();
- ui->trimsDisplay->hide();
- }
+ ui->trimsDisplay->setField(model.trimsDisplay, this);
- for (int i=firmware->getCapability(NumFirstUsableModule); igetCapability(NumModules); i++) {
+ for (int i = firmware->getCapability(NumFirstUsableModule); i < firmware->getCapability(NumModules); i++) {
modules[i] = new ModulePanel(this, model, model.moduleData[i], generalSettings, firmware, i);
ui->modulesLayout->addWidget(modules[i]);
connect(modules[i], &ModulePanel::modified, this, &SetupPanel::modified);
connect(this, &SetupPanel::extendedLimitsToggled, modules[i], &ModulePanel::onExtendedLimitsToggled);
}
+ for (int i = firmware->getCapability(NumFirstUsableModule); i < firmware->getCapability(NumModules); i++) {
+ for (int j = firmware->getCapability(NumFirstUsableModule); j < firmware->getCapability(NumModules); j++) {
+ if (i != j) {
+ connect(modules[i], SIGNAL(failsafeModified(unsigned)), modules[j], SLOT(onFailsafeModified(unsigned)));
+ }
+ }
+ }
+
if (firmware->getCapability(ModelTrainerEnable)) {
modules[CPN_MAX_MODULES] = new ModulePanel(this, model, model.moduleData[CPN_MAX_MODULES], generalSettings, firmware, -1);
ui->modulesLayout->addWidget(modules[CPN_MAX_MODULES]);
@@ -1281,17 +1294,17 @@ void SetupPanel::on_image_currentIndexChanged(int index)
if (qd.exists()) {
QString fileName=path;
fileName.append(model->bitmap);
- if (!IS_HORUS(board))
+ if (!IS_FAMILY_HORUS_OR_T16(board))
fileName.append(".bmp");
QImage image(fileName);
- if (image.isNull() && !IS_HORUS(board)) {
+ if (image.isNull() && !IS_FAMILY_HORUS_OR_T16(board)) {
fileName=path;
fileName.append(model->bitmap);
fileName.append(".BMP");
image.load(fileName);
}
if (!image.isNull()) {
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
ui->imagePreview->setFixedSize(QSize(192, 114));
ui->imagePreview->setPixmap(QPixmap::fromImage(image.scaled(192, 114)));
}
@@ -1528,3 +1541,155 @@ void SetupPanel::on_editText_clicked()
}
}
+void SetupPanel::onTimerCustomContextMenuRequested(QPoint pos)
+{
+ QLabel *label = (QLabel *)sender();
+ selectedTimerIndex = label->property("index").toInt();
+ QPoint globalPos = label->mapToGlobal(pos);
+
+ QMenu contextMenu;
+ contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(cmTimerCopy()));
+ contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(cmTimerCut()));
+ contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(cmTimerPaste()))->setEnabled(hasTimerClipboardData());
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmTimerClear()));
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmTimerInsert()))->setEnabled(insertTimerAllowed());
+ contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmTimerDelete()));
+ contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(cmTimerMoveUp()))->setEnabled(moveTimerUpAllowed());
+ contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(cmTimerMoveDown()))->setEnabled(moveTimerDownAllowed());
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(cmTimerClearAll()));
+
+ contextMenu.exec(globalPos);
+}
+
+bool SetupPanel::hasTimerClipboardData(QByteArray * data) const
+{
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat(MIMETYPE_TIMER)) {
+ if (data)
+ data->append(mimeData->data(MIMETYPE_TIMER));
+ return true;
+ }
+ return false;
+}
+
+bool SetupPanel::insertTimerAllowed() const
+{
+ return ((selectedTimerIndex < timersCount - 1) && (model->timers[timersCount - 1].isEmpty()));
+}
+
+bool SetupPanel::moveTimerDownAllowed() const
+{
+ return selectedTimerIndex < timersCount - 1;
+}
+
+bool SetupPanel::moveTimerUpAllowed() const
+{
+ return selectedTimerIndex > 0;
+}
+
+void SetupPanel::cmTimerClear()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ model->timers[selectedTimerIndex].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, selectedTimerIndex);
+ emit timerUpdated();
+ emit modified();
+}
+
+void SetupPanel::cmTimerClearAll()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Timers. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ for (int i = 0; i < timersCount; i++) {
+ model->timers[i].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, i);
+ }
+ emit timerUpdated();
+ emit modified();
+}
+
+void SetupPanel::cmTimerCopy()
+{
+ QByteArray data;
+ data.append((char*)&model->timers[selectedTimerIndex], sizeof(TimerData));
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData(MIMETYPE_TIMER, data);
+ QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
+}
+
+void SetupPanel::cmTimerCut()
+{
+ cmTimerCopy();
+ cmTimerClear();
+}
+
+void SetupPanel::cmTimerDelete()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ int maxidx = timersCount - 1;
+ for (int i = selectedTimerIndex; i < maxidx; i++) {
+ if (!model->timers[i].isEmpty() || !model->timers[i + 1].isEmpty()) {
+ memcpy(&model->timers[i], &model->timers[i+1], sizeof(TimerData));
+ }
+ }
+ model->timers[maxidx].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, -1);
+ emit timerUpdated();
+ emit modified();
+}
+
+void SetupPanel::cmTimerInsert()
+{
+ for (int i = (timersCount - 1); i > selectedTimerIndex; i--) {
+ if (!model->timers[i].isEmpty() || !model->timers[i-1].isEmpty()) {
+ memcpy(&model->timers[i], &model->timers[i-1], sizeof(TimerData));
+ }
+ }
+ model->timers[selectedTimerIndex].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, 1);
+ emit timerUpdated();
+ emit modified();
+}
+
+void SetupPanel::cmTimerMoveDown()
+{
+ swapTimerData(selectedTimerIndex, selectedTimerIndex + 1);
+}
+
+void SetupPanel::cmTimerMoveUp()
+{
+ swapTimerData(selectedTimerIndex, selectedTimerIndex - 1);
+}
+
+void SetupPanel::cmTimerPaste()
+{
+ QByteArray data;
+ if (hasTimerClipboardData(&data)) {
+ TimerData *td = &model->timers[selectedTimerIndex];
+ memcpy(td, data.constData(), sizeof(TimerData));
+ emit timerUpdated();
+ emit modified();
+ }
+}
+
+void SetupPanel::swapTimerData(int idx1, int idx2)
+{
+ if ((idx1 != idx2) && (!model->timers[idx1].isEmpty() || !model->timers[idx2].isEmpty())) {
+ TimerData tdtmp = model->timers[idx2];
+ TimerData *td1 = &model->timers[idx1];
+ TimerData *td2 = &model->timers[idx2];
+ memcpy(td2, td1, sizeof(TimerData));
+ memcpy(td1, &tdtmp, sizeof(TimerData));
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
+ emit timerUpdated();
+ emit modified();
+ }
+}
diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h
index 586cba07d..fbd56ed86 100644
--- a/companion/src/modeledit/setup.h
+++ b/companion/src/modeledit/setup.h
@@ -24,6 +24,8 @@
#include "modeledit.h"
#include "eeprominterface.h"
+constexpr char MIMETYPE_TIMER[] = "application/x-companion-timer";
+
class RawSwitchFilterItemModel;
namespace Ui {
@@ -59,19 +61,19 @@ class ModulePanel : public ModelPanel
Q_OBJECT
public:
- ModulePanel(QWidget *parent, ModelData & model, ModuleData & module, GeneralSettings & generalSettings, Firmware * firmware, int moduleIdx);
+ ModulePanel(QWidget * parent, ModelData & model, ModuleData & module, GeneralSettings & generalSettings, Firmware * firmware, int moduleIdx);
virtual ~ModulePanel();
virtual void update();
- bool moduleHasFailsafes();
public slots:
void onExtendedLimitsToggled();
+ void onFailsafeModified(unsigned index);
signals:
void channelsRangeChanged();
+ void failsafeModified(unsigned index);
private slots:
- int getMaxChannelCount();
void setupFailsafes();
void on_trainerMode_currentIndexChanged(int index);
void onProtocolChanged(int index);
@@ -95,7 +97,8 @@ class ModulePanel : public ModelPanel
void onFailsafeUsecChanged(int value);
void onFailsafePercentChanged(double value);
void onFailsafesDisplayValueTypeChanged(int type);
- void updateFailsafe(int channel);
+ void onRfFreqChanged(int freq);
+ void updateFailsafe(unsigned channel);
void on_optionValue_editingFinished();
void onClearAccessRxClicked();
@@ -114,6 +117,7 @@ class ModulePanel : public ModelPanel
Ui::Module *ui;
QMap failsafeGroupsMap;
static quint8 failsafesValueDisplayType; // FailsafeValueDisplayTypes
+ void updateFailsafeUI(unsigned channel, quint8 updtSb);
};
class SetupPanel : public ModelPanel
@@ -129,6 +133,7 @@ class SetupPanel : public ModelPanel
signals:
void extendedLimitsToggled();
void updated();
+ void timerUpdated();
private slots:
void on_name_editingFinished();
@@ -148,6 +153,16 @@ class SetupPanel : public ModelPanel
void potWarningToggled(bool checked);
void on_potWarningMode_currentIndexChanged(int index);
void on_editText_clicked();
+ void onTimerCustomContextMenuRequested(QPoint pos);
+ void cmTimerClear();
+ void cmTimerClearAll();
+ void cmTimerCopy();
+ void cmTimerCut();
+ void cmTimerDelete();
+ void cmTimerInsert();
+ void cmTimerPaste();
+ void cmTimerMoveDown();
+ void cmTimerMoveUp();
private:
Ui::Setup *ui;
@@ -161,6 +176,13 @@ class SetupPanel : public ModelPanel
void updatePotWarnings();
void updateBeepCenter();
void populateThrottleSourceCB();
+ int timersCount;
+ int selectedTimerIndex;
+ bool hasTimerClipboardData(QByteArray * data = nullptr) const;
+ bool insertTimerAllowed() const;
+ bool moveTimerDownAllowed() const;
+ bool moveTimerUpAllowed() const;
+ void swapTimerData(int idx1, int idx2);
};
#endif // _SETUP_H_
diff --git a/companion/src/modeledit/setup.ui b/companion/src/modeledit/setup.ui
index 9ad725ce1..fc499ad63 100644
--- a/companion/src/modeledit/setup.ui
+++ b/companion/src/modeledit/setup.ui
@@ -590,7 +590,7 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
-
-
+
50
diff --git a/companion/src/modeledit/setup_module.ui b/companion/src/modeledit/setup_module.ui
index c0a54d024..654af2a54 100644
--- a/companion/src/modeledit/setup_module.ui
+++ b/companion/src/modeledit/setup_module.ui
@@ -126,6 +126,12 @@
0
+
+
+ 100
+ 0
+
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -173,6 +179,15 @@
0
+
+
+ 100
+ 0
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
@@ -214,6 +229,12 @@
0
+
+
+ 100
+ 0
+
+
QComboBox::AdjustToContents
@@ -417,6 +438,7 @@
-
+
@@ -485,6 +507,12 @@
0
+
+
+ 80
+ 0
+
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -529,6 +557,12 @@
0
+
+
+ 80
+ 0
+
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -573,6 +607,15 @@
0
+
+
+ 80
+ 0
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
ms
@@ -617,19 +660,58 @@
0
+
+
+ 80
+ 0
+
+
QComboBox::AdjustToContents
+ -
+
+
+ RX Frequency
+
+
+
-
+
+
+ Option value
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 80
+ 0
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
Output type
- -
+
-
@@ -652,21 +734,7 @@
- -
-
-
- Option value
-
-
-
- -
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
+
-
Qt::Horizontal
@@ -679,6 +747,34 @@
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 80
+ 0
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ Hz
+
+
+ 50
+
+
+ 400
+
+
+
-
@@ -711,11 +807,17 @@
-
-
+
0
0
+
+
+ 180
+ 0
+
+
QComboBox::AdjustToContents
@@ -754,11 +856,17 @@
-
-
+
0
0
+
+
+ 150
+ 0
+
+
QComboBox::AdjustToContents
@@ -774,11 +882,17 @@
-
-
+
0
0
+
+
+ 150
+ 0
+
+
QComboBox::AdjustToContents
@@ -847,11 +961,17 @@
-
-
+
0
0
+
+
+ 150
+ 0
+
+
QComboBox::AdjustToContents
@@ -901,11 +1021,17 @@
-
-
+
0
0
+
+
+ 150
+ 0
+
+
QComboBox::AdjustToContents
@@ -934,17 +1060,17 @@
Master/SBUS in battery compartment
- -
+
-
Master/Bluetooth
- -
+
-
Slave/Bluetooth
- -
+
-
Master/Multi
diff --git a/companion/src/modeledit/telemetry.cpp b/companion/src/modeledit/telemetry.cpp
index 68be10638..99915eae5 100644
--- a/companion/src/modeledit/telemetry.cpp
+++ b/companion/src/modeledit/telemetry.cpp
@@ -20,7 +20,6 @@
#include "telemetry.h"
#include "ui_telemetry.h"
-#include "ui_telemetry_analog.h"
#include "ui_telemetry_customscreen.h"
#include "ui_telemetry_sensor.h"
#include "helpers.h"
@@ -29,291 +28,6 @@
#include
-TelemetryAnalog::TelemetryAnalog(QWidget *parent, FrSkyChannelData & analog, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
- ModelPanel(parent, model, generalSettings, firmware),
- ui(new Ui::TelemetryAnalog),
- analog(analog),
- lock(false)
-{
- ui->setupUi(this);
-
- float ratio = analog.getRatio();
-
- if (analog.type==0 || analog.type==1 || analog.type==2) {
- ui->RatioSB->setDecimals(1);
- ui->RatioSB->setMaximum(25.5*firmware->getCapability(TelemetryMaxMultiplier));
- }
- else {
- ui->RatioSB->setDecimals(0);
- ui->RatioSB->setMaximum(255*firmware->getCapability(TelemetryMaxMultiplier));
- }
- ui->RatioSB->setValue(ratio);
-
- update();
-
- ui->UnitCB->setCurrentIndex(analog.type);
- ui->alarm1LevelCB->setCurrentIndex(analog.alarms[0].level);
- ui->alarm1GreaterCB->setCurrentIndex(analog.alarms[0].greater);
- ui->alarm2LevelCB->setCurrentIndex(analog.alarms[1].level);
- ui->alarm2GreaterCB->setCurrentIndex(analog.alarms[1].greater);
-
- if (!(firmware->getCapability(Telemetry) & TM_HASOFFSET)) {
- ui->CalibSB->hide();
- ui->CalibLabel->hide();
- }
- else {
- ui->label_Max->setText(tr("Range"));
- }
-
- disableMouseScrolling();
-}
-
-void TelemetryAnalog::update()
-{
- float ratio = analog.getRatio();
- float step = ratio / 255;
- float mini = (ratio * analog.offset) / 255;
- float maxi = mini + ratio;
-
- ui->alarm1ValueSB->setDecimals(2);
- ui->alarm1ValueSB->setSingleStep(step);
- ui->alarm1ValueSB->setMinimum(mini);
- ui->alarm1ValueSB->setMaximum(maxi);
- ui->alarm1ValueSB->setValue(mini + step*analog.alarms[0].value);
-
- ui->alarm2ValueSB->setDecimals(2);
- ui->alarm2ValueSB->setSingleStep(step);
- ui->alarm2ValueSB->setMinimum(mini);
- ui->alarm2ValueSB->setMaximum(maxi);
- ui->alarm2ValueSB->setValue(mini + step*analog.alarms[1].value);
-
- ui->CalibSB->setDecimals(2);
- ui->CalibSB->setMaximum(step*127);
- ui->CalibSB->setMinimum(-step*128);
- ui->CalibSB->setSingleStep(step);
- ui->CalibSB->setValue(mini);
-}
-
-static int findmult(float value, float base)
-{
- int vvalue = value*10;
- int vbase = base*10;
- vvalue--;
-
- int mult = 0;
- for (int i=8; i>=0; i--) {
- if (vvalue/vbase >= (1<RatioSB->setDecimals(1);
- ui->RatioSB->setMaximum(25.5*firmware->getCapability(TelemetryMaxMultiplier));
- break;
- default:
- ui->RatioSB->setDecimals(0);
- ui->RatioSB->setMaximum(255*firmware->getCapability(TelemetryMaxMultiplier));
- break;
- }
- ui->RatioSB->setValue(ratio);
- update();
- emit modified();
-}
-
-void TelemetryAnalog::on_RatioSB_valueChanged()
-{
- if (!lock) {
- if (analog.type==0 || analog.type==1 || analog.type==2) {
- analog.multiplier = findmult(ui->RatioSB->value(), 25.5);
- float singlestep =(1<RatioSB->setSingleStep(singlestep);
- ui->RatioSB->setValue(round(ui->RatioSB->value()/singlestep)*singlestep);
- lock=false;
- }
- else {
- analog.multiplier = findmult(ui->RatioSB->value(), 255);
- float singlestep = (1<RatioSB->setSingleStep(singlestep);
- ui->RatioSB->setValue(round(ui->RatioSB->value()/singlestep)*singlestep);
- lock = false;
- }
- emit modified();
- }
-}
-
-void TelemetryAnalog::on_RatioSB_editingFinished()
-{
- if (!lock) {
- float ratio, calib, alarm1value,alarm2value;
-
- if (analog.type==0 || analog.type==1 || analog.type==2) {
- analog.multiplier = findmult(ui->RatioSB->value(), 25.5);
- ui->CalibSB->setSingleStep((1<alarm1ValueSB->setSingleStep((1<alarm2ValueSB->setSingleStep((1<RatioSB->value()*10))/(1 <RatioSB->value(), 255);
- ui->CalibSB->setSingleStep(1<alarm1ValueSB->setSingleStep(1<alarm2ValueSB->setSingleStep(1<RatioSB->value()/(1 << analog.multiplier));
- }
- ui->CalibSB->setMaximum((ui->RatioSB->value()*127)/255);
- ui->CalibSB->setMinimum((ui->RatioSB->value()*-128)/255);
- ui->alarm1ValueSB->setMaximum(ui->RatioSB->value());
- ui->alarm2ValueSB->setMaximum(ui->RatioSB->value());
- repaint();
- ratio=analog.ratio * (1 << analog.multiplier);
- calib=ui->CalibSB->value();
- alarm1value=ui->alarm1ValueSB->value();
- alarm2value=ui->alarm2ValueSB->value();
- if (analog.type==0) {
- calib*=10;
- alarm1value*=10;
- alarm2value*=10;
- }
- if (calib>0) {
- if (calib>((ratio*127)/255)) {
- analog.offset=127;
- }
- else {
- analog.offset=round(calib*255/ratio);
- }
- }
- if (calib<0) {
- if (calib<((ratio*-128)/255)) {
- analog.offset=-128;
- }
- else {
- analog.offset=round(calib*255/ratio);
- }
- }
- analog.alarms[0].value=round((alarm1value*255-analog.offset*(analog.ratio<CalibSB->value()/ratio));
- calib=ratio*analog.offset/255.0;
- alarm1value=ui->alarm1ValueSB->value();
- alarm2value=ui->alarm2ValueSB->value();
- if (alarm1value(ratio+calib)) {
- alarm1value=ratio+calib;
- }
- if (alarm2value(ratio+calib)) {
- alarm2value=ratio+calib;
- }
- analog.alarms[0].value=round(((alarm1value-calib)*255)/ratio);
- analog.alarms[1].value=round(((alarm2value-calib)*255)/ratio);
- }
- else {
- analog.offset=0;
- analog.alarms[0].value=0;
- analog.alarms[1].value=0;
- }
- update();
- emit modified();
-}
-
-void TelemetryAnalog::on_alarm1LevelCB_currentIndexChanged(int index)
-{
- analog.alarms[0].level = index;
- emit modified();
-}
-
-
-void TelemetryAnalog::on_alarm1GreaterCB_currentIndexChanged(int index)
-{
- analog.alarms[0].greater = index;
- emit modified();
-}
-
-void TelemetryAnalog::on_alarm1ValueSB_editingFinished()
-{
- float ratio = analog.getRatio();
- float calib, alarm1value;
-
- calib=analog.offset;
- alarm1value=ui->alarm1ValueSB->value();
-
- if (alarm1value<((calib*ratio)/255)) {
- analog.alarms[0].value=0;
- }
- else if (alarm1value>(ratio+(calib*ratio)/255)) {
- analog.alarms[0].value=255;
- }
- else {
- analog.alarms[0].value = round((alarm1value-((calib*ratio)/255))/ratio*255);
- }
- update();
- emit modified();
-}
-
-void TelemetryAnalog::on_alarm2LevelCB_currentIndexChanged(int index)
-{
- analog.alarms[1].level = index;
- emit modified();
-}
-
-void TelemetryAnalog::on_alarm2GreaterCB_currentIndexChanged(int index)
-{
- analog.alarms[1].greater = index;
- emit modified();
-}
-
-void TelemetryAnalog::on_alarm2ValueSB_editingFinished()
-{
- float calib, alarm2value;
- float ratio = analog.getRatio();
- calib = analog.offset;
- alarm2value = ui->alarm2ValueSB->value();
- if (alarm2value<((calib*ratio)/255)) {
- analog.alarms[1].value=0;
- }
- else if (alarm2value>(ratio+(calib*ratio)/255)) {
- analog.alarms[1].value=255;
- }
- else {
- analog.alarms[1].value = round((alarm2value-((calib*ratio)/255))/ratio*255);
- }
- update();
- emit modified();
-}
-
-TelemetryAnalog::~TelemetryAnalog()
-{
- delete ui;
-}
/******************************************************/
@@ -377,8 +91,7 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model,
disableMouseScrolling();
lock = true;
- if (IS_ARM(firmware->getBoard()))
- ui->screenType->addItem(tr("None"), TELEMETRY_SCREEN_NONE);
+ ui->screenType->addItem(tr("None"), TELEMETRY_SCREEN_NONE);
ui->screenType->addItem(tr("Numbers"), TELEMETRY_SCREEN_NUMBERS);
ui->screenType->addItem(tr("Bars"), TELEMETRY_SCREEN_BARS);
if (IS_TARANIS(firmware->getBoard()))
@@ -439,14 +152,8 @@ void TelemetryCustomScreen::updateBar(int line)
if (source.type != SOURCE_TYPE_NONE) {
RawSourceRange range = source.getRange(model, generalSettings);
- if (!IS_ARM(getCurrentBoard())) {
- int max = round((range.max - range.min) / range.step);
- if (int(255-screen.body.bars[line].barMax) > max) {
- screen.body.bars[line].barMax = 255 - max;
- }
- }
float minVal = range.getValue(screen.body.bars[line].barMin);
- float maxVal = IS_ARM(getCurrentBoard()) ? screen.body.bars[line].barMax : 255 - screen.body.bars[line].barMax;
+ float maxVal = screen.body.bars[line].barMax;
maxVal = range.getValue(maxVal);
if (source.isTimeBased()) {
@@ -552,10 +259,7 @@ void TelemetryCustomScreen::barMinChanged(double value)
{
if (!lock) {
int line = sender()->property("index").toInt();
- if (IS_ARM(getCurrentBoard()))
- screen.body.bars[line].barMin = round(value / minSB[line]->singleStep());
- else
- screen.body.bars[line].barMin = round((value-minSB[line]->minimum()) / minSB[line]->singleStep());
+ screen.body.bars[line].barMin = round(value / minSB[line]->singleStep());
// TODO set min (maxSB)
emit modified();
}
@@ -565,10 +269,7 @@ void TelemetryCustomScreen::barMaxChanged(double value)
{
if (!lock) {
int line = sender()->property("index").toInt();
- if (IS_ARM(getCurrentBoard()))
- screen.body.bars[line].barMax = round((value) / maxSB[line]->singleStep());
- else
- screen.body.bars[line].barMax = 255 - round((value-minSB[line]->minimum()) / maxSB[line]->singleStep());
+ screen.body.bars[line].barMax = round((value) / maxSB[line]->singleStep());
// TODO set max (minSB)
emit modified();
}
@@ -583,22 +284,34 @@ void TelemetryCustomScreen::barTimeChanged()
if (!te)
return;
- if (IS_ARM(getCurrentBoard()))
- valRef = round(te->timeInSeconds() / te->singleStep());
- else
- valRef = round((te->timeInSeconds() - te->minimumTime()) / te->singleStep());
+ valRef = round(te->timeInSeconds() / te->singleStep());
emit modified();
}
}
-TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
+/******************************************************/
+
+TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::TelemetrySensor),
sensor(sensor),
- lock(false)
+ lock(false),
+ sensorIndex(sensorIndex),
+ selectedIndex(0)
{
ui->setupUi(this);
+ ui->numLabel->setText(tr("TELE%1").arg(sensorIndex + 1));
+ ui->numLabel->setProperty("index", sensorIndex);
+ ui->numLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ QFontMetrics *f = new QFontMetrics(QFont());
+ QSize sz;
+ sz = f->size(Qt::TextSingleLine, "TELE00");
+ ui->numLabel->setMinimumWidth(sz.width());
+ ui->numLabel->setContextMenuPolicy(Qt::CustomContextMenu);
+ ui->numLabel->setToolTip(tr("Popup menu available"));
+ ui->numLabel->setMouseTracking(true);
+ connect(ui->numLabel, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(on_customContextMenuRequested(QPoint)));
ui->id->setField(sensor.id, this);
ui->instance->setField(sensor.instance, this);
ui->ratio->setField(sensor.ratio, this);
@@ -613,7 +326,7 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor,
ui->ampsSensor->setField(sensor.amps, this);
ui->cellsSensor->setField(sensor.source, this);
ui->cellsIndex->addItem(tr("Lowest"), SensorData::TELEM_CELL_INDEX_LOWEST);
- for (int i=1; i<=6; i++)
+ for (int i = 1; i <= 6; i++)
ui->cellsIndex->addItem(tr("Cell %1").arg(i), i);
ui->cellsIndex->addItem(tr("Highest"), SensorData::TELEM_CELL_INDEX_HIGHEST);
ui->cellsIndex->addItem(tr("Delta"), SensorData::TELEM_CELL_INDEX_DELTA);
@@ -622,6 +335,7 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor,
ui->source2->setField(sensor.sources[1], this);
ui->source3->setField(sensor.sources[2], this);
ui->source4->setField(sensor.sources[3], this);
+ ui->prec->setField(sensor.prec, 0, 2, false, "", this);
update();
}
@@ -645,7 +359,21 @@ void TelemetrySensorPanel::update()
ui->name->setText(sensor.label);
ui->type->setCurrentIndex(sensor.type);
ui->unit->setCurrentIndex(sensor.unit);
- ui->prec->setValue(sensor.prec);
+ ui->id->updateValue();
+ ui->instance->updateValue();
+ ui->ratio->updateValue();
+ ui->offset->updateValue();
+ ui->autoOffset->updateValue();
+ ui->filter->updateValue();
+ ui->logs->updateValue();
+ ui->persistent->updateValue();
+ ui->onlyPositive->updateValue();
+ ui->gpsSensor->updateValue();
+ ui->altSensor->updateValue();
+ ui->ampsSensor->updateValue();
+ ui->cellsSensor->updateValue();
+ ui->cellsIndex->updateValue();
+ ui->prec->updateValue();
if (sensor.type == SensorData::TELEM_TYPE_CALCULATED) {
sensor.updateUnit();
@@ -825,15 +553,85 @@ void TelemetrySensorPanel::on_unit_currentIndexChanged(int index)
}
}
-void TelemetrySensorPanel::on_prec_valueChanged(double value)
+void TelemetrySensorPanel::on_prec_valueChanged()
{
if (!lock) {
- sensor.prec = value;
+ update();
+ }
+}
+
+void TelemetrySensorPanel::on_customContextMenuRequested(QPoint pos)
+{
+ QLabel *label = (QLabel *)sender();
+ selectedIndex = label->property("index").toInt();
+ QPoint globalPos = label->mapToGlobal(pos);
+
+ QMenu contextMenu;
+ contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"),this,SLOT(cmCopy()));
+ contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"),this,SLOT(cmCut()));
+ contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData());
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear()));
+ contextMenu.addSeparator();
+ contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll()));
+
+ contextMenu.exec(globalPos);
+}
+
+bool TelemetrySensorPanel::hasClipboardData(QByteArray * data) const
+{
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat(MIMETYPE_TELE_SENSOR)) {
+ if (data)
+ data->append(mimeData->data(MIMETYPE_TELE_SENSOR));
+ return true;
+ }
+ return false;
+}
+
+void TelemetrySensorPanel::cmCopy()
+{
+ QByteArray data;
+ data.append((char*)&sensor, sizeof(SensorData));
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData(MIMETYPE_TELE_SENSOR, data);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+}
+
+void TelemetrySensorPanel::cmCut()
+{
+ cmCopy();
+ cmClear();
+}
+
+void TelemetrySensorPanel::cmPaste()
+{
+ QByteArray data;
+ if (hasClipboardData(&data)) {
+ memcpy(&sensor, data.constData(), sizeof(SensorData));
emit dataModified();
emit modified();
}
}
+void TelemetrySensorPanel::cmClear()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Telemetry Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ sensor.clear();
+ emit dataModified();
+ emit modified();
+}
+
+void TelemetrySensorPanel::cmClearAll()
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Telemetry Sensors. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ emit clearAllSensors();
+}
+
/******************************************************/
TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
@@ -846,30 +644,19 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
model.frsky.usrProto = 1;
}
- if (IS_ARM(firmware->getBoard())) {
- ui->varioSource->setField(model.frsky.varioSource, this);
- ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this);
- ui->A1GB->hide();
- ui->A2GB->hide();
- for (unsigned i=0; isensorsLayout->addWidget(panel);
- sensorPanels[i] = panel;
- connect(panel, SIGNAL(dataModified()), this, SLOT(update()));
- connect(panel, SIGNAL(modified()), this, SLOT(onModified()));
- }
+ ui->varioSource->setField(model.frsky.varioSource, this);
+ ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this);
+ ui->A1GB->hide();
+ ui->A2GB->hide();
+ for (unsigned i= 0; i < CPN_MAX_SENSORS; ++i) {
+ TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, model, generalSettings, firmware);
+ ui->sensorsLayout->addWidget(panel);
+ sensorPanels[i] = panel;
+ connect(panel, SIGNAL(dataModified()), this, SLOT(update()));
+ connect(panel, SIGNAL(modified()), this, SLOT(onModified()));
+ connect(panel, SIGNAL(clearAllSensors()), this, SLOT(on_clearAllSensors()));
}
- else {
- ui->sensorsGB->hide();
- ui->altimetryGB->hide();
- analogs[0] = new TelemetryAnalog(this, model.frsky.channels[0], model, generalSettings, firmware);
- ui->A1Layout->addWidget(analogs[0]);
- connect(analogs[0], SIGNAL(modified()), this, SLOT(onAnalogModified()));
- analogs[1] = new TelemetryAnalog(this, model.frsky.channels[1], model, generalSettings, firmware);
- ui->A2Layout->addWidget(analogs[1]);
- connect(analogs[1], SIGNAL(modified()), this, SLOT(onModified()));
- }
-
+
if (IS_TARANIS_X9(firmware->getBoard())) {
ui->voltsSource->setField(model.frsky.voltsSource, this);
ui->altitudeSource->setField(model.frsky.altitudeSource, this);
@@ -881,7 +668,7 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
RawSourceFilterItemModel * srcModel = (new RawSourceFilterItemModel(&generalSettings, &model, this));
connect(this, &TelemetryPanel::updated, srcModel, &RawSourceFilterItemModel::update);
- for (int i=0; igetCapability(TelemetryCustomScreens); i++) {
+ for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) {
TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, srcModel);
ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i+1));
telemetryCustomScreens[i] = tab;
@@ -916,10 +703,8 @@ void TelemetryPanel::update()
populateTelemetrySourcesComboBox(ui->varioSource, model, false);
}
- if (IS_ARM(firmware->getBoard())) {
- for (unsigned i=0; iupdate();
- }
+ for (unsigned i=0; iupdate();
}
emit updated();
@@ -931,52 +716,29 @@ void TelemetryPanel::setup()
lock = true;
- if (IS_ARM(firmware->getBoard())) {
- ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0);
- ui->telemetryProtocol->addItem(tr("FrSky D"), 1);
- if (IS_9XRPRO(firmware->getBoard()) ||
- (IS_TARANIS(firmware->getBoard()) && generalSettings.auxSerialMode == 2)) {
- ui->telemetryProtocol->addItem(tr("FrSky D (cable)"), 2);
- }
- ui->telemetryProtocol->setCurrentIndex(model->telemetryProtocol);
- ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this);
- ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled);
- }
- else {
- ui->telemetryProtocolLabel->hide();
- ui->telemetryProtocol->hide();
- ui->ignoreSensorIds->hide();
- ui->disableTelemetryAlarms->hide();
+ ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0);
+ ui->telemetryProtocol->addItem(tr("FrSky D"), 1);
+ if (IS_9XRPRO(firmware->getBoard()) ||
+ (IS_TARANIS(firmware->getBoard()) && generalSettings.auxSerialMode == 2)) {
+ ui->telemetryProtocol->addItem(tr("FrSky D (cable)"), 2);
}
+ ui->telemetryProtocol->setCurrentIndex(model->telemetryProtocol);
+ ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this);
+ ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled);
ui->rssiAlarmWarningSB->setValue(model->rssiAlarms.warning);
ui->rssiAlarmCriticalSB->setValue(model->rssiAlarms.critical);
- if (!IS_ARM(firmware->getBoard())) {
- ui->rssiSourceLabel->hide();
- ui->rssiSourceCB->hide();
- ui->rssiAlarmWarningCB->setCurrentIndex(model->rssiAlarms.level[0]);
- ui->rssiAlarmCriticalCB->setCurrentIndex(model->rssiAlarms.level[1]);
- }
- else {
- ui->rssiSourceLabel->show();
- ui->rssiSourceLabel->setText(tr("Source"));
- ui->rssiSourceCB->setField(model->rssiSource, this);
- ui->rssiSourceCB->show();
- populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false);
-
- ui->rssiAlarmWarningCB->hide();
- ui->rssiAlarmCriticalCB->hide();
- ui->rssiAlarmWarningLabel->setText(tr("Low Alarm"));
- ui->rssiAlarmCriticalLabel->setText(tr("Critical Alarm"));
- }
- /*if (IS_ARM(firmware->getBoard())) {
- for (int i=0; i, model, generalSettings, firmware);
- ui->sensorsLayout->addWidget(panel);
- sensorPanels[i] = panel;
- }
- }*/
+ ui->rssiSourceLabel->show();
+ ui->rssiSourceLabel->setText(tr("Source"));
+ ui->rssiSourceCB->setField(model->rssiSource, this);
+ ui->rssiSourceCB->show();
+ populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false);
+
+ ui->rssiAlarmWarningCB->hide();
+ ui->rssiAlarmCriticalCB->hide();
+ ui->rssiAlarmWarningLabel->setText(tr("Low Alarm"));
+ ui->rssiAlarmCriticalLabel->setText(tr("Critical Alarm"));
int varioCap = firmware->getCapability(HasVario);
if (!varioCap) {
@@ -1008,7 +770,7 @@ void TelemetryPanel::setup()
ui->altimetryGB->setVisible(firmware->getCapability(HasVario)),
ui->frskyProtoCB->setDisabled(firmware->getCapability(NoTelemetryProtocol));
- if (firmware->getCapability(Telemetry) & TM_HASWSHH) {
+ if (firmware->getCapability(Telemetry)) {
ui->frskyProtoCB->addItem(tr("Winged Shadow How High"));
}
else {
@@ -1016,38 +778,6 @@ void TelemetryPanel::setup()
}
ui->variousGB->hide();
- if (!IS_ARM(firmware->getBoard())) {
- if (!(firmware->getCapability(HasFasOffset)) && !(firmware_id.contains("fasoffset"))) {
- ui->fasOffset_label->hide();
- ui->fasOffset_DSB->hide();
- }
- else {
- ui->fasOffset_DSB->setValue(model->frsky.fasOffset/10.0);
- ui->variousGB->show();
- }
-
- if (!(firmware->getCapability(HasMahPersistent))) {
- ui->mahCount_label->hide();
- ui->mahCount_SB->hide();
- ui->mahCount_ChkB->hide();
- }
- else {
- if (model->frsky.mAhPersistent) {
- ui->mahCount_ChkB->setChecked(true);
- ui->mahCount_SB->setValue(model->frsky.storedMah);
- }
- else {
- ui->mahCount_SB->setDisabled(true);
- }
- ui->variousGB->show();
- }
-
- ui->frskyProtoCB->setCurrentIndex(model->frsky.usrProto);
- ui->bladesCount->setValue(model->frsky.blades);
- populateVarioSource();
- populateVoltsSource();
- populateCurrentSource();
- }
lock = false;
}
@@ -1069,10 +799,8 @@ void TelemetryPanel::populateVoltsSource()
cb->setField(model->frsky.voltsSource, this);
cb->addItem(tr("A1"), TELEMETRY_VOLTS_SOURCE_A1);
cb->addItem(tr("A2"), TELEMETRY_VOLTS_SOURCE_A2);
- if (IS_ARM(firmware->getBoard())) {
- cb->addItem(tr("A3"), TELEMETRY_VOLTS_SOURCE_A3);
- cb->addItem(tr("A4"), TELEMETRY_VOLTS_SOURCE_A4);
- }
+ cb->addItem(tr("A3"), TELEMETRY_VOLTS_SOURCE_A3);
+ cb->addItem(tr("A4"), TELEMETRY_VOLTS_SOURCE_A4);
cb->addItem(tr("FAS"), TELEMETRY_VOLTS_SOURCE_FAS);
cb->addItem(tr("Cells"), TELEMETRY_VOLTS_SOURCE_CELLS);
}
@@ -1084,10 +812,8 @@ void TelemetryPanel::populateCurrentSource()
cb->addItem(tr("---"), TELEMETRY_CURRENT_SOURCE_NONE);
cb->addItem(tr("A1"), TELEMETRY_CURRENT_SOURCE_A1);
cb->addItem(tr("A2"), TELEMETRY_CURRENT_SOURCE_A2);
- if (IS_ARM(firmware->getBoard())) {
- cb->addItem(tr("A3"), TELEMETRY_CURRENT_SOURCE_A3);
- cb->addItem(tr("A4"), TELEMETRY_CURRENT_SOURCE_A4);
- }
+ cb->addItem(tr("A3"), TELEMETRY_CURRENT_SOURCE_A3);
+ cb->addItem(tr("A4"), TELEMETRY_CURRENT_SOURCE_A4);
cb->addItem(tr("FAS"), TELEMETRY_CURRENT_SOURCE_FAS);
}
@@ -1122,18 +848,6 @@ void TelemetryPanel::on_frskyProtoCB_currentIndexChanged(int index)
}
}
-void TelemetryPanel::on_rssiAlarmWarningCB_currentIndexChanged(int index)
-{
- model->rssiAlarms.level[0] = index;
- emit modified();
-}
-
-void TelemetryPanel::on_rssiAlarmCriticalCB_currentIndexChanged(int index)
-{
- model->rssiAlarms.level[1] = index;
- emit modified();
-}
-
void TelemetryPanel::on_rssiAlarmWarningSB_editingFinished()
{
model->rssiAlarms.warning= ui->rssiAlarmWarningSB->value();
@@ -1198,3 +912,13 @@ void TelemetryPanel::on_mahCount_ChkB_toggled(bool checked)
ui->mahCount_SB->setDisabled(!checked);
emit modified();
}
+
+void TelemetryPanel::on_clearAllSensors()
+{
+ for (int i = 0; i < CPN_MAX_SENSORS; i++) {
+ model->sensorData[i].clear();
+ }
+
+ update();
+ emit modified();
+}
diff --git a/companion/src/modeledit/telemetry.h b/companion/src/modeledit/telemetry.h
index b23214927..28dc7643c 100644
--- a/companion/src/modeledit/telemetry.h
+++ b/companion/src/modeledit/telemetry.h
@@ -24,50 +24,18 @@
#include "modeledit.h"
#include "eeprominterface.h"
+constexpr char MIMETYPE_TELE_SENSOR[] = "application/x-companion-tele-sensor";
+
class AutoComboBox;
class RawSourceFilterItemModel;
class TimerEdit;
namespace Ui {
- class TelemetryAnalog;
class TelemetryCustomScreen;
class TelemetrySensor;
class Telemetry;
}
-class TelemetryAnalog: public ModelPanel
-{
- Q_OBJECT
-
- friend class TelemetryPanel;
-
- public:
- TelemetryAnalog(QWidget *parent, FrSkyChannelData & analog, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
- virtual ~TelemetryAnalog();
-
- signals:
- void modified();
-
- private slots:
- void on_UnitCB_currentIndexChanged(int index);
- void on_RatioSB_editingFinished();
- void on_RatioSB_valueChanged();
- void on_CalibSB_editingFinished();
- void on_alarm1LevelCB_currentIndexChanged(int index);
- void on_alarm1GreaterCB_currentIndexChanged(int index);
- void on_alarm1ValueSB_editingFinished();
- void on_alarm2LevelCB_currentIndexChanged(int index);
- void on_alarm2GreaterCB_currentIndexChanged(int index);
- void on_alarm2ValueSB_editingFinished();
-
- private:
- Ui::TelemetryAnalog *ui;
- FrSkyChannelData & analog;
- bool lock;
-
- void update();
-};
-
class TelemetryCustomScreen: public ModelPanel
{
Q_OBJECT
@@ -103,19 +71,27 @@ class TelemetrySensorPanel: public ModelPanel
Q_OBJECT
public:
- TelemetrySensorPanel(QWidget *parent, SensorData & sensor, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
+ TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
~TelemetrySensorPanel();
void update();
signals:
void dataModified();
+ void clearAllSensors();
protected slots:
void on_name_editingFinished();
void on_type_currentIndexChanged(int index);
void on_formula_currentIndexChanged(int index);
void on_unit_currentIndexChanged(int index);
- void on_prec_valueChanged(double value);
+ void on_prec_valueChanged();
+ void on_customContextMenuRequested(QPoint pos);
+ bool hasClipboardData(QByteArray * data = nullptr) const;
+ void cmCopy();
+ void cmCut();
+ void cmPaste();
+ void cmClear();
+ void cmClearAll();
protected:
void updateSourcesComboBox(AutoComboBox * cb, bool negative);
@@ -123,7 +99,9 @@ class TelemetrySensorPanel: public ModelPanel
private:
Ui::TelemetrySensor * ui;
SensorData & sensor;
- bool lock;
+ bool lock = false;
+ int sensorIndex = 0;
+ int selectedIndex = 0;
};
class TelemetryPanel : public ModelPanel
@@ -143,8 +121,6 @@ class TelemetryPanel : public ModelPanel
void onModified();
void on_frskyProtoCB_currentIndexChanged(int index);
void on_bladesCount_editingFinished();
- void on_rssiAlarmWarningCB_currentIndexChanged(int index);
- void on_rssiAlarmCriticalCB_currentIndexChanged(int index);
void on_rssiAlarmWarningSB_editingFinished();
void on_rssiAlarmCriticalSB_editingFinished();
void on_varioLimitMin_DSB_editingFinished();
@@ -154,10 +130,10 @@ class TelemetryPanel : public ModelPanel
void on_fasOffset_DSB_editingFinished();
void on_mahCount_SB_editingFinished();
void on_mahCount_ChkB_toggled(bool checked);
+ void on_clearAllSensors();
private:
Ui::Telemetry *ui;
- TelemetryAnalog * analogs[4];
TelemetryCustomScreen * telemetryCustomScreens[4];
TelemetrySensorPanel * sensorPanels[CPN_MAX_SENSORS];
diff --git a/companion/src/modeledit/telemetry_sensor.ui b/companion/src/modeledit/telemetry_sensor.ui
index 7d08243e0..12af2cf06 100644
--- a/companion/src/modeledit/telemetry_sensor.ui
+++ b/companion/src/modeledit/telemetry_sensor.ui
@@ -13,13 +13,32 @@
Form
-
+
0
0
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ TELE##
+
+
+
-
@@ -520,6 +539,11 @@
US fl.Oz.
+ -
+
+ ml/min
+
+
-
@@ -536,23 +560,7 @@
-
-
-
- true
-
-
-
- 0
- 0
-
-
-
- 0
-
-
- 2.000000000000000
-
-
+
-
@@ -711,6 +719,11 @@
QSpinBox
+
+ AutoPrecisionComboBox
+ QComboBox
+
+
diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp
index ac9f6f066..bd56876c6 100644
--- a/companion/src/modelprinter.cpp
+++ b/companion/src/modelprinter.cpp
@@ -224,6 +224,11 @@ QString ModelPrinter::printModule(int idx)
str << printLabelValue(tr("Sub Type"), module.subTypeToString());
str << printLabelValue(tr("RF Output Power"), module.powerValueToString(firmware));
}
+ if (module.protocol == PULSES_AFHDS3) {
+ str << printLabelValue(tr("Output Type"), module.subTypeToString());
+ str << printLabelValue(tr("RF Output Power"), module.powerValueToString(firmware));
+ str << printLabelValue(tr("RX Output Frequency"), QString("%1Hz").arg(module.afhds3.rxFreq));
+ }
}
}
result = str.join(" ");
@@ -897,9 +902,8 @@ QString ModelPrinter::printFailsafe(int idx)
ModuleData module = model.moduleData[idx];
strl << printLabelValue(tr("Failsafe Mode"), printFailsafeMode(module.failsafeMode));
if (module.failsafeMode == FAILSAFE_CUSTOM) {
- for (int i=0; igetBoard()))
- str << printLabelValue(tr("Display"), printTrimsDisplayMode());
+ str << printLabelValue(tr("Display"), printTrimsDisplayMode());
str << printLabelValue(tr("Extended"), printBoolean(model.extendedTrims, BOOLEAN_YESNO));
return str.join(" ");
}
diff --git a/companion/src/modelslist.cpp b/companion/src/modelslist.cpp
index 2fb5cc329..864c10028 100644
--- a/companion/src/modelslist.cpp
+++ b/companion/src/modelslist.cpp
@@ -145,7 +145,7 @@ TreeModel::TreeModel(RadioData * radioData, QObject * parent):
if (!hasCategories)
labels << tr("Index");
labels << tr("Name");
- if (!(IS_HORUS(board) || IS_SKY9X(board))) {
+ if (!(IS_FAMILY_HORUS_OR_T16(board) || IS_SKY9X(board))) {
labels << tr("Size");
}
labels << tr("RX #");
@@ -651,7 +651,7 @@ void TreeModel::refresh()
EEPROMInterface * eepromInterface = getCurrentEEpromInterface();
Board::Type board = eepromInterface->getBoard();
TreeItem * defaultCategoryItem = NULL;
- bool hasEepromSizeData = (IS_HORUS(board) ? false : true);
+ bool hasEepromSizeData = (IS_FAMILY_HORUS_OR_T16(board) ? false : true);
if (hasEepromSizeData) {
availableEEpromSize = Boards::getEEpromSize(board) - 64; // let's consider fat
diff --git a/companion/src/multimodelprinter.cpp b/companion/src/multimodelprinter.cpp
index f9d039d69..9d57e1f62 100644
--- a/companion/src/multimodelprinter.cpp
+++ b/companion/src/multimodelprinter.cpp
@@ -292,7 +292,7 @@ QString MultiModelPrinter::print(QTextDocument * document)
if (firmware->getCapability(GlobalFunctions))
str.append(printGlobalFunctions());
str.append(printSpecialFunctions());
- if (firmware->getCapability(Telemetry) & TM_HASTELEMETRY) {
+ if (firmware->getCapability(Telemetry)) {
str.append(printTelemetry());
str.append(printSensors());
if (firmware->getCapability(TelemetryCustomScreens)) {
@@ -751,32 +751,19 @@ QString MultiModelPrinter::printTelemetry()
MultiColumns columns(modelPrinterMap.size());
columns.appendSectionTableStart();
- // Analogs on non ARM boards
- if (!IS_ARM(firmware->getBoard())) {
- columns.appendRowHeader(QStringList() << tr("Analogs") << tr("Unit") << tr("Scale") << tr("Offset"));
- for (int i=0; i<2; i++) {
- columns.appendRowStart(QString("A%1").arg(i+1), 20);
- COMPARECELLWIDTH(FrSkyChannelData::unitString(model->frsky.channels[i].type), 20);
- COMPARECELLWIDTH(QString::number((model->frsky.channels[i].ratio / (model->frsky.channels[i].type==0 ? 10.0 : 1)), 10, (model->frsky.channels[i].type==0 ? 1 : 0)), 20);
- COMPARECELLWIDTH(QString::number((model->frsky.channels[i].offset*(model->frsky.channels[i].ratio / (model->frsky.channels[i].type==0 ?10.0 : 1)))/255, 10, (model->frsky.channels[i].type==0 ? 1 : 0)), 40);
- columns.appendRowEnd();
- }
- }
- else {
- // Protocol
- columns.appendRowStart(tr("Protocol"), 20);
- COMPARECELL(modelPrinter->printTelemetryProtocol(model->telemetryProtocol));
- columns.appendRowEnd();
- }
+ // Protocol
+ columns.appendRowStart(tr("Protocol"), 20);
+ COMPARECELL(modelPrinter->printTelemetryProtocol(model->telemetryProtocol));
+ columns.appendRowEnd();
// RSSI alarms
{
columns.appendRowStart(tr("RSSI Alarms"), 20);
columns.appendCellStart(80);
- COMPARESTRING("", (IS_ARM(getCurrentBoard()) ? tr("Low") : FrSkyAlarmData::alarmLevelName(model->rssiAlarms.level[0])), false);
+ COMPARESTRING("", tr("Low"), false);
columns.append(": ");
COMPARESTRING("", QString("< %1").arg(QString::number(model->rssiAlarms.warning, 10)), true);
- COMPARESTRING("", (IS_ARM(getCurrentBoard()) ? tr("Critical") : FrSkyAlarmData::alarmLevelName(model->rssiAlarms.level[1])), false);
+ COMPARESTRING("", tr("Critical"), false);
columns.append(": ");
COMPARESTRING("", QString("< %1").arg(QString::number(model->rssiAlarms.critical, 10)), true);
COMPARESTRING(tr("Telemetry audio"), modelPrinter->printRssiAlarmsDisabled(model->rssiAlarms.disabled), false);
@@ -818,39 +805,9 @@ QString MultiModelPrinter::printTelemetry()
columns.appendRowEnd();
}
- if (IS_ARM(firmware->getBoard())) {
- ROWLABELCOMPARECELL("Multi sensors", 0, modelPrinter->printIgnoreSensorIds(!model->frsky.ignoreSensorIds), 0);
- }
+ ROWLABELCOMPARECELL("Multi sensors", 0, modelPrinter->printIgnoreSensorIds(!model->frsky.ignoreSensorIds), 0);
// Various
- if (!IS_ARM(firmware->getBoard())) {
- columns.appendRowHeader(QStringList() << tr("Various"));
- if (!firmware->getCapability(NoTelemetryProtocol)) {
- columns.appendRowStart("", 20);
- LABELCOMPARECELL(tr("Serial protocol"), modelPrinter->printTelemetrySource(model->frsky.voltsSource), 80);
- columns.appendRowEnd();
- }
- columns.appendRowStart("", 20);
- columns.appendCellStart(80);
- QString firmware_id = g.profile[g.id()].fwType();
- if (firmware->getCapability(HasFasOffset) && firmware_id.contains("fasoffset")) {
- COMPARESTRING(tr("FAS offset"), QString("%1 A").arg(model->frsky.fasOffset/10.0), true);
- }
- if (firmware->getCapability(HasMahPersistent)) {
- COMPARESTRING(tr("mAh count"), QString("%1 mAh").arg(model->frsky.storedMah), true);
- COMPARESTRING(tr("Persistent mAh"), modelPrinter->printMahPersistent(model->frsky.mAhPersistent), false);
- }
- columns.appendRowEnd();
- columns.appendRowStart("", 20);
- columns.appendCellStart(80);
- COMPARESTRING(tr("Volts source"), modelPrinter->printVoltsSource(model->frsky.voltsSource), true);
- COMPARESTRING(tr("Current source"), modelPrinter->printCurrentSource(model->frsky.currentSource), false);
- columns.appendCellEnd();
- columns.appendRowEnd();
- columns.appendRowStart("", 20);
- LABELCOMPARECELL(tr("Blades"), model->frsky.blades, 80);
- columns.appendRowEnd();
- }
columns.appendTableEnd();
str.append(columns.print());
return str;
diff --git a/companion/src/process_flash.cpp b/companion/src/process_flash.cpp
index 599d7e653..ee01e29d0 100644
--- a/companion/src/process_flash.cpp
+++ b/companion/src/process_flash.cpp
@@ -134,27 +134,30 @@ void FlashProcess::onKillTimerElapsed()
#endif
}
-void FlashProcess::analyseStandardOutput(const QString &text)
+void FlashProcess::analyseStandardOutput(const QString & text)
{
currStdoutLine.append(text);
+
if (currStdoutLine.contains("size = ")) {
int pos = currStdoutLine.lastIndexOf("size = ");
QString temp = currStdoutLine.mid(pos+7);
pos = temp.lastIndexOf("\n");
int size = temp.left(pos).toInt();
- progress->setMaximum(size/2048);
+ progress->setMaximum(size / 2048);
}
+
if (currStdoutLine.contains("\n")) {
int nlPos = currStdoutLine.lastIndexOf("\n");
currStdoutLine = currStdoutLine.mid(nlPos+1);
}
+
if (!currStdoutLine.isEmpty()) {
if (currStdoutLine.at(0) == QChar('.')) {
int pos = currStdoutLine.lastIndexOf(".");
progress->setValue(pos);
}
else if (currStdoutLine.startsWith("Starting upload: [")) {
- int pos = (currStdoutLine.lastIndexOf("#")-19)*100/256;
+ int pos = (currStdoutLine.lastIndexOf("#") - 19) * 100 / 256;
progress->setValue(pos);
}
}
@@ -168,7 +171,15 @@ void FlashProcess::analyseStandardOutput(const QString &text)
int end = text.indexOf("%");
if (start > 0) {
start += 9;
- int value = text.mid(start, end-start).toInt();
+ int value = text.mid(start, end - start).toInt();
+ progress->setValue(value);
+ }
+ }
+
+ if (text.contains("Upload\t[") || text.contains("Download\t[")) {
+ int end = text.indexOf("%");
+ if (end > 0) {
+ int value = text.mid(end - 3, 3).toInt();
progress->setValue(value);
}
}
@@ -277,7 +288,7 @@ void FlashProcess::errorWizard()
DeviceStr = "Atmega 2561";
}
}
- if (fwexist==false) {
+ if (!fwexist) {
QMessageBox::warning(nullptr, "Companion - Tip of the day", tr("Your radio uses a %1 CPU!!!\n\nPlease check advanced burn options to set the correct cpu type.").arg(DeviceStr));
}
else {
diff --git a/companion/src/process_flash.h b/companion/src/process_flash.h
index c39be2644..530938590 100644
--- a/companion/src/process_flash.h
+++ b/companion/src/process_flash.h
@@ -53,10 +53,10 @@ protected:
void analyseStandardError(const QString &text);
void errorWizard();
void addReadFuses();
- ProgressWidget *progress;
+ ProgressWidget * progress;
const QString cmd;
const QStringList args;
- QProcess *process;
+ QProcess * process;
bool hasErrors;
QString currStdoutLine;
QString currStderrLine;
diff --git a/companion/src/process_sync.h b/companion/src/process_sync.h
index 67a139791..4fffc4d66 100644
--- a/companion/src/process_sync.h
+++ b/companion/src/process_sync.h
@@ -85,7 +85,7 @@ class SyncProcess : public QObject
maxFileSize = 2 * 1024 * 1024;
logLevel = QtWarningMsg;
flags = OPT_RECURSIVE;
- dirFilterFlags = QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Readable;
+ dirFilterFlags = QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot;
}
friend inline QDebug operator<<(QDebug debug, const SyncOptions &o) {
diff --git a/companion/src/profilechooser.cpp b/companion/src/profilechooser.cpp
new file mode 100644
index 000000000..17a9570e5
--- /dev/null
+++ b/companion/src/profilechooser.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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 "profilechooser.h"
+#include "ui_profilechooser.h"
+#include "appdata.h"
+
+ProfileChooserDialog::ProfileChooserDialog(QWidget * parent):
+ QDialog(parent),
+ ui(new Ui::ProfileChooserDialog)
+{
+ ui->setupUi(this);
+ setWindowIcon(QIcon(":/icon.png"));
+ QComboBox *prof = ui->cboProfiles;
+ prof->clear();
+
+ QMap active;
+ active = g.getActiveProfiles();
+ QMapIterator i(active);
+ while (i.hasNext()) {
+ i.next();
+ prof->addItem(i.value(), i.key());
+ }
+
+ prof->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ prof->setCurrentIndex(prof->findData(g.id()));
+ connect(prof, SIGNAL(currentIndexChanged(int)), this, SLOT(on_cboProfilesCurrentIndexChanged(int)));
+}
+
+ProfileChooserDialog::~ProfileChooserDialog()
+{
+ delete ui;
+}
+
+void ProfileChooserDialog::on_cboProfilesCurrentIndexChanged(int index)
+{
+ QComboBox *prof = ui->cboProfiles;
+
+ if ((prof->currentIndex() > -1)) {
+ int oldid = g.id();
+ int newid = prof->currentData().toInt();
+ if (oldid != newid)
+ emit profileChanged(newid);
+ }
+}
diff --git a/companion/src/profilechooser.h b/companion/src/profilechooser.h
new file mode 100644
index 000000000..b40e6b359
--- /dev/null
+++ b/companion/src/profilechooser.h
@@ -0,0 +1,47 @@
+/*
+ * 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 _PROFILECHOOSER_H_
+#define _PROFILECHOOSER_H_
+
+#include
+
+namespace Ui {
+ class ProfileChooserDialog;
+}
+
+class ProfileChooserDialog : public QDialog
+{
+ Q_OBJECT
+
+ public:
+ ProfileChooserDialog(QWidget * parent = 0);
+ ~ProfileChooserDialog();
+signals:
+ void profileChanged(int newid);
+
+ private slots:
+ void on_cboProfilesCurrentIndexChanged(int index);
+
+ private:
+ Ui::ProfileChooserDialog *ui;
+};
+
+#endif // _PROFILECHOOSER_H_
diff --git a/companion/src/profilechooser.ui b/companion/src/profilechooser.ui
new file mode 100644
index 000000000..10a6d6bbe
--- /dev/null
+++ b/companion/src/profilechooser.ui
@@ -0,0 +1,110 @@
+
+
+ ProfileChooserDialog
+
+
+
+ 0
+ 0
+ 352
+ 102
+
+
+
+
+ 0
+ 0
+
+
+
+ Select Profile
+
+
+
+
+ 20
+ 20
+ 311
+ 66
+
+
+
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Profile
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Ok
+
+
+ false
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ ProfileChooserDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ ProfileChooserDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/companion/src/radiointerface.cpp b/companion/src/radiointerface.cpp
index 63befdd0c..0ad24fe6c 100644
--- a/companion/src/radiointerface.cpp
+++ b/companion/src/radiointerface.cpp
@@ -36,43 +36,8 @@ QString getRadioInterfaceCmd()
if (IS_STM32(board)) {
return bcd.getDFU();
}
- else if (IS_SKY9X(board)) {
+ else
return bcd.getSAMBA();
- }
- else {
- return bcd.getAVRDUDE();
- }
-}
-
-QStringList getAvrdudeArgs(const QString & cmd, const QString & filename)
-{
- QStringList args;
- burnConfigDialog bcd;
- QString programmer = bcd.getProgrammer();
- QString mcu = bcd.getMCU();
- Board::Type board = getCurrentBoard();
-
- args << "-c" << programmer << "-p";
- if (IS_2560(board))
- args << "m2560";
- else if (board == Board::BOARD_9X_M128)
- args << "m128";
- else
- args << mcu;
-
- args << bcd.getAvrdudeArgs();
-
- QString fullcmd = cmd + filename;
- if (QFileInfo(filename).suffix().toUpper() == "HEX")
- fullcmd += ":i";
- else if (QFileInfo(filename).suffix().toUpper()=="BIN")
- fullcmd += ":r";
- else
- fullcmd += ":a";
-
- args << "-U" << fullcmd;
-
- return args;
}
QStringList getDfuArgs(const QString & cmd, const QString & filename)
@@ -119,11 +84,8 @@ QStringList getReadEEpromCmd(const QString & filename)
if (IS_STM32(eepromInterface->getBoard())) {
// impossible
}
- else if (IS_SKY9X(eepromInterface->getBoard())) {
- result = getSambaArgs(QString("SERIALFLASH::Init 0\n") + "receive_file {SerialFlash AT25} \"" + filename + "\" 0x0 0x80000 0\n");
- }
else {
- result = getAvrdudeArgs("eeprom:r:", filename);
+ result = getSambaArgs(QString("SERIALFLASH::Init 0\n") + "receive_file {SerialFlash AT25} \"" + filename + "\" 0x0 0x80000 0\n");
}
return result;
}
@@ -135,11 +97,8 @@ QStringList getWriteEEpromCmd(const QString & filename)
// impossible
return QStringList();
}
- else if (IS_SKY9X(board)) {
- return getSambaArgs(QString("SERIALFLASH::Init 0\n") + "send_file {SerialFlash AT25} \"" + filename + "\" 0x0 0\n");
- }
else {
- return getAvrdudeArgs("eeprom:w:", filename);
+ return getSambaArgs(QString("SERIALFLASH::Init 0\n") + "send_file {SerialFlash AT25} \"" + filename + "\" 0x0 0\n");
}
}
@@ -152,11 +111,8 @@ QStringList getWriteFirmwareArgs(const QString & filename)
else if (board == Board::BOARD_SKY9X) {
return getSambaArgs(QString("send_file {Flash} \"") + filename + "\" 0x400000 0\n" + "FLASH::ScriptGPNMV 2\n");
}
- else if (board == Board::BOARD_9XRPRO || board == Board::BOARD_AR9X) {
- return getSambaArgs(QString("send_file {Flash} \"") + filename + "\" 0x400000 0\n" + "FLASH::ScriptGPNMV 2\n");
- }
else {
- return getAvrdudeArgs("flash:w:", filename);
+ return getSambaArgs(QString("send_file {Flash} \"") + filename + "\" 0x400000 0\n" + "FLASH::ScriptGPNMV 2\n");
}
}
@@ -169,91 +125,11 @@ QStringList getReadFirmwareArgs(const QString & filename)
else if (board == Board::BOARD_SKY9X) {
return getSambaArgs(QString("receive_file {Flash} \"") + filename + "\" 0x400000 0x40000 0\n");
}
- else if (board == Board::BOARD_9XRPRO) {
+ else {
return getSambaArgs(QString("receive_file {Flash} \"") + filename + "\" 0x400000 0x80000 0\n");
}
- else {
- return getAvrdudeArgs("flash:r:", filename);
- }
}
-void readAvrdudeFuses(ProgressWidget * progress)
-{
- burnConfigDialog bcd;
- QStringList args;
- args << "-c" << bcd.getProgrammer() << "-p" << bcd.getMCU() << bcd.getAvrdudeArgs() << "-U" << "lfuse:r:-:i" << "-U" << "hfuse:r:-:i" << "-U" << "efuse:r:-:i";
- FlashProcess flashProcess(bcd.getAVRDUDE(), args, progress);
- flashProcess.run();
-}
-
-void resetAvrdudeFuses(bool eepromProtect, ProgressWidget * progress)
-{
- //fuses
- //avrdude -c usbasp -p m64 -U lfuse:w:<0x0E>:m
- //avrdude -c usbasp -p m64 -U hfuse:w:<0x89>:m 0x81 for eeprom protection
- //avrdude -c usbasp -p m64 -U efuse:w:<0xFF>:m
-
- burnConfigDialog bcd;
- QMessageBox::StandardButton ret = QMessageBox::No;
- ret = QMessageBox::warning(NULL, CPN_STR_APP_NAME,
- QCoreApplication::translate("RadioInterface",
- "WARNING!" \
- "
This will reset the fuses of %1 to the factory settings.
"
- "Writing fuses can mess up your radio.
Do this only if you are sure they are wrong!
"
- "Are you sure you want to continue?").arg(bcd.getMCU()),
- QMessageBox::Yes | QMessageBox::No);
- if (ret == QMessageBox::Yes) {
- QStringList args = bcd.getAvrdudeArgs();
- QStringList str;
- if (bcd.getMCU() == "m2560") {
- args << "-B8";
- QString erStr = eepromProtect ? "hfuse:w:0x51:m" : "hfuse:w:0x59:m";
- str << "-U" << "lfuse:w:0xD7:m" << "-U" << erStr << "-U" << "efuse:w:0xFC:m";
- //use hfuse = 0x81 to prevent eeprom being erased with every flashing
- }
- else {
- QString lfuses;
- QString tempFile = generateProcessUniqueTempFileName("ftemp.bin");
- QStringList argread;
- argread << "-c" << bcd.getProgrammer() << "-p" << bcd.getMCU() << args <<"-U" << "lfuse:r:"+tempFile+":r";
- FlashProcess flashProcess(bcd.getAVRDUDE(), argread, progress);
- flashProcess.run();
- QFile file(tempFile);
- if (file.exists() && file.size()==1) {
- file.open(QIODevice::ReadOnly);
- char bin_flash[1];
- file.read(bin_flash, 1);
- if (bin_flash[0]==0x0E) {
- lfuses = "lfuse:w:0x0E:m";
- }
- else {
- lfuses = "lfuse:w:0x3F:m";
- }
- file.close();
- qunlink(tempFile);
- }
- else {
- lfuses = "lfuse:w:0x3F:m";
- }
-
- QString erStr = eepromProtect ? "hfuse:w:0xC1:m" : "hfuse:w:0xC9:m";
- str << "-U" << lfuses << "-U" << erStr << "-U" << "efuse:w:0xFF:m";
- //use hfuse = 0x81 to prevent eeprom being erased with every flashing
- }
-
- QStringList arguments;
- if (bcd.getMCU() == "m2560") {
- arguments << "-c" << bcd.getProgrammer() << "-p" << bcd.getMCU() << args << "-u" << str;
- }
- else {
- arguments << "-c" << bcd.getProgrammer() << "-p" << bcd.getMCU() << args << "-B" << "100" << "-u" << str;
- }
- FlashProcess flashProcess(bcd.getAVRDUDE(), arguments, progress);
- flashProcess.run();
- }
-}
-
-
bool readFirmware(const QString & filename, ProgressWidget * progress)
{
bool result = false;
@@ -265,16 +141,14 @@ bool readFirmware(const QString & filename, ProgressWidget * progress)
return false;
}
- if (IS_ARM(getCurrentBoard())) {
- QString path = findMassstoragePath("FIRMWARE.BIN");
- if (!path.isEmpty()) {
- qDebug() << "readFirmware: reading" << path << "into" << filename;
- CopyProcess copyProcess(path, filename, progress);
- result = copyProcess.run();
- }
+ QString path = findMassstoragePath("FIRMWARE.BIN");
+ if (!path.isEmpty()) {
+ qDebug() << "readFirmware: reading" << path << "into" << filename;
+ CopyProcess copyProcess(path, filename, progress);
+ result = copyProcess.run();
}
- if (result == false) {
+ if (!result) {
qDebug() << "readFirmware: reading" << filename << "with" << getRadioInterfaceCmd() << getReadFirmwareArgs(filename);
FlashProcess flashProcess(getRadioInterfaceCmd(), getReadFirmwareArgs(filename), progress);
result = flashProcess.run();
@@ -289,13 +163,11 @@ bool readFirmware(const QString & filename, ProgressWidget * progress)
bool writeFirmware(const QString & filename, ProgressWidget * progress)
{
- if (IS_ARM(getCurrentBoard())) {
- QString path = findMassstoragePath("FIRMWARE.BIN");
- if (!path.isEmpty()) {
- qDebug() << "writeFirmware: writing" << path << "from" << filename;
- CopyProcess copyProcess(filename, path, progress);
- return copyProcess.run();
- }
+ QString path = findMassstoragePath("FIRMWARE.BIN");
+ if (!path.isEmpty()) {
+ qDebug() << "writeFirmware: writing" << path << "from" << filename;
+ CopyProcess copyProcess(filename, path, progress);
+ return copyProcess.run();
}
qDebug() << "writeFirmware: writing" << filename << "with" << getRadioInterfaceCmd() << getWriteFirmwareArgs(filename);
@@ -314,12 +186,12 @@ bool readEeprom(const QString & filename, ProgressWidget * progress)
return false;
}
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
QString radioPath = findMassstoragePath("RADIO", true);
qDebug() << "Searching for SD card, found" << radioPath;
if (radioPath.isEmpty()) {
QMessageBox::critical(progress, CPN_STR_TTL_ERROR,
- QCoreApplication::translate("RadioInterface", "Unable to find Horus radio SD card!"));
+ QCoreApplication::translate("RadioInterface", "Unable to find radio SD card!"));
return false;
}
RadioData radioData;
@@ -340,26 +212,25 @@ bool readEeprom(const QString & filename, ProgressWidget * progress)
}
}
else {
- if (IS_ARM(board)) {
- QString path = findMassstoragePath("EEPROM.BIN");
- if (path.isEmpty()) {
- // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :(
- path = findMassstoragePath("TARANIS.BIN");
- }
- if (path.isEmpty()) {
- // Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :(
- path = findMassstoragePath("ERSKY9X.BIN");
- }
- if (path.isEmpty()) {
- RadioNotFoundDialog dialog(progress);
- dialog.exec();
- return false;
- }
- CopyProcess copyProcess(path, filename, progress);
- if (!copyProcess.run()) {
- return false;
- }
+ QString path = findMassstoragePath("EEPROM.BIN");
+ if (path.isEmpty()) {
+ // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :(
+ path = findMassstoragePath("TARANIS.BIN");
}
+ if (path.isEmpty()) {
+ // Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :(
+ path = findMassstoragePath("ERSKY9X.BIN");
+ }
+ if (path.isEmpty()) {
+ RadioNotFoundDialog dialog(progress);
+ dialog.exec();
+ return false;
+ }
+ CopyProcess copyProcess(path, filename, progress);
+ if (!copyProcess.run()) {
+ return false;
+ }
+
if (!IS_STM32(board)) {
FlashProcess flashProcess(getRadioInterfaceCmd(), getReadEEpromCmd(filename), progress);
@@ -376,20 +247,18 @@ bool writeEeprom(const QString & filename, ProgressWidget * progress)
{
Board::Type board = getCurrentBoard();
- if (IS_ARM(board)) {
- QString path = findMassstoragePath("EEPROM.BIN");
- if (path.isEmpty()) {
- // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :(
- path = findMassstoragePath("TARANIS.BIN");
- }
- if (path.isEmpty()) {
- // Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :(
- path = findMassstoragePath("ERSKY9X.BIN");
- }
- if (!path.isEmpty()) {
- CopyProcess copyProcess(filename, path, progress);
- return copyProcess.run();
- }
+ QString path = findMassstoragePath("EEPROM.BIN");
+ if (path.isEmpty()) {
+ // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :(
+ path = findMassstoragePath("TARANIS.BIN");
+ }
+ if (path.isEmpty()) {
+ // Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :(
+ path = findMassstoragePath("ERSKY9X.BIN");
+ }
+ if (!path.isEmpty()) {
+ CopyProcess copyProcess(filename, path, progress);
+ return copyProcess.run();
}
if (!IS_TARANIS(board)) {
@@ -397,10 +266,8 @@ bool writeEeprom(const QString & filename, ProgressWidget * progress)
return flashProcess.run();
}
- if (IS_ARM(board)) {
- RadioNotFoundDialog dialog(progress);
- dialog.exec();
- }
+ RadioNotFoundDialog dialog(progress);
+ dialog.exec();
return false;
}
diff --git a/companion/src/radiointerface.h b/companion/src/radiointerface.h
index f896d96c5..37053fac5 100644
--- a/companion/src/radiointerface.h
+++ b/companion/src/radiointerface.h
@@ -30,13 +30,9 @@ QString getRadioInterfaceCmd();
QString findMassstoragePath(const QString &filename, bool onlyPath = false);
-QStringList getAvrdudeArgs(const QString &cmd, const QString &filename);
QStringList getSambaArgs(const QString &tcl);
QStringList getDfuArgs(const QString &cmd, const QString &filename);
-void readAvrdudeFuses(ProgressWidget *progress);
-void resetAvrdudeFuses(bool eepromProtect, ProgressWidget *progress);
-
QStringList getReadEEpromCmd(const QString &filename);
QStringList getWriteEEpromCmd(const QString &filename);
QStringList getReadFirmwareArgs(const QString &filename);
diff --git a/companion/src/releasenotesfirmwaredialog.cpp b/companion/src/releasenotesfirmwaredialog.cpp
index bcce6709c..753599c52 100644
--- a/companion/src/releasenotesfirmwaredialog.cpp
+++ b/companion/src/releasenotesfirmwaredialog.cpp
@@ -50,4 +50,3 @@ void ReleaseNotesFirmwareDialog::replyFinished(QNetworkReply * reply)
ui->textEditor->setOpenExternalLinks(true);
reply->deleteLater();
}
-
diff --git a/companion/src/shared/CMakeLists.txt b/companion/src/shared/CMakeLists.txt
index 81df9dd67..2fbbafbf9 100644
--- a/companion/src/shared/CMakeLists.txt
+++ b/companion/src/shared/CMakeLists.txt
@@ -15,6 +15,7 @@ set(shared_HDRS
autolineedit.h
genericpanel.h
hexspinbox.h
+ autoprecisioncombobox.h
)
qt5_wrap_cpp(shared_SRCS ${shared_HDRS})
diff --git a/companion/src/shared/autoprecisioncombobox.h b/companion/src/shared/autoprecisioncombobox.h
new file mode 100644
index 000000000..4e143f286
--- /dev/null
+++ b/companion/src/shared/autoprecisioncombobox.h
@@ -0,0 +1,257 @@
+/*
+ * 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 _AUTOPRECISIONCOMBOBOX_H_
+#define _AUTOPRECISIONCOMBOBOX_H_
+
+#include "genericpanel.h"
+
+#include
+#include
+
+class AutoPrecisionComboBox: public QComboBox
+{
+ Q_OBJECT
+ //! \property minDecimals Determines the first list item
+ Q_PROPERTY(unsigned int minDecimals READ minDecimals WRITE setMinDecimals)
+ //! \property maxDecimals Determines the last list item
+ Q_PROPERTY(unsigned int maxDecimals READ maxDecimals WRITE setMaxDecimals)
+ //! \property padding If true, add trailing underscore placeholders to each list item
+ Q_PROPERTY(bool padding READ padding WRITE setPadding)
+ //! \property suffix Optional text suffix to each list value
+ Q_PROPERTY(QString suffix READ suffix WRITE setSuffix)
+
+ public:
+ explicit AutoPrecisionComboBox(QWidget * parent = nullptr):
+ QComboBox(parent)
+ {
+ init();
+ }
+
+ explicit AutoPrecisionComboBox(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr):
+ QComboBox(parent)
+ {
+ setField(field, minDecimals, maxDecimals, padding, suffix, panel);
+ init();
+ }
+
+ explicit AutoPrecisionComboBox(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr):
+ QComboBox(parent)
+ {
+ setField(field, minDecimals, maxDecimals, padding, suffix, panel);
+ init();
+ }
+
+ inline int minDecimals() const { return m_minDecimals; }
+ inline int maxDecimals() const { return m_maxDecimals; }
+ inline bool padding() const { return m_padding; }
+ inline QString suffix() const { return m_suffix; }
+
+ public slots:
+ void setField(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr)
+ {
+ m_field = reinterpret_cast(&field);
+ initField(minDecimals, maxDecimals, padding, suffix);
+ setPanel(panel);
+ }
+
+ void setField(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr)
+ {
+ m_field = &field;
+ initField(minDecimals, maxDecimals, padding, suffix);
+ setPanel(panel);
+ }
+
+ void setMinDecimals(unsigned int minDecimals)
+ {
+ m_minDecimals = rangecheckDecimals(minDecimals);
+ if (m_minDecimals > m_maxDecimals)
+ m_minDecimals = m_maxDecimals;
+ if (!m_lock)
+ updateList();
+ }
+
+ void setMaxDecimals(unsigned int maxDecimals)
+ {
+ m_maxDecimals = rangecheckDecimals(maxDecimals);
+ if (m_maxDecimals < m_minDecimals)
+ m_maxDecimals = m_minDecimals;
+ if (!m_lock)
+ updateList();
+ }
+
+ void setPadding(bool padding)
+ {
+ m_padding = padding;
+ if (!m_lock)
+ updateList();
+ }
+
+ void setSuffix(QString suffix)
+ {
+ m_suffix = suffix.trimmed();
+ if (!m_lock)
+ updateList();
+ }
+
+ void setPanel(GenericPanel * panel)
+ {
+ m_panel = panel;
+ }
+
+ void setValue(int value)
+ {
+ if (!m_field)
+ return;
+ const unsigned int val = (unsigned int)value;
+ if (*m_field != val) {
+ *m_field = rangecheckDecimals(val);
+ updateValue();
+ emit valueChanged();
+ }
+ }
+
+ void setValue(unsigned int value)
+ {
+ if (!m_field)
+ return;
+ if (*m_field != value) {
+ *m_field = rangecheckDecimals(value);
+ updateValue();
+ emit valueChanged();
+ }
+ }
+
+ void updateValue()
+ {
+ if (!m_field)
+ return;
+ if (!isValidDecimals(*m_field))
+ return;
+ if (*m_field > m_maxDecimals) {
+ setMaxDecimals(*m_field);
+ }
+ const bool savedlock = setLocked(true);
+ setCurrentIndex(findData(*m_field));
+ setLocked(savedlock);
+ }
+
+ void setAutoIndexes()
+ {
+ for (int i = 0; i < count(); ++i)
+ setItemData(i, i);
+ updateValue();
+ }
+
+ signals:
+ void valueChanged();
+
+ protected slots:
+ void init()
+ {
+ connect(this, QOverload::of(&AutoPrecisionComboBox::currentIndexChanged), this, &AutoPrecisionComboBox::onCurrentIndexChanged);
+ }
+
+ void initField(unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix)
+ {
+ const bool savedlock = setLocked(true);
+ setMinDecimals(minDecimals);
+ setMaxDecimals(maxDecimals);
+ setPadding(padding);
+ setSuffix(suffix);
+ setLocked(savedlock);
+ updateList();
+ }
+
+ void updateList()
+ {
+ const bool savedlock = setLocked(true);
+ unsigned int i;
+ int j;
+ clear();
+
+ for (i = APCB_DECIMALS_MIN, j = (int)m_maxDecimals; j >= 0; i++, j--) {
+ if (i >= m_minDecimals) {
+ QString str = QString("0.%1").arg(QString(i, '0'));
+ if (m_padding)
+ str.append(QString(j, '_'));
+ if (m_suffix != "")
+ str.append(QString(" %1").arg(m_suffix));
+ addItem(str, i);
+ }
+ }
+
+ setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ setLocked(savedlock);
+ }
+
+ void onCurrentIndexChanged(int index)
+ {
+ if (index < 0)
+ return;
+ if (m_field && !m_lock) {
+ *m_field = itemData(index).toUInt();
+ if (m_panel)
+ emit m_panel->modified();
+ emit valueChanged();
+ }
+ }
+
+ unsigned int rangecheckDecimals(unsigned int decimals)
+ {
+ unsigned int ret;
+ if (decimals < APCB_DECIMALS_MIN)
+ ret = APCB_DECIMALS_MIN;
+ else if (decimals > APCB_DECIMALS_MAX)
+ ret = APCB_DECIMALS_MAX;
+ else
+ ret = decimals;
+ return ret;
+ }
+
+ bool isValidDecimals(unsigned int value)
+ {
+ if (value >= APCB_DECIMALS_MIN && value <= APCB_DECIMALS_MAX)
+ return true;
+ else
+ return false;
+ }
+
+ bool setLocked(bool lock)
+ {
+ const bool ret = m_lock;
+ m_lock = lock;
+ return ret;
+ }
+
+ protected:
+ constexpr static unsigned int APCB_DECIMALS_MIN = {0};
+ constexpr static unsigned int APCB_DECIMALS_MAX = {6};
+
+ unsigned int * m_field = nullptr;
+ GenericPanel * m_panel = nullptr;
+ unsigned int m_minDecimals = 0;
+ unsigned int m_maxDecimals = 0;
+ bool m_padding = false;
+ QString m_suffix = "";
+ bool m_lock = false;
+};
+
+#endif // _AUTOPRECISIONCOMBOBOX_H_
diff --git a/companion/src/shared/genericpanel.h b/companion/src/shared/genericpanel.h
index 1ce8e906e..5351355b6 100644
--- a/companion/src/shared/genericpanel.h
+++ b/companion/src/shared/genericpanel.h
@@ -39,6 +39,7 @@ class GenericPanel : public QWidget
friend class AutoHexSpinBox;
friend class AutoLineEdit;
friend class GVarGroup;
+ friend class AutoPrecisionComboBox;
public:
GenericPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware);
diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt
index 7601f8f04..a03090888 100644
--- a/companion/src/simulation/CMakeLists.txt
+++ b/companion/src/simulation/CMakeLists.txt
@@ -14,6 +14,8 @@ set(simulation_SRCS
simulateduiwidgetX12.cpp
simulateduiwidgetJumperT12.cpp
simulateduiwidgetJumperT16.cpp
+ simulateduiwidgetJumperT18.cpp
+ simulateduiwidgetTX16S.cpp
simulatorinterface.cpp
simulatormainwindow.cpp
simulatorstartupdialog.cpp
@@ -38,6 +40,8 @@ set(simulation_UIS
simulateduiwidgetX12.ui
simulateduiwidgetJumperT12.ui
simulateduiwidgetJumperT16.ui
+ simulateduiwidgetJumperT18.ui
+ simulateduiwidgetTX16S.ui
simulatormainwindow.ui
simulatorstartupdialog.ui
simulatorwidget.ui
diff --git a/companion/src/simulation/joystick.cpp b/companion/src/simulation/joystick.cpp
index 87f7476f0..070825a21 100644
--- a/companion/src/simulation/joystick.cpp
+++ b/companion/src/simulation/joystick.cpp
@@ -99,8 +99,9 @@ void Joystick::processEvents()
axes[i] = moved;
}
}
- else
+ else {
axisRepeatTimers[i].restart();
+ }
}
else {
emit axisValueChanged(i, 0);
@@ -108,17 +109,20 @@ void Joystick::processEvents()
}
for (i = 0; i < numButtons; i++) {
Uint8 changed = SDL_JoystickGetButton(joystick, i);
- if ( (changed != buttons[i]) ) {
+ if ((changed != buttons[i])) {
emit buttonValueChanged(i, (bool) changed);
buttons[i] = changed;
buttonRepeatTimers[i].restart();
- } else if (autoRepeat && changed != 0) {
+ }
+ else if (autoRepeat && changed != 0) {
if ( buttonRepeatTimers[i].elapsed() >= autoRepeatDelay ) {
emit buttonValueChanged(i, (bool) changed);
buttons[i] = changed;
}
- } else
+ }
+ else {
buttonRepeatTimers[i].restart();
+ }
}
for (i = 0; i < numHats; i++) {
Uint8 changed = SDL_JoystickGetHat(joystick, i);
@@ -126,19 +130,22 @@ void Joystick::processEvents()
emit hatValueChanged(i, changed);
hats[i] = changed;
hatRepeatTimers[i].restart();
- } else if (autoRepeat && changed != 0) {
- if ( hatRepeatTimers[i].elapsed() >= autoRepeatDelay ) {
+ }
+ else if (autoRepeat && changed != 0) {
+ if (hatRepeatTimers[i].elapsed() >= autoRepeatDelay) {
emit hatValueChanged(i, changed);
hats[i] = changed;
}
- } else
+ }
+ else {
hatRepeatTimers[i].restart();
+ }
}
for (i = 0; i < numTrackballs; i++) {
int dx, dy;
SDL_JoystickGetBall(joystick, i, &dx, &dy);
- if ( dx != 0 || dy != 0 )
+ if (dx != 0 || dy != 0)
emit trackballValueChanged(i, dx, dy);
}
}
diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h
index d688c641a..8419840c5 100644
--- a/companion/src/simulation/simulateduiwidget.h
+++ b/companion/src/simulation/simulateduiwidget.h
@@ -113,6 +113,8 @@ namespace Ui {
class SimulatedUIWidgetX12;
class SimulatedUIWidgetJumperT12;
class SimulatedUIWidgetJumperT16;
+ class SimulatedUIWidgetJumperT18;
+ class SimulatedUIWidgetTX16S;
}
class SimulatedUIWidget9X: public SimulatedUIWidget
@@ -251,5 +253,29 @@ class SimulatedUIWidgetJumperT16: public SimulatedUIWidget
Ui::SimulatedUIWidgetJumperT16 * ui;
};
+class SimulatedUIWidgetJumperT18: public SimulatedUIWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit SimulatedUIWidgetJumperT18(SimulatorInterface * simulator, QWidget * parent = nullptr);
+ virtual ~SimulatedUIWidgetJumperT18();
+
+ private:
+ Ui::SimulatedUIWidgetJumperT18 * ui;
+};
+
+class SimulatedUIWidgetTX16S: public SimulatedUIWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit SimulatedUIWidgetTX16S(SimulatorInterface * simulator, QWidget * parent = nullptr);
+ virtual ~SimulatedUIWidgetTX16S();
+
+ private:
+ Ui::SimulatedUIWidgetTX16S * ui;
+};
+
#endif // SIMULATEDUIWIDGET_H
diff --git a/companion/src/simulation/simulateduiwidgetJumperT16.cpp b/companion/src/simulation/simulateduiwidgetJumperT16.cpp
index 317fdb24c..66fc7f36e 100644
--- a/companion/src/simulation/simulateduiwidgetJumperT16.cpp
+++ b/companion/src/simulation/simulateduiwidgetJumperT16.cpp
@@ -34,27 +34,27 @@ SimulatedUIWidgetJumperT16::SimulatedUIWidgetJumperT16(SimulatorInterface *simul
// add actions in order of appearance on the help menu
act = new RadioUiAction(3, QList() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL);
- addRadioWidget(ui->leftbuttons->addArea(QRect(10, 70, 80, 35), "JumperT16/left_mdl.png", act));
+ addRadioWidget(ui->leftbuttons->addArea(QRect(50, 70, 80, 35), "JumperT16/left_mdl.png", act));
act = new RadioUiAction(6, QList() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS);
- addRadioWidget(ui->leftbuttons->addArea(QRect(10, 10, 80, 35), "JumperT16/left_sys.png", act));
+ addRadioWidget(ui->leftbuttons->addArea(QRect(25, 10, 95, 35), "JumperT16/left_sys.png", act));
act = new RadioUiAction(5, QList() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE);
- addRadioWidget(ui->leftbuttons->addArea(QRect(10, 190, 80, 35), "JumperT16/left_tele.png", act));
+ addRadioWidget(ui->leftbuttons->addArea(QRect(50, 190, 80, 35), "JumperT16/left_tele.png", act));
act = new RadioUiAction(4, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace,
SIMU_STR_HLP_KEY_DN % "
" % SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_RTN);
- addRadioWidget(ui->rightbuttons->addArea(QRect(35, 10, 80, 35), "JumperT16/right_rtn.png", act));
+ addRadioWidget(ui->rightbuttons->addArea(QRect(50, 10, 95, 35), "JumperT16/right_rtn.png", act));
act = new RadioUiAction(1, QList() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN);
- addRadioWidget(ui->leftbuttons->addArea(QRect(10, 131, 80, 35), "JumperT16/left_page.png", act));
+ addRadioWidget(ui->leftbuttons->addArea(QRect(50, 131, 80, 35), "JumperT16/left_page.png", act));
m_scrollUpAction = new RadioUiAction(-1, QList() << Qt::Key_Minus, SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_ROT_LFT);
m_scrollDnAction = new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT);
connectScrollActions();
m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
- addRadioWidget(ui->rightbuttons->addArea(QRect(45, 70, 100, 160), "JumperT16/right_ent.png", m_mouseMidClickAction));
+ addRadioWidget(ui->rightbuttons->addArea(QRect(55, 90, 56, 120), "JumperT16/right_ent.png", m_mouseMidClickAction));
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 252, 30, 30), "JumperT16/left_scrnsht.png", m_screenshotAction));
diff --git a/companion/src/simulation/simulateduiwidgetJumperT18.cpp b/companion/src/simulation/simulateduiwidgetJumperT18.cpp
new file mode 100644
index 000000000..1a66138ca
--- /dev/null
+++ b/companion/src/simulation/simulateduiwidgetJumperT18.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+// NOTE: RadioUiAction(NUMBER,...): NUMBER relates to enum EnumKeys in the specific board.h
+
+#include "simulateduiwidget.h"
+#include "ui_simulateduiwidgetJumperT18.h"
+
+SimulatedUIWidgetJumperT18::SimulatedUIWidgetJumperT18(SimulatorInterface *simulator, QWidget * parent):
+ SimulatedUIWidget(simulator, parent),
+ ui(new Ui::SimulatedUIWidgetJumperT18)
+{
+ RadioUiAction * act;
+
+ ui->setupUi(this);
+
+ // add actions in order of appearance on the help menu
+
+ act = new RadioUiAction(3, QList() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(60, 90, 80, 35), "JumperT18/left_mdl.png", act));
+
+ act = new RadioUiAction(6, QList() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(25, 5, 100, 40), "JumperT18/left_sys.png", act));
+
+ act = new RadioUiAction(5, QList() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(60, 180, 80, 35), "JumperT18/left_tele.png", act));
+
+ act = new RadioUiAction(4, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace,
+ SIMU_STR_HLP_KEY_DN % "
" % SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_RTN);
+ addRadioWidget(ui->rightbuttons->addArea(QRect(20, 5, 100, 40), "JumperT18/right_rtn.png", act));
+
+ act = new RadioUiAction(1, QList() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(60, 140, 80, 35), "JumperT18/left.png", act));
+
+ m_scrollUpAction = new RadioUiAction(-1, QList() << Qt::Key_Minus, SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_ROT_LFT);
+ m_scrollDnAction = new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT);
+ connectScrollActions();
+
+ m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
+ addRadioWidget(ui->rightbuttons->addArea(QRect(25, 90, 70, 130), "JumperT18/right_ent.png", m_mouseMidClickAction));
+
+ addRadioWidget(ui->leftbuttons->addArea(QRect(10, 245, 30, 30), "JumperT18/left_scrnsht.png", m_screenshotAction));
+
+ m_backlightColors << QColor(47, 123, 227);
+
+ setLcd(ui->lcd);
+}
+
+SimulatedUIWidgetJumperT18::~SimulatedUIWidgetJumperT18()
+{
+ delete ui;
+}
diff --git a/companion/src/simulation/simulateduiwidgetJumperT18.ui b/companion/src/simulation/simulateduiwidgetJumperT18.ui
new file mode 100644
index 000000000..1c14df404
--- /dev/null
+++ b/companion/src/simulation/simulateduiwidgetJumperT18.ui
@@ -0,0 +1,197 @@
+
+
+ SimulatedUIWidgetJumperT18
+
+
+
+ 0
+ 0
+ 825
+ 292
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 825
+ 292
+
+
+
+
+ 825
+ 292
+
+
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 131
+ 289
+
+
+
+
+ 131
+ 289
+
+
+
+ background:url(:/images/simulator/JumperT18/right.png)
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 480
+ 272
+
+
+
+
+ 480
+ 272
+
+
+
+
+ 5
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 131
+ 289
+
+
+
+
+ 131
+ 289
+
+
+
+ true
+
+
+ background:url(:/images/simulator/JumperT18/left.png);
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 480
+ 10
+
+
+
+
+ 480
+ 10
+
+
+
+
+ 5
+
+
+
+ background:url(:/images/simulator/JumperT18/top.png)
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 480
+ 10
+
+
+
+
+ 480
+ 10
+
+
+
+
+ 5
+ false
+
+
+
+ background:url(:/images/simulator/JumperT18/bottom.png)
+
+
+
+
+
+
+
+ LcdWidget
+ QWidget
+
+ 1
+
+
+ ButtonsWidget
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/companion/src/simulation/simulateduiwidgetTX16S.cpp b/companion/src/simulation/simulateduiwidgetTX16S.cpp
new file mode 100644
index 000000000..76bfd1f33
--- /dev/null
+++ b/companion/src/simulation/simulateduiwidgetTX16S.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+// NOTE: RadioUiAction(NUMBER,...): NUMBER relates to enum EnumKeys in the specific board.h
+
+#include "simulateduiwidget.h"
+#include "ui_simulateduiwidgetTX16S.h"
+
+SimulatedUIWidgetTX16S::SimulatedUIWidgetTX16S(SimulatorInterface *simulator, QWidget * parent):
+ SimulatedUIWidget(simulator, parent),
+ ui(new Ui::SimulatedUIWidgetTX16S)
+{
+ RadioUiAction * act;
+
+ ui->setupUi(this);
+
+ // add actions in order of appearance on the help menu
+
+ act = new RadioUiAction(3, QList() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL);
+ addRadioWidget(ui->rightbuttons->addArea(QRect(40, 0, 110, 35), "TX16S/right_mdl.png", act));
+
+ m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
+ addRadioWidget(ui->rightbuttons->addArea(QRect(45, 70, 100, 160), "TX16S/right_ent.png", m_mouseMidClickAction));
+
+ act = new RadioUiAction(6, QList() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(32, 1, 80, 35), "TX16S/left_sys.png", act));
+
+ act = new RadioUiAction(5, QList() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(55, 220, 80, 35), "TX16S/left_tele.png", act));
+
+ act = new RadioUiAction(1, QList() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(55, 115, 80, 35), "TX16S/left_page.png", act));
+
+ act = new RadioUiAction(0, QList() << Qt::Key_PageUp, SIMU_STR_HLP_KEY_PGUP, SIMU_STR_HLP_ACT_PGUP);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(55, 160, 80, 35), "TX16S/left_page2.png", act));
+
+ act = new RadioUiAction(4, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace,
+ SIMU_STR_HLP_KEY_DN % "
" % SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_RTN);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(55, 55, 80, 35), "TX16S/left_rtn.png", act));
+
+ m_scrollUpAction = new RadioUiAction(-1, QList() << Qt::Key_Minus, SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_ROT_LFT);
+ m_scrollDnAction = new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT);
+ connectScrollActions();
+
+ addRadioWidget(ui->leftbuttons->addArea(QRect(10, 245, 30, 30), "TX16S/left_scrnsht.png", m_screenshotAction));
+
+ m_backlightColors << QColor(47, 123, 227);
+
+ setLcd(ui->lcd);
+}
+
+SimulatedUIWidgetTX16S::~SimulatedUIWidgetTX16S()
+{
+ delete ui;
+}
diff --git a/companion/src/simulation/simulateduiwidgetTX16S.ui b/companion/src/simulation/simulateduiwidgetTX16S.ui
new file mode 100644
index 000000000..e5137d992
--- /dev/null
+++ b/companion/src/simulation/simulateduiwidgetTX16S.ui
@@ -0,0 +1,197 @@
+
+
+ SimulatedUIWidgetTX16S
+
+
+
+ 0
+ 0
+ 825
+ 292
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 825
+ 292
+
+
+
+
+ 825
+ 292
+
+
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 174
+ 292
+
+
+
+
+ 174
+ 292
+
+
+
+ background:url(:/images/simulator/TX16S/right.png)
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 480
+ 272
+
+
+
+
+ 480
+ 272
+
+
+
+
+ 5
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 174
+ 292
+
+
+
+
+ 174
+ 292
+
+
+
+ true
+
+
+ background:url(:/images/simulator/TX16S/left.png);
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 480
+ 10
+
+
+
+
+ 480
+ 10
+
+
+
+
+ 5
+
+
+
+ background:url(:/images/simulator/TX16S/top.png)
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 480
+ 10
+
+
+
+
+ 480
+ 10
+
+
+
+
+ 5
+ false
+
+
+
+ background:url(:/images/simulator/TX16S/bottom.png)
+
+
+
+
+
+
+
+ LcdWidget
+ QWidget
+
+ 1
+
+
+ ButtonsWidget
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/companion/src/simulation/simulatorstartupdialog.cpp b/companion/src/simulation/simulatorstartupdialog.cpp
index 57272bf99..b7faf0261 100644
--- a/companion/src/simulation/simulatorstartupdialog.cpp
+++ b/companion/src/simulation/simulatorstartupdialog.cpp
@@ -86,7 +86,7 @@ void SimulatorStartupDialog::changeEvent(QEvent *e)
// FIXME : need a better way to check for this
bool SimulatorStartupDialog::usesCategorizedStorage(const QString & name)
{
- return name.contains(QRegExp("(x12|x10|horus|t16)", Qt::CaseInsensitive));
+ return name.contains(QRegExp("(x12|x10|horus|16|18)", Qt::CaseInsensitive));
}
bool SimulatorStartupDialog::usesCategorizedStorage()
diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp
index c96cd480e..f70813442 100644
--- a/companion/src/simulation/simulatorwidget.cpp
+++ b/companion/src/simulation/simulatorwidget.cpp
@@ -64,6 +64,7 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato
radioUiWidget = new SimulatedUIWidgetX9LITE(simulator, this);
break;
case Board::BOARD_TARANIS_X7:
+ case Board::BOARD_TARANIS_X7_ACCESS:
radioUiWidget = new SimulatedUIWidgetX7(simulator, this);
break;
case Board::BOARD_TARANIS_X9D:
@@ -93,6 +94,12 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato
case Board::BOARD_JUMPER_T16:
radioUiWidget = new SimulatedUIWidgetJumperT16(simulator, this);
break;
+ case Board::BOARD_JUMPER_T18:
+ radioUiWidget = new SimulatedUIWidgetJumperT18(simulator, this);
+ break;
+ case Board::BOARD_RADIOMASTER_TX16S:
+ radioUiWidget = new SimulatedUIWidgetTX16S(simulator, this);
+ break;
default:
radioUiWidget = new SimulatedUIWidget9X(simulator, this);
break;
@@ -269,7 +276,7 @@ bool SimulatorWidget::setRadioData(RadioData * radioData)
saveTempRadioData = (flags & SIMULATOR_FLAGS_STANDALONE);
- if (IS_HORUS(m_board))
+ if (IS_FAMILY_HORUS_OR_T16(m_board))
ret = useTempDataPath(true);
if (ret) {
@@ -695,9 +702,11 @@ void SimulatorWidget::restoreRadioWidgetsState()
void SimulatorWidget::saveRadioWidgetsState(QList & state)
{
if (m_radioWidgets.size()) {
- state.clear();
- foreach (RadioWidget * rw, m_radioWidgets)
- state.append(rw->getStateData());
+ if (g.simuSW()) {
+ state.clear();
+ foreach (RadioWidget * rw, m_radioWidgets)
+ state.append(rw->getStateData());
+ }
}
}
diff --git a/companion/src/storage/appdata.h b/companion/src/storage/appdata.h
index 3ffa7d688..a17b9c1ce 100644
--- a/companion/src/storage/appdata.h
+++ b/companion/src/storage/appdata.h
@@ -575,6 +575,7 @@ class AppData: public CompStoreObj
PROPERTY4(bool, snapToClpbrd, "snapshot_to_clipboard", false)
PROPERTY4(bool, autoCheckApp, "startup_check_companion", true)
PROPERTY4(bool, autoCheckFw, "startup_check_fw", true)
+ PROPERTY4(bool, promptProfile, "startup_prompt_profile", false)
PROPERTY(bool, enableBackup, false)
PROPERTY(bool, backupOnFlash, true)
diff --git a/companion/src/storage/categorized.cpp b/companion/src/storage/categorized.cpp
index 9ca248cc4..d659ae81f 100644
--- a/companion/src/storage/categorized.cpp
+++ b/companion/src/storage/categorized.cpp
@@ -93,7 +93,7 @@ bool CategorizedStorageFormat::load(RadioData & radioData)
return false;
}
strncpy(radioData.models[modelIndex].filename, qPrintable(fileName), sizeof(radioData.models[modelIndex].filename));
- if (IS_HORUS(board) && !strcmp(radioData.generalSettings.currModelFilename, qPrintable(fileName))) {
+ if (IS_FAMILY_HORUS_OR_T16(board) && !strcmp(radioData.generalSettings.currModelFilename, qPrintable(fileName))) {
radioData.generalSettings.currModelIndex = modelIndex;
qDebug() << "currModelIndex =" << modelIndex;
}
diff --git a/companion/src/storage/firmwareinterface.cpp b/companion/src/storage/firmwareinterface.cpp
index 369af6504..a07ebbd67 100644
--- a/companion/src/storage/firmwareinterface.cpp
+++ b/companion/src/storage/firmwareinterface.cpp
@@ -36,7 +36,6 @@
FirmwareInterface::FirmwareInterface(const QString & filename):
flash(FSIZE_MAX, 0),
flashSize(0),
- versionId(0),
eepromVersion(0),
eepromVariant(0),
splashOffset(0),
@@ -65,7 +64,7 @@ FirmwareInterface::FirmwareInterface(const QString & filename):
// old version format
int index = version.lastIndexOf('-');
flavour = version.mid(0, index);
- version = version.mid(index+1);
+ version = version.mid(index + 1);
}
date = seekLabel(DATE_MARK);
time = seekLabel(TIME_MARK);
@@ -80,7 +79,6 @@ FirmwareInterface::FirmwareInterface(const QString & filename):
eepromVersion = eepromId.toInt();
}
- versionId = version2index(version);
seekSplash();
isValidFlag = !version.isEmpty();
}
diff --git a/companion/src/storage/firmwareinterface.h b/companion/src/storage/firmwareinterface.h
index ce9aa994a..d6dee286b 100644
--- a/companion/src/storage/firmwareinterface.h
+++ b/companion/src/storage/firmwareinterface.h
@@ -39,14 +39,13 @@
class FirmwareInterface
{
public:
- FirmwareInterface(const QString &filename);
+ FirmwareInterface(const QString & filename);
inline QString getDate() { return date; }
inline QString getTime() { return time; }
int getSize() { return flashSize; }
QString getFlavour() const;
bool isHardwareCompatible(const FirmwareInterface &previousFirmware) const;
inline QString getVersion() { return version; }
- unsigned int getVersionId() { return versionId; }
inline int getEEpromVersion() { return eepromVersion; }
inline int getEEpromVariant() { return eepromVariant; }
inline QString getEEpromId() { return eepromId; }
@@ -72,7 +71,6 @@ class FirmwareInterface
QString time;
QString flavour;
QString version;
- int versionId;
QString eepromId;
int eepromVersion;
int eepromVariant;
diff --git a/companion/src/storage/rlefile.cpp b/companion/src/storage/rlefile.cpp
index b4d9da611..4d38adac9 100644
--- a/companion/src/storage/rlefile.cpp
+++ b/companion/src/storage/rlefile.cpp
@@ -64,7 +64,7 @@ void RleFile::EeFsCreate(uint8_t *eeprom, int size, Board::Type board, unsigned
}
}
}
- else if (IS_TARANIS(board)) {
+ else {
eeFsArm = (EeFsArm *)eeprom;
eeFsVersion = 5;
eeFsSize = 8+4*62;
@@ -84,36 +84,6 @@ void RleFile::EeFsCreate(uint8_t *eeprom, int size, Board::Type board, unsigned
eeFsArm->freeList = eeFsFirstBlock;
// EeFsFlush();
}
- else {
- eeFs = (EeFs *)eeprom;
- eeFsVersion = (IS_2560(board) || board==Board::BOARD_9X_M128) ? 5 : 4;
- eeFsBlockSize = 16;
- eeFsLinkSize = 1;
-
- if (eeFsVersion == 5) {
- eeFsSize = 4+3*36;
- eeFsFirstBlock = 1;
- eeFsBlocksOffset = 112 - 16;
- eeFsBlocksMax = 1 + (4096-112)/16;
- }
- else {
- eeFsSize = 4+3*20;
- eeFsFirstBlock = 4;
- eeFsBlocksOffset = 0;
- eeFsBlocksMax = 2048/16;
- }
-
- memset(eeprom, 0, size);
- eeFs->version = eeFsVersion;
- eeFs->mySize = eeFsSize;
- eeFs->freeList = 0;
- eeFs->bs = eeFsBlockSize;
- for (unsigned int i=eeFsFirstBlock; ifreeList = eeFsFirstBlock;
- // EeFsFlush();
- }
}
PACK(struct EepromFileHeader
@@ -146,7 +116,7 @@ bool RleFile::EeFsOpen(uint8_t *eeprom, int size, Board::Type board)
searchFat();
return 1;
}
- else if (IS_TARANIS(board)) {
+ else {
eeFsArm = (EeFsArm *)eeprom;
eeFsVersion = eeFsArm->version;
eeFsSize = 8+4*62;
@@ -157,29 +127,6 @@ bool RleFile::EeFsOpen(uint8_t *eeprom, int size, Board::Type board)
eeFsBlocksMax = 1 + (Boards::getEEpromSize(board)-eeFsSize) / eeFsBlockSize;
return eeFsArm->mySize == eeFsSize;
}
- else {
- eeFs = (EeFs *)eeprom;
- eeFsVersion = eeFs->version;
- eeFsBlockSize = 16;
- eeFsLinkSize = 1;
- if (eeFsVersion == 5) {
- eeFsSize = 4+3*36;
- eeFsFirstBlock = 1;
- eeFsBlocksOffset = 112 - 16;
- eeFsBlocksMax = 1 + (4096-112)/16;
- }
- else if (eeFsVersion == 4) {
- eeFsSize = 4+3*20;
- eeFsFirstBlock = 4;
- eeFsBlocksOffset = 0;
- eeFsBlocksMax = 2048/16;
- }
- else {
- return 0;
- }
-
- return eeFs->mySize == eeFsSize;
- }
}
void RleFile::eeprom_read_block (void *pointer_ram, unsigned int pointer_eeprom, size_t size)
@@ -206,25 +153,16 @@ void RleFile::EeFsWrite(unsigned int blk, unsigned int ofs, uint8_t val)
unsigned int RleFile::EeFsGetLink(unsigned int blk)
{
- if (IS_ARM(board)) {
- int16_t ret;
- eeprom_read_block((uint8_t *)&ret, blk*eeFsBlockSize+eeFsBlocksOffset, eeFsLinkSize);
- return ret;
- }
- else {
- return EeFsRead(blk, 0);
- }
+ int16_t ret;
+ eeprom_read_block((uint8_t *)&ret, blk*eeFsBlockSize+eeFsBlocksOffset, eeFsLinkSize);
+ return ret;
}
void RleFile::EeFsSetLink(unsigned int blk, unsigned int val)
{
- if (IS_ARM(board)) {
- int16_t s_link = val;
- eeprom_write_block((uint8_t *)&s_link, (blk*eeFsBlockSize)+eeFsBlocksOffset, eeFsLinkSize);
- }
- else {
- EeFsWrite(blk, 0, val);
- }
+ int16_t s_link = val;
+ eeprom_write_block((uint8_t *)&s_link, (blk*eeFsBlockSize)+eeFsBlocksOffset, eeFsLinkSize);
+
}
uint8_t RleFile::EeFsGetDat(unsigned int blk, unsigned int ofs)
@@ -239,15 +177,12 @@ void RleFile::EeFsSetDat(unsigned int blk, unsigned int ofs, const uint8_t *buf,
unsigned int RleFile::EeFsGetFree()
{
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 0;
unsigned int ret = 0;
unsigned int i;
- if (IS_ARM(board))
- i = eeFsArm->freeList;
- else
- i = eeFs->freeList;
+ i = eeFsArm->freeList;
while (i) {
ret += eeFsBlockSize-eeFsLinkSize;
@@ -261,19 +196,13 @@ unsigned int RleFile::EeFsGetFree()
*/
void RleFile::EeFsFree(unsigned int blk)
{
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return;
unsigned int i = blk;
while (EeFsGetLink(i)) i = EeFsGetLink(i);
- if (IS_ARM(board)) {
- EeFsSetLink(i, eeFsArm->freeList);
- eeFsArm->freeList = blk; //chain in front
- }
- else {
- EeFsSetLink(i, eeFs->freeList);
- eeFs->freeList = blk; //chain in front
- }
+ EeFsSetLink(i, eeFsArm->freeList);
+ eeFsArm->freeList = blk; //chain in front
}
/*
@@ -281,14 +210,11 @@ void RleFile::EeFsFree(unsigned int blk)
*/
unsigned int RleFile::EeFsAlloc()
{
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 0;
- unsigned int ret = (IS_ARM(board) ? eeFsArm->freeList : eeFs->freeList);
+ unsigned int ret = eeFsArm->freeList;
if (ret) {
- if (IS_ARM(board))
- eeFsArm->freeList = EeFsGetLink(ret);
- else
- eeFs->freeList = EeFsGetLink(ret);
+ eeFsArm->freeList = EeFsGetLink(ret);
EeFsSetLink(ret, 0);
}
return ret;
@@ -296,15 +222,15 @@ unsigned int RleFile::EeFsAlloc()
unsigned int RleFile::size(unsigned int id)
{
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 0;
else
- return IS_ARM(board) ? eeFsArm->files[id].size : eeFs->files[id].size;
+ return eeFsArm->files[id].size;
}
unsigned int RleFile::openRd(unsigned int i_fileId)
{
- if (IS_HORUS(board)) {
+ if (IS_FAMILY_HORUS_OR_T16(board)) {
return 1;
}
else if (IS_SKY9X(board)) {
@@ -327,31 +253,28 @@ unsigned int RleFile::openRd(unsigned int i_fileId)
else {
m_fileId = i_fileId;
m_pos = 0;
- m_currBlk = (IS_ARM(board) ? eeFsArm->files[m_fileId].startBlk : eeFs->files[m_fileId].startBlk);
+ m_currBlk = eeFsArm->files[m_fileId].startBlk;
m_ofs = 0;
m_zeroes = 0;
m_bRlc = 0;
m_err = ERR_NONE; //error reasons
- if (IS_ARM(board))
- return eeFsArm->files[m_fileId].typ;
- else
- return eeFs->files[m_fileId].typ;
+ return eeFsArm->files[m_fileId].typ;
}
}
unsigned int RleFile::read(uint8_t *buf, unsigned int i_len)
{
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 0;
- unsigned int len = IS_ARM(board) ? eeFsArm->files[m_fileId].size : eeFs->files[m_fileId].size;
+ unsigned int len = eeFsArm->files[m_fileId].size;
len -= m_pos;
if (i_len > len) i_len = len;
len = i_len;
while(len) {
if (!m_currBlk) break;
*buf++ = EeFsGetDat(m_currBlk, m_ofs++);
- if (m_ofs >= (eeFsBlockSize-(IS_ARM(board)? 2 : 1))) {
+ if (m_ofs >= (eeFsBlockSize - 2)) {
m_ofs = 0;
m_currBlk = EeFsGetLink(m_currBlk);
}
@@ -364,7 +287,7 @@ unsigned int RleFile::read(uint8_t *buf, unsigned int i_len)
// G: Read runlength (RLE) compressed bytes into buf.
unsigned int RleFile::readRlc12(uint8_t *buf, unsigned int i_len, bool rlc2)
{
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 0;
memset(buf, 0, i_len);
@@ -492,10 +415,7 @@ unsigned int RleFile::write(const uint8_t *buf, unsigned int i_len)
unsigned int len = i_len;
if (!m_currBlk && m_pos==0)
{
- if (IS_ARM(board))
- eeFsArm->files[m_fileId].startBlk = m_currBlk = EeFsAlloc();
- else
- eeFs->files[m_fileId].startBlk = m_currBlk = EeFsAlloc();
+ eeFsArm->files[m_fileId].startBlk = m_currBlk = EeFsAlloc();
}
while (len)
{
@@ -527,30 +447,22 @@ unsigned int RleFile::write(const uint8_t *buf, unsigned int i_len)
void RleFile::create(unsigned int i_fileId, unsigned int typ)
{
openRd(i_fileId); //internal use
- if (IS_ARM(board)) {
- eeFsArm->files[i_fileId].typ = typ;
- eeFsArm->files[i_fileId].size = 0;
- }
- else {
- eeFs->files[i_fileId].typ = typ;
- eeFs->files[i_fileId].size = 0;
- }
+ eeFsArm->files[i_fileId].typ = typ;
+ eeFsArm->files[i_fileId].size = 0;
+
}
void RleFile::closeTrunc()
{
unsigned int fri=0;
- if (IS_ARM(board))
- eeFsArm->files[m_fileId].size = m_pos;
- else
- eeFs->files[m_fileId].size = m_pos;
+ eeFsArm->files[m_fileId].size = m_pos;
if (m_currBlk && ( fri = EeFsGetLink(m_currBlk))) EeFsSetLink(m_currBlk, 0);
if(fri) EeFsFree( fri ); //chain in
}
unsigned int RleFile::writeRlc1(unsigned int i_fileId, unsigned int typ, const uint8_t *buf, unsigned int i_len)
{
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 0;
create(i_fileId, typ);
@@ -599,7 +511,7 @@ unsigned int RleFile::writeRlc1(unsigned int i_fileId, unsigned int typ, const u
*/
unsigned int RleFile::writeRlc2(unsigned int i_fileId, unsigned int typ, const uint8_t *buf, unsigned int i_len)
{
- if (IS_HORUS(board))
+ if (IS_FAMILY_HORUS_OR_T16(board))
return 0;
if (IS_SKY9X(board)) {
diff --git a/companion/src/translations.cpp b/companion/src/translations.cpp
index 03172dac8..76d63b425 100644
--- a/companion/src/translations.cpp
+++ b/companion/src/translations.cpp
@@ -45,7 +45,7 @@ QStringList const Translations::getAvailableTranslations()
//<< "nl_NL"
<< "pl_PL"
//<< "pt_PT"
- //<< "ru_RU"
+ << "ru_RU"
<< "sv_SE"
<< "zh_CN"
<< "ja_JP" ;
diff --git a/companion/src/translations/companion_es.ts b/companion/src/translations/companion_es.ts
index 7e1cf51d6..bdd44458d 100644
--- a/companion/src/translations/companion_es.ts
+++ b/companion/src/translations/companion_es.ts
@@ -11,22 +11,22 @@
Yes, controlled by a single channel
- Si, controlado por un único canal
+ Sí, controlado por un único canal
Yes, controlled by two channels
- Si, controlado por dos canales
+ Sí, controlado por dos canales
<br>First Aileron Channel:
- <br>Canal Primer Alerón:
+ <br>Canal primer alerón:
Second Aileron Channel:
- Canal Segundo Alerón:
+ Canal segundo alerón:
@@ -39,22 +39,22 @@
Yes, controlled by a single channel
- Si, controlado por un único canal
+ Sí, controlado por un único canal
Yes, controlled by two channels
- Si, controlado por dos canales
+ Sí, controlado por dos canales
<br>First Airbrake Channel:
- <br>Primer Canal Aerofreno:
+ <br>Primer canal aerofreno:
Second Airbrake Channel:
- Segundo Canal Aerofreno:
+ Segundo canal aerofreno:
@@ -63,22 +63,23 @@
Application Settings have been saved to
%1
-
+ Los ajustes de la aplicación han sido grabados a
+.%1
Could not save Application Settings to file "%1"
-
+ No se han podido grabar los ajustes de la aplicación en el archivo "%1"
because the file could not be saved (check access permissions).
-
+ porque el archivo no se ha podido grabar (revisa los permisos).
for unknown reasons.
-
+ por causas desconocidas.
@@ -86,48 +87,64 @@
Show this message again at next startup?
-
+ ¿Mostrar este mensaje de nuevo en el siguiente inicio?
AppPreferencesDialog
+
+
Edit Settings
- Editar Ajustes
+ Editar ajustes
+
+
Radio Profile
- Perfil de Radio
+ Perfil de radio
-
+
+
+
Default Channel Order
- Orden Prederterminado Canales
+ Orden prederterminado canales
-
+
+
+
Build Options
- Opciones Firmware
+ Opciones del firmware
-
+
+
+
Menu Language
- Lenguaje Menú
+ Lenguaje de los menús
-
+
+
+
Default Stick Mode
- Modo Prederterminado Sticks
+ Modo prederterminado sticks
-
+
+
+
Select Image
- Seleccionar Imagen
+ Seleccionar imagen
-
+
+
+
Mode selection:
Mode 1:
@@ -147,508 +164,712 @@ Mode 4:
Right stick: Elevator, Rudder
- Selección de Modo:
+ Selección de modo:
Modo 1:
- Stick Izquierdo: Elevador, Timón
- Stick Derecho: Acelerador, Alerón
+ Stick izquierdo: Elevador, Timón
+ Stick derecho: Acelerador, Alerón
Modo 2:
- Stick Izquierdo: Acelerador, Timón
- Stick Derecho: Elevador, Alerón
+ Stick izquierdo: Acelerador, Timón
+ Stick derecho: Elevador, Alerón
Modo 3:
- Stick Izquierdo: Elevador, Alerón
- Stick Derecho: Acelerador, Timón
+ Stick izquierdo: Elevador, Alerón
+ Stick derecho: Acelerador, Timón
Modo 4:
- Stick Izquierdo: Acelerador, Alerón
- Stick Derecho: Elevador, Timón
+ Stick izquierdo: Acelerador, Alerón
+ Stick derecho: Elevador, Timón
-
+
+
+
Mode 1 (RUD ELE THR AIL)
Modo 1 (RUD ELE THR AIL)
-
+
+
+
Mode 2 (RUD THR ELE AIL)
- Modo 2 (RUD THR ELE AIL)
+ Modo 2 (RUD THR ELE AIL)
-
+
+
+
Mode 3 (AIL ELE THR RUD)
Modo 3 (AIL ELE THR RUD)
-
+
+
+
Mode 4 (AIL THR ELE RUD)
Modo 4 (AIL THR ELE RUD)
-
+
+
+
Splash Screen
- Pantalla de Inicio
+ Pantalla de inicio
-
-
+
+
+
+
+
+
The profile specific folder, if set, will override general Backup folder
-
+ La carpeta específica del perfil, si está fijada, anulará la carpeta de copia de seguridad general
-
+
+
+
Backup folder
-
+ Carpeta de copia de seguridad
-
+
+
+
If set it will override the application general setting
-
+ Si está fijado anulará los ajustes generales de la aplicación>
-
+
+
+
if set, will override general backup enable
-
+ si está fijado anulará la copia de seguridad general>
-
+
+
+
<html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html>
<html><head/><body><p>Orden de los canales</p><p><br/></p><p>Define el orden por defecto de las mezclas en un nuevo modelo</p></body></html>
-
+
+
+
R E T A
- R E T A
+
-
+
+
+
R E A T
- R E A T
+
-
+
+
+
R T E A
- R T E A
+
-
+
+
+
R T A E
- R T A E
+
-
+
+
+
R A E T
- R A E T
+
-
+
+
+
R A T E
- R A T E
+
-
+
+
+
E R T A
- E R T A
+
-
+
+
+
E R A T
- E R A T
+
-
+
+
+
E T R A
- E T R A
+
-
+
+
+
E T A R
- E T A R
+
-
+
+
+
E A R T
- E A R T
+
-
+
+
+
E A T R
- E A T R
+
-
+
+
+
T R E A
- T R E A
+
-
+
+
+
T R A E
- T R A E
+
-
+
+
+
T E R A
- T E R A
+
-
+
+
+
T E A R
- T E A R
+
-
+
+
+
T A R E
- T A R E
+
-
+
+
+
T A E R
- T A E R
+
-
+
+
+
A R E T
- A R E T
+
-
+
+
+
A R T E
- A R T E
+
-
+
+
+
A E R T
- A E R T
+
-
+
+
+
A E T R
- A E T R
+
-
+
+
+
A T R E
- A T R E
+
-
+
+
+
A T E R
- A T E R
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Select Folder
-
+ Selecciona carpeta
-
+
+
+
Select Executable
-
+ Selecciona ejecutable
-
+
+
+
Release channel
-
+ Canal de distribución
-
+
+
+
Releases (stable)
-
+ Releases (estable)
-
+
+
+
Release candidates (testing)
-
+ Release candidates (testing)
-
+
+
+
Nightly builds (unstable)
-
+ Nightly builds (inestable)
-
+
+
+
Simulator Volume Gain
-
+ Ganancia de volumen del simulador
-
+
+
+
+ Simulator controls
+ Controles de simulador
+
+
+
+
+
+ Save switch/pot positions on simulator exit
+ Guardar las posiciones de interruptores/pots al salir del simulador
+
+
+
+
+
+ Clear saved positions
+ Limpiar las posiciones guardadas
+
+
+
+
+
Profile Name
- Nombre de Perfil
+ Nombre de perfil
-
+
+
+
Clear Image
- Limpiar Imagen
+ Limpiar imagen
-
+
+
+
Append version number to FW file name
- Agregar el número de version al nombre de archivo de Firmware
+ Agregar el número de versión al nombre de archivo de firmware
-
+
+
+
Offer to write FW to Tx after download
Ofrecer grabar el firmware al Tx después de la descarga
-
+
+
+
Radio Type
- Tipo de Radio
+ Tipo de radio
-
+
+
+
Other Settings
- Otros Ajustes
+ Otros ajustes
-
+
+
+
General Settings
- Ajustes Generales
+ Ajustes generales
-
+
+
+
SD Structure path
Estructura de archivos SD
-
+
+
+
Application Settings
- Ajustes Aplicación
+ Ajustes de la aplicación
-
+
+
+
Show splash screen when Companion starts
- Mostrar pantalla de inicion cuando Companion comience
+ Mostrar pantalla de inicio cuando Companion comience
-
+
+
+
Automatic check for Companion updates
Comprobar automáticamente actualizaciones de Companion
-
-
+
+
+
+
+
+
Enable automatic backup before writing firmware
Activar copia de seguridad automática antes de escribir el firmware
-
+
+
+
Automatic check for OpenTX firmware updates
- Comprobar auromaticamente actualizaciones del firmware OpenTX
+ Comprobar automáticamente actualizaciones del firmware OpenTX
-
+
+
+
Splash Screen Library
- Libreria de pantallas de inicio
+ Librería de pantallas de inicio
-
+
+
+
Google Earth Executable
Ejecutable Google Earth
-
+
+
+
Only show user splash images
- Mostrar solo pantallas de inicio del usuario
+ Mostrar sólo pantallas de inicio de usuario
-
+
+
+
Show user and companion splash images
- Mostrar pantallas de inicio del usuario y companion
+ Mostrar pantallas de inicio de usuario y companion
-
+
+
+
User Splash Screens
- Pantallas de Inicio del Usuario
+ Pantallas de inicio de usuario
-
+
+
+
Automatic Backup Folder
- Carpeta copia de seguridad Automática
+ Carpeta copia de seguridad automática
-
+
+
+
Simulator Settings
- Ajustes Simulador
+ Ajustes del simulador
-
+
+
+
Simulator BackLight
Luz de fondo del simulador
-
+
+
+
Enable
Activado
-
+
+
+
most recently used files
-
+ ficheros usados recientemente
-
+
+
+
Startup Settings
-
+ Ajustes de inicio
-
+
+
+
Remember
-
+ Recordar
-
+
+
+
Output Logs Folder
-
+ Carpeta de reportes
-
+
+
+
<html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html>
-
+ <html><head/><body><p>Esta opción mantiene el comportamiento de las versiones anteriores de OpenTx donde se conservan los slots de modelos vacíos cuando se elimina o mueve un modelo. </p><p>Cuando esta opción no está seleccionada, los otros modelos pueden reordenarse para llenar el hueco dejado por el modelo borrado.</p></body></html>
-
+
+
+
Remove empty model slots when deleting models (only applies for radios w/out categories)
-
+ Eliminar los slots vacíos cuando se borran modelos (sólo aplica a radios sin categorías)
-
+
+
+
Use model wizard
-
+ Usar el asistente de modelos
-
+
+
+
Open model editor
-
+ Abrir el editor de modelos
-
+
+
+
Just create the model
-
+ Sólo crear el modelo
-
+
+
+
Debug Output Logging
-
+ Reporte de depuración
-
+
+
+
<html><head/><body><p>Keep a log of all debugging messages generated by the desktop Companion/Simulator applications. An OpenTX developer may request this to help diagnose an issue.</p></body></html>
-
+ <html><head/><body><p>Mantiene un reporte para todos los mensajes de depuración generados por las aplicaciones Companion/Simulador. Un desarrollador de OpenTX los puede requerir para ayudar a diagnosticar el problema.</p></body></html>
-
+
+
+
Application (Companion/Simulator)
-
+ Aplicación (Companion/simulador)
-
+
+
+
<html><head/><body><p>Keep a log of all messages generated by the radio firmware when running in Simulator. This is the same information one would also see in the Simulator <span style=" font-style:italic;">Debug Output</span> window.</p></body></html>
-
+ <html><head/><body><p>Mantiene un log para todos los mensajes generados por el firmware de la radio mientras se ejecuta en el simulador. Esta es la misma información que se vería en el simulador <span style=" font-style:italic;">Salida de depuración</span> ventana.</p></body></html>
-
+
+
+
Radio Firmware (in Simulator)
-
+ Radio firmware (en simulador)
-
+
+
+
Action on New Model
-
+ Accioń en nuevo modelo
-
+
+
+
Blue
Azul
-
+
+
+
Green
Verde
-
+
+
+
Red
Rojo
-
+
+
+
Orange
Naranja
-
+
+
+
Yellow
Amarillo
-
+
+
+
Screenshot capture folder
-
+ Carpeta de capturas de pantalla
-
+
+
+
Joystick
Joystick
-
+
+
+
Calibrate
Calibrar
-
+
+
+
Only capture to clipboard
- Solo capturar a portapapeles
-
-
-
- Remember simulator switch values
- Recordar los valores de los switch en el simulador
+ Sólo capturar al portapapeles
My Radio
- Mi Radio
+ Mi radio
<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>
-
+ <p><b>No puedes cambiar el tipo de radio o las opciones del firmware mientras hay cambios sin guardar ¿Qué quieres hacer?</b></p> <ul><li><i>Guardar todo</i> - Guardar los archivos abiertos andtes de guardar los ajustes.<li><li><i>Resetear</i> - Volver al tipo de radio y opciones de firmware anteriores antes de salvar los los ajustes.</li><li><i>Cancelar</i> - Volver a la ventana de edición de ajustes.</li></ul>
Select your snapshot folder
- Selecciona tu carpeta de capturas
+ Selecciona la carpeta de capturas
Note: Nightly builds are not available in this version, Release/RC update channel will be used.
-
+ Nota: No hay nightly builds para esta versión, se usará el canal Release/RC.
-
+
No joysticks found
- No se han encopntrado joysticks
+ No se han encontrado joysticks
EMPTY: No radio settings stored in profile
- VACIO: No se han guardado ajustes en el perfil de tu radio
+ VACÍO: No se han guardado ajustes en el perfil de tu radio
AVAILABLE: Radio settings of unknown age
- DISPONIBLE:Ajustes de radio de tiempo desconocido
+ DISPONIBLE:Ajustes de radio de antigüedad desconocida
@@ -658,7 +879,7 @@ Modo 4:
Select your library folder
- Selecciona tu carpeta de una carpeta
+ Selecciona tu carpeta de librerías
@@ -669,7 +890,7 @@ Modo 4:
Select a folder for application logs
-
+ Selecciona una carpeta para los reportes de la aplicación
@@ -677,19 +898,19 @@ Modo 4:
Selecciona el ejecutable de Google Earth
-
+
Select the folder replicating your SD structure
- Selecciona la carpeta que replica la structura de tu tarjeta SD
+ Selecciona la carpeta que replica la estructura de tu tarjeta SD
-
+
Open Image to load
- Abrir imagen para cargar
+ Abre imagen para cargar
-
+
Images (%1)
- Imagenes (%1)
+ Imágenes (%1)
@@ -697,89 +918,90 @@ Modo 4:
Error reading %1: %2
-
+ Error leyendo %1: %2
Cannot save EEPROM
-
+ No se puede guardar la EEPROM
Cannot open file %1:
%2.
-
+ No se puede abrir el archivo %1:
+%2.
Error writing file %1:
%2.
- Error escribiendo el archivo %1:
+ Error escribiendo el archivo %1:
%2.
Invalid binary EEPROM file %1
-
+ Archivo binario de la EEPROM no válido %1
Boards
-
+
Left Horizontal
- Izquierda Hrizontal
+ Izquierda horizontal
-
+
Left Vertical
- Izquierda Vertical
+ Izquierda vertical
-
+
Right Vertical
- Derecha Vertical
-
-
-
- Right Horizontal
- Derecha Horizontal
-
-
-
- Aux. 1
-
-
-
-
- Aux. 2
-
-
-
-
-
- Unknown
- Desconocido
+ Derecha vertical
- Rud
- Rud
+ Right Horizontal
+ Derecha horizontal
- Ele
- Ele
+ Aux. 1
+
- Thr
- Thr
+ Aux. 2
+
-
+
+
+ Unknown
+ Desconocido
+
+
+
+ Rud
+
+
+
+
+ Ele
+
+
+
+
+ Thr
+
+
+
+
Ail
- Ail
+
@@ -787,17 +1009,17 @@ Modo 4:
Negative span
- Amplitud negativa
+ Amp. negativa
Mid value
- Valor medio
+ Valor medio
Positive span
- Amplitud positiva
+ Amp. positiva
@@ -805,153 +1027,192 @@ Modo 4:
Can't extract RADIO/radio.bin
-
+ No se puede extraer RADIO/radio.bin
Can't extract RADIO/models.txt
-
+ No se puede extraer RADIO/models.txt
Can't extract %1
-
+ No se puede extraer %1
Error loading models
-
+ Error cargando modelos
Channels
-
+
Name
Nombre
-
+
Min
- Min
+ Mín
-
+
Max
- Max
+ Máx
-
+
Subtrim
- Subtrim
+
-
+
Direction
Dirección
-
+
Curve
Curva
-
+
PPM Center
Centro PPM
-
+
Linear Subtrim
Subtrim lineal
-
+
CH%1
-
+
-
+
Popup menu available
-
+ Menú emergente disponible
-
+
---
- ---
+
-
+
INV
- INV
+
-
- &Copy
- &Copiar
+
+ Copy
+ Copiar
-
- &Cut
- C&ortar
+
+ Cut
+ Cortar
-
- &Paste
- &Pegar
+
+ Paste
+ Pegar
-
- &Delete
- &Borrar
+
+ Clear
+ Limpiar
+
+
+
+ Insert
+ Insertar
+
+
+
+ Delete
+ Borrar
+
+
+
+ Move Up
+ Mover arriba
+
+
+
+ Move Down
+ Mover abajo
+
+
+
+ Clear All
+ Limpiar todo
ChecklistDialog
+
+
Edit Checklist
-
+ Editar lista de verificación
+
+
Line nn, Col nn
-
+ Línea nn, Col nn
+
+
&Import...
-
+ &Importar...
+
+
&Cancel
-
+ &Cancelar
+
+
&OK
-
+
+
+
Please note, the maximum width displayable is radio model limited. Also, renaming the model will break the link to this checklist file.
-
+ Ten en cuenta que el máximo ancho del display está limitado por el modelo de la radio. También renombrar el modelo rompe el link a este archivo de verificación.
+
+
File: unknown
-
+ Archivo: desconocido
Open Checklist
-
+ Abrir lista de verificación
Checklist Files (*.txt)
-
+ Ficheros de verificación (*.txt)
@@ -960,43 +1221,47 @@ Modo 4:
Model Checklist
-
+ Lista de verificación del modelo
Cannot open file for writing %1:
%2.
-
+ No se puede abrir el archivo para escritura %1:
+%2.
Cannot write to file %1:
%2.
-
+ No se puede escribir en el archivo %1:
+%2.
Cannot write file %1:
%2.
- No se puede escribir el archivo %1:
+ No se puede escribir el archivo %1:
%2.
Cannot open file %1:
%2.
-
+ No se puede abrir el archivo %1:
+%2.
Cannot read file %1:
%2.
-
+ No se puede leer el archivo %1:
+%2.
Line %1, Col %2
-
+ Línea %1, Col %2
@@ -1004,118 +1269,119 @@ Modo 4:
OpenTX Companion
-
+
Information
- Información
+ Información
Warning
- Aviso
+ Aviso
Error
- Error
+ Error
Application Settings
- Ajustes Aplicación
+ Ajustes aplicación
files
-
+ archivos
Radio and Models settings
-
+ Ajustes de radio y modelos
-
+
Select or create a file for exported Settings:
-
+ Selecciona o crea un archivo para exportar los ajustes:
-
+
Press the 'Retry' button to choose another file.
-
+ Presiona el botón de 'Reintentar' para elegir otro archivo.
-
+
Simulator for this firmware is not yet available
- El simulador para este firmware ya no está disponible
+ El simulador para este firmware aún no está disponible
-
+
Uknown error during Simulator startup.
-
+ Error durante el arranque del simulador.
-
+
Simulator Error
-
+ Error del simulador
-
+
Data Load Error
-
+ Error de carga de datos
-
+
Error occurred while starting simulator.
-
+ Ha ocurrido un error al arrancar el simulador.
<p><b>Welcome to OpenTX %1.</b></p><p>As the first step, please configure the initial Radio Profile by selecting your Radio Type, Menu Language, and Build Options.</p><p>You may also want to take this time to review the other available options in the displayed Settings dialog.</p><p>After saving your settings, we recommend you download the latest firmware for your radio by using the <i>File -> Download</i> menu option.</p><p>Please visit <a href='http://www.open-tx.org'>open-tx.org</a> for latest news, updates and documentation. Thank you for choosing OpenTX!</p>- The OpenTX Team.
-
+ <p><b>Bienvenido a OpenTX %1.</b></p><p>Como primer paso, por favor configura el perfil de radio inicial seleccionando el tipo de radio, el lenguaje y las opciones de firmware.</p><p>También puedes tomarte un tiempo para revisar las otras opciones disponibles en el cuadro de diálogo Ajustes que se muestra.</p><p>Después de guardar la configuración, te recomendamos que descargues el firmware más reciente para tu radio utilizando la opción de menú <i>Archivo -> Descargar</i>.</p><p>Por favor visita <a href='http://www.open-tx.org'>open-tx.org</a> para últims noticies y documentación. Gracias pr elegir OpenTX!</p>- El equipo de OpenTX.
<p><b>Thank you for upgrading to OpenTX %1.</b></p><p>This is a major upgrade that adds and modifies a lot of things, so please make sure that you read release notes carefully to learn about the changes, and thoroughly check each of your models for proper function.</p><p>Please visit <a href='http://www.open-tx.org'>open-tx.org</a> for release notes and other documentation.</p>- The OpenTX Team.
-
+ <p><b>Gracias por actualizar a OpenTX %1.</b></p><p>Esta es una actualización mayor que añade y modifica muchas cosas, por favor asegúrate que lees cuidadosamente las notas de la version para entender los cambios y verificar que cada uno de tus modelos funciona correctamente.</p><p>Por favor visita <a href='http://www.open-tx.org'>open-tx.org</a> para las notas de la versión y otra documentación.</p>- El equipo de OpenTX.
<p>The radio type in the selected profile does not exist. Using the default type instead.</p> <p><b>Please update your profile settings!</b></p>
-
+ <p>El tipo de radio en el perfil seleccionado no existe. Usando en su lugar el tipo predeterminado.</p> <p><b>¡Por favor, actualiza los ajustes del perfil!</b></p>
The saved settings could not be imported, please try again or continue with current settings.
-
+ Los ajustes guardados no pudieron ser importafos, por favor inténtalo de nuevo con los ajustes actuales.
Import from File
-
+ Importar desde archivo
Import from v%1
-
+ Importar desde v%1
Do not import
-
+ No importar
We have found possible Companion settings backup file(s).
Do you want to import settings from a file?
-
+ Se ha encontrado archivo(s) de ajustes de Companion
+¿Quieres importar los ajustes desde un archivo?
Import settings from a file, or start with current values.
-
+ Importar ajustes desde un archivo, o empezar con los valores actuales.
@@ -1123,105 +1389,120 @@ Do you want to import settings from a file?
Do you want to import them?
If you have a settings backup file, you may import that instead.
-
+ Se han encontrado ajutes de la versión de Companion: %1.
+¿Quieres importarlos?
+
+Si tienes un archivo de backup, puedes importar en su lugar.
Select %1:
-
+ Selecciona %1:
Save application settings to file...
-
+ Guardar ajustes aplicación a archivo...
Load application settings from file or previous version...
-
+ Cargar ajustes de aplicación desde archivo o versión previa...
Reset ALL application settings to default and remove radio profiles...
-
+ Resetea TODOS los ajustes de la aplicación y eliminar los perfiles de radio...
Exit before settings initialization and application startup.
-
+ Salir antes de inicializar ajustes y arrancar aplicación.
Print version number and exit.
-
+ Muestra número de de versión y sale.
Print this help text.
-
+ Muestra este texto de ayuda.
Reset ALL application settings to default values and remove radio profiles, are you sure?
-
+ Resetea TODOS los ajustes a valores predeterminados y elimina los perfiles de radio, ¿estás seguro?
Would you like to perform a backup first?
-
+ ¿Quieres hacer una copia primero?
Application settings were reset and saved.
-
+ Los ajustes de la aplicación fueron reseteados y guadados.
settings
-
+ ajustes
CompareDialog
+
+
Compare Models
-
+ Comparar modelos
+
+
To compare models, drag and drop them anywhere in this window.
-
+ Para comparar modelos, arrastra y suéltalos en esta ventana.
+
+
Close
Cerrar
+
+
Style
-
+ Estilo
+
+
Print
Imprimir
+
+
Print to file
Imprimir a archivo
Unnamed Model %1
-
+ Modelo sin nombre %1
Click to remove this model.
-
+ Presiona para eleminar este modelo.
@@ -1231,7 +1512,7 @@ If you have a settings backup file, you may import that instead.
Select PDF output file
- Seleccionar archivo de salida PDF
+ Seleccionar archivo de salida PDF
@@ -1239,7 +1520,7 @@ If you have a settings backup file, you may import that instead.
OK, I understand.
- OK, Entiendo.
+ OK, entiendo.
@@ -1247,17 +1528,17 @@ If you have a settings backup file, you may import that instead.
Write error
- Error escritura
+ Error de escritura
Cannot write %1 (reason: %2)
-
+ No se puede escribir %1 (razón: %2)
Cannot open %1 (reason: %2)
-
+ No se puede abrir %1 (razón: %2)
@@ -1265,55 +1546,55 @@ If you have a settings backup file, you may import that instead.
OpenTX Contributors
-
+ Colaboradores de OpenTX
Honors go to Rafal Tomczak (RadioClone), Thomas Husterer (th9x) and Erez Raviv (er9x and eePe)
- Los honores van a Rafal Tomczak (RadioClone), Thomas Husterer (th9x) y Erez Raviv (er9x y eePe)
+ Los honores son para Rafal Tomczak (RadioClone), Thomas Husterer (th9x) y Erez Raviv (er9x y eePe)
OpenTX Blacklist
-
+
Main developers
-
+ Desarrolladores principales
Translators
-
+ Traductores
Companies and projects who have donated to OpenTX
-
+ Compañías y proyectos que han donado a OpenTX
People who have donated to OpenTX
-
+ Gente que ha donado a OpenTX
Other contributors
-
+ Otros colaboradores
monthly
-
+ mensualmente
CurveData
-
+
CV
-
+
@@ -1321,17 +1602,17 @@ If you have a settings backup file, you may import that instead.
Diff
- Diff
+
Expo
- Expo
+
Func
- Func
+
@@ -1344,109 +1625,145 @@ If you have a settings backup file, you may import that instead.
Diff(%1)
-
+
Expo(%1)
-
+
Function(%1)
- Función(%1)
+ Función(%1)
Curve(%1)
- Curva(%1)
+ Curva(%1)
Curves
+
+
Fixed X
- X Fija
+ X fija
+
+
Custom X
- X A medida
+ X personalizada
+
+
Lines
- Lineas
+ Líneas
+
+
Smooth
Suave
+
+
+
+
Curve type
- Tipo de Curva
+ Tipo de curva
+
+
Curve Creator
- Creador de curva
+ Propiedades de la curva
+
+
Y at X=0
- Y a X=0
+ Y en X=0
+
+
Point size
-
+ Tamaño punto
+
+
Y at X=100
- Y a X=100
+ Y en X=100
+
+
Both
Ambos
+
+
x>0
- x>0
+
+
+
x<0
- x<0
+
+
+
Apply
Aplicar
+
+
Side
- Cara
+ Lado
+
+
Y at X=-100
- Y a X=-100
+ Y en X=-100
+
+
Coefficient
Coeficiente
+
+
Curve name
Nombre de la curva
@@ -1458,7 +1775,7 @@ If you have a settings backup file, you may import that instead.
Popup menu available
-
+ Menú desplegable disponible
@@ -1473,47 +1790,47 @@ If you have a settings backup file, you may import that instead.
Single Expo
- Expo Unico
+ Expo único
Symmetrical f(x)=-f(-x)
- Simetricas f(x)=-f(-x)
+ Simétricas f(x)=-f(-x)
Symmetrical f(x)=f(-x)
- Simetricas f(x)=f(-x)
+ Simétricas f(x)=f(-x)
Copy
-
+ Copiar
Paste
-
+ Pegar
Clear
-
+ Limpiar
Clear all curves
-
+ Limpiar todas las curvas
Are you sure you want to reset curve %1?
-
+ ¿Seguro que quieres resetear todas la curva %1?
Are you sure you want to reset all curves?
-
+ ¿Seguro que quiere resetear todas las curvas?
@@ -1523,7 +1840,7 @@ If you have a settings backup file, you may import that instead.
Not enough free points in EEPROM to store the curve.
- No hay suficientes puntos en el EEPROM para guardar la curva.
+ No hay suficientes puntos libres en la EEPROM para guardar la curva.
@@ -1531,234 +1848,239 @@ If you have a settings backup file, you may import that instead.
GF
-
+
SF
- SF
+
Override %1
- Invalidar %1
+ Invalidar %1
Trainer
- Trainer
+ Entrenador
Trainer RUD
- Entrenador RUD
+ Entrenador RUD
Trainer ELE
- Entrenador ELE
+ Entrenador ELE
Trainer THR
- Entrenador THR
+ Entrenador THR
Trainer AIL
- Entrenador AIL
+ Entrenador AIL
- Instant Trim
- Trim Instantáneo
+ Trainer Channels
+ Canales entrenador
- Play Sound
- Reproducir Sonido
+ Instant Trim
+ Trim instantáneo
- Haptic
- Reproducir Haptic
+ Play Sound
+ Reproducir sonido
- Reset
- Resetear
+ Haptic
+ Reproducir haptic
- Set Timer %1
- Ajustar temporizador %1
+ Reset
+ Resetear
- Vario
-
+ Set Timer %1
+ Ajustar temporizador %1
- Play Track
- Reproducir Pista
+ Vario
+ Variómetro
- Play Both
- Reproducir Ambos
+ Play Track
+ Reproducir pista
- Play Value
- Reproducir Valor
+ Play Both
+ Reproducir ambos
- Play Script
-
+ Play Value
+ Reproducir valor
- SD Logs
-
+ Play Script
+ Reproducir script
- Volume
- Volumen
+ SD Logs
+ Reportes SD
- Backlight
- Luz de Fondo
+ Volume
+ Volumen
- Screenshot
-
+ Backlight
+ Luz de fondo
- Background Music
- Música de Fondo
+ Screenshot
+ Captura
- Background Music Pause
- Pausar Música de Fondo
+ Background Music
+ Música de fondo
- Adjust %1
-
+ Background Music Pause
+ Pausar música de fondo
- SetFailsafe Int. Module
-
+ Adjust %1
+ Ajustar %1
- SetFailsafe Ext. Module
-
+ SetFailsafe Int. Module
+ Fijar failsafe módulo interno
- RangeCheck Int. Module
-
+ SetFailsafe Ext. Module
+ Fijar failsafe módulo externo
- RangeCheck Ext. Module
-
+ RangeCheck Int. Module
+ RangeCheck módulo interno
- Bind Int. Module
-
+ RangeCheck Ext. Module
+ RangeCheck módulo externo
+ Bind Int. Module
+ Bind módulo interno
+
+
+
Bind Ext. Module
-
+ Bind módulo externo
-
+
Timer1
- Temporizador1
-
-
-
- Timer2
- Temporizador 2
+ Temporizador 1
- Timer3
- Temporizador 3
+ Timer2
+ Temporizador 2
+ Timer3
+ Temporizador 3
+
+
+
Flight
-
+ Vuelo
-
+
Telemetry
- Telemetría
+ Telemetría
-
+
Rotary Encoder
- Codificador Rotativo
+ Codificador rotativo
-
+
REa
-
+
-
+
REb
-
+
-
+
s
-
+
-
-
-
+
+
+
<font color=red><b>Inconsistent parameter</b></font>
- <font color=red><b>Parámetro Inconsistente</b></font>
+ <font color=red><b>Parámetro Inconsistente</b></font>
-
+
Value
- Valor
+ Valor
-
+
played once, not during startup
-
+ reproducido una vez, no durante el inicio
-
+
repeat(%1s)
-
+ repetir(%1s)
-
+
DISABLED
-
+ DESABILITADO
-
+
CFN
-
+
@@ -1766,7 +2088,7 @@ If you have a settings backup file, you may import that instead.
Switch
- Cambiar
+ Interruptor
@@ -1786,150 +2108,210 @@ If you have a settings backup file, you may import that instead.
Popup menu available
-
+ Menú deplegable disponible
SF%1
- SF%1
+
GF%1
-
+
ON
- ON
+
Error occurred while trying to play sound, possibly the file is already opened. (Err: %1 [%2])
-
+ Ha ocurrido un error al reproducir el sonido, posiblemente el archivo ya está abierto. (Err: %1 [%2])
Unable to find or open sound file:
%1
-
+ No se puede encontrar o abrir el archivo de sonido:
+%1
-
- Value
- Valor
-
-
-
- Source
-
-
-
-
- GVAR
- GVAR
-
-
-
- Increment
- Incremento
-
-
-
- &Delete
- &Borrar
+
+ Copy
+ Copiar
- &Copy
- &Copiar
+ Cut
+ Cortar
- &Cut
- C&ortar
+ Paste
+ Pegar
- &Paste
- &Pegar
+ Clear
+ Limpiar
+
+
+
+ Insert
+ Insertar
+
+
+
+ Delete
+ Borrar
+
+
+
+ Move Up
+ Mover arriba
+
+
+
+ Move Down
+ Mover abajo
+
+
+
+ Clear All
+ Limpiar todo
+
+
+
+ Value
+ Valor
+
+
+
+ Source
+ Fuente
+
+
+
+ GVAR
+
+
+
+
+ Increment
+ Incremento
CustomizeSplashDialog
+
+
Transmitter Splash Screen Editor
- Editor de la pantalla de inicio del transmisor
+ Editor de la pantalla de inicio de la radio
+
+
+
+
Invert
Invertir
+
+
+
+
Load FW
Cargar FW
+
+
+
+
Load Pict
- Cargar Imag
+ Cargar imag
+
+
+
+
Load Profile
- Cargar Perfil
+ Cargar perfil
+
+
+
+
Save
Guardar
+
+
+
+
Open Splash Library
- Abrir libreria de pantallas de inicio
+ Abrir librería de pantallas de inicio
+
+
+
+
+
+
+
+
...
FW: %1
-
+
Pict: %1
-
+
Profile image
- Nombre de Perfil
+ Nombre de imagen
Open Firmware File
- Abrir archivo de Firmware
+ Abrir archivo de firmware
Can not load embedded image from firmware file %1.
- No se pueden cargar la imagen incrustada el archivo de firmware %1.
+ No se puede cargar la imagen incrustada en el archivo de firmware %1.
@@ -1939,7 +2321,7 @@ If you have a settings backup file, you may import that instead.
Images (%1)
- Imagenes (%1)
+ Imágenes (%1)
@@ -1959,7 +2341,7 @@ If you have a settings backup file, you may import that instead.
File Saved
- Archivo Guardado
+ Archivo guardado
@@ -1979,7 +2361,7 @@ If you have a settings backup file, you may import that instead.
File Save Error
- Error Guardado de Archivo
+ Error en el guardado del archivo
@@ -1992,22 +2374,22 @@ If you have a settings backup file, you may import that instead.
90
- 90
+
120
- 120
+
120x
- 120x
+
140
- 140
+
@@ -2015,169 +2397,186 @@ If you have a settings backup file, you may import that instead.
Conversion error on field %1
-
+ Error de conversión en el campo %1
-
+
Switch
-
+ Interruptor
-
+
Switch
-
+ Interruptor
-
+
cannot be exported on this board!
-
+ no puede ser exportada en esta placa!
-
+
Source
-
+ Fuente
-
+
Source %1 cannot be exported on this board!
-
+ ¡La fuente %1 no puede ser exportada a esta placa!
-
+
OpenTX only accepts %1 points in all curves
- OpenTx solo aceta %1 puntos en todas las curvas
+ OpenTX sólo acepta %1 puntos en todas las curvas
-
+
OpenTx only accepts %1 points in all curves
- OpenTx solo aceta %1 puntos en todas las curvas
+ OpenTX sólo acepta %1 puntos en todas las curvas
-
-
+
+
OpenTX on this board doesn't accept this function
- OpenTX en esta placa no acepta esa función
+ OpenTX en esta placa no acepta esa función
-
+
OpenTX doesn't accept this radio protocol
- OpenTX en esta placa no acepta este protocolo de radio
+ OpenTX no acepta este protocolo de radio
DebugOutput
-
+
+
Debug Output
-
+ Salida de depuración
-
+
+
<html><head/><body><p>Enable or disable the filter. If the button won't stay enabled, it is likely there is a syntax error in the Regular Expression entered.</p></body></html>
-
+ <html><head/><body><p>Activa/desactiva el filtro. Si el botón no permanece activo, probablemente hay un error de sintaxis en la expresión introducida.</p></body></html>
-
+
+
Filter:
-
+ Filtro:
-
+
+
<html><head/><body><p>Enter filter text here. Click the help/info button for details about using the filter. </p><p>
To <b>remove a remembered entry</b> from the filter list, first choose it, and then press <code>Shift-Delete</code> (or <code>Shift-Backspace</code>) key combination.</p></body></html>
-
+ <html><head/><body><p>Introduce fitro de texto aquí. Presiona el botón de ayuda/info para detalles acerca del uso del filtro. </p><p>
+Para <b>eliminar una entrada recordada</b> desde la lista de filtros, primero elígelo, y entonces presiona la combinación de teclas <code>Shift-Delete</code> (o <code>Shift-Backspace</code>) .</p></body></html>
-
+
+
Buffer:
-
+ Buffer:
-
+
+
Number of lines to keep in display.
-
+ Número de líneas a mantener en display.
-
+
+
Filter &Help
-
+ &Ayuda filtros
-
+
+
Show information about using the filter.
-
+ Muestra información acerca del uso de filtros.
-
+
+
Word &Wrap
-
+ Ajuste de &línea
-
+
+
Toggle word wrapping on/off.
-
+ Habilita/desabilita ajuste de línea.
-
+
+
&Clear
-
+ &Limpiar
-
+
+
Clear the output window of all text.
-
+ Limpia de texto la ventana de salida.
-
+
+
Enable &Filter
-
+ Habilitar &filtro
-
+
+
Turn the filter on/off.
-
+ Apaga/enciende el filtro.
-
+
<html><head><style>kbd {background-color: palette(alternate-base); font-size: large; white-space: nowrap;}</style></head><body><p>The filter supports two syntax types: basic matching with common wildcards as well as full Perl-style (<code>pcre</code>) Regular Expressions.</p><p>By default a filter will only show lines which match (<b>inclusive</b>). To make an <b>exclusive</b> filter which removes matching lines, prefix the filter expression with a <kbd>!</kbd> (exclamation mark).</p><p>To use <b>Regular Expressions</b> (RegEx), prefix the filter text with a <kbd>/</kbd> (slash) or <kbd>^</kbd> (up caret). <ul><li>Put the <kbd>/</kbd> or <kbd>^</kbd> after the exclusive <kbd>!</kbd> indicator if you're using one.</li><li>By default the match is case-sensitive. To make it insensitive, add the typical <kbd>/i</kbd> (slash i) operator at the end of your RegEx.</li><li>If you use a caret (^) to denote a RegEx, it will become part of the Reg. Ex. (that is, matches from start of line).</li><li>If the RegEx is invalid, the filter edit field should show a red border and you will not be able to enable the filter.</li><li>A useful resource for testing REs (with a full reference) can be found at <a href="http://www.regexr.com/">http://www.regexr.com/</a></li></ul></p><p>To use <b>basic matching</b> just type any text.<ul><li>Wildcards: <kbd>*</kbd> (asterisk) matches zero or more of any character(s), and <kbd>?</kbd> (question mark) matches any single character.</li><li>The match is always case-insensitive.</li><li>The match always starts from the beginning of a log line. To ignore characters at the start, use a leading <kbd>*</kbd> wildcard.</li><li>A trailing <kbd>*</kbd> is always implied (that is, matches anything to the end of the log line). To avoid this, use a RegEx.</li><li>You can match literal wildcard characters by prefixing them with a <kbd>\</kbd> (backslash) character (eg. "foo\*bar" matches "foo*bar").</li></ul></p><p>After <b>editing text</b>, press ENTER or TAB key (or click anywhere outside the box) to update the filter.</p><p>To <b>remove an entry</b> from the filter selector list, first choose it, and while in the line editor press <kbd>Shift-Delete</kbd> (or <kbd>Shift-Backspace</kbd>) key combination. The default filters cannot be removed. Up to 50 filters are stored.</p></body></html>
-
+ <html><head><style>kbd {background-color: palette(alternate-base); font-size: large; white-space: nowrap;}</style></head><body><p>El filtro admite dos tipos de sintaxis: coincidencia básica con comodines comunes y expresiones regulares Perl-style (<code>pcre</code>).</p><p>Por defecto, un filtro solo mostrará líneas que coinciden (<b>inclusivo</b>). Para hacer un filtro <b>exclusivo</b> que elimine la lineas con coincidencias, prefija la expresión del filtro con un <kbd>!</kbd> (símbolo de exclamación).</p><p>Para usar <b>expresiones regulares</b> (RegEx), prefija el filtro de texto con un <kbd>/</kbd> (barra oblicua) o <kbd>^</kbd> (et). <ul><li>Pon el <kbd>/</kbd> o <kbd>^</kbd> después del indicador exclusivo <kbd>!</kbd> si estás usando uno.</li><li> Por defecto, la coincidencia distingue entre mayúsculas y minúsculas. Para hacerlo insensible, agrega el operador típico<kbd>/i</kbd> (barra invertida) al final del RegEx.</li><li>Si usas un et (^) para indicar RegEx, se convertirá en parte del Reg. Ex. (esto es, coincidencia desde el incio de línea).</li><li>Si el RegEx no es válido, el campo de edición del filtro mostrará un borde rojo y no se podrá habilitar el filtro.</li><li>Encuentra un recurso útil para probar RE (con una referencia completa) en <a href="http://www.regexr.com/">http://www.regexr.com/</a></li></ul></p><p>Para usar <b>coincidencia básica</b> simplemente teclee cualquier texto.<ul><li>Comodines: <kbd>*</kbd> (asterisco) coincidencia de ningúno o más caracter(es), y <kbd>?</kbd> (símbolo de interrogación) coincidecia de caracteres individuales.</li><li>La coincidecia es insensible a mayús/minus.</li><li>La coincidencia siempre empieza desde el inicio de la línea de reporte. Para ignorar caracteres al inicio, usa un comodín de comienzo <kbd>*</kbd>.</li><li>De final <kbd>*</kbd> está siempre implícito (esto es, cualquier coincidecia hasta el final de la línea de reporte). Para evitar esto, use ub RegEx.</li><li>Puedes hacer coincidir con caracteres comodines prefijándolos con el carácter <kbd>\</kbd> (barra invertida) (ej. "foo\*bar" coincide "foo*bar").</li></ul></p><p>Después de <b>editar texto</b>, presiona la tecla ENTER o TAB (o haz click fuera del texto para actualizar el filtro.</p><p>Para <b>eliminar una entrada</b> de la lista de selección de filtro, primero selecciónala, y mientras estás en la linea del editor pulsa la combinación de teclas <kbd>Shift-Delete</kbd> (o <kbd>Shift-Backspace</kbd>). Los filtros predeterminados no se pueden eliminar. Se guardan hasta 50 filtros.</p></body></html>
-
+
Debug Console Filter Help
-
+ Ayuda del filtro de la consola de depuración
DownloadDialog
+
+
Downloading:
- Descargando:
+ Descargando:
Unable to save the file %1: %2.
- No se puede guardar el archivo %1: %2.
+ No se puede guardar el archivo %1: %2.
Download failed: %1.
- Descarga fallida: %1.
+ Descarga fallida: %1.
@@ -2185,85 +2584,87 @@ To <b>remove a remembered entry</b> from the filter list, first cho
Possible causes for this:
-
+ Posibles causas de esto:
- Eeprom is from a newer version of OpenTX
-
+ - Eeprom es de una versión más nueva de OpenTX
- Eeprom is not from OpenTX
-
+ - Eeprom no es de OpenTX
- Eeprom is not from Th9X
-
+ - Eeprom no es de Th9X
- Eeprom is not from Gruvin9X
-
+ - Eeprom no es de Gruvin9X
- Eeprom is not from ErSky9X
-
+ - Eeprom no es de ErSky9X
- Eeprom is not from Er9X
-
+ - Eeprom no es de Er9X
- Eeprom size is invalid
-
+ - Tamaño de eeprom no es válido
- Eeprom file system is invalid
-
+ - Sistema de archivos de eeprom no es válido
- Eeprom is from a unknown board
-
+ - Eeprom es de una placa desconocida
- Eeprom is from the wrong board
-
+ - Eeprom es de una placa errónea
- Eeprom backup not supported
-
+ - Backup de Eeprom no soportado
- Something that couldn't be guessed, sorry
-
+ - Algo que no pudo ser adivinado, lo siento
Warning:
-
+ Advertencia:
- Your radio probably uses a wrong firmware,
eeprom size is 4096 but only the first 2048 are used
-
+ Tu radio probablemente usa un firmware erróneo,
+ el tamaño de la eeprom es de 4096 pero sólo los primeros 2048 son usados
- Your eeprom is from an old version of OpenTX, upgrading!
To keep your original file as a backup, please choose File -> Save As specifying a different name.
-
+ Tu eeprom es de una vesión anterior de OpenTX, actualizando!
+ Para mantener tu archivo original como un backup, por favor elige Archivo -> Guarda Como especificando un nombre diferente.
@@ -2271,12 +2672,12 @@ To <b>remove a remembered entry</b> from the filter list, first cho
Unable to open %1: %2
-
+ No se puede abrir %1: %2
Invalid EEPROM file %1
-
+ Fichero EEPROM %1 no válido
@@ -2284,12 +2685,12 @@ To <b>remove a remembered entry</b> from the filter list, first cho
<br>First Elevon Channel:
- <br>Primer canal de Elevon:
+ <br>Primer canal de elevón:
Second Elevon Channel:
- Segundo canal de Elevon:
+ Segundo canal de elevón:
@@ -2297,18 +2698,20 @@ To <b>remove a remembered entry</b> from the filter list, first cho
INP
-
+
(@%1)
-
+
ExpoDialog
+
+
Weight
Peso
@@ -2316,103 +2719,147 @@ To <b>remove a remembered entry</b> from the filter list, first cho
+
+
+
+
+
+
GV
- GV
+
+
+
Input name
Nombre entrada
+
+
Flight modes
Modos de vuelo
+
+
Switch
- Switch
+ Interruptor
+
+
Source
- Origen
+ Fuente
+
+
Line name
- Nombre de linea
+ Nombre de línea
+
+
Stick Side
- Lado Stick
+ Lado stick
+
+
Scale
Escala
+
+
Include Trim
- Incluir Trim
+ Incluir trim
+
+
No
- No
+
+
+
Yes
- Si
+ Sí
+
+
Curve
Curva
+
+
Curve applied to the source.
- Curva aplicada al origen.
+ Curva aplicada a la fuente.
+
+
Offset
Offset
+
+
The source for the mixer
- El origen de la mezcla
+ La fuente de la mezcla
+
+
NEG
- NEG
+
+
+
Source for the mixer.
- Origen para la mezcla.
+ Fuente para la mezcla.
+
+
Switch used to enable the line.
If blank then the input is considered to be "ON" all the time.
- Switch usado para activar la linea.
-Si está en blanco entonces las entradas son consideradas como ON todo el tiempo.
+ Interruptor usado para activar la linea.
+Si está en blanco entonces las entradas son consideradas ON todo el tiempo.
+
+
POS
- POS
+
+
+
ALL
TODO
@@ -2424,22 +2871,22 @@ Si está en blanco entonces las entradas son consideradas como ON todo el tiempo
Popup menu available
-
+ Disponible menú desplegable
Clear All
-
+ Limpiar todo
Set All
-
+ Fijar todo
Invert All
-
+ Invertir todo
@@ -2447,57 +2894,57 @@ Si está en blanco entonces las entradas son consideradas como ON todo el tiempo
Select All
-
+ Selecciona todo
Copy selection as TAB-delimited text
-
+ Copiar selección como texto delimitado por TAB
Copy selection as cooma-delimited text (CSV)
-
+ Copiar selección como texto delimitado por comas (CSV)
Copy selection as pipe-delimited text
-
+ Copiar selección como texto delimitado por barras verticales
Copy selection as HTML
-
+ Copiar selección como HTML
Save selection to file
-
+ Guardar seleccíon a archivo
Tab-delimited text
-
+ Texto delimitado por TAB
Comma-delimited text
-
+ Texto delimitado por comas
Pipe-delimited text
-
+ Texto delimitado por barras verticales
HTML
-
+
Save to file
-
+ Guardar a archivo
@@ -2505,22 +2952,22 @@ Si está en blanco entonces las entradas son consideradas como ON todo el tiempo
Throttle Channel:
- Canal de Acelerador:
+ Canal de acelerador:
Yaw Channel:
- Canal de Yaw:
+ Canal de viraje:
Pitch Channel:
- Canal de pitch:
+ Canal de inclinación:
Roll Channel:
- Canal de roll:
+ Canal de balanceo:
@@ -2528,565 +2975,604 @@ Si está en blanco entonces las entradas son consideradas como ON todo el tiempo
Synchronize Files
-
+ Sincroniza ficheros
Are you sure you wish to abort the sync?
-
+ ¿Seguro que quieres abortar la sincronización?
Source Folder:
-
+ Carpeta de origen:
Destination Folder:
-
+ Carpeta de destino:
%1%2 Both directions, to destination folder first
-
+ %1%2 ambas direcciones, a la carpeta de destino primero
%1%2 Both directions, to source folder first
-
+ %1%2 ambas direcciones, a la carpeta de origen primero
%1 Only from source folder to destination folder
-
+ %1 Sólo de la carpeta de origen a la carpeta de destino
%1 Only from destination folder to source folder
-
+ %1 Sólo de la carpeta de destino a la carpeta de origen
How to handle overwriting files which already exist in the destination folder.
-
+ Como manejar sobreescritura de archivos que ya existen en la carpte de destino.
Copy only if newer and different (compare contents)
-
+ Sólo copiar si es más reciente y diferente (comparar contenido)
Copy only if newer (do not compare contents)
-
+ Sólo copiar si más reciente (no comparar contenido)
Copy only if different (ignore file time stamps)
-
+ Copiar si es diferente (ignora marcas de tiempo del archivo)
Always copy (force overwite existing files)
-
+ Siempre copia (fuerza sobreescritura de archivos existentes)
Any size
-
+ Cualquier tamaño
Skip files larger than this size. Enter zero for unlimited.
-
+ Omitir archivos mayores de este tamaño. Cero para ilimitado.
Minimum reporting level. Events of this type and of higher importance are shown.
WARNING: High log rates may make the user interface temporarily unresponsive.
-
+ Mínimo nivel de reporte. Eventos de este tipo y de mayor importancia son mostrados.
+ADVERTENCIA: Altos niveles de reporte pueden hace que la interfaz de usuario no responda temporalemente.
Skipped
-
+ Omitido
Created
-
+ Creado
Updated
-
+ Actualizado
Errors Only
-
+ Sólo errores
Test-run only
-
+ Sólo Test-run
Run as normal but do not actually copy anything. Useful for verifying results before real sync.
-
+ Ejecución normal pero no copia nada. Útil para verificar resultados antes de una sincronización real.
Log Level:
-
+ Nivel de reporte:
Filters:
-
+ Filtros:
The "Include" filter will only copy files which match the pattern(s).
The "Exclude" filter will skip files matching the filter pattern(s).
The Include filter is evaluated first.
-
+ El filtro "Incluye" sólo copiará archivos que coincidan con el patrón(es).
+El filtro "Excluye" omitirá archivos que coincidan con el patrón(es).
+El filtro Incluye es evaluado primero.
One or more file pattern(s) to exclude, separated by commas.
Blank means exclude none. ?, *, and [...] wildcards accepted.
-
+ Uno o más patrones de archivos a excluir, separados por comas.
+Vacío significa incluir todos. Comodines ?, *, y [...] aceptados.
One or more file pattern(s) to include, separated by commas.
Blank means include all. ?, *, and [...] wildcards accepted.
-
+ Uno o más patrones de archivos a incluir, separados por comas.
+Vacío significa incluir todos. Comodines ?, *, y [...] aceptados.
Include:
-
+ Incluye:
Exclude:
-
+ Excluye:
Case sensitive
-
+ Distingue mayús/minus
Follow links
-
+ Sigue links
Include hidden
-
+ Incluye ocultos
Recursive
-
+ Recursivo
Skip empty
-
+ Omitir vacíos
Apply filters
-
+ Aplica filtros
Filter Options:
-
+ Opciones de filtro:
Folder Options:
-
+ Opciones de carpeta:
Options
-
+ Opciones
Show extra options
-
+ Muestra opciones extra
Reset to defaults
-
+ Resetear a predeterminados
Close
- Cerrar
+ Cerrar
Sync. Direction:
-
+ Dirección de sinc:
Existing Files:
-
+ Archivos existentes:
Max. File Size:
-
+ Max. tamaño archivo:
MB
-
+
KB
-
+
Abort
-
+ Abortar
Start
- Comenzar
+ Iniciar
Total: <b>%1</b>; Created: <b>%2</b>; Updated: <b>%3</b>; Skipped: <b>%4</b>; Errors: <font color=%6><b>%5</b></font>;
-
+ Total: <b>%1</b>; Creados: <b>%2</b>; Actualizados: <b>%3</b>; Omitidos: <b>%4</b>; Errores: <font color=%6><b>%5</b></font>;
Current: <b>%1</b> of
-
+ Actual: <b>%1</b> de
Source folder not found.
-
+ Carpeta de origen no encontrada.
Destination folder not found.
-
+ Carpeta de destino no encontrada.
Source and destination folders are the same.
-
+ Carpetas de origen y destino son las mismas.
Firmware
-
+
Channel values displayed in us
- Visualizar los valores de canal en us
+ Visualiza los valores de canal en us
-
+
No OverrideCH functions available
- No hay funciones OverrideCH disponibles
+ Sin funciones OverrideCH
-
+
Possibility to enable FAI MODE (no telemetry) at field
-
-
-
-
- FAI MODE (no telemetry) always enabled
-
-
-
-
- Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015
-
+ Posibilidad de habilitar el MODO FAI (sin telemetría)
-
+ FAI MODE (no telemetry) always enabled
+ MODO FAI (sin telemetría) siempre activado
+
+
+
+ Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015
+ Elimina el soporte para el protocolo D8 FrSky el cual no es de uso legal en EU en radios vendidas después del 1 de enero de 2015
+
+
+
+
Disable HELI menu and cyclic mix support
- Desactivar el menú de HELI y el soporte de mezcla de cíclico
+ Desactiva el menú de HELI y el soporte de mezcla de cíclico
-
-
+
+
Disable Global variables
- Desactivar las variables Globales
+ Desactiva las variables globales
-
-
+
+
Enable Lua custom scripts screen
-
-
-
-
- Use alternative SQT5 font
- Usar fuente alternativa SQT5
-
-
-
- Pots use in menus navigation
- Usar potenciómetros en los menús de navegación
-
-
-
- FrSky Taranis X9D+
-
-
-
-
- Support for PPM internal module hack
-
-
-
-
- Enable non certified firmwares
-
-
-
-
- Disable RAS (SWR)
-
-
-
-
- FrSky Taranis X9D+ 2019
-
-
-
-
- FrSky Taranis X9D
-
-
-
-
- Haptic module installed
- Módulo Haptic instalado
-
-
-
- FrSky Taranis X9E
-
-
-
-
- Confirmation before radio shutdown
-
-
-
-
- Horus gimbals installed (Hall sensors)
-
-
-
-
- FrSky Taranis X9-Lite
-
-
-
-
-
- Support for auto update on boot
-
-
-
-
- FrSky Taranis X7 / X7S
-
-
-
-
- FrSky Taranis X-Lite S/PRO
-
-
-
-
- FrSky Taranis X-Lite
-
-
-
-
- FrSky Horus X10 / X10S
-
-
-
-
- FrSky Horus X12S
-
-
-
-
- Use ONLY with first DEV pcb version
-
-
-
-
- Turnigy 9XR-PRO
-
-
-
-
- Enable HELI menu and cyclic mix support
- Activar menú HELI y el soporte de mezcla de cíclico
-
-
-
- Global variables
- Variables globales
-
-
-
- In model setup menus automatically set source by moving the control
- En el menú de ajuste de modelo se selecciona automáticamente el origen del control moviendolo
-
-
-
- In model setup menus automatically set switch by moving the control
- En el menú de ajuste de modelo se selecciona automáticamente el switch de control moviendolo
-
-
-
- No graphical check boxes and sliders
- Sin casillas de verificación ni sliders gráficos
-
-
-
- Battery graph
- Gráfico batería
+ Habilita la pantalla de Lua custom scripts
- Don't use bold font for highlighting active items
- No usar la fuente negrita para destacar elementos activos
+ Use alternative SQT5 font
+ Usa la fuente alternativa SQT5
-
-
- Support for ACCESS internal module replacement
-
+
+ Pots use in menus navigation
+ Usa potenciómetros en los menús de navegación
+
+
+
+ FrSky Taranis X9D+
+
+
+
+
+ Support for PPM internal module hack
+ Soporte para el hack de PPM del módulo interno
+
+
+
+ Enable non certified firmwares
+ Habilita firmware no certificado
+
+
+
+
+ Disable RAS (SWR)
+ Desactiva RAS (SWR)
+
+
+
+ FrSky Taranis X9D+ 2019
+
+
+
+
+ FrSky Taranis X9D
+
+
+
+
+ Haptic module installed
+ Módulo haptic instalado
+
+
+
+ FrSky Taranis X9E
+
+
+
+
+ Confirmation before radio shutdown
+ Confirmar antes de apagar la radio
- FrSky Horus X10 Express
-
+ Horus gimbals installed (Hall sensors)
+ Gimbals Horus instalados (sensores Hall)
-
- Jumper T12
-
+
+ FrSky Taranis X9-Lite
+
-
- Enable non certified R9M firmwares
-
+
+ FrSky Taranis X7 / X7S
+
-
- Turnigy 9XR with m128 chip
-
+
+ FrSky Taranis X-Lite S/PRO
+
-
- Turnigy 9XR
-
-
-
-
- 9X with stock board
-
-
-
-
- Enable resetting values by pressing up and down at the same time
- Activar el reseteo de valores presionando up y down al mismo tiempo
-
-
-
- 9X with stock board and m128 chip
-
-
-
-
- 9X with AR9X board
-
-
-
-
- 9X with Sky9x board
-
-
-
-
- 9X with Gruvin9x board
-
+
+ FrSky Taranis X-Lite
+
+ FrSky Horus X10 / X10S
+
+
+
+
+ FrSky Horus X10 Express / X10S Express
+
+
+
+
+ FrSky Horus X12S
+
+
+
+
+ Use ONLY with first DEV pcb version
+ Usar SÓLO con la primera versión DEV pcb
+
+
+
+ Jumper T12 / T12 Pro
+
+
+
+
+
+ Support for MULTI internal module
+ Soporte para módulo interno MULTI
+
+
+
+ Jumper T16 / T16+ / T16 Pro
+
+
+
+
+
+ Support for bluetooth module
+ Soporte para módulo bluetooth
+
+
+
+ Radiomaster TX16s / TX16s Hall / TX16s Masterfire
+
+
+
+
+ Turnigy 9XR-PRO
+
+
+
+
+ Enable HELI menu and cyclic mix support
+ Activar menú HELI y el soporte de mezcla de cíclico
+
+
+
+ Global variables
+ Variables globales
+
+
+
+ In model setup menus automatically set source by moving the control
+ En el menú de ajuste de modelo se selecciona automáticamente el origen del control moviéndolo
+
+
+
+ In model setup menus automatically set switch by moving the control
+ En el menú de ajuste de modelo se selecciona automáticamente el interruptor de control moviéndolo
+
+
+
+ No graphical check boxes and sliders
+ Sin casillas de verificación ni sliders gráficos
+
+
+
+ Battery graph
+ Gráfico batería
+
+
+
+ Don't use bold font for highlighting active items
+ No usar la fuente negrita para destacar elementos activos
+
+
+
+ FrSky Taranis X9-Lite S
+
+
+
+
+ FrSky Taranis X7 / X7S Access
+ FrSky Taranis X7 / X7S Access
+
+
+
+
+ Support for ACCESS internal module replacement
+ Soporte para módulo interno ACCESS de reemplazo
+
+
+
+ Turnigy 9XR with m128 chip
+ Turnigy 9XR con chip m128
+
+
+
+ Turnigy 9XR
+
+
+
+
+ 9X with stock board
+ 9X con placa de stock
+
+
+
+ Enable resetting values by pressing up and down at the same time
+ Activar el reseteo de valores presionando arriva y abajo al mismo tiempo
+
+
+
+ 9X with stock board and m128 chip
+ 9X con placa de stock y chip m128
+
+
+
+ 9X with AR9X board
+ 9X con placa AR9X
+
+
+
+ 9X with Sky9x board
+ 9X con placa Sky9x
+
+
+
+ 9X with Gruvin9x board
+ 9X con placa Gruvin9x
+
+
+
DIY MEGA2560 radio
-
+
FirmwarePreferencesDialog
+
+
Downloads
Descargas
+
+
Check for updates
- Comprobar Actualizaciones
+ Comprobar actualizaciones
+
+
Firmware
- Firmware
+
+
+
Download firmware
-
+ Descargar firmware
+
+
Download SD contents
-
+ Descargar contenido SD
+
+
Latest Download
- Última Descarga
+ Última descarga
Unknown
- Desconocido
+ Desconocido
@@ -3094,319 +3580,373 @@ Blank means include all. ?, *, and [...] wildcards accepted.
No
- No
+
Yes, controlled by a single channel
- Si, controlado por un único canal
+ Sí, controlado por un único canal
Yes, controlled by two channels
- Si, controlado por dos canales
+ Sí, controlado por dos canales
<br>First Flap Channel:
- <br>Canal del primer Flap:
+ <br>Canal del primer flap:
Second Flap Channel:
- Canal del segundo Flap:
+ Canal del segundo flap:
FlashEEpromDialog
+
+
Write Models and Settings to Radio
- Escribir Modelos y Ajustes a la Radio
+ Escribir modelos y ajustes a la radio
+
+
Load...
-
+ Cargar...
+
+
Current Profile
- Perfil Actual
+ Perfil actual
+
+
Allows Companion to write to older version of the firmware
- Permitir a Companion escribir a las versiones viejas de firmware
+ Permite a Companion escribir en las versiones anteriores de firmware
+
+
Check Firmware compatibility
- Comprobar la compatibilidad del firmware
+ Comprobar la compatibilidad del firmware
+
+
<html><head/><body><p>Saves a dated copy of your eeprom to the backup folder you specified in the Companion settings before writing the current model to the radio.</p></body></html>
-
+ <html><head/><body><p>Guarda una copia de la eeprom a la carpeta de backup especificada en los ajustes de Companion antes de escribir el modelo actual en la radio.</p></body></html>
+
+
Backup before Write
-
+ Guadar antes de escribir
+
+
<html><head/><body><p>Modify calibration parameters using settings from current profile</p></body></html>
- <html><head/><body><p>Modificar los parámetros de calibración utilizando la configuración de perfil actual</p></body></html>
+ <html><head/><body><p>Modifica los parámetros de calibración utilizando la configuración de perfil actual</p></body></html>
+
+
Patch calibration setting from profile
- Arreglar los ajustes de calibración desde el perfil
+ Arreglar los ajustes de calibración desde el perfil
+
+
<html><head/><body><p>Modify HW parameters using settings from current profile</p></body></html>
- <html><head/><body><p>Modificar los parámetros de HW usando los ajustes del perfil actual</p></body></html>
+ <html><head/><body><p>Modifica los parámetros de HW usando los ajustes del perfil actual</p></body></html>
+
+
Patch HW settings from profile
-
+ Arreglar los ajustes de HW desde el perfil
+
+
Cancel
- Cancelar
+ Cancelar
+
+
Write to TX
- Escribir al TX
+ Escribir al TX
Current profile: %1
-
+ Perfil actual: %1
Choose Radio Backup file
- Elegir archivo de copia de seguridad de la radio
+ Elegir archivo de copia de seguridad de la radio
Wrong radio calibration data in profile, Settings not patched
- Datos de calibración de radio incorrectos en el perfil, ajustes no corregidos
+ Datos de calibración de radio incorrectos en el perfil, ajustes no corregidos
Wrong radio setting data in profile, Settings not patched
- Datos de ajustes de radio incorrectos en el perfil, ajustes no corregidos
+ Datos de ajustes de radio incorrectos en el perfil, ajustes no corregidos
Cannot write file %1:
%2.
- No se puede escribir el archivo %1:
+ No se puede escribir el archivo %1:
%2.
Error writing file %1:
%2.
- Error escribiendo el archivo %1:
+ Error escribiendo el archivo %1:
%2.
The radio firmware belongs to another product family, check file and preferences!
- El firmware de la radio pertenece a otro producto, ¡comprueba el archivo y las preferencias!
+ El firmware de la radio pertenece a otro producto, ¡comprueba el archivo y las preferencias!
The radio firmware is outdated, please upgrade!
- El firmware de la radio está obsoleto, ¡por favor actializalo!
+ El firmware de la radio está obsoleto, ¡por favor actualízalo!
Cannot check Models and Settings compatibility! Continue anyway?
- ¡No se pueden comprobar la compatibilidad de Modelos y Ajustes! ¿Continuar de todas maneras?
+ ¡No se puede comprobar la compatibilidad de modelos y ajustes! ¿Continuar de todas maneras?
FlashFirmwareDialog
+
+
Flash Firmware
-
+ Flash firmware
+
+
Load...
-
+ Cargando...
+
+
Date & Time
- Fecha & Hora
+ Fecha & Hora
+
+
Variant
- Variante
+ Variante
+
+
Version
-
+ Versión
+
+
Use profile start screen
- Usar la pantala de inicio del perfil
+ Usar la pantalla de inicio del perfil
+
+
Use firmware start screen
- Usar la pantalla de inicio del firmware
+ Usar la pantalla de inicio del firmware
+
+
Use library start screen
- Usar la libreria de pantalla de inicio
+ Usar la librería de pantalla de inicio
+
+
Use another start screen
- Usar otra pantalla de inicio
+ Usar otra pantalla de inicio
+
+
Allows Companion to write to older version of the firmware
- Permitir a Companion escribir a las versiones viejas de firmware
+ Permitir a Companion escribir a las versiones anteriores de firmware
+
+
Check Hardware compatibility
-
+ Verificar compatibilidad del hardware
+
+
Backup and restore Models and Settings
- Copia de seguridad y restauración de Modelos y Ajustes
+ Copia de seguridad y restauración de modelos y ajustes
+
+
Cancel
- Cancelar
+ Cancelar
+
+
Write to TX
- Escribir al TX
+ Escribir al TX
Open Firmware File
- Abrir archivo de Firmware
+ Abrir archivo de firmware
%1 may not be a valid firmware file
- %1 puede no ser un archivo de firmware válido
+ %1 puede no ser un archivo de firmware válido
The firmware file is not valid.
- El archivo de firmware no es válido.
+ El archivo de firmware no es válido.
There is no start screen image in the firmware file.
- No hay imagen de pantalla de inicio en el archivo de firmware.
+ No hay imagen de pantalla de inicio en el archivo de firmware.
Profile image %1 is invalid.
- El perfil de imagen %1 es inválido.
+ El perfil de imagen %1 no es válido.
Open image file to use as radio start screen
- Abir archivo de imagen para usar de pantalla de inicio de la radio
+ Abrir archivo de imagen para usar de pantalla de inicio de la radio
Images (%1)
- Imagenes (%1)
+ Imágenes (%1)
Image could not be loaded from %1
- La imagen no puede ser cargada desde %1
+ La imagen no puede ser cargada desde %1
The library image could not be loaded
- La librería de imágen no puede ser cargada
+ La librería de imágen no puede ser cargada
Splash image not found
-
+ Imagen de inicio no encontrada
Cannot save customized firmware
- No se puede guardar el firmware personalizado
+ No se puede guardar el firmware personalizado
Write Firmware to Radio
- Escribir Firmware a la Radio
+ Escribir firmware a la radio
Firmware check failed
-
+ Ha fallado la verificación del firmware
Could not check firmware from radio
-
+ No se puede verificar el firmware de la radio
New firmware is not compatible with the one currently installed!
-
+ ¡El nuevo firmware no es compatible con el instalado actualmente!
Conversion failed
- Coversion fallida
+ Coversión fallida
Cannot convert Models and Settings for use with this firmware, original data will be used
- No se pueden convertir los Modelos y Ajustes para usar con este firmware, se usarán los datos originales
+ No se puede convertir los modelos y ajustes para usar con este firmware, se usarán los datos originales
Restore failed
- Restauración fallida
+ Restauración fallida
Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1
- No se ha podido restaurar los Modelos y Ajustes a la Radio. Los datos de los modelos y ajustes se pueden encontrar en: %1
+ No se ha podido restaurar los modelos y ajustes a la radio. Los datos de los modelos y ajustes se pueden encontrar en: %1
Flashing done
-
+ Flashing hecho
@@ -3414,58 +3954,58 @@ Blank means include all. ?, *, and [...] wildcards accepted.
Executable %1 not found
-
+ Ejecutable %1 no encontrado
Writing...
-
+ Escribiendo...
Reading...
-
+ Leyendo...
Verifying...
-
+ Verificando...
unknown
-
+ desconocido
ie: OpenTX for 9X board or OpenTX for 9XR board
- Esto es: OpenTX para placas 9x o OpenTX para placas 9XR
+ Esto es: OpenTX para placas 9x o OpenTX para placas 9XR
ie: OpenTX for M128 / 9X board or OpenTX for 9XR board with M128 chip
- Esto es: OpenTX para placas M128 / 9x o OpenTX para placas 9XR con el chip M128
+ Esto es: OpenTX para placas M128 / 9x o OpenTX para placas 9XR con el chip M128
ie: OpenTX for Gruvin9X board
- Esto es: OpenTX para placas Gruvin9x
+ Esto es: OpenTX para placas Gruvin9x
Your radio uses a %1 CPU!!!
Please check advanced burn options to set the correct cpu type.
- Tu radio usa un %1 CPU!!!
+ Tu radio usa un %1 CPU!!!
-Por favor comprueba en las opciones avanzadas de gravado el tipo correcto de cpu.
+Por favor comprueba en las opciones avanzadas de grabado el tipo correcto de cpu.
Your radio uses a %1 CPU!!!
Please select an appropriate firmware type to program it.
- Tu radio usa un %1 CPU!!!
+ Tu radio usa un %1 CPU!!!
Por favor elige el tipo de firmware apropiado para programarlo.
@@ -3474,183 +4014,205 @@ Por favor elige el tipo de firmware apropiado para programarlo.
You are currently using:
%1
-
+
Actualmente estás usando:
%1
Your radio does not seem connected to USB or the driver is not initialized!!!.
-
+ ¡¡¡La radio no parece estar conectada al USB o el controlador no está inicializado!!!
Flashing done (exit code = %1)
-
+ Flashing hecho (código salida = %1)
Flashing done with errors
-
+ Flashing hecho con errores
FUSES: Low=%1 High=%2 Ext=%3
-
+ FUSIBLES: Low=%1 High=%2 Ext=%3
FlightMode
+
+
Fade In
-
+ Transición entrada
+
+
Fade Out
-
+ Transición salida
+
+
Name
Nombre
+
+
Switch
- Switch
+ Interruptor
+
+
+
+
+
+ trim6
+
+
+
+
+
+
+ trim5
+
FlightModeData
-
+
FM
-
+
FlightModePanel
-
+
Rotary Encoder %1
- Codificador Rotativo %1
+ Codificador rotativo %1
-
+
Name
- Nombre
+ Nombre
-
+
Value source
-
+ Valor fuente
-
+
Value
- Valor
+ Valor
+
+
+
+ GVAR%1
+
- GVAR%1
- GVAR%1
-
-
-
Popup enabled
- Popup activado
+ Menú desplegable activado
Popup menu available
-
+ Menú desplegable disponible
-
+
Trim disabled
- Trim desactivado
+ Trim desactivado
-
+
Own Trim
- Trim propio
+ Trim propio
-
+
Use Trim from Flight mode %1
- Usar Trim para el modo de vuelo %1
+ Usar trim para modo de vuelo %1
-
+
Use Trim from Flight mode %1 + Own Trim as an offset
- Usar Trim para el modo de vuelo %1 + Trim propio com un compensador
-
-
-
- Unit
- Unidad
-
-
-
- Prec
-
+ Usar trim para modo de vuelo %1 + trim propio con compensador
- Min
-
+ Unit
+ Unidad
+ Prec
+
+
+
+
+ Min
+ Mín
+
+
+
Max
-
+ Máx
-
+
0._
-
+
-
+
0.0
- 6P {0.0?}
+
-
-
+
+
&Clear
-
+ &Limpiar
-
-
+
+
Clear
-
+ Limpiar
-
+
Clear all current Flight Mode properties?
-
+ ¿Limpiar todas las propiedades del modo de vuelo actual?
FlightModesPanel
-
+
Flight Mode %1
- Modo de vuelo%1
+ Modo de vuelo %1
-
+
(%1)
- (%1)
+
-
+
(default)
- (Predeterminado)
+ (predeterminado)
@@ -3658,17 +4220,17 @@ Actualmente estás usando:
Has Flybar
- Tiene Flybar
+ Tiene flybar
Flybarless
- Flybarless
+
Flybar:
- Flybar:
+
@@ -3676,17 +4238,17 @@ Actualmente estás usando:
Yellow
- Amarillo
+ Amarillo
Orange
- Naranja
+ Naranja
Red
- Rojo
+ Rojo
@@ -3695,23 +4257,27 @@ Actualmente estás usando:
V
-
+
---
- ---
+
FusesDialog
+
+
Fuses
-
+ Fusibles
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -3725,15 +4291,31 @@ p, li { white-space: pre-wrap; }
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Proper states for AtMega 2560 :</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">EEPROM erase fuse not set: D7, 11, FC</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">EEPROM erase fuse set: D7, 19, FC</span></p></body></html>
-
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Lee los fuses actuales en el controlador AVR.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Estados apropiados para </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">AtMega 64 </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">:</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">EEPROM borrar fuse no fijado: 0E, 81, FF</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">EEPROM borra fuse fijado: 0E, 89, FF</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Estados apropiados para AtMega 2560 :</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">EEPROM borrar fuse no fijado: D7, 11, FC</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">EEPROM borrar fuse fijado: D7, 19, FC</span></p></body></html>
+
+
Read Fuses
- Leer Fuses
+ Leer fusibles
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -3749,17 +4331,35 @@ p, li { white-space: pre-wrap; }
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">When in doubt consult either the project's page or the 9xforum (http://9xforums.com/forum/)</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">If you do get locked out - google lookup for "dealing with Fuse Bricks".</span></p></body></html>
-
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600; text-decoration: underline;">Resetear fusibles</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Los fusibles en el AVR le dicen cómo comportarse. Al presionar este botón, los fusibles tienen los parámetros predeterminados necesarios en el FW. Estos parámetros son diferentes para el stock y 4,1 MB, verifique que haya seleccionado el tipo de procesador apropiado en las preferencias. </span> </p>
+<p style = "- qt-parameter-type: empty; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent : 0px; familia de fuentes: 'MS Shell Dlg 2'; tamaño de fuente: 8pt; "> <br /> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> Este botón también establece la "Protección EEPROM" Fusible. </span> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> Esto evita que se borre la EEPROM cuando se escribe la memoria flash. </span> </p>
+<p style = "- qt-parameter-type: empty; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent : 0px; familia de fuentes: 'MS Shell Dlg 2'; tamaño de fuente: 8pt; "> <br /> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "familia-fuente: 'MS Shell Dlg 2'; tamaño de fuente: 8pt; peso de fuente: 600; decoración de texto: subrayado;"> ADVERTENCIA </span> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> La configuración de los fusibles puede ocasionar problemas e incluso un bloqueo total de tu controlador. Haz esto solo si sabes lo que estás haciendo. </span> </p>
+<p style = "- qt-parameter-type: empty; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent : 0px; familia de fuentes: 'MS Shell Dlg 2'; tamaño de fuente: 8pt; "> <br /> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> En caso de duda, consulta la página del proyecto o el 9xforum (http://9xforums.com/forum/) </span> </ p >
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> Si quedas bloqueado, busca en google para & quot; tratar con Fuse Bricks & quot ;. </span> </p> </body> </html>
+
+
Reset Fuses
EEPROM - PROTECT
- Resetear Fuses
+ Resetear fusibles
EEPROM - PROTEGIDA
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -3775,16 +4375,35 @@ p, li { white-space: pre-wrap; }
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">When in doubt consult either the project's page or the 9xforum (http://9xforums.com/forum/)</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">If you do get locked out - google lookup for "dealing with Fuse Bricks".</span></p></body></html>
-
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600; text-decoration: underline;">Resetear fusibles</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Los fusibles en el AVR te dicen cómo comportarse. Al presionar este botón, los fusibles tienen los parámetros predeterminados necesarios en </span> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> FW. Estos parámetros son diferentes para el stock y 4,1 MB, verifique que haya seleccionado el tipo de procesador apropiado en las preferencias. </span> </p>
+<p style = "- qt-parameter-type: empty; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent : 0px; familia de fuentes: 'MS Shell Dlg 2'; tamaño de fuente: 8pt; "> <br /> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> Este botón también borra la "protección EEPROM" Fusible. </span> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> Esto causa el borrado de la EEPROM cuando se escribe la memoria flash. </span> </p>
+<p style = "- qt-parameter-type: empty; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent : 0px; familia de fuentes: 'MS Shell Dlg 2'; tamaño de fuente: 8pt; "> <br /> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "familia-fuente: 'MS Shell Dlg 2'; tamaño de fuente: 8pt; peso de fuente: 600; decoración de texto: subrayado;"> ADVERTENCIA </span> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> La configuración de los fusibles puede ocasionar problemas e incluso un bloqueo total de su controlador. Haz esto solo si sabes lo que estás haciendo. </span> </p>
+<p style = "- qt-parameter-type: empty; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent : 0px; familia de fuentes: 'MS Shell Dlg 2'; tamaño de fuente: 8pt; "> <br /> </p>
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> En caso de duda, consulta la página del proyecto o el 9xforum (http://9xforums.com/forum/) </span> </ p >
+<p style = "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-block-indent: 0; text-indent: 0px;"> <span style = "font-family: 'MS Shell Dlg 2'; font-size: 8pt;"> Si quedas bloqueado, busca en google para & quot; tratar con Fuse Bricks & quot ;. </span> </p> </body> </html>
+
+
Reset Fuses
EEPROM - DELETE
-
+ Resetear fusibles
+EEPROM - BORRAR
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -3793,18 +4412,24 @@ p, li { white-space: pre-wrap; }
<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changing the fuses can mess up your radio.</p>
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Proceed only if you know what you are doing.</p></body></html>
-
+ <html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">AVISO</span></p>
+<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Cambiar los fuses de la radio puede estropear la radio.</p>
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Continúa sólo si sabes lo que estás haciendo.</p></body></html>
Reset Radio Fuses
-
+ Resetear fusibles de la radio
Read Fuses from Radio
-
+ Leer fusibles de la radio
@@ -3812,53 +4437,57 @@ p, li { white-space: pre-wrap; }
%
-
+
?
-
+
0._
-
+
0.0
- 6P {0.0?}
+
?.?
-
+
GV
- GV
+
Own value
- Valor propio
+ Valor propio
Flight mode %1 value
- Valor modo de vuelo%1
+ Valor modo de vuelo %1
GeneralEdit
+
+
Radio settings
-
+ Ajustes radio
+
+
General settings used throught the transmitter.
These will be relevant for all models in the same EEPROM.
Ajustes generales usados a través del transmisor.
@@ -3872,32 +4501,36 @@ Estos puede ser relevantes para todos los modelos en el mismo EEPROM.
Trainer
- Trainer
+ Entrenador
+
+
Store calib. and hw settings in selected profile
- Guardar calib. y los ajustes de hw en el perfil seleccionado
+ Guardar calib. y ajustes hw en el perfil seleccionado
+
+
Retrieve calib. and hw settings from profile
- Recuperar calib. y los ajustes de hw de un perfil
+ Recuperar calib. y ajustes hw de un perfil
Global Functions
-
+ Funciones globales
Hardware
-
+ Hardware
Calibration
-
+ Calibración
@@ -3907,12 +4540,12 @@ Estos puede ser relevantes para todos los modelos en el mismo EEPROM.
Wrong data in profile, Switch/pot config not retrieved
-
+ Datos erróneos en el perfil, configuración de interruptor/pot no se ha recuperado
Wrong data in profile, hw related parameters were not retrieved
- Datos incorrectos en el perfil,los parámetros de hw no se ha recuperado
+ Datos incorrectos en el perfil, los parámetros de hw no se han recuperado
@@ -3928,236 +4561,330 @@ Estos puede ser relevantes para todos los modelos en el mismo EEPROM.
GeneralSettings
-
+
Radio Settings
-
+ Ajustes de radio
GeneralSetup
+
+
Form
-
+ Form
+
+
Readonly Unlock
- Desactivar solo lectura
+ Desactivar sólo lectura
+
+
SC
-
+
+
+
SE
-
+
+
+
SA
-
+
+
+
SF
- SF
+
+
+
SH
-
+
+
+
SD
-
+
+
+
SB
-
+
+
+
SG
-
+
+
+
Timeshift from UTC
- Zona horaria UTC
+ Zona horaria UTC
+
+
Voice Language
- Lenguaje de las Voces
+ Lenguaje de las voces
+
+
Country Code
- Codigo País
+ Código país
+
+
Stick reverse
-
+ Invertir stick
+
+
FAI Mode
- Modo FAI
+ Modo FAI
+
+
Adjust RTC
-
+ Ajustar RTC
+
+
Vario pitch at max
- Tono de vario al max
+ Tono de vario al máx
+
+
+
+
Hz
-
+
+
+
Speaker Volume
- Volumen Altavoz
+ Volumen altavoz
+
+
Backlight Switch
- Switch de pantalla
+ Interruptor de luz de fondo
+
+
Sound Mode
- Modo sonido
+ Modo sonido
+
+
Color 1
-
+
+
+
Color 2
-
+
+
+
Speaker Pitch (spkr only)
- Tono del altavoz (solo altavoz)
+ Tono altavoz(sólo alt)
+
+
If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds.
- Si este valor no es 0, cualquier pulsación encenderá la pantalla y se apagará despues de un número determinado de segundos.
+ Si este valor no es 0, cualquier pulsación encenderá la pantalla y se apagará despues de un número determinado de segundos.
+
+
+
+
+
+
sec
- seg
+ seg
+
+
Backlight color
- Color de pantalla
+ Color de pantalla
+
+
Beeper
-
+ Beeper
+
+
Speaker
- Altavoz
+ Altavoz
+
+
BeeperVoice
- BeeperVoz
+ VozBeeper
+
+
SpeakerVoice
- VozAltavoz
+ VozAltavoz
+
+
Beep volume
- Volumen Beep
+ Volumen beep
+
+
Wav volume
- Volumen Wav
+ Volumen wav
+
+
Vario volume
- Volumen Vario
+ Volumen vario
+
+
Background volume
- Volumen de Fondo
+ Volumen de fondo
+
+
+
+
ms
-
+
+
+
Backlight Auto OFF after
- Apagado automático de pantalla después
+ Auto apagado de pantalla después de
+
+
Backlight flash on alarm
- Pantalla parpadea con una alarma
+ Pantalla parpadea con alarma
+
+
Vario pitch at zero
- Tono de vario a cero
+ Tono de vario en cero
+
+
Vario repeat at zero
- Vario repite a cero
+ Vario repite en cero
+
+
This is the switch selectrion for turning on the backlight (if installed).
- Este es el switch seleccionado para encender la pantalla (si está instalada).
+ Este es el interruptor seleccionado para encender la luz de fondo (si está instalada).
+
+
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
@@ -4166,41 +4893,57 @@ p, li { white-space: pre-wrap; }
+
+
Backlight Brightness
- Brillo pantalla
+ Brillo pantalla
+
+
RotEnc Navigation
- Navegación RotEnc
+ Navegación RotEnc
+
+
Automatically adjust the radio's clock if a GPS is connected to telemetry.
-
+ Ajusta automáticamente el reloj de la radio si se conecta un GPS a la telemetría.
+
+
America
-
+ América
+
+
Japan
- Japón
+ Japón
+
+
Europe
- Europa
+ Europa
+
+
Backlight OFF Brightness
-
+ Brillo luz de fondo OFF
+
+
Mode selection:
Mode 1:
@@ -4220,7 +4963,7 @@ Mode 4:
Right stick: Elevator, Rudder
- Selección de Modo:
+ Selección de modo:
Modo 1:
Stick Izquierdo: Elevador, Timón
@@ -4242,465 +4985,661 @@ Modo 4:
+
+
Mode 1 (RUD ELE THR AIL)
- Modo 1 (RUD ELE THR AIL)
+ Modo 1 (RUD ELE THR AIL)
+
+
Mode 2 (RUD THR ELE AIL)
- Modo 2 (RUD THR ELE AIL)
+ Modo 2 (RUD THR ELE AIL)
+
+
Mode 3 (AIL ELE THR RUD)
- Modo 3 (AIL ELE THR RUD)
+ Modo 3 (AIL ELE THR RUD)
+
+
Mode 4 (AIL THR ELE RUD)
- Modo 4 (AIL THR ELE RUD)
+ Modo 4 (AIL THR ELE RUD)
+
+
<html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html>
- <html><head/><body><p>Orden de los canales</p><p><br/></p><p>Define el orden por defecto de las mezclas en un nuevo modelo</p></body></html>
+ <html><head/><body><p>Orden de los canales</p><p><br/></p><p>Define el orden por defecto de las mezclas en un nuevo modelo</p></body></html>
+
+
If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio.
-
+ Si activas FAI, sólo los sensores RSSI y RxBt seguirán funcionando. Esta función no puede ser deshabilitada en la radio.
+
+
RSSI Poweroff Warning
-
+ Aviso RSSI al apagado
+
+
Low EEPROM Warning
-
+ Advertencia de poca EEPROM
+
+
Owner Registration ID
-
-
-
-
- aaaaaaAA
-
+ ID de propietario
+
+
R E T A
- R E T A
+
+
+
R E A T
- R E A T
+
+
+
R T E A
- R T E A
+
+
+
R T A E
- R T A E
+
+
+
R A E T
- R A E T
+
+
+
R A T E
- R A T E
+
+
+
E R T A
- E R T A
+
+
+
E R A T
- E R A T
+
+
+
E T R A
- E T R A
+
+
+
E T A R
- E T A R
+
+
+
E A R T
- E A R T
+
+
+
E A T R
- E A T R
+
+
+
T R E A
- T R E A
+
+
+
T R A E
- T R A E
+
+
+
T E R A
- T E R A
+
+
+
T E A R
- T E A R
+
+
+
T A R E
- T A R E
+
+
+
T A E R
- T A E R
+
+
+
A R E T
- A R E T
+
+
+
A R T E
- A R T E
+
+
+
A E R T
- A E R T
+
+
+
A E T R
- A E T R
+
+
+
A T R E
- A T R E
+
+
+
A T E R
- A T E R
+
+
+
Power On Delay
-
+ Retraso de encendido
+
+
Jack Mode
-
+ Modo jack
+
+
Audio
-
+
+
+
Trainer
- Trainer
+ Entrenador
+
+
DMS
-
+
+
+
USB Mode
-
+ Modo USB
+
+
Power Off Delay
-
+ Retraso de apagado
+
+
+
+
Ask on Connect
-
+ Preguntar al conectar
+
+
Joystick (HID)
-
+ Joystick (HID)
+
+
USB Mass Storage
-
+ Almacenamiento USB
+
+
USB Serial (CDC)
-
+ USB Serial (CDC)
+
+
Stick Mode
- Modo Stick
+ Modo sticks
+
+
Metric
- Métrico
+ Métrico
+
+
Imperial
-
+ Imperial
+
+
Default Channel Order
- Orden Prederterminado Canales
+ Orden prederterminado canales
+
+
GPS Coordinates
- Coordenadas GPS
+ Coordenadas GPS
+
+
Min
-
+ Mín
+
+
+
+
v
-
+
+
+
Max
-
+ Máx
+
+
Inactivity Timer
- Tiempo de inactividad
+ Tiempo de inactividad
+
+
Show Splash Screen on Startup
- Mostrar Pantalla de Inicio al Enceder
+ Mostrar pantalla de inicio al encender
+
+
Contrast
- Contraste
+ Contraste
+
+
Battery Meter Range
-
+ Medidor de rango de batería
+
+
Haptic Strength
- Fuerza de Haptic
+ Fuerza de haptic
+
+
LCD Display Type
- Tipo de Pantalla LCD
+ Tipo de pantalla LCD
+
+
"No Sound" Warning
- Aviso "Sin Sonido"
+ Aviso "sin sonido"
+
+
Battery Warning
- Aviso de Bateria
+ Aviso de batería
+
+
Haptic Length
- Longitud Haptic
+ Duración haptic
+
+
MAVLink Baud Rate
- Transferencia Baud MAVLink
+ Velocidad de transmisión MAVLink
+
+
+
+
Quiet
- Silencio
+ Silencio
+
+
Only Alarms
- Solo Alarmas
+ Sólo alarmas
+
+
+
+
No Keys
- Sin teclas
+ No teclas
+
+
+
+
All
- Todo
+ Todo
+
+
Battery warning voltage.
This is the threashhold where the battery warning sounds.
Acceptable values are 5v..10v
- Voltaje de aviso de la batería.
+ Voltaje de aviso de la batería.
Este es el umbral cuando la batería emite sonidos de aviso.
Los valores aceptables son 5v..10v
+
+
Standard
- Estandar
+ Estándar
+
+
Optrex
-
+
+
+
If not zero will sound beeps if the transmitter has been left without inputs for the specified number of minutes.
- Si no es cero emitirá sonidos si el transmisor de deja sin pulsaciones surante el numero específico de minutos.
+ Si no es cero emitirá sonidos si el transmisor se deja sin pulsaciones durante el número específico de minutos.
+
+
+
+
+
+ nnnnnnNN
+
+
+
min
- min
+
+
+
+
+
Show splash screen on startup
- Mostrar pantalla de inicio al encender
+ Mostrar pantalla de inicio al encender
+
+
---
- ---
+
+
+
2s
- 2s
+
+
+
3s
- 3s
+
+
+
4s
- 4s
+
+
+
6s
- 6s
+
+
+
8s
- 8s
+
+
+
10s
- 10s
+
+
+
15s
- 15s
+
+
+
4800 Baud
-
+
+
+
9600 Baud
-
+
+
+
14400 Baud
-
+
+
+
19200 Baud
-
+
+
+
38400 Baud
-
+
+
+
57600 Baud
-
+
+
+
76800 Baud
-
+
+
+
115200 Baud
-
+
+
+
+
+
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -4712,7 +5651,7 @@ p, li { white-space: pre-wrap; }
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Switch warning - will alert if switches are not in their defaul position</p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Memory warning - will alert if there's not a lot of memory left</p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Silent mode warning - will alert you if the beeper is set to quiet (0)</p></body></html>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
@@ -4720,72 +5659,106 @@ p, li { white-space: pre-wrap; }
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Esto define los avisos al inicio.</p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Aviso de acelerador - te alertará sin el gas no esta en la posición inactiva</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Aviso de Switch - tealertará si los switches no están en su posición prederterminada</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Aviso de interruptor - te alertará si los interruptores no están en su posición prederterminada</p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Aviso de memoria - te alertará si no hay suficiente memoria libre</p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Aviso de silencio - te alertará si el beeper está en modo silencio (0)</p></body></html>
+
+
+
+
X-Short
- X-Corto
+ X-Corto
+
+
+
+
Short
- Corto
+ Corto
+
+
+
+
Normal
-
+
+
+
+
+
Long
- Largo
+ Largo
+
+
+
+
X-Long
- X-Largo
+ X-Largo
+
+
NMEA
-
+
+
+
Play Delay (switch mid position)
- Retardo de Play (switch en posición media)
+ Retardo de reproducción (interruptor en posición media)
+
+
Measurement Units
- Unidades de Medida
+ Unidades de medida
+
+
Haptic Mode
- Modo Haptic
+ Modo haptic
+
+
Beeper Length
- Longitud del beeper
+ Duración del beeper
+
+
Beeper Mode
- Modo Beeper
+ Modo beeper
+
+
Beeper volume
0 - Quiet. No beeps at all.
@@ -4793,18 +5766,20 @@ p, li { white-space: pre-wrap; }
2 - Normal.
3 - Loud.
4 - Extra loud.
- Volumen Beeper
+ Volumen beeper
0 - Silencio. Ningun tipo de beep.
-1 - Sin teclas. Los beeps suenan normal pero las teclas de menu no sonarán.
+1 - No teclas. Los beeps suenan normal pero las teclas de menu no sonarán.
2 - Normal.
3 - Alto.
4 - Extra Alto.
+
+
Alarms Only
- Solo Alarmas
+ Sólo alarmas
@@ -4812,129 +5787,131 @@ p, li { white-space: pre-wrap; }
OFF
-
+
Keys
- Teclas
+ Teclas
Sticks
-
+ Sticks
Keys + Sticks
- Teclas + Sticks
+ Teclas + Sticks
ON
- ON
+
English
- Inglés
+ Inglés
Dutch
-
+ Holandés
French
- Francés
+ Francés
Italian
- Italiano
+ Italiano
German
- Alemán
+ Alemán
Czech
- Checo
+ Checo
Slovak
- Eslovaco
+ Eslovaco
Spanish
- Español
+ Español
Polish
- Polaco
+ Polaco
Portuguese
- Portugués
+ Portugués
Russian
-
+ Ruso
Swedish
- Sueco
+ Sueco
Hungarian
-
+ Húngaro
No
- No
+
RotEnc A
-
+
Rot Enc B
-
+
Rot Enc C
-
+
Rot Enc D
-
+
Rot Enc E
-
+
If you enable FAI, only RSSI and RxBt sensors will keep working.
This function cannot be disabled by the radio.
Are you sure ?
-
+ Si activas FAI, sólo sensores RSSI and RxBt seguirán funcionando.
+Esta función no puede ser deshabilitada en la radio.
+¿ Estás seguro ?
@@ -4942,433 +5919,568 @@ Are you sure ?
No
- No
+
Yes, controled by a switch
- Si, controlado por un switch
+ Sí, controlado por un interruptor
Yes, controlled by a pot
- Si, controlado por un potenciómetro
+ Sí, controlado por un potenciómetro
Hardware
+
+
Form
-
-
-
-
- SQ
-
-
-
-
- SR
-
-
-
-
- LS2
-
-
-
-
- SP
-
-
-
-
- SO
-
-
-
-
- S4
-
-
-
-
- RS
-
-
-
-
- SB
-
-
-
-
- PPM 2
- PPM 2
-
-
-
- OFF
-
-
-
-
- S-Port Mirror
- S-Port Espejo
-
-
-
- Telemetry
- Telemetría
-
-
-
- SBUS Trainer
-
-
-
-
- Debug
- Depurar
-
-
-
- Rud
- Rud
-
-
-
- PPM 3
- PPM 3
-
-
-
- S1
-
-
-
-
- S2
-
-
-
-
- S3
-
-
-
-
- PPM 1
- PPM 1
-
-
-
- Serial Port
- Puerto Serie
-
-
-
- v
-
-
-
-
- PPM Multiplier
- Multiplicador PPM
-
-
-
- Current Offset
-
-
-
-
- PPM 4
- PPM 4
-
-
-
- SA
-
-
-
-
- Ele
- Ele
-
-
-
- Antenna
-
-
-
-
- S5
-
-
-
-
- Ail
- Ail
-
-
-
- Thr
- Thr
-
-
-
- SC
-
-
-
-
- LS
- LS
-
-
-
- SD
-
-
-
-
- Battery Offset
-
-
-
-
- SE
-
-
-
-
- SF
- SF
-
-
-
- SG
-
-
-
-
- SH
-
-
-
-
- SI
-
-
-
-
- SJ
-
-
-
-
- SK
-
+ Form
+
+
+ SQ
+
+
+
+
+
+
+ SR
+
+
+
+
+
+
+ LS2
+
+
+
+
+
+
+ SP
+
+
+
+
+
+
+ SO
+
+
+
+
+
+
+ S4
+
+
+
+
+
+
+ RS
+
+
+
+
+
+
+ SB
+
+
+
+
+
+
+ PPM 2
+
+
+
+
+
+
+ OFF
+
+
+
+
+
+
+ S-Port Mirror
+ S-Port
+
+
+
+
+
+ Telemetry
+ Telemetría
+
+
+
+
+
+ SBUS Trainer
+ Entrenador SBUS
+
+
+
+
+
+ Debug
+ Depuración
+
+
+
+
+
+ RTC Batt Check
+ Check Batería RTC
+
+
+
+
+
+ Rud
+
+
+
+
+
+
+ PPM 3
+
+
+
+
+
+
+ S1
+
+
+
+
+
+
+ S2
+
+
+
+
+
+
+ S3
+
+
+
+
+
+
+ PPM 1
+
+
+
+
+
+
+ Serial Port
+ Puerto Serie
+
+
+
+
+
+ v
+
+
+
+
+
+
+ PPM Multiplier
+ Multiplicador PPM
+
+
+
+
+
+ Current Offset
+ Offset actual
+
+
+
+
+
+ PPM 4
+
+
+
+
+
+
+ SA
+
+
+
+
+
+
+ Ele
+
+
+
+
+
+
+ Antenna
+ Antena
+
+
+
+
+
+ S5
+
+
+
+
+
+
+ Ail
+
+
+
+
+
+
+ Thr
+
+
+
+
+
+
+ SC
+
+
+
+
+
+
+ LS
+
+
+
+
+
+
+ SD
+
+
+
+
+
+
+ Battery Offset
+ Offset batería
+
+
+
+
+
+ SE
+
+
+
+
+
+
+ SF
+
+
+
+
+
+
+ SG
+
+
+
+
+
+
+ SH
+
+
+
+
+
+
+ SI
+
+
+
+
+
+
+ SJ
+
+
+
+
+
+
+ SK
+
+
+
+
+
+
SL
-
+
+
+
SM
-
+
+
+
SN
-
+
-
+
+
+
RS2
-
+
+
+
Bluetooth
-
+ Bluetooth
+
+
ADC Filter
-
+ Filtro ADC
+
+
Device Name:
-
+ Nombre dispositivo:
HardwarePanel
-
-
+
+
None
- Ninguno
+ Ninguno
2 Positions Toggle
-
+ 2 posiciones palanca
2 Positions
-
+ 2 posiciones
3 Positions
-
+ 3 posiciones
-
+
Pot with detent
-
+ Pos con fijador
-
+
Multipos switch
-
+ Interruptor multipos
-
+
Pot without detent
-
+ Pot sin fijador
-
+
Slider with detent
-
-
-
-
- OFF
-
-
-
-
- Enabled
-
-
-
-
- Telemetry
- Telemetría
+ Slider con fijador
+ OFF
+
+
+
+
+ Enabled
+ Activado
+
+
+
+ Telemetry
+ Telemetría
+
+
+
Trainer
- Trainer
+ Entrenador
-
+
Internal
-
+ Interno
-
+
Ask
-
+ Preguntar
-
+
Per model
-
+ Por modelo
-
+
Internal + External
-
+ Interno + Externo
-
+
External
-
+ Externo
Heli
+
+
Invert Elevator
- Invertir Elevador
+ Invertir elevador
+
+
Invert Aileron
- Invertir Aleron
+ Invertir alerón
+
+
Invert Collective
- Invertir Colectivo
+ Invertir colec.
+
+
Invert
Invertir
+
+
Off
+
+
120
+
+
120X
+
+
140
+
+
90
+
+
Long. cyc
-
+ Cíclico longitudinal
+
+
Lateral cyc
-
+ Cíclico lateral
+
+
Collective
Colectivo
+
+
Swash Type
- Tipo de Plato
+ Tipo de plato
+
+
Swash Ring
-
+ Plato
@@ -5376,22 +6488,22 @@ Are you sure ?
Throttle Channel:
- Canal de Acelerador:
+ Canal de acelerador:
Yaw Channel:
- Canal de Yaw:
+ Canal de viraje:
Pitch Channel:
- Canal de pitch:
+ Canal de inclinación:
Roll Channel:
- Canal de roll:
+ Canal de balanceo:
@@ -5399,19 +6511,20 @@ Are you sure ?
Invalid EEPROM File %1
- Archivo EEPROM inválido %1
+ Archivo EEPROM no válido %1
Cannot open file %1:
%2.
-
+ No se puede abrir el archivo %1:
+%2.
Error writing file %1:
%2.
- Error escribiendo el archivo %1:
+ Error escribiendo el archivo %1:
%2.
@@ -5421,30 +6534,30 @@ Are you sure ?
Move Up
- Mover Arriba
+ Mover arriba
Ctrl+Up
-
+ Ctrl+Arriba
Move Down
- Mover Abajo
+ Mover abajo
Ctrl+Down
-
+ Ctrl+Abajo
Clear All Inputs
- Limpiar Todas las entradas
+ Limpiar todas las entradas
@@ -5454,7 +6567,7 @@ Are you sure ?
Delete Selected Inputs?
- ¿Borrar las Entradas Seleccionadas?
+ ¿Borrar las entradas seleccionadas?
@@ -5474,7 +6587,7 @@ Are you sure ?
Enter
-
+ Intro
@@ -5494,7 +6607,7 @@ Are you sure ?
Ctrl+C
- Ctrl+C
+
@@ -5504,7 +6617,7 @@ Are you sure ?
Ctrl+X
- Ctrl+X
+
@@ -5542,17 +6655,17 @@ Are you sure ?
INV
- INV
+
NOR
- NOR
+
CH
-
+
@@ -5560,7 +6673,7 @@ Are you sure ?
GV
- GV
+
@@ -5568,122 +6681,122 @@ Are you sure ?
---
- ---
+
a>x
-
+
a<x
-
+
|a|>x
-
+
|a|<x
-
+
AND
-
+
OR
-
+
XOR
-
+
a=b
-
+
a!=b
-
+
a>b
-
+
a<b
-
+
a>=b
-
+
a<=b
-
+
d>=x
-
+
|d|>=x
-
+
a=x
-
+
a~x
-
+
Timer
- Temporizador
+ Temporizador
Sticky
-
+ Pegajoso
Edge
-
+ Borde
Unknown
- Desconocido
+ Desconocido
L
-
+
LSW
-
+
@@ -5716,22 +6829,22 @@ Are you sure ?
AND Switch
-
+ Interruptor AND
Popup menu available
-
+ Menú emergente disponible
(instant)
-
+ (instante)
(infinite)
-
+ (infinito)
@@ -5758,172 +6871,192 @@ Are you sure ?
LogsDialog
+
+
Companion Log Viewer
- Visor de registros de Companion
+ Visor de registros de Companion
+
+
Filename
- Nombre Archivo
+ Nombre archivo
+
+
Open LogFile
- Abrir archivo Registros
+ Abrir archivo registros
+
+
Zoom
-
+ Zoom
+
+
Save session CSV
-
+ Guardar sesión CSV
+
+
X
-
+
+
+
Y
-
+
+
+
Reset
- Resetear
+ Resetear
+
+
Fly sessions
- Sesiones de vuelo
+ Sesiones de vuelo
Telemetry logs
- Registros de telemetría
+ Registros de telemetría
Time (hh:mm:ss)
- Hora (hh:mm:ss)
+ Hora (hh:mm:ss)
Plot Title Change
-
+ Cambia título de plot
New plot title:
-
+ Nuevo título de plot:
Axis Label Change
-
+ Cambia etiqueta de eje
New axis label:
-
+ Nueva etiqueta de eje:
Graph Name Change
-
+ Cambia nombre gráfico
New graph name:
-
+ Nuevo nombre gráfico:
Error: no GPS data found
-
+ Error: datos de GPS no encontrados
The column containing GPS coordinates must be named "GPS".
The columns for altitude "GAlt" and for speed "GSpd" are optional
-
+ La columna conteniendo las coordenadas GPS debe llamarse "GPS".
+
+Las columnas para altitud "GAlt" y para velocidad "GSpd" son opcionales
Cannot write file %1:
%2.
- No se puede escribir el archivo %1:
+ No se puede escribir el archivo %1:
%2.
Cursor A: %1 m
-
+ Cursor A: %1 m
Cursor B: %1 m
-
+ Cursor B: %1 m
Time delta: %1
-
+ Tiempo delta: %1
Climb rate: %1 m/s
-
+ Velocidad de ascenso: %1 m/s
Select your log file
- Selecciona tu archivo de registros
+ Selecciona tu archivo de registros
Available fields
- Campos disponibles
+ Campos disponibles
The selected logfile contains %1 invalid lines out of %2 total lines
- El archivo de registros elegido contiene %1 lineas inválidas de un total de %2 lineas
+ El archivo de registros elegido contiene %1 líneas inválidas de un total de %2 líneas
- total duration
-
+ time span
+ lapso de tiempo
duration
-
+ duración
(L1)
-
+
(R1)
-
+
(L2)
-
+
(R2)
-
+
@@ -5932,13 +7065,13 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
File loaded
- Archivo Cargado
+ Archivo cargado
Save As
- Guardar Como
+ Guardar como
@@ -5969,24 +7102,24 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
Archivo guardado
-
+
Read Models and Settings From Radio
- Leer los Modelos y Ajustes de la Radio
+ Leer los modelos y ajustes de la radio
Save Radio Backup to File
- Guardar Copia deSeguridad de la Radio a un Archivo
+ Guardar copia de seguridad de la radio a un archivo
Read Radio Firmware to File
- Leer el Firmware de la Radio a un Archivo
+ Leer el firmware de la radio a un archivo
OpenTX Home Page: <a href='%1'>%1</a>
-
+ OpenTX Home Page: <a href='%1'>%1</a>
@@ -6008,18 +7141,18 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
Compilation server too busy, try later
- Servidor de compilación demasiado ocupado, inténtalo mas tarde
+ Servidor de compilación demasiado ocupado, inténtalo más tarde
Unknown server failure, try later
- Fallo desconocido de servidor, inténtalo mas tarde
+ Fallo desconocido de servidor, inténtalo más tarde
Yes
- Si
+ Sí
@@ -6031,83 +7164,83 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
Release Notes
- Notas de la Versión
+ Notas de la versión
-
+
Open Models and Settings file
- Abrir archivo de Modelos y Ajustes
+ Abre archivo de modelos y ajustes
-
+
New
Nuevo
-
+
Open...
Abrir...
-
+
Save
Guardar
-
+
Save As...
- Guardar Como...
+ Guardar como...
-
+
Compare models
Comparar modelos
-
+
Exit the application
- Salir de la aplicación
+ Sale de la aplicación
-
+
List available programmers
Lista de programadores disponibles
-
+
Show fuses dialog
-
+ Muestra ventane de fusibles
-
+
Show the application's About box
- Mostrar la ventana de aplicación Acerca de
+ Muestra la ventana de aplicación Acerca de
-
+
Set Menu Language
- Menú Ajuste Lenguaje
+ Lenguaje
-
+
Write
Escribir
-
+
%2
- %2
+
-
+
Alt+%1
-
+
-
+
New Radio
- Nueva Radio
+ Nueva radio
@@ -6117,7 +7250,7 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
Do you want to write the firmware to the radio now ?
- ¿Te gustaría escribir el firmware a la radio ahora?
+ ¿Te gustaría escribir el firmware en la radio ahora?
@@ -6130,421 +7263,423 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
Acerca de Companion
-
+
A monochrome black icon theme
Tema de icono monocromo negro
-
+
A monochrome white icon theme
Tema de icono monocromo blanco
-
+
A monochrome blue icon theme
Tema de icono monocromo azul
Diskimage (*.dmg)
-
+ Imagen de disco(*.dmg)
Would you like to open the disk image to install the new version?
-
+ ¿Quieres abrir la imagen del disco para instalar la nueva versioń?
A new release of Companion is available, please check the <a href='%1'>OpenTX website!</a>
-
+ Una nueva versión de Companion está disponible, por favor visita <a href='%1'>OpenTX website!</a>
There are unsaved file changes which you may lose when switching radio types.
Do you wish to continue?
-
+ Hay cambios sin guardar en el archivo que se perderán al cambiar de tipo de radio.
+
+¿Quieres continuar?
No local SD structure path configured!
-
+ ¡No configurada la ruta a la estructura SD local!
No Radio or SD card detected!
-
+ ¡No radio o tarjeta SD detectada!
-
+
Close
- Cerrar
+ Cerrar
-
+
Close Models and Settings file
-
+ Cierra el archivo de modelos y ajustes
-
+
List of recently used files
-
+ Lista de los archivos recientes
-
+
Radio Profiles
-
+ Perfiles de radio
-
+
Create or Select Radio Profiles
-
+ Crea o selecciona perfiles de radio
-
+
Release notes...
-
+ Notas de la versión...
-
+
Show release notes
-
+ Muestra notas de la versión
-
+
Create a new Radio Settings Profile
-
+ Crea un nuevo perfil de ajustes de radio
-
+
Copy Current Radio Profile
-
+ Copiar el perfil de radio actual
-
+
Duplicate current Radio Settings Profile
-
+ Duplica el perfil de radio actual
-
+
Delete Current Radio Profile...
-
+ Borrar el perfil de radio actual...
-
+
Delete the current Radio Settings Profile
-
+ Borra los ajustes actuales del perfil de radio actual
-
+
Export Application Settings..
-
+ Exportar ajustes aplicación...
-
+
Save all the current %1 and Simulator settings (including radio profiles) to a file.
-
+ Guarda los ajustes actuales de %1 y del simulador (incluyendo perfiles de radio) a un archivo
-
+
Import Application Settings..
-
+ Importar ajustes de la aplicación...
-
+
Load %1 and Simulator settings from a prevously exported settings file.
-
+ Carga los ajustes de %1 y del simulador desde un fichero de ajustes exportado previamente
-
- Tabbed Windows
-
-
-
-
+
Use tabs to arrange open windows.
-
+ Usa las pestañas para organizar las ventanas abiertas
-
+
+ Tabbed Windows
+ Ventanas con pestañas
+
+
+
Tile Windows
-
+ Ventanas en cascada
-
+
Arrange open windows across all the available space.
-
+ Organiza las ventanas en todo el espacio disponible
-
+
Cascade Windows
-
+ Ventanas en cascada
-
+
Arrange all open windows in a stack.
-
+ Organiza todas las ventanas abiertas en una cascada
-
+
Close All Windows
-
+ Cierra todas las ventanas
-
+
Closes all open files (prompts to save if necessary.
-
+ Cierra todos los archivos abiertos (pregunta guardar si es necesario)
-
+
Window
-
-
-
-
- Ctrl+Shift+S
-
-
-
-
- Ctrl+Alt+L
-
+ Ventana
+ Ctrl+Shift+S
+
+
+
+
+ Ctrl+Alt+L
+
+
+
+
Ctrl+Alt+D
-
+
-
+
Ctrl+Alt+R
-
+
-
+
Small
Pequeño
-
+
Use small toolbar icons
- Usar iconos pequeños en la barra de herramientas
+ Usa iconos pequeños en la barra de herramientas
-
+
Use normal size toolbar icons
- Usar iconos normales en la barra de herramientas
+ Usa iconos normales en la barra de herramientas
-
+
Normal
-
+ Normal
-
+
Use big toolbar icons
- Usar iconos grandes en la barra de herramientas
+ Usa iconos grandes en la barra de herramientas
-
+
Big
Grande
-
+
Use huge toolbar icons
- Usar iconos extra grandes en la barra de herramientas
+ Usa iconos extra grandes en la barra de herramientas
-
+
Huge
Extra Grande
-
+
- Copy
-
+ - Copiar
-
+
Companion :: Open files warning
-
+ Companion :: advertencia de archivos abiertos
-
+
Please save or close modified file(s) before deleting the active profile.
-
+ Por favor guarda o cierra los archivos modificados antes de borrar el perfil activo.
-
+
Not possible to remove profile
- No es posible eliminar el perfil
+ No se puede eliminar el perfil
-
+
The default profile can not be removed.
- El perfil prederterminado no se puede eliminar.
+ El perfil prederterminado no se puede eliminar.
-
+
Confirm Delete Profile
-
+ Confirma borrar perfil
-
+
Are you sure you wish to delete the "%1" radio profile? There is no way to undo this action!
-
+ ¿Seguro que quieres borrar el perfil de radio "%1"? ¡Esta acción no se puede deshacer!
-
+
Please save or close all modified files before importing settings
-
+ Por favor guarda o cierra todos los archivos modificados antes de importar ajustes
-
+
<html><p>%1 and Simulator settings can be imported (restored) from a previosly saved export (backup) file. This will replace current settings with any settings found in the file.</p><p>An automatic backup of the current settings will be attempted. But if the current settings are useful then it is recommended that you make a manual backup first.</p><p>For best results when importing settings, <b>close any other %1 windows you may have open, and make sure the standalone Simulator application is not running.</p><p>Do you wish to continue?</p></html>
-
+ <html><p>Los ajustes de %1 y del simulador pueden ser importados (restaurar) desde archvo exportado previamente (copia de seguridad). Esto reemplazará los ajustes actuales con los ajustes del archivo.</p><p>Se realizará automáticamente una copia de seguridad de los ajustes actuales. Pero si los ajustes actuales son útiles se recomienda que hagas una copia de seguridad manual primero.</p><p>Para los mejores resultados al importar ajustes, <b>cierra otras ventanas de %1 que tengas abiertas, y asegúrate que la aplicación del simulador no se está ejecutando.</p><p>¿Quieres continuar?</p></html>
-
+
Confirm Settings Import
-
-
-
-
- Select %1:
-
-
-
-
- backup
-
+ Confirma importar ajustes
+ Select %1:
+ Selecciona %1
+
+
+
+ backup
+ copia de seguridad
+
+
+
Press the 'Ignore' button to continue anyway.
-
+ Presiona el botón de 'Ignorar' para continuar de todos modos.
-
+
The settings could not be imported.
-
-
-
-
- <html><p>New settings have been imported from:<br> %1.</p><p>%2 will now re-initialize.</p><p>Note that you may need to close and restart %2 before some settings like language and icon theme take effect.</p>
-
+ Los ajustes no han podido ser importados.
+ <html><p>New settings have been imported from:<br> %1.</p><p>%2 will now re-initialize.</p><p>Note that you may need to close and restart %2 before some settings like language and icon theme take effect.</p>
+ <html><p>Nuevos ajustes han sido importados desde:<br> %1.</p><p>%2 ahora se reiniciará.</p><p>Ten en cuenta que puedes necesitar cerrar y reiniciar %2 antes de que algunos ajustes como el lenguaje y el tema de iconos se hagan efectivos.</p>
+
+
+
<p>The previous settings were backed up to:<br> %1</p>
-
+ <p>Los ajustes anteriores fueron guardados en:<br> %1</p>
Not enough flash available on this board for all the selected options
-
+ No hay suficiente flash en esta placa para todas las opciones seleccionadas
Compilation server temporary failure, try later
-
+ Fallo temporal del servidor de compilación, intentalo más tarde
Compilation error
-
+ Error de compilación
Invalid firmware
-
+ Firmware no válido
Invalid board
-
+ Placa no válida
Invalid language
-
+ Lenguaje no válido
-
+
Some text will not be translated until the next time you start Companion. Please note that some translations may not be complete.
-
+ Algunos textos no serán traducidos hasta que reinicie Companion. Por favor ten en cuenta que algunas traducciones no están completas.
Models and Settings read
-
+ Lee modelos y ajustes
No Companion release candidates are currently being served for this version, please switch release channel
-
+ Actualmente no hay release candidates de Companion disponibles para esta versión, por favor cambia el canal de distribución
No nightly Companion builds are currently being served for this version, please switch release channel
-
+ Actualmente no hay nightly builds de Companion disponibles para esta versión, por favor cambia el canal de distribución
No Companion release builds are currently being served for this version, please switch release channel
-
+ Actualmente no hay distribuciones de Companion disponibles para esta versión, por favor cambia el canal de distribución
Companion update check failed, new version information not found.
-
+ El chequeo de la actualización de Companion ha fallado, la información de la nueva versión no se ha encontrado.
No firmware release candidates are currently being served for this version, please switch release channel
-
+ Actualmente no hay releases candidates de firmware disponibles para esta versión, por favor cambia el canal de distribución
No firmware nightly builds are currently being served for this version, please switch release channel
-
+ Actualmente no hay nightly builds de firmware disponibles para esta versión, por favor cambia el canal de distribución
No firmware release builds are currently being served for this version, please switch release channel
-
+ Actualmente no hay distribuciones de firmware disponibles para esta versión, por favor cambia el canal de distribución
Release candidate builds are now available for this version, would you like to switch to using them?
-
+ Ya hay disponibles release candidates para esta versión, ¿quieres cambiar para usarlas?
Channel changed to RC, please restart the download process
-
+ Canal cambiado a RC, por favor reinicia el proceso de descarga
Official release builds are now available for this version, would you like to switch to using them?
-
+ Ya hay disponibles distribuciones oficiales para esta versión, ¿quieres cambiar para usarlas?
Channel changed to Release, please restart the download process
-
+ Canal cambiado a Release, por favor reinicia el proceso de descarga
This radio (%1) is not currently available in this firmware release channel
-
+ Actualmente la radio (%1) no está disponible en este canal de distribución
Firmware update check failed, new version information not found or invalid.
-
+ El chequeo de la actualización del firmware ha fallado, la información de la versión no se ha encontrado o no es válida.
@@ -6553,34 +7688,38 @@ Version %2 is available.
Do you want to download it now?
We recommend you view the release notes using the button below to learn about any changes that may be important to you.
-
+ El firmware %1 parece que no se ha descargado anteriormente:
+La versión %2 está disponible.
+¿Quieres descargarla ahora?
+
+Te recomendamos que revises las notas de la versión usando el botón de abajo para los ver cambios que puedan ser importantes para tí.
Do you want to download version %1 now ?
-
+ ¿Quieres descargar ahora la versión %1?
Ignore this version %1?
-
+ ¿Ignorar esta versión %1?
Local Folder
-
+ Carpeta local
Radio Folder
-
+ Carpeta de radio
This function is not yet implemented
-
+ Esta función aún no está implementada
@@ -6593,68 +7732,68 @@ We recommend you view the release notes using the button below to learn about an
Derechos de autor del equipo OpenTX
-
+
Create a new Models and Settings file
- Crear un nuevo archivo de Modelos y Ajustes
+ Crea un nuevo archivo de modelos y ajustes
-
-
+
+
Save Models and Settings file
- Guardar el archivo de Modelos y Ajustes
+ Guarda el archivo de modelos y ajustes
-
+
Exit
Salir
-
+
Use default system language.
-
+ Usa el lenguaje predeterminado del sistema.
-
+
Use %1 language (some translations may not be complete).
-
+ Usa lenguaje %1 (algunas traducciones pueden no estar completas)
-
+
Classical
- Clasico
+ Clásico
-
+
The classic companion9x icon theme
- Tema de iconos clasicos de companion9x
+ Tema de iconos clásicos de companion9x
-
+
Yerico
-
+ Yerico
-
+
Yellow round honey sweet icon theme
Tema de iconos amarillo miel redondo
-
+
Monochrome
Monocromo
-
+
MonoWhite
MonoBlanco
-
+
MonoBlue
MonoAzul
-
+
System language
Lenguaje del sistema
@@ -6667,231 +7806,237 @@ We recommend you view the release notes using the button below to learn about an
Do you want to download it now?
We recommend you view the release notes using the button below to learn about any changes that may be important to you.
-
+ Una nueva versión del firmware %1 está disponible:
+ - actual es %2
+ - nuevo es %3
+
+¿Quieres descargar ahora?
+
+Te recomendamos que revises las notas de la versión usando el botón de abajo para los ver cambios que puedan ser importantes para tí.
-
+
Synchronize SD
-
+ Sincronizar SD
-
+
OpenTX Companion %1 - Radio: %2 - Profile: %3
-
+ OpenTX Companion %1 - Radio: %2 - Perfil: %3
-
+
About...
Acerca de...
-
+
View Log File...
- Ver Archivo de Registro...
+ Ver archivo de registro...
-
+
Open and view log file
- Abrir y ver el archivo de registro
+ Abre el archivo de registro
-
+
Settings...
Ajustes...
-
+
Edit Settings
- Editar Ajustes
+ Edita ajustes
-
+
Download...
Descargar...
-
+
Download firmware and voice files
- Descargar los archivos de firmware y voces
+ Descarga los archivos de firmware y voces
-
+
Check for Updates...
- Comprobar Actualizaciones...
+ Comprobar actualizaciones...
-
+
Check OpenTX and Companion updates
- Comprobar la actualizaciones de OpenTX y Companion
+ Comprueba las actualizaciones de OpenTX y Companion
-
+
Compare Models...
- Comparar Modelos...
+ Comparar modelos...
-
+
Edit Radio Splash Image...
- Editar Imagen de Inicio de la Radio...
+ Editar imagen de inicio de la radio...
-
+
Edit the splash image of your Radio
Editar la imagen de inicio de tu radio
-
+
List programmers...
Lista de programadores...
-
+
Fuses...
-
+ Fusibles...
-
- Read Firmware from Radio
- Leer Firmware desde la Radio
-
-
-
- Read firmware from Radio
- Leer firmware desde la Radio
-
-
-
- Write Firmware to Radio
- Escribir Firmware a la Radio
-
-
-
- Write firmware to Radio
- Escribir firmware a la Radio
-
-
-
- Add Radio Profile
- Añadir perfil de Radio
-
-
-
- Manuals and other Documents
- Manuales y otros Documentos
-
-
-
- Open the OpenTX document page in a web browser
- Abrir la página de documentación de OpenTX en un navegador
-
-
-
- Write Models and Settings To Radio
- Escribir Modelos y Ajustes a la Radio
-
-
-
- Write Models and Settings to Radio
- Escribir Modelos y Ajustes a la Radio
-
-
-
- Read Models and Settings from Radio
- Leer los Modelos y Ajustes de la Radio
+ Read Firmware from Radio
+ Leer firmware de la radio
+
+
+
+ Read firmware from Radio
+ Leer firmware de la radio
- Configure Communications...
- Configurar Comunicaciones...
+ Write Firmware to Radio
+ Escribir firmware a la radio
- Configure software for communicating with the Radio
- Configurar software para la comunicación con la Radio
+ Write firmware to Radio
+ Escribir firmware a la radio
-
- Write Backup to Radio
- Escribir Copia de Seguridad a la Radio
-
-
-
- Write Backup from file to Radio
- Escribir Copia de Seguridad desde un archivo a la Radio
-
-
-
- Backup Radio to File
- Copia de Seguridad de la Radio a un Archivo
-
-
-
- Save a complete backup file of all settings and model data in the Radio
- Guardar una copia de seguridad completa de todos los datos de ajustes y modelos en la Radio
+
+ Add Radio Profile
+ Añadir perfil de radio
+ Manuals and other Documents
+ Manuales y otros documentos
+
+
+
+ Open the OpenTX document page in a web browser
+ Abre la página de documentación de OpenTX en un navegador
+
+
+
+ Write Models and Settings To Radio
+ Escribir modelos y ajustes a la radio
+
+
+
+ Write Models and Settings to Radio
+ Escribir modelos y ajustes a la radio
+
+
+
+
+ Read Models and Settings from Radio
+ Leer los modelos y ajustes de la radio
+
+
+
+ Configure Communications...
+ Configurar comunicaciones...
+
+
+
+ Configure software for communicating with the Radio
+ Configura software para la comunicación con la radio
+
+
+
+ Write Backup to Radio
+ Escribir copia de seguridad a la radio
+
+
+
+ Write Backup from file to Radio
+ Escribir copia de seguridad desde un archivo a la radio
+
+
+
+ Backup Radio to File
+ Copia de seguridad de la radio a un archivo
+
+
+
+ Save a complete backup file of all settings and model data in the Radio
+ Guardar una copia de seguridad completa de todos los datos de ajustes y modelos en la radio
+
+
+
Contributors...
Contribuidores...
-
+
A tribute to those who have contributed to OpenTX and Companion
Un tributo a aquellos que han contribuido en OpenTX y Companion
-
+
SD card synchronization
-
+ Sincronización de la tarjeta SD
-
+
Recent Files
- Archivos Recientes
+ Archivos recientes
-
- Set Icon Theme
- Selecciona el Tema de Iconos
-
-
-
- Set Icon Size
- Selecciona el Tamaño de Iconos
-
-
-
+ Set Icon Theme
+ Tema de iconos
+
+
+
+ Set Icon Size
+ Tamaño de iconos
+
+
+
+
File
Archivo
-
-
+
+
Edit
Editar
-
+
Settings
Ajustes
-
+
Read/Write
Leer/Escribir
-
-
+
+
Help
Ayuda
-
+
Ready
Listo
@@ -6899,63 +8044,58 @@ We recommend you view the release notes using the button below to learn about an
MdiChild
-
+
Editing model %1:
Editando modelo %1:
Delete
- Borrar
+ Borrar
Move to Category
-
+ Mover a categoría
Alt+S
-
+
-
+
Do you want to overwrite radio general settings?
- ¿Quieres sobreescribir los ajustes generales de la radio?
+ ¿Quieres sobreescribir los ajustes generales de la radio?
-
+
This category is not empty!
-
+ ¡Esta categoría no está vacía!
-
+
New model
Translators: do NOT use accents here, this is a default model name.
-
+ Nuevo modelo
-
+
<p><b>Currently selected radio type (%1) is not compatible with file %3 (from %2), models and settings need to be converted.</b></p>
-
+ ><p><b>El tipo actualmente seleccionado de radio (%1) no es compatible con el archivo %3 (de %2), los modelos y ajustes necesitan ser convertidos.</b></p>
-
- Unable to find Horus radio SD card!
-
-
-
-
+
Models and Settings written
-
+ Modelos y ajustes escritos
-
+
Unable to find file %1!
- ¡No es posible encontrar el archivo %1!
+ ¡No se puede encontrar el archivo %1!
-
+
Error reading file %1:
%2.
Error leyendo el archivo %1:
@@ -6969,303 +8109,313 @@ We recommend you view the release notes using the button below to learn about an
Alt+Shift+E
-
+
Ctrl+Alt+C
-
+
Ctrl+Alt+V
-
+
Alt+Shift+S
-
+
Alt+C
-
+
Alt+A
-
+
Alt+R
-
+
Alt+W
-
+
Alt+U
-
+
%n Model(s)
As in "Copy 3 Models" or "Cut 1 Model" or "Delete 3 Models" action).
-
-
-
+
+ %n modelo
+ %n modelos
%n Model(s)
As in "Paste 3 Models" or "Insert 1 Model."
-
-
-
+
+ %n modelo
+ %n modelos
%n Category(ies)
As in "Delete 3 Categories" or "Delete 1 Category."
-
-
-
+
+ %n categoría
+ %n categorías
Nothing selected
-
+ Nada seleccionado
Rename Category
-
+ Renombrar categoría
Edit Model
-
+ Editar modelo
Cut
-
+ Cortar
Copy
-
+ Copiar
Paste
-
+ Pegar
Insert
-
+ Insertar
Edit Radio Settings
-
+ Editar ajustes de radio
Copy Radio Settings
-
+ Copiar ajustes de radio
Paste Radio Settings
-
+ Pegar ajustes de radio
Simulate Radio
-
+ Simular radio
Add Category
-
+ Añadir categoría
Category
-
+ Categoría
Add Model
-
+ Añadir modelo
Model
- Modelo
+ Modelo
Restore from Backup
-
+ Restaurar desde copia de seguridad
Model Wizard
- Asistente Modelos
+ Asistente modelos
Set as Default
-
+ Fijar como predeterminado
Print Model
-
+ Imprimir modelo
Simulate Model
-
+ Simular modelo
Duplicate Model
-
+ Duplicar modelo
Show Category Actions Toolbar
-
+ Muestra barra de acciones de categoría
Show Radio Actions Toolbar
-
+ Muestra barra de acciones de radio
Show Model Actions Toolbar
-
+ Muestra barra de acciones de modelo
-
+
+ read only
+ solo lectura
+
+
+
New category
Translators do NOT use accent for this, this is the default category name on Horus.
-
+ Nueva categoria
-
+
Category index out of range.
-
+ Índice de categoría fuera de rango.
-
+
Cannot delete the last category.
-
+ No se puede eliminar la última categoría.
-
+
Cannot insert model, last model in list would be deleted.
-
+ No se puede insertar el modelo, no hay slots de modelo disponibles.
-
+
Cannot add model, could not find an available model slot.
-
+ No se puede añadir el modelo, no hay slots de modelo disponibles.
-
+
Cannot paste model, out of available model slots.
-
+ No se puede pegar el modelo, no hay slots de modelo disponibles.
-
+
You are replacing an existing model, are you sure?
-
+ Estás reemplazando un modelo existente, ¿estás seguro?
-
+
Delete %n selected model(s)?
-
-
-
+
+ ¿Borrar %n modelo seleccionado?
+ ¿Borrar %n modelos seleccionados?
-
+
Delete %n selected category(ies)?
-
-
-
+
+ ¿Borrar %n categoría seleccionada?
+ ¿Borrar %n categorías seleccionadas?
-
+
Cannot duplicate model, could not find an available model slot.
-
+ No se puede duplicar el modelo, no hay un slot de modelo disponibles.
-
+
Do you wish to continue with the conversion?
-
+ ¿Quieres continuar la conversión?
-
+
Choose <i>Apply</i> to convert the file, or <i>Close</i> to close it without conversion.
-
+ Elige <i>Aplicar</i> para convertir el archivo, o <i>Cerrar</i> para cerrar sin conversión.
-
+
<b>The conversion generated some important messages, please review them below.</b>
-
+ <b>La conversión ha generado mensajes importantes, por favor revísalos.</b>
-
+
Companion :: Conversion Result for %1
-
+ Companion :: Resultado de la conversión para %1
-
+
+ Unable to find radio SD card!
+ ¡No se puede encontrar la tarjeta SD de la radio!
+
+
+
Error opening file %1:
%2.
Error abriendo el archivo %1:
%2.
-
+
Save As
- Guardar Como
+ Guardar como
-
+
Open backup Models and Settings file
- Abrir archivo de copia de seguridad de Modelos y Ajustes
+ Abre archivo de copia de seguridad de modelos y ajustes
-
+
%1 has been modified.
Do you want to save your changes?
%1 ha sido modificado.
¿Quieres guardar los cambios?
-
+
Invalid binary backup File %1
- Archivo binariode copia de seguridad inválido %1
+ Archivo binariode copia de seguridad no válido %1
-
+
Cannot write temporary file!
¡No se puede escribir el archivo temporal!
@@ -7275,23 +8425,27 @@ Do you want to save your changes?
MIX
-
+
(@%1)
-
+
MixerDialog
+
+
Dialog
Mezclas
+
+
Source
Fuente
@@ -7300,71 +8454,107 @@ Do you want to save your changes?
+
+
+
+
+
+
+
+
The source for the mixer
- LA fuente de la mezcla
+ La fuente de la mezcla
+
+
Weight
- Carga
+ Peso
+
+
+
+
+
+
GV
-
+ GV
+
+
Switch used by the mix.
If blank then the mix is considered to be "ON" all the time.
The value of the mixer is multiplied by this value and divided by 100.
- Switch usado por la mezcla.
+ Interruptor usado por la mezcla.
Si está en blanco entonces la mezcla se considera que está activa todo el tiempo.
+
+
Offset
-
+ Offset
+
+
Include Trim
- Incluir Trim
+ Incluir trim
+
+
Curve
Curva
+
+
The curve used by the mix
La curva usada por la mezcla
+
+
Switch
-
+ Interruptor
+
+
Yes
- Si
+ Sí
+
+
No
- No
+
+
+
Warning
Aviso
+
+
Name
Nombre
@@ -7373,6 +8563,14 @@ Si está en blanco entonces la mezcla se considera que está activa todo el tiem
+
+
+
+
+
+
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -7384,44 +8582,57 @@ p, li { white-space: pre-wrap; }
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -> the value states the number of seconds it takes to transit from -100 to 100.</p></body></html>
-
+
+
+
Mixer warning.
Setting this value will cause a beep to be emmitted when this value is active.
- Sellecionar este valor provocará un beep emitido cuando este activo.
Aviso del mezclador.
-
+Selecionar este valor provocará un beep cuando el valor esté activo.
+
+
OFF
APAGADO
+
+
1 Beep
+
+
2 Beep
2 Beeo
+
+
3 Beep
+
+
Multiplex
- Opciones
+
+
+
Multiplexer
This determines how mixer values are added.
@@ -7429,9 +8640,9 @@ This determines how mixer values are added.
"+" means the value of the current mix is added to the previous mixes in the same channel.
"*" means the value of the current mix is amultiplied with the previous mixes in the same channel.
"R" means the value replaces the previous values. If the switch is off the value will be ignored.
- Opciones
+ Multiplexer
-Esto determina como los valores de mezcla son añadidos.
+Esto determina cómo los valores de mezcla son añadidos.
"+" significa que el valor de la mezcla actual es añadido a la mezcla previa en el mismo canal.
"*" significa que el valor de la mezcla actual es multiplicada por la mezcla previa en el mismo canal
@@ -7439,73 +8650,91 @@ Esto determina como los valores de mezcla son añadidos.
+
+
ADD
AÑADIR
+
+
MULTIPLY
MULTIPLICAR
+
+
REPLACE
REEMPLAZAR
+
+
Flight modes
Modos de vuelo
+
+
Include DR/Expo
- Incluye DR/Expo
+ IncluirDR/Expo
+
+
Delay
Retardo
+
+
Slow
Lento
+
+
Up
Arriba
+
+
Down
Abajo
DEST -> %1
-
+
Click to access popup menu
-
+ Pulsa para acceder el menú emergente
Clear All
-
+ Limpiar todo
Set All
-
+ Fijar todo
Invert All
-
+ Ivertir todo
@@ -7513,22 +8742,22 @@ Esto determina como los valores de mezcla son añadidos.
Increase font size
-
+ Aumentar tamaño de fuente
Decrease font size
-
+ Reducir tamaño de fuente
Default font size
-
+ Tamaño de fuente predeterminado
Ctrl+0
-
+
@@ -7537,7 +8766,7 @@ Esto determina como los valores de mezcla son añadidos.
Move Up
- Mover Arriba
+ Mover arriba
@@ -7549,7 +8778,7 @@ Esto determina como los valores de mezcla son añadidos.
Move Down
- Mover Abajo
+ Mover abajo
@@ -7590,12 +8819,12 @@ Esto determina como los valores de mezcla son añadidos.
Enter
- Enter
+ Intro
&Toggle highlight
- &Seleccionar Palanca
+ &Seleccionar palanca
@@ -7668,18 +8897,20 @@ Esto determina como los valores de mezcla son añadidos.
Model:
-
+ Modelo:
Throttle Source
- Fuente del acelerador
+ Fuente del acelerador
ModelEdit
+
+
Dialog
Mensaje
@@ -7691,7 +8922,7 @@ Esto determina como los valores de mezcla son añadidos.
Heli
-
+ Heli
@@ -7701,7 +8932,7 @@ Esto determina como los valores de mezcla son añadidos.
Logical Switches
- Switches lógicos
+ Interruptor lógicos
@@ -7711,7 +8942,7 @@ Esto determina como los valores de mezcla son añadidos.
Outputs
- Salidas
+ Salidas
@@ -7735,6 +8966,8 @@ Esto determina como los valores de mezcla son añadidos.
+
+
Simulate
Simular
@@ -7744,102 +8977,102 @@ Esto determina como los valores de mezcla son añadidos.
Exponential
- Exponencial
+ Exponencial
Extra Fine
- Extra Fino
+ Extra Fino
Fine
- Fino
+ Fino
Medium
- Medio
+ Medio
Coarse
- Duro
+ Duro
Unknown
- Desconocido
+ Desconocido
Slave/Jack
-
+ Slave/Jack
Master/SBUS Module
-
+ Módulo Master/SBUS
Master/CPPM Module
-
+ Módulo Master/CPPM
Master/SBUS in battery compartment
-
+ Master/SBUS en compartimento de la batería
Master/Jack
-
+
Enable
-
+ Activar
Disable
-
+ Desactivar
True
-
+ Verdadero
False
-
+ Falso
Yes
- Si
+ Sí
No
- No
+
Y
-
+
N
-
+
ON
- ON
+
@@ -7847,458 +9080,458 @@ Esto determina como los valores de mezcla son añadidos.
OFF
-
+
bytes
-
+
Mode
- Modo
+ Modo
Channels
- Canales
+ Canales
Frame length
-
+ Longitud frame
PPM delay
- Retardo PPM
+ Retardo PPM
Polarity
- Polaridad
+ Polaridad
Protocol
- Protocolo
+ Protocolo
Delay
- Retardo
+ Retardo
Receiver
- Receptor
+ Receptor
Radio protocol
-
+ Protocolo radio
Subtype
-
+ Subtipo
Option value
-
+ Valor opción
Sub Type
-
+ Sub tipo
RF Output Power
-
+ Potencia de salida RF
90
- 90
+
120
- 120
+
120X
- 120X
+
140
- 140
+
MULT!
-
+
Offset
- Offset
+
Slow
- Lento
+ Lento
Warn
-
+ Aviso
Flight modes
- Modos de vuelo
+ Modos de vuelo
Flight mode
- Modo de vuelo
+ Modo de vuelo
All
- Todo
+ Todo
Edge
-
+ Borde
Sticky
-
+ Pegajoso
Timer
- Temporizador
+ Temporizador
missing
-
+ falta
Duration
- Duración
+ Duración
Extended Limits
- Límites extendidos
+ Límites extendidos
Display Checklist
- Lista verificación pantalla
+ Mostrar lista de verificación
Global Functions
-
+ Funciones globales
Manual
-
+ Manual
Auto
-
+ Auto
Failsafe Mode
- Modo Failsafe
+ Modo failsafe
Hold
- Esperar
+ Mantener
No Pulse
-
+ Sin pulsos
Not set
-
+ No fijado
No pulses
-
+ Sin pulsos
Silent
- Silencio
+ Silencio
Beeps
-
+ Beeps
Voice
- Voz
+ Voz
Haptic
- Reproducir Haptic
+ Haptic
Flight
-
+ Vuelo
Manual reset
-
+ Reset manual
Step
-
+ Paso
Display
-
+ Mostrar
Extended
-
+ Extendido
Never
-
+ Nunca
On Change
-
+ Al cambiar
Always
-
+ Siempre
Source
-
+ Fuente
Trim idle only
-
+ Trim sólo al ralentí
Warning
- Aviso
+ Aviso
Reversed
-
+ Invertido
Tmr
-
+ Temporiz.
FrSky S.PORT
-
+
FrSky D
-
+
FrSky D (cable)
-
+
Alti
-
+
Alti+
-
+
VSpeed
-
+ Veloc. vert.
A1
-
+
A2
-
+
A3
-
+
A4
-
+
FAS
-
+
Cells
-
+ Celdas
Calculated
-
+ Calculado
Add
-
+ Sumar
Average
-
+ Media
Min
-
+ Mínimo
Max
-
+ Máximo
Multiply
-
+ Multiplicar
Totalise
-
+ Total
Cell
-
+ Celda
Consumption
-
+ Consumo
Distance
-
+ Distancia
Lowest
-
+ Menor
Cell %1
-
+ Celda %1
Highest
-
+ Mayor
Delta
-
+
Formula
-
+ Fórmula
Id
-
+
Instance
-
+ Instancia
@@ -8306,130 +9539,130 @@ Esto determina como los valores de mezcla son añadidos.
Sensor
-
+
Sources
-
+ Fuentes
GPS
-
+ GPS
Alt.
-
+
Blades
- Palas
+ Palas
Multi.
-
+
F
-
+
Inst
-
+
Alt
-
+
Unit
- Unidad
+ Unidad
Prec
-
+
Ratio
-
+
Multi
-
+
A/Offset
-
+
Filter
-
+ Filtro
Persist
-
+ Persist.
Positive
- Positivo
+ Positivo
Log
-
+ Reporte
Numbers
-
+ Números
Bars
- Barras
+ Barras
Script
-
+ Script
Filename
- Nombre Archivo
+ Nombre archivo
Error: Unable to open or read file!
-
+ Error: ¡No se puede abrir o leer el archivo!
Persistent
-
+ Persistente
Off
- Apagado
+
@@ -8439,89 +9672,89 @@ Esto determina como los valores de mezcla son añadidos.
None
- Ninguno
+ Ninguno
Name
- Nombre
+ Nombre
Countdown
- Cuenta Atrás
+ Cuenta atrás
Minute call
-
+ Cada minuto
FM%1
-
+
FM%1%2
-
+
FM%1+%2
-
+
Weight
-
+ Peso
Switch
-
+ Interruptor
NoTrim
-
+
No DR/Expo
-
+
Offset(%1)
-
+
Disabled in all flight modes
-
+ Desactivado en todos los modos de vuelo
instant
-
+ instante
Custom
- A medida
+ Personalizado
Standard
- Estandar
+ Estándar
@@ -8544,368 +9777,500 @@ Esto determina como los valores de mezcla son añadidos.
Model Name:
- Nombre Modelo:
+ Nombre modelo:
Model Type:
- Tipo Modelo:
+ Tipo modelo:
Module
-
+
+
+
Failsafe Mode
- Modo Failsafe
+ Modo failsafe
+
+
Start
Comenzar
-
+
+
+
PPM delay
Retardo PPM
+
+
Negative
Negativo
+
+
Positive
Positivo
+
+
Polarity
Polaridad
-
+
+
+
Trainer Mode
- Modo Entrenador
+ Modo entrenador
-
+
+
+
PPM Frame Length
- Longitud Trama PPM
+ Longitud trama PPM
+
+
CH
-
+
+
+
Antenna
-
+ Antena
-
+
+
+
Option value
-
-
-
-
- Bind on startup
-
+ Valor opción
+
+
RF Output Power
-
+ Potencia de salida de RF
-
+
+
+
Low Power
-
+ Baja potencia
-
+
+
+
us
-
+
+
+
Multi Radio Protocol
-
+ Multi Radio protocol
-
+
+
+
Sub Type
-
+ Sub tipo
-
+
+
+
Master/Jack
-
+ Master/Jack
-
+
+
+
Slave/Jack
-
+ Slave/Jack
-
+
+
+
Master/SBUS Module
-
+ Módulo Master/SBUS
-
+
+
+
Master/CPPM Module
-
+ Módulo Master/CPPM
-
+
+
+
Master/SBUS in battery compartment
-
+ Master/SBUS en compartimento de la batería
-
+
+
+
Show values in:
-
+ Muestra valores en:
-
+
+
+
%
abbreviation for percent
-
+
-
+
+
+
μs
abbreviation for microseconds
-
+
-
+
+
+
ms
+
+
Receiver 1
-
+ Receptor 1
+
+
+
+
+
+
X
-
+
+
+
Receiver 2
-
+ Receptor 2
+
+
Receiver 3
-
+ Receptor 3
+
+
WARNING: changing RF Output Power needs RE-BIND
-
+ AVISO: cambiar potencia salida de RF requiere RE-BIND
-
+
+
+
Channels
Canales
-
+
+
+
Registration ID
-
+ Registro ID
-
+
+
+
WARNING: Requires non-certified firmware!
-
+ AVISO: ¡Requiere firmware no certificado!
-
+
+
+
Not set
-
+ No fijado
-
+
+
+
Hold
- Esperar
+ Mantener
-
+
+
+
Custom
- A medida
+ Personalizado
-
+
+
+
No Pulses
Sin Pulsos
-
+
+
+
Receiver
Receptor
-
- Failsafe Positions
- Posiciones Failsafe
+
+
+
+ Master/Bluetooth
+ Master/Bluetooth
-
+
+
+
+ Slave/Bluetooth
+ Slave/Bluetooth
+
+
+
+
+
+ Master/Multi
+ Master/Multi
+
+
+
+
+
+ Disable Telemetry
+ Desactivar telemetría
+
+
+
+
+
+ Disable Ch. Map
+ Desactivar mapa canales
+
+
+
+
+
+ Failsafe Positions
+ Posiciones failsafe
+
+
+
+
+
Protocol
Protocolo
+
+
Receiver No.
Receptor Nº.
-
+
+
+
Output type
-
+ Tipo de salida
-
+
+
+
Open Drain
-
+
-
+
+
+
Push Pull
-
+
ModuleData
-
+
Positive
- Positivo
+ Positivo
-
+
Negative
- Negativo
+ Negativo
-
+
Trainer Port
- Puerto Entrenador
+ Puerto entrenador
-
+
Internal Radio System
- Sistema Interno de Radio
+ Sistema de radio interno
-
+
External Radio Module
- Modulo externo de Radio
+ Módulo externo de radio
-
+
Extra Radio System
- Extra Sistema de Radio
+ Sistema de radio extra
-
+
Radio System
- Sistema de Radio
+ Sistema de radio
-
+
10mW - 16CH
-
+
-
-
+
+
100mW - 16CH
-
+
-
+
500mW - 16CH
-
+
-
+
Auto <= 1W - 16CH
-
+
-
-
+
+
25mW - 8CH
-
+
-
-
+
+
25mW - 16CH
-
+
-
+
200mW - 16CH (no telemetry)
-
+ 200mW - 16CH (sin telemetría)
-
+
500mW - 16CH (no telemetry)
-
+ 500mW - 16CH (sin telemetría)
-
+
100mW - 16CH (no telemetry)
-
+ 100mW - 16CH (sin telemetría)
ModulePanel
-
+
Value
- Valor
+ Valor
-
+
Hold
- Esperar
+ Mantener
-
+
No Pulse
-
+ Sin pulsos
-
+
Ask
-
+ Preguntar
-
+
Internal
-
+ Interno
-
+
Internal + External
-
+ Interno + Externo
-
+
External
-
+ Externo
+
+
+
+ Autodetect Format
+ Autodetectar formato
+
+
+
+ Bind on channel
+ Bind con canal
@@ -8913,448 +10278,448 @@ Esto determina como los valores de mezcla son añadidos.
Input
- Entrada
+ Entrada
Weight
-
+ Peso
Long. cyc
-
+ Cíc. long.
Lateral cyc
-
+ Cíc. lateral
Collective
- Colectivo
+ Colectivo
Flight modes
- Modos de vuelo
+ Modos de vuelo
Flight mode
- Modo de vuelo
+ Modo de vuelo
Switch
-
+ Interruptores
General
-
+
EEprom Size
-
+ Tamaño EEprom
Model Image
- Imagen del modelo
+ Imagen del modelo
Throttle
- Acelerador
+ Acelerador
Trims
-
+
Center Beep
-
+ Beep en centro
Switch Warnings
- Avisos palancas (Switch)
+ Avisos interruptores
Pot Warnings
- Avisos Potenciómetros
+ Avisos potenciómetros
Other
-
+ Otro
Timers
-
+ Temporizadores
Time
- Hora
+ Hora
Countdown
- Cuenta Atrás
+ Cuenta atrás
Modules
-
+ Módulos
Trainer port
-
+ Puerto entrenador
Helicopter
- Helicóptero
+ Helicóptero
Swash
-
+
Type
-
+ Tipo
Ring
-
+
Protocol
- Protocolo
+ Protocolo
Low
-
+ Bajo
Critical
-
+ Crítico
Telemetry audio
-
+ Audio telemetría
Altimetry
- Altímetro
+ Altímetro
Vario source
- Fuente Variómetro
+ Fuente variómetro
Vario limits >
-
+ Límites variómetro
Sink max
-
+ Descenso máx
Sink min
-
+ Descenso mín
Climb min
-
+ Ascenso mín
Climb max
-
+ Ascenso máx
Center silent
-
+ Centro silencio
Top Bar
-
+ Barra superior
Volts source
-
+ Fuente de voltage
Altitude source
-
+ Fuente de altitud
Various
- Varios
+ Varios
Serial protocol
-
+ Protocolo serie
FAS offset
-
+
mAh count
- Valor mAh
+ Valor mAh
Persistent mAh
- mAh Constantes
+ mAh persistente
Current source
- Fuente Actual
+ Fuente actual
Blades
- Palas
+ Palas
Parameters
- Parámetros
+ Parámetros
Telemetry Sensors
-
+ Sensores de telemetría
Telemetry Screens
-
+ Pantallas de telemetría
GF%1
-
+
Global Functions
-
+ Funciones globales
Checklist
-
+ Lista de verificación
GV%1
-
+
RE%1
-
+
Channel
-
+ Canal
Name
- Nombre
+ Nombre
Prec
-
+
Popup
-
+ Emergente
Outputs
- Salidas
+ Salidas
Subtrim
- Subtrim
+
Direct
-
+ Directo
Curve
- Curva
+ Curva
PPM
-
+
Linear
- Lineal
+ Lineal
Telemetry
- Telemetría
+ Telemetría
Offset
- Offset
+
Min
-
+ Mín
Min.call
-
+ Cada min
Persist
-
+ Persistente
F.In
-
+ Atn. entr.
F.Out
-
+ Atn.sal.
Global vars
-
+ Vars globales
Max
-
+ Máx
Global Variables
- Variables globales
+ Variables globales
Inputs
- Entradas
+ Entradas
Mixers
- Mezclas
+ Mezclas
Curves
- Curvas
+ Curvas
L%1
-
+
Logical Switches
- Switches lógicos
+ Interruptores lógicos
SF%1
- SF%1
+
Special Functions
- Funciones especiales
+ Funciones especiales
Analogs
-
+ Analógicos
Unit
- Unidad
+ Unidad
Scale
- Escala
+ Escala
RSSI Alarms
-
+ Alarmas RSSI
@@ -9362,52 +10727,47 @@ Esto determina como los valores de mezcla son añadidos.
Subtype
-
+ Subtipo
Video TX frequency
-
+ Frecuencia vídeo TX
CC2500 frequency fine tune
-
+ CC2500 ajuste fino de frecuencia
Telemetry
- Telemetría
+ Telemetría
Radio output power
-
+ Potencia de salida radio
Servo output frequency
-
+ Frecuencia de salida servo
Option value
-
+ Valor opción
Fixed ID value
-
+ Valor ID fijo
DEFAULT
-
-
-
-
- Custom - proto %1)
-
+ PREDETERMINADO
@@ -9415,45 +10775,45 @@ Esto determina como los valores de mezcla son añadidos.
Throttle Channel:
- Canal Throttle:
+ Canal de acelerador:
Yaw Channel:
- Canal Yaw:
+ Canal de viraje:
Pitch Channel:
- Canal Pitch:
+ Canal de inclinación:
Roll Channel:
- Canal Roll:
+ Canal de balanceo:
OpenTxEepromInterface
-
-
- Unknown error
-
-
+ Unknown error
+ Error desconocido
+
+
+
... plus %1 errors
-
+ ... más %1 errores
-
+
Cannot write radio settings
-
+ No se pueden escribir los ajustes de la radio
-
+
Cannot write model %1
-
+ No se puede escribir el modelo %1
@@ -9461,12 +10821,12 @@ Esto determina como los valores de mezcla son añadidos.
Throttle Cut
- Corte de Gas
+ Corte de gas
Throttle Timer
- Temporizador de Gas
+ Temporizador de gas
@@ -9480,62 +10840,71 @@ Esto determina como los valores de mezcla son añadidos.
Error opening file %1:
%2.
- Error abriendo el archivo %1:
+ Error abriendo el archivo %1:
%2.
Error opening OTX archive %1
-
+ Error abriendo archivo OTX %1
Error initializing OTX archive writer
-
+ Error inicializando el escritor de archivo OTX
Error writing file %1:
%2.
- Error escribiendo el archivo %1:
+ Error escribiendo el archivo %1:
%2.
Error creating OTX file %1:
%2.
-
+ Error creando el fichero OTX %1:
+%2.
Error creating OTX archive
-
+ Error creando el archivo OTX
Error adding %1 to OTX archive
-
+ Error añadiendo %1 al archivo OTX
PrintDialog
+
+
Close
Cerrar
+
+
Style
-
+ Estilo
+
+
Print
Imprimir
+
+
Print to file
Imprimir a archivo
@@ -9547,7 +10916,7 @@ Esto determina como los valores de mezcla son añadidos.
Select PDF output file
- Seleccionar archivo de salida PDF
+ Seleccionar archivo de salida PDF
@@ -9559,27 +10928,46 @@ Esto determina como los valores de mezcla son añadidos.
ProgressDialog
+
+
Flash Firmware
-
+
+
+
Close
- Cerrar
+ Cerrar
Cancel
- Cancelar
+ Cancelar
ProgressWidget
+
+
Show Details
- Mostrar detalles
+ Mostrar detalles
+
+
+
+ QObject
+
+
+ WARNING
+ AVISO
+
+
+
+ <p>Importing JumperTX data into OpenTX 2.3 is <b>not supported and dangerous.</b></p> <p>It is unfortunately not possible for us to differentiate JumperTX data from legitimate FrSky X10 data, but <b>You should only continue here if the file you opened comes from a real FrSky X10.</b></p> <p>Do you really want to continue?</p>
+ <p> Importar datos de JumperTX a OpenTX 2.3 <b> no es compatible y es peligroso. </b> </p> <p> Desafortunadamente, no es posible diferenciar los datos de JumperTX de los datos legítimos de FrSky X10, pero <b> Sólo debes continuar aquí si el archivo que se abrió proviene de un FrSky X10 real. </b> </p> <p> ¿Realmente deseas continuar? </p>
@@ -9587,7 +10975,7 @@ Esto determina como los valores de mezcla son añadidos.
Models
-
+ Modelos
@@ -9595,97 +10983,97 @@ Esto determina como los valores de mezcla son añadidos.
is invalid
-
+ es inválido
converted to
-
+ convertido a
verify is
-
+ verificar si
[DBG]
-
+
[NFO]
-
+
[WRN]
-
+
[CVT]
-
+
[ERR]
-
+
[INV]
-
+
Event
-
+ Evento
Origin
-
+ Fuente
Comp
-
+ Comp
Sub-Component
-
+ Sub-componente
Field
-
+ Campo
Type
-
+ Tipo
Old
-
+ Anterior
Action
- Acción
+ Acción
New
- Nuevo
+ Nuevo
Seq
-
+
@@ -9694,24 +11082,24 @@ Esto determina como los valores de mezcla son añadidos.
Cannot write file %1:
%2.
- No se puede escribir el archivo %1:
+ No se puede escribir el archivo %1:
%2.
<b><u>WARNING!</u></b><br>This will reset the fuses of %1 to the factory settings.<br>Writing fuses can mess up your radio.<br>Do this only if you are sure they are wrong!<br>Are you sure you want to continue?
- <b><u>¡AVISO!</u></b><br>Esto reseteará los fuses de %1 a los ajustes de fábrica.<br>Escribir fuses puede estropear tu radio.<br>¡Haz esto sólo si estás seguro que están mal!<br>¿Estás seguro de continuar?
+ <b><u>¡AVISO!</u></b><br>Esto reseteará los fusibles de %1 a los ajustes de fábrica.<br>Escribir los fusibles puede estropear tu radio.<br>¡Haz esto sólo si estás seguro que están mal!<br>¿Estás seguro de continuar?
Could not delete temporary file: %1
-
+ No se puede borrar el archivo temporal: %1
- Unable to find Horus radio SD card!
-
+ Unable to find radio SD card!
+ ¡No se puede encontrar la tarjeta SD de la radio!
@@ -9719,28 +11107,34 @@ Esto determina como los valores de mezcla son añadidos.
<p>Value (input): <b>%1</b></p>
-
+ <p>Valor (entrada): <b>%1</b></p>
Right-double-click to reset to center.
-
+ Doble click derecho para reiniciar centro.
RadioNotFoundDialog
+
+
No Radio Found
- No se ha encontrado la Radio
+ No se ha encontrado radio
+
+
<html><head/><body><p>No Radio was found!</p><p>Make sure that you hold the lower trim buttons towards the center while you turn it on.</p><p>Then connect the USB wire.</p><p><span style=" font-family:'arial,sans-serif'; font-size:13px; font-style:italic; color:#222222; background-color:#ffffff;">Note: if you have a Taranis that has not had the firmware upgraded to 2.0 then this version of Companion will not work.</span></p></body></html>
-
+ <html><head/><body> <p> ¡No se encontró radio! </p> <p> Asegúrate de mantener presionados los botones de ajuste inferiores hacia el centro mientras la enciendes. </p> <p> Luego, conecta el cable USB. </p> <p> <span style = "font-family: 'arial, sans-serif'; font-size: 13px; font-style: italic; color: # 222222; background-color : #ffffff; "> Nota: si tienes una Taranis que no tiene el firmware actualizado a 2.0, entonces esta versión de Companion no funcionará. </span> </p> </body> </html>
+
+
OK
@@ -9749,64 +11143,78 @@ Esto determina como los valores de mezcla son añadidos.
RadioOutputsWidget
-
+
+
Form
-
+
-
+
+
View:
-
+ Vista:
-
+
+
Logical Switches
- Switches lógicos
+ Interruptores lógicos
-
+
+
Global Variables
- Variables globales
+ Variables globales
-
+
+
Channel Outputs
-
+ Salidas canales
-
+
+
Mix Outputs
-
+ Salidas mixes
-
+
+
L
o
g
i
c
-
+ L
+ó
+g
+i
+c
+o
-
+
+
G
l
o
b
a
l
-
+
-
+
+
C
h
a
@@ -9815,27 +11223,34 @@ n
e
l
s
-
+ C
+a
+n
+a
+l
+e
+s
-
+
+
M
i
x
e
s
-
+
FM%1
-
+
GV%1
-
+
@@ -9843,7 +11258,7 @@ s
Latch/unlatch the momentary switch.
-
+ Activa/desactiva el interruptor momentáneo.
@@ -9854,7 +11269,7 @@ s
V
-
+
@@ -9862,428 +11277,428 @@ s
s
-
+
ft
-
+
m
-
+
°C
-
+
°
-
+
%
-
+
mph
-
+
km/h
-
+
m/s
-
+
A
-
+
mAh
-
+
W
-
+
g
-
+
TrmR
-
+
TrmE
-
+
TrmT
-
+
TrmA
-
+
Trm5
-
+
Trm6
-
+
TrmH
-
+
TrmV
-
+
Batt
- Batería
+ Batería
Time
- Hora
+ Hora
Timer1
- Temporizador1
+ Temporizador1
Timer2
- Temporizador 2
+ Temporizador 2
Timer3
- Temporizador 3
+ Temporizador 3
RAS
-
+
RSSI Tx
-
+
RSSI Rx
-
+
A1
-
+
A2
-
+
A3
-
+
A4
-
+
Alt
-
+
Rpm
-
+
Fuel
- Combustible
+ Combustible
T1
-
+
T2
-
+
Speed
- Velocidad
+ Velocidad
Dist
-
+ Distancia
GPS Alt
-
+
Cell
-
+ Celda
Cells
-
+ Celdas
Vfas
-
+
Curr
-
+
Cnsp
-
+ Cons
Powr
-
+
AccX
-
+
AccY
-
+
AccZ
-
+
Hdg
-
+
VSpd
-
+ VelocVert
AirSpeed
-
+ VelocAire
dTE
-
+
A1-
-
+
A2-
-
+
A3-
-
+
A4-
-
+
Alt-
-
+
Alt+
-
+
Rpm+
-
+
T1+
-
+
T2+
-
+
Speed+
- Velocidad+
+ Velocidad+
Dist+
-
+
AirSpeed+
-
+ VelocAire+
Cell-
-
+ Celda-
Cells-
-
+ Celdas-
Vfas-
-
+
Curr+
-
+
Powr+
-
+
ACC
-
+
GPS Time
- Hora GPS
+ Hora GPS
REa
-
+
REb
-
+
???
- ???
+
----
-
+
I
as in Input
-
+
LUA%1%2
-
+
MAX
-
+
CYC%1
-
+
TR
as in Trainer
-
+
SRC
-
+
@@ -10291,165 +11706,170 @@ s
↑
-
+
↓
-
+
-
-
+
!
-
+
RudTrim Left
- RudTrim Izquierda
+ RudTrim izquierda
RudTrim Right
- RudTrim Derecha
+ RudTrim derecha
EleTrim Down
- EleTrim Abajo
+ EleTrim Abajo
EleTrim Up
- EleTrim Arriba
+ EleTrim Arriba
ThrTrim Down
- ThrTrim Abajo
+ ThrTrim abajo
ThrTrim Up
- ThrTrim Arriba
+ ThrTrim arriba
AilTrim Left
- AilTrim Izquierda
+ AilTrim Izquierda
AilTrim Right
- AilTrim Derecha
+ AilTrim Derecha
Trim 5 Down
-
+ Trim 5 abajo
Trim 5 Up
-
+ Trim 5 arriba
Trim 6 Down
-
+ Trim 6 abajo
Trim 6 Up
-
+ Trim 6 arriba
TrmH Left
-
+ TrmH izquierda
TrmH Right
-
+ TrmH derecha
TrmV Down
-
+ TrmV abajo
TrmV Up
-
+ TrmV arriba
REa
-
+
REb
-
+
OFF
-
+
ON
- ON
+
THs
-
+
TH%
-
+
THt
-
+
-
+
???
- ???
+
One
- Uno
+ Uno
-
+
+ Act
+
+
+
+
----
-
+
-
+
Telemetry
- Telemetría
+ Telemetría
-
+
SW
-
+
@@ -10457,7 +11877,7 @@ s
Companion Release Notes
- Notas de la versión Companion
+ Notas de la versión de Companion
@@ -10465,7 +11885,7 @@ s
OpenTX Release Notes
- Notas de la versión OpenTX
+ Notas de la versión de OpenTX
@@ -10473,17 +11893,17 @@ s
Played once, not during startup
- Reproducir una vez, no en el inicio
+ Reproducir una vez, no durante el inicio
No repeat
- No Repetir
+ No repetir
%1s
- %1s
+
@@ -10496,7 +11916,7 @@ s
Yes
- Si
+ Sí
@@ -10510,14 +11930,15 @@ s
Error opening file %1:
%2.
- Error abriendo el archivo %1:
+ Error abriendo el archivo %1:
%2.
Error opening file %1 in write mode:
%2.
-
+ Error abriendo archivo %1 en modo de escritura:
+%2.
@@ -10526,293 +11947,352 @@ s
V
-
+
A
-
+
mA
-
+
kts
-
+
m/s
-
+
km/h
-
+
mph
-
+
m
-
+
f
-
+
°C
-
+
°F
-
+
%
-
+
mAh
-
+
W
-
+
mW
-
+
dB
-
+
rpms
-
+
g
-
+
°
-
+
Rad
-
+
hours
-
+ horas
minutes
-
+ minutos
seconds
-
+ segundos
-
+
+ ml/minute
+ ml/minuto
+
+
+
TELE
-
-
-
-
- Internal
-
-
-
-
- External
-
+
Setup
+
+
Center beep
Centro beep
+
+
OFF
- OFF
+
+
+
Model Image
Imagen del modelo
+
+
Exponential
Exponencial
+
+
Throttle Trim Idle Only
- Trim de acelerador ajuste de ralentí
+ Trim acel. ralentí
+
+
Extra Fine
Extra Fino
+
+
Fine
Fino
+
+
Medium
Medio
+
+
Coarse
- Duro
+ Grueso
+
+
Display Checklist
- Lista verificación pantalla
+ Lista de verific.
+
+
Timer 2
Temporizador 2
+
+
Timer 1
- Temporizador1
+ Temporizador 1
+
+
Timer 3
- Temporizador3
+ Temporizador 3
+
+
Never
-
+ Nunca
+
+
Top LCD Timer
-
+ Temp. LCD superior
+
+
On change
-
+ Al cambiar
+
+
Always
-
+ Siempre
+
+
Global Functions
-
+ Funcs. globales
+
+
Edit Checklist...
-
+ Lista de verific...
+
+
Throttle Source
- Fuente del acelerador
+ Fuente acelerador
+
+
Trim Step
- Pasos de Trim
+ Paso de trim
+
+
Trims Display
-
+ Mostrar trims
+
+
Warnings
Avisos
+
+
Switch Warnings
- Avisos palancas (Switch)
+ Avisos interruptores
+
+
Pot Warnings
Avisos Potenciómetros
+
+
Manual
-
+ Manual
+
+
Auto
+
+
Model
Modelo
+
+
Extended Limits
Límites extendidos
+
+
Extended Trims
Trims extendidos
+
+
Throttle Warning
Aviso acelerador
+
+
Reverse throttle operation.
If this is checked the throttle will be reversed. Idle will be forward, trim will also be reversed and the throttle warning will be reversed as well.
@@ -10824,31 +12304,33 @@ Si está marcado el acelerador será invertido. El ralentí será delante, el t
+
+
Reverse Throttle
- Invertir acelerador (Throttle)
+ Invertir acelerador
SetupPanel
-
+
Timer %1
-
+ Temporizador %1
-
+
THR
-
+
-
+
Profile Settings
-
+ Ajustes de perfil
-
+
SD structure path not specified or invalid
-
+ Ruta de la SD no especificada o no válida
@@ -10856,7 +12338,7 @@ Si está marcado el acelerador será invertido. El ralentí será delante, el t
Elevator Channel:
- Canal Profundidad (Elevator):
+ Canal de profundidad:
@@ -10865,203 +12347,203 @@ Si está marcado el acelerador será invertido. El ralentí será delante, el t
screenshot
Simulator LCD screenshot file name prefix
-
+ captura
ENTER
-
+ INTRO
S
-
+
PG-UP
-
+ RE PÁG
PG-DN
-
+ AV PÁG
DEL
-
+ SUPR
BKSP
-
+ RETR
ESC
-
+
INS
-
+
<font size=+3>+</font>
-
+
<font size=+3>-</font>
-
+
<font size=+3>←</font>
-
+
<font size=+3>→</font>
-
+
<font size=+3>↑</font>
-
+
<font size=+3>↓</font>
-
+
<font size=+3>⚆</font>
-
+
<font size=+3>↶</font>
-
+
<font size=+3>↷</font>
-
+
<font size=+3>⇆</font>
-
+
<font size=+3>⇓</font>
-
+
<font size=+3>⇑</font>
-
+
<font size=+3>⇕</font>
-
+
<img src='qrc:/images/simulator/icons/svg/mouse.svg' width=20 height=18 />
-
+
<img src='qrc:/images/simulator/icons/svg/arrow_click.svg' width=18 height=18 />
-
+
<pre>[ MENU ]</pre>
-
+
<pre>[ PAGE ]</pre>
-
+
<pre>[ EXIT ]</pre>
-
+
<pre>[ ENT ]</pre>
-
+
<pre>[ SHIFT ]</pre>
-
+
<pre>[ UP ]</pre>
-
+
<pre>[ DN ]</pre>
-
+
<pre>[ <font size=+2>+</font> ]</pre>
-
+
<pre>[ <font size=+2>-</font> ]</pre>
-
+
<pre>[ PgUp ]</pre>
-
+
<pre>[ PgDn ]</pre>
-
+
<pre>[ MDL ]</pre>
-
+
<pre>[ RTN ]</pre>
-
+
<pre>[ SYS ]</pre>
-
+
<pre>[ TELE ]</pre>
-
+
<font size=+3>≡</font>
-
+
@@ -11069,609 +12551,673 @@ Si está marcado el acelerador será invertido. El ralentí será delante, el t
OpenTx Simulator
-
+ Simulador de OpenTx
Available profiles:
-
+ Perfiles disponibles:
ID:
-
+
Name:
-
+ Nombre:
Available radios:
-
+ Radios disponibles:
Radio profile ID or Name to use for simulator.
-
+ Perfil ID de radio o nombre a usar para simulador.
profile
-
+ perfil
Radio type to simulate (usually defined in profile).
-
+ Tipo de radio a simular (normalmente definido en el perfil).
radio
-
+ radio
Directory containing the SD card image to use. The default is configured in the chosen Radio Profile.
-
+ Directorio conteniendo la imagen de la tarjeta SD a usar. El predeterminado es configurado en el perfil de radio seleccionado.
path
-
+ ruta
Data source type to use (applicable to Horus only). One of:
-
+ Origen de datos a usar (sólo aplicable a Horus). Uno de:
type
-
+ tipo
data-source
-
+ origen-datos
Radio data (.bin/.eeprom/.otx) image file to use OR data folder path (for Horus-style radios).
NOTE: any existing EEPROM data incompatible with the selected radio type may be overwritten!
-
+ Imagen de datos de radio (.bin/.eeprom/.otx) o carpeta (para radios estilo Horus) a usar.
+NOTA: cualquier dato EEPROM incompatible con la radio seleccionada puede ser sobreescrito!
[data-source]
-
+ [origen-datos]
Error: Profile ID %1 was not found.
-
+ Error: Perfil ID %1 no encontrado.
Unrecognized startup data source type: %1
-
+ Tipo de origen de datos de arranque desconocido: %1
WARNING: couldn't initialize SDL:
%1
-
+ WARNING: No se puede inicializar SDL:
+%1
ERROR: No simulator libraries available.
-
+ ERROR: No hay librerías de simulador disponibles.
ERROR: Couldn't start simulator, missing radio/profile/data file/folder.
Profile ID: [%1]; Radio ID: [%2];
Data File: [%3]
-
+ ERROR: No se puede iniciar el simulador, falta radio/perfil/datos ficheo/carpeta.
+ Perfil ID: [%1]; Radio ID: [%2];
+Archivo datos: [%3]
ERROR: Radio profile or simulator firmware not found.
Profile ID: [%1]; Radio ID: [%2]
-
+ ERROR: Perfil de radio o firmware del simulador no encontrado.
+Perfil ID: [%1]; Radio ID: [%2]
Uknown error during Simulator startup.
-
+ Error desconocido al iniciar el simulador.
SimulatorMainWindow
-
+
+
OpenTx Simulator
-
+ Simulador de OpenTX
-
+
+
View
-
+ Vista
-
+
+
Radio Window
-
+ Ventana de radio
-
+
+
Reload...
-
+ Recargar...
-
+
+
Tools
-
+ Herramientas
-
+
+
Toolbar
-
+ Barra de herramientas
-
+
+
Reload Lua Scripts
-
+ Recarga scripts Lua
-
+
+
Reload the Lua environment on the simulated radio.
-
+ Recarga el entorno Lua en la simulación de la radio.
-
+
+
F7
-
+
-
+
+
Reload Radio Data
-
+ Recarga datos de radio
-
+
+
Reload all radio data without restarting the simulator.
-
+ Recarga todos los datos de la radio sin reiniciar el simulador.
-
+
+
F9
-
+
-
+
+
Key Mapping
-
+ Mapa de teclas
-
+
+
Show keyboard maping reference.
-
+ Muestra el mapa de teclas.
-
+
+
F1
-
+
-
+
+
Joystick Settings
-
+ Ajustes joystick
-
+
+
Open joystick configuration settings dialog.
-
+ Abre la configuracíon de ajustes del joystick.
-
+
+
F3
-
+
-
+
+
LCD Screenshot
-
+ Captura LCD
-
+
+
Save a screenshot of the current simulated LCD screen.
-
+ Guarda una captura de la simulación de la pantalla LCD.
-
+
+
F8
-
+
-
+
+
Dock In Main Window
-
+ Anclar en la ventana principal
-
+
+
Show the radio in the main window or as a separate "floating" window.
-
+ Muestra la radio en la ventana principal o en una ventana "flotante" separada.
-
+
+
Menu Bar
-
+ Barra superior
-
+
+
Show or hide the top menu bar.
-
+ Muestra u oculta la barra superior.
-
+
+
Alt+M
-
+ Alt+M
-
+
+
Constrain Width
-
+ Restringir ancho
-
+
+
Set radio widget width to be a fixed size.
-
+ Fija el ancho de widget de la radio a un tamaño fijo.
-
+
+
Constrain Height
-
+ Restringir alto
-
+
+
Set radio widget height to be a fixed size.
-
+ Fija el alto de widget de la radio a un tamaño fijo.
ERROR: Failed to create simulator interface, possibly missing or bad library.
-
+ ERROR: No se puede crear la interfaz de simulador, posiblemente falta o es erronea la librería.
Alt+T
-
+
Radio Outputs
-
+ Salidas de radio
F2
-
+
Telemetry Simulator
-
+ Simulador de telemetría
F4
-
+
Trainer Simulator
-
+ Simulador de entrenador
F5
-
+
Debug Output
-
+ Salida de depuración
F6
-
+
<b>Simulator Controls:</b>
-
+ <b>Controles simulador:</b>
<tr><th>Key/Mouse</th><th>Action</th></tr>
note: must match html layout of each table row (keyTemplate).
-
+ <tr><th>Tecla/Ratón</th><th>Acción</th></tr>
<tr><td><kbd>%1</kbd></td><td>%2</td></tr>
note: must match html layout of help text table header.
-
+ <tr><td><kbd>%1</kbd></td><td>%2</td></tr>
Simulator Help
-
+ Ayuda simulador
SimulatorStartupDialog
-
+
+
OpenTX Simulator - Startup Options
-
+ Simulador de OpenTX - Opciones de arranque
-
+
+
Simulator Startup Options:
-
+ Opciones de arranque del simulador:
-
+
+
Radio Profile:
-
+ Perfil de radio:
-
+
+
Existing radio profiles are shown here.<br />
Create or edit profiles using the Companion application.
-
+ Los perfiles de radio existentes se muestran aquí.<br />
+Crea o edita perfiles usando la aplicación de Companion.
-
+
+
Radio Type:
-
+ Tipo de radio:
-
+
+
Existing radio simulators are shown here.<br />
The radio type specified in the selected profile is used by default.
-
+ Los simuladores de radio existentes se muestran aquí.<br />
+Por defecto se us el tipo de radio especificado en en perfil seleccionado.
-
+
+
Data Source:
-
+ Origen de datos:
-
+
+
Data File:
-
+ Archivo de datos:
-
+
+
Data Folder:
-
+ Carpeta de datos:
-
+
+
SD Image Path:
-
+ Ruta de la imagen SD:
-
+
+
Radio data (.bin/.eeprom/.otx) image file to use. A new file with a default image will be created if necessary.<br />
<b>NOTE</b>: any existing EEPROM data incompatible with the selected radio type may be overwritten!
-
+ Archivo de datos de la radio (.bin/.eeprom/.otx) a usar. Un nuevo archivo con imange predeterminada se creará si es necesario.<br />
+<b>NOTE</b>: cualquier EEPROM incompatible con la radio selccionada se sobreescribirá!
-
+
+
Select data file...
-
+ Selecciona archivo de datos...
-
-
-
+
+
+
+
+
+
...
-
+
-
+
+
Directory containing RADIO and MODELS folders to use.<br />
New folder(s) with default radio/model will be created here if necessary.
-
+ Directorio conteniendo RADIO y MODELOS a usar.<br />
+Nuevas carpeta(s) con radio/modelo predeterminado se crearán aquí si es necesario.
-
+
+
Select data folder...
-
+ Selecciona carpeta de datos...
-
+
+
Directory containing the SD card image to use.<br/>
The default is configured in the chosen Radio Profile.
-
+ Directorio que contiene la imagen de la tarjeta SD a usar.<br/>
+El predeterminado es configurado en el Perfil de radio seleccionado.
-
+
+
Select SD card image folder...
-
+ Selecciona la carpeta de la imagen de la tarjeta SD...
-
+
+
Select which of the data sources (File/Folder/SD Card) you would like to start the simulator with.
-
+ Selecciona el origen de datos (Archivo/carpeta/tarjata SD) con el que quieres iniciar el simulador.
-
+
+
File
- Archivo
+ Archivo
-
+
+
Folder
-
+ Carpeta
-
+
+
SD Path
-
+ Ruta SD
All files (*.*)
-
+ Todos los ficheros (*.*)
Select a data file
-
+ Selecciona un archivo de datos
Select Data Directory
-
+ Selecciona directorio de datos
Select SD Card Image Folder
-
+ Selecciona carpeta de imágenes de la tarjeta SD
SimulatorWidget
-
+
+
Companion Simulator
- Simulador Companion
+ Simulador Companion
Radio Simulator (%1)
-
+ Simulador radio (%1)
-
+
Could not determine startup data source.
-
+ No se pueden determinar los datos de arranque.
-
+
Could not load data, possibly wrong format.
-
+ No se puede cargar datos, posiblemente formato erróneo.
-
+
Data Load Error
-
+ Error de carga de de datos
-
+
Invalid startup data provided. Plese specify a proper file/path.
-
+ Datos de inicio inválidos. Por favor specifica un archivo/ruta válido.
-
+
Simulator Startup Error
-
+ Error de arranque del simulador
-
+
Error saving data: could open file for writing: '%1'
-
+ Error salvando datos: no se puede abrir el archivo como escritura: '%1'
-
+
Error saving data: could not get data from simulator interface.
-
+ Error salvando datos: no se puede obtener datos de la interfaz del simulador.
-
+
An unexpected error occurred while attempting to save radio data to file '%1'.
-
+ Ha ocurrido un error inesperado al intentar guardar los datos de la radio al archivo '%1'.
-
+
Data Save Error
-
+ Error de guardado de datos
-
+
Radio firmware error: %1
-
+ Error del firmware de la radio: %1
-
+
- Flight Mode %1 (#%2)
-
+ - Modo de vuelo %1 (#%2)
-
+
Cannot open joystick, joystick disabled
- No se puede abrir el joystick, joystick desactivado
+ No se puede abrir el joystick, joystick desactivado
@@ -11679,12 +13225,12 @@ The default is configured in the chosen Radio Profile.
Right-double-click to reset to center.
-
+ Doble click derecho para reiniciar el centro.
<p>Value (input): <b>%1</b></p>
-
+ <p>Valor (entrada): <b>%1</b></p>
@@ -11692,18 +13238,22 @@ The default is configured in the chosen Radio Profile.
+
+
+
+
...
Splash Library - page %1 of %2
- LIbreria de pantallas de inicio - página %1 de %2
+ LIbrería de pantallas de inicio - página %1 de %2
Invalid image in library %1
- Imagen inválida en la librería %1
+ Imagen no válida en la librería %1
@@ -11724,56 +13274,69 @@ The default is configured in the chosen Radio Profile.
Unable to find file %1!
- ¡No es posible encontrar el archivo %1!
+ ¡No se puede encontrar el archivo %1!
StyleEditDialog
+
+
Style Sheet Editor
-
+ Editor de hoja de estilo
+
+
&Reset to default
-
+ &Reiniciar a los predeterminados
+
+
&Cancel
-
+ &Cancelar
+
+
&OK
-
+
+
+
This feature does not validate your changes and assumes you are familiar with CSS syntax for QT.
-
+ Esta propiedad no valida tus cambios y asume que eres familiar con la sintaxis CSS para QT.
Cannot retrieve style %1
Error: %2
-
+ No se puede obtener el estilo %1
+Error: %2
Cannot retrieve default style %1
Error: %2
-
+ No se puede obtener el estilo predeterminado %1
+Error: %2
Cannot update custom style %1
Error: %2
-
+ No se puede actualizar el estilo personalizado %1
+Error: %2
@@ -11781,47 +13344,47 @@ Error: %2
Style sheet data read from '%1'
-
+ Hoja de estilo leída desde '%1'
Style sheet data unable to be read from '%1'
-
+ No se puede leer hoja de estilo desde '%1'
Cannot create folder '%1'
-
+ No se puede crear el directorio '%1'
Cannot open file for writing '%1': Error: %2
-
+ No se puede abrir el archivo para escritura '%1': Error: %2
Cannot write to file '%1': Error: %2
-
+ No se puede escribir en el archivo '%1': Error: %2
Cannot flush buffer for file '%1': Error: %2
-
+ No se puede vaciar buffer para el archivo '%1': Error: %2
Style sheet written to '%1'
-
+ Hoja de estilo escrita a '%1'
Custom style sheet deleted: '%1'
-
+ Hoja de estilo personalizada borrada: '%1'
Unable to delete custom style sheet: '%1'
-
+ No se puede borrar hoja de estilo personalizada: '%1'
@@ -11829,141 +13392,145 @@ Error: %2
[TEST RUN]
-
+ [TEST RUN]
Synchronization failed, nothing found to copy.
-
+ Sincronización fallida, no se ha encontrado nada para copiar.
Skipping large file: %1 (%2KB)
-
+ Omitiendo archivo largo: %1 (%2KB)
Creating directory: %1
-
+ Creando directorio: %1
Could not create directory: %1
-
+ No se puede crear el directorio: %1
Gathering file information for %1...
-
+ Reuniendo información del archivo para %1...
No files found in %1
-
+ Ficheros no encontrados en %1
Synchronization aborted at %1 of %2 files.
-
+ Sincronización abortada con %1 de %2 ficheros.
Synchronization finished with %1 files in %2m %3s.
-
+ Sincronización finalizada con %1 ficheros en %2m %3s.
Synchronizing: %1
To: %2
-
+ Sincronizando: %1
+ a: %2
Starting synchronization:
%1 -> %2
-
+ Iniciando sincronización:
+ %1 -> %2
+
Too many errors, giving up.
-
+
+Demasiados errores, abortando.
Skipping filtered file: %1
-
+ Omitiendo archivo filtrado: %1
Skipping linked file: %1
-
+ Omitiendo archivo linkado: %1
Aborted synchronization of:
-
+ Sincronizacíon abortada de:
Finished synchronizing:
-
+ Sincronización finalizada:
Created: %1; Updated: %2; Skipped: %3; Errors: %4;
-
+ Creado: %1; Actualizado: %2; Omitido: %3; Errores: %4;
Directory exists: %1
-
+ Existe el directorio: %1
At least one of the file modification dates is in the future, error on: %1
-
+ Al menos una de las fechas de modificación de los ficheros está en el futuro, error en: %1
Skipping older file: %1
-
+ Omitiendo fichero más antiguo: %1
Could not open source file '%1': %2
-
+ No se puede abrir el archivo de origen '%1': %2
Could not open destination file '%1': %2
-
+ No se puede abrir el archivo de destino '%1': %2
Skipping identical file: %1
-
+ Omitiendo archivo idéntico: %1
Replacing file: %1
-
+ Reemplazando archivo:; %1
Creating file: %1
-
+ Creando archivo: %1
Could not delete destination file '%1': %2
-
+ No se puede borrar el archivo de destino '%1': %2
Copy failed: '%1' to '%2': %3
-
+ Copia fallida: '%1' a '%2': %3
@@ -11976,12 +13543,12 @@ Too many errors, giving up.
Elevator Channel:
- Canal Profundidad (Elevator):
+ Canal de profundidad:
Only one channel still available!<br>You probably should configure your model without using the wizard.
-
+ ¡Sólo hay un canal disponible!<br>Deberías configurar el modelo sin el asistente.
@@ -11994,7 +13561,7 @@ Too many errors, giving up.
Only Elevator
- Solo profundidad
+ Sólo profundidad
@@ -12011,299 +13578,433 @@ Too many errors, giving up.
Telemetry
+
+
A1
+
+
A2
+
+
RSSI
+
+
Alarm 1
Alarma 1
+
+
+
+
----
+
+
+
+
Yellow
Amarillo
+
+
+
+
Orange
Naranja
+
+
+
+
Red
Rojo
+
+
Alarm 2
Alarma 2
+
+
Disable telemetry audio warnings
-
+ Desactivar avisos de telemetría
+
+
Source
-
+ Fuente
+
+
Center Silent
-
+ Centro silencioso
+
+
Altitude source
-
+ Fuente de altitud
+
+
Volts source
-
+ Fuente de voltage
+
+
Top Bar
-
+ Barra superior
+
+
Serial Protocol
- Protocolo Serie
+ Protocolo serie
+
+
Sensors
-
+ Sensores
+
+
Disable multi sensor handling
-
+ Desactivar soporte sensor múltiple
+
+
Volt source
Fuente Voltaje
+
+
Current source
Fuente Actual
+
+
Protocol
Protocolo
+
+
None
Ninguno
+
+
FrSky Sensor Hub
-
+ FrSky Sensor Hub
+
+
Blades
Palas
+
+
Sink Max
- Descenso Máximo
+ Máximo descenso
+
+
Climb Max
- Máximo Ascenso
+ Máximo ascenso
+
+
Sink Min
- Descenso Mínimo
+ Mínimo descenso
+
+
Climb Min
- Mínimo Ascenso
+ Mínimo ascenso
+
+
Vario source
- Fuente Variómetro
+ Fuente variómetro
+
+
Vario limits
- Límites Variómetro
+ Límites variómetro
+
+
Altimetry
Altímetro
+
+
mAh
+
+
A
+
+
Various
Varios
+
+
mAh count
Valor mAh
+
+
FAS Offset
+
+
Persistent mAh
- mAh Constantes
+ mAh constantes
TelemetryAnalog
+
+
Unit
Unidad
+
+
Max Value
- Valor Máximo
+ Valor máx
+
+
Alarm 1
Alarma 1
+
+
+
+
----
+
+
+
+
Yellow
Amarillo
+
+
+
+
Orange
Naranja
+
+
+
+
Red
Rojo
+
+
+
+
<
+
+
+
+
>
+
+
Alarm 2
Alarma 2
+
+
Offset
- Offset
+
+
+
Volts (V)
Voltios (V)
+
+
Amps (A)
Amperios (A)
+
+
Speed (m/s or ft/s)
Velocidad (m/s o pies/s)
+
+
Raw (-)
+
+
Speed (km/h or miles/h)
Velocidad (km/h o millas/h)
+
+
Meters (m or ft)
Metros (m o pies)
+
+
Temp (°)
- Temp (°)
+
+
+
Fuel (%)
Combustible (%)
+
+
mAmps (mA)
miliAmperios (mA)
@@ -12317,18 +14018,20 @@ Too many errors, giving up.
TelemetryCustomScreen
+
+
Custom Screen Type
Personalizar tipo pantalla
None
- Ninguno
+ Ninguno
Numbers
-
+ Números
@@ -12338,25 +14041,33 @@ Too many errors, giving up.
Script
-
+ Script
+
+
Min
Mínimo
+
+
Source
Fuente
+
+
Gauge
Medida
+
+
Max
Máximo
@@ -12364,104 +14075,104 @@ Too many errors, giving up.
TelemetryPanel
-
+
FrSky S.PORT
-
+
FrSky D
-
+
FrSky D (cable)
-
+
Telemetry screen %1
Pantalla telemetría %1
-
+
Source
-
+ Fuente
-
+
Low Alarm
- Alarma Baja
+ Alarma baja
-
+
Critical Alarm
Alarma crítica
-
+
Winged Shadow How High
-
+
Winged Shadow How High (not supported)
Winged Shadow How High (no soportado)
-
+
Alti
-
+
Alti+
-
+
VSpeed
-
+ VelocVert
-
-
-
+
+
+
A1
-
-
-
+
+
+
A2
-
-
+
+
A3
-
-
+
+
A4
-
-
+
+
FAS
-
+
Cells
-
+ Celdas
-
+
---
@@ -12470,448 +14181,649 @@ Too many errors, giving up.
TelemetrySensor
+
+
Form
-
-
-
-
- Custom
- A medida
-
-
-
- Calculated
-
+ Form
+
+
+ Custom
+ Personalizado
+
+
+
+
+
+ Calculated
+ Calculado
+
+
+
+
+
Id
-
+
-
+
+
+
Instance
-
+ Instancia
-
+
+
+
Rx
-
+
-
- Mod.
-
-
-
-
+
+
+
Add
-
+ Suma
-
+
+
+
Average
-
+ Media
-
+
+
+
Min
-
+ Mín
-
+
+
+
Max
-
+ Máx
-
+
+
+
Multiply
-
+ Multiplicar
-
+
+
+
Totalize
-
+ Total
-
+
+
+
Cell
-
+ Celda
-
+
+
+
Consumption
-
+ Consumo
-
+
+
+
Dist
-
+ Distancia
-
+
+
+
Cells Sensor :
-
+ Sensor celdas :
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
---
- ---
+
-
+
+
+
GPS Sensor :
-
+ Sensor GPS:
-
+
+
+
Alt. Sensor :
-
+ Sensor alt:
-
+
+
+
Sensor :
-
+
-
+
+
+
V
-
+
-
+
+
+
A
-
+
-
+
+
+
mA
-
+
-
+
+
+
kt
-
+
-
+
+
+
m/s
-
+
-
+
+
+
ft/s
-
+
-
+
+
+
km/h
-
+
-
+
+
+
mph
-
+
-
+
+
+
m
-
+
-
+
+
+
ft
-
+
-
+
+
+
°C
-
+
-
+
+
+
°F
-
+
-
+
+
+
%
-
+ %
-
+
+
+
mAh
-
+
-
+
+
+
W
-
+
-
+
+
+
mW
-
+
-
+
+
+
dBm
-
+
-
+
+
+
g
-
+
-
+
+
+
°
-
+
-
+
+
+
Rad
-
+
-
+
+
+
mL
-
+
-
+
+
+
US fl.Oz.
-
+
-
+
+
+
Raw (-)
-
+
-
+
+
+
+ TELE##
+
+
+
+
+
+
RPM
-
+
-
+
+
+
+ ml/min
+
+
+
+
+
+
Precision
-
+ Precisión
-
+
+
+
Ratio
-
+ Ratio
-
+
+
+
Blades
- Palas
+ Palas
-
+
+
+
Offset
- Offset
+ Offset
-
+
+
+
Multiplier
-
+
-
+
+
+
Auto Offset
-
+
-
+
+
+
Filter
-
+ Filtro
-
+
+
+
Persistent
-
+ Persistente
-
+
+
+
Positive
- Positivo
+ Positivo
-
+
+
+
Logs
-
+
TelemetrySensorPanel
-
+
+ TELE%1
+
+
+
+
+ Popup menu available
+ Menú desplegable disponible
+
+
+
Lowest
-
+ Menor
-
+
Cell %1
-
+ Celda %1
-
+
Highest
-
+ Mayor
-
+
Delta
-
+
+
+
+
+ Copy
+ Copiar
+
+
+
+ Cut
+ Cortar
+
+
+
+ Paste
+ Pegar
+
+
+
+ Clear
+ Limpiar
+
+
+
+ Clear All
+ Limpiar todo
+
+
+
+ Clear Telemetry Sensor. Are you sure?
+ Limpiar el sensor de telemetría ¿Estás seguro?
+
+
+
+ Clear all Telemetry Sensors. Are you sure?
+ Limpiar todos los sensores de telemetría ¿Estás seguro?
TelemetrySimulator
-
+
+
Telemetry Simulator
-
+ Simulador de telemetría
-
+
+
VFAS
-
+
-
+
+
RSSI
-
+
-
+
+
A1
-
+
-
+
+
A2
-
+
-
+
+
Simulate
- Simular
+ Simular
-
+
+
Replay SD Log File
-
+ Reproducir archivo SD de reporte
-
+
+
Replay rate
-
+ Velocidad de reproducción
-
+
+
Load
-
+ Cargar
-
+
+
|>
-
+
-
+
+
<|
-
+
-
+
+
>
-
+
-
+
+
<-
-
+
-
+
+
X
-
+
-
+
+
Row #
Timestamp
-
+ Col #
+Tiempo
-
+
+
1/5x
- 1/5x
+
-
+
+
5x
- 5x
+
-
+
+
No Log File Currently Loaded
-
+ Actualmente no hay cargado archivo de reporte
-
+
+
RAS
-
+
-
-
-
+
+
+
+
+
+
V / ratio
-
+
-
+
+
Db
-
+
-
+
+
RxBt
-
+
@@ -12927,274 +14839,331 @@ Timestamp
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<html><head/><body><p><br/></p></body></html>
-
+
-
+
+
Tmp1
-
+ Temporizador 1
-
+
+
A3
-
+
-
+
+
A4
-
+
-
+
+
Tmp2
-
+ Temporizador 2
-
+
+
Fuel
- Combustible
+ Combustible
-
-
+
+
+
+
°C
-
+
-
+
+
ml
-
+
-
+
+
%
-
+
-
-
+
+
+
+
Meters
-
+ Metros
-
+
+
Alt
-
+
-
+
+
VSpd
-
+ VelocVertical
-
+
+
m/s
-
+
-
+
+
Fuel Qty
-
+ Cant. combust.
-
-
+
+
+
+
km/h
-
+
-
+
+
Hdg
-
+
-
+
+
ASpd
-
+ VelocAire
-
-
-
+
+
+
+
+
+
G
-
+
-
+
+
GPS
-
+
-
+
+
Lat,Lon
(dec.deg.)
-
+
-
+
+
AccX
-
+
-
+
+
dd-MM-yyyy
hh:mm:ss
-
+
-
+
+
Date
-
+ Fecha
-
+
+
Amps
-
+
-
+
+
AccZ
-
+
-
+
+
GAlt
-
+
-
-
+
+
+
+
Volts
-
+ Voltios
-
+
+
Cels
-
+ Celdas
-
+
+
Curr
-
+
-
+
+
AccY
-
+
-
+
+
GSpd
-
+ VelocTierra
-
+
+
Degrees
-
+ Grados
-
+
+
Setting RSSI to zero simulates telemetry and radio link loss.
-
+ Fijando RSSI a cero simula pérdida de telemetría y conexión con la radio.
-
+
+
Set RSSI to zero when paused.
-
+ Fijar RSSI a cero en pausa.
-
+
+
Stop sending telemetry data when the Telemetry Simulator window is hidden.
-
+ Para de enviar datos de telemetría cuado el simulador esté oculto.
-
+
+
Pause simulation when hidden.
-
+ Pausar simulación cuando se oculte.
-
-
+
+
+
+
RPM
-
+
-
+
+
When enabled, sends any non-blank values as simulated telemetry data.
-
+ Cuando está activado, envía valores no vacíos como datos de telemetría simulados.
Log File
-
+ Archivo Log
LOG Files (*.csv)
-
+ Ficheros LOG (*.csv)
ERROR - invalid file
-
+ ERROR - archivo no válido
@@ -13202,30 +15171,34 @@ hh:mm:ss
Yes
- Si
+ Sí
No
- No
+
<br>Throttle Channel:
- <br>Canal de Acelerador:
+ <br>Canal de acelerador:
Timer
+
+
Countdown
- Cuenta Atrás
+ Cuenta atrás
+
+
Minute Call
- Cada Minuto
+ Cada minuto
@@ -13233,12 +15206,12 @@ hh:mm:ss
TMR
-
+
Timer %1
-
+ Temporizador %1
@@ -13247,22 +15220,23 @@ hh:mm:ss
Use mouse scroll or UP/DOWN arrow keys to change time in small steps.
CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
-
+ Usar el scroll del ratón o teclas ARRIBA/ABAJO para cambiar el tiempo en pequeños pasos.
+CTRL + scroll o AV/RE PÁG para cambiar el tiempo en pasos grandes.
m
-
+
h
-
+
s
-
+
@@ -13285,7 +15259,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Haptic
- Reproducir Haptic
+
@@ -13307,28 +15281,38 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Trainer
+
+
Form
-
+
+
+
Mode
- Modo
+ Modo
+
+
Input
- Entrada
+ Entrada
+
+
Weight
-
+ Peso
+
+
Rud
- Rud
+
@@ -13339,6 +15323,22 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Beeper volume
0 - Quiet. No beeps at all.
@@ -13346,10 +15346,10 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
2 - Normal.
3 - Loud.
4 - Extra loud.
- Volumen Beeper
+ Volumen Beeper
0 - Silencio. Ningun tipo de beep.
-1 - Sin teclas. Los beeps suenan normal pero las teclas de menu no sonarán.
+1 - No teclas. Los beeps suenan normal pero las teclas de menú no sonarán.
2 - Normal.
3 - Alto.
4 - Extra Alto.
@@ -13359,80 +15359,143 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
+
+
+
+
+
+
+
+
Off
- Apagado
+ Apagado
+
+
+
+
+
+
+
+
+= (Sum)
-
+ += (Suma)
+
+
+
+
+
+
+
+
:= (Replace)
- := (Reemplazar)
+ := (Reemplazar)
+
+
+
+
+
+
+
+
chn1
-
+
+
+
+
+
+
+
+
+
chn2
-
+
+
+
+
+
+
+
+
+
chn3
-
+
+
+
+
+
+
+
+
+
chn4
-
+
+
+
Ele
- Ele
+
+
+
Thr
- Thr
+
+
+
Ail
- Ail
+
TrainerSimulator
-
+
+
Trainer simulator
-
+ Simulador de entrenador
@@ -13440,34 +15503,34 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Index
-
+ Índice
Name
- Nombre
+ Nombre
Size
-
+ Tamaño
RX #
-
+
Models
Translators do NOT use accent for this, this is the default category name on Horus.
-
+ Modelos
Model %1
Translators: do NOT use accents here, this is a default model name.
-
+ Modelo %1
@@ -13475,12 +15538,12 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
First Tail Channel:
- Primer Canal de cola:
+ Primer canal de cola:
Second Tail Channel:
- Segundo Canal de cola:
+ Segundo canal de cola:
@@ -13488,42 +15551,42 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Hld Y
-
+
Hold Vertical stick position.
-
+ Mantener la posición vertical del stick.
Fix Y
- Fijar Y
+ Fijar Y
Prevent Vertical movement of stick.
-
+ Evitar el movimiento vertical del stick.
Fix X
- Fijar X
+ Fijar X
Prevent Horizontal movement of stick.
-
+ Evitar el movimiento horizontal del stick.
Hld X
-
+
Hold Horizontal stick position.
-
+ Mantener la posición horizontal del stick.
@@ -13531,7 +15594,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Standard Wing
- Ala estandar
+ Ala estándar
@@ -13589,7 +15652,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Flaps
-
+ Flaps
@@ -13681,7 +15744,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Rotor Type
- Tipo Rotor
+ Tipo rotor
@@ -13703,7 +15766,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Multirotor
-
+ Multirotor
@@ -13728,7 +15791,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Manually check the direction of each control surface and reverse any channels that make controls move in the wrong direction. Remove the propeller/propellers before you try to control your model for the first time.<br>Please note that continuing removes all old model settings!
- Comprobar manualmente la dirección de cada control de superficie y los reversos de cualquier canal para que el control de movimiento no se erroneo. Saca la hélice/hélices antes de intentar controlar tu modelo por primera vez.<br> ¡Por favor tenga en cuenta eliminar los ajustes viejos!
+ Comprobar manualmente la dirección de cada control de superficie y los reversos de cualquier canal para que el control de movimiento no sea erróneo. Saca la hélice/hélices antes de intentar controlar tu modelo por primera vez.<br> ¡Por favor ten en cuenta que continuar eliminar los ajustes anteriores del modelo!
@@ -13743,17 +15806,17 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Most aircraft have a main wing and a tail with control surfaces. Flying wings and delta winged aircraft only have a single wing. The main control surface on a standard wing controls the roll of the aircraft. This surface is called an aileron.<br>The control surface of a delta wing controls both roll and pitch. This surface is called an elevon.
- La mayoría de los aviones tienen un ala principal y una cola con controles de superficie. Volando alas y alas delta solo hay un ala simple. El control principal de superficie en un ala estandar controla el alabeo del avión. Esta superficie se llama alerón.<br> El control de superficie de un ala delta controla ambos alabeo y cabeceo. Esta superficie se llama elevon.
+ La mayoría de los aviones tienen un ala principal y una cola con controles de superficie. Volando alas y alas delta sólo hay un ala simple. El control principal de superficie en un ala estandar controla el alabeo del avión. Esta superficie se llama alerón.<br> El control de superficie de un ala delta controla ambos alabeo y cabeceo. Esta superficie se llama elevon.
Models use one or two channels to control the ailerons.<br>A so called Y-cable can be used to connect a single receiver channel to two separate aileron servos. If your servos are connected by a Y-cable you should select the single-servo option.<br><br>Aileron - Spektrum: CH2, Futaba: CH1
- Los modelos usan 1 o 2 canales para controlar los alerones.<br>Un cable en Y se puede usar para conectar un solo canal del receptor a dos servos separados de los alerones. Si usas servos conectados por un cable Y debes seleccionar la opcion de servo único.<br><br> Alerón Spektrum: CH2, Futaba CH1
+ Los modelos usan 1 o 2 canales para controlar los alerones.<br>Un cable en Y se puede usar para conectar un sólo canal del receptor a dos servos separados de los alerones. Si usas servos conectados por un cable Y debes seleccionar la opcion de servo único.<br><br> Alerón - Spektrum: CH2, Futaba CH1
This wizard assumes that your flaps are controlled by a switch. If your flaps are controlled by a potentiometer you can change that manually later.
- Este asistente asume que tus flaps estan controlados por un switch. Si tus flaps están controlados por un potenciómetro lo puedes cambiar manualmente mas tarde.
+ Este asistente asume que tus flaps estan controlados por un interruptor. Si tus flaps están controlados por un potenciómetro lo puedes cambiar manualmente más tarde.
@@ -13833,12 +15896,12 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
Model Name:
- Nombre Modelo:
+ Nombre modelo:
Model Type:
- Tipo Modelo:
+ Tipo Modelo:
@@ -13855,17 +15918,23 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
burnConfigDialog
+
+
AVRDUDE Location
- Localización AVRDUDE
+ Ubicación AVRDUDE
+
+
Location of AVRDUDE executable
Locatioon of AVRDUDE executable
- Localización del ejecutable AVRDUDE
+ Ubicación del ejecutable AVRDUDE
+
+
Programmer Configuration
Configuration AVRDUDE / SAM-BA
Configuración del programador
@@ -13875,36 +15944,62 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
+
+
+
+
+
+
+
+
The location of the AVRDUDE executable.
The location of the AVRDUDE.EXE executable.
- La localización del ejecutable AVRDUDE.
+ La ubicación del ejecutable AVRDUDE.
+
+
DFU-Util Location
- Localización de la utilidad DFU
+ Ubicación de la utilidad DFU
+
+
+
+
+
+
Use this button to browse and look for the AVRDUDE executable file.
- Usa este botón para explorar y mirar el archivo ejecutable de AVRDUDE.
+ Usa este botón para explorar y ver el archivo ejecutable de AVRDUDE.
+
+
+
+
+
+
Browse...
Explorar...
+
+
Programmer
Programador
+
+
Programmer used for communicating with the controller.
Please consult the programmer's documentation and the AVRDUDE documentation to select the appropriate programmer.
Programador usado para la comunicación con el controlador.
@@ -13912,23 +16007,35 @@ Por favor consulta la documentacion del programador y la documentación de AVRDU
+
+
List all available programmers.
Lista todos los programadores disponibles.
+
+
List Available
- Listado Disponibles
+ Listado disponibles
+
+
+
+
Extra arguments that will be passed to AVRDUDE on every call
- Argumentos extras que deben pasar a AVRDUDE en cada llamada
+ Argumentos extra que deben pasar a AVRDUDE en cada llamada
+
+
+
+
Extra arguments used in AVRDUDE.
This can be used for providing extra information to AVRDUDE.
@@ -13940,69 +16047,99 @@ Por favor solamente usa esto si sabes lo que estás haciendo. No hay control de
+
+
Extra Arguments
Argumentos extra
+
+
Show AVRDUDE help
Mostrar la ayuda de AVRDUDE
+
+
Show Help
- Mostrar Ayuda
+ Mostrar ayuda
+
+
Communication port to the programmer.
Puerto de comunicaciones al programador.
+
+
MCU
+
+
at91sam3s8-9xr
+
+
Alternate device
Dispositivo alternativo
+
+
Use advanced controls
Usar controles avanzados
+
+
+
+
Port
Puerto
+
+
SAM-BA Location
- Localizacon SAM-BA
+ Ubicación SAM-BA
+
+
+
+
Location of sam-ba executable
- Localización del ejecutable sam-ba
+ Ubicación del ejecutable sam-ba
+
+
ARM MCU
+
+
sam-ba serial port
Puerto serie sam-ba
@@ -14026,32 +16163,40 @@ Por favor solamente usa esto si sabes lo que estás haciendo. No hay control de
Select Location
- Seleccionar localización
+ Seleccionar ubicación
List available programmers
- Lista de programadores disponibles
+ Lista de programadores disponibles
Avrdude help
-
+ Ayuda Avrdude
<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.
- <b><u>¡AVISO!</u></b><br>Normalmente el tipo de CPU ees automáticamente elegida para el tipo de firmware.<br>Si cambias el tipo de CPU el eeprom resultante podria ser inconsistente.
+ <b><u>¡AVISO!</u></b><br>Normalmente el tipo de CPU es automáticamente elegida para el tipo de firmware.<br>Si cambias el tipo de CPU el eeprom resultante podría ser inconsistente.
+
+
+
+
CPU of your TX
- CPU a tu TX
+ CPU de tu TX
+
+
+
+
CPU present on your 9x radio
Should be m64 for stock radios
m2560 for v4.1 boards
@@ -14064,87 +16209,101 @@ m2560 para las placas v4.1
joystickDialog
-
+
+
Configure Joystick
- Configurar Joystick
+ Configurar joystick
-
+
+
Ch2
-
+
+
Ch1
-
+
+
Ch4
-
+
+
Ch6
-
+
+
Ch3
-
+
+
Ch5
-
+
+
Ch7
-
+
+
Ch8
-
+
+
Instructions
Instrucciones
-
+
+
Enable
-
+ Activar
-
+
+
Cancel
Cancelar
-
+
+
Back
-
+ Atrás
-
+
+
Start
- Comenzar
+ Inicio
@@ -14153,29 +16312,30 @@ m2560 para las placas v4.1
-
+
+
Ok
Not Assigned
-
+ No asignado
Stick
-
+
Knob/Slider %1
-
+ Knob/Slider %1
No joysticks found
- No se han encopntrado joysticks
+ No se han encontrado joysticks
@@ -14186,158 +16346,48 @@ m2560 para las placas v4.1
Press the Start button to start the stick range calibration procedure.
You may change the channel assignments or inversion at any time.
-
+ Presiona el botón Inicio para empezar el procedimiento de calibración de los stick
+Puedes cambiar la asinación de canales o inversión en cualquier momento.
Move sticks and pots in every direction making full movement
Press Next when finished
-
+ Mueve los sticks y pots hasta el final en todas las direcciones
+Presiona Siguiente al finalizar
Place sticks and pots in middle position.
Press Next when done
-
+ Mueve los sticks y pots a la posición central
+Presiona Siguiente al finalizar
Map joystick channels to controls using comboboxes.
Press Next when done.
-
+ Mapea los canales de joystick a los controles usando las listas deplegables
+Presiona Siguiente al finalizar.
Check inversion checkbox to if necessary to reverse direction.
Press Next when done.
-
+ Revisa la casilla de inversión si es necesario invertir la dirección.
+Presiona Siguiente cuando finalices.
Press OK to save configuration
Press Cancel to abort joystick calibration without saving.
-
+ Presiona OK oara guardar la configuración
+Presiona Cancelar para abortar la calibración del joystick sin guardar.
Calibration not complete, save anyway?
-
-
-
-
- preferencesDialog
-
-
- Preferences
- Preferencias
-
-
-
- Simulator capture folder
- Carpeta de captura de simulador
-
-
-
- Use clipboard only
- Usar sólo portapapeles
-
-
-
-
- ...
-
-
-
-
- Splash library behaviour
- Libreria de pantallas de inicio
-
-
-
- Remember simulator switches
- Recordar los switch en el simulador
-
-
-
- Include companion splashes
- Incluir pantallas de inicio de companion
-
-
-
- Only user defined splashes
- Solo pantallas de inicio definidas por el usuario
-
-
-
- Custom TX splash screen
- Pantalla de inicio personalizada del TX
-
-
-
- Personal splash library
- Pantallas de inicio personales
-
-
-
- Joystick
-
-
-
-
-
- Open Folder
- Abrir Carpeta
-
-
-
- Blue
- Blu
- Azul
-
-
-
- Simu BackLight
- Luz de fondo del simulador
-
-
-
- Green
- Verde
-
-
-
- Red
- Rojo
-
-
-
- Orange
- Naranja
-
-
-
- Yellow
- Amarillo
-
-
-
- Enable
- Activado
-
-
-
- Calibrate
- Calibrar
-
-
-
- Open Image
- Abrir Imagen
-
-
-
- Invert Pixels
- Ivertir Pixeles
+ Calibración incompleta, ¿guardar?
diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts
index 8f69bf1bb..fff65e6d9 100644
--- a/companion/src/translations/companion_fr.ts
+++ b/companion/src/translations/companion_fr.ts
@@ -103,32 +103,32 @@
Profil de radio
-
+
Default Channel Order
Ordre des voies par défaut
-
+
Build Options
Options de compilation
-
+
Menu Language
Langue des menus
-
+
Default Stick Mode
Mode par défaut
-
+
Select Image
Sélectionner une image
-
+
Mode selection:
Mode 1:
@@ -169,526 +169,541 @@ Manche Droit: Profondeur, Direction
-
+
Mode 1 (RUD ELE THR AIL)
Mode 1 (DIR PROF GAZ AIL)
-
+
Mode 2 (RUD THR ELE AIL)
Mode 2 (DIR GAZ PROF AIL)
-
+
Mode 3 (AIL ELE THR RUD)
Mode 3 (AIL PROF GAZ DIR)
-
+
Mode 4 (AIL THR ELE RUD)
Mode 4 (AIL GAZ PROF DIR)
-
+
Splash Screen
Ecran d'accueil
-
-
+
+
The profile specific folder, if set, will override general Backup folder
Dossier de sauvegarde spécifique au profil courant, si défini remplace le paramètre de l'application
-
+
Backup folder
Dossier de sauvegarde
-
+
If set it will override the application general setting
Si défini, remplace le paramètre de l'application pour ce profil
-
+
if set, will override general backup enable
Si défini, remplace le paramètre de l'application pour ce profil
-
+
<html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html>
<html><head/><body><p>Ordre des voies</p><p><br/></p><p>Détermine l'ordre des mixages par défaut sur un nouveau modèle.</p></body></html>
-
+
R E T A
D P G A
-
+
R E A T
D P A G
-
+
R T E A
D G P A
-
+
R T A E
D G A P
-
+
R A E T
D A P G
-
+
R A T E
D A G P
-
+
E R T A
P D G A
-
+
E R A T
P D A G
-
+
E T R A
P G D A
-
+
E T A R
P G A D
-
+
E A R T
P A D G
-
+
E A T R
P A G D
-
+
T R E A
G D P A
-
+
T R A E
G D A P
-
+
T E R A
G P D A
-
+
T E A R
G P A D
-
+
T A R E
G A D P
-
+
T A E R
G A P D
-
+
A R E T
A D P G
-
+
A R T E
A D G P
-
+
A E R T
A P D G
-
+
A E T R
A P G D
-
+
A T R E
A G D P
-
+
A T E R
A G P D
-
-
-
-
-
-
+
+
+
+
+
+
Select Folder
Sélectionner dossier
-
+
+ Show splash screen
+ Afficher l'écran de démarrage
+
+
+
Select Executable
Sélectionner exécutable
-
+
Release channel
Canal de version
-
+
Releases (stable)
Officiel (stable)
-
+
Release candidates (testing)
Candidate (test)
-
+
Nightly builds (unstable)
Nighlty (instable)
-
+
Simulator Volume Gain
Gain de volume du simulateur
-
+
+ Simulator controls
+ Commandes du simulateur
+
+
+
+ Save switch/pot positions on simulator exit
+ Enregistrer les positions des inters/pots à la sortie du simulateur
+
+
+
+ Clear saved positions
+ Effacer les positions enregistrées
+
+
+
Profile Name
Nom du profil
-
+
Clear Image
Effacer l'image
-
+
Append version number to FW file name
Ajouter le numéro de version au nom du fichier téléchargé
-
+
Offer to write FW to Tx after download
Proposer de transférer le firmware à la radio après téléchargement
-
+
Radio Type
Type de radio
-
+
Other Settings
Autres paramètres
-
+
General Settings
Paramètres généraux
-
+
SD Structure path
Chemin de la structure de la carte SD
-
+
Application Settings
Paramètres de l'application
-
- Show splash screen when Companion starts
- Afficher l'écran d'accueil au lancement de Companion
-
-
-
+
Automatic check for Companion updates
Vérifier la présence de mises à jour de Companion automatiquement
-
-
+
+
Enable automatic backup before writing firmware
Sauvegarder les paramètres et modèles automatiquement lors des transferts
-
+
Automatic check for OpenTX firmware updates
Vérifier la présence de mises à jour de firmware automatiquement
-
+
Splash Screen Library
Bibliothèque d'écrans d'accueil
-
+
Google Earth Executable
Exécutable Google Earth
-
+
Only show user splash images
Ne montrer que les images de l'utilisateur
-
+
Show user and companion splash images
Montrer les images de Companion et de l'utilisateur
-
+
User Splash Screens
Ecrans d'accueil personnalisés
-
+
Automatic Backup Folder
Dossier de sauvegardes automatiques
-
+
Simulator Settings
Paramètres du simulateur
-
+
Simulator BackLight
Rétroéclairage du simulateur
-
+
Enable
Actif
-
+
Action on New Model
Action par défaut "Ajout Modèle"
-
+
Use model wizard
Assistant
-
+
Open model editor
Éditer modèle
-
+
Just create the model
Créer modèle
-
+
<html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html>
<html><head/><body><p><b><u>/!\</u> Uniquement pour les radios sans catégories <u>/!\</u></b></p><p>Cette option maintient le comportement des anciennes versions d’OpenTx où les emplacements des modèles vides sont conservés lorsqu'un modèle est supprimé ou déplacé.</p><p>Lorsque cette option est désélectionnée, les autres modèles peuvent être réarrangés pour combler l'écart laissé par le modèle supprimé.</p></body></html>
-
+
most recently used files
fichiers récemment utilisés
-
+
Startup Settings
Paramètres de démarrage
-
+
Remember
Mémoriser
-
+
Output Logs Folder
Dossier des logs sauvegardés
-
+
Remove empty model slots when deleting models (only applies for radios w/out categories)
Supprimer les emplacements vides lors de la suppression de modèles
-
+
Debug Output Logging
Log les messages de debug
-
+
<html><head/><body><p>Keep a log of all debugging messages generated by the desktop Companion/Simulator applications. An OpenTX developer may request this to help diagnose an issue.</p></body></html>
<html><head/><body><p>Garder un log de tous les messages de débogage générés par les applications Companion/Simulateur. Un développeur OpenTX peut demander ce log afin d'aider à diagnostiquer un problème.</p></body></html>
-
+
Application (Companion/Simulator)
Application (Companion/Simulateur)
-
+
<html><head/><body><p>Keep a log of all messages generated by the radio firmware when running in Simulator. This is the same information one would also see in the Simulator <span style=" font-style:italic;">Debug Output</span> window.</p></body></html>
<html><head/><body><p>Conserver un log de tous les messages générés par le firmware radio lors de l'exécution du Simulateur. C'est la même information visible depuis le Simulateur dans la <span style=" font-style:italic;">Fenêtre de débogage</span>.</p></body></html>
-
+
Radio Firmware (in Simulator)
Firmware radio (Simulateur)
-
+
+ Prompt for radio profile
+ Afficher le choix "profil radio" au démarrage
+
+
+
Blue
Bleu
-
+
Green
Vert
-
+
Red
Rouge
-
+
Orange
Orange
-
+
Yellow
Jaune
-
+
Screenshot capture folder
Dossier des captures d'écran
-
+
Joystick
-
+
Calibrate
Calibrer
-
+
Only capture to clipboard
Capturer dans le presse-papiers uniquement
-
- Remember simulator switch values
- Mémoriser les positions des inters du simulateur
-
-
-
+
My Radio
Ma radio
-
+
<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>
<p><b>Vous ne pouvez pas changer de type de radio ou modifier les options de compilation tant que les changements ne sont pas sauvegardés. Que souhaitez-vous faire?</b></p> <ul><li><i>Sauvegarder tout</i> - Enregistrez le(s) fichier(s) ouvert(s) avant d'enregistrer les paramètres.<li><li><i>Réinitialiser</i> - Revenir aux précédentes options de type et de compilation de la radio avant d'enregistrer les paramètres</li><li><i>Annuler</i> - Retournez dans la boîte de dialogue de l'éditeur de paramètres.</li></ul>
-
+
Select your snapshot folder
Sélectionner le dossier où stocker les captures d'écran
-
+
Note: Nightly builds are not available in this version, Release/RC update channel will be used.
Remarque: la version " nightly" n'est pas disponible dans cette version. Le canal de mise à jour "officiel" sera utilisé.
-
-
+
+
No joysticks found
Aucun Joystick trouvé
-
+
EMPTY: No radio settings stored in profile
VIDE: Aucune donnée stockée dans le profil
-
+
AVAILABLE: Radio settings of unknown age
DISPONIBLE: Paramètres enregistrés à une date inconnue
-
+
AVAILABLE: Radio settings stored %1
DISPONIBLE: Paramètres enregistrés le %1
-
+
Select your library folder
Sélectionner le dossier de bibliothèque
-
-
+
+
Select your Models and Settings backup folder
Sélectionner le dossier dans lequel une sauvegarde des paramètres et modèles sera placée automatiquement lors de chaque opération
-
+
Select a folder for application logs
Sélectionner un dossier pour le log des applications
-
+
Select Google Earth executable
Sélectionner l'emplacement de l'exécutable Google Earth
-
+
Select the folder replicating your SD structure
Sélectionner un dossier contenant une copie des dossiers de la carte SD
-
+
Open Image to load
Ouvrir l'image à charger
-
+
Images (%1)
Images (%1)
@@ -728,58 +743,58 @@ Manche Droit: Profondeur, Direction
Boards
-
+
Left Horizontal
Gauche Horizontal
-
+
Left Vertical
Gauche Vertical
-
+
Right Vertical
Droit Vertical
-
+
Right Horizontal
Droit Horizontal
-
+
Aux. 1
-
+
Aux. 2
-
-
+
+
Unknown
Inconnu
-
+
Rud
Dir
-
+
Ele
Prf
-
+
Thr
Gaz
-
+
Ail
@@ -888,50 +903,65 @@ Manche Droit: Profondeur, Direction
-
+
+ Delete Channel. Are you sure?
+ Supprimer la Voie. Êtes-vous sûr?
+
+
+
Copy
Copier
-
+
Cut
Couper
-
+
Paste
Coller
-
+
Clear
Effacer
-
+
Insert
Insérer
-
+
Delete
Supprimer
-
+
Move Up
Monter
-
+
Move Down
Descendre
-
+
Clear All
Effacer Tout
+
+
+ Clear Channel. Are you sure?
+ Effacer la Voie. Êtes-vous sûr?
+
+
+
+ Clear all Channels. Are you sure?
+ Effacer toutes les Voies. Êtes-vous sûr?
+
ChecklistDialog
@@ -1346,7 +1376,7 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
CurveData
-
+
CV
CB
@@ -1486,77 +1516,107 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
Nom de la courbe
-
+
Curve %1
Courbe %1
-
+
Popup menu available
Menu contextuel disponible
-
+
%1 points
-
+
Linear
Linéaire
-
+
Single Expo
Expo simple
-
+
Symmetrical f(x)=-f(-x)
Symétrique f(x)=-f(-x)
-
+
Symmetrical f(x)=f(-x)
Symétrique f(x)=f(-x)
-
+
Copy
Copier
-
+
+ Cut
+ Couper
+
+
+
Paste
Coller
-
+
Clear
Effacer
-
- Clear all curves
- Effacer toutes les courbes
+
+ Insert
+ Insérer
-
- Are you sure you want to reset curve %1?
- Etes-vous sûr de vouloir effacer la courbe %1 ?
+
+ Delete
+ Supprimer
-
- Are you sure you want to reset all curves?
- Etes-vous sûr de vouloir effacer toutes les courbes ?
+
+ Move Up
+ Monter
-
+
+ Move Down
+ Descendre
+
+
+
+ Clear All
+ Effacer Tout
+
+
+
+ Clear Curve. Are you sure?
+ Effacer la Courbe. Êtes-vous sûr?
+
+
+
+ Clear all Curves. Are you sure?
+ Effacer toutes les Courbes. Êtes-vous sûr?
+
+
+
+ Delete Curve. Are you sure?
+ Supprimer la Courbe. Êtes-vous sûr?
+
+
+
Editing curve %1
Édition de la courbe %1
-
+
Not enough free points in EEPROM to store the curve.
Pas assez de points disponibles en mémoire pour enregistrer la courbe.
@@ -1581,7 +1641,7 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
Trainer
- Écolage
+ Écolage Manches
@@ -1605,193 +1665,198 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
+ Trainer Channels
+ Écolage Channels
+
+
+
Instant Trim
Trims instantanés
-
+
Play Sound
Jouer Son
-
+
Haptic
Vibreur
-
+
Reset
Remise à zéro
-
+
Set Timer %1
Définir chrono %1
-
+
Vario
-
+
Play Track
Jouer fichier
-
+
Play Both
Jouer les deux
-
+
Play Value
Lire valeur
-
+
Play Script
Exécuter script
-
+
SD Logs
Logs SD
-
+
Volume
-
+
Backlight
Rétroéclairage
-
+
Screenshot
Capture d'écran
-
+
Background Music
Musique de fond
-
+
Background Music Pause
Pause musique de fond
-
+
Adjust %1
Ajuster %1
-
+
SetFailsafe Int. Module
Définir failsafe module interne
-
+
SetFailsafe Ext. Module
Définir failsafe module externe
-
+
RangeCheck Int. Module
Test portée module interne
-
+
RangeCheck Ext. Module
Test portée module externe
-
+
Bind Int. Module
Bind module interne
-
+
Bind Ext. Module
Bind module externe
-
+
Timer1
Chrono 1
-
+
Timer2
Chrono 2
-
+
Timer3
Chrono 3
-
+
Flight
Vol
-
+
Telemetry
Télémétrie
-
+
Rotary Encoder
Sélecteur Rotatif
-
+
REa
-
+
REb
-
+
s
-
-
-
+
+
+
<font color=red><b>Inconsistent parameter</b></font>
<font color=red><b>Paramètre inconsistant</b></font>
-
+
Value
Valeur
-
+
played once, not during startup
!1x Lu une fois, mais pas à la mise en route
-
+
repeat(%1s)
Répéter chaque %1s
-
+
DISABLED
DESACTIVE
-
+
CFN
FPN
@@ -1851,70 +1916,85 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
%1
-
+
+ Delete Special Function. Are you sure?
+ Supprimer la Fonction Spéciale. Êtes-vous sûr?
+
+
+
Copy
Copier
-
+
Cut
Couper
-
+
Paste
Coller
-
+
Clear
Effacer
-
+
Insert
Insérer
-
+
Delete
Supprimer
-
+
Move Up
Monter
-
+
Move Down
Descendre
-
+
Clear All
Effacer Tout
-
+
Value
Valeur
-
+
Source
Source
-
+
GVAR
VG
-
+
Increment
Incrément
+
+
+ Clear Special Function. Are you sure?
+ Effacer la Fonction Spéciale. Êtes-vous sûr?
+
+
+
+ Clear all Special Functions. Are you sure?
+ Supprimer toutes les Fonctions Spéciales. Êtes-vous sûr?
+
CustomizeSplashDialog
@@ -2104,23 +2184,23 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
La source %1 n'est pas supportée sur cette plateforme !
-
+
OpenTX only accepts %1 points in all curves
OpenTX n'accepte que %1 points au maximum entre toutes les courbes
-
+
OpenTx only accepts %1 points in all curves
OpenTX n'accepte que %1 points au maximum entre toutes les courbes
-
-
+
+
OpenTX on this board doesn't accept this function
OpenTX ne supporte pas cette fonction sur cette carte
-
+
OpenTX doesn't accept this radio protocol
OpenTX ne supporte pas ce protocole radio
@@ -2200,12 +2280,12 @@ Pour <b>retirer un filtre de l'historique</b>, sélectionnez-le
Basculer le filtre on/off.
-
+
<html><head><style>kbd {background-color: palette(alternate-base); font-size: large; white-space: nowrap;}</style></head><body><p>The filter supports two syntax types: basic matching with common wildcards as well as full Perl-style (<code>pcre</code>) Regular Expressions.</p><p>By default a filter will only show lines which match (<b>inclusive</b>). To make an <b>exclusive</b> filter which removes matching lines, prefix the filter expression with a <kbd>!</kbd> (exclamation mark).</p><p>To use <b>Regular Expressions</b> (RegEx), prefix the filter text with a <kbd>/</kbd> (slash) or <kbd>^</kbd> (up caret). <ul><li>Put the <kbd>/</kbd> or <kbd>^</kbd> after the exclusive <kbd>!</kbd> indicator if you're using one.</li><li>By default the match is case-sensitive. To make it insensitive, add the typical <kbd>/i</kbd> (slash i) operator at the end of your RegEx.</li><li>If you use a caret (^) to denote a RegEx, it will become part of the Reg. Ex. (that is, matches from start of line).</li><li>If the RegEx is invalid, the filter edit field should show a red border and you will not be able to enable the filter.</li><li>A useful resource for testing REs (with a full reference) can be found at <a href="http://www.regexr.com/">http://www.regexr.com/</a></li></ul></p><p>To use <b>basic matching</b> just type any text.<ul><li>Wildcards: <kbd>*</kbd> (asterisk) matches zero or more of any character(s), and <kbd>?</kbd> (question mark) matches any single character.</li><li>The match is always case-insensitive.</li><li>The match always starts from the beginning of a log line. To ignore characters at the start, use a leading <kbd>*</kbd> wildcard.</li><li>A trailing <kbd>*</kbd> is always implied (that is, matches anything to the end of the log line). To avoid this, use a RegEx.</li><li>You can match literal wildcard characters by prefixing them with a <kbd>\</kbd> (backslash) character (eg. "foo\*bar" matches "foo*bar").</li></ul></p><p>After <b>editing text</b>, press ENTER or TAB key (or click anywhere outside the box) to update the filter.</p><p>To <b>remove an entry</b> from the filter selector list, first choose it, and while in the line editor press <kbd>Shift-Delete</kbd> (or <kbd>Shift-Backspace</kbd>) key combination. The default filters cannot be removed. Up to 50 filters are stored.</p></body></html>
<html><head><style>kbd {background-color: palette(alternate-base); font-size: large; white-space: nowrap;}</style></head><body><p>Le filtre supporte deux types de syntaxes: la recherche simple utilisant les métacaractères ou la recherche avancée utilisant les expressions régulières (<code>RegEx</code>) de type Perl.</p><p>Par défaut, un filtre ne montre que les lignes qui correspondent (<b>inclusif</b>). Pour faire un filtre <b>exclusif</b> qui supprime les lignes de correspondance, préfixez l'expression du filtre avec un <kbd>!</kbd> (point d'exclamation).</p><p>Pour utiliser les <b>Expressions Régulières</b> (RegEx), préfixez le texte du filtre avec un <kbd>/</kbd> (slash) ou <kbd>^</kbd> (accent circonflexe).<ul><li>Il faut mettre le <kbd>!</kbd> <u>avant</u> le <kbd>/</kbd> ou <kbd>^</kbd> dans le cas d'un filtre exclusif.</li><li>Par défaut, la correspondance est sensible à la casse (ex: a ≠ A). Pour la rendre insensible (ex: a = A), ajoutez l'opérateur typique <kbd>/i</kbd> (slash i) à la fin de votre RegEx.</li><li>Si vous utilisez un <kbd>^</kbd> pour désigner une RegEx, il deviendra une partie de la RegEx (<kbd>^</kbd> est le caractère de début de chaîne).</li><li>Si la RegEx n'est pas valide, le champ d'édition du filtre affichera une bordure rouge et vous ne pourrez pas activer le filtre.</li><li>Une ressource utile pour tester les RegExs (avec une référence complète) peut être trouvée sur le site <a href="http://www.regexr.com/">http://www.regexr.com/</a> (tutoriel en français: <a href="http://perl.mines-albi.fr/DocFr/perlretut.html">Expressions rationnelles/régulières en Perl</a>)</li></ul></p><p>Pour utiliser la <b>recherche simple</b>, tapez simplement le texte recherché.<ul><li>Métacaractères: le quantificateur <kbd>*</kbd> (astérisque) correspond à zéro ou plus de n'importe quel caractère, et le quantificateur <kbd>?</kbd> (point d'interrogation) correspond à un caractère unique.</li><li>La correspondance est toujours sensible à la casse.</li><li>La correspondance commence toujours au début du Log. Pour ignorer les caractères au début, utilisez le métacaractère <kbd>*</kbd>.</li><li>Un métacaractère <kbd>*</kbd> est implicitement ajouté à la fin (ainsi, toutes les correspondances valides soient bien affichées jusqu'à la fin du Log). Si vous voulez éviter ce métacaractère implicite, il faut utiliser une RegEx.</li><li>Pour rechercher un caractère qui est lui-même un métacaractère, il faut préfixer avec un <kbd>\</kbd> (backslash) (ex: "<i>toto\*titi</i>" correspond à "<i>toto*titi</i>").</li></ul></p><p>Quand l'<b>édition</b> est terminée, appuyez sur la touche ENTRER ou TAB (ou cliquez n'importe où à l'extérieur du champ du filtre) afin de mettre à jour le filtre.</p><p>Pour <b>retirer un filtre de l'historique</b>, sélectionnez-le d'abord, puis faite le raccourci clavier <kbd>Shift-Suppr</kbd> (ou <kbd>Shift-Retour Arrière</kbd>). Les filtres par défaut ne peuvent pas être effacés. Jusqu'à 50 filtres peuvent être mémorisés.</p></body></html>
-
+
Debug Console Filter Help
Aide sur les filtres pour la console de débogage
@@ -2857,267 +2937,279 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont
Firmware
-
+
Channel values displayed in us
Positions de voies affichées en µs
-
+
No OverrideCH functions available
Désactive la fonction spéciale "Remplacer VOIExx"
-
+
Possibility to enable FAI MODE (no telemetry) at field
Possibilité d'activer le mode FAI (télémétrie désactivée) sur le terrain
-
+
FAI MODE (no telemetry) always enabled
Mode FAI (télémétrie toujours désactivée)
-
+
Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015
Masque le protocole D8. Légalement obligatoire sur les radios Européennes importées après le 1er janvier 2015
-
-
+
+
Disable HELI menu and cyclic mix support
Supprimer le menu HELICO et les mixages cycliques
-
-
+
+
Disable Global variables
Supprimer le support des variables globales
-
-
+
+
Enable Lua custom scripts screen
Activer l'écran des scripts Lua personnalisés
-
+
Support for PPM internal module hack
Support du remplacement du module interne par un module PPM
-
+
Use alternative SQT5 font
Utiliser la police alternative SQT5
-
+
+
Disable RAS (SWR)
Désactiver le RAS (SWR). Utile uniquement pour les X9D+ avec un RAS/SWR non fonctionnel
-
+
Pots use in menus navigation
Support de la navigation dans les menus avec les POTS
-
+
FrSky Taranis X9D+
-
+
FrSky Taranis X9D+ 2019
-
+
FrSky Taranis X9D
-
+
Haptic module installed
Module vibreur installé
-
+
FrSky Taranis X9E
-
+
Confirmation before radio shutdown
Confirmation avant l'arrêt de la radio
-
+
Horus gimbals installed (Hall sensors)
Manches Horus à effet HALL installés
-
+
FrSky Taranis X9-Lite
-
+
FrSky Taranis X9-Lite S
-
+
FrSky Taranis X7 / X7S
-
+
+ FrSky Taranis X7 / X7S Access
+
+
+
+
FrSky Taranis X-Lite S/PRO
-
+
FrSky Taranis X-Lite
-
+
FrSky Horus X10 / X10S
-
-
+
+
Support for ACCESS internal module replacement
Prise en charge du module de remplacement interne ACCESS
-
+
FrSky Horus X10 Express / X10S Express
-
+
FrSky Horus X12S
-
+
Use ONLY with first DEV pcb version
Exclusivement pour les Horus DEV
-
- Enable non certified R9M firmwares
- Activer les firmwares R9M non certifiés
-
-
-
-
+
+
Support for MULTI internal module
Prise en charge du module MULTI interne
-
+
+
Support for bluetooth module
Prise en charge du module Bluetooth
-
+
+ Radiomaster TX16s / TX16s Hall / TX16s Masterfire
+
+
+
+
+ Support internal GPS
+ Prise en charge du GPS interne
+
+
+
Turnigy 9XR-PRO
-
+
Enable HELI menu and cyclic mix support
Activer le menu hélico et les mixages CCPM
-
+
Global variables
Variables globales
-
+
Enable non certified firmwares
Activer les firmwares non certifiés
-
+
In model setup menus automatically set source by moving the control
Sélectionner les sources des mixeurs en bougeant le contrôle désiré
-
+
In model setup menus automatically set switch by moving the control
Sélectionner les interrupteurs en bougeant le contrôle désiré
-
+
No graphical check boxes and sliders
Pas de cases à cocher et de curseurs graphiques
-
+
Battery graph
Graphique de la batterie
-
+
Don't use bold font for highlighting active items
Ne pas mettre les lignes actives en gras
-
+
Turnigy 9XR with m128 chip
Turnigy 9XR avec une puce m128
-
+
Turnigy 9XR
-
+
9X with stock board
9X avec carte mère d'origine
-
+
Enable resetting values by pressing up and down at the same time
Permet la remise à zéro des valeurs en pressant haut-bas en même temps, valeur min avec gauche/bas, valeur max avec haut/droite, inversion avec gauche/droite
-
+
9X with stock board and m128 chip
Carte 9x avec un chip m128
-
+
9X with AR9X board
9X avec carte AR9X
-
+
Jumper T12 / T12 Pro
-
+
Jumper T16 / T16+ / T16 Pro
-
+
9X with Sky9x board
9X avec carte Sky9x
-
+
9X with Gruvin9x board
9X avec carte Gruvin9x
-
+
DIY MEGA2560 radio
Radio DIY à base de MEGA2560
@@ -3592,11 +3684,21 @@ Vous utilisez actuellement:
Switch
Interrupteur
+
+
+ trim6
+
+
+
+
+ trim5
+
+
FlightModeData
-
+
FM
PV
@@ -3604,122 +3706,200 @@ Vous utilisez actuellement:
FlightModePanel
-
+
Rotary Encoder %1
Sélecteur Rotatif %1
-
+
Name
Nom
-
+
Value source
Source valeur
-
+
Value
Valeur
-
+
Unit
-
+
Prec
-
+
Min
Min
-
+
Max
Max
-
+
GVAR%1
VG%1
-
+
+ Warning: Global variable links back to itself. Flight Mode 0 value used.
+ Avertissement: la Variable Globale boucle sur elle-même. La Phase de Vol 0 est utilisée.
+
+
+
+ Warning: Rotary encoder links back to itself. Flight Mode 0 value used.
+ Avertissement: le Sélecteur Rotatif boucle sur lui-même. La Phase de Vol 0 est utilisée.
+
+
+
+
+ Copy
+ Copier
+
+
+
+
+ Cut
+ Couper
+
+
+
+
+ Paste
+ Coller
+
+
+
+
+ Insert
+ Insérer
+
+
+
+
+ Delete
+ Supprimer
+
+
+
+
+ Move Up
+ Monter
+
+
+
+
+ Move Down
+ Descendre
+
+
+
+
+ Clear All
+ Effacer Tout
+
+
+
+ Clear Flight Mode. Are you sure?
+ Effacer la Phase de Vol. Êtes-vous sûr?
+
+
+
+ Clear all Flight Modes. Are you sure?
+ Effacer toutes les Phases de Vol. Êtes-vous sûr?
+
+
+
+ Delete Flight Mode. Are you sure?
+ Supprimer la Phase de Vol. Êtes-vous sûr?
+
+
+
+ Clear selected Global Variable across all Flight Modes. Are you sure?
+ Effacer les Variables Globales selectionnées à travers toutes les Phases de Vol. Êtes-vous sûr?
+
+
+
+ Clear all Global Variables for all Flight Modes. Are you sure?
+ Effacer toutes les Variables Globales pour toutes les Phases de Vol. Êtes-vous sûr?
+
+
+
+ Clear all Global Variables for this Flight Mode. Are you sure?
+ Effacer toutes les Variables Globales pour cette Phase de Vol. Êtes-vous sûr?
+
+
+
Popup enabled
Indication activée
-
+
+
Popup menu available
Menu contextuel disponible
-
+
Trim disabled
Trim désactivé
-
+
Own Trim
Valeur indépendante
-
+
Use Trim from Flight mode %1
Utiliser le trim de la phase de vol %1
-
+
Use Trim from Flight mode %1 + Own Trim as an offset
Utiliser le trim de la phase de vol %1 + une valeur indépendante additionnée
-
+
0._
-
+
0.0
-
-
- &Clear
- &Effacer
-
-
-
-
+
+
Clear
Effacer
-
-
- Clear all current Flight Mode properties?
- Effacer tout les modes de vols ?
-
FlightModesPanel
-
+
Flight Mode %1
Phase de vol %1
-
+
(%1)
-
+
(default)
(par défaut)
@@ -4047,7 +4227,7 @@ Communs à tous les modèles d'une même EEPROM.
GeneralSettings
-
+
Radio Settings
Paramètres de la radio
@@ -4392,11 +4572,6 @@ Mode 4:
Owner Registration ID
Enregistrement ID du propriétaire
-
-
- aaaaaaAA
-
-
R E T A
@@ -4714,6 +4889,11 @@ Plage de valeurs: 5v...10v
Si différent de 0, émission d'un bip sonore régulier si aucune action n'a été effectuée sur l'émetteur depuis le temps spécifié (en minutes).
Réinitialisation en agissant sur n'importe lequel des manches / touches de navigation.
+
+
+ nnnnnnNN
+
+
min
@@ -5545,25 +5725,27 @@ Cette fonction ne peut pas être désactivée sur la radio.
InputsPanel
-
+
+
Move Up
Monter
-
+
Ctrl+Up
Ctrl+Haut
-
+
+
Move Down
Descendre
-
+
Ctrl+Down
Ctrl+Bas
@@ -5573,110 +5755,141 @@ Cette fonction ne peut pas être désactivée sur la radio.
Effacer toutes les entrées
-
- Not enough available inputs!
- Pas assez d'entrées disponibles !
+
+ Not enough available Inputs!
+ Pas assez d'Entrées disponibles!
-
- Delete Selected Inputs?
- Supprimer les entrées sélectionnées ?
+
+ Delete selected Inputs. Are you sure?
+ Supprimer les Entrées selectionnés. Êtes-vous sûr?
-
+
+ Lines
+ Linéaire
+
+
+
&Add
&Ajouter
-
+
Ctrl+A
Ctrl+A
-
+
&Edit
&Édition
-
+
Enter
Entrée
-
+
&Delete
&Supprimer
-
+
+
Delete
Supprimer
-
+
&Copy
&Copier
-
+
Ctrl+C
-
+
&Cut
&Couper
-
+
Ctrl+X
-
+
&Paste
&Coller
-
+
Ctrl+V
-
+
Du&plicate
Du&pliquer
-
+
Ctrl+U
-
- Clear Inputs?
- Effacer toutes les entrées ?
+
+ Input
+ Entrée
-
- Really clear all the inputs?
- Voulez-vous vraiment effacer toutes les entrées ?
+
+ Insert
+ Insérer
+
+
+
+ Clear
+ Effacer
+
+
+
+ Clear All
+ Effacer Tout
+
+
+
+ Clear all Inputs. Are you sure?
+ Effacer toutes les Entrées. Êtes-vous sûr?
+
+
+
+ Clear Input. Are you sure?
+ Effacer l'Entrée. Êtes-vous sûr?
+
+
+
+ Delete Input. Are you sure?
+ Supprimer l'Entrée. Êtes-vous sûr?
LimitData
-
+
INV
-
+
NOR
-
+
CH
VOIE
@@ -5815,69 +6028,104 @@ Cette fonction ne peut pas être désactivée sur la radio.
LogicalSwitchesPanel
-
+
V1
-
+
V2
-
+
Duration
Durée
-
+
Delay
Délai
-
+
Function
Fonction
-
+
AND Switch
ET supplémentaire
-
+
Popup menu available
Menu contextuel disponible
-
+
(instant)
-
+
(infinite)
(infini)
-
- &Delete
- &Supprimer
-
-
-
- &Copy
- &Copier
-
-
-
- &Cut
- &Couper
+
+ Delete Logical Switch. Are you sure?
+ Supprimer l'Interrupteur Logique. Êtes-vous sûr?
- &Paste
- &Coller
+ Copy
+ Copier
+
+
+
+ Cut
+ Couper
+
+
+
+ Paste
+ Coller
+
+
+
+ Clear
+ Effacer
+
+
+
+ Insert
+ Insérer
+
+
+
+ Delete
+ Supprimer
+
+
+
+ Move Up
+ Monter
+
+
+
+ Move Down
+ Descendre
+
+
+
+ Clear All
+ Effacer Tout
+
+
+
+ Clear all Logical Switches. Are you sure?
+ Effacer tous les Interrupteurs Logiques. Êtes-vous sûr?
@@ -6025,8 +6273,8 @@ Les colonnes contenant l'altitude "GAlt" et la vitesse "GSpd
- total duration
- durée totale
+ time span
+ plage de temps
@@ -6057,79 +6305,79 @@ Les colonnes contenant l'altitude "GAlt" et la vitesse "GSpd
MainWindow
-
-
+
+
Edit
Édition
-
-
+
+
File
Fichier
-
+
New release available
Nouvelle version disponible
-
+
Error opening file %1:
%2.
Erreur à l'ouverture du fichier %1:
%2.
-
+
Compilation server too busy, try later
Serveur de compilation surchargé, veuillez réessayer plus tard
-
+
Unknown server failure, try later
Erreur inconnue du serveur de compilation, veuillez réessayer plus tard
-
+
Do you want to write the firmware to the radio now ?
Voulez vous transférer le firmware à la radio maintenant ?
-
-
+
+
Yes
Oui
-
-
+
+
No
Non
-
-
+
+
Release Notes
Notes de version
-
+
Compare models
Comparer les modèles
-
+
Show fuses dialog
Afficher les paramètres des fusibles
-
+
A monochrome black icon theme
Thème avec icônes monochromes noires
-
+
A new version of %1 firmware is available:
- current is %2
- newer is %3
@@ -6146,511 +6394,511 @@ Voulez vous la télécharger maintenant ?
Nous recommandons de lire attentivement les notes de version à l'aide du bouton ci-dessous, celles-ci peuvent contenir des infos importantes concernant les changements effectués depuis la version précédente.
-
-
+
+
Synchronize SD
Synchroniser la carte SD
-
+
New
Nouveau
-
+
Open...
Ouvrir...
-
+
A monochrome white icon theme
Thème avec icônes monochromes blanches
-
+
A monochrome blue icon theme
Thème avec icônes monochromes bleues
-
+
Small
Petites
-
+
Use small toolbar icons
Petites icônes de barre d'outils
-
+
Use normal size toolbar icons
Icônes de barre d'outils normales
-
+
Normal
Normales
-
+
Use big toolbar icons
Grosses icônes de barre d'outils
-
+
Big
Grandes
-
+
Use huge toolbar icons
Immenses icônes de barre d'outils
-
+
Huge
Immenses
-
+
List programmers...
Lister les programmateurs...
-
+
Fuses...
Fusibles...
-
-
+
+
Read Firmware from Radio
Lire le firmware de la radio
-
+
Read firmware from Radio
Lire le firmware de la radio
-
+
Write Firmware to Radio
Transférer le firmware à la radio
-
+
Write firmware to Radio
Transférer le firmware à la radio
-
+
Add Radio Profile
Ajouter un profil de radio
-
+
Manuals and other Documents
Manuels et documents
-
+
Open the OpenTX document page in a web browser
Ouvre la page de documentation d'OpenTX dans un navigateur
-
+
Write Models and Settings To Radio
Transférer les paramètres et modèles vers la radio
-
+
Write Models and Settings to Radio
Transférer les paramètres et modèles vers la radio
-
-
+
+
Read Models and Settings from Radio
Lire les paramètres et modèles depuis la radio
-
+
OpenTX Companion %1 - Radio: %2 - Profile: %3
OpenTX Companion %1 - Radio: %2 - Profil: %3
-
+
List of recently used files
Liste des fichiers récemment utilisés
-
+
Radio Profiles
Profil radio
-
+
Create or Select Radio Profiles
Créer ou Sélectionner un profil radio
-
+
Configure Communications...
Configurer les communications...
-
+
Configure software for communicating with the Radio
Configurer le programme gérant les communications avec la radio
-
+
Write Backup to Radio
Transférer une sauvegarde à la radio
-
+
Write Backup from file to Radio
Transférer une sauvegarde à la radio
-
+
Backup Radio to File
Sauvegarder la radio
-
+
Save a complete backup file of all settings and model data in the Radio
Créer une copie de sauvegarde de tous les paramètres et modèles de la radio
-
+
Contributors...
Contributeurs...
-
+
A tribute to those who have contributed to OpenTX and Companion
Remerciements à tout ceux qui ont contribué à OpenTX et Companion
-
+
SD card synchronization
Synchronisation de la carte SD
-
+
Recent Files
Fichiers récents
-
+
Set Icon Theme
Choisir le thème d'icônes
-
+
Set Icon Size
Choisir la taille des icônes
-
+
Write
Ecrire
-
+
A new version of Companion is available (version %1)<br>Would you like to download it?
Une nouvelle version de Companion est disponible (version %1)<br>Voulez-vous la télécharger ?
-
+
OpenTX Home Page: <a href='%1'>%1</a>
Page d'accueil d'OpenTX: <a href='%1'>%1</a>
-
+
If you've found this program useful, please support by <a href='%1'>donating</a>
Si vous trouvez ce programme utile, merci de le supporter par une <a href='%1'>donation</a>
-
+
Ready
Prêt
-
+
Show the application's About box
Afficher la fenêtre "A propos" de l'application
-
-
+
+
File loaded
Fichier chargé
-
-
+
+
Open Models and Settings file
Ouvrir un fichier de paramètres et modèles
-
+
File saved
Fichier sauvegardé
-
+
Read Models and Settings From Radio
Lire les paramètres et modèles depuis la radio
-
+
Not enough flash available on this board for all the selected options
Pas assez de place disponible pour les options sélectionnées
-
+
Compilation server temporary failure, try later
Erreur de compilation sur le serveur, veuillez réessayer plus tard
-
+
Compilation error
Erreur de compilation
-
+
Invalid firmware
Firmware invalide
-
+
Invalid board
Carte non valide
-
+
Invalid language
Language non valide
-
+
Some text will not be translated until the next time you start Companion. Please note that some translations may not be complete.
Certains textes ne seront pas traduits avant le prochain redémarrage de Companion. Veuillez noter que certaines traductions peuvent ne pas être complètes.
-
+
Models and Settings read
Lecture des modèles et paramètres
-
+
Companion update check failed, new version information not found.
La vérification de mise à jour de Companion a échoué, les infos sur une nouvelle version sont introuvables.
-
+
Firmware update check failed, new version information not found or invalid.
La vérification de mise à jour du Firmware a échoué, les infos sur une nouvelle version sont introuvables ou invalides.
-
+
Local Folder
Dossier "Local"
-
+
Radio Folder
Dossier "Radio"
-
-
+
+
This function is not yet implemented
Cette fonction n'est pas implémentée pour l'instant
-
+
Save Radio Backup to File
Sauvegarder la radio
-
+
Read Radio Firmware to File
Sauvegarder le firmware de la radio
-
+
The OpenTX Companion project was originally forked from <a href='%1'>eePe</a>
Le projet OpenTX Companion a été créé à partir d'<a href='%1'>eePe</a>
-
+
Copyright OpenTX Team
-
+
Create a new Models and Settings file
Créer un nouveau fichier de paramètres et modèles
-
-
+
+
Save Models and Settings file
Enregistrer le fichier de paramètres et modèles
-
+
Save
Enregistrer
-
+
Save As...
Enregistrer sous...
-
+
Close
Fermer
-
+
Close Models and Settings file
Fermer le fichier de paramètres et modèles
-
+
Exit the application
Quitter l'application
-
+
Exit
Quitter
-
+
Create a new Radio Settings Profile
Créer un nouveau profil de paramètres et modèles
-
+
Copy Current Radio Profile
Copier le profil radio actuel
-
+
Duplicate current Radio Settings Profile
Dupliquer les paramètres radio du profil actuel
-
+
Delete the current Radio Settings Profile
Supprimer les paramètres radio du profil actuel
-
+
Use default system language.
Utiliser le langage système par défaut.
-
+
Use %1 language (some translations may not be complete).
Utiliser la langue %1 (certaines traductions peuvent être incomplètes).
-
+
Classical
Classique
-
+
Diskimage (*.dmg)
Image disque (*.dmg)
-
+
Would you like to open the disk image to install the new version?
Voulez-vous ouvrir l'image disque afin d'installer la nouvelle version ?
-
+
Executable (*.exe)
Exécutable (*.exe)
-
-
+
+
Would you like to launch the installer?
Voulez-vous lancer l'installateur ?
-
+
No Companion release candidates are currently being served for this version, please switch release channel
Aucune version "candidate" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel"
-
+
No nightly Companion builds are currently being served for this version, please switch release channel
Aucune version "nightly" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel"
-
+
No Companion release builds are currently being served for this version, please switch release channel
Aucune version "officielle" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "candidate" ou "nightly"
-
+
A new release of Companion is available, please check the <a href='%1'>OpenTX website!</a>
Une nouvelle version de Companion est disponible, vérifiez le site OpenTX <a href='%1'> !</a>
-
+
No firmware release candidates are currently being served for this version, please switch release channel
Aucun firmware "candidate" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel"
-
+
No firmware nightly builds are currently being served for this version, please switch release channel
Aucun firmware "nightly" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel"
-
+
No firmware release builds are currently being served for this version, please switch release channel
Aucun firmware "officiel" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "candidate" ou "nightly"
-
+
Release candidate builds are now available for this version, would you like to switch to using them?
Une version "candidate" est maintenant disponible pour cette version, voulez-vous commuter de canal afin de l'utiliser?
-
+
Channel changed to RC, please restart the download process
Canal commuté sur "candidate", veuillez redémarrer le processus de téléchargement
-
+
Official release builds are now available for this version, would you like to switch to using them?
Une version "officielle" est maintenant disponible pour cette version, voulez-vous commuter de canal afin de l'utiliser?
-
+
Channel changed to Release, please restart the download process
Canal commuté sur "officiel", veuillez redémarrer le processus de téléchargement
-
+
This radio (%1) is not currently available in this firmware release channel
Le firmware pour cette radio (%1) n'est actuellement pas disponible dans le canal "officiel"
-
+
Firmware %1 does not seem to have ever been downloaded.
Version %2 is available.
Do you want to download it now?
@@ -6663,18 +6911,18 @@ Voulez-vous le télécharger maintenant?
Nous vous recommandons de consulter les notes de mise à jour à l'aide du bouton ci-dessous pour en savoir plus sur les modifications susceptibles de vous intéresser.
-
-
+
+
Do you want to download version %1 now ?
Voulez-vous télécharger la version %1 maintenant?
-
+
Ignore this version %1?
Ignorer cette version %1?
-
+
There are unsaved file changes which you may lose when switching radio types.
Do you wish to continue?
@@ -6683,355 +6931,355 @@ Do you wish to continue?
Êtes-vous sûr de vouloir continuer ?
-
+
No local SD structure path configured!
Aucun chemin de configuré pour la structure SD en local !
-
+
No Radio or SD card detected!
Pas de Radio ou carte SD de détectée !
-
+
Release notes...
Notes de version...
-
+
Show release notes
Afficher les notes de version
-
+
Delete Current Radio Profile...
Supprimer le profil radio actuel...
-
+
Export Application Settings..
Exporter Préférences Application...
-
+
Save all the current %1 and Simulator settings (including radio profiles) to a file.
Enregistrez tous les paramètres actuels %1 et du simulateur (y compris les profils radio) dans un fichier.
-
+
Import Application Settings..
Importer les paramètres de l'application...
-
+
Load %1 and Simulator settings from a prevously exported settings file.
Charger les paramètres %1 et les paramètres de Simulation depuis un fichier précédemment exporté.
-
+
Tabbed Windows
Fenêtres à onglets
-
+
Use tabs to arrange open windows.
Utilisez les onglets pour organiser les fenêtres ouvertes.
-
+
Tile Windows
Titre de la fenêtre
-
+
Arrange open windows across all the available space.
Disposez les fenêtres ouvertes sur tout l'espace disponible.
-
+
Cascade Windows
Fenêtres en cascade
-
+
Arrange all open windows in a stack.
Organisez toutes les fenêtres ouvertes dans une pile.
-
+
Close All Windows
Fermer toutes les fenêtres
-
+
Closes all open files (prompts to save if necessary.
Fermer tous les fichiers ouverts (proposer de sauvegarder si nécessaire).
-
+
Window
Fenêtre
-
+
Ctrl+Shift+S
-
+
Ctrl+Alt+L
-
+
Ctrl+Alt+D
-
+
Ctrl+Alt+R
-
+
The classic companion9x icon theme
Thème d'icônes classique de Companion
-
+
Yerico
-
+
Yellow round honey sweet icon theme
Thème d'icônes rondes jaunes
-
+
Monochrome
-
+
MonoWhite
Monochrome Blanc
-
+
Alt+%1
-
+
- Copy
- Copier
-
+
Companion :: Open files warning
Companion::Ouvrir les fichiers d'avertissement
-
+
Please save or close modified file(s) before deleting the active profile.
Veuillez sauvegarder ou fermer le(s) fichier(s) modifié(s) avant de supprimer le profil actif.
-
+
Not possible to remove profile
Impossible de supprimer le profil
-
+
The default profile can not be removed.
Le profil par défaut ne peut pas être supprimé.
-
+
Confirm Delete Profile
Confirmer la suppression du profil
-
+
Are you sure you wish to delete the "%1" radio profile? There is no way to undo this action!
Etes-vous sûr de vouloir supprimer le profil radio %1? Cette action est irréversible!
-
+
Please save or close all modified files before importing settings
Veuillez sauvegarder ou fermer tous les fichiers modifiés avant d'importer les paramètres
-
+
<html><p>%1 and Simulator settings can be imported (restored) from a previosly saved export (backup) file. This will replace current settings with any settings found in the file.</p><p>An automatic backup of the current settings will be attempted. But if the current settings are useful then it is recommended that you make a manual backup first.</p><p>For best results when importing settings, <b>close any other %1 windows you may have open, and make sure the standalone Simulator application is not running.</p><p>Do you wish to continue?</p></html>
<html><p>%1 et les paramètres du simulateur peuvent être importés (restaurés) à partir d’un fichier d’exportation (sauvegarde) préalablement sauvegardé. Ceci remplacera les paramètres actuels par tous les paramètres trouvés dans le fichier.</p><p>Une sauvegarde automatique des paramètres actuels sera tentée. Mais si les paramètres actuels sont utiles, il est recommandé de commencer par une sauvegarde manuelle.</p><p>Pour obtenir de meilleurs résultats lors de l'importation des paramètres,<b> fermez les autres fenêtres %1 que vous avez éventuellement ouvertes et assurez-vous que l'application autonome Simulator n'est pas en cours d'exécution. </p><p>Souhaitez-vous continuer? </p></html>
-
+
Confirm Settings Import
Confirmer les paramètres d'importation
-
+
Select %1:
Sélectionnez %1:
-
+
backup
sauvegarde
-
+
Press the 'Ignore' button to continue anyway.
Appuyez sur le bouton 'Ignorer' pour continuer quand même.
-
+
The settings could not be imported.
Les paramètres n'ont pas pu être importés.
-
+
<html><p>New settings have been imported from:<br> %1.</p><p>%2 will now re-initialize.</p><p>Note that you may need to close and restart %2 before some settings like language and icon theme take effect.</p>
<html><p>Les nouveaux paramètres ont été importés depuis:<br> %1. </p><p>%2 sera maintenant réinitialisé.</p><p>Notez que vous devrez peut-être fermer et redémarrer %2 avant que certains paramètres tels que la langue et le thème d’icône prennent effet.</p>
-
+
<p>The previous settings were backed up to:<br> %1</p>
<p>Les paramètres précédents ont été sauvegardés sous:<br> %1 </p>
-
+
MonoBlue
Monochrome Bleu
-
+
System language
Langue du système
-
+
About...
A propos...
-
+
View Log File...
Ouvrir un Log...
-
+
Open and view log file
Ouvrir et visualiser un log
-
+
Settings...
Préférences...
-
+
Edit Settings
Éditer les préférences
-
+
Download...
Télécharger...
-
+
Download firmware and voice files
Télécharger firmware et fichiers son
-
+
Check for Updates...
Vérifier les mises à jour...
-
+
Check OpenTX and Companion updates
Vérifier les mises à jour d'OpenTX et Companion
-
+
Compare Models...
Comparer 2 modèles...
-
+
Edit Radio Splash Image...
Éditer l'écran d'accueil de la radio...
-
+
Edit the splash image of your Radio
Éditer l'écran d'accueil de la radio
-
+
List available programmers
Lister les programmateurs supportés
-
-
+
+
Save As
Enregistrer Sous
-
-
+
+
No updates available at this time.
Aucune mise à jour disponible.
-
-
+
+
Help
Aide
-
+
Checking for updates
Recherche de mises à jour
-
+
The new theme will be loaded the next time you start Companion.
Le nouveau thème sera utilisé lors du prochain lancement de Companion.
-
+
About Companion
A propos de Companion
-
+
Set Menu Language
Choisir la langue des menus
-
+
Settings
Paramètres
-
+
Read/Write
Transfert
-
+
%2
-
+
New Radio
Nouvelle radio
@@ -7328,11 +7576,6 @@ Do you wish to continue?
Companion :: Conversion Result for %1
Companion :: Résultat de conversion de %1
-
-
- Unable to find Horus radio SD card!
- Impossible de trouver la carte SD de la Horus !
-
Models and Settings written
@@ -7399,6 +7642,11 @@ Do you wish to continue?
<p><b>Currently selected radio type (%1) is not compatible with file %3 (from %2), models and settings need to be converted.</b></p>
<p><b>Le type de radio actuellement sélectionné (%1) n'est pas compatible avec le fichier %3 (à partir de %2), les modèles et les paramètres doivent être convertis.</b></p>
+
+
+ Unable to find radio SD card!
+ Impossible de trouver la carte SD de la radio!
+
Open backup Models and Settings file
@@ -7420,12 +7668,12 @@ Enregistrer les changements ?
MixData
-
+
MIX
-
+
(@%1)
@@ -7820,12 +8068,12 @@ Mixage actif par défaut si non-renseigné.
ModelData
-
+
Model:
Modèle:
-
+
Throttle Source
Source des gaz
@@ -8154,7 +8402,7 @@ Mixage actif par défaut si non-renseigné.
Extended Limits
- Débattements étendus
+ Limites étendues
@@ -8961,12 +9209,12 @@ Mixage actif par défaut si non-renseigné.
ModuleData
-
+
Positive
-
+
Negative
Négative
@@ -9047,47 +9295,47 @@ Mixage actif par défaut si non-renseigné.
ModulePanel
-
+
Value
Valeur
-
+
Hold
Maintien
-
+
No Pulse
Pas d'impulsion
-
+
Ask
Demander
-
+
Internal
Interne
-
+
Internal + External
Interne + Externe
-
+
External
Externe
-
+
Autodetect Format
Format Détection auto
-
+
Bind on channel
Bind avec VOIE
@@ -9588,11 +9836,6 @@ Mixage actif par défaut si non-renseigné.
DEFAULT
DÉFAUT
-
-
- Custom - proto %1)
- Personnaliser - proto %1)
-
MultirotorPage
@@ -9620,22 +9863,22 @@ Mixage actif par défaut si non-renseigné.
OpenTxEepromInterface
-
+
Unknown error
Erreur inconnue
-
+
... plus %1 errors
... plus %1 erreurs
-
+
Cannot write radio settings
Impossible d'écrire les paramètres de la radio
-
+
Cannot write model %1
Impossible d'écrire le modèle %1
@@ -9740,6 +9983,19 @@ Mixage actif par défaut si non-renseigné.
Fichiers ODF (*.odt);; Fichiers PDF (*.pdf);;Fichiers HTML (*.htm *.html);;Tous les fichiers (*)
+
+ ProfileChooserDialog
+
+
+ Select Profile
+ Choisir Profil
+
+
+
+ Profile
+ Profil
+
+
ProgressDialog
@@ -9908,8 +10164,8 @@ Mixage actif par défaut si non-renseigné.
- Unable to find Horus radio SD card!
- Impossible de trouver la carte SD de la Horus !
+ Unable to find radio SD card!
+ Impossible de trouver la carte SD de la radio!
@@ -10843,7 +11099,12 @@ E
secondes
-
+
+ ml/minute
+
+
+
+
TELE
@@ -10993,7 +11254,7 @@ E
Extended Limits
- Débattements étendus
+ Limites étendues
@@ -11025,25 +11286,90 @@ Si cette option est cochée, la voie des gaz est inversée: le ralenti est &apo
SetupPanel
-
+
+ Popup menu available
+ Menu contextuel disponible
+
+
+
Timer %1
Chrono %1
-
+
THR
GAZ
-
+
Profile Settings
Paramètres du profil
-
+
SD structure path not specified or invalid
Chemin de la structure SD non spécifié ou invalide
+
+
+ Copy
+ Copier
+
+
+
+ Cut
+ Couper
+
+
+
+ Paste
+ Coller
+
+
+
+ Clear
+ Effacer
+
+
+
+ Insert
+ Insérer
+
+
+
+ Delete
+ Supprimer
+
+
+
+ Move Up
+ Monter
+
+
+
+ Move Down
+ Descendre
+
+
+
+ Clear All
+ Effacer Tout
+
+
+
+ Clear Timer. Are you sure?
+ Effacer le Chrono. Êtes-vous sûr?
+
+
+
+ Clear all Timers. Are you sure?
+ Effacer tous les Chronos. Êtes-vous sûr?
+
+
+
+ Delete Timer. Are you sure?
+ Supprimer le Chrono. Êtes-vous sûr?
+
SimpleTailPage
@@ -11764,62 +12090,62 @@ La valeur par défaut est configurée dans le profil radio sélectionné.Simulateur Radio (%1)
-
+
Could not determine startup data source.
Impossible de déterminer les données source.
-
+
Could not load data, possibly wrong format.
Impossible de charger les données, mauvais format.
-
+
Data Load Error
Erreur de lecture des données
-
+
Invalid startup data provided. Plese specify a proper file/path.
Données de démarrage fournies non valides. Veuillez spécifier un fichier/chemin approprié.
-
+
Simulator Startup Error
Erreur de démarrage du simulateur
-
+
Error saving data: could open file for writing: '%1'
Erreur de sauvegarde des données: impossible d'écrire le fichier '%1'
-
+
Error saving data: could not get data from simulator interface.
Erreur de sauvegarde des données: impossible de récupérer les données depuis l'interface de simulation.
-
+
An unexpected error occurred while attempting to save radio data to file '%1'.
Une erreur inattendue s'est produite lors de l'enregistrement des données radio dans le fichier '%1'.
-
+
Data Save Error
Erreur de sauvegarde des données
-
+
Cannot open joystick, joystick disabled
Impossible d'accéder au Joystick, Joystick désactivé
-
+
Radio firmware error: %1
Erreur firmware radio: %1
-
+
- Flight Mode %1 (#%2)
- Phase de Vol %1 (#%2)
@@ -12522,104 +12848,104 @@ Trop d'erreurs, abandon.
TelemetryPanel
-
+
FrSky S.PORT
-
+
FrSky D
-
+
FrSky D (cable)
FrSky D (câble)
-
+
Telemetry screen %1
Ecran de télémesure %1
-
+
Source
-
+
Low Alarm
Alarme basse
-
+
Critical Alarm
Alarme critique
-
+
Winged Shadow How High
-
+
Winged Shadow How High (not supported)
Winged Shadow How High (non supporté)
-
+
Alti
Alt
-
+
Alti+
Alt+
-
+
VSpeed
Vitesse verticale
-
-
-
+
+
+
A1
-
-
-
+
+
+
A2
-
-
+
+
A3
-
-
+
+
A4
-
-
+
+
FAS
-
+
Cells
Velm
-
+
---
@@ -12632,274 +12958,284 @@ Trop d'erreurs, abandon.
Formulaire
-
+
+ TELE##
+
+
+
+
Custom
Prédéfini
-
+
Calculated
Calculé
-
+
Id
-
+
Instance
-
+
Rx
-
+
Add
Addition
-
+
Average
Moyenne
-
+
Min
-
+
Max
-
+
Multiply
Multiplication
-
+
Totalize
Totalisation
-
+
Cell
Element LiPo
-
+
Consumption
Consommation
-
+
Dist
Distance
-
+
Cells Sensor :
Capteur d'éléments:
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
---
-
+
GPS Sensor :
Capteur GPS:
-
+
Alt. Sensor :
Capteur d'altitude:
-
+
Sensor :
Capteur:
-
+
V
-
+
A
-
+
mA
-
+
kt
-
+
m/s
-
+
ft/s
-
+
km/h
-
+
mph
-
+
m
-
+
ft
-
+
°C
-
+
°F
-
+
%
-
+
mAh
-
+
W
-
+
mW
-
+
dBm
-
+
g
-
+
°
-
+
Rad
-
+
mL
-
+
US fl.Oz.
-
+
Raw (-)
Chiffres bruts (-)
-
+
RPM
Tours/minute
-
+
+ ml/min
+
+
+
+
Precision
Précision
-
+
Ratio
-
+
Blades
Pales
-
+
Offset
Décalage
-
+
Multiplier
Multiplicateur
-
+
Auto Offset
Offset auto
-
+
Filter
Filtre
-
+
Persistent
Persistant
-
+
Positive
-
+
Logs
@@ -12907,25 +13243,70 @@ Trop d'erreurs, abandon.
TelemetrySensorPanel
-
+
+ TELE%1
+
+
+
+
+ Popup menu available
+ Menu contextuel disponible
+
+
+
Lowest
Min
-
+
Cell %1
Elém. %1
-
+
Highest
Max
-
+
Delta
+
+
+ Copy
+ Copier
+
+
+
+ Cut
+ Couper
+
+
+
+ Paste
+ Coller
+
+
+
+ Clear
+ Effacer
+
+
+
+ Clear All
+ Effacer Tout
+
+
+
+ Clear Telemetry Sensor. Are you sure?
+ Effacer le capteur de télémétrie. Êtes-vous sûr?
+
+
+
+ Clear all Telemetry Sensors. Are you sure?
+ Effacez tous les capteurs de télémétrie. Êtes-vous sûr?
+
TelemetrySimulator
@@ -13305,12 +13686,12 @@ hh:mm:ss
TimerData
-
+
TMR
-
+
Timer %1
Chrono %1
@@ -14287,120 +14668,4 @@ Cliquer sur Annuler pour interrompre la calibration sans sauvegarder.Calibration incomplète, sauvegarder tout de même ?
-
- preferencesDialog
-
-
-
- ...
-
-
-
-
- Enable
- Actif
-
-
-
- Remember simulator switches
- Mémoriser les positions des inters du simulateur
-
-
-
- Calibrate
- Calibrer
-
-
-
-
- Open Folder
- Ouvrir le dossier
-
-
-
- Custom TX splash screen
- Personnaliser l'écran d'accueil
-
-
-
- Simulator capture folder
- Dossier des captures d'écran
-
-
-
- Use clipboard only
- Utiliser le presse-papiers
-
-
-
- Simu BackLight
- Rétroéclairage simu
-
-
-
- Blue
- Blu
- Bleu
-
-
-
- Green
- Vert
-
-
-
- Red
- Rouge
-
-
-
- Orange
-
-
-
-
- Yellow
- Jaune
-
-
-
- Personal splash library
- Librairie d'écran d'accueil personnalisé
-
-
-
- Splash library behaviour
- Utilisation de la librairie d'écran d'accueil
-
-
-
- Include companion splashes
- Inclure les écrans d'accueil de Companion
-
-
-
- Only user defined splashes
- Seulement les écrans d'accueil personnalisé
-
-
-
- Joystick
-
-
-
-
- Open Image
- Charger une image
-
-
-
- Invert Pixels
- Inverser les couleurs
-
-
-
- Preferences
- Préférences
-
-
diff --git a/companion/src/translations/companion_it.ts b/companion/src/translations/companion_it.ts
index 21b3e87db..3572d1d4c 100644
--- a/companion/src/translations/companion_it.ts
+++ b/companion/src/translations/companion_it.ts
@@ -6797,7 +6797,7 @@ We recommend you view the release notes using the button below to learn about an
Set Menu Language
- Inposta Menu Lingua
+ Menù Impostazione Lingua
diff --git a/companion/src/translations/companion_ja.ts b/companion/src/translations/companion_ja.ts
index ddc8b2c37..da32c47fc 100644
--- a/companion/src/translations/companion_ja.ts
+++ b/companion/src/translations/companion_ja.ts
@@ -108,94 +108,94 @@
送信機プロファイル
-
-
-
-
-
-
+
+
+
+
+
+
Select Folder
フォルダの選択
-
-
+
+
The profile specific folder, if set, will override general Backup folder
プロファイル保存フォルダが指定される場合は、バックアップフォルダを上書き保存します
-
+
Splash Screen
起動イメージ
-
+
Select Image
イメージの選択
-
+
Clear Image
イメージの消去
-
+
Profile Name
プロファイル名
-
+
Radio Type
送信機タイプ
-
+
Menu Language
メニュー言語
-
+
Build Options
ビルドオプション
-
+
SD Structure path
SDカード保存先パス
-
+
Backup folder
バックアップフォルダ
-
+
If set it will override the application general setting
設定されている場合はアプリケーション設定を上書き保存します
-
+
if set, will override general backup enable
設定されている場合は有効なバックアップを上書き保存します
-
-
+
+
Enable automatic backup before writing firmware
設定した場合は自動バックアップを有効にします
-
+
General Settings
一般設定
-
+
Default Stick Mode
初期スティックモード
-
+
Mode selection:
Mode 1:
@@ -218,464 +218,479 @@ Mode 4:
-
+
Mode 1 (RUD ELE THR AIL)
モード1 (左:エレベーター・ラダー 右:スロットル・エルロン)
-
+
Mode 2 (RUD THR ELE AIL)
モード2 (左:スロットル・ラダー 右:エレベーター・エルロン)
-
+
Mode 3 (AIL ELE THR RUD)
モード3 (左:エレベーター・エルロン 右:スロットル・ラダー)
-
+
Mode 4 (AIL THR ELE RUD)
モード4 (左:スロットル・エルロン 右:エレベーター・ラダー)
-
+
Default Channel Order
初期チャンネルマップ
-
+
<html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html>
<html><head/><body><p>チャンネルマップ</p><p><br/></p><p>モデル作成された際の初期チャンネルマップを定義します</p></body></html>
-
+
R E T A
↔RUD ↕ELE ↕THR ↔AIL [R E T A]
-
+
R E A T
↔RUD ↕ELE ↔AIL ↕THR [R E A T]
-
+
R T E A
↔RUD ↕THR ↕ELE ↔AIL [R T E A]
-
+
R T A E
↔RUD ↕THR ↔AIL ↕ELE [R T A E]
-
+
R A E T
↔RUD ↔AIL ↕ELE ↕THR [R A E T]
-
+
R A T E
↔RUD ↔AIL ↕THR ↕ELE [R A T E]
-
+
E R T A
↕ELE ↔RUD ↕THR ↔AIL [E R T A]
-
+
E R A T
↕ELE ↔RUD ↔AIL ↕THR [E R A T]
-
+
E T R A
↕ELE ↕THR ↔RUD ↔AIL [E T R A]
-
+
E T A R
↕ELE ↕THR ↔AIL ↔RUD [E T A R]
-
+
E A R T
↕ELE ↔AIL ↔RUD ↕THR [E A R T]
-
+
E A T R
↕ELE ↔AIL ↕THR ↔RUD [E A T R]
-
+
T R E A
↕THR ↔RUD ↕ELE ↔AIL [T R E A]
-
+
T R A E
↕THR ↔RUD ↔AIL ↕ELE [T R A E]
-
+
T E R A
↕THR ↕ELE ↔RUD ↔AIL [T E R A]
-
+
T E A R
↕THR ↕ELE ↔AIL ↔RUD [T E A R]
-
+
T A R E
↕THR ↔AIL ↔RUD ↕ELE [T A R E]
-
+
T A E R
↕THR ↔AIL ↕ELE ↔RUD [T A E R]
-
+
A R E T
↔AIL ↔RUD ↕ELE ↕THR [A R E T]
-
+
A R T E
↔AIL ↔RUD ↕THR ↕ELE [A R T E]
-
+
A E R T
↔AIL ↕ELE ↔RUD ↕THR [A E R T]
-
+
A E T R
↔AIL ↕ELE ↕THR ↔RUD [A E T R]
-
+
A T R E
↔AIL ↕THR ↔RUD ↕ELE [A T R E]
-
+
A T E R
↔AIL ↕THR ↕ELE ↔RUD [A T E R]
-
+
Append version number to FW file name
ファームウェア ファイル名にバージョン番号を追加
-
+
+ Simulator controls
+ シミュレータ コントロール
+
+
+
+ Save switch/pot positions on simulator exit
+ シミュレータ終了時にスイッチ/ポットのポジションを保存
+
+
+
+ Clear saved positions
+ 保存したポジションを消去
+
+
+
Offer to write FW to Tx after download
ダウンロード後、送信機にFWを適用可能な事を通知
-
+
Other Settings
その他の設定
-
+
Application Settings
アプリケーション設定
-
+
Automatic check for OpenTX firmware updates
OpenTXファームアップデートの自動チェック
-
+
Automatic check for Companion updates
Companionアップデートの自動チェック
-
+
most recently used files
最近使用したファイル
-
+
Startup Settings
スタートアップ設定
-
+
Google Earth Executable
Google Earthの実行
-
+
Automatic Backup Folder
自動バックアップフォルダ
-
+
Remember
ファイル履歴
-
- Show splash screen when Companion starts
- Companion起動時に起動イメージを表示
-
-
-
+
Output Logs Folder
ログ出力フォルダ
-
+
<html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html>
<html><head/><body><p>このオプションは、機体モデルが削除または移動した際、そのモデルスロットが保持される旧版のOpenTxバージョンの挙動を維持します。</p><p>このオプションが選択されない場合は、他の機体モデルは削除により残された差異を埋めるために並べ替えるかもしれません。</p></body></html>
-
+
Remove empty model slots when deleting models (only applies for radios w/out categories)
モデルを削除するとき同時に空モデルスロットを削除 (カテゴリなしの機体モデルにのみ適用)
-
+
Use model wizard
機体モデルウィザードを使用
-
+
Open model editor
機体モデルエディタを開く
-
+
Just create the model
機体モデルの作成のみ
-
+
Debug Output Logging
出力したログのデバッグ
-
+
Only show user splash images
オリジナルの起動イメージのみを表示
-
+
Show user and companion splash images
オリジナルとCompanion標準イメージを表示
-
+
+ Show splash screen
+ 起動イメージを表示
+
+
+
Select Executable
実行ファイル選択
-
+
<html><head/><body><p>Keep a log of all debugging messages generated by the desktop Companion/Simulator applications. An OpenTX developer may request this to help diagnose an issue.</p></body></html>
<html><head/><body><p>デスクトップのCompanion / シミュレータ アプリケーションにより生成された、すべてのデバッグメッセージのログを保存します。OpenTX開発者は問題を診断・解析するため、ログを要求するかもしれません。</p></body></html>
-
+
Application (Companion/Simulator)
アプリケーション (Companion / シミュレータ)
-
+
<html><head/><body><p>Keep a log of all messages generated by the radio firmware when running in Simulator. This is the same information one would also see in the Simulator <span style=" font-style:italic;">Debug Output</span> window.</p></body></html>
<html><head/><body><p>シミュレータで実行しているときは、送信機ファームウェアによって生成されたすべてのメッセージのログを保存してください。これはシミュレータの<span style = "font-style:italic;">デバッグ出力</span>ウィンドウにも同じ情報が表示されます。</p></body></html>
-
+
Radio Firmware (in Simulator)
送信機ファームウェア (シミュレータ内)
-
+
Splash Screen Library
起動イメージライブラリ
-
+
User Splash Screens
オリジナル起動イメージ
-
+
Action on New Model
機体モデル新規作成
-
+
Release channel
リリース状態 選択
-
+
Releases (stable)
リリース版 (Stable)
-
+
Release candidates (testing)
Release candidates RC版 (Testing)
-
+
Nightly builds (unstable)
ナイトリービルド版 (Unstable)
-
+
+ Prompt for radio profile
+ 送信機プロファイルの呼び出し
+
+
+
Simulator Settings
シミュレータ設定
-
+
Calibrate
キャリブレート
-
+
Blue
青色
-
+
Green
緑色
-
+
Red
赤色
-
+
Orange
オレンジ
-
+
Yellow
黄色
-
+
Screenshot capture folder
画面キャプチャフォルダ
-
+
Only capture to clipboard
キャプチャをクリップボードのみにコピー
-
+
Enable
有効
-
+
Joystick
スティック
-
+
Simulator BackLight
バックライト
-
- Remember simulator switch values
- シミュレータで設定した各スイッチの値を記憶
-
-
-
+
Simulator Volume Gain
シミュレータ 音量幅
-
+
My Radio
マイ送信機
-
+
<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>
<p><b>ファイル変更後で保存されていない間は、送信機タイプの切り替えやビルドオプションの変更はできません。保存しますか?</b></p> <ul><li><i>すべて保存</i> - 設定を保存する前に、開いているファイルをすべて保存します <li><li><i>リセット</i> - 設定を保存する前に、以前の送信機タイプとビルドオプションに戻します </li><li><i>キャンセル</i> - 設定エディタダイアログに戻ります </li></ul>
-
+
Select your snapshot folder
画面キャプチャフォルダ選択してください
-
+
Note: Nightly builds are not available in this version, Release/RC update channel will be used.
注: このバージョンではナイトリービルドは使用できません。リリース/RC版のアップデートチャネルが使用されます。
-
-
+
+
No joysticks found
スティックが認識できません
-
+
EMPTY: No radio settings stored in profile
空: プロファイルに送信機設定が保存されていません
-
+
AVAILABLE: Radio settings of unknown age
利用可能: 詳細不明の送信機設定
-
+
AVAILABLE: Radio settings stored %1
利用可能: 送信機設定は %1 に保存されています
-
+
Select your library folder
ライブラリフォルダを選択してください
-
-
+
+
Select your Models and Settings backup folder
機体モデルの選択とバックアップフォルダの設定をしてください
-
+
Select a folder for application logs
アプリケーションログフォルダを選択してください
-
+
Select Google Earth executable
Google Earth実行有無を選択してください
-
+
Select the folder replicating your SD structure
SDカード保存先フォルダを選択してください
-
+
Open Image to load
イメージを開いてロードします
-
+
Images (%1)
イメージ (%1)
@@ -715,58 +730,58 @@ Mode 4:
Boards
-
+
Left Horizontal
左・横
-
+
Left Vertical
左・縦
-
+
Right Vertical
右・縦
-
+
Right Horizontal
右・横
-
+
Aux. 1
AUX. 1
-
+
Aux. 2
AUX. 2
-
-
+
+
Unknown
不明
-
+
Rud
ラダー
-
+
Ele
エレベーター
-
+
Thr
スロットル
-
+
Ail
エルロン
@@ -815,84 +830,124 @@ Mode 4:
Channels
-
+
Name
名称
-
+
Subtrim
サブトリム
-
+
Min
最小
-
+
Max
最大
-
+
Direction
方向
-
+
Curve
カーブ
-
+
PPM Center
PPM センター
-
+
Linear Subtrim
線形サブトリム
-
+
CH%1
CH%1
-
+
Popup menu available
利用可能なポップアップメニュー
-
+
---
---
-
+
INV
リバース
-
- &Copy
- &コピー
-
-
-
- &Cut
- &切り取り
+
+ Delete Channel. Are you sure?
+ チャンネルを削除します。よろしいですか?
- &Paste
- &貼り付け
+ Copy
+ コピー
- &Delete
- &削除
+ Cut
+ 切り取り
+
+
+
+ Paste
+ 貼り付け
+
+
+
+ Clear
+ 消去
+
+
+
+ Insert
+ 挿入
+
+
+
+ Delete
+ 削除
+
+
+
+ Move Up
+ 上へ移動
+
+
+
+ Move Down
+ 下へ移動
+
+
+
+ Clear All
+ すべて消去
+
+
+
+ Clear Channel. Are you sure?
+ チャンネルを消去します。よろしいですか?
+
+
+
+ Clear all Channels. Are you sure?
+ チャンネルをすべて消去します。よろしいですか?
@@ -1310,7 +1365,7 @@ If you have a settings backup file, you may import that instead.
CurveData
-
+
CV
CV
@@ -1450,79 +1505,109 @@ If you have a settings backup file, you may import that instead.
点のサイズ
-
+
Curve %1
カーブ %1
-
+
Popup menu available
利用可能なポップアップメニュー
-
+
%1 points
%1 点
-
+
Linear
線形
-
+
Single Expo
シングルエクスポ
-
+
Symmetrical f(x)=-f(-x)
対称 f(x)=-f(-x)
-
+
Symmetrical f(x)=f(-x)
対称 f(x)=f(-x)
-
+
Editing curve %1
カーブ %1 編集
-
+
Not enough free points in EEPROM to store the curve.
EEPROMにカーブを保存する十分な空き容量がありません。
-
+
Copy
コピー
-
+
+ Cut
+ 切り取り
+
+
+
Paste
貼り付け
-
+
Clear
消去
-
- Clear all curves
- すべてのカーブ消去
+
+ Insert
+ 挿入
-
- Are you sure you want to reset curve %1?
- カーブ %1をリセットしてもよいですか?
+
+ Delete
+ 削除
-
- Are you sure you want to reset all curves?
- すべてのカーブをリセットしてもよいですか?
+
+ Move Up
+ 上へ移動
+
+
+
+ Move Down
+ 下へ移動
+
+
+
+ Clear All
+ すべて消去
+
+
+
+ Clear Curve. Are you sure?
+ カーブを消去します。よろしいですか?
+
+
+
+ Clear all Curves. Are you sure?
+ カーブをすべて消去します。よろしいですか?
+
+
+
+ Delete Curve. Are you sure?
+ カーブを削除します。よろしいですか?
@@ -1569,193 +1654,198 @@ If you have a settings backup file, you may import that instead.
+ Trainer Channels
+ トレーナー チャンネル
+
+
+
Instant Trim
トリム
-
+
Play Sound
サウンド 再生
-
+
Haptic
タッチパネル
-
+
Reset
リセット
-
+
Set Timer %1
設定: タイマー %1
-
+
Vario
バリオ
-
+
Play Track
トラック 再生
-
+
Play Both
両方 実行
-
+
Play Value
値 実行
-
+
Play Script
スクリプト 実行
-
+
SD Logs
SDログ
-
+
Volume
音量
-
+
Backlight
バックライト
-
+
Screenshot
画面キャプチャ
-
+
Background Music
BGM
-
+
Background Music Pause
BGM一時停止
-
+
Adjust %1
アジャスト %1
-
+
SetFailsafe Int. Module
設定: フェイルセーフ 内部モジュール
-
+
SetFailsafe Ext. Module
設定: フェイルセーフ 外部モジュール
-
+
RangeCheck Int. Module
レンジチェック 内部モジュール
-
+
RangeCheck Ext. Module
レンジチェック 外部モジュール
-
+
Bind Int. Module
バインド 内部モジュール
-
+
Bind Ext. Module
バインド 外部モジュール
-
+
Timer1
タイマー1
-
+
Timer2
タイマー2
-
+
Timer3
タイマー3
-
+
Flight
フライト
-
+
Telemetry
テレメトリー
-
+
Rotary Encoder
エンコーダ再生
-
+
REa
エンコーダ再生a
-
+
REb
エンコーダ再生b
-
+
s
s
-
-
-
+
+
+
<font color=red><b>Inconsistent parameter</b></font>
<font color=red><b>矛盾しているパラメータ</b></font>
-
+
Value
値
-
+
played once, not during startup
起動時以外 1回実行
-
+
repeat(%1s)
リピート(%1s)
-
+
DISABLED
無効
-
+
CFN
CFN
@@ -1815,42 +1905,82 @@ If you have a settings backup file, you may import that instead.
%1
-
- &Copy
- &コピー
+
+ Delete Special Function. Are you sure?
+ スペシャルファンクションを削除します。よろしいですか?
-
- &Cut
- &切り取り
+
+ Copy
+ コピー
-
- &Paste
- &貼り付け
+
+ Cut
+ 切り取り
-
- &Delete
- &削除
+
+ Paste
+ 貼り付け
-
+
+ Clear
+ 消去
+
+
+
+ Insert
+ 挿入
+
+
+
+ Delete
+ 削除
+
+
+
+ Move Up
+ 上へ移動
+
+
+
+ Move Down
+ 下へ移動
+
+
+
+ Clear All
+ すべて消去
+
+
+
+ Clear Special Function. Are you sure?
+ スペシャルファンクションを消去します。よろしいですか?
+
+
+
+ Clear all Special Functions. Are you sure?
+ スペシャルファンクションをすべて消去します。よろしいですか?
+
+
+
Value
値
-
+
Source
選択元
-
+
GVAR
GVAR
-
+
Increment
増加
@@ -2043,23 +2173,23 @@ If you have a settings backup file, you may import that instead.
このボードでは選択元 %1 をエクスポートできません!
-
+
OpenTX only accepts %1 points in all curves
OpenTXはすべてのカーブで %1 点のみを許容します
-
+
OpenTx only accepts %1 points in all curves
OpenTxはすべてのカーブで %1 点のみを許容します
-
-
+
+
OpenTX on this board doesn't accept this function
このボード上のOpenTXはこの機能を受け付けません
-
+
OpenTX doesn't accept this radio protocol
OpenTXはこの送信機プロトコルを受け付けません
@@ -2139,12 +2269,12 @@ To <b>remove a remembered entry</b> from the filter list, first cho
フィルタをON / OFFします。
-
+
<html><head><style>kbd {background-color: palette(alternate-base); font-size: large; white-space: nowrap;}</style></head><body><p>The filter supports two syntax types: basic matching with common wildcards as well as full Perl-style (<code>pcre</code>) Regular Expressions.</p><p>By default a filter will only show lines which match (<b>inclusive</b>). To make an <b>exclusive</b> filter which removes matching lines, prefix the filter expression with a <kbd>!</kbd> (exclamation mark).</p><p>To use <b>Regular Expressions</b> (RegEx), prefix the filter text with a <kbd>/</kbd> (slash) or <kbd>^</kbd> (up caret). <ul><li>Put the <kbd>/</kbd> or <kbd>^</kbd> after the exclusive <kbd>!</kbd> indicator if you're using one.</li><li>By default the match is case-sensitive. To make it insensitive, add the typical <kbd>/i</kbd> (slash i) operator at the end of your RegEx.</li><li>If you use a caret (^) to denote a RegEx, it will become part of the Reg. Ex. (that is, matches from start of line).</li><li>If the RegEx is invalid, the filter edit field should show a red border and you will not be able to enable the filter.</li><li>A useful resource for testing REs (with a full reference) can be found at <a href="http://www.regexr.com/">http://www.regexr.com/</a></li></ul></p><p>To use <b>basic matching</b> just type any text.<ul><li>Wildcards: <kbd>*</kbd> (asterisk) matches zero or more of any character(s), and <kbd>?</kbd> (question mark) matches any single character.</li><li>The match is always case-insensitive.</li><li>The match always starts from the beginning of a log line. To ignore characters at the start, use a leading <kbd>*</kbd> wildcard.</li><li>A trailing <kbd>*</kbd> is always implied (that is, matches anything to the end of the log line). To avoid this, use a RegEx.</li><li>You can match literal wildcard characters by prefixing them with a <kbd>\</kbd> (backslash) character (eg. "foo\*bar" matches "foo*bar").</li></ul></p><p>After <b>editing text</b>, press ENTER or TAB key (or click anywhere outside the box) to update the filter.</p><p>To <b>remove an entry</b> from the filter selector list, first choose it, and while in the line editor press <kbd>Shift-Delete</kbd> (or <kbd>Shift-Backspace</kbd>) key combination. The default filters cannot be removed. Up to 50 filters are stored.</p></body></html>
<html><head><style>kbd {background-color: palette(alternate-base); font-size: large; white-space: nowrap;}</style></head><body><p>フィルタは2つのシンタックスタイプをサポートしています: 一般的なワイルドカードを用いた完全一致、そして完全なPerlスタイル (<code>pcre</code>) 正規表現です。初期値ではフィルタは一致する (<b>包括的</b>) な行のみを表示します。一致する行を削除する<b>排他的</b>フィルタを作成するには、フィルタ式の先頭に<kbd>!</kbd>(Exclamationマーク)を付けます。</p><p>To use <b>Regular Expressions</b> (RegEx), prefix the filter text with a <kbd>/</kbd> (slash) or <kbd>^</kbd> (up caret). <b>正規表現</b> (RegEx)を使用するには、フィルタテキストの先頭に<kbd>/</kbd> (スラッシュ) または<kbd>^</kbd>(アップキャレット)を付けます。<ul><li>既に <kbd>/</kbd> または <kbd>^</kbd> を使用している場合は、 <kbd>!</kbd> の後ろに置きます。</li><li>初期値では大文字と小文字が区別されます。それを鈍感にするには、正規表現の最後に典型的な <kbd>/i</kbd> (スラッシュ+i)演算子を追加します。</li> <li> 正規表現を表すためにキャレット『^』を使用すると、それは正規表現の一部になります。例(つまり、行頭から一致します。)</li> <li> 正規表現が無効な場合、フィルタ編集フィールドには赤い枠が表示されフィルタを有効にすることはできません。</li> <li> 正規表現のテストに役立つリソース(参考文献)は、<a href="http://www.regexr.com/"> http://www.regexr.com/にあります。</a></li> </ul></p><p><b>標準一致 basic matching</b> を使用するには、テキストを入力するだけです。<ul><li>ワイルドカード: <kbd>*</kbd> (アスタリスク)は0個以上の任意の文字に一致し、 <kbd>?</kbd> (クエスチョンマーク) は任意の1文字に一致します。</li><li>この一致では常に大文字と小文字が区別されません。</li><li>一致は常にログの先頭行から始まります。 先頭の文字を無視するには、先頭に<kbd>*</kbd>ワイルドカードを使用します。</li><li>末尾の <kbd>*</kbd> は常に暗黙的に指定されます。(つまり、ログ末尾行までが対象) これを回避するには、正規表現を使用します。</li><li>リテラルワイルドカード文字の前に <kbd>\</kbd> (バックスラッシュ) 文字を付けることで一致させることができます。(例: "foo\*bar"は"foo*bar"と一致)</li></ul></p><p><b>テキスト編集</b>後、EnterまたはTabキーを押して (またはボックスの外側をクリックし) フィルタを更新します。</p><p>フィルタセレクタリストから<b>エントリー削除</b>をするには、まずエントリーを選択しエディタで<kbd>Shift+Delete</kbd> (または<kbd>Shift+Backspace</kbd>) を押します。デフォルトのフィルタは削除できません。また最大50個のフィルタが保存されています。</p></body></html>
-
+
Debug Console Filter Help
デバッグコンソールフィルタ ヘルプ
@@ -2795,275 +2925,279 @@ Blank means include all. ?, *, and [...] wildcards accepted.
Firmware
-
+
Channel values displayed in us
表示されるチャンネル値
-
+
No OverrideCH functions available
使用可能な上書きチャンネル機能はありません
-
+
Possibility to enable FAI MODE (no telemetry) at field
フィールドでFAIモード (テレメトリーなし) を有効にする可能性
-
+
FAI MODE (no telemetry) always enabled
FAIモード (テレメトリーなし) を常に有効
-
+
Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015
2015/01/01以降に販売された送信機に対し、EUでの使用に適さないD8 FrSkyプロトコルサポートを削除
-
+
Enable non certified firmwares
認定されていないファームウェアを有効にする
-
-
+
+
Disable HELI menu and cyclic mix support
HELIメニューとサイクリックミックスサポートを無効にする
-
-
+
+
Disable Global variables
グローバル変数を無効にする
-
-
+
+
Enable Lua custom scripts screen
Luaカスタムスクリプト画面を有効にする
-
+
Use alternative SQT5 font
SQT5 代替フォントを使用する
-
+
Pots use in menus navigation
メニューナビゲーションでダイヤルを使用
-
+
FrSky Taranis X9D+
FrSky Taranis X9D+
-
+
Support for PPM internal module hack
PPM内部モジュールハックのサポート
-
+
+
Disable RAS (SWR)
RAS (SWR)を無効にする
-
+
FrSky Taranis X9D+ 2019
-
+
FrSky Taranis X9D
FrSky Taranis X9D
-
+
Haptic module installed
タッチパネル対応モジュールをインストール
-
+
FrSky Taranis X9E
FrSky Taranis X9E
-
+
Confirmation before radio shutdown
送信機シャットダウン前の確認
-
+
Horus gimbals installed (Hall sensors)
Horusジンバル (ホールセンサー) をインストール
-
+
FrSky Taranis X9-Lite
FrSky Taranis X9-Lite
-
-
-
-
-
- Support for auto update on boot
- 起動時の自動更新サポート
-
-
-
+
FrSky Taranis X9-Lite S
-
+
FrSky Taranis X7 / X7S
FrSky Taranis X7 / X7S
-
+
FrSky Taranis X-Lite S/PRO
FrSky Taranis X-Lite S/PRO
-
+
FrSky Taranis X-Lite
FrSky Taranis X-Lite
-
+
FrSky Horus X10 / X10S
FrSky Horus X10 / X10S
-
- FrSky Horus X10 / X10S Express
-
-
-
-
+
FrSky Horus X12S
FrSky Horus X12S
-
+
Use ONLY with first DEV pcb version
初期DEV pcbバージョンでのみ使用
-
- Jumper T16 / T16+
-
-
-
-
+
+
Support for MULTI internal module
MULTI内部モジュールのサポート
-
+
+
Support for bluetooth module
Bluetoothモジュールのサポート
-
+
Turnigy 9XR-PRO
Turnigy 9XR-PRO
-
+
Enable HELI menu and cyclic mix support
HELIメニューとサイクリックミックスのサポートを有効にする
-
+
Global variables
グローバル変数
-
+
In model setup menus automatically set source by moving the control
モデル設定メニューでは、コントローラーを動かし自動的に選択元を設定します
-
+
In model setup menus automatically set switch by moving the control
モデル設定メニューでは、コントローラーを動かし自動的にスイッチを設定します
-
+
No graphical check boxes and sliders
グラフィカルなチェックボックスとスライダーはありません
-
+
Battery graph
バッテリーグラフ
-
+
Don't use bold font for highlighting active items
有効なアイテムを強調表示するために太字フォントを使用しない
-
-
+
+ FrSky Taranis X7 / X7S Access
+ FrSky Taranis X7 / X7S ACCESS
+
+
+
+
Support for ACCESS internal module replacement
ACCESS内部モジュール変更のサポート
-
- Jumper T12
-
-
-
-
- Enable non certified R9M firmwares
- 非認定 R9Mファームウェアを有効
-
-
-
+
Turnigy 9XR with m128 chip
Turnigy 9XR m128チップ搭載
-
+
Turnigy 9XR
Turnigy 9XR
-
+
9X with stock board
9X ストックボード
-
+
Enable resetting values by pressing up and down at the same time
上下に同時に押し、値のリセットを有効にする
-
+
9X with stock board and m128 chip
9X ストックボード+m128 chip
-
+
9X with AR9X board
9X AR9Xボード
-
+
+ FrSky Horus X10 Express / X10S Express
+ FrSky Horus X10 Express / X10S Express
+
+
+
+ Jumper T12 / T12 Pro
+ Jumper T12 / T12 Pro
+
+
+
+ Jumper T16 / T16+ / T16 Pro
+ Jumper T16 / T16+ / T16 Pro
+
+
+
+ Radiomaster TX16s / TX16s Hall / TX16s Masterfire
+ Radiomaster TX16s / TX16s Hall / TX16s Masterfire
+
+
+
+ Support internal GPS
+ 内蔵GPSサポート
+
+
+
9X with Sky9x board
9X Sky9Xボード
-
+
9X with Gruvin9x board
9X Gruvin9X
-
+
DIY MEGA2560 radio
DIY MEGA2560 送信機
@@ -3538,11 +3672,21 @@ You are currently using:
Switch
スイッチ
+
+
+ trim6
+ トリム6
+
+
+
+ trim5
+ トリム5
+
FlightModeData
-
+
FM
FM
@@ -3550,122 +3694,200 @@ You are currently using:
FlightModePanel
-
+
+
Popup menu available
利用可能なポップアップメニュー
-
+
Trim disabled
トリム 無効
-
+
Own Trim
独自トリム
-
+
Use Trim from Flight mode %1
フライトモードからトリムを使用してください %1
-
+
Use Trim from Flight mode %1 + Own Trim as an offset
フライトモードからトリムを使用してください %1+オフセット独自トリム
-
+
Rotary Encoder %1
ロータリーエンコーダ %1
-
+
Name
名称
-
+
Value source
元値
-
+
Value
値
-
+
Unit
ユニット
-
+
Prec
-
+
Min
最小
-
+
Max
最大
-
+
Popup enabled
ポップアップ有効
-
+
GVAR%1
-
+
0._
-
+
0.0
0.0
-
-
- &Clear
- &消去
+
+ Warning: Global variable links back to itself. Flight Mode 0 value used.
+ 警告: フライトモード0の値を使用するとグローバル変数としてリンクされます。
-
-
+
+ Warning: Rotary encoder links back to itself. Flight Mode 0 value used.
+ 警告: フライトモード0の値を使用するとロータリーエンコーダとしてリンクされます。
+
+
+
+
+ Copy
+ コピー
+
+
+
+
+ Cut
+ 切り取り
+
+
+
+
+ Paste
+ 貼り付け
+
+
+
+
+ Insert
+ 挿入
+
+
+
+
+ Delete
+ 削除
+
+
+
+
+ Move Up
+ 上へ移動
+
+
+
+
+ Move Down
+ 下へ移動
+
+
+
+
+ Clear All
+ すべて消去
+
+
+
+ Clear Flight Mode. Are you sure?
+ フライトモードを消去します。よろしいですか?
+
+
+
+ Clear all Flight Modes. Are you sure?
+ フライトモードをすべて消去します。よろしいですか?
+
+
+
+ Delete Flight Mode. Are you sure?
+ フライトモードを削除します。よろしいですか?
+
+
+
+ Clear selected Global Variable across all Flight Modes. Are you sure?
+ すべてのフライトモードの選択したグローバル変数を消去します。よろしいですか?
+
+
+
+ Clear all Global Variables for all Flight Modes. Are you sure?
+ すべてのフライトモードのすべてのグローバル変数を消去します。よろしいですか?
+
+
+
+ Clear all Global Variables for this Flight Mode. Are you sure?
+ このフライトモードのすべてのグローバル変数を消去します。よろしいですか?
+
+
+
+
Clear
消去
-
-
- Clear all current Flight Mode properties?
- 現在のフライトモードのプロパティをすべて消去しますか?
-
FlightModesPanel
-
+
Flight Mode %1
フライトモード %1
-
+
(%1)
(%1)
-
+
(default)
(初期値)
@@ -3993,7 +4215,7 @@ These will be relevant for all models in the same EEPROM.
GeneralSettings
-
+
Radio Settings
送信機設定
@@ -4462,6 +4684,11 @@ p, li { white-space: pre-wrap; }
Show splash screen on startup
起動時、起動イメージ表示
+
+
+ nnnnnnNN
+ nnnnnnNN
+
Power On Delay
@@ -4648,11 +4875,6 @@ Acceptable values are 5v..10v
Owner Registration ID
オーナー登録ID
-
-
- aaaaaaAA
-
-
R E T A
@@ -5283,8 +5505,8 @@ Are you sure ?
HardwarePanel
-
-
+
+
None
なし
@@ -5304,67 +5526,67 @@ Are you sure ?
3 ポジション
-
+
Pot with detent
ダイヤル (ノッチあり)
-
+
Multipos switch
マルチPosスイッチ
-
+
Pot without detent
ダイヤル (ノッチなし)
-
+
Slider with detent
スライダー (ノッチあり)
-
+
OFF
OFF
-
+
Enabled
有効
-
+
Telemetry
テレメトリー
-
+
Trainer
トレーナー
-
+
Internal
内部
-
+
Ask
確認
-
+
Per model
Per モデル
-
+
Internal + External
内部 + 外部
-
+
External
外部
@@ -5491,138 +5713,171 @@ Are you sure ?
InputsPanel
-
+
+
Move Up
上へ移動
-
+
Ctrl+Up
-
+
+
Move Down
下へ移動
-
+
Ctrl+Down
Clear All Inputs
- すべての入力を消去
+ すべての入力項目を消去
-
- Not enough available inputs!
- 入力項目が足りません!
+
+ Not enough available Inputs!
+ 入力項目が不足しています!
-
- Delete Selected Inputs?
- 選択した入力を削除しますか?
+
+ Delete selected Inputs. Are you sure?
+ 選択した入力項目を削除します。よろしいですか?
-
+
+ Lines
+ 直線
+
+
+
&Add
&追加
-
+
Ctrl+A
-
+
&Edit
&編集
-
+
Enter
Enter
-
+
&Delete
&削除
-
+
+
Delete
削除
-
+
&Copy
&コピー
-
+
Ctrl+C
-
+
&Cut
&切り取り
-
+
Ctrl+X
-
+
&Paste
&貼り付け
-
+
Ctrl+V
-
+
Du&plicate
&複製
-
+
Ctrl+U
-
- Clear Inputs?
- 入力を消去しますか?
+
+ Input
+ 入力
-
- Really clear all the inputs?
- すべての入力を本当に消去しますか?
+
+ Insert
+ 挿入
+
+
+
+ Clear
+ 消去
+
+
+
+ Clear All
+ すべて消去
+
+
+
+ Clear all Inputs. Are you sure?
+ すべての入力項目を消去します。よろしいですか?
+
+
+
+ Clear Input. Are you sure?
+ 入力項目を消去します。よろしいですか?
+
+
+
+ Delete Input. Are you sure?
+ 入力項目を削除します。よろしいですか?
LimitData
-
+
INV
リバース
-
+
NOR
ノーマル
-
+
CH
CH
@@ -5761,69 +6016,104 @@ Are you sure ?
LogicalSwitchesPanel
-
+
Function
機能
-
+
V1
-
+
V2
-
+
AND Switch
& スイッチ
-
+
Duration
期間
-
+
Delay
遅延
-
+
Popup menu available
利用可能なポップアップメニュー
-
+
(instant)
(瞬間)
-
+
(infinite)
(無制限)
-
- &Copy
- &コピー
-
-
-
- &Cut
- &切り取り
+
+ Delete Logical Switch. Are you sure?
+ 論理スイッチを削除します。よろしいですか?
- &Paste
- &貼り付け
+ Copy
+ コピー
- &Delete
- &削除
+ Cut
+ 切り取り
+
+
+
+ Paste
+ 貼り付け
+
+
+
+ Clear
+ 消去
+
+
+
+ Insert
+ 挿入
+
+
+
+ Delete
+ 削除
+
+
+
+ Move Up
+ 上へ移動
+
+
+
+ Move Down
+ 下へ移動
+
+
+
+ Clear All
+ すべて消去
+
+
+
+ Clear all Logical Switches. Are you sure?
+ 論理スイッチをすべて消去します。よろしいですか?
@@ -5971,8 +6261,8 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
- total duration
- 合計期間
+ time span
+ 期間
@@ -6003,123 +6293,123 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
MainWindow
-
+
Diskimage (*.dmg)
ディスクイメージ (*.dmg)
-
+
Would you like to open the disk image to install the new version?
新しいバージョンをインストールするためにディスクイメージを開きますか?
-
+
Executable (*.exe)
実行ファイル (*.exe)
-
-
+
+
Would you like to launch the installer?
インストーラを起動しますか?
-
-
+
+
File loaded
ファイルがロードされました
-
+
Checking for updates
アップデートの確認
-
+
A new version of Companion is available (version %1)<br>Would you like to download it?
Companionの新しいバージョンがあります。 (version %1)<br>ダウンロードしますか?
-
-
+
+
Save As
名前を付けて保存
-
+
New release available
新リリースが利用可能
-
+
A new release of Companion is available, please check the <a href='%1'>OpenTX website!</a>
Companionの新リリースが利用可能です。<a href='%1'>OpenTX Webサイト</a>をチェックしてください
-
-
+
+
No updates available at this time.
現時点で利用可能なアップデートはありません。
-
+
Error opening file %1:
%2.
ファイル %1 を開くときにエラーが発生しました:
%2.
-
+
Not enough flash available on this board for all the selected options
選択されたすべてのオプションに対してこのボードでは十分な書き込みが行えません
-
+
Compilation server temporary failure, try later
コンパイルサーバが一時的に失敗しました。後程お試しください
-
+
Compilation server too busy, try later
コンパイルサーバがビジー状態です。後程お試しください
-
+
Compilation error
コンパイルエラー
-
+
Invalid firmware
無効なファームウェア
-
+
Invalid board
無効なボード
-
+
Invalid language
無効な言語
-
+
Unknown server failure, try later
不明なサーバの障害です。後程お試しください
-
+
Do you want to write the firmware to the radio now ?
今すぐファームウェアを送信機に書き込みますか?
-
+
Firmware update check failed, new version information not found or invalid.
ファームウェアアップデートの確認に失敗しました。新しいバージョン情報が見つからないか、または無効です。
-
+
Firmware %1 does not seem to have ever been downloaded.
Version %2 is available.
Do you want to download it now?
@@ -6132,31 +6422,31 @@ We recommend you view the release notes using the button below to learn about an
重要な変更については、下のボタンをクリックしてリリースノートを参照することをお勧めします。
-
-
+
+
Yes
はい
-
-
+
+
No
いいえ
-
-
+
+
Release Notes
リリースノート
-
-
+
+
Do you want to download version %1 now ?
今すぐバージョン %1 をダウンロードしますか?
-
+
A new version of %1 firmware is available:
- current is %2
- newer is %3
@@ -6173,29 +6463,29 @@ We recommend you view the release notes using the button below to learn about an
重要な変更については、下のボタンをクリックしてリリースノートを参照することをお勧めします。
-
+
Ignore this version %1?
このバージョン %1 を無視しますか?
-
+
The new theme will be loaded the next time you start Companion.
次回Companionを起動したときに、新しいテーマがロードされます。
-
-
+
+
Open Models and Settings file
機体モデルと設定ファイルを開く
-
+
File saved
ファイル 保存
-
+
There are unsaved file changes which you may lose when switching radio types.
Do you wish to continue?
@@ -6204,780 +6494,780 @@ Do you wish to continue?
そのまま続けますか?
-
-
+
+
Synchronize SD
SDカードを同期する
-
+
No local SD structure path configured!
SDカード保存先パスが設定されていません!
-
+
No Companion release candidates are currently being served for this version, please switch release channel
現在このバージョンのCompanion RC版は提供されていません。リリース状態を切り替えてください
-
+
No nightly Companion builds are currently being served for this version, please switch release channel
現在、このバージョンのCompanion ナイトリービルド版は提供されていません。リリース状態を切り替えてください
-
+
No Companion release builds are currently being served for this version, please switch release channel
このバージョンのCompanion リリース版は現在提供されていません。リリース状態を切り替えてください
-
+
Companion update check failed, new version information not found.
Companionアップデートの確認に失敗しました。新しいバージョン情報が見つかりません。
-
+
No firmware release candidates are currently being served for this version, please switch release channel
現在、このバージョンのファームウェア RC版は提供されていません。リリース状態を切り替えてください
-
+
No firmware nightly builds are currently being served for this version, please switch release channel
現在、このバージョンのファームウェア ナイトリービルド版は提供されていません。リリース状態を切り替えてください
-
+
No firmware release builds are currently being served for this version, please switch release channel
現在、このバージョンのファームウェア リリース版は提供されていません。リリース状態を切り替えてください
-
+
Release candidate builds are now available for this version, would you like to switch to using them?
RC版はこのバージョンで利用可能になりました。それらに切り替えますか?
-
+
Channel changed to RC, please restart the download process
リリース状態をRC版に変更しました。ダウンロードプロセスを再起動してください
-
+
Official release builds are now available for this version, would you like to switch to using them?
このバージョンの公式リリース版が利用可能になりました。それらに切り替えますか?
-
+
Channel changed to Release, please restart the download process
リリース状態をリリース版に変更しました。ダウンロードプロセスを再起動してください
-
+
This radio (%1) is not currently available in this firmware release channel
この送信機 (%1) は、現在このファームウェアリリース状態では利用できません
-
+
No Radio or SD card detected!
送信機またはSDカードが検出されませんでした!
-
+
Local Folder
ローカルフォルダ
-
+
Radio Folder
送信機フォルダ
-
-
+
+
Read Firmware from Radio
送信機からファームウェアを読み込み
-
-
+
+
Read Models and Settings from Radio
送信機から機体モデルや設定を読み込み
-
+
Models and Settings read
機体モデルと設定の読み込み
-
-
+
+
This function is not yet implemented
この機能はまだ実装されていません
-
+
Save Radio Backup to File
送信機のバックアップをファイルに保存
-
+
Read Radio Firmware to File
送信機ファームウェアからファイルへの読み込み
-
+
OpenTX Home Page: <a href='%1'>%1</a>
OpenTX ホームページ: <a href='%1'>%1</a>
-
+
The OpenTX Companion project was originally forked from <a href='%1'>eePe</a>
OpenTX Companionプロジェクトは元々<a href='%1'>eePe</a>から派生しました
-
+
If you've found this program useful, please support by <a href='%1'>donating</a>
このプログラムが役に立つと感じた場合は、<a href='%1'>寄付</a>でのサポートをお願いします
-
+
Copyright OpenTX Team
Copyright OpenTX Team
-
+
About Companion
Companionについて
-
+
OpenTX Companion %1 - Radio: %2 - Profile: %3
OpenTX Companion %1 - 送信機: %2 - プロファイル: %3
-
+
New
新規
-
+
Create a new Models and Settings file
新規モデルと設定ファイルを作成します
-
+
Open...
開く...
-
+
Save
保存
-
-
+
+
Save Models and Settings file
機体モデルと設定ファイルを保存します
-
+
Save As...
名前を付けて保存...
-
+
Close
閉じる
-
+
Close Models and Settings file
機体モデルと設定ファイルを閉じます
-
+
Exit
終了
-
+
Exit the application
アプリケーションを終了します
-
+
About...
バージョン情報...
-
+
Show the application's About box
アプリケーションのバージョン情報を表示します
-
+
Recent Files
最近使用したファイル
-
+
List of recently used files
最近使用したファイルを一覧表示
-
+
Radio Profiles
送信機プロファイル
-
+
Create or Select Radio Profiles
送信機プロファイルを作成または選択します
-
+
View Log File...
ログファイルを表示...
-
+
Open and view log file
ログファイルを開いて表示します
-
+
Settings...
設定...
-
+
Edit Settings
設定を編集します
-
+
Download...
ダウンロード...
-
+
Download firmware and voice files
ファームウェアと音声ファイルをダウンロードします
-
+
Check for Updates...
アップデートのチェック...
-
+
Check OpenTX and Companion updates
OpenTXとCompanionのアップデートを確認します
-
+
Release notes...
リリースノート...
-
+
Show release notes
リリースノートを表示します
-
+
Compare Models...
機体モデルを比較...
-
+
Compare models
機体モデルを比較します
-
+
Edit Radio Splash Image...
送信機の起動イメージを編集...
-
+
Edit the splash image of your Radio
送信機の起動イメージを編集します
-
+
List programmers...
プログラムを一覧表示...
-
+
List available programmers
利用可能なプログラムを一覧表示します
-
+
Fuses...
ヒューズ...
-
+
Show fuses dialog
ヒューズダイアログを表示します
-
+
Read firmware from Radio
送信機からファームウェアを読み込み
-
+
Write Firmware to Radio
送信機にファームウェアを書き込み
-
+
Write firmware to Radio
送信機にファームウェアを書き込み
-
+
SD card synchronization
SDカードの同期
-
+
Manuals and other Documents
マニュアルと他の文書
-
+
Open the OpenTX document page in a web browser
WebブラウザでOpenTXドキュメントページを開く
-
+
Write Models and Settings To Radio
機体モデルと設定を送信機に書き込み
-
+
Write Models and Settings to Radio
機体モデルと設定を送信機に書き込み
-
+
Read Models and Settings From Radio
送信機から機体モデルや設定を読み込み
-
+
Configure Communications...
送信機疎通を設定...
-
+
Configure software for communicating with the Radio
送信機と疎通するためのソフトウェアを設定します
-
+
Write Backup to Radio
送信機からバックアップを書き出す
-
+
Write Backup from file to Radio
送信機ファイルからバックアップを書き出します
-
+
Backup Radio to File
ファイルを送信機にバックアップ
-
+
Save a complete backup file of all settings and model data in the Radio
すべての設定とモデルデータの完全なバックアップファイルを送信機に保存します
-
+
Contributors...
貢献者...
-
+
A tribute to those who have contributed to OpenTX and Companion
OpenTXとCompanionに貢献した人々への賛辞
-
+
Add Radio Profile
送信機プロファイルの追加
-
+
Create a new Radio Settings Profile
新しい送信機設定プロファイルを作成します
-
+
Copy Current Radio Profile
現在の送信機プロファイルをコピー
-
+
Duplicate current Radio Settings Profile
現在の送信機設定プロファイルを複製します
-
+
Delete Current Radio Profile...
現在の送信機プロファイルを削除...
-
+
Delete the current Radio Settings Profile
現在の送信機設定プロファイルを削除します
-
+
Export Application Settings..
アプリケーション設定のエクスポート..
-
+
Save all the current %1 and Simulator settings (including radio profiles) to a file.
現在のすべての%1およびシミュレータ設定(送信機プロファイル含)をファイルに保存します。
-
+
Import Application Settings..
アプリケーション設定をインポート..
-
+
Load %1 and Simulator settings from a prevously exported settings file.
以前にエクスポートした設定ファイルから%1とシミュレーション設定を読み込みます。
-
+
Tabbed Windows
タブ付きウィンドウ
-
+
Use tabs to arrange open windows.
開いているウィンドウを並べ替えるのにタブを使用します。
-
+
Tile Windows
ウィンドウのタイトル
-
+
Arrange open windows across all the available space.
利用可能なすべてのスペースに開いているウィンドウを配置します。
-
+
Cascade Windows
ウィンドウを重ねる
-
+
Arrange all open windows in a stack.
開いているウィンドウをすべて重ねて配置します。
-
+
Close All Windows
すべてのウィンドウを閉じる
-
+
Closes all open files (prompts to save if necessary.
開いているファイルをすべて閉じます (必要に応じ保存を求められます)。
-
-
+
+
Edit
編集
-
-
+
+
File
ファイル
-
+
Settings
設定
-
+
Set Icon Theme
アイコンテーマ設定
-
+
Set Icon Size
アイコンサイズ設定
-
+
Read/Write
読み込み/書き込み
-
+
Window
ウィンドウ
-
-
+
+
Help
ヘルプ
-
+
Write
書き込み
-
+
Some text will not be translated until the next time you start Companion. Please note that some translations may not be complete.
次にCompanionを起動するまで一部のテキストは翻訳されません。いくつかの翻訳は完全ではないかもしれませんのでご注意ください。
-
+
Ctrl+Shift+S
-
+
Ctrl+Alt+L
-
+
Ctrl+Alt+D
-
+
Ctrl+Alt+R
-
+
Classical
クラシック
-
+
The classic companion9x icon theme
クラシック Companion9x アイコンテーマ
-
+
Yerico
イェリコ
-
+
Yellow round honey sweet icon theme
Yellow round honey sweet アイコンテーマ
-
+
Monochrome
モノクローム
-
+
A monochrome black icon theme
A monochrome black アイコンテーマ
-
+
MonoBlue
モノブルー
-
+
A monochrome blue icon theme
A monochrome blue アイコンテーマ
-
+
MonoWhite
モノホワイト
-
+
A monochrome white icon theme
A monochrome white アイコンテーマ
-
+
Small
小サイズ
-
+
Use small toolbar icons
小サイズのツールバーアイコンを使用
-
+
Normal
標準サイズ
-
+
Use normal size toolbar icons
標準サイズのツールバーアイコンを使用
-
+
Big
大サイズ
-
+
Use big toolbar icons
大サイズのツールバーアイコンを使用
-
+
Huge
特大サイズ
-
+
Use huge toolbar icons
特大サイズのツールバーアイコンを使用
-
+
Set Menu Language
メニュー言語を設定
-
+
System language
システム言語
-
+
Use default system language.
デフォルトのシステム言語を使用します。
-
+
Use %1 language (some translations may not be complete).
%1言語を使用します (一部の翻訳が不完全な場合あり)。
-
+
Ready
準備完了
-
+
%2
%2
-
+
Alt+%1
-
+
New Radio
新規 送信機
-
+
- Copy
- コピー
-
+
Companion :: Open files warning
Companion :: ファイルを開くときの警告
-
+
Please save or close modified file(s) before deleting the active profile.
有効なプロファイルを削除する前に、変更したファイルを保存するか閉じてください。
-
+
Not possible to remove profile
プロファイルを削除できません
-
+
The default profile can not be removed.
デフォルトプロファイルは削除できません。
-
+
Confirm Delete Profile
プロファイル削除の確認
-
+
Are you sure you wish to delete the "%1" radio profile? There is no way to undo this action!
『%1』送信機プロファイルを削除してもよろしいですか?この操作を元に戻すことはできません!
-
+
Please save or close all modified files before importing settings
設定をインポートする前に、変更したファイルをすべて保存するか閉じてください
-
+
<html><p>%1 and Simulator settings can be imported (restored) from a previosly saved export (backup) file. This will replace current settings with any settings found in the file.</p><p>An automatic backup of the current settings will be attempted. But if the current settings are useful then it is recommended that you make a manual backup first.</p><p>For best results when importing settings, <b>close any other %1 windows you may have open, and make sure the standalone Simulator application is not running.</p><p>Do you wish to continue?</p></html>
<html><p>%1とシミュレータの設定は、以前に保存したエクスポート(バックアップ)ファイルからインポート(復元)できます。これにより、現在の設定がファイル内の設定に置き換えられます。</p><p>現在の設定の自動バックアップが実行されます。ただし、現在の設定が便利な場合は、まず手動バックアップを作成することをお勧めします。</p><p>設定をインポートし最良の結果を得るには、<b>開いている%1ウィンドウをすべて閉じます。スタンドアロンのシミュレーターアプリケーションが実行されていません。</p><p>続行しますか?</p></html>
-
+
Confirm Settings Import
設定のインポートの確認
-
+
Select %1:
%1を選択:
-
+
backup
バックアップ
-
+
Press the 'Ignore' button to continue anyway.
とにかく続行するには『無視』ボタンを押してください。
-
+
The settings could not be imported.
設定をインポートできませんでした。
-
+
<html><p>New settings have been imported from:<br> %1.</p><p>%2 will now re-initialize.</p><p>Note that you may need to close and restart %2 before some settings like language and icon theme take effect.</p>
<html><p>新しい設定は次の場所からインポートされました。<br>%1.</p><p>%2は再初期化されます。</p><p>場合によっては閉じて再起動する必要があります。言語やアイコンテーマなどの設定が有効になる前に%2が発生しました。</p>
-
+
<p>The previous settings were backed up to:<br> %1</p>
<p>以前の設定は次の場所にバックアップされました:<br> %1</p>
@@ -7194,159 +7484,164 @@ Do you wish to continue?
空き容量
-
+
+ read only
+ 読み取りのみ
+
+
+
New category
Translators do NOT use accent for this, this is the default category name on Horus.
新規カテゴリ
-
+
Category index out of range.
カテゴリインデックスが範囲外です。
-
+
Cannot delete the last category.
最後のカテゴリは削除できません。
-
+
This category is not empty!
このカテゴリは空ではありません!
-
+
Cannot insert model, last model in list would be deleted.
機体モデルを挿入できません。リストの最後のモデルが削除されます。
-
+
Cannot add model, could not find an available model slot.
機体モデルを追加できません。利用可能なモデルスロットが見つかりません。
-
+
New model
Translators: do NOT use accents here, this is a default model name.
新規モデル
-
+
Cannot paste model, out of available model slots.
利用可能なモデルスロットから、機体モデルを貼り付けることができません。
-
+
You are replacing an existing model, are you sure?
既存の機体モデルを差し替えます。よろしいですか?
-
+
Do you want to overwrite radio general settings?
送信機の一般設定を上書きしますか?
-
+
Delete %n selected model(s)?
選択した機体モデルを %n つ削除しますか?
-
+
Delete %n selected category(ies)?
選択したカテゴリ(ies)を %n つ削除しますか?
-
+
Cannot duplicate model, could not find an available model slot.
機体モデルを複製できません。利用なモデルスロットが見つかりません。
-
+
Editing model %1:
機体モデル %1 を編集しています:
-
+
Save As
名前を付けて保存
-
+
%1 has been modified.
Do you want to save your changes?
%1 は変更されました。
変更を保存しますか?
-
+
<p><b>Currently selected radio type (%1) is not compatible with file %3 (from %2), models and settings need to be converted.</b></p>
<p><b>現在選択されている送信機タイプ (%1) はファイル %3 (from %2) と互換性がありません。機体モデルと設定を変換する必要があります。</b></p>
-
+
Do you wish to continue with the conversion?
変換を続けますか?
-
+
Choose <i>Apply</i> to convert the file, or <i>Close</i> to close it without conversion.
ファイルを変換するには<i>適用</i>を、変換せずに閉じるには<i>閉じる</i>を選択します。
-
+
<b>The conversion generated some important messages, please review them below.</b>
<b>変換によっていくつかの重要なメッセージが出力されました。下記の内容を確認してください。</b>
-
+
Companion :: Conversion Result for %1
Companion :: %1 の変換結果
-
- Unable to find Horus radio SD card!
- Horus送信機のSDカードが見つかりません!
+
+ Unable to find radio SD card!
+ 送信機のSDカードが見つかりません!
-
+
Models and Settings written
機体モデルと設定が書かれました
-
+
Cannot write temporary file!
一時ファイルを書き込めません!
-
+
Open backup Models and Settings file
バックアップ機体モデルと設定ファイルを開く
-
+
Unable to find file %1!
ファイル %1 が見つかりません!
-
+
Error opening file %1:
%2.
ファイル %1 を開くときにエラーが発生しました:
%2.
-
+
Error reading file %1:
%2.
ファイル %1 の読み取りエラーです:
%2.
-
+
Invalid binary backup File %1
無効なバイナリバックアップファイルです %1
@@ -7354,12 +7649,12 @@ Do you want to save your changes?
MixData
-
+
MIX
ミックス
-
+
(@%1)
@@ -7754,12 +8049,12 @@ If blank then the mix is considered to be "ON" all the time.
ModelData
-
+
Model:
機体モデル:
-
+
Throttle Source
スロットル値
@@ -8700,12 +8995,7 @@ If blank then the mix is considered to be "ON" all the time.
受信機 3
-
- Bind on startup
- 起動時バインド
-
-
-
+
Low Power
低パワー
@@ -8715,158 +9005,183 @@ If blank then the mix is considered to be "ON" all the time.
警告: 送信出力を変更するには再バインドが必要です
-
+
Channels
チャンネル
-
+
PPM delay
PPM 遅延
-
+
us
-
+
PPM Frame Length
PPM フレーム長
-
+
ms
ms
-
+
Antenna
アンテナ
-
+
Output type
出力タイプ
-
+
Open Drain
オープン ドレン
-
+
Push Pull
プッシュ プル
-
+
Option value
オプション値
-
+
Protocol
プロトコル
-
+
Registration ID
登録ID
-
+
Multi Radio Protocol
マルチプロトコル
-
+
Sub Type
サブタイプ
-
+
Failsafe Mode
フェイルセーフモード
-
+
Not set
設定なし
-
+
Hold
ホールド
-
+
Custom
カスタム
-
+
No Pulses
パルスなし
-
+
Receiver
受信機
-
+
Trainer Mode
トレーナーモード
-
+
Master/Jack
マスター/Jack
-
+
Slave/Jack
スレーブ/Jack
-
+
Master/SBUS Module
マスター/SBUSモジュール
-
+
Master/CPPM Module
マスター/CPPMモジュール
-
+
Master/SBUS in battery compartment
マスター/バッテリーカバー内SBUB
-
+
WARNING: Requires non-certified firmware!
警告: 未認定のR9Mファームウェアが必要です!
-
+
+ Master/Bluetooth
+ マスター/Bluetooth
+
+
+
+ Slave/Bluetooth
+ スレーブ/Bluetooth
+
+
+
+ Master/Multi
+ マスター/Multi
+
+
+
+ Disable Telemetry
+ テレメトリー無効
+
+
+
+ Disable Ch. Map
+ チャンネルマップ無効
+
+
+
Failsafe Positions
フェイルセーフポジション
-
+
Show values in:
値の表示:
-
+
%
abbreviation for percent
-
+
μs
abbreviation for microseconds
@@ -8948,12 +9263,12 @@ If blank then the mix is considered to be "ON" all the time.
100mW - 16CH (テレメトリーなし)
-
+
Positive
ノーマル
-
+
Negative
リバース
@@ -8961,40 +9276,50 @@ If blank then the mix is considered to be "ON" all the time.
ModulePanel
-
+
Value
値
-
+
Hold
ホールド
-
+
No Pulse
パルスなし
-
+
Ask
確認
-
+
Internal
内部
-
+
Internal + External
内部 + 外部
-
+
External
外部
+
+
+ Autodetect Format
+ フォーマット自動検出
+
+
+
+ Bind on channel
+ チャンネルへバインド
+
MultiModelPrinter
@@ -9492,11 +9817,6 @@ If blank then the mix is considered to be "ON" all the time.
DEFAULT
初期値
-
-
- Custom - proto %1)
- カスタム - プロトコル%1)
-
MultirotorPage
@@ -9524,22 +9844,22 @@ If blank then the mix is considered to be "ON" all the time.
OpenTxEepromInterface
-
+
Unknown error
不明のエラー
-
+
... plus %1 errors
...追加 %1 エラー
-
+
Cannot write radio settings
送信機設定を書き込めません
-
+
Cannot write model %1
機体モデル %1 を書き込めません
@@ -9644,6 +9964,19 @@ If blank then the mix is considered to be "ON" all the time.
ODFファイル (*.odt);;PDFファイル (*.pdf);;HTMLファイル (*.htm *.html);;すべてのファイル (*)
+
+ ProfileChooserDialog
+
+
+ Select Profile
+ プロファイル選択
+
+
+
+ Profile
+ プロファイル
+
+
ProgressDialog
@@ -9812,8 +10145,8 @@ If blank then the mix is considered to be "ON" all the time.
- Unable to find Horus radio SD card!
- Horus送信機のSDカードが見つかりません!
+ Unable to find radio SD card!
+ 送信機のSDカードが見つかりません!
@@ -10750,7 +11083,12 @@ X
-
+
+ ml/minute
+
+
+
+
TELE
@@ -10930,25 +11268,90 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
SetupPanel
-
+
+ Popup menu available
+ 利用可能なポップアップメニュー
+
+
+
Timer %1
タイマー %1
-
+
THR
-
+
Profile Settings
プロファイル設定
-
+
SD structure path not specified or invalid
SDカード保存先パスが指定されていないか無効です
+
+
+ Copy
+ コピー
+
+
+
+ Cut
+ 切り取り
+
+
+
+ Paste
+ 貼り付け
+
+
+
+ Clear
+ 消去
+
+
+
+ Insert
+ 挿入
+
+
+
+ Delete
+ 削除
+
+
+
+ Move Up
+ 上へ移動
+
+
+
+ Move Down
+ 下へ移動
+
+
+
+ Clear All
+ すべて消去
+
+
+
+ Clear Timer. Are you sure?
+ タイマーを消去します。よろしいですか?
+
+
+
+ Clear all Timers. Are you sure?
+ タイマーをすべて消去します。よろしいですか?
+
+
+
+ Delete Timer. Are you sure?
+ タイマーを削除します。よろしいですか?
+
SimpleTailPage
@@ -11671,62 +12074,62 @@ The default is configured in the chosen Radio Profile.
送信機シミュレータ (%1)
-
+
Could not determine startup data source.
起動データ元を特定できませんでした。
-
+
Could not load data, possibly wrong format.
データをロードできません、フォーマットが間違っている可能性があります。
-
+
Data Load Error
データロード エラー
-
+
Invalid startup data provided. Plese specify a proper file/path.
無効なスタートアップデータが提供されました。正しいファイル/パスを指定してください。
-
+
Simulator Startup Error
シミュレータ スタートアップ エラー
-
+
Error saving data: could open file for writing: '%1'
データ保存エラー: 書き込み用にファイルを開くことができました: 「%1」
-
+
Error saving data: could not get data from simulator interface.
データ保存エラー: シミュレータのインターフェイスからデータを取得できませんでした。
-
+
An unexpected error occurred while attempting to save radio data to file '%1'.
送信機データをファイル「%1」に保存しようとしたときに予期せぬエラーが発生しました。
-
+
Data Save Error
データ保存 エラー
-
+
Cannot open joystick, joystick disabled
スティックが接続不可、もしくはスティックが無効です
-
+
Radio firmware error: %1
送信機 ファームウェア エラー: %1
-
+
- Flight Mode %1 (#%2)
- フライトモード %1 (#%2)
@@ -12427,104 +12830,104 @@ Too many errors, giving up.
TelemetryPanel
-
+
Telemetry screen %1
テレメトリースクリーン %1
-
+
FrSky S.PORT
-
+
FrSky D
-
+
FrSky D (cable)
-
+
Source
信号元
-
+
Low Alarm
低アラーム
-
+
Critical Alarm
クリティカルアラーム
-
+
Winged Shadow How High
Winged Shadow How High
-
+
Winged Shadow How High (not supported)
Winged Shadow How High (サポートなし)
-
+
Alti
-
+
Alti+
-
+
VSpeed
-
-
-
+
+
+
A1
-
-
-
+
+
+
A2
-
-
+
+
A3
-
-
+
+
A4
-
-
+
+
FAS
-
+
Cells
セル
-
+
---
---
@@ -12537,274 +12940,284 @@ Too many errors, giving up.
フォーム
-
+
+ TELE##
+ TELE##
+
+
+
Custom
カスタム
-
+
Calculated
計算値
-
+
Id
ID
-
+
Instance
インスタンス
-
+
Rx
受信
-
+
Add
追加
-
+
Average
平均
-
+
Min
最小
-
+
Max
最大
-
+
Multiply
乗算
-
+
Totalize
合計
-
+
Cell
セル
-
+
Consumption
消費
-
+
Dist
距離
-
+
Cells Sensor :
セル センサー :
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
---
---
-
+
GPS Sensor :
GPS センサー :
-
+
Alt. Sensor :
高度 センサー :
-
+
Sensor :
センサー :
-
+
Raw (-)
Raw (-)
-
+
V
V
-
+
A
-
+
mA
-
+
kt
-
+
m/s
-
+
ft/s
-
+
km/h
-
+
mph
-
+
m
分
-
+
ft
-
+
°C
-
+
°F
-
+
%
-
+
mAh
-
+
W
-
+
mW
-
+
dBm
-
+
RPM
-
+
g
-
+
°
-
+
Rad
-
+
mL
-
+
US fl.Oz.
-
+
+ ml/min
+
+
+
+
Precision
精度
-
+
Ratio
レシオ
-
+
Blades
ブレード
-
+
Offset
オフセット
-
+
Multiplier
乗算
-
+
Auto Offset
自動オフセット
-
+
Filter
フィルタ
-
+
Persistent
持続
-
+
Positive
ノーマル
-
+
Logs
ログ
@@ -12812,25 +13225,70 @@ Too many errors, giving up.
TelemetrySensorPanel
-
+
+ TELE%1
+
+
+
+
+ Popup menu available
+ 利用可能なポップアップメニュー
+
+
+
Lowest
より低く
-
+
Cell %1
セル %1
-
+
Highest
より高く
-
+
Delta
差分
+
+
+ Copy
+ コピー
+
+
+
+ Cut
+ 切り取り
+
+
+
+ Paste
+ 貼り付け
+
+
+
+ Clear
+ 消去
+
+
+
+ Clear All
+ すべて消去
+
+
+
+ Clear Telemetry Sensor. Are you sure?
+ テレメトリーセンサーを消去します。よろしいですか?
+
+
+
+ Clear all Telemetry Sensors. Are you sure?
+ テレメトリーセンサーのすべてを消去します。よろしいですか?
+
TelemetrySimulator
@@ -13209,12 +13667,12 @@ hh:mm:ss
TimerData
-
+
TMR
-
+
Timer %1
タイマー %1
@@ -14192,119 +14650,4 @@ Press Cancel to abort joystick calibration without saving.
キャリブレーションが完了していません。そのまま保存しますか?
-
- preferencesDialog
-
-
- Preferences
- 設定
-
-
-
- Simu BackLight
- シミュレータ バックライト
-
-
-
- Simulator capture folder
- シミュレータ キャプチャフォルダ
-
-
-
- Joystick
- スティック
-
-
-
- Remember simulator switches
- シミュレータスイッチの記憶
-
-
-
- Enable
- 有効
-
-
-
- Use clipboard only
- クリップボードのみを使用
-
-
-
- Calibrate
- キャリブレート
-
-
-
- Blue
- 青色
-
-
-
- Green
- 緑色
-
-
-
- Red
- 赤色
-
-
-
- Orange
- オレンジ
-
-
-
- Yellow
- 黄色
-
-
-
-
- Open Folder
- フォルダを開く
-
-
-
- Personal splash library
- 個人イメージライブラリ
-
-
-
- Include companion splashes
- 標準Companion起動イメージ
-
-
-
- Only user defined splashes
- ユーザ設定の起動イメージのみ
-
-
-
- Splash library behaviour
- 起動イメージライブラリの動作
-
-
-
- Custom TX splash screen
- カスタム起動イメージ
-
-
-
- Open Image
- イメージを開く
-
-
-
-
- ...
- ...
-
-
-
- Invert Pixels
- ピクセルを反転
-
-
diff --git a/companion/src/translations/companion_ru.ts b/companion/src/translations/companion_ru.ts
index 148edd16c..540e00c7d 100644
--- a/companion/src/translations/companion_ru.ts
+++ b/companion/src/translations/companion_ru.ts
@@ -1,110 +1,144 @@
-
+
AileronsPage
-
+
No
-
+ Нет
-
+
Yes, controlled by a single channel
-
+ Да, управляются одним каналом
-
+
Yes, controlled by two channels
-
+ Да, управляются двумя каналами
-
+
<br>First Aileron Channel:
-
+ <br>Первый канал элеронов:
-
+
Second Aileron Channel:
-
+ Второй канал элеронов:
AirbrakesPage
-
+
No
-
+ Нет
-
+
Yes, controlled by a single channel
-
+ Да, управляются одним каналом
-
+
Yes, controlled by two channels
-
+ Да, управляются двумя каналами
-
+
<br>First Airbrake Channel:
-
+ <br>Первый канал воздушного тормоза:
-
+
Second Airbrake Channel:
-
+ Второй канал воздушного тормоза:
+
+
+
+ AppData
+
+
+ Application Settings have been saved to
+ %1
+ Настройки приложения сохранены в
+ %1
+
+
+
+ Could not save Application Settings to file "%1"
+ Не удалось сохранить настройки приложения в файл "%1"
+
+
+
+ because the file could not be saved (check access permissions).
+ файл нельзя сохранить (проверьте права доступа).
+
+
+
+ for unknown reasons.
+ причина неизвестна.
+
+
+
+ AppMessages
+
+
+ Show this message again at next startup?
+ Показывать это сообщение при следующем запуске?
AppPreferencesDialog
-
+
Edit Settings
-
+ Настройки
-
+
Radio Profile
-
+ Профиль передатчика
-
-
-
-
-
- Open Folder
-
-
-
-
+
Default Channel Order
- Порядок следов. каналов
+ Порядок каналов
-
+
Build Options
-
+ Параметры прошивки
-
+
Menu Language
-
+ Язык меню
-
+
Default Stick Mode
- Режим стиков
+ Режим стиков (мода)
-
+
Select Image
-
+ Выбрать картинку
-
+
+
+
+
+
+
+ Select Folder
+ Выбрать папку
+
+
+
Mode selection:
Mode 1:
@@ -124,1037 +158,1248 @@ Mode 4:
Right stick: Elevator, Rudder
-
+ Выбор моды передатчика:
+
+Mode 1:
+ Левый стик: Руль высоты (Elevator), Руль направления (Rudder)
+ Правый стик: Газ (Throttle), Элероны (Aileron)
+
+Mode 2:
+ Левый стик: Газ (Throttle), Руль направления (Rudder)
+ Правый стик: Руль высоты (Elevator), Элероны (Aileron)
+
+Mode 3:
+ Левый стик: Руль высоты (Elevator), Элероны (Aileron)
+ Правый стик: Газ (Throttle), Руль направления (Rudder)
+
+Mode 4:
+ Левый стик: Газ (Throttle), Элероны (Aileron)
+ Правый стик: Руль высоты (Elevator), Руль направления (Rudder)
+
+
-
+
Mode 1 (RUD ELE THR AIL)
-
+
-
+
Mode 2 (RUD THR ELE AIL)
-
+
-
+
Mode 3 (AIL ELE THR RUD)
-
+
-
+
Mode 4 (AIL THR ELE RUD)
-
+
-
+
Splash Screen
-
+ Заставка при включении
-
-
+
+
The profile specific folder, if set, will override general Backup folder
-
+ Папка с резервными копиями. Относится к выбранному профилю, переопределяет настройки приложения
-
+
Backup folder
-
-
-
-
- If set it will override the application general setting
-
-
-
-
- if set, will override general backup enable
-
-
-
-
- <html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html>
-
-
-
-
- R E T A
-
-
-
-
- R E A T
-
-
-
-
- R T E A
-
-
-
-
- R T A E
-
-
-
-
- R A E T
-
-
-
-
- R A T E
-
-
-
-
- E R T A
-
-
-
-
- E R A T
-
-
-
-
- E T R A
-
-
-
-
- E T A R
-
-
-
-
- E A R T
-
-
-
-
- E A T R
-
-
-
-
- T R E A
-
-
-
-
- T R A E
-
-
-
-
- T E R A
-
-
-
-
- T E A R
-
-
-
-
- T A R E
-
-
-
-
- T A E R
-
-
-
-
- A R E T
-
-
-
-
- A R T E
-
-
-
-
- A E R T
-
-
-
-
- A E T R
-
-
-
-
- A T R E
-
+ Резервное копирование
- A T E R
-
+ If set it will override the application general setting
+ Переопределяет папку, заданную в настройках приложения
-
- Use OpenTX firmware nightly builds
-
+
+ if set, will override general backup enable
+ Переопределяет настроки приложения
-
- Use Companion nightly builds
-
+
+ <html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html>
+ <html><head/><body><p>Порядок каналов</p><p><br/></p><p>Задает порядок микшеров при создании новой модели.</p></body></html>
-
- Simulator Volume Gain
-
+
+ R E T A
+
-
- Profile Name
-
+
+ R E A T
+
-
- Remove Profile
-
+
+ R T E A
+
-
- Clear Image
-
+
+ R T A E
+
-
- Append version number to FW file name
-
+
+ R A E T
+
-
- Offer to write FW to Tx after download
-
+
+ R A T E
+
-
- Radio Type
-
+
+ E R T A
+
+
+
+
+ E R A T
+
+
+
+
+ E T R A
+
+ E T A R
+
+
+
+
+ E A R T
+
+
+
+
+ E A T R
+
+
+
+
+ T R E A
+
+
+
+
+ T R A E
+
+
+
+
+ T E R A
+
+
+
+
+ T E A R
+
+
+
+
+ T A R E
+
+
+
+
+ T A E R
+
+
+
+
+ A R E T
+
+
+
+
+ A R T E
+
+
+
+
+ A E R T
+
+
+
+
+ A E T R
+
+
+
+
+ A T R E
+
+
+
+
+ A T E R
+
+
+
+
+ Simulator Volume Gain
+ Усиление звука в симуляторе
+
+
+
+ Profile Name
+ Название профиля
+
+
+
+ Clear Image
+ Убрать картинку
+
+
+
+ Append version number to FW file name
+ Добавить номер версии к названию файла прошивки
+
+
+
+ Offer to write FW to Tx after download
+ Предложить обновить прошивку после загрузки
+
+
+
+ Radio Type
+ Тип передатчика
+
+
+
Other Settings
-
+ Другие настройки
-
+
General Settings
- Основные настройки
+ Основные настройки
-
+
SD Structure path
-
+ Папка с содержимым SD
-
- Set voice language.
-May be different from firmware language
-
-
-
-
- Voice Language
-
-
-
-
+
Application Settings
-
+ Настройки приложения
-
+
Show splash screen when Companion starts
-
+ Показывать заставку при загрузке Companion
-
+
Automatic check for Companion updates
-
+ Автоматически проверять наличие обновлений Companion
-
-
+
+
Enable automatic backup before writing firmware
-
+ Автоматически делать резервную копию перед обновлением прошивки
-
+
Automatic check for OpenTX firmware updates
-
+ Автоматически проверять наличие обновлений прошивки (OpenTX)
-
+
Splash Screen Library
-
+ Галерея изображений
-
- Files to keep
-
-
-
-
- Find Executable
-
-
-
-
+
Google Earth Executable
-
+ Запуск Google Earth
-
+
Only show user splash images
-
+ Показывать только пользовательские изображения
-
+
Show user and companion splash images
-
+ Показывать встроенные и пользовательские изображения
-
+
User Splash Screens
-
+ Пользовательские заставки
-
+
Automatic Backup Folder
-
+ Папка для резервн. копий
-
- Use model wizard when creating a new model
-
-
-
-
+
Simulator Settings
-
+ Настройки симулятора
-
+
Simulator BackLight
-
+ Подсветка в симуляторе
-
+
Enable
-
+ Включить
-
+
+ most recently used files
+ часто используемых файлов
+
+
+
+ Startup Settings
+ Запуск приложения
+
+
+
+ Remember
+ Запомнить
+
+
+
+ <html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html>
+ <html><head/><body><p>Это опция нужна, чтобы при удалении или перемещении модели сохранить поведение как старых версиях OpenTX. </p><p>Если отключить, то при удалении модели другие модели могут быть перемещены, чтобы убрать пустые слоты</p></body></html>
+
+
+
+ Remove empty model slots when deleting models (only applies for radios w/out categories)
+ Удалять пустые слоты при удалении модели (только если нет категорий)
+
+
+
+ Output Logs Folder
+ Папка с журналами
+
+
+
+ Debug Output Logging
+ Журнал событий
+
+
+
+ Use model wizard
+ использовать мастер
+
+
+
+ Open model editor
+ открыть редактор
+
+
+
+ Just create the model
+ просто создать модель
+
+
+
+ Select Executable
+ Указать файл
+
+
+
+ Action on New Model
+ Создание новой модели
+
+
+
+ <html><head/><body><p>Keep a log of all debugging messages generated by the desktop Companion/Simulator applications. An OpenTX developer may request this to help diagnose an issue.</p></body></html>
+ <html><head/><body><p>Сохранение отладочных сообщений из Companion и симулятора. При поиске проблем разработчики OpenTX могут попросить эти журналы.</p></body></html>
+
+
+
+ Application (Companion/Simulator)
+ приложения (Companion/Симулятор)
+
+
+
+ <html><head/><body><p>Keep a log of all messages generated by the radio firmware when running in Simulator. This is the same information one would also see in the Simulator <span style=" font-style:italic;">Debug Output</span> window.</p></body></html>
+ <html><head/><body><p>Сохранение всех сообщений прошивки запущенной в симуляторе. Это те же сообщения, что вы можете увидеть в симуляторе, в окне <span style=" font-style:italic;">Debug Output</span></p></body></html>
+
+
+
+ Radio Firmware (in Simulator)
+ прошивки передатчика (в симуляторе)
+
+
+
+ Release channel
+ Версии обновлений
+
+
+
+ Releases (stable)
+ Релизы (стабильные версии)
+
+
+
+ Release candidates (testing)
+ Предварительные версии (тестовые) / Release candidates
+
+
+
+ Nightly builds (unstable)
+ Ночные сборки (нестабильные версии)
+
+
+
Blue
-
+ Синяя
-
+
Green
-
+ Зеленая
-
+
Red
-
+ Красная
-
+
Orange
-
+ Оранжевая
-
+
Yellow
-
+ Желтая
-
+
+ Screenshot capture folder
+ Папка для скриншотов
+
+
+
Joystick
-
+ Джойстик
-
+
Calibrate
-
+ Калибровка
-
- Simulator capture folder
-
-
-
-
+
Only capture to clipboard
-
+ Не сохранять, только копировать в буфер обмена
-
+
Remember simulator switch values
-
+ Запоминать положения тумблеров в симуляторе
-
+
My Radio
-
+
+ <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>
+ <p><b>Если есть несохраненные изменения, то нельзя поменять тип передатчика и параметры прошивки. Что делать?</b></p> <ul><li><i>Сохранить все</i> - Сохранить все открытые файлы, прежде чем менять настройки.<li><li><i>Сбросить</i> - Перед сохранением вернуть все настройки назад.</li><li><i>Отмена</i> - Ничего не делать, вернуться к настройкам..</li></ul>
+
+
+
Select your snapshot folder
+ Выберите папку
+
+
+
+ Note: Nightly builds are not available in this version, Release/RC update channel will be used.
-
-
+
+
No joysticks found
-
+ Джойстик не найден
-
+
EMPTY: No radio settings stored in profile
-
+ ПУСТО: в профиле нет настроек аппаратуры
-
+
AVAILABLE: Radio settings of unknown age
-
+
AVAILABLE: Radio settings stored %1
-
+
Select your library folder
-
+ Выберите папку
-
-
+
+
Select your Models and Settings backup folder
-
+ Выберите папку для резервного копирования моделей и настроек
-
+
+ Select a folder for application logs
+ Выберите папку для хранения журнала событий
+
+
+
Select Google Earth executable
-
+ Выбрать исполняемый файл Google Earth
-
+
Select the folder replicating your SD structure
-
+ Выберите папку, в которой хранится содержимое SD карточки
-
- Not possible to remove profile
-
-
-
-
- The default profile can not be removed.
-
-
-
-
+
Open Image to load
-
+ Выберите изображение
-
+
Images (%1)
-
+ Изображения (%1)
- Calibration
+ BinEepromFormat
-
- Form
+
+ Error reading %1: %2
+ Ошибка чтения %1: %2
+
+
+
+ Cannot save EEPROM
+ Не удалось сохранить EEPROM
+
+
+
+ Cannot open file %1:
+%2.
+ Не удалось открыть файл %1:
+%2.
+
+
+
+ Error writing file %1:
+%2.
+ Ошибка при записи файла %1:
+%2.
+
+
+
+ Invalid binary EEPROM file %1
+ Неправильный бинарный EEPROM файл %1
+
+
+
+ Boards
+
+
+ Left Horizontal
-
- SQ
+
+ Left Vertical
-
- SR
+
+ Right Vertical
-
- LS2
+
+ Right Horizontal
-
- SP
+
+ Aux. 1
-
- SO
+
+ Aux. 2
-
- S4
+
+
+ Unknown
-
- RS
-
-
-
-
- SB
-
-
-
-
- Serial Port
-
-
-
-
-
-
-
-
-
-
-
-
-
- Beeper volume
-
-0 - Quiet. No beeps at all.
-1 - No Keys. Normal beeps but menu keys do not beep.
-2 - Normal.
-3 - Loud.
-4 - Extra loud.
- Громкость.
-
-0 - Тишина.
-1 - Без кнопок.
-2 - Обычная.
-3 - Громкая.
-4 - Очень громкая.
-
-
-
- OFF
- ВЫКЛ
-
-
-
- S-Port Mirror
-
-
-
-
- Telemetry
-
-
-
-
- SBUS Trainer
-
-
-
-
- Debug
-
-
-
-
+
Rud
-
-
- Mid value
-
-
-
-
- Pot. 4
-
-
-
-
- Pot. 3
-
-
-
-
- Pot. 2
-
-
-
-
- Pot. 1
-
-
-
-
- PPM 1
-
-
-
-
- Stick 3
-
-
-
-
-
- Negative span
-
-
-
-
-
- Positive span
-
-
-
-
- Stick 1
-
-
-
-
- PPM 2
-
-
-
-
- Stick 2
-
-
-
-
- Stick 4
-
-
-
-
- v
- В
-
-
-
- PPM Multiplier
- PPM множитель
-
-
-
- PPM 3
-
-
-
-
- PPM 4
-
-
-
-
- Battery Offset
-
-
-
-
- Current Offset
-
-
-
-
- S1
-
-
-
-
- S2
-
-
-
-
- S3
-
-
-
-
- SA
-
-
-
-
+
Ele
-
- Ail
-
-
-
-
+
Thr
-
- SC
-
-
-
-
- LS
-
-
-
-
- SD
-
-
-
-
- SE
-
-
-
-
- SF
-
-
-
-
- SG
-
-
-
-
- SH
-
-
-
-
- SI
-
-
-
-
- SJ
-
-
-
-
- SK
-
-
-
-
- SL
-
-
-
-
- SM
-
-
-
-
- SN
-
-
-
-
- RS2
-
-
-
-
- Bluetooth
+
+ Ail
CalibrationPanel
-
-
-
- None
+
+ Negative span
-
- 2 Positions Toggle
+
+ Mid value
-
- 2 Positions
+
+ Positive span
+
+
+
+
+ CategorizedStorageFormat
+
+
+ Can't extract RADIO/radio.bin
-
- 3 Positions
+
+ Can't extract RADIO/models.txt
-
- Pot with detent
-
+
+ Can't extract %1
+ Не удалось извлечь %1
-
- Multipos switch
-
-
-
-
- Pot without detent
-
-
-
-
- Slider with detent
+
+ Error loading models
Channels
-
+
Name
-
+ Название
-
+
Min
Мин
-
+
Max
Макс
-
+
Subtrim
-
+ Субтриммер
-
+
Direction
-
+ Направление
-
+
Curve
Кривая
-
+
PPM Center
-
+
Linear Subtrim
+ Линайный субтриммер
+
+
+
+ CH%1
-
- Channel %1
+
+ Popup menu available
-
+
+ Copy
+ Копировать
+
+
+
+ Cut
+ Вырезать
+
+
+
+ Paste
+ Вставить
+
+
+
+ Clear
+ Очистить
+
+
+
+ Insert
+ Вставка
+
+
+
+ Delete
+ Удалить
+
+
+
+ Move Up
+ Сдвинуть вверх
+
+
+
+ Move Down
+ Сдвинуть вниз
+
+
+
+ Clear All
+ Очистить всё
+
+
+
---
-
+
INV
+
+ ChecklistDialog
+
+
+ Edit Checklist
+ Редактирование контрольной карты
+
+
+
+ Line nn, Col nn
+ Строка nn, столбец nn
+
+
+
+ &Import...
+ Импорт...
+
+
+
+ &Cancel
+ Отмена
+
+
+
+ &OK
+
+
+
+
+ Please note, the maximum width displayable is radio model limited. Also, renaming the model will break the link to this checklist file.
+ Учтите, что ширина отображаемого текста ограничена. Переименование модели удалит ссылку на эту контрольную карту.
+
+
+
+ File: unknown
+ Файл: неизвестен
+
+
+
+ Open Checklist
+ Открыть контрольную карту
+
+
+
+ Checklist Files (*.txt)
+ Контрольные карты (*.txt)
+
+
+
+
+
+
+
+ Model Checklist
+
+
+
+
+ Cannot open file for writing %1:
+%2.
+
+
+
+
+ Cannot write to file %1:
+%2.
+
+
+
+
+ Cannot write file %1:
+%2.
+ Не удается записать файл %1:
+%2.
+
+
+
+ Cannot open file %1:
+%2.
+
+
+
+
+ Cannot read file %1:
+%2.
+
+
+
+
+ Line %1, Col %2
+ Строка %1, столбец %2
+
+
+
+ Companion
+
+
+ The saved settings could not be imported, please try again or continue with current settings.
+
+
+
+
+ Import from File
+
+
+
+
+ Import from v%1
+
+
+
+
+ Do not import
+
+
+
+
+ We have found possible Companion settings backup file(s).
+Do you want to import settings from a file?
+
+
+
+
+ Import settings from a file, or start with current values.
+
+
+
+
+ We have found existing settings for Companion version: %1.
+Do you want to import them?
+
+If you have a settings backup file, you may import that instead.
+
+
+
+
+ Select %1:
+
+
+
+
+ Save application settings to file...
+
+
+
+
+ Load application settings from file or previous version...
+
+
+
+
+ Reset ALL application settings to default and remove radio profiles...
+
+
+
+
+ Exit before settings initialization and application startup.
+
+
+
+
+ Print version number and exit.
+
+
+
+
+ Print this help text.
+
+
+
+
+ Reset ALL application settings to default values and remove radio profiles, are you sure?
+
+
+
+
+ Would you like to perform a backup first?
+
+
+
+
+ Application settings were reset and saved.
+
+
+
+
+ OpenTX Companion
+
+
+
+
+ Information
+
+
+
+
+ Warning
+ Звук
+
+
+
+ Error
+ Ошибка
+
+
+
+ files
+
+
+
+
+ Radio and Models settings
+
+
+
+
+ Application Settings
+ Настройки приложения
+
+
+
+ Select or create a file for exported Settings:
+
+
+
+
+ Press the 'Retry' button to choose another file.
+
+
+
+
+ Simulator for this firmware is not yet available
+
+
+
+
+ Uknown error during Simulator startup.
+
+
+
+
+ Simulator Error
+
+
+
+
+ Data Load Error
+
+
+
+
+ Error occurred while starting simulator.
+
+
+
+
+ settings
+
+
+
+
+ <p><b>Welcome to OpenTX %1.</b></p><p>As the first step, please configure the initial Radio Profile by selecting your Radio Type, Menu Language, and Build Options.</p><p>You may also want to take this time to review the other available options in the displayed Settings dialog.</p><p>After saving your settings, we recommend you download the latest firmware for your radio by using the <i>File -> Download</i> menu option.</p><p>Please visit <a href='http://www.open-tx.org'>open-tx.org</a> for latest news, updates and documentation. Thank you for choosing OpenTX!</p>- The OpenTX Team.
+
+
+
+
+ <p><b>Thank you for upgrading to OpenTX %1.</b></p><p>This is a major upgrade that adds and modifies a lot of things, so please make sure that you read release notes carefully to learn about the changes, and thoroughly check each of your models for proper function.</p><p>Please visit <a href='http://www.open-tx.org'>open-tx.org</a> for release notes and other documentation.</p>- The OpenTX Team.
+
+
+
+
+ <p>The radio type in the selected profile does not exist. Using the default type instead.</p> <p><b>Please update your profile settings!</b></p>
+
+
+
CompareDialog
Compare Models
-
+ Сравнение моделей
-
- Drag first model here
-
+
+ To compare models, drag and drop them anywhere in this window.
+ Чтобы сравнить модели перетащите их в это окно.
-
- Drag second model here
-
-
-
-
+
Close
-
+ Закрыть
-
+
+ Style
+ Стиль
+
+
+
Print
-
+ Печать
-
+
Print to file
-
+ В файл
-
- No name
-
+
+ Unnamed Model %1
+ Неизвестная модель %1
-
+
+ Click to remove this model.
+ Нажмите, чтобы убрать эту модель.
+
+
+
Print Document
-
+ Распечатать
-
+
Select PDF output file
-
+ PDF файл для сохранения
ConclusionPage
-
+
OK, I understand.
-
-
-
-
- ContributorsDialog
-
-
- OpenTX Contributors
-
-
-
-
- Main Developers
-
-
-
-
- Other contributors
-
-
-
-
- Companies and projects who have donated to OpenTX
-
-
-
-
- People who have donated to OpenTX
-
-
-
-
- Honors go to Rafal Tomczak (RadioClone), Thomas Husterer (th9x) and Erez Raviv (er9x and eePe)
-
-
-
-
- OpenTX Blacklist
-
-
-
-
- monthly
-
+ Хорошо, я понял.
CopyProcess
-
-
-
- Error
- Ошибка
-
-
-
+
Write error
-
+
Cannot write %1 (reason: %2)
-
+
Cannot open %1 (reason: %2)
+
+ CreditsDialog
+
+
+ OpenTX Contributors
+
+
+
+
+ Honors go to Rafal Tomczak (RadioClone), Thomas Husterer (th9x) and Erez Raviv (er9x and eePe)
+
+
+
+
+ OpenTX Blacklist
+
+
+
+
+ Main developers
+
+
+
+
+ Translators
+
+
+
+
+ Companies and projects who have donated to OpenTX
+
+
+
+
+ People who have donated to OpenTX
+
+
+
+
+ Other contributors
+
+
+
+
+ monthly
+
+
+
+
+ CurveData
+
+
+ CV
+
+
+
CurveGroup
-
+
Diff
-
+
Expo
-
+
Func
-
+
Curve
Кривая
+
+ CurveReference
+
+
+ Diff(%1)
+
+
+
+
+ Expo(%1)
+
+
+
+
+ Function(%1)
+
+
+
+
+ Curve(%1)
+
+
+
Curves
Fixed X
-
+ Фиксированный X
Custom X
-
+ Произвольный X
@@ -1168,356 +1413,933 @@ May be different from firmware language
-
+
Curve type
-
+ Тип кривой
Curve Creator
-
+ Параметры кривой
-
+
Y at X=0
-
+
+ Point size
+ Размер точки
+
+
+
Y at X=100
-
+
Both
-
+ Обе
-
+
x>0
-
+
x<0
-
+
Apply
-
+ Применить
-
+
Side
-
+ Сторона
-
+
Y at X=-100
-
+
Coefficient
-
+ Коэффициент
Curve name
+ Название кривой
+
+
+
+ Curve %1
+ Кривая %1
+
+
+
+ Popup menu available
-
- Curve %1
- Кривая %1
-
-
-
+
%1 points
-
+
Linear
-
+ Линейная
-
+
Single Expo
-
+ Экспонента
-
+
Symmetrical f(x)=-f(-x)
-
+ Симметричная f(x)=-f(-x)
-
+
Symmetrical f(x)=f(-x)
-
+ Симметричная f(x)=f(-x)
-
+
Copy
-
+ Копировать
-
+
Paste
-
+ Вставить
-
+
Clear
-
+ Очистить
-
+
Clear all curves
-
+ Удалить все кривые
-
+
Are you sure you want to reset curve %1?
-
+ Вы действительно хотите сбросить настройки Кривой %1?
-
+
Are you sure you want to reset all curves?
-
+ Вы действительно хотите удалить все кривые?
-
+
Editing curve %1
+ Редактирование кривой %1
+
+
+
+ Not enough free points in EEPROM to store the curve.
+
+
+
+
+ CustomFunctionData
+
+
+ GF
-
- Not enough free points in EEPROM to store the curve.
+
+ SF
+
+
+
+
+ Override %1
+
+
+
+
+ Trainer
+
+
+
+
+ Trainer RUD
+
+
+
+
+ Trainer ELE
+
+
+
+
+ Trainer THR
+
+
+
+
+ Trainer AIL
+
+
+
+
+ Instant Trim
+
+
+
+
+ Play Sound
+
+
+
+
+ Haptic
+
+
+
+
+ Reset
+
+
+
+
+ Set Timer %1
+
+
+
+
+ Vario
+
+
+
+
+ Play Track
+
+
+
+
+ Play Both
+
+
+
+
+ Play Value
+
+
+
+
+ Play Script
+
+
+
+
+ SD Logs
+
+
+
+
+ Volume
+
+
+
+
+ Backlight
+
+
+
+
+ Screenshot
+
+
+
+
+ Background Music
+
+
+
+
+ Background Music Pause
+
+
+
+
+ Adjust %1
+
+
+
+
+ SetFailsafe Int. Module
+
+
+
+
+ SetFailsafe Ext. Module
+
+
+
+
+ RangeCheck Int. Module
+
+
+
+
+ RangeCheck Ext. Module
+
+
+
+
+ Bind Int. Module
+
+
+
+
+ Bind Ext. Module
+
+
+
+
+ Timer1
+
+
+
+
+ Timer2
+
+
+
+
+ Timer3
+
+
+
+
+ Flight
+
+
+
+
+ Telemetry
+
+
+
+
+ Rotary Encoder
+
+
+
+
+ REa
+
+
+
+
+ REb
+
+
+
+
+ s
+
+
+
+
+
+
+ <font color=red><b>Inconsistent parameter</b></font>
+
+
+
+
+ Value
+
+
+
+
+ played once, not during startup
+
+
+
+
+ repeat(%1s)
+
+
+
+
+ DISABLED
+
+
+
+
+ CFN
CustomFunctionsPanel
-
+
Switch
Тумблер
-
+
Action
-
+
Parameters
-
+
Enable
+ Включить
+
+
+
+ Popup menu available
-
+
SF%1
-
+
GF%1
-
+
ON
-
- Error
- Ошибка
-
-
-
- Unable to find sound file %1!
+
+ Error occurred while trying to play sound, possibly the file is already opened. (Err: %1 [%2])
-
- &Delete
- Удалить
+
+ Unable to find or open sound file:
+%1
+
-
+
+ Copy
+
+
+
+
+ Cut
+
+
+
+
+ Paste
+
+
+
+
+ Clear
+
+
+
+
+ Insert
+
+
+
+
+ Move Up
+
+
+
+
+ Move Down
+
+
+
+
+ Clear All
+
+
+
+
+ Value
+ Значение
+
+
+
+ Source
+ Источник
+
+
+
+ GVAR
+
+
+
+
+ Increment
+
+
+
+
Delete
Удалить
+
+
+ CustomizeSplashDialog
-
- &Copy
- Копировать
-
-
-
- Ctrl+C
+
+ Transmitter Splash Screen Editor
-
- &Cut
- Вырезать
+
+
+ Invert
+ Инверт
-
- Ctrl+X
+
+
+ Load FW
-
- &Paste
- Вставить
+
+
+ Load Pict
+
-
- Ctrl+V
+
+
+ Load Profile
+
+
+
+
+
+ Save
+
+
+
+
+
+ Open Splash Library
+
+
+
+
+
+
+
+ ...
+ ...
+
+
+
+ FW: %1
+
+
+
+
+ Pict: %1
+
+
+
+
+ Profile image
+
+
+
+
+ Open Firmware File
+
+
+
+
+ Can not load embedded image from firmware file %1.
+
+
+
+
+ Open Image to load
+
+
+
+
+ Images (%1)
+ Изображения (%1)
+
+
+
+ Cannot load the image file %1.
+
+
+
+
+ Cannot load profile image %1.
+
+
+
+
+ Cannot load the library image %1.
+
+
+
+
+ File Saved
+
+
+
+
+ The image was saved to the file %1
+
+
+
+
+ Image Refresh Error
+
+
+
+
+ Failed to refresh image from file %1
+
+
+
+
+ File Save Error
+
+
+
+
+ Failed to write image to %1
CyclicPage
-
+
90
-
+ 15 сек. {90?}
-
+
120
-
+ 15 сек. {120?}
-
+
120x
+ 15 сек. {120x?}
+
+
+
+ 140
+ 15 сек. {140?}
+
+
+
+ DataField
+
+
+ Conversion error on field %1
-
- 140
+
+ Switch
+ Тумблер
+
+
+
+ Switch
+
+
+
+
+ cannot be exported on this board!
+
+
+
+
+ Source
+ Источник
+
+
+
+ Source %1 cannot be exported on this board!
+
+
+
+
+ OpenTX only accepts %1 points in all curves
+
+
+
+
+ OpenTx only accepts %1 points in all curves
+
+
+
+
+
+ OpenTX on this board doesn't accept this function
+
+
+
+
+ OpenTX doesn't accept this radio protocol
DebugOutput
-
+
Debug Output
+
+
+ <html><head/><body><p>Enable or disable the filter. If the button won't stay enabled, it is likely there is a syntax error in the Regular Expression entered.</p></body></html>
+
+
+
+
+ Filter:
+
+
+
+
+ <html><head/><body><p>Enter filter text here. Click the help/info button for details about using the filter. </p><p>
+To <b>remove a remembered entry</b> from the filter list, first choose it, and then press <code>Shift-Delete</code> (or <code>Shift-Backspace</code>) key combination.</p></body></html>
+
+
+
+
+ Buffer:
+
+
+
+
+ Number of lines to keep in display.
+
+
+
+
+ Filter &Help
+
+
+
+
+ Show information about using the filter.
+
+
+
+
+ Word &Wrap
+
+
+
+
+ Toggle word wrapping on/off.
+
+
+
+
+ &Clear
+
+
+
+
+ Clear the output window of all text.
+
+
+
+
+ Enable &Filter
+
+
+
+
+ Turn the filter on/off.
+
+
+
+
+ <html><head><style>kbd {background-color: palette(alternate-base); font-size: large; white-space: nowrap;}</style></head><body><p>The filter supports two syntax types: basic matching with common wildcards as well as full Perl-style (<code>pcre</code>) Regular Expressions.</p><p>By default a filter will only show lines which match (<b>inclusive</b>). To make an <b>exclusive</b> filter which removes matching lines, prefix the filter expression with a <kbd>!</kbd> (exclamation mark).</p><p>To use <b>Regular Expressions</b> (RegEx), prefix the filter text with a <kbd>/</kbd> (slash) or <kbd>^</kbd> (up caret). <ul><li>Put the <kbd>/</kbd> or <kbd>^</kbd> after the exclusive <kbd>!</kbd> indicator if you're using one.</li><li>By default the match is case-sensitive. To make it insensitive, add the typical <kbd>/i</kbd> (slash i) operator at the end of your RegEx.</li><li>If you use a caret (^) to denote a RegEx, it will become part of the Reg. Ex. (that is, matches from start of line).</li><li>If the RegEx is invalid, the filter edit field should show a red border and you will not be able to enable the filter.</li><li>A useful resource for testing REs (with a full reference) can be found at <a href="http://www.regexr.com/">http://www.regexr.com/</a></li></ul></p><p>To use <b>basic matching</b> just type any text.<ul><li>Wildcards: <kbd>*</kbd> (asterisk) matches zero or more of any character(s), and <kbd>?</kbd> (question mark) matches any single character.</li><li>The match is always case-insensitive.</li><li>The match always starts from the beginning of a log line. To ignore characters at the start, use a leading <kbd>*</kbd> wildcard.</li><li>A trailing <kbd>*</kbd> is always implied (that is, matches anything to the end of the log line). To avoid this, use a RegEx.</li><li>You can match literal wildcard characters by prefixing them with a <kbd>\</kbd> (backslash) character (eg. "foo\*bar" matches "foo*bar").</li></ul></p><p>After <b>editing text</b>, press ENTER or TAB key (or click anywhere outside the box) to update the filter.</p><p>To <b>remove an entry</b> from the filter selector list, first choose it, and while in the line editor press <kbd>Shift-Delete</kbd> (or <kbd>Shift-Backspace</kbd>) key combination. The default filters cannot be removed. Up to 50 filters are stored.</p></body></html>
+
+
+
+
+ Debug Console Filter Help
+
+
- EepromInterface
+ DownloadDialog
-
+
+ Downloading:
+
+
+
+
+ Unable to save the file %1: %2.
+
+
+
+
+ Download failed: %1.
+
+
+
+
+ EEPROMInterface
+
+
Possible causes for this:
-
+
- Eeprom is from a newer version of OpenTX
-
+
- Eeprom is not from OpenTX
-
+
- Eeprom is not from Th9X
-
+
- Eeprom is not from Gruvin9X
-
+
- Eeprom is not from ErSky9X
-
+
- Eeprom is not from Er9X
-
+
- Eeprom size is invalid
-
+
- Eeprom file system is invalid
-
+
- Eeprom is from a unknown board
-
+
- Eeprom is from the wrong board
-
+
- Eeprom backup not supported
-
+
- Something that couldn't be guessed, sorry
-
+
Warning:
-
-
+
+
- Your radio probably uses a wrong firmware,
eeprom size is 4096 but only the first 2048 are used
-
+
- Your eeprom is from an old version of OpenTX, upgrading!
- You should 'save as' to keep the old file as a backup.
+ To keep your original file as a backup, please choose File -> Save As specifying a different name.
+
+
+
+
+ EepeFormat
+
+
+ Unable to open %1: %2
-
- Warnings!
+
+ Invalid EEPROM file %1
ElevonsPage
-
+
<br>First Elevon Channel:
+ Первый канал элевонов:
+
+
+
+ Second Elevon Channel:
+ Второй канал элевонов:
+
+
+
+ ExpoData
+
+
+ INP
-
- Second Elevon Channel:
+
+ (@%1)
@@ -1526,7 +2348,7 @@ May be different from firmware language
Weight
- Вес
+ Вес
@@ -1538,42 +2360,42 @@ May be different from firmware language
Offset
- Смещен.
+ Смещение
The source for the mixer
- Источник для микшера
+
Input name
-
+ Название Входа
Flight modes
-
+ Полётные режимы
Switch
- Тумблер
+ Тумблер
Source
- Источник
+ Источник
Line name
-
+ Название строки
Stick Side
-
+ Сторона стика
@@ -1583,32 +2405,32 @@ May be different from firmware language
Include Trim
- Исп. трим
+ Использовать триммер
No
-
+ Нет
Yes
-
+ Да
Curve
- Кривая
+ Кривая
Curve applied to the source.
-
+ Кривая применяется к источнику.
NEG
-
+ МИНУС
@@ -1619,131 +2441,752 @@ May be different from firmware language
Switch used to enable the line.
If blank then the input is considered to be "ON" all the time.
-
+ Тумблер используется для активации линии.
+Если не указан, тогда Вход всегда активен.
POS
-
+ ПЛЮС
ALL
+ ОБЕ
+
+
+
+ Edit %1
+ Редактирование %1
+
+
+
+ Popup menu available
-
- Edit %1
+
+ Clear All
+
+
+
+
+ Set All
+
+
+
+
+ Invert All
+ Инвертировать всё
+
+
+
+ ExportableTableView
+
+
+ Select All
+
+
+
+
+ Copy selection as TAB-delimited text
+
+
+
+
+ Copy selection as cooma-delimited text (CSV)
+
+
+
+
+ Copy selection as pipe-delimited text
+
+
+
+
+ Copy selection as HTML
+
+
+
+
+ Save selection to file
+
+
+
+
+ Tab-delimited text
+
+
+
+
+ Comma-delimited text
+
+
+
+
+ Pipe-delimited text
+
+
+
+
+ HTML
+
+
+
+
+ Save to file
FblPage
-
+
Throttle Channel:
-
+
Yaw Channel:
-
+
Pitch Channel:
-
+
Roll Channel:
+
+ FileSyncDialog
+
+
+ Synchronize Files
+
+
+
+
+ Are you sure you wish to abort the sync?
+
+
+
+
+ Source Folder:
+
+
+
+
+ Destination Folder:
+
+
+
+
+ %1%2 Both directions, to destination folder first
+ %1%2 Оба направления, вначале в папку передатчика
+
+
+
+ %1%2 Both directions, to source folder first
+ %1%2 Оба направления, вначале в локальную папку
+
+
+
+ %1 Only from source folder to destination folder
+ %1 Только из локальной папки в папку передатчика
+
+
+
+ %1 Only from destination folder to source folder
+ %1 Только из папки передатчика в локальную папку
+
+
+
+ How to handle overwriting files which already exist in the destination folder.
+ Определяет, как обрабатывать файлы, которые уже существуют.
+
+
+
+ Copy only if newer and different (compare contents)
+ Копировать только если новее и отличается содержимое
+
+
+
+ Copy only if newer (do not compare contents)
+ Копировать только если новее (не сравнивать содержимое)
+
+
+
+ Copy only if different (ignore file time stamps)
+ Копировать только если разные (игнорировать дату файла)
+
+
+
+ Always copy (force overwite existing files)
+ Всегда копировать (перезаписывать существующие файлы)
+
+
+
+ Any size
+
+
+
+
+ Skip files larger than this size. Enter zero for unlimited.
+ Пропускать, если файл больше указанного размера. Поставьте 0, если ограничение не нужно.
+
+
+
+ Minimum reporting level. Events of this type and of higher importance are shown.
+WARNING: High log rates may make the user interface temporarily unresponsive.
+ Уровень журналирования синхронизации. Будут показываться событие выбранного и более высоких уровней.
+ПРЕДУПРЕЖДЕНИЕ: высокий уровень журналирования может временно заблокировать интерфейс.
+
+
+
+ Skipped
+ Пропущенные
+
+
+
+ Created
+ Новые
+
+
+
+ Updated
+ Обновленные
+
+
+
+ Errors Only
+ Только ошибки
+
+
+
+ Test-run only
+ Только тестирование
+
+
+
+ Run as normal but do not actually copy anything. Useful for verifying results before real sync.
+ Запускает обычную синхронизацию, только ничего не копирует. Полезно для проверки результатов перед реальной синхронизацией.
+
+
+
+ Log Level:
+ Журнал:
+
+
+
+ Filters:
+ Фильтры:
+
+
+
+ The "Include" filter will only copy files which match the pattern(s).
+The "Exclude" filter will skip files matching the filter pattern(s).
+The Include filter is evaluated first.
+ Фильтр "Включить" позволяет копировать файлы соответствующие шаблону(ам).
+Фильтр "Исключить" позволяет пропускать файлы соответствующие шаблону(ам).
+Вначале учитывается фильтр "Включить".
+
+
+
+ One or more file pattern(s) to exclude, separated by commas.
+Blank means exclude none. ?, *, and [...] wildcards accepted.
+ Один или несколько шаблонов, разделенных запятыми
+Пустое поле означает обработку всех файлов, допускаются маски ?, * и [...].
+
+
+
+ One or more file pattern(s) to include, separated by commas.
+Blank means include all. ?, *, and [...] wildcards accepted.
+ Один или несколько шаблонов, разделенных запятыми
+Пустое поле означает обработку всех файлов, допускаются маски ?, * и [...].
+
+
+
+ Include:
+ Включить:
+
+
+
+ Exclude:
+ Исключить:
+
+
+
+ Case sensitive
+ Чувствительный к регистру
+
+
+
+
+ Follow links
+ Учитывать ссылки
+
+
+
+ Include hidden
+ Учитывать скрытые
+
+
+
+ Recursive
+ Рекурсивно
+
+
+
+ Skip empty
+ Пропускать пустые
+
+
+
+ Apply filters
+ Применять фильтры
+
+
+
+ Filter Options:
+ Настройки фильтров:
+
+
+
+ Folder Options:
+ Параметры папок:
+
+
+
+
+ Options
+ Параметры
+
+
+
+ Show extra options
+ Показать дополнительные настройки
+
+
+
+ Reset to defaults
+ Использовать настройки по умолчанию
+
+
+
+ Close
+ Закрыть
+
+
+
+ Sync. Direction:
+ Направление синхронизации:
+
+
+
+ Existing Files:
+ Существующие файлы:
+
+
+
+ Max. File Size:
+ Макс. размер файла:
+
+
+
+ MB
+
+
+
+
+ KB
+
+
+
+
+ Abort
+ Остановить
+
+
+
+ Start
+ Начать
+
+
+
+ Total: <b>%1</b>; Created: <b>%2</b>; Updated: <b>%3</b>; Skipped: <b>%4</b>; Errors: <font color=%6><b>%5</b></font>;
+ Итого: <b>%1</b>; Создано: <b>%2</b>; Обновлено: <b>%3</b>; Пропущено: <b>%4</b>; Ошибки: <font color=%6><b>%5</b></font>;
+
+
+
+ Current: <b>%1</b> of
+ Обработано: <b>%1</b> Всего.
+
+
+
+ Source folder not found.
+ Локальная папка (источник) не найдена.
+
+
+
+ Destination folder not found.
+ Папка назначения (в передатчике) не найдена.
+
+
+
+ Source and destination folders are the same.
+ Выберите разные папки.
+
+
+
+ Firmware
+
+
+ Possibility to enable FAI MODE (no telemetry) at field
+
+
+
+
+ FAI MODE (no telemetry) always enabled
+
+
+
+
+ Channel values displayed in us
+
+
+
+
+ No OverrideCH functions available
+
+
+
+
+ Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015
+
+
+
+
+ Enable non certified firmwares
+
+
+
+
+ Use alternative SQT5 font
+
+
+
+
+
+ Disable HELI menu and cyclic mix support
+
+
+
+
+
+ Disable Global variables
+
+
+
+
+
+ Enable Lua custom scripts screen
+
+
+
+
+ Support for PPM internal module hack
+
+
+
+
+ Enable HELI menu and cyclic mix support
+
+
+
+
+ Global variables
+
+
+
+
+ Pots use in menus navigation
+
+
+
+
+ In model setup menus automatically set source by moving the control
+
+
+
+
+ In model setup menus automatically set switch by moving the control
+
+
+
+
+ No graphical check boxes and sliders
+
+
+
+
+ Battery graph
+
+
+
+
+ Don't use bold font for highlighting active items
+
+
+
+
+ Enable resetting values by pressing up and down at the same time
+
+
+
+
+ FrSky Taranis X9D+
+
+
+
+
+ Disable RAS (SWR)
+
+
+
+
+ FrSky Taranis X9D+ 2019
+
+
+
+
+ FrSky Taranis X9D
+
+
+
+
+ Haptic module installed
+
+
+
+
+ FrSky Taranis X9E
+
+
+
+
+ Confirmation before radio shutdown
+
+
+
+
+ Horus gimbals installed (Hall sensors)
+
+
+
+
+ FrSky Taranis X9-Lite
+
+
+
+
+ FrSky Taranis X9-Lite S
+
+
+
+
+ FrSky Taranis X7 / X7S
+
+
+
+
+ FrSky Taranis X-Lite S/PRO
+
+
+
+
+ FrSky Taranis X-Lite
+
+
+
+
+ FrSky Horus X10 / X10S
+
+
+
+
+
+ Support for ACCESS internal module replacement
+
+
+
+
+ FrSky Horus X10 Express / X10S Express
+
+
+
+
+ FrSky Horus X12S
+
+
+
+
+ Use ONLY with first DEV pcb version
+
+
+
+
+ Jumper T12 / T12 Pro
+
+
+
+
+ Enable non certified R9M firmwares
+
+
+
+
+
+ Support for MULTI internal module
+
+
+
+
+ Jumper T16 / T16+ / T16 Pro
+
+
+
+
+ Support for bluetooth module
+
+
+
+
+ Turnigy 9XR-PRO
+
+
+
+
+ 9X with AR9X board
+
+
+
+
+ 9X with Sky9x board
+
+
+
+
+ Turnigy 9XR
+
+
+
+
+ Turnigy 9XR with m128 chip
+
+
+
+
+ 9X with stock board
+
+
+
+
+ 9X with stock board and m128 chip
+
+
+
+
+ 9X with Gruvin9x board
+
+
+
+
+ DIY MEGA2560 radio
+
+
+
FirmwarePreferencesDialog
Downloads
-
+ Загрузки
-
+
Check for updates
-
+ Проверить наличие обновлений
-
- Voice
-
-
-
-
- Set voice language.
-May be different from firmware language
-
-
-
-
- Download Voice
-
-
-
-
- Download FW
-
-
-
-
+
Firmware
-
+ Прошивка
-
+
+ Download firmware
+ Скачать прошивку
+
+
+
+ Download SD contents
+ Скачать содержимое SD
+
+
+
Latest Download
-
+ Загруженная версия:
+
+
+
+ Unknown
+ неизвестная
FlapsPage
-
+
No
-
+ Нет
-
+
Yes, controlled by a single channel
-
+ Да, управляются одним каналом
-
+
Yes, controlled by two channels
-
+ Да, управляются двумя каналами
-
+
<br>First Flap Channel:
-
+ <br>Первый канал закрылков:
-
+
Second Flap Channel:
-
+ Второй канал закрылков:
FlashEEpromDialog
-
+
Write Models and Settings to Radio
-
+ Записать настройки и модели в передатчик
Load...
-
+ Выбрать...
@@ -1752,19 +3195,23 @@ May be different from firmware language
-
Allows Companion to write to older version of the firmware
Check Firmware compatibility
+ Проверить совместимость с передатчиком
+
+
+
+ <html><head/><body><p>Saves a dated copy of your eeprom to the backup folder you specified in the Companion settings before writing the current model to the radio.</p></body></html>
Backup before Write
-
+ Сделать резервную копию
@@ -1789,114 +3236,59 @@ May be different from firmware language
Cancel
-
+ Отмена
Write to TX
-
+ Записать
-
+
Current profile: %1
-
+
Choose Radio Backup file
-
+ Выберите файл с резервной копией
-
-
-
-
-
-
-
-
-
-
-
- Error
- Ошибка
-
-
-
- Unable to find file %1!
- Невозможно найти файл %1!
-
-
-
-
-
- Error opening file %1:
-%2.
-
-
-
-
-
- Invalid Models and Settings File %1
-
-
-
-
- Error reading file %1:
-%2.
- Ошибка при считывании файла %1:
-%2.
-
-
-
- Invalid Models and Settings file %1
-
-
-
-
-
-
-
- Warning
- Звук
-
-
-
+
Wrong radio calibration data in profile, Settings not patched
-
+
Wrong radio setting data in profile, Settings not patched
-
-
+
Cannot write file %1:
%2.
- Не удается записать файл %1:
+ Не удается записать файл %1:
%2.
-
+
Error writing file %1:
%2.
- Ошибка при записи файла %1:
+ Ошибка при записи файла %1:
%2.
-
+
The radio firmware belongs to another product family, check file and preferences!
-
+
The radio firmware is outdated, please upgrade!
-
+
Cannot check Models and Settings compatibility! Continue anyway?
@@ -1906,47 +3298,47 @@ May be different from firmware language
Flash Firmware
-
+ Обновление прошивки
Load...
-
+ Выбрать...
Date & Time
-
+ Дата
Variant
-
+ Сборка
Version
-
+ Версия
Use profile start screen
-
+ Заставка из профиля
Use firmware start screen
-
+ Заставка из прошивки
Use library start screen
-
+ Заставка из библиотеки
Use another start screen
-
+ Другая заставка
@@ -1956,228 +3348,205 @@ May be different from firmware language
Check Hardware compatibility
-
+ Проверить совместимость с передатчиком
Backup and restore Models and Settings
-
+ Сделать резервную копию настроек и моделей
Cancel
-
+ Отмена
Write to TX
-
+ Записать
-
+
Open Firmware File
-
+ Выбрать файл с прошивкой
-
-
-
- Warning
- Звук
-
-
-
+
%1 may not be a valid firmware file
-
+ %1 - не прошивка
-
-
-
-
- Error
- Ошибка
-
-
-
The firmware file is not valid.
-
+ Битый файл с прошивкой.
-
+
There is no start screen image in the firmware file.
-
+
Profile image %1 is invalid.
-
+
Open image file to use as radio start screen
-
+ Выбрать картинку для заставки
-
+
Images (%1)
-
+ Изображения (%1)
-
+
Image could not be loaded from %1
-
+
The library image could not be loaded
-
+
Splash image not found
-
+ Файл с заставкой не найден
-
+
Cannot save customized firmware
-
+
Write Firmware to Radio
-
+ Записать прошивку в передатчик
-
-
+
+
Firmware check failed
-
+ Не удалось проверить прошивку
-
+
Could not check firmware from radio
-
+ Не удалось проверить прошивку передатчика
-
+
New firmware is not compatible with the one currently installed!
-
+
Conversion failed
-
+
Cannot convert Models and Settings for use with this firmware, original data will be used
-
+ Невозможно сконвертировать модели и настройки для этой прошивки, будут использованы оригинальные данные
-
+
Restore failed
-
+
Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1
-
+
Flashing done
-
+ Обновление завершено
FlashProcess
-
+
Executable %1 not found
-
+
Writing...
-
+
Reading...
-
+
Verifying...
-
+
unknown
-
+
ie: OpenTX for 9X board or OpenTX for 9XR board
-
+
ie: OpenTX for M128 / 9X board or OpenTX for 9XR board with M128 chip
-
+
ie: OpenTX for Gruvin9X board
-
+
Your radio uses a %1 CPU!!!
Please check advanced burn options to set the correct cpu type.
-
+
Your radio uses a %1 CPU!!!
Please select an appropriate firmware type to program it.
-
+
You are currently using:
%1
-
- Your radio does not seem connected to USB or the driver is not installed!!!
-
-Please use ZADIG to properly install the driver.
-
-
-
-
+
Your radio does not seem connected to USB or the driver is not initialized!!!.
-
+
Flashing done (exit code = %1)
-
+
Flashing done with errors
-
+
FUSES: Low=%1 High=%2 Ext=%3
@@ -2187,38 +3556,133 @@ Please use ZADIG to properly install the driver.
Fade In
-
+ Переход к режиму
Fade Out
-
+ Выход из режима
Name
-
+ Название
Switch
- Тумблер
+ Тумблер
+
+
+
+ FlightModeData
+
+
+ FM
+
FlightModePanel
+
+
+ Popup menu available
+
+
+
+
+ Trim disabled
+ Триммер отключен
+
+ Own Trim
+ Свой триммер
+
+
+
+ Use Trim from Flight mode %1
+ Использовать триммер Полётного режима %1
+
+
+
+ Use Trim from Flight mode %1 + Own Trim as an offset
+ Использовать триммер Полётного режима %1 + 'Свой триммер' как смещение
+
+
+
Rotary Encoder %1
-
+
+ Name
+ Название
+
+
+
+ Value source
+ Источник значений
+
+
+
+ Value
+ Значение
+
+
+
+ Unit
+ Ед.
+
+
+
+ Prec
+ Точность
+
+
+
+ Min
+ Мин
+
+
+
+ Max
+ Макс
+
+
+
GVAR%1
-
+
+ 0._
+
+
+
+
+ 0.0
+
+
+
+
+
+ &Clear
+
+
+
+
+
+ Clear
+
+
+
+
+ Clear all current Flight Mode properties?
+
+
+
+
Popup enabled
@@ -2226,39 +3690,71 @@ Please use ZADIG to properly install the driver.
FlightModesPanel
-
+
Flight Mode %1
-
+ Полётный режим %1
-
+
(%1)
-
+ (%1)
-
+
(default)
-
+ (по умолчанию)
FlybarSelectionPage
-
+
Has Flybar
-
+
Flybarless
-
+
Flybar:
+
+ FrSkyAlarmData
+
+
+ Yellow
+ Желтая
+
+
+
+ Orange
+ Оранжевая
+
+
+
+ Red
+ Красная
+
+
+
+ FrSkyChannelData
+
+
+
+ V
+
+
+
+
+ ---
+
+
+
FusesDialog
@@ -2351,23 +3847,66 @@ p, li { white-space: pre-wrap; }
-
-
+
+
Reset Radio Fuses
-
+
Read Fuses from Radio
+
+ GVarData
+
+
+ %
+
+
+
+
+ ?
+
+
+
+
+ 0._
+
+
+
+
+ 0.0
+ 15 сек. {0.0?}
+
+
+
+ ?.?
+
+
+
+
+ GV
+
+
+
+
+ Own value
+
+
+
+
+ Flight mode %1 value
+
+
+
GeneralEdit
- General Edit
- Основная настройка
+ Radio settings
+ Параметры передатчика
@@ -2377,14 +3916,14 @@ These will be relevant for all models in the same EEPROM.
Это относится ко всем моделям сохраненным в EEPROM.
-
+
Setup
Настройка
-
+
Trainer
-
+ Тренер
@@ -2397,40 +3936,52 @@ These will be relevant for all models in the same EEPROM.
-
+
Global Functions
-
+ Глобальные функции
-
- Hardware / Calibration
-
+
+ Hardware
+ Оборудование
-
-
- Warning
- Звук
+
+ Calibration
+ Калибровка
-
+
Wrong data in profile, radio calibration was not retrieved
-
+
+ Wrong data in profile, Switch/pot config not retrieved
+
+
+
+
Wrong data in profile, hw related parameters were not retrieved
-
+
Do you want to store calibration in %1 profile<br>overwriting existing calibration?
-
+
Calibration and HW parameters saved.
-
+ Параметры оборудования и калибровки сохранены.
+
+
+
+ GeneralSettings
+
+
+ Radio Settings
+ Параметры передатчика
@@ -2486,209 +4037,229 @@ These will be relevant for all models in the same EEPROM.
-
+
Timeshift from UTC
-
+ Смещение от UTC
-
+
Voice Language
-
+ Язык для голоса
-
+
Country Code
-
+ Регион
-
+
Stick reverse
-
+ Реверс стиков
-
+
FAI Mode
-
+ Режим FAI
-
-
- If you enable FAI, you loose the vario, the play functions, the telemetry screen. This function cannot be disabled by the radio.
-
-
-
-
+
Adjust RTC
-
+ Коррекция часов
-
+
Vario pitch at max
-
+ Макс. тон вариометра
-
-
+
+
Hz
-
+ Гц
-
+
Speaker Volume
-
+ Громкость динамика
-
+
Backlight Switch
-
+ Включение подсветки
-
+
Sound Mode
-
+ Режим звука
-
+
Color 1
-
+ Цвет 1
-
+
Color 2
-
+ Цвет 2
-
+
Speaker Pitch (spkr only)
-
+ Тон динамика
-
+
If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds.
- Если не равно нулю, то любое нажатие кнопок будет включать подсветку и выключать ее через указанное кол-во секунд.
+ Если не равно нулю, то любое нажатие кнопок будет включать подсветку и выключать её через указанное кол-во секунд.
-
+
+
+
sec
- сек
+ сек
-
+
Backlight color
-
+ Цвет фона
-
+
Beeper
-
+
-
+
Speaker
-
+ Динамик
-
+
BeeperVoice
-
+
SpeakerVoice
-
-
- Beep volume
-
-
-
-
- Wav volume
-
-
-
-
- Vario volume
-
-
+ Beep volume
+ Громкость писка
+
+
+
+ Wav volume
+ Громкость Wav
+
+
+
+ Vario volume
+ Громкость варио
+
+
+
Background volume
-
+ Громкость фон. музыки
-
-
+
+
ms
-
+ мс
-
+
Backlight Auto OFF after
-
+ Отключать подсветку через
-
+
Backlight flash on alarm
-
+ Мигать подсветкой при увед.
-
+
Vario pitch at zero
-
+ Мин. тон вариометра
-
+
Vario repeat at zero
-
+ Повтор если вариометр 0
-
+
This is the switch selectrion for turning on the backlight (if installed).
- Включение подсветки (при ее наличии).
+ Включение подсветки (при ее наличии).
-
-
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html>
- Контраст LCD дисплея
-Значения в пределах 20-45
+
-
+
Backlight Brightness
-
+ Яркость фона
-
+
RotEnc Navigation
-
+ Навигация крутилкой
-
+
+ Backlight OFF Brightness
+ Яркость отключенной подсветки
+
+
+
America
-
+ Америка
-
+
Japan
-
+ Япония
-
+
Europe
+ Европа
+
+
+
+ If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio.
+ Если включить режим FAI, то будут работать только датчики RSSI и напряжения. Эту функцию нельзя отключить в передатчике.
+
+
+
+ Automatically adjust the radio's clock if a GPS is connected to telemetry.
-
+
+ Owner Registration ID
+
+
+
+
+ aaaaaaAA
+
+
+
+
Mode selection:
Mode 1:
@@ -2711,389 +4282,431 @@ Mode 4:
-
+
Mode 1 (RUD ELE THR AIL)
-
+
Mode 2 (RUD THR ELE AIL)
-
+
Mode 3 (AIL ELE THR RUD)
-
+
Mode 4 (AIL THR ELE RUD)
-
+
<html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html>
-
+ <html><head/><body><p>Порядок каналов</p><p><br/></p><p>Задает порядок микшеров при создании новой модели.</p></body></html>
-
+
R E T A
-
+
R E A T
-
+
R T E A
-
+
R T A E
-
+
R A E T
-
+
R A T E
-
+
E R T A
-
+
E R A T
-
+
E T R A
-
+
E T A R
-
+
E A R T
-
+
E A T R
-
+
T R E A
-
+
T R A E
-
+
T E R A
-
+
T E A R
-
+
T A R E
-
+
T A E R
-
+
A R E T
-
+
A R T E
-
+
A E R T
-
+
A E T R
-
+
A T R E
-
+
A T E R
-
+
+ Power On Delay
+ Пауза при включении
+
+
+
+ Jack Mode
+ Режим разъема наушников
+
+
+
+
+ Ask on Connect
+ Спросить при подключении
+
+
+
+ Audio
+ Звук
+
+
+
+ Trainer
+ Тренер
+
+
+
+ DMS
+
+
+
+
+ Low EEPROM Warning
+ Предупреждать, если мало памяти (EEPROM)
+
+
+
+ RSSI Poweroff Warning
+ Предупреждать, если есть сигнал RSSI
+
+
+
Stick Mode
- Режим стиков
+ Режим стиков
-
+
+ Power Off Delay
+ Пауза при выключении
+
+
+
Metric
-
+ Метрическая (метры)
-
+
Imperial
-
+ Имперская (мили, футы)
-
+
Default Channel Order
- Порядок следов. каналов
+ Порядок следов. каналов
-
+
GPS Coordinates
-
+ GPS координаты
-
+
Min
- Мин
+ Мин
-
-
+
+
v
- В
+ В
-
+
Max
- Макс
+ Макс
-
- Low Memory Warning
-
-
-
-
+
Inactivity Timer
- Таймер активности
+ Таймер активности
-
+
Show Splash Screen on Startup
- Показывать заставку
+ Показывать заставку при включении
-
+
Contrast
- Конраст
+ Конраст
-
+
Battery Meter Range
-
+ Напряжение аккумулятора
-
+
Haptic Strength
-
+ Сила вибрации
-
+
LCD Display Type
-
+ Тип LCD экрана
-
+
"No Sound" Warning
-
+ Предупреждать, если отключен звук
-
+
Battery Warning
- Напряж. при разряде
+ Напряж. при разряде
-
+
Haptic Length
-
+ Продолжительность вибрации
-
+
MAVLink Baud Rate
-
+ Скорость MAVLink
-
-
+
+
Quiet
- тихо
+ Тихо
-
+
Only Alarms
-
+ Только предупреждения
-
-
+
+
No Keys
- без кнопок
+ Все, кроме кнопок
-
-
+
+
All
-
+ Все
-
+
Battery warning voltage.
This is the threashhold where the battery warning sounds.
Acceptable values are 5v..10v
- Предупреждение о разряде.
+ Предупреждение о разряде аккумулятора.
Значение при котором сработает сигнализация.
Диапазон 5В..10В
-
+
Standard
-
+ Стандартный
-
+
Optrex
-
+ Optrex
-
+
If not zero will sound beeps if the transmitter has been left without inputs for the specified number of minutes.
- Если не равно нулю, начнет бипать при отсутсвии активности через указанное кол-во минут.
+ Если не равно нулю, то передатчик начнет пищать при отсутсвии активности через указанное кол-во минут.
-
+
min
- мин
+ мин
-
-
+
+
Show splash screen on startup
- Показывать заставку при включении
+ Показывать заставку при включении
-
+
---
-
+
2s
-
+ 2 сек.
-
+
3s
-
+ 3 сек.
-
+
4s
-
+ 4 сек.
-
+
6s
-
+ 6 сек.
-
+
8s
-
+ 8 сек.
-
+
10s
-
+ 10 сек.
-
+
15s
-
+ 15 сек.
-
+
4800 Baud
-
+ 4800
-
+
9600 Baud
-
+ 9600
-
+
14400 Baud
-
+ 14400
-
+
19200 Baud
-
+ 19200
-
+
38400 Baud
-
+ 38400
-
+
57600 Baud
-
+ 57600
-
+
76800 Baud
-
+ 76800
-
+
115200 Baud
-
+ 115200
-
-
+
+
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
@@ -3112,72 +4725,87 @@ p, li { white-space: pre-wrap; }
"Тишина" - Предупреждение о "тихом" режиме (без звука)
-
-
+
+
X-Short
-
+ Очень кратко
-
-
+
+
Short
-
+ Кратко
-
-
+
+
Normal
- нормально
+ Нормальная
-
-
+
+
Long
- долго
+ Долго
-
-
+
+
X-Long
-
-
-
-
- hh° (N/S) mm' ss''.dd
-
+ Очень долго
-
+
NMEA
-
+
Play Delay (switch mid position)
-
+ Пауза воспр. (тумблер в сред. полож.)
-
+
+ USB Mode
+ Режим работы USB порта
+
+
+
+ Joystick (HID)
+ Джойстик
+
+
+
+ USB Mass Storage
+ Съемный диск
+
+
+
+ USB Serial (CDC)
+ Последовательный порт
+
+
+
Measurement Units
-
+ Система мер
-
+
Haptic Mode
-
+ Режим вибрации
-
+
Beeper Length
-
+ Продолжительность писка
-
+
Beeper Mode
- Режим бипов
+ Уведомления (писк)
-
+
Beeper volume
0 - Quiet. No beeps at all.
@@ -3185,25 +4813,145 @@ p, li { white-space: pre-wrap; }
2 - Normal.
3 - Loud.
4 - Extra loud.
- Громкость.
+ Громкость.
-0 - Тишина.
-1 - Без кнопок.
+0 - Тишина. Никаких звуков.
+1 - Без кнопок. Обычный писк на уведомления, но кнопки не пищат
2 - Обычная.
3 - Громкая.
4 - Очень громкая.
-
+
Alarms Only
-
+ Только предупреждения
GeneralSetupPanel
-
- If you enable FAI, you loose the vario, the play functions, the telemetry screen.
+
+ OFF
+ Всегда выключена
+
+
+
+ Keys
+ Кнопки
+
+
+
+ Sticks
+ Стики
+
+
+
+ Keys + Sticks
+ Кнопки + Стики
+
+
+
+ ON
+ Всегда включена
+
+
+
+ English
+
+
+
+
+ Dutch
+
+
+
+
+ French
+
+
+
+
+ Italian
+
+
+
+
+ German
+
+
+
+
+ Czech
+
+
+
+
+ Slovak
+
+
+
+
+ Spanish
+
+
+
+
+ Polish
+
+
+
+
+ Portuguese
+
+
+
+
+ Russian
+
+
+
+
+ Swedish
+
+
+
+
+ Hungarian
+
+
+
+
+ No
+ Нет
+
+
+
+ RotEnc A
+
+
+
+
+ Rot Enc B
+
+
+
+
+ Rot Enc C
+
+
+
+
+ Rot Enc D
+
+
+
+
+ Rot Enc E
+
+
+
+
+ If you enable FAI, only RSSI and RxBt sensors will keep working.
This function cannot be disabled by the radio.
Are you sure ?
@@ -3212,18 +4960,366 @@ Are you sure ?
GyroPage
-
+
No
-
+ Нет
-
+
Yes, controled by a switch
+ Да, управляется тумблером
+
+
+
+ Yes, controlled by a pot
+ Да, управляется крутилкой
+
+
+
+ Hardware
+
+
+ Form
-
- Yes, controlled by a pot
+
+ SM
+
+
+
+
+ SC
+
+
+
+
+ Device Name:
+
+
+
+
+ SR
+
+
+
+
+ S4
+
+
+
+
+ RS2
+
+
+
+
+ Bluetooth
+
+
+
+
+ Current Offset
+
+
+
+
+ PPM 2
+
+
+
+
+ SD
+
+
+
+
+ SJ
+
+
+
+
+ SA
+
+
+
+
+ S1
+
+
+
+
+ S3
+
+
+
+
+ SP
+
+
+
+
+ SF
+
+
+
+
+ LS
+
+
+
+
+ Battery Offset
+
+
+
+
+ Serial Port
+
+
+
+
+ SG
+
+
+
+
+ S2
+
+
+
+
+ Ele
+
+
+
+
+ SI
+
+
+
+
+ SL
+
+
+
+
+ SQ
+
+
+
+
+ SO
+
+
+
+
+ PPM 1
+
+
+
+
+ PPM 4
+
+
+
+
+ SB
+
+
+
+
+ v
+
+
+
+
+ PPM Multiplier
+
+
+
+
+ Rud
+
+
+
+
+ ADC Filter
+
+
+
+
+ S5
+
+
+
+
+ Antenna
+
+
+
+
+ PPM 3
+
+
+
+
+ Ail
+
+
+
+
+ SK
+
+
+
+
+ SE
+
+
+
+
+ LS2
+
+
+
+
+ Thr
+
+
+
+
+ SH
+
+
+
+
+ OFF
+
+
+
+
+ S-Port Mirror
+
+
+
+
+ Telemetry
+
+
+
+
+ SBUS Trainer
+
+
+
+
+ Debug
+
+
+
+
+ RS
+
+
+
+
+ SN
+
+
+
+
+ RTC Batt Check
+
+
+
+
+ HardwarePanel
+
+
+
+
+ None
+
+
+
+
+ 2 Positions Toggle
+
+
+
+
+ 2 Positions
+
+
+
+
+ 3 Positions
+
+
+
+
+ Pot with detent
+
+
+
+
+ Multipos switch
+
+
+
+
+ Pot without detent
+
+
+
+
+ Slider with detent
+
+
+
+
+ OFF
+ ВЫКЛ
+
+
+
+ Enabled
+
+
+
+
+ Telemetry
+
+
+
+
+ Trainer
+
+
+
+
+ Internal
+
+
+
+
+ Ask
+
+
+
+
+ Per model
+
+
+
+
+ Internal + External
+
+
+
+
+ External
@@ -3247,7 +5343,7 @@ Are you sure ?
Invert
- Инверт
+
@@ -3303,236 +5399,385 @@ Are you sure ?
HeliPage
-
+
Throttle Channel:
-
+
Yaw Channel:
-
+
Pitch Channel:
-
+
Roll Channel:
- InputsPanel
+ HexEepromFormat
-
-
- Move Up
+
+ Invalid EEPROM File %1
-
-
+
+ Cannot open file %1:
+%2.
+
+
+
+
+ Error writing file %1:
+%2.
+ Ошибка при записи файла %1:
+%2.
+
+
+
+ InputsPanel
+
+
+
+ Move Up
+ Сдвинуть вверх
+
+
+
+
Ctrl+Up
-
-
+
+
Move Down
-
+ Сдвинуть вниз
-
-
+
+
Ctrl+Down
-
+
Clear All Inputs
-
+ Очистить все Входы
-
+
Not enough available inputs!
-
+
Delete Selected Inputs?
-
+ Удалить выбранные Входы?
-
+
&Add
- Добавить
+ Добавить
-
+
Ctrl+A
-
+
&Edit
- Правка
+ Редактировать
-
+
Enter
- Ввод
+
-
+
&Delete
- Удалить
+ Удалить
-
+
Delete
- Удалить
+
-
+
&Copy
- Копировать
+ Копировать
-
+
Ctrl+C
-
+
&Cut
- Вырезать
+ Вырезать
-
+
Ctrl+X
-
+
&Paste
- Вставить
+ Вставить
-
+
Ctrl+V
-
+
Du&plicate
-
+ Сделать копию
-
+
Ctrl+U
-
+
Clear Inputs?
+ Очистить Входы?
+
+
+
+ Really clear all the inputs?
+ Точно удалить все Входы?
+
+
+
+ LimitData
+
+
+ INV
-
- Really clear all the inputs?
+
+ NOR
+
+
+
+
+ CH
+
+
+
+
+ LimitsGroup
+
+
+ GV
+
+
+
+
+ LogicalSwitchData
+
+
+ ---
+
+
+
+
+ a>x
+
+
+
+
+ a<x
+
+
+
+
+ |a|>x
+
+
+
+
+ |a|<x
+
+
+
+
+ AND
+
+
+
+
+ OR
+
+
+
+
+ XOR
+
+
+
+
+ a=b
+
+
+
+
+ a!=b
+
+
+
+
+ a>b
+
+
+
+
+ a<b
+
+
+
+
+ a>=b
+
+
+
+
+ a<=b
+
+
+
+
+ d>=x
+
+
+
+
+ |d|>=x
+
+
+
+
+ a=x
+
+
+
+
+ a~x
+
+
+
+
+ Timer
+
+
+
+
+ Sticky
+
+
+
+
+ Edge
+
+
+
+
+ Unknown
+
+
+
+
+ L
+
+
+
+
+ LSW
LogicalSwitchesPanel
-
+
V1
-
+
V2
-
+
Duration
-
+
Delay
Задержка
-
+
+ Popup menu available
+
+
+
+
+ (instant)
+
+
+
+
+ (infinite)
+
+
+
+
Function
Функция
-
+
AND Switch
-
- L%1
-
-
-
-
+
&Delete
Удалить
-
- Delete
- Удалить
-
-
-
+
&Copy
Копировать
-
-
- (no release)
-
-
-
-
- (infinite)
-
-
-
-
- Ctrl+C
-
-
-
-
+
&Cut
Вырезать
-
- Ctrl+X
-
-
-
-
+
&Paste
Вставить
-
-
- Ctrl+V
-
-
LogsDialog
@@ -3542,146 +5787,166 @@ Are you sure ?
-
+
Filename
-
+
Open LogFile
-
+
Zoom
-
+
+ Save session CSV
+
+
+
+
X
-
+
Y
-
+
Reset
-
+
Fly sessions
-
+
Telemetry logs
-
+
Time (hh:mm:ss)
-
+
Plot Title Change
-
+
New plot title:
-
+
Axis Label Change
-
+
New axis label:
-
+
Graph Name Change
-
+
New graph name:
-
- Error: no GPS data not found
-
-
-
-
+
The column containing GPS coordinates must be named "GPS".
The columns for altitude "GAlt" and for speed "GSpd" are optional
-
- Error
- Ошибка
+
+ Error: no GPS data found
+
-
+
Cannot write file %1:
%2.
Не удается записать файл %1:
%2.
-
+
+ Cursor A: %1 m
+
+
+
+
+ Cursor B: %1 m
+
+
+
+
+ Time delta: %1
+
+
+
+
+ Climb rate: %1 m/s
+
+
+
+
Select your log file
-
+
Available fields
-
+
The selected logfile contains %1 invalid lines out of %2 total lines
-
+
total duration
-
+
duration
-
+
(L1)
-
+
(R1)
-
+
(L2)
-
+
(R2)
@@ -3689,119 +5954,81 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
MainWindow
-
-
-
-
+
+
File loaded
Файл загружен
-
-
-
+
+
Save As
- Сохранить как...
+ Сохранить как
-
-
+
+
No updates available at this time.
-
- Unable to check for updates.
-
-
-
-
+
Executable (*.exe)
-
+
+
Would you like to launch the installer?
-
-
+
+
File saved
Файл записан
-
- Display previous warning again at startup ?
-
-
-
-
+
New release available
-
-
- Error
- Ошибка
-
-
-
+
Error opening file %1:
%2.
-
- Compilation server termporary failure, try later
-
-
-
-
+
Compilation server too busy, try later
-
-
- Unknown server failure, try later
-
-
-
-
- Firmware %1 does not seem to have ever been downloaded.
-Release %2 is available.
-Do you want to download it now?
-
-We recommend you view the release notes using the button below to learn about any changes that may be important to you.
-
-
-
-
-
- Yes
-
-
-
-
-
- No
-
-
-
-
-
- Release Notes
-
-
-
- Do you want to download release %1 now ?
-
+ Unknown server failure, try later
+ Неизвестная ошибка, попробуйте позже
-
+
+
+ Yes
+ Да
+
+
+
+
+ No
+ Нет
+
+
+
+
+ Release Notes
+ Информация
+
+
+
A new version of %1 firmware is available:
- current is %2
- newer is %3
@@ -3812,725 +6039,887 @@ We recommend you view the release notes using the button below to learn about an
-
- The selected language will be used the next time you start Companion.
-
-
-
-
+
The new theme will be loaded the next time you start Companion.
-
- The icon size will be used the next time you start Companion.
-
-
-
-
-
+
+
Synchronize SD
-
+ Синхронизация содержимого SD
-
- Firmware updates
-
-
-
-
- Current firmware does not provide release notes informations.
-
-
-
-
+
OpenTX Home Page: <a href='%1'>%1</a>
-
+
If you've found this program useful, please support by <a href='%1'>donating</a>
-
+
New
-
+ Новый
-
+
Open...
-
+ Открыть...
-
+
Save
-
+ Сохранить
-
+
Save As...
-
+ Сохранить как...
-
- Copy Model
-
-
-
-
- Paste Model
-
-
-
-
- Load backup from file
-
-
-
-
+
Compare models
-
+ Сравнить модели
-
+
Exit the application
Выйти из программы
-
+
List available programmers
Показать список программаторов
-
+
Show fuses dialog
Показать диалог установки фьюзов
-
+
Show the application's About box
Показать окно "О программе"
-
+
Set Menu Language
-
+ Язык меню
-
- Show the list of radio profiles
-
-
-
-
+
Write
-
+
+ Use default system language.
+ Использовать язык системы.
+
+
+
+ Use %1 language (some translations may not be complete).
+
+
+
+
%2
-
+
+ Alt+%1
+
+
+
+
New Radio
-
+
Checking for updates
-
+
A new version of Companion is available (version %1)<br>Would you like to download it?
-
- A new release of Companion is available, please check the OpenTX website!
-
-
-
-
- Not enough memory for all the selected firmware options
-
-
-
-
- Compilation server requires registration, please check OpenTX web site
-
-
-
-
+
About Companion
-
+ О программе OpenTX Companion
-
+
A monochrome black icon theme
-
+ Монохромная черная тема
-
+
A monochrome white icon theme
-
+ Монохромная белая тема
-
+
A monochrome blue icon theme
+ Монохромная синяя тема
+
+
+
+ Diskimage (*.dmg)
-
+
+ Would you like to open the disk image to install the new version?
+
+
+
+
+ No Companion release candidates are currently being served for this version, please switch release channel
+
+
+
+
+ No nightly Companion builds are currently being served for this version, please switch release channel
+
+
+
+
+ No Companion release builds are currently being served for this version, please switch release channel
+
+
+
+
+ Companion update check failed, new version information not found.
+
+
+
+
+ A new release of Companion is available, please check the <a href='%1'>OpenTX website!</a>
+
+
+
+
+ Not enough flash available on this board for all the selected options
+
+
+
+
+ Compilation server temporary failure, try later
+
+
+
+
+ Compilation error
+
+
+
+
+ Invalid firmware
+
+
+
+
+ Invalid board
+
+
+
+
+ Invalid language
+
+
+
+
+ No firmware release candidates are currently being served for this version, please switch release channel
+
+
+
+
+ No firmware nightly builds are currently being served for this version, please switch release channel
+
+
+
+
+ No firmware release builds are currently being served for this version, please switch release channel
+
+
+
+
+ Release candidate builds are now available for this version, would you like to switch to using them?
+
+
+
+
+ Channel changed to RC, please restart the download process
+
+
+
+
+ Official release builds are now available for this version, would you like to switch to using them?
+
+
+
+
+ Channel changed to Release, please restart the download process
+
+
+
+
+ This radio (%1) is not currently available in this firmware release channel
+
+
+
+
+ Firmware update check failed, new version information not found or invalid.
+
+
+
+
+ Firmware %1 does not seem to have ever been downloaded.
+Version %2 is available.
+Do you want to download it now?
+
+We recommend you view the release notes using the button below to learn about any changes that may be important to you.
+ Прошивка %1 не была загружена.
+Доступна версия %2.
+Хотите её скачать?
+
+Мы рекомендуем вначале воспользоваться кнопкой "Информация", чтобы прочесть обо всех новшествах.
+
+
+
+
+ Do you want to download version %1 now ?
+ Вы хотите скачать версию %1?
+
+
+
+ Ignore this version %1?
+ Игнорировать версию %1?
+
+
+
+ There are unsaved file changes which you may lose when switching radio types.
+
+Do you wish to continue?
+
+
+
+
+ No local SD structure path configured!
+
+
+
+
+ No Radio or SD card detected!
+
+
+
+
+ Local Folder
+ Локальная папка
+
+
+
+ Radio Folder
+ Папка в передатчике
+
+
+
+ Models and Settings read
+
+
+
+
+
+ This function is not yet implemented
+
+
+
+
+ Close
+ Закрыть
+
+
+
+ Close Models and Settings file
+ Закрыть окно с моделями с настройками
+
+
+
+ List of recently used files
+ Список недавно открытых файлов
+
+
+
+ Radio Profiles
+ Профили передатчиков
+
+
+
+ Create or Select Radio Profiles
+ Выбрать профиль передатчика или создать новый
+
+
+
+ Release notes...
+ Описание версии ПО...
+
+
+
+ Show release notes
+ Показать информацию о текущей версии ПО
+
+
+
+ Create a new Radio Settings Profile
+ Создать новый профиль передатчика
+
+
+
+ Copy Current Radio Profile
+ Копировать текущий профиль передатчика
+
+
+
+ Duplicate current Radio Settings Profile
+ Копировать текущий профиль передатчика
+
+
+
+ Delete Current Radio Profile...
+ Удалить текущий профиль передатчика...
+
+
+
+ Delete the current Radio Settings Profile
+ Удалить текущий профиль передатчика
+
+
+
+ Export Application Settings..
+ Экспорт настроек приложения...
+
+
+
+ Save all the current %1 and Simulator settings (including radio profiles) to a file.
+ Сохранить все текущие настройки %1 и симулятора (включая профиль передатчика) в файл.
+
+
+
+ Import Application Settings..
+ Импорт настроек приложения...
+
+
+
+ Load %1 and Simulator settings from a prevously exported settings file.
+ Чтение ранее экспортированных настроек %1 и симулятора из файла.
+
+
+
+ Tabbed Windows
+ В виде закладок
+
+
+
+ Use tabs to arrange open windows.
+ Использовать закладки для переключения между окнами.
+
+
+
+ Tile Windows
+ По горизонтали
+
+
+
+ Arrange open windows across all the available space.
+ Выравнивание открытых окон по горизонтали.
+
+
+
+ Cascade Windows
+ Каскадом
+
+
+
+ Arrange all open windows in a stack.
+ Выравнивание открытых окон каскадом.
+
+
+
+ Close All Windows
+ Закрыть все окна
+
+
+
+ Closes all open files (prompts to save if necessary.
+ Закрыть все окна (с запросом на сохранение изменений).
+
+
+
+ Window
+ Окно
+
+
+
+ Some text will not be translated until the next time you start Companion. Please note that some translations may not be complete.
+ Некоторые сообщения не будут переведены, пока вы не перезапустите Companion. Учтите, что не все сообщения переведены на выбранный язык.
+
+
+
+ Ctrl+Shift+S
+
+
+
+
+ Ctrl+Alt+L
+
+
+
+
+ Ctrl+Alt+D
+
+
+
+
+ Ctrl+Alt+R
+
+
+
+
Small
-
+ Маленькие
-
+
Use small toolbar icons
-
+ Использовать маленькие иконки
-
+
Use normal size toolbar icons
-
+ Использоват иконки стандартного размера
-
+
Normal
- нормально
+ Стандартные
-
+
Use big toolbar icons
-
+ Использовать большие иконки
-
+
Big
-
+ Большие
-
+
Use huge toolbar icons
-
+ Использовать огромные иконки
-
+
Huge
+ Огромные
+
+
+
+ - Copy
-
+
+ Companion :: Open files warning
+
+
+
+
+ Please save or close modified file(s) before deleting the active profile.
+
+
+
+
+ Not possible to remove profile
+ Невозможно удалить профиль
+
+
+
+ The default profile can not be removed.
+ Нельзя удалить профиль по умолчанию.
+
+
+
+ Confirm Delete Profile
+
+
+
+
+ Are you sure you wish to delete the "%1" radio profile? There is no way to undo this action!
+
+
+
+
+ Please save or close all modified files before importing settings
+
+
+
+
+ <html><p>%1 and Simulator settings can be imported (restored) from a previosly saved export (backup) file. This will replace current settings with any settings found in the file.</p><p>An automatic backup of the current settings will be attempted. But if the current settings are useful then it is recommended that you make a manual backup first.</p><p>For best results when importing settings, <b>close any other %1 windows you may have open, and make sure the standalone Simulator application is not running.</p><p>Do you wish to continue?</p></html>
+
+
+
+
+ Confirm Settings Import
+
+
+
+
+ Select %1:
+
+
+
+
+ backup
+
+
+
+
+ Press the 'Ignore' button to continue anyway.
+
+
+
+
+ The settings could not be imported.
+ Невозможно импортировать настройки.
+
+
+
+ <html><p>New settings have been imported from:<br> %1.</p><p>%2 will now re-initialize.</p><p>Note that you may need to close and restart %2 before some settings like language and icon theme take effect.</p>
+
+
+
+
+ <p>The previous settings were backed up to:<br> %1</p>
+
+
+
+
Do you want to write the firmware to the radio now ?
-
-
+
+
Open Models and Settings file
-
+ Открыть файл с моделями и настройками
-
+
Read Models and Settings From Radio
-
+ Прочитать модели и настройки из передатчика
-
- Ignore this release %1?
-
-
-
-
-
-
- Companion
-
-
-
-
+
Save Radio Backup to File
-
+
Read Radio Firmware to File
-
+ Сохранить прошивку из передатчика в файл
-
+
The OpenTX Companion project was originally forked from <a href='%1'>eePe</a>
-
+
Copyright OpenTX Team
-
+
OpenTX Companion %1 - Radio: %2 - Profile: %3
-
+
Create a new Models and Settings file
-
+ Создать новую модель и настройки передатчика
-
-
+
+
Save Models and Settings file
-
+ Сохранить модели и настройки в файл
-
+
Exit
-
+ Выход
-
- Cut Model
-
-
-
-
- Cut current model to the clipboard
-
-
-
-
- Copy current model to the clipboard
-
-
-
-
- Paste model from clipboard
-
-
-
-
+
Classical
-
+
The classic companion9x icon theme
-
+ Классическая тема companion9x
-
+
Yerico
-
+
Yellow round honey sweet icon theme
-
+ Желтая тема
-
+
Monochrome
-
+
MonoWhite
-
+
MonoBlue
-
+
System language
-
+ Язык ОС
-
- Use system language in menus
-
-
-
-
- Czech
-
-
-
-
- Use Czech in menus
-
-
-
-
- German
-
-
-
-
- Use German in menus
-
-
-
-
- English
-
-
-
-
- Use English in menus
-
-
-
-
- Finnish
-
-
-
-
- Use Finnish in menus
-
-
-
-
- French
-
-
-
-
- Use French in menus
-
-
-
-
- Italian
-
-
-
-
- Use Italian in menus
-
-
-
-
- Polish
-
-
-
-
- Use Polish in menus
-
-
-
-
- Spanish
-
-
-
-
- Use Spanish in menus
-
-
-
-
- Swedish
-
-
-
-
- Use Swedish in menus
-
-
-
-
+
About...
-
+ О программе...
-
- Print...
-
-
-
-
- Print current model
-
-
-
-
- Simulate...
-
-
-
-
- Simulate current model
-
-
-
-
- Alt+S
-
-
-
-
- Load Backup...
-
-
-
-
+
View Log File...
-
+ Открыть журнал...
-
+
Open and view log file
-
+ Открыть и просмотреть журнал (логи)
-
+
Settings...
-
+ Настройки...
-
+
Edit Settings
-
+ Настройки
-
+
Download...
-
+ Скачать...
-
+
Download firmware and voice files
-
+ Скачать прошивку и содержимое SD карточки
-
+
Check for Updates...
-
+ Поиск обновлений...
-
+
Check OpenTX and Companion updates
-
+ Проверить наличие обновлений OpenTX и Companion
-
- Companion Changes...
-
-
-
-
- Show Companion change log
-
-
-
-
- Firmware Changes...
-
-
-
-
- Show firmware change log
-
-
-
-
+
Compare Models...
-
+ Сравнить модели...
-
+
Edit Radio Splash Image...
-
+ Редактировать заставку передатчика...
-
+
Edit the splash image of your Radio
-
+
List programmers...
-
+
Fuses...
-
-
+
+
Read Firmware from Radio
-
+ Скачать прошивку из передатчика
-
+
Read firmware from Radio
-
+ Сохранить прошивку из передатчика в файл
-
-
+
Write Firmware to Radio
-
+ Обновить прошивку передатчика
-
+
Write firmware to Radio
-
+ Обновить прошивку передатчика
-
+
Add Radio Profile
-
+ Добавить профиль передатчика
-
- Create a new Radio Setting Profile
-
-
-
-
+
Manuals and other Documents
-
+ Инструкции и руководства
-
+
Open the OpenTX document page in a web browser
-
+ Открыть инструкцию к OpenTX в браузере
-
+
Write Models and Settings To Radio
-
+ Записать модели и настройки в передатчик
-
-
+
Write Models and Settings to Radio
-
-
-
-
-
- Read Models and Settings from Radio
-
-
-
-
- Configure Communications...
-
-
-
-
- Configure software for communicating with the Radio
-
-
-
-
- Write Backup to Radio
-
-
-
-
- Write Backup from file to Radio
-
-
-
-
- Backup Radio to File
-
-
-
-
- Save a complete backup file of all settings and model data in the Radio
-
-
-
-
- Contributors...
-
-
-
-
- A tribute to those who have contributed to OpenTX and Companion
-
-
-
-
- SD card synchronization
-
-
-
-
- Recent Files
-
+ Записать модели и настройки в передатчик
+
- Recent Models+Settings
-
+ Read Models and Settings from Radio
+ Прочитать модели и настройки из передатчика
-
+
+ Configure Communications...
+ Настройка подключения...
+
+
+
+ Configure software for communicating with the Radio
+ Настройка подключения к передатчику
+
+
+
+ Write Backup to Radio
+ Записать резервную копию из файла в передатчик
+
+
+
+ Write Backup from file to Radio
+ Записать резервную копию из файла в передатчик
+
+
+
+ Backup Radio to File
+ Сделать резервную копию передатчика
+
+
+
+ Save a complete backup file of all settings and model data in the Radio
+ Сделать полную копию всех моделей и настроек, хранящихся в передатчике
+
+
+
+ Contributors...
+ Разработчики...
+
+
+
+ A tribute to those who have contributed to OpenTX and Companion
+ Показать список тех, кто помогал в разработке OpenTX и Companion
+
+
+
+ SD card synchronization
+ Синхронизация содержимого SD карточки
+
+
+
+ Recent Files
+ Последние
+
+
+
Set Icon Theme
-
+ Стиль иконок
-
+
Set Icon Size
-
+ Размер иконок
-
-
+
+
File
Файл
-
-
+
+
Edit
Правка
-
+
Settings
-
+ Параметры
-
+
Read/Write
-
+ Чтение/Запись
-
-
+
+
Help
-
+ Помощь
-
-
- Radio Profile
-
-
-
-
- Show recent Models+Settings documents
-
-
-
-
+
Ready
Готово
@@ -4538,131 +6927,397 @@ We recommend you view the release notes using the button below to learn about an
MdiChild
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Error
- Ошибка
-
-
-
+
Editing model %1:
Редактирование модели %1:
-
-
+
+ <p><b>Currently selected radio type (%1) is not compatible with file %3 (from %2), models and settings need to be converted.</b></p>
+
+
+
+
+ Do you wish to continue with the conversion?
+
+
+
+
+ Choose <i>Apply</i> to convert the file, or <i>Close</i> to close it without conversion.
+
+
+
+
+ <b>The conversion generated some important messages, please review them below.</b>
+
+
+
+
+ Companion :: Conversion Result for %1
+
+
+
+
+ Unable to find Horus radio SD card!
+
+
+
+
+ Models and Settings written
+
+
+
+
Unable to find file %1!
Невозможно найти файл %1!
-
-
+
Error reading file %1:
%2.
Ошибка при считывании файла %1:
%2.
-
-
-
-
+
Error opening file %1:
%2.
-
- free bytes
+
+ Alt+Shift+E
-
- Companion
+
+ Ctrl+Alt+C
-
-
- Invalid EEPROM File %1
+
+ Ctrl+Alt+V
-
- Invalid binary EEPROM File %1
+
+ Alt+Shift+S
+
+
+ Alt+C
+
+
+
+
+ Alt+A
+
+
+
+
+ Alt+R
+
+
+
+
+ Alt+W
+
+
+
+
+ Alt+U
+
+
+
+
+ Alt+S
+
+
+
+
+ %n Model(s)
+ As in "Copy 3 Models" or "Cut 1 Model" or "Delete 3 Models" action).
+
+ модель
+ %n модели(ей)
+ %n модели
+
+
+
+
+ %n Model(s)
+ As in "Paste 3 Models" or "Insert 1 Model."
+
+ модель
+ %n модели(ей)
+ %n модели(ей)
+
+
+
+
+ %n Category(ies)
+ As in "Delete 3 Categories" or "Delete 1 Category."
+
+ категорию
+ %n категории(ий)
+ %n категории(ий)
+
+
+
+
+ Nothing selected
+
+
+
+
+ Rename Category
+ Переименовать категорию
+
+
+
+ Edit Model
+ Редактировать модель
+
+
+
+ Delete
+ Удалить
+
+
+
+ Cut
+ Вырезать
+
+
+
+ Copy
+ Копировать
+
+
+
+ Paste
+ Вставить
+
+
+
+ Insert
+ Вставить
+
+ Edit Radio Settings
+ Параметры передатчика
+
+
+
+ Copy Radio Settings
+ Копировать настройки передатчика
+
+
-
+ Paste Radio Settings
+ Вставить настройки передатчика
+
+
+
+ Simulate Radio
+ Симулятор передатчика
+
+
+
+ Add Category
+ Добавить категорию
+
+
+
+ Category
+ Категория
+
+
+
+ Add Model
+ Добавить модель
+
+
+ Model
+ Модель
+
+
+
+ Restore from Backup
+ Восстановить из резервной копии
+
+
+
+ Model Wizard
+ Мастер по настройке
+
+
+
+ Set as Default
+ Модель по умолчанию
+
+
+
+ Print Model
+ Распечатать модель
+
+
+
+ Simulate Model
+ Симулятор модели
+
+
+
+ Duplicate Model
+ Сделать копию
+
+
+
+ Move to Category
+ Переместить в категорию
+
+
+
+ Show Category Actions Toolbar
+
+
+
+
+ Show Radio Actions Toolbar
+
+
+
+
+ Show Model Actions Toolbar
+
+
+
+
+ free bytes
+ байт свободно
+
+
+
+ read only
+
+
+
+
+ New category
+ Translators do NOT use accent for this, this is the default category name on Horus.
+
+
+
+
+ Category index out of range.
+
+
+
+
+ Cannot delete the last category.
+ Нельзя удалять последнюю категорию.
+
+
+
+ This category is not empty!
+ В этой категории есть модели!
+
+
+
+ Cannot insert model, last model in list would be deleted.
+
+
+
+
+ Cannot add model, could not find an available model slot.
+
+
+
+
+ New model
+ Translators: do NOT use accents here, this is a default model name.
+
+
+
+
+ Cannot paste model, out of available model slots.
+
+
+
+
+ You are replacing an existing model, are you sure?
+ Вы действительно хотите перезаписать модель?
+
+
+
+ Do you want to overwrite radio general settings?
+
+
+
+
+ Delete %n selected model(s)?
+
+ Удалить выбранную модель?
+ Удалить выбранные модели (%n)?
+ Удалить выбранные модели (%n)?
+
+
+
+
+ Delete %n selected category(ies)?
+
+ Удалить выбранную категорию?
+ Удалить выбранные категории?
+ Удалить выбранные категории (%n)?
+
+
+
+
+ Cannot duplicate model, could not find an available model slot.
+
+
+
+
Save As
- Сохранить как...
+ Сохранить как
-
-
-
-
- Cannot write file %1:
-%2.
- Не удается записать файл %1:
-%2.
-
-
-
+
Open backup Models and Settings file
-
-
-
-
- Warning
- Звук
-
-
-
+
Invalid binary backup File %1
-
+
%1 has been modified.
Do you want to save your changes?
+ %1 изменен.
+Вы хотите сохранить изменения?
+
+
+
+ Cannot write temporary file!
+ Не удается записать временный файл!
+
+
+
+ MixData
+
+
+ MIX
-
-
- Error writing file %1:
-%2.
- Ошибка при записи файла %1:
-%2.
-
-
-
- Cannot write temporary file!
- Не удается записать временный файл!
+
+ (@%1)
+
@@ -4671,7 +7326,7 @@ Do you want to save your changes?
Dialog
???
- Диалог
+ Настройки микшера
@@ -4684,7 +7339,7 @@ Do you want to save your changes?
The source for the mixer
- Источник для микшера
+ Источник данных для микшера
@@ -4703,17 +7358,18 @@ Do you want to save your changes?
Switch used by the mix.
If blank then the mix is considered to be "ON" all the time.
The value of the mixer is multiplied by this value and divided by 100.
- Значение микшера умножается на это значение и делится на 100
+ Микшер можно активировать тумблером.
+Если тумблер не указан, тогда микшер будет включен всё время.
Offset
- Смещен.
+ Смещение
Include Trim
- Исп. трим
+ Использовать триммер
@@ -4723,7 +7379,7 @@ If blank then the mix is considered to be "ON" all the time.
The curve used by the mix
- Кривая используемая микшером
+ Кривая, используемая микшером
@@ -4733,12 +7389,12 @@ If blank then the mix is considered to be "ON" all the time.
Yes
-
+ Да
No
-
+ Нет
@@ -4748,7 +7404,7 @@ If blank then the mix is considered to be "ON" all the time.
Name
-
+ Название
@@ -4766,14 +7422,23 @@ p, li { white-space: pre-wrap; }
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -> the value states the number of seconds it takes to transit from -100 to 100.</p></body></html>
-
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Задержка и замедление</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Эти значения управляют скоростью и задержкой применения микшера</p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Если задержка больше 0, то микшер будет активирован не сразу, а через указанное время</p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Если замедление не равно 0, то это скорость применения микшера. Т.е. значение в секундах для перехода от -100 к +100 (например, плавный выпуск закрылков/шасси)</p></body></html>
Mixer warning.
Setting this value will cause a beep to be emmitted when this value is active.
- Индикация включения.
-Когда микшер активируется звучит выбранный сигнал.
+ Передатчик будет издавать звуки пока микшер активен.
@@ -4783,18 +7448,18 @@ Setting this value will cause a beep to be emmitted when this value is active.
1 Beep
- 1 бип
+ 1 сигнал
2 Beep
2 Beeo
- 2 бипа
+ 2 сигнала
3 Beep
- 3 бипа
+ 3 сигнала
@@ -4812,31 +7477,31 @@ This determines how mixer values are added.
"R" means the value replaces the previous values. If the switch is off the value will be ignored.
Мультиплексор
-Определяет, каким образом добавляется значение микшера.
+Определяет, каким образом вычисляется значение микшера.
-"+" - значение текущего микшера добавляется к предыдущему значению на этом же канале.
-"*" - значение текущего микшера умножается на предыдущее значение на этом же канале
-"R" - значение текущего микшера заменяет предыдущее значение на этом же канале.
+"+" - значение текущего микшера добавляется к предыдущему микшеру на этом же канале.
+"*" - значение текущего микшера умножается на значение предыдущего микшера на этом же канале
+"R" - значение текущего микшера заменяет предыдущее значение. Если тумблер отключен, то значение игнорируется.
ADD
- ДОБАВИТЬ
+ СЛОЖЕНИЕ
MULTIPLY
- УМНОЖИТЬ
+ УМНОЖЕНИЕ
REPLACE
- ЗАМЕНИТЬ
+ ЗАМЕНА
Flight modes
-
+ Полётные режимы
@@ -4851,153 +7516,209 @@ This determines how mixer values are added.
Slow
- Замедлен.
+ Замедление
Up
- Верх
+ Вверх
Down
- Низ
+ Вниз
-
- DEST -> CH%1
+
+ DEST -> %1
+
+
+
+
+ Click to access popup menu
+ Нажмите, чтобы открыть меню
+
+
+
+ Clear All
+ Убрать всё
+
+
+
+ Set All
+ Выбрать всё
+
+
+
+ Invert All
+ Инвертировать
+
+
+
+ MixersListWidget
+
+
+ Increase font size
+
+
+
+
+ Decrease font size
+
+
+
+
+ Default font size
+
+
+
+
+ Ctrl+0
MixesPanel
-
-
+
+
Move Up
-
+ Сдвинуть вверх
-
-
+
+
Ctrl+Up
-
-
+
+
Move Down
-
+ Сдвинуть вниз
-
-
+
+
Ctrl+Down
-
+
Clear Mixes
-
+ Удалить микшеры
-
+
Not enough available mixers!
-
+ Недостаточно микшеров!
-
+
Delete Selected Mixes?
- Удалить выбранные микшеры?
+ Удалить выбранные микшеры?
-
+
&Add
- Добавить
+ Добавить
-
+
Ctrl+A
-
+
&Edit
- Правка
+ Редактировать
-
+
Enter
- Ввод
+
-
+
&Toggle highlight
-
+
Ctrl+T
-
+
&Delete
- Удалить
+ Удалить
-
+
Delete
- Удалить
+
-
+
&Copy
- Копировать
+ Копировать
-
+
Ctrl+C
-
+
Ctrl+X
-
+
C&ut
-
+
&Paste
- Вставить
+ Вставить
-
+
Ctrl+V
-
+
Du&plicate
-
+ Сделать копию
-
+
Ctrl+U
-
+
Clear Mixes?
+ Удалить все микшеры?
+
+
+
+ Really clear all the mixes?
+ Вы действительно хотите удалить все микшеры?
+
+
+
+ ModelData
+
+
+ Model:
-
- Really clear all the mixes?
+
+ Throttle Source
@@ -5009,929 +7730,1865 @@ This determines how mixer values are added.
Диалог
-
+
Setup
- Настройка
+ Основные
-
+
Heli
-
+ Вертолёт
-
+
Inputs
-
+ Входы
-
+
Logical Switches
-
+ Логические переключатели
-
+
Mixes
Микшеры
-
+
Outputs
-
+ Выходы
-
+
Curves
Кривые
-
+
Special Functions
-
+ Специальные функции
-
+
Telemetry
-
+ Телеметрия
-
+
Flight Modes
-
+ Полетные режимы
Simulate
- Симуляция
+ Симулятор
ModelPrinter
-
- %1 bytes
+
+ Enable
+ Вкл.
+
+
+
+ Disable
-
- CH%1
+
+ True
-
+
+ False
+
+
+
+
+ Yes
+ Да
+
+
+
+ No
+ Нет
+
+
+
+ Y
+ Да
+
+
+
+ N
+
+
+
+
+ ON
+
+
+
+
+
+
+
+ OFF
+ ВЫКЛ
+
+
+
+ bytes
+
+
+
+
Exponential
- экспонента
+ по экспоненте
-
+
Extra Fine
- очень точно
+ очень точно
-
+
Fine
- точно
+ точно
-
+
Medium
- средне
+ средне
-
+
Coarse
- грубо
+ грубо
-
+
Unknown
-
+ неизвестно
-
- Enabled
-
-
-
-
- Disabled
-
-
-
-
- %1, Channels(%2-%3), PPM delay(%4usec), Pulse polarity(%5)
-
-
-
-
- %1, Channels(%2-%3)
-
-
-
-
- Receiver number(%1)
-
-
-
-
- Slave/Jack
-
-
-
-
- Master/SBUS Module
-
-
-
-
- Master/CPPM Module
-
-
-
-
- Master/SBUS in battery compartment
-
-
-
-
- Master/Jack
-
-
-
-
- Rudder
- Руддер
-
-
-
- Elevator
- Элеватор
-
-
-
- Throttle
- Газ
-
-
-
- Aileron
- Элероны
-
-
-
- Name(%1)
-
-
-
-
- Persistent
-
-
-
-
- MinuteBeep
-
-
-
-
- CountDown(Beeps)
-
+
+
+ Mode
+ Режим
- CountDown(Voice)
+
+ Channels
+ Каналы
+
+
+
+
+ Frame length
- CountDown(Haptic)
+ PPM delay
-
+
+
+ Polarity
+ Полярность
+
+
+
+ Protocol
+ Протокол
+
+
+
+
+
+ Delay
+ Задержка
+
+
+
+
+ Receiver
+ Приёмник
+
+
+
+ Radio protocol
+ Протокол
+
+
+
+ Subtype
+ Подтип
+
+
+
+ Option value
+
+
+
+
+ Sub Type
+ Подтип
+
+
+
+ RF Output Power
+ Выходная мощность передатчика
+
+
+
+ 90
+
+
+
+
+ 120
+
+
+
+
+ 120X
+
+
+
+
+ 140
+
+
+
+
+ MULT!
+
+
+
+
+
+ Offset
+ Смещен.
+
+
+
+ Slow
+ Замедление
+
+
+
+ Warn
+
+
+
+
+ Flight modes
+ Полетные режимы
+
+
+
+ Flight mode
+ Полетный режим
+
+
+
+ All
+
+
+
+
+ Edge
+
+
+
+
+ instant
+
+
+
+
+ Sticky
+
+
+
+
+ Timer
+
+
+
+
+ missing
+
+
+
+
+ Duration
+
+
+
+
+ Extended Limits
+ Расш. лимиты
+
+
+
+ Display Checklist
+ Показать контрольную карту
+
+
+
+ Global Functions
+ Глобальные функции
+
+
+
+ Manual
+ вручную
+
+
+
+ Auto
+ автоматически
+
+
+
+ Failsafe Mode
+ Режим Failsafe
+
+
+
+
+ Hold
+ удержание
+
+
+
+ No Pulse
+ без сигнала
+
+
+
+ Not set
+ не задан
+
+
+
+ No pulses
+ Без сигнала
+
+
+
+ Silent
+ Тихо
+
+
+
+ Beeps
+ Писком
+
+
+
+ Voice
+ Голосом
+
+
+
+ Haptic
+ Вибрацией
+
+
+
+ Flight
+
+
+
+
+ Manual reset
+
+
+
+
+ Step
+ Шаг
+
+
+
+ Display
+ Показывать
+
+
+
+ Extended
+ Расширенные
+
+
+
+ Never
+ никогда
+
+
+
+ On Change
+ при изменении
+
+
+
+ Always
+ всегда
+
+
+
+
+
+ Source
+ Источник
+
+
+
+ Trim idle only
+ Триммировать только холостой ход
+
+
+
+ Warning
+ Предупреждать
+
+
+
+ Reversed
+ Реверс
+
+
+
+ Tmr
+
+
+
+
+ FrSky S.PORT
+
+
+
+
+ FrSky D
+
+
+
+
+ FrSky D (cable)
+
+
+
+
+ Alti
+
+
+
+
+ Alti+
+
+
+
+
+ VSpeed
+
+
+
+
+
+
+ A1
+
+
+
+
+
+
+ A2
+
+
+
+
+
+ A3
+
+
+
+
+
+ A4
+
+
+
+
+
+ FAS
+
+
+
+
+ Cells
+
+
+
+
+ Calculated
+
+
+
+
+ Add
+
+
+
+
+ Average
+
+
+
+
+
+ Min
+
+
+
+
+
+ Max
+
+
+
+
+ Multiply
+
+
+
+
+ Totalise
+
+
+
+
+ Cell
+
+
+
+
+ Consumption
+
+
+
+
+ Distance
+
+
+
+
+ Lowest
+
+
+
+
+ Cell %1
+
+
+
+
+ Highest
+
+
+
+
+ Delta
+
+
+
+
+ Formula
+
+
+
+
+
+ Id
+
+
+
+
+ Instance
+
+
+
+
+
+
+
+ Sensor
+
+
+
+
+
+ Sources
+
+
+
+
+
+ GPS
+
+
+
+
+ Alt.
+
+
+
+
+
+ Blades
+
+
+
+
+ Multi.
+
+
+
+
+ F
+
+
+
+
+ Inst
+
+
+
+
+ Alt
+
+
+
+
+ Unit
+ Ед. измерения
+
+
+
+ Prec
+ Точность
+
+
+
+ Ratio
+ Коэффициент
+
+
+
+ Multi
+
+
+
+
+ A/Offset
+ Авт. смещ.
+
+
+
+ Filter
+
+
+
+
+ Persist
+
+
+
+
+ Positive
+ Положительный
+
+
+
+ Log
+ Журнал
+
+
+
+ Numbers
+
+
+
+
+ Bars
+
+
+
+
+ Script
+
+
+
+
+ Filename
+
+
+
+
+ Error: Unable to open or read file!
+ Ошибка: невозможно открыть файл!
+
+
+
+ Slave/Jack
+ Ученик (джек)
+
+
+
+ Master/SBUS Module
+ Главный (SBUS модуль)
+
+
+
+ Master/CPPM Module
+ Главный (модуль CPPM)
+
+
+
+ Master/SBUS in battery compartment
+ Главный (SBUS в батарейном отсеке)
+
+
+
+ Master/Jack
+ Главный (джек)
+
+
+
+ Persistent
+
+
+
+
Off
-
-
-
-
+
+
+
+
+
+
+ None
+ Нет
+
+
+
+ Name
+
+
+
+
+ Countdown
+
+
+
+
+ Minute call
+
+
+
+
+
+
FM%1
-
+
FM%1%2
-
+
FM%1+%2
-
- [I%1]
-
-
-
-
- Input%1
-
-
-
-
+
+
Weight
- Вес
+ Вес
-
+
+
Switch
- Тумблер
+ Тумблер
-
-
+
+
NoTrim
-
- Weight(%1)
-
-
-
-
- Switch(%1)
-
-
-
-
+
No DR/Expo
-
+
Offset(%1)
-
- Delay(u%1:d%2)
-
-
-
-
- Slow(u%1:d%2)
-
-
-
-
- Warn(%1)
-
-
-
-
+
Disabled in all flight modes
-
+ Отключен во всех полетных режимах
-
- Flight modes(%1)
-
-
-
-
- Flight mode(%1)
-
-
-
-
- Edge(%1, [%2:%3])
-
-
-
-
- Sticky(%1, %2)
-
-
-
-
- Timer(%1, %2)
-
-
-
-
- Duration(%1s)
-
-
-
-
- Delay(%1s)
-
-
-
-
+
+
+
Custom
-
+ Другой
-
+
Standard
-
+ Стандартный
ModelSelectionPage
-
+
Plane
-
+ Самолёт
-
+
Multirotor
-
+ Мультикоптер
-
+
Helicopter
-
+ Вертолет
-
+
Model Name:
-
+ Название модели:
-
+
Model Type:
-
-
-
-
- ModelsListWidget
-
-
-
- &Edit
- Правка
-
-
-
- &Restore from backup
-
-
-
-
- &Model Wizard
-
-
-
-
- &Delete
- Удалить
-
-
-
- Delete
- Удалить
-
-
-
- &Copy
- Копировать
-
-
-
- Ctrl+C
-
-
-
-
- &Cut
- Вырезать
-
-
-
- Ctrl+X
-
-
-
-
- &Paste
- Вставить
-
-
-
- Ctrl+V
-
-
-
-
- D&uplicate
- Дублировать
-
-
-
- Ctrl+U
-
-
-
-
- &Use as default
-
-
-
-
- P&rint model
-
-
-
-
- Ctrl+P
-
-
-
-
- Alt+S
-
-
-
-
- &Simulate model
-
-
-
-
- General Settings
- Основные настройки
-
-
-
- Delete Selected Models?
- Удалить выбранные модели?
-
-
-
-
- Cannot delete default model.
-
-
-
-
- Cannot cut default model.
-
-
-
-
- Do you want to overwrite radio general settings?
-
-
-
-
- You are pasting on an not empty model, are you sure?
- You are pasting on an not empty model, are you sure ?
-
-
-
-
- No free slot available, cannot duplicate
-
+ Тип модели:
Module
-
+
Failsafe Mode
-
+ Режим Failsafe
-
+
Start
-
+ Начать с
-
+
PPM delay
-
+
Negative
-
+
Positive
-
+
Polarity
-
+ Полярность
-
+
Trainer Mode
-
+ Тренерский режим
-
+
PPM Frame Length
-
+ Длите. кадра PPM
-
+
CH
+ Канал
+
+
+
+ RF Output Power
+ Выходная мощность передатчика
+
+
+
+ Receiver 1
+ Приёмник 1
+
+
+
+
+
+ X
-
+
+ Receiver 2
+ Приёмник 2
+
+
+
+ Receiver 3
+ Приёмник 3
+
+
+
+ WARNING: changing RF Output Power needs RE-BIND
+
+
+
+
+ Low Power
+
+
+
+
us
-
+
+ Antenna
+ Антенна
+
+
+
+ Option value
+
+
+
+
+ Registration ID
+
+
+
+
+ Multi Radio Protocol
+ Режим мультипротокольного модуля
+
+
+
+ Sub Type
+ Подтип
+
+
+
+ WARNING: Requires non-certified firmware!
+
+
+
+
Master/Jack
-
+ Главный (джек)
-
+
Slave/Jack
-
+ Ученик (джек)
-
+
Master/SBUS Module
-
+ Главный (SBUS модуль)
-
+
Master/CPPM Module
-
+ Главный (модуль CPPM)
-
+
Master/SBUS in battery compartment
+ Главный (SBUS в батарейном отсеке)
+
+
+
+ Show values in:
-
+
+ %
+ abbreviation for percent
+
+
+
+
+ μs
+ abbreviation for microseconds
+
+
+
+
ms
-
-
-
-
- Channels
- Каналы
-
-
-
- Not set
-
-
-
-
- Hold
-
-
-
-
- Custom
-
-
-
-
- No Pulses
-
-
-
-
- Receiver
-
-
-
-
- Failsafe Positions
-
+ мс
- Protocol
- Протокол
+ Channels
+ Кол-во каналов
-
- Receiver No.
+
+ Not set
+ Не задан
+
+
+
+ Hold
+ Удержание
+
+
+
+ Custom
+ Другой
+
+
+
+ No Pulses
+ Без сигнала
+
+
+
+ Receiver
+ В приёмнике
+
+
+
+ Master/Bluetooth
+ Главный (bluetooth)
+
+
+
+ Slave/Bluetooth
+ Ученик (bluetooth)
+
+
+
+ Master/Multi
+ Главный (мультимодуль)
+
+
+
+ Disable Telemetry
+ Отключить телеметрию
+
+
+
+ Disable Ch. Map
-
+
+ Failsafe Positions
+ Параметры Failsafe
+
+
+
+ Protocol
+ Протокол
+
+
+
+ Receiver No.
+ Номер приёмника
+
+
+
Output type
-
+
Open Drain
-
+
Push Pull
+
+ ModuleData
+
+
+ Trainer Port
+
+
+
+
+ Internal Radio System
+ Встроенный радиомодуль
+
+
+
+ External Radio Module
+ Внешний радиомодуль
+
+
+
+ Extra Radio System
+
+
+
+
+ Radio System
+
+
+
+
+ 10mW - 16CH
+ 10 мВт - 16 каналов
+
+
+
+
+ 100mW - 16CH
+ 100 мВт - 16 каналов
+
+
+
+ 500mW - 16CH
+ 500 мВт - 16 каналов
+
+
+
+ Auto <= 1W - 16CH
+ Автоматически: < 1 Вт - 16 каналов
+
+
+
+
+ 25mW - 8CH
+ 25 мВт - 8 каналов
+
+
+
+
+ 25mW - 16CH
+ 25 мВт - 16 каналов
+
+
+
+ 200mW - 16CH (no telemetry)
+ 200 мВт - 16 каналов (без телеметрии)
+
+
+
+ 500mW - 16CH (no telemetry)
+ 500 мВт - 16 каналов (без телеметрии)
+
+
+
+ 100mW - 16CH (no telemetry)
+ 100 мВт - 16 каналов (без телеметрии)
+
+
+
+ Positive
+
+
+
+
+ Negative
+
+
+
ModulePanel
-
- Trainer Port
-
-
-
-
- Internal Radio System
-
-
-
-
- External Radio Module
-
-
-
-
-
- Radio System
-
-
-
-
- Extra Radio System
-
-
-
-
+
Value
Значение
-
+
Hold
-
+
No Pulse
+
+
+ Ask
+
+
+
+
+ Internal
+
+
+
+
+ Internal + External
+
+
+
+
+ External
+
+
+
+
+ Autodetect Format
+
+
+
+
+ Bind on channel
+
+
MultiModelPrinter
-
- General Model Settings
-
-
-
-
- Name:
-
-
-
-
- EEprom Size:
-
-
-
-
- Timer%1:
-
-
-
-
- Module%1:
-
-
-
-
- Module:
-
-
-
-
- Trainer port:
-
-
-
-
- Throttle Trim:
-
-
-
-
- Trim Increment:
-
-
-
-
- Center Beep:
-
-
-
-
+
Flight modes
-
+ Полетные режимы
-
-
+
+
Flight mode
-
+ Режим
-
+
+
Switch
- Тумблер
+ Тумблер
-
- Fade IN
-
-
-
-
- Fade OUT
-
-
-
-
-
- FM%1
-
-
-
-
-
+
+
GV%1
-
+
RE%1
-
- Limits
- Лимиты
-
-
-
+
Channel
-
+ Канал
-
+
+
+
Name
+ Название
+
+
+
+ General
+ Основные параметры
+
+
+
+ EEprom Size
+ Размер
+
+
+
+ Model Image
+ Изображение
+
+
+
+ Throttle
+ Газ
+
+
+
+ Trims
+ Триммеры
+
+
+
+ Center Beep
+ Сигнал в центре
+
+
+
+ Switch Warnings
+ Проверка тумблеров
+
+
+
+ Pot Warnings
+ Проверка крутилок
+
+
+
+ Other
+ Прочее
+
+
+
+ Timers
+ Таймеры
+
+
+
+ Time
+ Время
+
+
+
+ Countdown
+ Отсчет
+
+
+
+ Min.call
+ Ежеминутный сигнал
+
+
+
+ Persist
+ Постоянный
+
+
+
+ Modules
+ Радиомодули
+
+
+
+ Trainer port
+ Тренерский разъем
+
+
+
+ Helicopter
+ Вертолет
+
+
+
+ Swash
+ Автомат перекоса
+
+
+
+
+ Type
+ Тип
+
+
+
+ Ring
+ Тарелка
+
+
+
+ Input
+ Вход
+
+
+
+ Weight
+ Вес
+
+
+
+ Long. cyc
-
-
+
+ Lateral cyc
+
+
+
+
+ Collective
+
+
+
+
+ F.In
+
+
+
+
+ F.Out
+
+
+
+
+ Global vars
+ Глобальные переменные
+
+
+
+ Prec
+
+
+
+
+ Popup
+
+
+
+
+ Outputs
+ Выходы
+
+
+
+ Subtrim
+ Субтриммер
+
+
+
+ Direct
+
+
+
+
+ Curve
+ Кривая
+
+
+
+ PPM
+
+
+
+
+ Linear
+ Линейный
+
+
+
+ Telemetry
+ Телеметрия
+
+
+
Offset
Смещен.
-
+
+ Protocol
+ Протокол
+
+
+
+ Low
+ Низкий
+
+
+
+ Critical
+ Критический
+
+
+
+ Telemetry audio
+ Звук телеметрии
+
+
+
+ Altimetry
+ Измерение высоты
+
+
+
+
+ Vario source
+ Вариометр
+
+
+
+ Vario limits >
+ Пределы вариометра >
+
+
+
+ Sink max
+ Сниж. макс.
+
+
+
+ Sink min
+ Сниж. мин.
+
+
+
+ Climb min
+ Набор мин.
+
+
+
+ Climb max
+ Набор макс.
+
+
+
+ Center silent
+ Тишина в 0
+
+
+
+ Top Bar
+ Верхняя строка
+
+
+
+
+ Volts source
+ Напряжение
+
+
+
+ Altitude source
+ Высота
+
+
+
+ Various
+
+
+
+
+ Serial protocol
+
+
+
+
+ FAS offset
+
+
+
+
+ mAh count
+
+
+
+
+ Persistent mAh
+
+
+
+
+ Current source
+ Датчик тока
+
+
+
+ Blades
+
+
+
+
+ Parameters
+ Параметры
+
+
+
+ Telemetry Sensors
+ Датчики телеметрии
+
+
+
+ Telemetry Screens
+
+
+
+
+ GF%1
+
+
+
+
+ Global Functions
+ Глобальные функции
+
+
+
+ Checklist
+ Контрольная карта
+
+
+
+
Min
- Мин
+ Мин
-
+
+
Max
- Макс
+ Макс
-
- Invert
- Инверт
-
-
-
+
Global Variables
-
+ Глобальные переменные
-
+
Inputs
-
+ Входы
-
+
Mixers
-
+ Микшеры
-
- CV%1
-
-
-
-
+
Curves
- Кривые
+ Кривые
-
+
L%1
-
+
Logical Switches
-
+ Логические переключатели
-
+
SF%1
-
+
Special Functions
-
+ Специальные функции
-
- Telemetry Settings
-
-
-
-
+
Analogs
-
+
+
Unit
-
+ Ед.
-
+
Scale
-
- A%1
+
+ RSSI Alarms
+ Уровень RSSI
+
+
+
+ Multiprotocols
+
+
+ Subtype
-
- RSSI Alarms
+
+ Video TX frequency
+
+
+
+
+ CC2500 frequency fine tune
+
+
+
+
+ Telemetry
+
+
+
+
+ Radio output power
+
+
+
+
+ Servo output frequency
+
+
+
+
+ Option value
+
+
+
+
+ Fixed ID value
+
+
+
+
+ DEFAULT
+
+
+
+
+ Custom - proto %1)
MultirotorPage
-
+
Throttle Channel:
-
+ Газ:
-
+
Yaw Channel:
-
+ Рысканье (yaw):
-
+
Pitch Channel:
+ Тангаж (pitch):
+
+
+
+ Roll Channel:
+ Крен (roll):
+
+
+
+ OpenTxEepromInterface
+
+
+ Unknown error
-
- Roll Channel:
+
+ ... plus %1 errors
+
+
+
+
+ Cannot write radio settings
+
+
+
+
+ Cannot write model %1
OptionsPage
-
+
Throttle Cut
-
+ Отсечка газа (throttle cut)
-
+
Throttle Timer
+ Таймер газа
+
+
+
+ Flight Timer
+ Таймер полетного времени
+
+
+
+ OtxFormat
+
+
+ Error opening file %1:
+%2.
-
- Flight Timer
+
+ Error opening OTX archive %1
+
+
+
+
+ Error initializing OTX archive writer
+
+
+
+
+ Error writing file %1:
+%2.
+ Ошибка при записи файла %1:
+%2.
+
+
+
+ Error creating OTX file %1:
+%2.
+
+
+
+
+ Error creating OTX archive
+
+
+
+
+ Error adding %1 to OTX archive
@@ -5940,2396 +9597,221 @@ This determines how mixer values are added.
Close
-
+ Закрыть
- Print
-
+ Style
+ Стили
+ Print
+ Печать
+
+
+
Print to file
-
+ В файл
-
+
Print Document
-
+ Распечатать
-
+
Select PDF output file
-
+ PDF файл для сохранения
-
+
ODF files (*.odt);;PDF Files(*.pdf);;HTML-Files (*.htm *.html);;All Files (*)
-
+ ODF файлы (*.odt);;PDF файлы (*.pdf);;HTML-файлы (*.htm *.html);;Все файлы (*)
ProgressDialog
-
+
Flash Firmware
-
+
+
Close
-
+ Закрыть
+
+
+
+ Cancel
+ Отмена
ProgressWidget
-
- Form
-
-
-
-
+
Show Details
-
+ Подробный отчет
QObject
-
- Polish
+
+ WARNING
-
- CH%1
+
+ <p>Importing JumperTX data into OpenTX 2.3 is <b>not supported and dangerous.</b></p> <p>It is unfortunately not possible for us to differentiate JumperTX data from legitimate FrSky X10 data, but <b>You should only continue here if the file you opened comes from a real FrSky X10.</b></p> <p>Do you really want to continue?</p>
+
+
+ RadioData
-
- No
+
+ Models
+
+
+ RadioDataConversionState
-
- RotEnc A
+
+ is invalid
-
- Rot Enc B
+
+ converted to
-
- Rot Enc C
+
+ verify is
-
- Rot Enc D
+
+ [DBG]
-
- Rot Enc E
+
+ [NFO]
-
- Trainer
+
+ [WRN]
-
- Trainer RUD
+
+ [CVT]
-
- Trainer ELE
+
+ [ERR]
-
- Trainer THR
+
+ [INV]
-
- Trainer AIL
+
+ Event
-
- Instant Trim
+
+ Origin
-
- Play Sound
+
+ Comp
-
- Start Logs
+
+ Sub-Component
-
- Haptic
+
+ Field
-
-
-
- ---
+
+ Type
-
- Rud Trim
+
+ Old
-
- Ele Trim
+
+ Action
-
- Thr Trim
+
+ New
-
- Ail Trim
+
+ Seq
+
+
+ RadioInterface
-
- Rot Enc
-
-
-
-
- English
-
-
-
-
- French
-
-
-
-
- Italian
-
-
-
-
- German
-
-
-
-
- Czech
-
-
-
-
- Slovak
-
-
-
-
- Spanish
-
-
-
-
- Portuguese
-
-
-
-
- Swedish
-
-
-
-
- No repeat
-
-
-
-
- Reset
-
-
-
-
- mA
-
-
-
-
- kts
-
-
-
-
- f
-
-
-
-
- dB
-
-
-
-
- rpms
-
-
-
-
- hours
-
-
-
-
- minutes
-
-
-
-
- seconds
-
-
-
-
- h:m
-
-
-
-
- m:s
-
-
-
-
- h:m:s
-
-
-
-
-
- F1
-
-
-
-
-
- F2
-
-
-
-
-
- F3
-
-
-
-
-
- F4
-
-
-
-
-
- S3
-
-
-
-
-
-
- Timer3
-
-
-
-
- RSSI Tx
-
-
-
-
- RSSI Rx
-
-
-
-
- A3
-
-
-
-
- A4
-
-
-
-
- Cells
-
-
-
-
- dTE
-
-
-
-
- Hdg
-
-
-
-
- AirSpeed
-
-
-
-
- A3-
-
-
-
-
- A4-
-
-
-
-
- Speed+
-
-
-
-
- Dist+
-
-
-
-
- AirSpeed+
-
-
-
-
- Cell-
-
-
-
-
- Cells-
-
-
-
-
- Vfas-
-
-
-
-
- Curr+
-
-
-
-
- Powr+
-
-
-
-
- ACC
-
-
-
-
- GPS Time
-
-
-
-
-
- L1
-
-
-
-
-
- L2
-
-
-
-
-
- L3
-
-
-
-
-
- L4
-
-
-
-
-
- L5
-
-
-
-
-
- L6
-
-
-
-
-
- L7
-
-
-
-
-
- L8
-
-
-
-
-
- L9
-
-
-
-
-
- L10
-
-
-
-
-
- L11
-
-
-
-
-
- L12
-
-
-
-
-
- L13
-
-
-
-
-
- L14
-
-
-
-
-
- L15
-
-
-
-
-
- L16
-
-
-
-
-
- L17
-
-
-
-
-
- L18
-
-
-
-
-
- L19
-
-
-
-
-
- L20
-
-
-
-
-
- L21
-
-
-
-
-
- L22
-
-
-
-
-
- L23
-
-
-
-
-
- L24
-
-
-
-
-
- L25
-
-
-
-
-
- L26
-
-
-
-
-
- L27
-
-
-
-
-
- L28
-
-
-
-
-
- L29
-
-
-
-
-
- L30
-
-
-
-
-
- L31
-
-
-
-
-
- L32
-
-
-
-
- [I%1]
-
-
-
-
- LUA%1%2
-
-
-
-
- TR%1
-
-
-
-
- FM0
-
-
-
-
- FM1
-
-
-
-
- FM2
-
-
-
-
- FM3
-
-
-
-
- FM4
-
-
-
-
- FM5
-
-
-
-
- FM6
-
-
-
-
- FM7
-
-
-
-
- FM8
-
-
-
-
- S31
-
-
-
-
- S32
-
-
-
-
- S33
-
-
-
-
- S34
-
-
-
-
- S35
-
-
-
-
- S36
-
-
-
-
- RudTrim Left
-
-
-
-
- RudTrim Right
-
-
-
-
- EleTrim Down
-
-
-
-
- EleTrim Up
-
-
-
-
- ThrTrim Down
-
-
-
-
- ThrTrim Up
-
-
-
-
- AilTrim Left
-
-
-
-
- AilTrim Right
-
-
-
-
- THs
-
-
-
-
- TH%
-
-
-
-
- THt
-
-
-
-
- One
-
-
-
-
- ???
-
-
-
-
- a>x
-
-
-
-
- a<x
-
-
-
-
- |a|>x
-
-
-
-
- |a|<x
-
-
-
-
- AND
-
-
-
-
- OR
-
-
-
-
- XOR
-
-
-
-
- a=b
-
-
-
-
- a!=b
-
-
-
-
- a>b
-
-
-
-
- a<b
-
-
-
-
- a>=b
-
-
-
-
- a<=b
-
-
-
-
- d>=x
-
-
-
-
- |d|>=x
-
-
-
-
- a=x
-
-
-
-
- a~x
-
-
-
-
- Timer
-
-
-
-
- Sticky
-
-
-
-
- Unknown
-
-
-
-
- Override %1
-
-
-
-
- Set Timer %1
-
-
-
-
- Vario
-
-
-
-
- Play Track
-
-
-
-
- Play Both
-
-
-
-
- Play Value
-
-
-
-
- Play Script
-
-
-
-
- Volume
-
-
-
-
- Backlight
-
-
-
-
- Screenshot
-
-
-
-
- Background Music
-
-
-
-
- Background Music Pause
-
-
-
-
- played once, not during startup
-
-
-
-
- repeat(%1s)
-
-
-
-
- DISABLED
-
-
-
-
- INV
-
-
-
-
- NOR
-
-
-
-
- Edge
-
-
-
-
- SetFailsafe Int. Module
-
-
-
-
- SetFailsafe Ext. Module
-
-
-
-
- RangeCheck Int. Module
-
-
-
-
- RangeCheck Ext. Module
-
-
-
-
- Bind Int. Module
-
-
-
-
- Bind Ext. Module
-
-
-
-
-
-
- <font color=red><b>Inconsistent parameter</b></font>
-
-
-
-
- Value
-
-
-
-
- Decr:
-
-
-
-
- Incr:
-
-
-
-
- Played once, not during startup
-
-
-
-
- %1s
-
-
-
-
- Adjust GV%1
-
-
-
-
- Rotary Encoder
-
-
-
-
- Value
- Значение
-
-
-
- Source
- Источник
-
-
-
- GVAR
-
-
-
-
- Increment
-
-
-
-
- Flight
-
-
-
-
- Finnish
-
-
-
-
- !Flight mode %1
-
-
-
-
- Flight mode %1
-
-
-
-
- Flight mode %1 value
-
-
-
-
- Yellow
-
-
-
-
- Orange
-
-
-
-
- Red
-
-
-
-
- Winged Shadow How High
-
-
-
-
- Winged Shadow How High (not supported)
-
-
-
-
- FrSky Sensor Hub
-
-
-
-
- None
-
-
-
-
- Imperial
-
-
-
-
- Metric
-
-
-
-
-
-
- Timer1
-
-
-
-
-
-
- Timer2
-
-
-
-
- Telemetry
-
-
-
-
- Own value
-
-
-
-
- Keys
-
-
-
-
- Sticks
-
-
-
-
- Keys + Sticks
-
-
-
-
-
- -GV%1
-
-
-
-
-
-
-
- ----
-
-
-
-
-
-
- P1
-
-
-
-
-
-
- P2
-
-
-
-
-
-
- P3
-
-
-
-
- MAX
-
-
-
-
-
- Rud
-
-
-
-
-
- Ele
-
-
-
-
-
- Thr
-
-
-
-
-
- Ail
-
-
-
-
-
-
- REa
-
-
-
-
-
-
- REb
-
-
-
-
- Alt
-
-
-
-
- Rpm
-
-
-
-
- Fuel
-
-
-
-
- Speed
-
-
-
-
- Dist
-
-
-
-
- GPS Alt
-
-
-
-
- Cell
-
-
-
-
- A1
-
-
-
-
- A2
-
-
-
-
- T1
-
-
-
-
- T2
-
-
-
-
-
- Simultaneous usage of expo and curves is no longer supported
-
-
-
-
- TrmR
-
-
-
-
- TrmE
-
-
-
-
- TrmT
-
-
-
-
- TrmA
-
-
-
-
-
-
-
- S1
-
-
-
-
-
-
-
-
-
-
- V
-
-
-
-
-
- s
-
-
-
-
- ft
-
-
-
-
-
-
- m
-
-
-
-
-
- °C
-
-
-
-
-
- °
-
-
-
-
-
- %
-
-
-
-
-
-
- mph
-
-
-
-
-
-
- km/h
-
-
-
-
-
- m/s
-
-
-
-
-
- A
-
-
-
-
- °F
-
-
-
-
-
- mAh
-
-
-
-
-
- W
-
-
-
-
-
- g
-
-
-
-
-
-
-
- S2
-
-
-
-
-
-
-
- LS
-
-
-
-
-
-
-
- RS
-
-
-
-
-
- Batt
-
-
-
-
- SWR
-
-
-
-
- Vfas
-
-
-
-
- Curr
-
-
-
-
- Cnsp
-
-
-
-
- Powr
-
-
-
-
- AccX
-
-
-
-
- AccY
-
-
-
-
- AccZ
-
-
-
-
- VSpd
-
-
-
-
- A1-
-
-
-
-
- A2-
-
-
-
-
- Alt-
-
-
-
-
- Alt+
-
-
-
-
- Rpm+
-
-
-
-
- T1+
-
-
-
-
- T2+
-
-
-
-
-
- Time
-
-
-
-
- CYC%1
-
-
-
-
- S11
-
-
-
-
- S12
-
-
-
-
- S13
-
-
-
-
- S14
-
-
-
-
- S15
-
-
-
-
- S16
-
-
-
-
- S21
-
-
-
-
- S22
-
-
-
-
- S23
-
-
-
-
- S24
-
-
-
-
- S25
-
-
-
-
- S26
-
-
-
-
- Diff(%1)
-
-
-
-
- Expo(%1)
-
-
-
-
- Function(%1)
-
-
-
-
- Curve(%1)
-
-
-
-
- !Curve(%1)
-
-
-
-
-
-
- GV%1
-
-
-
-
- THR
-
-
-
-
-
-
- ON
-
-
-
-
-
-
- OFF
- ВЫКЛ
-
-
-
-
- Support for frsky telemetry mod
-
-
-
-
-
- Support for jeti telemetry mod
-
-
-
-
-
- Support for receiving ardupilot data
-
-
-
-
-
- Support for receiving NMEA data
-
-
-
-
- Support for telemetry easy board
-
-
-
-
-
- Support for MAVLINK devices
-
-
-
-
- Rotary Encoder use in menus navigation
-
-
-
-
-
-
-
-
-
- Enable heli menu and cyclic mix support
-
-
-
-
-
-
-
-
-
-
-
-
- Enable TEMPLATES menu
-
-
-
-
-
-
-
- No splash screen
-
-
-
-
-
-
-
-
-
-
-
-
- Disable curves menus
-
-
-
-
-
-
-
- Support for radio modified with regular speaker
-
-
-
-
-
-
-
-
- Used if you have modified your radio with voice mode
-
-
-
-
-
-
-
-
- Used if you have modified your radio with haptic mode
-
-
-
-
- Channel values displayed in us
-
-
-
-
-
-
-
-
-
-
-
-
- In model setup menus automatically set source by moving the control
-
-
-
-
-
-
-
-
-
-
-
-
- In model setup menus automatically set switch by moving the control
-
-
-
-
- Use alternative SQT5 font
-
-
-
-
- (displaying only first 10 warnings)
-
-
-
-
- Possibility to enable FAI MODE (no telemetry) at field
-
-
-
-
- FAI MODE (no telemetry) always enabled
-
-
-
-
-
-
-
- Support for a third timer
-
-
-
-
- Instead of Joystick emulation, USB connection is Mass Storage (as in the Bootloader)
-
-
-
-
- Instead of Joystick emulation, USB connection is Command Line Interface
-
-
-
-
- Removes D8 and LR12 FrSky protocols that are not legal for use in the EU on radios sold after Jan 1st, 2015
-
-
-
-
- Support for PPM internal module hack
-
-
-
-
- ST7565P LCD or compatible
-
-
-
-
- ST7565R LCD or compatible
-
-
-
-
- ERC12864FSF LCD
-
-
-
-
- ST7920 LCD
-
-
-
-
- 9X board
-
-
-
-
-
-
-
- Enable the throttle trace in Statistics
-
-
-
-
- EEprom write progress bar
-
-
-
-
-
- No Winged Shadow How High support
-
-
-
-
-
- No vario support
-
-
-
-
-
- No GPS support
-
-
-
-
-
- No gauges in the custom telemetry screen
-
-
-
-
- Allow compensating for offset errors in FrSky FAS current sensors
-
-
-
-
-
- Add support for reversing stick inputs (e.g. needed for FrSky gimbals)
-
-
-
-
- Power management by soft-off circuitry
-
-
-
-
- ar9x board / 9X
-
-
-
-
- 9XR-PRO
-
-
-
-
- FrSky Taranis
-
-
-
-
- FrSky Taranis Plus
-
-
-
-
- FrSky Taranis X9E
-
-
-
-
- Confirmation before radio shutdown
-
-
-
-
-
- Adds mixers output view to the CHANNELS MONITOR screen, pressing [ENT] switches between the views
-
-
-
-
- Haptic module installed
-
-
-
-
- Support for Lua model scripts
-
-
-
-
-
- Support of FrSky PXX protocol
-
-
-
-
- Disable HELI menu and cyclic mix support
-
-
-
-
- Disable Global variables
-
-
-
-
-
-
-
-
- Support for DSM2 modules
-
-
-
-
-
-
-
-
-
-
-
-
- PPM center adjustment in limits
-
-
-
-
-
-
-
-
-
-
-
-
- Symetrical Limits
-
-
-
-
-
-
-
-
-
-
- Pots use in menus navigation
-
-
-
-
- No OverrideCH functions available
-
-
-
-
-
-
-
-
-
-
-
-
- No flight modes
-
-
-
-
-
- SmartieParts 2.2 Backlight support
-
-
-
-
-
-
-
-
-
- Enable resetting values by pressing up and down at the same time
-
-
-
-
-
-
-
-
-
-
-
-
- No graphical check boxes and sliders
-
-
-
-
-
-
-
-
-
-
-
-
- Battery graph
-
-
-
-
-
-
-
-
-
-
-
-
- Don't use bold font for highlighting active items
-
-
-
-
-
-
-
-
- EEprom write Progress bar
-
-
-
-
-
-
-
-
-
- Imperial units
-
-
-
-
- M128 / 9X board
-
-
-
-
- 9XR
-
-
-
-
- 9XR with M128 chip
-
-
-
-
- Gruvin9x board / 9X
-
-
-
-
- MEGA2560 board
-
-
-
-
- Sky9x board / 9X
-
-
-
-
-
-
- Bluetooth interface
-
-
-
-
-
-
-
-
-
-
-
-
- Global variables
-
-
-
-
-
- Support for SD memory card
-
-
-
-
- Support for DSM2 modules using ppm instead of true serial
-
-
-
-
-
-
- Enable HELI menu and cyclic mix support
-
-
-
-
-
- Warning
- Звук
-
-
-
- EEPROM saved with these warnings:
-
-
-
-
- Simulator for this firmware is not yet available
-
-
-
-
- th9x on this board doesn't have Rotary Encoders
-
-
-
-
- Source %1 cannot be exported on this board!
-
-
-
-
- OpenTX only accepts %1 points in all curves
-
-
-
-
- OpenTx only accepts %1 points in all curves
-
-
-
-
-
-
-
-
- OpenTX on this board doesn't accept this function
-
-
-
-
- OpenTX doesn't accept this telemetry protocol
-
-
-
-
-
-
- OpenTX doesn't accept this radio protocol
-
-
-
-
- OpenTX doesn't allow this number of channels
-
-
-
-
- Trim disabled
-
-
-
-
- Own Trim
-
-
-
-
- Use Trim from Flight mode %1
-
-
-
-
- Use Trim from Flight mode %1 + Own Trim as an offset
-
-
-
-
- FW: %1
-
-
-
-
- Pict: %1
-
-
-
-
- Profile image
-
-
-
-
- Simultaneous usage of expo and curves is no longer supported in OpenTX
-
-
-
-
- Thank you for upgrading to OpenTX 2.0. This is a major upgrade that adds and modifies a lot of things, so please make sure that you read release notes carefully to learn about the changes, and thoroughly check each of your models for proper function.
-
-The OpenTX Team.
-
-
-
-
-
-
-
-
- Synchronization error
-
-
-
-
- No SD directory configured!
-
-
-
-
- No Radio connected!
-
-
-
-
- GV
-
-
-
-
- -%1
-
-
-
-
-
- The directory '%1' doesn't exist!
-
-
-
-
- Create '%1' failed
-
-
-
-
- Copy '%1' to '%2' failed
-
-
-
-
- Open '%1' failed
-
-
-
-
- Write '%1' failed
-
-
-
-
-
-
- Error
- Ошибка
-
-
-
+
Cannot write file %1:
%2.
Не удается записать файл %1:
%2.
-
- Companion
-
-
-
-
+
<b><u>WARNING!</u></b><br>This will reset the fuses of %1 to the factory settings.<br>Writing fuses can mess up your radio.<br>Do this only if you are sure they are wrong!<br>Are you sure you want to continue?
-
-
+
+
Could not delete temporary file: %1
-
- Radio type
+
+ Unable to find Horus radio SD card!
+
+
+
+
+ RadioKnobWidget
+
+
+ <p>Value (input): <b>%1</b></p>
-
- Which radio type do you want to simulate?
+
+ Right-double-click to reset to center.
@@ -8351,10 +9833,712 @@ The OpenTX Team.
+
+ RadioOutputsWidget
+
+
+ Form
+
+
+
+
+ View:
+
+
+
+
+ Logical Switches
+
+
+
+
+ Global Variables
+
+
+
+
+ Channel Outputs
+
+
+
+
+ Mix Outputs
+
+
+
+
+ L
+o
+g
+i
+c
+
+
+
+
+ G
+l
+o
+b
+a
+l
+
+
+
+
+ C
+h
+a
+n
+n
+e
+l
+s
+
+
+
+
+ M
+i
+x
+e
+s
+
+
+
+
+ FM%1
+
+
+
+
+ GV%1
+
+
+
+
+ RadioSwitchWidget
+
+
+ Latch/unlatch the momentary switch.
+
+
+
+
+ RawSource
+
+
+
+
+
+ V
+
+
+
+
+
+
+
+ s
+
+
+
+
+ ft
+
+
+
+
+
+ m
+
+
+
+
+ °C
+
+
+
+
+ °
+
+
+
+
+ %
+
+
+
+
+
+ mph
+
+
+
+
+
+ km/h
+
+
+
+
+ m/s
+
+
+
+
+ A
+
+
+
+
+ mAh
+
+
+
+
+ W
+
+
+
+
+ g
+
+
+
+
+ TrmR
+
+
+
+
+ TrmE
+
+
+
+
+ TrmT
+
+
+
+
+ TrmA
+
+
+
+
+ Trm5
+
+
+
+
+ Trm6
+
+
+
+
+ TrmH
+
+
+
+
+ TrmV
+
+
+
+
+
+ Batt
+
+
+
+
+
+ Time
+
+
+
+
+
+ Timer1
+
+
+
+
+
+ Timer2
+
+
+
+
+
+ Timer3
+
+
+
+
+ RAS
+
+
+
+
+ RSSI Tx
+
+
+
+
+ RSSI Rx
+
+
+
+
+ A1
+
+
+
+
+ A2
+
+
+
+
+ A3
+
+
+
+
+ A4
+
+
+
+
+ Alt
+
+
+
+
+ Rpm
+
+
+
+
+ Fuel
+
+
+
+
+ T1
+
+
+
+
+ T2
+
+
+
+
+ Speed
+
+
+
+
+ Dist
+
+
+
+
+ GPS Alt
+
+
+
+
+ Cell
+
+
+
+
+ Cells
+
+
+
+
+ Vfas
+
+
+
+
+ Curr
+
+
+
+
+ Cnsp
+
+
+
+
+ Powr
+
+
+
+
+ AccX
+
+
+
+
+ AccY
+
+
+
+
+ AccZ
+
+
+
+
+ Hdg
+
+
+
+
+ VSpd
+
+
+
+
+ AirSpeed
+
+
+
+
+ dTE
+
+
+
+
+ A1-
+
+
+
+
+ A2-
+
+
+
+
+ A3-
+
+
+
+
+ A4-
+
+
+
+
+ Alt-
+
+
+
+
+ Alt+
+
+
+
+
+ Rpm+
+
+
+
+
+ T1+
+
+
+
+
+ T2+
+
+
+
+
+ Speed+
+
+
+
+
+ Dist+
+
+
+
+
+ AirSpeed+
+
+
+
+
+ Cell-
+
+
+
+
+ Cells-
+
+
+
+
+ Vfas-
+
+
+
+
+ Curr+
+
+
+
+
+ Powr+
+
+
+
+
+ ACC
+
+
+
+
+ GPS Time
+
+
+
+
+ REa
+
+
+
+
+ REb
+
+
+
+
+
+ ???
+
+
+
+
+ ----
+
+
+
+
+ I
+ as in Input
+
+
+
+
+ LUA%1%2
+
+
+
+
+ MAX
+
+
+
+
+ CYC%1
+
+
+
+
+ TR
+ as in Trainer
+
+
+
+
+ SRC
+
+
+
+
+ RawSwitch
+
+
+ ↑
+
+
+
+
+ ↓
+
+
+
+
+ -
+
+
+
+
+ !
+
+
+
+
+ RudTrim Left
+
+
+
+
+ RudTrim Right
+
+
+
+
+ EleTrim Down
+
+
+
+
+ EleTrim Up
+
+
+
+
+ ThrTrim Down
+
+
+
+
+ ThrTrim Up
+
+
+
+
+ AilTrim Left
+
+
+
+
+ AilTrim Right
+
+
+
+
+ Trim 5 Down
+
+
+
+
+ Trim 5 Up
+
+
+
+
+ Trim 6 Down
+
+
+
+
+ Trim 6 Up
+
+
+
+
+ TrmH Left
+
+
+
+
+ TrmH Right
+
+
+
+
+ TrmV Down
+
+
+
+
+ TrmV Up
+
+
+
+
+ REa
+
+
+
+
+ REb
+
+
+
+
+
+ OFF
+ ВЫКЛ
+
+
+
+
+ ON
+
+
+
+
+ THs
+
+
+
+
+ TH%
+
+
+
+
+ THt
+
+
+
+
+
+ ???
+
+
+
+
+ One
+
+
+
+
+ Act
+
+
+
+
+ ----
+
+
+
+
+ Telemetry
+
+
+
+
+ SW
+
+
+
ReleaseNotesDialog
-
+
Companion Release Notes
@@ -8362,26 +10546,183 @@ The OpenTX Team.
ReleaseNotesFirmwareDialog
-
+
OpenTX Release Notes
+
+ RepeatComboBox
+
+
+ Played once, not during startup
+
+
+
+
+ No repeat
+
+
+
+
+ %1s
+
+
+
RudderPage
-
-
- No
-
-
-
-
- Yes
-
-
+ No
+ Нет
+
+
+
+ Yes
+ Есть
+
+
+
<br>Rudder Channel:
+ Канал руля направления:
+
+
+
+ SdcardFormat
+
+
+ Error opening file %1:
+%2.
+
+
+
+
+ Error opening file %1 in write mode:
+%2.
+
+
+
+
+ SensorData
+
+
+
+ V
+
+
+
+
+ A
+
+
+
+
+ mA
+
+
+
+
+ kts
+
+
+
+
+ m/s
+
+
+
+
+ km/h
+
+
+
+
+ mph
+
+
+
+
+ m
+
+
+
+
+ f
+
+
+
+
+ °C
+
+
+
+
+ °F
+
+
+
+
+ %
+
+
+
+
+ mAh
+
+
+
+
+ W
+
+
+
+
+ mW
+
+
+
+
+ dB
+
+
+
+
+ rpms
+
+
+
+
+ g
+
+
+
+
+ °
+
+
+
+
+ Rad
+
+
+
+
+ hours
+
+
+
+
+ minutes
+
+
+
+
+ seconds
+
+
+
+
+ TELE
@@ -8390,350 +10731,977 @@ The OpenTX Team.
Center beep
- Бип в центре
+ Сигнал в центре
OFF
- ВЫКЛ
+ ВЫКЛ
Model Image
-
+ Изображение модели
-
+
Exponential
- экспонента
+ По экспоненте
-
+
Throttle Trim Idle Only
-
+ Триммировать только холостой ход
-
+
Extra Fine
- очень точно
+ Очень точно
-
+
Fine
- точно
+ Точно
-
+
Medium
- средне
+ Средне
-
+
Coarse
- грубо
+ Грубо
-
+
Display Checklist
-
+ Показать контрольную карту
-
+
Timer 2
-
+ Таймер 2
Timer 1
-
+ Таймер 1
-
+
Timer 3
-
+ Таймер 3
-
+
Never
-
+ Никогда
Top LCD Timer
-
+ Верхний таймер
-
+
On change
-
+ При изменении
-
+
Always
-
+ Всегда
-
+
Global Functions
-
+ Глобальные функции
-
+
+ Edit Checklist...
+ Редактировать...
+
+
+
Throttle Source
-
+ Канал газа
-
+
Trim Step
-
+ Шаг триммирования
-
+
Trims Display
-
+ Показывать триммеры
Warnings
-
+ Предупреждения
Switch Warnings
-
+ Тумблеры
Pot Warnings
-
+ Крутилки
Manual
-
+ Вручную
Auto
-
+ Автоматически
Model
-
+ Модель
-
+
Extended Limits
- Расш. лимиты
+ Расширенные лимиты
-
+
Extended Trims
-
+ Расширенные триммеры
-
+
Throttle Warning
-
+ Предупреждать если не убран
-
+
Reverse throttle operation.
If this is checked the throttle will be reversed. Idle will be forward, trim will also be reversed and the throttle warning will be reversed as well.
- Реверсировать канал газа (а также триммеры и предупреждения)
+ Реверс газа
+Если выбрана эта опция, то будет включен реверс газа, холостого хода и триммеров. Предупреждение о не нулевом положении стика газа также будет инвертировано.
+
+
-
+
Reverse Throttle
-
+ Реверс газа
SetupPanel
-
+
Timer %1
+
+
+ THR
+
+
+
+
+ Profile Settings
+
+
+
+
+ SD structure path not specified or invalid
+
+
SimpleTailPage
-
+
Elevator Channel:
+ Канал руля высоты:
+
+
+
+ SimulatedUIWidget
+
+
+ screenshot
+ Simulator LCD screenshot file name prefix
+
+
+
+
+ ENTER
+
+
+
+
+ S
+
+
+
+
+ PG-UP
+
+
+
+
+ PG-DN
+
+
+
+
+ DEL
+
+
+
+
+ BKSP
+
+
+
+
+ ESC
+
+
+
+
+ INS
+
+
+
+
+ <font size=+3>+</font>
+
+
+
+
+ <font size=+3>-</font>
+
+
+
+
+ <font size=+3>←</font>
+
+
+
+
+ <font size=+3>→</font>
+
+
+
+
+ <font size=+3>↑</font>
+
+
+
+
+ <font size=+3>↓</font>
+
+
+
+
+ <font size=+3>⚆</font>
+
+
+
+
+ <font size=+3>↶</font>
+
+
+
+
+ <font size=+3>↷</font>
+
+
+
+
+ <font size=+3>⇆</font>
+
+
+
+
+
+ <font size=+3>⇓</font>
+
+
+
+
+ <font size=+3>⇑</font>
+
+
+
+
+ <font size=+3>⇕</font>
+
+
+
+
+ <img src='qrc:/images/simulator/icons/svg/mouse.svg' width=20 height=18 />
+
+
+
+
+ <img src='qrc:/images/simulator/icons/svg/arrow_click.svg' width=18 height=18 />
+
+
+
+
+ <pre>[ MENU ]</pre>
+
+
+
+
+ <pre>[ PAGE ]</pre>
+
+
+
+
+ <pre>[ EXIT ]</pre>
+
+
+
+
+ <pre>[ ENT ]</pre>
+
+
+
+
+ <pre>[ SHIFT ]</pre>
+
+
+
+
+ <pre>[ UP ]</pre>
+
+
+
+
+ <pre>[ DN ]</pre>
+
+
+
+
+ <pre>[ <font size=+2>+</font> ]</pre>
+
+
+
+
+ <pre>[ <font size=+2>-</font> ]</pre>
+
+
+
+
+ <pre>[ PgUp ]</pre>
+
+
+
+
+ <pre>[ PgDn ]</pre>
+
+
+
+
+ <pre>[ MDL ]</pre>
+
+
+
+
+ <pre>[ RTN ]</pre>
+
+
+
+
+ <pre>[ SYS ]</pre>
+
+
+
+
+ <pre>[ TELE ]</pre>
+
+
+
+
+ <font size=+3>≡</font>
- SimulatorDialog
+ SimulatorMain
-
-
- Warning
- Звук
-
-
-
- Joystick enabled but not configured correctly
+
+ OpenTx Simulator
-
+
+ Available profiles:
+
+
+
+
+ ID:
+
+
+
+
+ Name:
+
+
+
+
+ Available radios:
+
+
+
+
+ Radio profile ID or Name to use for simulator.
+
+
+
+
+ profile
+
+
+
+
+ Radio type to simulate (usually defined in profile).
+
+
+
+
+ radio
+
+
+
+
+ Directory containing the SD card image to use. The default is configured in the chosen Radio Profile.
+
+
+
+
+ path
+
+
+
+
+ Data source type to use (applicable to Horus only). One of:
+
+
+
+
+ type
+
+
+
+
+ data-source
+
+
+
+
+ Radio data (.bin/.eeprom/.otx) image file to use OR data folder path (for Horus-style radios).
+NOTE: any existing EEPROM data incompatible with the selected radio type may be overwritten!
+
+
+
+
+ [data-source]
+
+
+
+
+ Error: Profile ID %1 was not found.
+
+
+
+
+ Unrecognized startup data source type: %1
+
+
+
+
+ WARNING: couldn't initialize SDL:
+%1
+
+
+
+
+ ERROR: No simulator libraries available.
+
+
+
+
+ ERROR: Couldn't start simulator, missing radio/profile/data file/folder.
+ Profile ID: [%1]; Radio ID: [%2];
+Data File: [%3]
+
+
+
+
+ ERROR: Radio profile or simulator firmware not found.
+Profile ID: [%1]; Radio ID: [%2]
+
+
+
+
+ Uknown error during Simulator startup.
+
+
+
+
+ SimulatorMainWindow
+
+
+ OpenTx Simulator
+
+
+
+
+ View
+
+
+
+
+ Radio Window
+
+
+
+
+ Reload...
+
+
+
+
+ Tools
+
+
+
+
+ Toolbar
+
+
+
+
+ Reload Lua Scripts
+
+
+
+
+ Reload the Lua environment on the simulated radio.
+
+
+
+
+ F7
+
+
+
+
+ Reload Radio Data
+
+
+
+
+ Reload all radio data without restarting the simulator.
+
+
+
+
+ F9
+
+
+
+
+ Key Mapping
+
+
+
+
+ Show keyboard maping reference.
+
+
+
+
+ F1
+
+
+
+
+ Joystick Settings
+
+
+
+
+ Open joystick configuration settings dialog.
+
+
+
+
+ F3
+
+
+
+
+ LCD Screenshot
+
+
+
+
+ Save a screenshot of the current simulated LCD screen.
+
+
+
+
+ F8
+
+
+
+
+ Dock In Main Window
+
+
+
+
+ Show the radio in the main window or as a separate "floating" window.
+
+
+
+
+ Menu Bar
+
+
+
+
+ Show or hide the top menu bar.
+
+
+
+
+ Alt+M
+
+
+
+
+ Constrain Width
+
+
+
+
+ Set radio widget width to be a fixed size.
+
+
+
+
+ Constrain Height
+
+
+
+
+ Set radio widget height to be a fixed size.
+
+
+
+
+ ERROR: Failed to create simulator interface, possibly missing or bad library.
+
+
+
+
+ Alt+T
+
+
+
+
+ Radio Outputs
+
+
+
+
+ F2
+
+
+
+
+ Telemetry Simulator
+
+
+
+
+ F4
+
+
+
+
+ Trainer Simulator
+
+
+
+
+ F5
+
+
+
+
+ Debug Output
+
+
+
+
+ F6
+
+
+
+
+ <b>Simulator Controls:</b>
+
+
+
+
+ <tr><th>Key/Mouse</th><th>Action</th></tr>
+ note: must match html layout of each table row (keyTemplate).
+
+
+
+
+ <tr><td><kbd>%1</kbd></td><td>%2</td></tr>
+ note: must match html layout of help text table header.
+
+
+
+
+ Simulator Help
+
+
+
+
+ SimulatorStartupDialog
+
+
+ OpenTX Simulator - Startup Options
+ Настройки симулятора OpenTX
+
+
+
+ Simulator Startup Options:
+
+
+
+
+ Radio Profile:
+ Профиль передатчика:
+
+
+
+ Existing radio profiles are shown here.<br />
+Create or edit profiles using the Companion application.
+
+
+
+
+ Radio Type:
+ Тип передатчика:
+
+
+
+ Existing radio simulators are shown here.<br />
+The radio type specified in the selected profile is used by default.
+
+
+
+
+ Data Source:
+ Источник данных:
+
+
+
+ Data File:
+ Файл с данными:
+
+
+
+ Data Folder:
+ Папка с данными:
+
+
+
+ SD Image Path:
+ Папка с образом SD:
+
+
+
+ Radio data (.bin/.eeprom/.otx) image file to use. A new file with a default image will be created if necessary.<br />
+<b>NOTE</b>: any existing EEPROM data incompatible with the selected radio type may be overwritten!
+
+
+
+
+ Select data file...
+
+
+
+
+
+
+ ...
+ ...
+
+
+
+ Directory containing RADIO and MODELS folders to use.<br />
+New folder(s) with default radio/model will be created here if necessary.
+
+
+
+
+ Select data folder...
+ Выберите папку с данными...
+
+
+
+ Directory containing the SD card image to use.<br/>
+The default is configured in the chosen Radio Profile.
+
+
+
+
+ Select SD card image folder...
+
+
+
+
+ Select which of the data sources (File/Folder/SD Card) you would like to start the simulator with.
+
+
+
+
+ File
+ Файл
+
+
+
+ Folder
+ Папка
+
+
+
+ SD Path
+ Путь к SD
+
+
+
+ All files (*.*)
+ Все файлы (*.*)
+
+
+
+ Select a data file
+ Выбор файла с данными моделей
+
+
+
+ Select Data Directory
+
+
+
+
+ Select SD Card Image Folder
+
+
+
+
+ SimulatorWidget
+
+
+ Companion Simulator
+
+
+
+
+ Radio Simulator (%1)
+
+
+
+
+ Could not determine startup data source.
+
+
+
+
+ Could not load data, possibly wrong format.
+
+
+
+
+ Data Load Error
+
+
+
+
+ Invalid startup data provided. Plese specify a proper file/path.
+
+
+
+
+ Simulator Startup Error
+
+
+
+
+ Error saving data: could open file for writing: '%1'
+
+
+
+
+ Error saving data: could not get data from simulator interface.
+
+
+
+
+ An unexpected error occurred while attempting to save radio data to file '%1'.
+
+
+
+
+ Data Save Error
+
+
+
+
Cannot open joystick, joystick disabled
-
- Simulating Radio (%1)
+
+ Radio firmware error: %1
-
-
- Outputs
-
-
-
-
- Firmware %1 error: %2
+
+ - Flight Mode %1 (#%2)
- SimulatorDialog9X
+ SliderWidget
-
- Companion Simulator
+
+ <p>Value (input): <b>%1</b></p>
-
-
-
-
- Right Double Click to Reset
-
-
-
-
-
- Hold X
-
-
-
-
-
- Fix X
-
-
-
-
-
- Fix Y
-
-
-
-
-
- Hold Y
-
-
-
-
- BEEP
-
-
-
-
- 9x Simulator
-
-
-
-
- Outputs
-
-
-
-
- Outputs2
-
-
-
-
- Gvars
-
-
-
-
- SimulatorDialogTaranis
-
-
- Companion Simulator
-
-
-
-
- Outputs2
-
-
-
-
- Gvars
-
-
-
-
- S3
-
-
-
-
- S4
-
-
-
-
-
- Hold Y
-
-
-
-
-
- Fix Y
-
-
-
-
-
- Fix X
-
-
-
-
-
- Hold X
-
-
-
-
-
-
-
- Right Double Click to Reset
-
-
-
-
- Taranis Simulator
-
-
-
-
- Outputs
+
+ Right-double-click to reset to center.
@@ -8743,30 +11711,20 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
...
-
+ ...
-
+
Splash Library - page %1 of %2
-
- Warning
- Звук
-
-
-
+
Invalid image in library %1
-
- Information
-
-
-
-
+
No valid image found in library, check your settings
@@ -8774,256 +11732,491 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
StandardPage
-
+
Channel %1
+
+ Storage
+
+
+ Unable to find file %1!
+ Невозможно найти файл %1!
+
+
+
+ StyleEditDialog
+
+
+
+
+
+ Style Sheet Editor
+
+
+
+
+ &Reset to default
+
+
+
+
+ &Cancel
+
+
+
+
+ &OK
+
+
+
+
+ This feature does not validate your changes and assumes you are familiar with CSS syntax for QT.
+
+
+
+
+ Cannot retrieve style %1
+Error: %2
+
+
+
+
+ Cannot retrieve default style %1
+Error: %2
+
+
+
+
+ Cannot update custom style %1
+Error: %2
+
+
+
+
+ Stylesheet
+
+
+ Style sheet data read from '%1'
+
+
+
+
+ Style sheet data unable to be read from '%1'
+
+
+
+
+ Cannot create folder '%1'
+
+
+
+
+ Cannot open file for writing '%1': Error: %2
+
+
+
+
+ Cannot write to file '%1': Error: %2
+
+
+
+
+ Cannot flush buffer for file '%1': Error: %2
+
+
+
+
+ Style sheet written to '%1'
+
+
+
+
+ Custom style sheet deleted: '%1'
+
+
+
+
+ Unable to delete custom style sheet: '%1'
+
+
+
SyncProcess
-
- %1/%2 files
-
+
+ [TEST RUN]
+ [ТЕСТОВЫЙ ЗАПУСК]
-
- Create directory %1
-
-
+
+ Gathering file information for %1...
+ Собираем информацию о %1...
-
- Copy %1 to %2
-
-
+
+ No files found in %1
+ Файлы не найдены: %1
-
- Write %1
+
+ Synchronization failed, nothing found to copy.
+ Ошибка синхронизации, файлы не найдены.
+
+
+
+ Synchronization aborted at %1 of %2 files.
+ Синхронизация остановлена. Обработано %1 из %2.
+
+
+
+ Synchronization finished with %1 files in %2m %3s.
+ Синхронизация завершена %1 файлов за %2 мин %3 с.
+
+
+
+ Synchronizing: %1
+ To: %2
+ Синхронизация: %1
+ в: %2
+
+
+
+ Starting synchronization:
+ %1 -> %2
-
+ Начинаем синхронизацию:
+ %1 -> %2
+
+
+
+
+
+Too many errors, giving up.
+
+Слишком много ошибок.
+
+
+
+ Skipping large file: %1 (%2KB)
+ Пропускаем большой файл: %1 (%2КБ)
+
+
+
+ Skipping filtered file: %1
+ Пропускаем файл из-за фильтра: %1
+
+
+
+ Skipping linked file: %1
+ Пропускаем ссылку на %1
+
+
+
+ Aborted synchronization of:
+ Синхронизация прервана:
+
+
+
+ Finished synchronizing:
+ Синхронизация завершена:
+
+
+
+ Created: %1; Updated: %2; Skipped: %3; Errors: %4;
+ Создано: %1; Обновлено: %2; Пропущено: %3; Ошибок: %4;
+
+
+
+ Creating directory: %1
+ Создаем папку: %1
+
+
+
+ Could not create directory: %1
+ Невозможнос создать папку %1
+
+
+
+ Directory exists: %1
+ Папка уже существует: %1
+
+
+
+ At least one of the file modification dates is in the future, error on: %1
+ Как минимум у одного файла дата модификации в будущем, ошибка: %1
+
+
+
+ Skipping older file: %1
+ Пропускаем старый файл: %1
+
+
+
+ Could not open source file '%1': %2
+ Невозможно открыть файл '%1': %2
+
+
+
+ Could not open destination file '%1': %2
+ Невозможно открыть файл в папке передатчика: '%1': %2
+
+
+
+ Skipping identical file: %1
+ Пропускаем одинаковые файлы: %1
+
+
+
+ Replacing file: %1
+ Заменяем файл: %1
+
+
+
+ Could not delete destination file '%1': %2
+ Невозможнос удалить файл в папке передатчика e '%1': %2
+
+
+
+ Creating file: %1
+ Создаем файл: %1
+
+
+
+ Copy failed: '%1' to '%2': %3
+ Ошибка копирования: '%1' в '%2': %3
TailPage
-
+
Rudder Channel:
-
+ Руль направления:
-
+
Elevator Channel:
-
+ Руль высоты:
-
+
Only one channel still available!<br>You probably should configure your model without using the wizard.
-
+ Доступен только один канал!<br>Возможно стоит настроить модель без использования этого мастера.
TailSelectionPage
-
+
Elevator and Rudder
-
+ Руль высоты и руль направления
-
+
Only Elevator
-
+ Только руль высоты
-
+
V-tail
-
+ V-образное оперение
-
+
Tail Type:
-
+ Тип хвостового оперения:
Telemetry
-
+
A1
-
+
A2
-
+
RSSI
-
+
Alarm 1
-
-
+
+
----
-
-
+
+
Yellow
-
-
+
+
Orange
-
-
+
+
Red
-
+
+ Disable telemetry audio warnings
+ Отключить головые предупреждения
+
+
+
Alarm 2
-
- Center Silent
-
+
+ Source
+ Источник
-
+
+ Center Silent
+ Тишина в центре
+
+
+
Altitude source
-
+
Volts source
-
+
Top Bar
-
+ Верхняя строка
-
+
Serial Protocol
-
+
Sensors
-
+
Disable multi sensor handling
-
+
Volt source
-
+ Напряжение
-
+
Current source
-
+ Датчик тока
Protocol
- Протокол
+ Протокол
-
+
None
-
+
FrSky Sensor Hub
-
+
Blades
-
+
Sink Max
-
+ Сниж. макс.
-
+
Climb Max
-
+ Набор макс.
-
+
Sink Min
-
+ Сниж. мин.
-
+
Climb Min
-
+ Набор мин.
-
+
Vario source
-
+ Вариометр
-
+
Vario limits
-
+ Пределы
-
+
Altimetry
-
+ Измерение высоты
-
+
mAh
-
+
A
-
+
Various
-
+
mAh count
-
+
FAS Offset
-
+
Persistent mAh
@@ -9055,19 +12248,19 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
Yellow
-
+ Желтая
Orange
-
+ Оранжевая
Red
-
+ Красная
@@ -9121,7 +12314,7 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
Meters (m or ft)
-
+
Temp (°)
@@ -9137,7 +12330,7 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
-
+
Range
@@ -9150,22 +12343,22 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
-
+
None
-
+
Numbers
-
+
Bars
-
+
Script
@@ -9193,99 +12386,104 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
TelemetryPanel
-
+
FrSky S.PORT
-
+
FrSky D
-
+
FrSky D (cable)
-
+
Telemetry screen %1
-
+
+ Source
+ Источник
+
+
+
Low Alarm
-
+ Низкий уровень
-
+
Critical Alarm
-
+ Критический уровень
-
+
Winged Shadow How High
-
+
Winged Shadow How High (not supported)
-
+
Alti
-
+
Alti+
-
+
VSpeed
-
-
-
+
+
+
A1
-
-
-
+
+
+
A2
-
-
+
+
A3
-
-
+
+
A4
-
-
+
+
FAS
-
+
Cells
-
+
---
@@ -9298,259 +12496,274 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
-
+
Custom
-
+
Calculated
-
+
Id
-
+
Instance
-
+
+ Rx
+
+
+
+
Add
-
+
Average
-
+
Min
Мин
-
+
Max
Макс
-
+
Multiply
-
+
Totalize
-
+
Cell
-
+
Consumption
-
+
Dist
-
+
Cells Sensor :
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
---
-
+
GPS Sensor :
-
+
Alt. Sensor :
-
+
Sensor :
-
+
V
-
+
A
-
+
mA
-
+
kt
-
+
m/s
-
+
ft/s
-
+
km/h
-
+
mph
-
+
m
-
+
ft
-
-
+
+
°C
-
-
+
+
°F
-
+
%
-
+
mAh
-
+
W
-
+
+ mW
+
+
+
+
dBm
-
+
g
-
-
+
+
°
-
- mL
-
-
-
-
- US fl.Oz.
-
-
-
-
- Raw (-)
-
-
-
-
- RPM
-
-
-
-
- Precision
+
+ Rad
+ mL
+
+
+
+
+ US fl.Oz.
+
+
+
+
+ Raw (-)
+
+
+
+
+ RPM
+
+
+
+
+ Precision
+
+
+
+
Ratio
-
+
Blades
-
+
Offset
- Смещен.
+
-
+
Multiplier
-
+
Auto Offset
-
+
Filter
-
+
Persistent
-
+
Positive
-
+
Logs
@@ -9558,22 +12771,22 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
TelemetrySensorPanel
-
+
Lowest
-
+
Cell %1
-
+
Highest
-
+
Delta
@@ -9581,242 +12794,361 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
TelemetrySimulator
-
+
Telemetry Simulator
-
- Vario Altitude
-
-
-
-
- V-ALT
-
-
-
-
- Vario Vertical Speed
-
-
-
-
- V-VSPD
-
-
-
-
- ACCZ
-
-
-
-
- GPS Time
-
-
-
-
- GPS-T
-
-
-
-
- ACCX
-
-
-
-
- GPS Lat/Lon
-
-
-
-
- GPS-LL
-
-
-
-
+
VFAS
-
- FAS-V
-
-
-
-
- GPS Speed
-
-
-
-
- GPS-S
-
-
-
-
- CELLS
-
-
-
-
- ACCY
-
-
-
-
- GPS Course
-
-
-
-
- GPS-C
-
-
-
-
- GPS Altitude
-
-
-
-
- GPS-A
-
-
-
-
- CURRENT
-
-
-
-
- FAS-C
-
-
-
-
- 30
-
-
-
-
+
RSSI
-
- 75
-
-
-
-
- SWR
-
-
-
-
- FR_ID_AIR_SPEED
-
-
-
-
- ASPD
-
-
-
-
+
A1
-
+
A2
-
+
+ Simulate
+
+
+
+
+ RAS
+
+
+
+
+
+
+ V / ratio
+
+
+
+
+ Db
+
+
+
+
+ RxBt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <html><head/><body><p><br/></p></body></html>
+
+
+
+
+ Tmp1
+
+
+
+
A3
-
+
A4
-
- Temperature 1
+
+ Tmp2
-
- T1
+
+ Fuel
-
- Temperature 2
+
+
+ °C
-
- T2
+
+ ml
-
+
+ %
+
+
+
+
+
+ Meters
+
+
+
+
+ Alt
+
+
+
+
+ VSpd
+
+
+
+
+ m/s
+
+
+
+
+ Fuel Qty
+
+
+
+
+
+ km/h
+
+
+
+
+ Hdg
+
+
+
+
+ ASpd
+
+
+
+
+
+
+ G
+
+
+
+
+ GPS
+
+
+
+
+ Lat,Lon
+(dec.deg.)
+
+
+
+
+ AccX
+
+
+
+
+ dd-MM-yyyy
+hh:mm:ss
+
+
+
+
+ Date
+
+
+
+
+ Amps
+
+
+
+
+ AccZ
+
+
+
+
+ GAlt
+
+
+
+
+
+ Volts
+
+
+
+
+ Cels
+
+
+
+
+ Curr
+
+
+
+
+ AccY
+
+
+
+
+ GSpd
+
+
+
+
+ Degrees
+
+
+
+
+ Replay SD Log File
+
+
+
+
+ Replay rate
+
+
+
+
+ Load
+
+
+
+
+ |>
+
+
+
+
+ <|
+
+
+
+
+ >
+
+
+
+
+ <-
+
+
+
+
+ X
+
+
+
+
+ Row #
+Timestamp
+
+
+
+
+ 1/5x
+
+
+
+
+ 5x
+
+
+
+
+ No Log File Currently Loaded
+
+
+
+
+ Setting RSSI to zero simulates telemetry and radio link loss.
+
+
+
+
+ Set RSSI to zero when paused.
+
+
+
+
+ Stop sending telemetry data when the Telemetry Simulator window is hidden.
+
+
+
+
+ Pause simulation when hidden.
+
+
+
+
+
RPM
-
- FUEL
-
-
-
-
+
When enabled, sends any non-blank values as simulated telemetry data.
-
- simulate
+
+ Log File
-
- Instance
+
+ LOG Files (*.csv)
-
- 2
-
-
-
-
- <html><head/><body><p>Start with <span style=" font-style:italic;">0x</span> for hex, <span style=" font-style:italic;">0</span> for octal, otherwise decimal.<br/>Numeric entry only. Blank values are not sent.</p></body></html>
+
+ ERROR - invalid file
ThrottlePage
-
+
Yes
-
+ Да
-
+
No
-
+ Нет
-
+
<br>Throttle Channel:
-
+ Канал газа:
@@ -9824,50 +13156,88 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
Countdown
-
+ Отсчет
Minute Call
+ Ежеминутный сигнал
+
+
+
+ TimerData
+
+
+ TMR
+
+
+ Timer %1
+ Таймер %1
+
+
+
+ TimerEdit
+
+
+ Use mouse scroll or UP/DOWN arrow keys to change time in small steps.
+CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps.
+ Используйте колесо мыши или стрелки ВВЕРХ/ВНИЗ для изменений с небольшим шагом
+CTRL+колесо или PAGE UP/DOWN - для изменения с большим шагом.
+
+
+
+ m
+ м
+
+
+
+ h
+ ч
+
+
+
+ s
+ с
+
TimerPanel
-
+
Silent
-
+ Тихо
-
+
Beeps
-
+ Писком
-
+
Voice
-
+ Голосом
-
+
Haptic
-
+ Вибрацией
-
+
Not persistent
-
+ Сбрасываемый
-
+
Persistent (flight)
-
+ Постоянный (только полет)
-
+
Persistent (manual reset)
-
+ Постоянный (только ручной сброс)
@@ -9996,345 +13366,423 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
TrainerSimulator
-
+
Trainer simulator
- VTailPage
+ TreeModel
-
- First Tail Channel:
+
+ Index
+ Номер
+
+
+
+ Name
+ Название
+
+
+
+ Size
+ Размер
+
+
+
+ RX #
-
+
+ Models
+ Translators do NOT use accent for this, this is the default category name on Horus.
+ Модели
+
+
+
+ Model %1
+ Translators: do NOT use accents here, this is a default model name.
+ Модель %1
+
+
+
+ VTailPage
+
+
+ First Tail Channel:
+ Первый канал управления:
+
+
+
Second Tail Channel:
+ Второй канал управления:
+
+
+
+ VirtualJoystickWidget
+
+
+ Hld Y
+
+
+
+
+ Hold Vertical stick position.
+
+
+
+
+ Fix Y
+
+
+
+
+ Prevent Vertical movement of stick.
+
+
+
+
+ Fix X
+
+
+
+
+ Prevent Horizontal movement of stick.
+
+
+
+
+ Hld X
+
+
+
+
+ Hold Horizontal stick position.
WingtypeSelectionPage
-
+
Standard Wing
-
+ Классическая схема
-
+
Flying Wing / Deltawing
-
+ Летающее крыло
WizardDialog
-
+
Model Wizard
-
+ Мастер по настройке модели
-
+
Model Type
-
+ Тип модели
-
+
Enter model name and model type.
-
+ Введите название модели и выберите её тип.
-
+
Throttle
- Газ
+ Газ
-
+
Has your model got a motor or an engine?
-
+ У вашей модели есть двигатель?
-
+
Wing Type
-
+ Тип крыла
-
+
Is your model a flying wing/deltawing or has it a standard wing configuration?
-
+ У вас классический самолет или летающее крыло?
-
+
Ailerons
-
+ Элероны
-
+
Has your model got ailerons?
-
+ У вашей модели есть элероны?
-
+
Flaps
-
+ Закрылки
-
+
Has your model got flaps?
-
+ У вашей модели есть закрылки?
-
+
Airbrakes
-
+ Воздушные тормоза
-
+
Has your model got airbrakes?
-
+ У вашей модели есть воздушные тормоза?
-
+
Flying-wing / Delta-wing
-
+ Летающее крыло
-
+
Select the elevons channels
-
-
-
-
- Rudder
- Руддер
-
-
-
- Does your model have a rudder?
-
-
-
-
- Tail Type
-
-
-
-
- Select which type of tail your model is equiped with.
-
-
-
-
-
- Tail
-
-
-
-
-
- Select channels for tail control.
-
-
-
-
- V-Tail
-
-
-
-
- Select elevator channel.
-
+ Выберите каналы элевонов
+ Rudder
+ Руль направления
+
+
+
+ Does your model have a rudder?
+ У вашей модели есть руль направления?
+
+
+
+ Tail Type
+ Тип хвостового оперения
+
+
+
+ Select which type of tail your model is equiped with.
+ Выберите тип хвостового оперения модели.
+
+
+
+
+ Tail
+ Хвостовое оперение
+
+
+
+
+ Select channels for tail control.
+ Выберите каналы для хвостового оперения.
+
+
+
+ V-Tail
+ V-образное оперение
+
+
+
+ Select elevator channel.
+ Выберите канал руля высоты.
+
+
+
Cyclic
-
+
Which type of swash control is installed in your helicopter?
-
+
Tail Gyro
-
+
Has your helicopter got an adjustable gyro for the tail?
-
+
Rotor Type
-
+
Has your helicopter got a flybar?
-
-
+
+
Helicopter
-
+ Вертолет
-
-
+
+
Select the controls for your helicopter
-
+
Multirotor
-
+ Мультикоптер
-
+
Select the control channels for your multirotor
-
+ Выберите каналы управления коптером
-
+
Model Options
-
+ Дополнительные опции
-
+
Select additional options
-
+ Выберите необходимое
-
+
Save Changes
-
+ Сохранить изменения
-
+
Manually check the direction of each control surface and reverse any channels that make controls move in the wrong direction. Remove the propeller/propellers before you try to control your model for the first time.<br>Please note that continuing removes all old model settings!
-
+ Вручную проверьте направление движения всех управляющих поверхностей, настройке реверсы там, где это необходимо. <br>Снимите пропеллер перед тестированием.<br>Учтите, что сохранение перезапишет старые настройки модели!
-
+
Enter a name for your model and select model type.
-
+ Введите название модели и выберите её тип.
-
+
Select the receiver channel that is connected to your ESC or throttle servo.<br><br>Throttle - Spektrum: CH1, Futaba: CH3
-
-
-
-
- Most aircraft have a main wing and a tail with control surfaces. Flying wings and delta winged aircraft only have a single wing. The main control surface on a standard wing controls the roll of the aircraft. This surface is called an aileron.<br>The control surface of a delta wing controls both roll and pitch. This surface is called an elevon.
-
+ Выберите канал на приемнике, к которому подключен регулятор скорости или сервомашинка для газа.<br><br>Spektrum: Канал1, Futaba: Канал3
+ Most aircraft have a main wing and a tail with control surfaces. Flying wings and delta winged aircraft only have a single wing. The main control surface on a standard wing controls the roll of the aircraft. This surface is called an aileron.<br>The control surface of a delta wing controls both roll and pitch. This surface is called an elevon.
+ Большинство самолетов имеют нормальную аэродинамическую схему (классическую). У летающих крыльев нет хвостового оперения. <br>В классической схеме за крен отвечают элероны.<br>У летающих крыльев элевоны отвечают и за крен и за тангаж.
+
+
+
Models use one or two channels to control the ailerons.<br>A so called Y-cable can be used to connect a single receiver channel to two separate aileron servos. If your servos are connected by a Y-cable you should select the single-servo option.<br><br>Aileron - Spektrum: CH2, Futaba: CH1
-
+ Для управления элеронами используется 1 или 2 канала.<br>Так называемый Y-кабель нужен для подключения одного канала к двум сервомашинкам.<br>Если сервомашнки подключены таким кабелем, то выберите вариант с одним каналом<br><br>Элероны на Spektrum: Канал2. На Futaba: Канал1
-
+
This wizard assumes that your flaps are controlled by a switch. If your flaps are controlled by a potentiometer you can change that manually later.
-
+ В этом мастере подразумевается, что закрылки управляются тумблером. Если вы используете крутилку, тогда придется настроить её вручную.
-
+
Air brakes are used to reduce the speed of advanced sail planes.<br>They are very uncommon on other types of planes.
-
+ Воздушные тормоза нужны для снижения скорости планеров.<br>Они редко используются на других типах самолетов.
-
+
Models use two channels to control the elevons.<br>Select these two channels
-
+ Для управления элевонами нужно 2 канала. Выберите их
-
+
Select the receiver channel that is connected to your rudder.<br><br>Rudder - Spektrum: CH4, Futaba: CH4
-
+ Выберите канал, к которому подключен руль направления.<br><br>Руль направления - Spektrum: Канал4, Futaba: Канал4
-
+
Select the tail type of your plane.
-
+ Нужно выбрать тип хвостового оперения модели.
-
- Select the Rudder and Elevator channels.<br><br>Rudder - Spektrum: CH4, Futaba: CH4<br>Elevator - Spektrum: CH3, Futaba: CH2
-
-
-
- Select the Elevator channel.<br><br>Elevator - Spektrum: CH3, Futaba: CH2
-
+ Select the Rudder and Elevator channels.<br><br>Rudder - Spektrum: CH4, Futaba: CH4<br>Elevator - Spektrum: CH3, Futaba: CH2
+ Выберите каналы для руля высоты и руля направления.<br><br>Руль направления - Spektrum: Канал4, Futaba: Канал4<br>Руль высоты - Spektrum: Канал3, Futaba: Канал2
-
-
-
-
-
-
-
+
+ Select the Elevator channel.<br><br>Elevator - Spektrum: CH3, Futaba: CH2
+ Выберите канал руля высоты.<br><br>Руль высоты - Spektrum: Канал3, Futaba: Канал2
+
+
+
+
+
+
+
+
+
TBD.
-
+
Select the control channels for your multirotor.<br><br>Throttle - Spektrum: CH1, Futaba: CH3<br>Yaw - Spektrum: CH4, Futaba: CH4<br>Pitch - Spektrum: CH3, Futaba: CH2<br>Roll - Spektrum: CH2, Futaba: CH1
-
+ Выберите каналы управления коптером.<br><br>Газ: Spektrum: Канал1, Futaba: Канал3<br>Рысканье: Spektrum: Канал4, Futaba: Канал4<br>Тангаж: Spektrum: Канал3, Futaba: Канал2<br>Крен: Spektrum: Канал2, Futaba: Канал1<br>
-
+
There is no help available for the current page.
-
+
Model Wizard Help
-
+ Помощь по использованию мастера
WizardPrinter
-
+
Plane
-
+
Multicopter
-
+
Helicopter
-
+
Model Name:
-
+
Model Type:
-
+
Options:
-
+
Channel %1:
@@ -10342,7 +13790,7 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
burnConfigDialog
-
+
AVRDUDE Configuration
Настроить программатор
@@ -10497,39 +13945,34 @@ Please only use this if you know what you are doing. There are no error checks
-
+
DFU-UTIL Configuration
-
+
SAM-BA Configuration
-
-
-
+
+
+
Select Location
Выбрать расположение
-
+
List available programmers
Показать список программаторов
-
+
Avrdude help
-
- Companion
-
-
-
-
+
<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.
@@ -10548,382 +13991,153 @@ m2560 for v4.1 boards
-
- CustomizeSplashDialog
-
-
- Transmitter Splash Screen Editor
-
-
-
-
-
- Invert
- Инверт
-
-
-
-
- Load FW
-
-
-
-
-
- Load Pict
-
-
-
-
-
- Load Profile
-
-
-
-
-
- Save
-
-
-
-
-
- Open Splash Library
-
-
-
-
-
-
-
- ...
-
-
-
-
-
-
-
- Error
- Ошибка
-
-
-
- Open Firmware File
-
-
-
-
- Can not load embedded image from firmware file %1.
-
-
-
-
- Open Image to load
-
-
-
-
- Images (%1)
-
-
-
-
- Cannot load the image file %1.
-
-
-
-
- Cannot load profile image %1.
-
-
-
-
- Cannot load the library image %1.
-
-
-
-
- File Saved
-
-
-
-
- The image was saved to the file %1
-
-
-
-
- Image Refresh Error
-
-
-
-
- Failed to refresh image from file %1
-
-
-
-
- File Save Error
-
-
-
-
- Failed to write image to %1
-
-
-
-
- downloadDialog
-
-
- Downloading:
-
-
-
-
- Unable to save the file %1: %2.
-
-
-
-
- Companion
-
-
-
-
- Download failed: %1.
-
-
-
joystickDialog
Configure Joystick
-
+ Настройки джойстика
-
+
Ch2
-
-
-
-
-
-
-
-
- Not Assigned
-
-
-
-
-
-
-
-
-
-
-
- Right Vertical
-
-
-
-
-
-
-
-
-
-
-
- Right Horizontal
-
-
-
-
-
-
-
-
-
-
-
- Left Vertical
-
-
-
-
-
-
-
-
-
-
-
- Left Horizontal
-
-
-
-
-
-
-
-
-
-
-
- P1
-
-
-
-
-
-
-
-
-
-
-
- P2
-
-
-
-
-
-
-
-
-
-
-
- P3/LS
-
-
-
-
-
-
-
-
-
-
-
- RS
-
-
-
-
+
Ch1
-
+
Ch4
-
+
Ch6
-
+
Ch3
-
+
Ch5
-
+
Ch7
-
+
Ch8
-
+
Instructions
-
+ Инструкции
-
+
+ Enable
+ Включить
+
+
+
Cancel
+ Отмена
+
+
+
+ Back
+ Назад
+
+
+
+ Start
-
- Next
+
+ Not Assigned
-
- Ok
+
+ Stick
-
+
+ Knob/Slider %1
+
+
+
+
+ No joysticks found
+ Джойстик не найден
+
+
+
+ Press the Start button to start the stick range calibration procedure.
+You may change the channel assignments or inversion at any time.
+
+
+
+
Move sticks and pots in every direction making full movement
-Press next when finished
+Press Next when finished
-
-
- Error
- Ошибка
+
+ Next
+ Дальше
-
- Cannot open joystick.
-
-
-
-
+
Place sticks and pots in middle position.
-Press next when done
+Press Next when done
-
+
Map joystick channels to controls using comboboxes.
-Press next when done
+Press Next when done.
-
- Check inversion checkbox to get maximum at top-right position.
-Press next when done
+
+ Check inversion checkbox to if necessary to reverse direction.
+Press Next when done.
-
- Press ok to save configuration
-Press cancel to abort joystick calibration
+
+ Press OK to save configuration
+Press Cancel to abort joystick calibration without saving.
-
- Duplicated stick assignment
+
+ Calibration not complete, save anyway?
-
-
- mdiChild
-
- Simulate Tx
-
+
+ Ok
+ Ок
+
+
+
+ Cannot open joystick.
+ Не удалось подключить джойстик.
@@ -10937,109 +14151,109 @@ Press cancel to abort joystick calibration
...
-
+ ...
Splash library behaviour
-
+ Библиотека заставок
Remember simulator switches
-
+ Запоминать положения тумблеров
Include companion splashes
-
+ Добавить кортинки Companion
Only user defined splashes
-
+ Только пользовательские заставки
Custom TX splash screen
-
+ Пользовательская заставка
Personal splash library
-
+ Моя библиотека заставок
Joystick
-
+ Джойстик
Open Folder
-
+ Выбрать папку
Simulator capture folder
-
+ Папка для скриншотов
Use clipboard only
-
+ Только копировать в буфер обмена
Simu BackLight
-
+ Подсветка в симуляторе
Blue
Blu
-
+ Синяя
Green
-
+ Зеленая
Red
-
+ Красная
Orange
-
+ Оранжевая
Yellow
-
+ Желтая
Enable
-
+ Включить
Calibrate
-
+ Калибровать
Open Image
-
+ Выбрать картинку
Invert Pixels
-
+ Инверсия
diff --git a/companion/src/wizarddata.cpp b/companion/src/wizarddata.cpp
index f544ee4b0..25adaee24 100644
--- a/companion/src/wizarddata.cpp
+++ b/companion/src/wizarddata.cpp
@@ -61,27 +61,28 @@ void WizMix::maxMixSwitch(char *name, MixData &mix, int channel, int sw, int wei
void WizMix::addMix(ModelData &model, Input input, int weight, int channel, int & mixIndex)
{
if (input != NO_INPUT) {
- bool isHorusOrTaranis = IS_ARM(getCurrentBoard());
if (input >= RUDDER_INPUT && input <= AILERONS_INPUT) {
MixData & mix = model.mixData[mixIndex++];
mix.destCh = channel+1;
- if (isHorusOrTaranis){
+ if (IS_SKY9X(getCurrentBoard())) {
+ mix.srcRaw = RawSource(SOURCE_TYPE_STICK, input-1);
+ }
+ else {
int channel = settings.getDefaultChannel(input-1);
mix.srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, channel);
}
- else
- mix.srcRaw = RawSource(SOURCE_TYPE_STICK, input-1);
+
mix.weight = weight;
}
else if (input==FLAPS_INPUT){
// There ought to be some kind of constants for switches somewhere...
- maxMixSwitch((char *)"Flaps Up", model.mixData[mixIndex++], channel+1, isHorusOrTaranis ? SWITCH_SA0 :-SWITCH_ELE , weight); //Taranis-Horus SA-UP, 9X ELE-UP
- maxMixSwitch((char *)"Flaps Dn", model.mixData[mixIndex++], channel+1, isHorusOrTaranis ? SWITCH_SA2 : SWITCH_ELE , -weight); //Taranis-Horus SA-DOWN, 9X ELE-DOWN
+ maxMixSwitch((char *)"Flaps Up", model.mixData[mixIndex++], channel+1, IS_SKY9X(getCurrentBoard()) ? -SWITCH_ELE : SWITCH_SA0, weight); //Taranis-Horus SA-UP, 9X ELE-UP
+ maxMixSwitch((char *)"Flaps Dn", model.mixData[mixIndex++], channel+1, IS_SKY9X(getCurrentBoard()) ? SWITCH_ELE : SWITCH_SA2, -weight); //Taranis-Horus SA-DOWN, 9X ELE-DOWN
}
else if (input==AIRBRAKES_INPUT){
- maxMixSwitch((char *)"AirbkOff", model.mixData[mixIndex++], channel+1, isHorusOrTaranis ? SWITCH_SE0 :-SWITCH_RUD , -weight); //Taranis-Horus SE-UP, 9X RUD-UP
- maxMixSwitch((char *)"AirbkOn", model.mixData[mixIndex++], channel+1, isHorusOrTaranis ? SWITCH_SE2 : SWITCH_RUD , weight); //Tatanis-Horus SE-DOWN, 9X RUD-DOWN
+ maxMixSwitch((char *)"AirbkOff", model.mixData[mixIndex++], channel+1, IS_SKY9X(getCurrentBoard()) ? -SWITCH_RUD : SWITCH_SE0, -weight); //Taranis-Horus SE-UP, 9X RUD-UP
+ maxMixSwitch((char *)"AirbkOn", model.mixData[mixIndex++], channel+1, IS_SKY9X(getCurrentBoard()) ? SWITCH_RUD : SWITCH_SE2, weight); //Tatanis-Horus SE-DOWN, 9X RUD-DOWN
}
}
}
@@ -120,7 +121,7 @@ WizMix::operator ModelData()
mix.srcRaw = SOURCE_TYPE_MAX;
mix.weight = -100;
mix.swtch.type = SWITCH_TYPE_SWITCH;
- mix.swtch.index = IS_ARM(getCurrentBoard()) ? SWITCH_SF0 : SWITCH_THR;
+ mix.swtch.index = IS_SKY9X(getCurrentBoard()) ? SWITCH_THR : SWITCH_SF0;
mix.mltpx = MLTPX_REP;
memset(mix.name, 0, sizeof(mix.name));
strncpy(mix.name, "Cut", MIXDATA_NAME_LEN);
diff --git a/companion/targets/windows/companion.nsi.in b/companion/targets/windows/companion.nsi.in
index 7ea693a1a..173edec97 100644
--- a/companion/targets/windows/companion.nsi.in
+++ b/companion/targets/windows/companion.nsi.in
@@ -6,6 +6,7 @@
;Include Modern UI
!include "MUI2.nsh"
+ !include "nsDialogs.nsh"
!include "@CMAKE_CURRENT_SOURCE_DIR@\..\targets\windows\FileAssociation.nsh"
;--------------------------------
@@ -32,6 +33,10 @@
;Variables
Var StartMenuFolder
+ Var StartMenuLocationDialog
+ Var StartMenuLocationRadioCurrent
+ Var StartMenuLocationRadioAll
+ Var StartMenuLocationValue ; "current_user" or "all_users"
;--------------------------------
;Interface Settings
@@ -68,9 +73,11 @@
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\OpenTX\Companion @VERSION_FAMILY@"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
-
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder
+ ;Start Menu Folder for current user or all users?
+ Page custom StartMenuLocationCreator StartMenuLocationLeave
+
!insertmacro MUI_PAGE_INSTFILES
# These indented statements modify settings for MUI_PAGE_FINISH
@@ -117,6 +124,7 @@ Section "OpenTX Companion @VERSION_FAMILY@" SecDummy
;Registry information for add/remove programs
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "DisplayName" "OpenTX Companion @VERSION_FAMILY@"
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "DisplayVersion" "@VERSION@"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "DisplayIcon" "$\"$INSTDIR\companion.exe$\""
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTX Companion @VERSION_FAMILY@" "Publisher" "OpenTX"
@@ -126,10 +134,14 @@ Section "OpenTX Companion @VERSION_FAMILY@" SecDummy
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
;Create shortcuts
+ ${If} $StartMenuLocationValue == "all_users"
+ SetShellVarContext all
+ ${Endif}
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Companion @VERSION_FAMILY@.lnk" "$INSTDIR\companion.exe"
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Firmware Simulator @VERSION_FAMILY@.lnk" "$INSTDIR\simulator.exe"
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall Companion @VERSION_FAMILY@.lnk" "$INSTDIR\Uninstall.exe"
+ SetShellVarContext current
!insertmacro MUI_STARTMENU_WRITE_END
@@ -141,6 +153,14 @@ SectionEnd
;Language strings
LangString DESC_SecDummy ${LANG_ENGLISH} "Models and settings editor for OpenTX"
LangString DESC_SecDummy ${LANG_FRENCH} "Editeur de r�glages et mod�les pour OpenTX"
+ LangString SML_SubTitle ${LANG_ENGLISH} "Choose a location for the Start Menu shortcuts"
+ LangString SML_SubTitle ${LANG_FRENCH} "Choisissez un emplacement pour les raccourcis de l'application"
+ LangString SML_MainLabel ${LANG_ENGLISH} "Create start menu shortcuts for:"
+ LangString SML_MainLabel ${LANG_FRENCH} "Emplacement pour les raccourcis de l'application:"
+ LangString SML_RadioCurrent ${LANG_ENGLISH} "Current user only"
+ LangString SML_RadioCurrent ${LANG_FRENCH} "Utilisateur actuel"
+ LangString SML_RadioAll ${LANG_ENGLISH} "All users"
+ LangString SML_RadioAll ${LANG_FRENCH} "Tous les utilisateurs"
;Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
@@ -203,6 +223,13 @@ Section "un.OpenTX Companion @VERSION_FAMILY@"
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
+ ; Always remove start menu folder for both locations: current user and all users
+ SetShellVarContext all
+ Delete "$SMPROGRAMS\$StartMenuFolder\Companion @VERSION_FAMILY@.lnk"
+ Delete "$SMPROGRAMS\$StartMenuFolder\Firmware Simulator @VERSION_FAMILY@.lnk"
+ Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall Companion @VERSION_FAMILY@.lnk"
+ RMDir "$SMPROGRAMS\$StartMenuFolder"
+ SetShellVarContext current
Delete "$SMPROGRAMS\$StartMenuFolder\Companion @VERSION_FAMILY@.lnk"
Delete "$SMPROGRAMS\$StartMenuFolder\Firmware Simulator @VERSION_FAMILY@.lnk"
Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall Companion @VERSION_FAMILY@.lnk"
@@ -218,3 +245,58 @@ SectionEnd
Function LaunchLink
ExecShell "" "$INSTDIR\companion.exe"
FunctionEnd
+
+
+; Custom page with radio buttons, if the start menu entries shall be created
+; for the current user or for all users.
+Function StartMenuLocationCreator
+ ; Set default value if not already set. Do this before we might "abort" this page.
+ ${If} $StartMenuLocationValue == ""
+ StrCpy $StartMenuLocationValue "current_user"
+ ${EndIf}
+
+ ; If the folder starts with >, the user has chosen not to create a shortcut (see NSIS/StartMenu.nsh)
+ StrCpy $R0 $StartMenuFolder 1
+ ${If} $R0 == ">"
+ Abort
+ ${EndIf}
+
+ !insertmacro MUI_HEADER_TEXT_PAGE $(MUI_TEXT_STARTMENU_TITLE) $(SML_SubTitle)
+
+ nsDialogs::Create 1018
+ Pop $StartMenuLocationDialog
+
+ ${If} $StartMenuLocationDialog == error
+ Abort
+ ${EndIf}
+
+ ${NSD_CreateLabel} 0u 0u 100% 12u $(SML_MainLabel)
+ Pop $R0
+
+ ${NSD_CreateRadioButton} 8u 20u 100% 12u $(SML_RadioCurrent)
+ Pop $StartMenuLocationRadioCurrent
+ ${NSD_AddStyle} $StartMenuLocationRadioCurrent ${WS_GROUP}
+
+ ${NSD_CreateRadioButton} 8u 40u 100% 12u $(SML_RadioAll)
+ Pop $StartMenuLocationRadioAll
+
+ ${If} $StartMenuLocationValue == "all_users"
+ ${NSD_SetState} $StartMenuLocationRadioAll ${BST_CHECKED}
+ ${Else}
+ ${NSD_SetState} $StartMenuLocationRadioCurrent ${BST_CHECKED}
+ ${EndIf}
+
+ ${NSD_OnBack} StartMenuLocationLeave
+
+ nsDialogs::Show
+FunctionEnd
+
+; Converts the radio button state back into a value for "StartMenuLocationValue"
+Function StartMenuLocationLeave
+ ${NSD_GetState} $StartMenuLocationRadioAll $R0
+ ${If} $R0 == ${BST_CHECKED}
+ StrCpy $StartMenuLocationValue "all_users"
+ ${Else}
+ StrCpy $StartMenuLocationValue "current_user"
+ ${Endif}
+FunctionEnd
diff --git a/launchpad/common/rules b/launchpad/common/rules
index cf96b0fda..2ee5a0a6c 100755
--- a/launchpad/common/rules
+++ b/launchpad/common/rules
@@ -15,9 +15,6 @@ STM32_OPTIONS = -DLUA=YES
build:
mkdir $(BUILDDIR);
- cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=9X ../ ; make libsimulator
- cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=GRUVIN9X ../ ; make libsimulator
- cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=MEGA2560 ../ ; make libsimulator
cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=SKY9X ../ ; make libsimulator
cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=9XRPRO ../ ; make libsimulator
diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/device.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/device.lua
index 50a8c7dde..3e4c2e4eb 100644
--- a/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/device.lua
+++ b/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/device.lua
@@ -72,7 +72,7 @@ local function incrField(step)
end
else
local min, max = 0, 0
- if field.type <= 5 then
+ if ((field.type <= 5) or (field.type == 8)) then
min = field.min
max = field.max
step = field.step * step
@@ -239,25 +239,21 @@ local function fieldFloatLoad(field, data, offset)
field.default = fieldGetValue(data, offset+12, 4)
fieldUnsignedToSigned(field, 4)
field.prec = data[offset+16]
- if field.prec > 2 then
- field.prec = 2
+ if field.prec > 3 then
+ field.prec = 3
end
field.step = fieldGetValue(data, offset+17, 4)
field.unit, offset = fieldGetString(data, offset+21)
end
+local function formatFloat(num, decimals)
+ local mult = 10^(decimals or 0)
+ local val = num / mult
+ return string.format("%." .. decimals .. "f", val)
+end
+
local function fieldFloatDisplay(field, y, attr)
- local attrnum
- if field.prec == 1 then
- attrnum = LEFT + attr + PREC1
- elseif field.prec == 2 then
- attrnum = LEFT + attr + PREC2
- else
- attrnum = LEFT + attr
- end
- -- lcd.drawNumber(140, y, field.value, attrnum) -- NOTE: original code getLastPos not available in Horus
- -- lcd.drawText(lcd.getLastPos(), y, field.unit, attr) -- NOTE: original code getLastPos not available in Horus
- lcd.drawText(140, y, field.value .. field.unit, attr) -- NOTE: Concenated fields instead of get lastPos
+ lcd.drawText(140, y, formatFloat(field.value, field.prec) .. field.unit, attr)
end
local function fieldFloatSave(field)
@@ -423,7 +419,7 @@ end
-- Main
local function runDevicePage(event)
- if event == EVT_EXIT_BREAK then -- exit script
+ if event == EVT_VIRTUAL_EXIT then -- exit script
if edit == true then
edit = false
local field = getField(lineIndex)
@@ -455,9 +451,9 @@ local function runDevicePage(event)
end
end
elseif edit then
- if event == EVT_VIRTUAL_INC then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
incrField(1)
- elseif event == EVT_VIRTUAL_DEC then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
incrField(-1)
end
else
@@ -493,7 +489,7 @@ end
local function runPopupPage(event)
local result
if fieldPopup.status == 3 then
- result = popupConfirmation(fieldPopup.info, event)
+ result = popupConfirmation("Confirmation", fieldPopup.info, event)
else
result = popupWarning(fieldPopup.info, event)
end
diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SBEC.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SBEC.lua
index 73d2b88e2..bbe819087 100644
--- a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SBEC.lua
+++ b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SBEC.lua
@@ -273,11 +273,6 @@ local function run(event)
if event == nil then
error("Cannot run as a model script!")
return 2
- elseif event == EVT_PAGE_BREAK or event == EVT_PAGEDN_FIRST or event == EVT_SHIFT_BREAK then
- --selectPage(1)
- elseif event == EVT_PAGE_LONG or event == EVT_PAGEUP_FIRST or event == EVT_SHIFT_LONG then
- --killEvents(event);
- --selectPage(-1)
end
local result = pages[page](event)
diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/Graupner HoTT.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/Graupner HoTT.lua
index ff6a3254c..d0a7d4af8 100644
--- a/radio/sdcard/horus/SCRIPTS/TOOLS/Graupner HoTT.lua
+++ b/radio/sdcard/horus/SCRIPTS/TOOLS/Graupner HoTT.lua
@@ -21,19 +21,41 @@
-- To start operation:
-- Write "HoTT" at address 0..3
-- Write 0xFF at address 4 will request the buffer to be cleared
--- Write 0xDF at address 5
+-- Write 0x0F at address 5
-- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters
-- by 8 lines
--- Write at address 5 sends an order to the RX: 0xDF=start, 0xD7=prev page,
--- 0xDE=next page, 0xD9=enter, 0xDD=next or 0xDB=prev
+-- Write at address 5 sends an order to the RX: 0xXF=start, 0xX7=prev page,
+-- 0xXE=next page, 0xX9=enter, 0xXD=next or 0xXB=prev with X being the sensor
+-- to request data from 8=RX only, 9=Vario, A=GPS, B=Cust, C=ESC, D=GAM, E=EAM
-- Write at address 4 the value 0xFF will request the buffer to be cleared
-- !! Before exiting the script must write 0 at address 0 for normal operation !!
--###############################################################################
+HoTT_Sensor = 0
+Timer_128 = 100
+
local function HoTT_Release()
multiBuffer( 0, 0 )
end
+local function HoTT_Send(button)
+ multiBuffer( 5, 0x80+(HoTT_Sensor*16) + button)
+end
+
+local function HoTT_Sensor_Inc()
+ local detected_sensors=multiBuffer( 4 )
+ local a
+ if detected_sensors ~= 0xFF then
+ repeat
+ HoTT_Sensor=(HoTT_Sensor+1)%7 -- Switch to next sensor
+ if HoTT_Sensor ~= 0 then
+ a = math.floor(detected_sensors/ (2^(HoTT_Sensor-1))) -- shift right
+ end
+ until HoTT_Sensor==0 or a % 2 == 1
+ HoTT_Send( 0x0F )
+ end
+end
+
local function HoTT_Draw_LCD()
local i
local value
@@ -41,12 +63,14 @@ local function HoTT_Draw_LCD()
local result
local offset=0
+ local sensor_name = { "", "+Vario", "+GPS", "+Cust", "+ESC", "+GAM", "+EAM" }
+
lcd.clear()
if LCD_W == 480 then
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
- lcd.drawText(1, 5, "Graupner HoTT RX configuration", MENU_TITLE_COLOR)
+ lcd.drawText(1, 5, "Graupner HoTT: config RX" .. sensor_name[HoTT_Sensor+1] .. " - Menu cycle Sensors", MENU_TITLE_COLOR)
--Draw RX Menu
if multiBuffer( 4 ) == 0xFF then
lcd.drawText(10,50,"No HoTT telemetry...", BLINK)
@@ -56,9 +80,9 @@ local function HoTT_Draw_LCD()
value=multiBuffer( line*21+6+i )
if value > 0x80 then
value = value - 0x80
- lcd.drawText(10+i*16,32+16*line,string.char(value).." ",INVERS)
+ lcd.drawText(10+i*16,32+20*line,string.char(value).." ",INVERS)
else
- lcd.drawText(10+i*16,32+16*line,string.char(value))
+ lcd.drawText(10+i*16,32+20*line,string.char(value))
end
end
end
@@ -68,14 +92,23 @@ local function HoTT_Draw_LCD()
if multiBuffer( 4 ) == 0xFF then
lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE)
else
- for line = 0, 7, 1 do
- for i = 0, 21-1, 1 do
- value=multiBuffer( line*21+6+i )
- if value > 0x80 then
- value = value - 0x80
- lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
- else
- lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
+ if Timer_128 ~= 0 then
+ --Intro page
+ Timer_128 = Timer_128 - 1
+ lcd.drawScreenTitle("Graupner Hott",0,0)
+ lcd.drawText(2,17,"Configuration of RX" .. sensor_name[HoTT_Sensor+1] ,SMLSIZE)
+ lcd.drawText(2,37,"Press menu to cycle Sensors" ,SMLSIZE)
+ else
+ --Menu page
+ for line = 0, 7, 1 do
+ for i = 0, 21-1, 1 do
+ value=multiBuffer( line*21+6+i )
+ if value > 0x80 then
+ value = value - 0x80
+ lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
+ else
+ lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
+ end
end
end
end
@@ -98,7 +131,10 @@ local function HoTT_Init()
--Request init of the RX buffer
multiBuffer( 4, 0xFF )
--Request RX to send the config menu
- multiBuffer( 5, 0xDF )
+ HoTT_Send( 0x0F )
+ HoTT_Sensor = 0;
+ HoTT_Detected_Sensors=0;
+ Timer_128 = 100
end
-- Main
@@ -111,18 +147,21 @@ local function HoTT_Run(event)
return 2
else
if event == EVT_VIRTUAL_PREV_PAGE then
- killEvents(event);
- multiBuffer( 5, 0xD7 )
- elseif event == EVT_VIRTUAL_NEXT_PAGE then
- multiBuffer( 5, 0xDE )
+ killEvents(event)
+ HoTT_Send( 0x07 )
elseif event == EVT_VIRTUAL_ENTER then
- multiBuffer( 5, 0xD9 )
- elseif event == EVT_VIRTUAL_NEXT then
- multiBuffer( 5, 0xDD )
+ HoTT_Send( 0x09 )
elseif event == EVT_VIRTUAL_PREV then
- multiBuffer( 5, 0xDB )
+ HoTT_Send( 0x0B )
+ elseif event == EVT_VIRTUAL_NEXT then
+ HoTT_Send( 0x0D )
+ elseif event == EVT_VIRTUAL_NEXT_PAGE then
+ HoTT_Send( 0x0E )
+ elseif event == EVT_VIRTUAL_MENU then
+ Timer_128 = 100
+ HoTT_Sensor_Inc()
else
- multiBuffer( 5, 0xDF )
+ HoTT_Send( 0x0F )
end
HoTT_Draw_LCD()
return 0
diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt
new file mode 100644
index 000000000..bf61d8ca6
--- /dev/null
+++ b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt
@@ -0,0 +1,157 @@
+1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
+1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
+1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL
+1,3,Flysky,V912,1,BtmBtn,TopBtn
+1,4,Flysky,CX20,0,CH5,CH6,CH7
+28,0,Flysky_AFHDS2A,PWM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+53,0,Flyzone,FZ-410,0
+2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
+2,1,Hubsan,H301,0,RTH,Light,Stab,Video
+2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
+41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
+60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
+37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
+37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
+37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
+25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
+3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
+3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8
+67,0,FrSkyL,LR12,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+67,1,FrSkyL,LR12_6CH,0,CH5,CH6
+15,0,FrSkyX,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+15,1,FrSkyX,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
+15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8
+15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
+64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8
+64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+55,1,FrSkyRX,CloneTX,0
+39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
+39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
+39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
+57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
+68,0,Skyartec,Std,0,CH5,CH6,CH7
+7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
+7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
+7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+7,3,Devo,6CH,0,CH5,CH6
+7,4,Devo,7CH,0,CH5,CH6,CH7
+30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
+30,1,WK2x01,WK2401,0
+30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
+30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
+30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
+30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
+6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
+24,0,Assan,Std,0,CH5,CH6,CH7,CH8
+14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
+14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
+14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
+14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
+14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
+59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
+42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
+42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
+34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
+13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
+12,0,CX10,Green,1,Flip,Rate
+12,1,CX10,Blue,1,Flip,Rate,Pict,Video
+12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
+12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
+12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
+12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
+33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
+45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
+45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
+45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
+16,0,ESKY,Std,0,Gyro,Pitch
+16,1,ESKY,ET4,0,Gyro,Pitch
+35,0,ESKY150,4CH,0
+35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
+20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
+20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
+23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
+32,0,GW008,FY326,1,Flip
+36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
+36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
+36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
+36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
+4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
+9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
+26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
+26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
+26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
+18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
+17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
+17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
+17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
+17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
+44,0,NCC1701,Std,1,Warp
+51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
+66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
+29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
+29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
+29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
+31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
+31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
+31,2,Q303,CX10D,1,Arm,Flip
+31,3,Q303,CX10WD,1,Arm,Flip
+50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
+50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
+11,0,SLT,V1,0,Gear,Pitch
+11,1,SLT,V2,0,CH5,CH6,CH7,CH8
+11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
+11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
+11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
+10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
+10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
+5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
+5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
+61,0,Tiger,Std,1,Flip,Light
+46,0,V911s,Std,1,Calib
+46,1,E119,Std,1,Calib
+62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
+62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
+8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
+8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
+8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
+8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
+8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
+65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8
+65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8
+56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+19,0,Shenqi,Cycle,1
+4,1,Hisky,HK310,0,Aux
+43,0,Traxxas,6519,0
+52,0,ZSX,280,1,Light
+48,0,V761,Std,1,Gyro
+49,0,KF606,Std,1,Trim
+47,0,GD00x,V1,1,Trim,LED,Rate
+47,1,GD00x,V2,1,Trim,LED,Rate
+58,0,FX816,P38,1
diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
new file mode 100644
index 000000000..42de75e4f
--- /dev/null
+++ b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
@@ -0,0 +1,302 @@
+
+local toolName = "TNS|Multi chan namer|TNE"
+
+---- #########################################################################
+---- # #
+---- # Copyright (C) OpenTX #
+-----# #
+---- # 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. #
+---- # #
+---- #########################################################################
+
+local protocol_name = ""
+local sub_protocol_name = ""
+local bind_ch = 0
+local module_conf = {}
+local module_pos = "Internal"
+local file_ok = 0
+local done = 0
+local protocol = 0
+local sub_protocol = 0
+local f_seek = 0
+local channel_names={}
+local num_search = "Searching"
+
+local function drawScreenTitle(title)
+ if LCD_W == 480 then
+ lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
+ lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
+ else
+ lcd.drawScreenTitle(title, 0, 0)
+ end
+end
+
+function bitand(a, b)
+ local result = 0
+ local bitval = 1
+ while a > 0 and b > 0 do
+ if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
+ result = result + bitval -- set the current bit
+ end
+ bitval = bitval * 2 -- shift left
+ a = math.floor(a/2) -- shift right
+ b = math.floor(b/2)
+ end
+ return result
+end
+
+local function Multi_Draw_LCD(event)
+ local line = 0
+
+ lcd.clear()
+ drawScreenTitle("Multi channels namer")
+
+ --Display settings
+ local lcd_opt = 0
+ if LCD_W == 480 then
+ x_pos = 10
+ y_pos = 32
+ y_inc = 20
+ else
+ x_pos = 0
+ y_pos = 9
+ y_inc = 8
+ lcd_opt = SMLSIZE
+ end
+
+ --Multi Module detection
+ if module_conf["Type"] ~= 6 then
+ if LCD_W == 480 then
+ lcd.drawText(10,50,"No Multi module configured...", BLINK)
+ else
+ --Draw on LCD_W=128
+ lcd.drawText(2,17,"No Multi module configured...",SMLSIZE)
+ end
+ return
+ else
+ lcd.drawText(x_pos, y_pos+y_inc*line,module_pos .. " Multi detected.", lcd_opt)
+ line = line + 1
+ end
+
+ --Channel order
+ if (ch_order == -1) then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Channels order can't be read from Multi...", lcd_opt)
+ line = line + 1
+ end
+
+ --Can't open file MultiChan.txt
+ if file_ok == 0 then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Can't read MultiChan.txt file...", lcd_opt)
+ return
+ end
+
+ if ( protocol_name == "" or sub_protocol_name == "" ) and f_seek ~=-1 then
+ local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
+ if f == nil then return end
+ lcd.drawText(x_pos, y_pos+y_inc*line,num_search, lcd_opt)
+ num_search = num_search .. "."
+ if #num_search > 15 then
+ num_search = string.sub(num_search,1,9)
+ end
+ local proto = 0
+ local sub_proto = 0
+ local proto_name = ""
+ local sub_proto_name = ""
+ local channels = ""
+ local nbr_try = 0
+ local nbr_car = 0
+ repeat
+ io.seek(f, f_seek)
+ local data = io.read(f, 100) -- read 100 characters
+ if #data ==0 then
+ f_seek = -1 -- end of file
+ break
+ end
+ proto, sub_proto, proto_name, sub_proto_name, bind_ch, channels = string.match(data,'(%d+),(%d),([%w-_ ]+),([%w-_ ]+),(%d)(.+)')
+ if proto ~= nil and sub_proto ~= nil and protocol_name ~= nil and sub_protocol_name ~= nil and bind_ch ~= nil then
+ if tonumber(proto) == protocol and tonumber(sub_proto) == sub_protocol then
+ protocol_name = proto_name
+ sub_protocol_name = sub_proto_name
+ bind_ch = tonumber(bind_ch)
+ if channels ~= nil then
+ --extract channel names
+ nbr_car = string.find(channels, "\r")
+ if nbr_car == nil then nbr_car = string.find(channels, "\n") end
+ if nbr_car ~= nil then
+ channels = string.sub(channels,1,nbr_car-1)
+ end
+ local i = 5
+ for k in string.gmatch(channels, ",([%w-_ ]+)") do
+ channel_names[i] = k
+ i = i + 1
+ end
+ end
+ f_seek = -1 -- protocol found
+ break
+ end
+ end
+ if f_seek ~= -1 then
+ nbr_car = string.find(data, "\n")
+ if nbr_car == nil then nbr_car = string.find(data, "\r") end
+ if nbr_car == nil then
+ f_seek = -1 -- end of file
+ break
+ end
+ f_seek = f_seek + nbr_car -- seek to next line
+ nbr_try = nbr_try + 1
+ end
+ until nbr_try > 20 or f_seek == -1
+ io.close(f)
+ end
+
+ if f_seek ~= -1 then
+ return -- continue searching...
+ end
+
+ --Protocol & Sub_protocol
+ if protocol_name == "" or sub_protocol_name == "" then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Unknown protocol "..tostring(protocol).."/"..tostring(sub_protocol).." ...", lcd_opt)
+ return
+ elseif LCD_W > 128 then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name .. " / SubProtocol: " .. sub_protocol_name, lcd_opt)
+ line = line + 1
+ else
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name, lcd_opt)
+ line = line + 1
+ lcd.drawText(x_pos, y_pos+y_inc*line,"SubProtocol: " .. sub_protocol_name, lcd_opt)
+ line = line + 1
+ end
+
+ text1=""
+ text2=""
+ for i,v in ipairs(channel_names) do
+ if i<=8 then
+ if i==1 then
+ text1 = v
+ else
+ text1=text1 .. "," .. v
+ end
+ else
+ if i==9 then
+ text2 = v
+ else
+ text2=text2 .. "," .. v
+ end
+ end
+ end
+ if LCD_W > 128 then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Channels: " .. text1, lcd_opt)
+ line = line + 1
+ if text2 ~= "" then
+ lcd.drawText(x_pos*9, y_pos+y_inc*line,text2, lcd_opt)
+ line = line + 1
+ end
+ end
+
+ if event ~= EVT_VIRTUAL_ENTER and done == 0 then
+ lcd.drawText(x_pos, y_pos+y_inc*line," Save", lcd_opt + INVERS + BLINK)
+ return
+ end
+
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Setting channel names.", lcd_opt)
+ line = line + 1
+ local output, nbr
+ if done == 0 then
+ for i,v in ipairs(channel_names) do
+ output = model.getOutput(i-1)
+ output["name"] = v
+ model.setOutput(i-1,output)
+ nbr = i
+ end
+ for i = nbr, 15 do
+ output = model.getOutput(i)
+ output["name"] = "n-a"
+ model.setOutput(i,output)
+ end
+ if bind_ch == 1 then
+ output = model.getOutput(15)
+ output["name"] = "BindCH"
+ model.setOutput(15,output)
+ end
+ done = 1
+ end
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Done!", lcd_opt)
+ line = line + 1
+end
+
+-- Init
+local function Multi_Init()
+ module_conf = model.getModule(0)
+ if module_conf["Type"] ~= 6 then
+ module_pos = "External"
+ module_conf = model.getModule(1)
+ if module_conf["Type"] ~= 6 then
+ return
+ end
+ end
+
+ protocol = module_conf["protocol"]
+ sub_protocol = module_conf["subProtocol"]
+
+ --Exceptions on first 4 channels...
+ local stick_names = { "Rud", "Ele", "Thr", "Ail" }
+ if ( protocol == 4 and sub_protocol ==1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX
+ stick_names[2] = "n-a"
+ stick_names[4] = "n-a"
+ elseif protocol == 43 then -- Traxxas
+ stick_names[2] = "Aux4"
+ stick_names[4] = "Aux3"
+ elseif protocol == 48 then -- V761
+ stick_names[4] = "n-a"
+ elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
+ stick_names[1] = "n-a"
+ stick_names[2] = "n-a"
+ end
+
+ --Determine fist 4 channels order
+ local ch_order=module_conf["channelsOrder"]
+ if (ch_order == -1) then
+ channel_names[1] = stick_names[defaultChannel(0)+1]
+ channel_names[2] = stick_names[defaultChannel(1)+1]
+ channel_names[3] = stick_names[defaultChannel(2)+1]
+ channel_names[4] = stick_names[defaultChannel(3)+1]
+ else
+ channel_names[bitand(ch_order,3)+1] = stick_names[4]
+ ch_order = math.floor(ch_order/4)
+ channel_names[bitand(ch_order,3)+1] = stick_names[2]
+ ch_order = math.floor(ch_order/4)
+ channel_names[bitand(ch_order,3)+1] = stick_names[3]
+ ch_order = math.floor(ch_order/4)
+ channel_names[bitand(ch_order,3)+1] = stick_names[1]
+ end
+ --Check MultiChan.txt
+ local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
+ if f == nil then return end
+ file_ok = 1
+ io.close(f)
+end
+
+-- Main
+local function Multi_Run(event)
+ if event == nil then
+ error("Cannot be run as a model script!")
+ return 2
+ else
+ Multi_Draw_LCD(event)
+ if event == EVT_VIRTUAL_EXIT then
+ return 2
+ end
+ end
+ return 0
+end
+
+return { init=Multi_Init, run=Multi_Run }
diff --git a/radio/sdcard/horus/SCRIPTS/WIZARD/glider/wizard.lua b/radio/sdcard/horus/SCRIPTS/WIZARD/glider/wizard.lua
index 1985589bc..86b08451e 100644
--- a/radio/sdcard/horus/SCRIPTS/WIZARD/glider/wizard.lua
+++ b/radio/sdcard/horus/SCRIPTS/WIZARD/glider/wizard.lua
@@ -91,9 +91,9 @@ end
-- Main
local function runFieldsPage(event)
- if event == EVT_EXIT_BREAK then -- exit script
+ if event == EVT_VIRTUAL_EXIT then -- exit script
return 2
- elseif event == EVT_ENTER_BREAK or event == EVT_ROT_BREAK then -- toggle editing/selecting current field
+ elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
if fields[current][5] ~= nil then
edit = not edit
if edit == false then
@@ -101,15 +101,15 @@ local function runFieldsPage(event)
end
end
elseif edit then
- if event == EVT_PLUS_FIRST or event == EVT_ROT_RIGHT or event == EVT_PLUS_REPT then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
addField(1)
- elseif event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT or event == EVT_MINUS_REPT then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
addField(-1)
end
else
- if event == EVT_MINUS_FIRST or event == EVT_ROT_RIGHT then
+ if event == EVT_VIRTUAL_NEXT then
selectField(1)
- elseif event == EVT_PLUS_FIRST or event == EVT_ROT_LEFT then
+ elseif event == EVT_VIRTUAL_PREV then
selectField(-1)
end
end
@@ -149,14 +149,13 @@ local function runMotorConfig(event)
lcd.drawBitmap(BackgroundImg, 0, 0)
lcd.drawBitmap(ImgPageDn, 455, 95)
lcd.drawBitmap(ImgEngine, 310, 50)
- lcd.setColor(CUSTOM_COLOR, lcd.RGB(255, 255, 255))
fields = MotorFields
lcd.drawText(40, 20, "Does your model have a motor ?", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 45, 200, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 45, 200, 30, TEXT_BGCOLOR)
fields[2][4]=0
if fields[1][5] == 1 then
lcd.drawText(40, 100, "What channel is it on ?", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
fields[2][4]=1
end
local result = runFieldsPage(event)
@@ -190,7 +189,7 @@ local function runAilConfig(event)
lcd.drawBitmap(ImgAilL, 395, 235)
drawMark(308, 115, "A")
drawMark(422, 220, "A")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
setFieldsVisible(1, 0)
elseif fields[1][5] == 2 then
@@ -198,16 +197,16 @@ local function runAilConfig(event)
lcd.drawBitmap(ImgAilL, 395, 235)
drawMark(308, 115, "A")
drawMark(422, 220, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
setFieldsVisible(1, 1)
else
setFieldsVisible(0, 0)
end
lcd.drawText(40, 20, "Number of ailerons on your model ?", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 45, 400, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
local result = runFieldsPage(event)
return result
end
@@ -235,7 +234,7 @@ local function runFlapsConfig(event)
lcd.drawBitmap(ImgFlp, 358, 202)
drawMark(332, 132, "A")
drawMark(412, 215, "A")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
setFieldsVisible(1, 0)
elseif fields[1][5] == 2 then
@@ -243,16 +242,16 @@ local function runFlapsConfig(event)
lcd.drawBitmap(ImgFlp, 358, 202)
drawMark(332, 132, "A")
drawMark(412, 215, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
setFieldsVisible(1, 1)
else
setFieldsVisible(0, 0)
end
lcd.drawText(40, 20, "Does your model have flaps ?", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 45, 400, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
local result = runFieldsPage(event)
return result
end
@@ -283,7 +282,7 @@ local function runTailConfig(event)
lcd.drawBitmap(ImgTail, 252, 100)
drawMark(360, 125, "A")
drawMark(390, 155, "A")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
setFieldsVisible(1, 0, 0)
end
@@ -293,9 +292,9 @@ local function runTailConfig(event)
drawMark(415, 150, "A")
drawMark(380, 120, "A")
drawMark(390, 185, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
setFieldsVisible(1, 1, 0)
end
@@ -305,11 +304,11 @@ local function runTailConfig(event)
drawMark(415, 150, "C")
drawMark(380, 120, "A")
drawMark(390, 185, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
- lcd.drawFilledRectangle(40, 202, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 202, 100, 30, TEXT_BGCOLOR)
drawMark(152, 204, "C")
setFieldsVisible(1, 1, 1)
end
@@ -317,14 +316,14 @@ local function runTailConfig(event)
lcd.drawBitmap(ImgVTail, 252, 100)
drawMark(315, 110, "A")
drawMark(382, 120, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
setFieldsVisible(1, 1, 0)
end
lcd.drawText(40, 20, "Pick the tail config of your model", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 45, 400, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
local result = runFieldsPage(event)
return result
end
@@ -465,9 +464,9 @@ local function run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
- elseif (event == EVT_PAGE_BREAK or event == EVT_PAGEDN_FIRST) and page < #pages-1 then
+ elseif event == EVT_VIRTUAL_NEXT_PAGE and page < #pages-1 then
selectPage(1)
- elseif (event == EVT_PAGE_LONG or event == EVT_PAGEUP_FIRST) and page > 1 then
+ elseif event == EVT_VIRTUAL_PREV_PAGE and page > 1 then
killEvents(event);
selectPage(-1)
end
diff --git a/radio/sdcard/horus/SCRIPTS/WIZARD/plane/wizard.lua b/radio/sdcard/horus/SCRIPTS/WIZARD/plane/wizard.lua
index 37a78d4e3..8a43ed159 100755
--- a/radio/sdcard/horus/SCRIPTS/WIZARD/plane/wizard.lua
+++ b/radio/sdcard/horus/SCRIPTS/WIZARD/plane/wizard.lua
@@ -91,9 +91,9 @@ end
-- Main
local function runFieldsPage(event)
- if event == EVT_EXIT_BREAK then -- exit script
+ if event == EVT_VIRTUAL_EXIT then -- exit script
return 2
- elseif event == EVT_ENTER_BREAK or event == EVT_ROT_BREAK then -- toggle editing/selecting current field
+ elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
if fields[current][5] ~= nil then
edit = not edit
if edit == false then
@@ -101,15 +101,15 @@ local function runFieldsPage(event)
end
end
elseif edit then
- if event == EVT_PLUS_FIRST or event == EVT_ROT_RIGHT or event == EVT_PLUS_REPT then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
addField(1)
- elseif event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT or event == EVT_MINUS_REPT then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
addField(-1)
end
else
- if event == EVT_MINUS_FIRST or event == EVT_ROT_RIGHT then
+ if event == EVT_VIRTUAL_NEXT then
selectField(1)
- elseif event == EVT_PLUS_FIRST or event == EVT_ROT_LEFT then
+ elseif event == EVT_VIRTUAL_PREV then
selectField(-1)
end
end
@@ -144,19 +144,18 @@ local ImgEngine
local function runMotorConfig(event)
lcd.clear()
if ImgEngine == nil then
- ImgEngine = Bitmap.open("img/prop.png")
+ ImgEngine = Bitmap.open("img/prop.png")
end
lcd.drawBitmap(BackgroundImg, 0, 0)
lcd.drawBitmap(ImgPageDn, 455, 95)
lcd.drawBitmap(ImgEngine, 310, 50)
- lcd.setColor(CUSTOM_COLOR, lcd.RGB(255, 255, 255))
fields = MotorFields
lcd.drawText(40, 20, "Does your model have a motor ?", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 45, 200, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 45, 200, 30, TEXT_BGCOLOR)
fields[2][4]=0
if fields[1][5] == 1 then
lcd.drawText(40, 100, "What channel is it on ?", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
fields[2][4]=1
end
local result = runFieldsPage(event)
@@ -190,7 +189,7 @@ local function runAilConfig(event)
lcd.drawBitmap(ImgAilL, 275, 210)
drawMark(362, 132, "A")
drawMark(302, 227, "A")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
setFieldsVisible(1, 0)
elseif fields[1][5] == 2 then
@@ -198,16 +197,16 @@ local function runAilConfig(event)
lcd.drawBitmap(ImgAilL, 275, 210)
drawMark(362, 132, "A")
drawMark(302, 227, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
setFieldsVisible(1, 1)
else
setFieldsVisible(0, 0)
end
lcd.drawText(40, 20, "Number of ailerons on your model ?", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 45, 400, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
local result = runFieldsPage(event)
return result
end
@@ -235,7 +234,7 @@ local function runFlapsConfig(event)
lcd.drawBitmap(ImgFlp, 285, 191)
drawMark(362, 132, "A")
drawMark(302, 227, "A")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
setFieldsVisible(1, 0)
elseif fields[1][5] == 2 then
@@ -243,16 +242,16 @@ local function runFlapsConfig(event)
lcd.drawBitmap(ImgFlp, 285, 191)
drawMark(362, 132, "A")
drawMark(302, 227, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
setFieldsVisible(1, 1)
else
setFieldsVisible(0, 0)
end
lcd.drawText(40, 20, "Does your model have flaps ?", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 45, 400, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
local result = runFieldsPage(event)
return result
end
@@ -283,7 +282,7 @@ local function runTailConfig(event)
lcd.drawBitmap(ImgTail, 252, 100)
drawMark(275, 120, "A")
drawMark(390, 155, "A")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
setFieldsVisible(1, 0, 0)
end
@@ -293,9 +292,9 @@ local function runTailConfig(event)
drawMark(275, 120, "A")
drawMark(390, 155, "A")
drawMark(370, 112, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
setFieldsVisible(1, 1, 0)
end
@@ -305,11 +304,11 @@ local function runTailConfig(event)
drawMark(275, 120, "A")
drawMark(390, 155, "C")
drawMark(370, 112, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
- lcd.drawFilledRectangle(40, 202, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 202, 100, 30, TEXT_BGCOLOR)
drawMark(152, 204, "C")
setFieldsVisible(1, 1, 1)
end
@@ -317,14 +316,14 @@ local function runTailConfig(event)
lcd.drawBitmap(ImgVTail, 252, 100)
drawMark(315, 110, "A")
drawMark(382, 120, "B")
- lcd.drawFilledRectangle(40, 122, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
drawMark(152, 124, "A")
- lcd.drawFilledRectangle(40, 162, 100, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
drawMark(152, 164, "B")
setFieldsVisible(1, 1, 0)
end
lcd.drawText(40, 20, "Pick the tail config of your model", TEXT_COLOR)
- lcd.drawFilledRectangle(40, 45, 400, 30, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
local result = runFieldsPage(event)
return result
end
@@ -465,9 +464,9 @@ local function run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
- elseif (event == EVT_PAGE_BREAK or event == EVT_PAGEDN_FIRST) and page < #pages-1 then
+ elseif event == EVT_VIRTUAL_NEXT_PAGE and page < #pages-1 then
selectPage(1)
- elseif (event == EVT_PAGE_LONG or event == EVT_PAGEUP_FIRST) and page > 1 then
+ elseif event == EVT_VIRTUAL_PREV_PAGE and page > 1 then
killEvents(event);
selectPage(-1)
end
diff --git a/radio/sdcard/horus/SxR Calibrate/SxR_Calibrate.lua b/radio/sdcard/horus/SxR Calibrate/SxR_Calibrate.lua
index 4568b50eb..fca13271f 100755
--- a/radio/sdcard/horus/SxR Calibrate/SxR_Calibrate.lua
+++ b/radio/sdcard/horus/SxR Calibrate/SxR_Calibrate.lua
@@ -237,9 +237,9 @@ end
-- Main
local function runFieldsPage(event)
- if event == EVT_EXIT_BREAK then -- exit script
+ if event == EVT_VIRTUAL_EXIT then -- exit script
return 2
- elseif event == EVT_ENTER_BREAK or event == EVT_ROT_BREAK then -- toggle editing/selecting current field
+ elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
if fields[current][4] ~= nil then
edit = not edit
if edit == false then
@@ -247,15 +247,15 @@ local function runFieldsPage(event)
end
end
elseif edit then
- if event == EVT_PLUS_FIRST or event == EVT_ROT_RIGHT or event == EVT_PLUS_REPT then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
addField(1)
- elseif event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT or event == EVT_MINUS_REPT then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
addField(-1)
end
else
- if event == EVT_MINUS_FIRST or event == EVT_ROT_RIGHT then
+ if event == EVT_VIRTUAL_NEXT then
selectField(1)
- elseif event == EVT_PLUS_FIRST or event == EVT_ROT_LEFT then
+ elseif event == EVT_VIRTUAL_PREV then
selectField(-1)
end
end
@@ -313,11 +313,11 @@ local function runCalibrationPage(event)
lcd.drawBitmap(Bitmap.open("img/done.bmp"),200, 100)
lcd.drawText(160, 220, "Press [RTN] when ready", attr)
end
- if calibrationStep > 6 and (event == EVT_ENTER_BREAK or event == EVT_EXIT_BREAK) then
+ if calibrationStep > 6 and (event == EVT_VIRTUAL_ENTER or event == EVT_VIRTUAL_EXIT) then
return 2
- elseif event == EVT_ENTER_BREAK then
+ elseif event == EVT_VIRTUAL_ENTER then
calibrationState = 1
- elseif event == EVT_EXIT_BREAK then
+ elseif event == EVT_VIRTUAL_EXIT then
if calibrationStep > 0 then
calibrationStep = 0
end
@@ -341,9 +341,9 @@ local function run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
- elseif event == EVT_PAGE_BREAK or event == EVT_PAGEDN_FIRST then
+ elseif event == EVT_VIRTUAL_NEXT_PAGE then
selectPage(1)
- elseif event == EVT_PAGE_LONG or event == EVT_PAGEUP_FIRST then
+ elseif event == EVT_VIRTUAL_PREV_PAGE then
killEvents(event);
selectPage(-1)
end
diff --git a/radio/sdcard/horus/THEMES/Darkblue/shutdown.bmp b/radio/sdcard/horus/THEMES/Darkblue/shutdown.bmp
new file mode 100755
index 000000000..be7034db7
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Darkblue/shutdown.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Darkblue/t16.bmp b/radio/sdcard/horus/THEMES/Darkblue/t16.bmp
index ac0d16cf6..9c78cb498 100755
Binary files a/radio/sdcard/horus/THEMES/Darkblue/t16.bmp and b/radio/sdcard/horus/THEMES/Darkblue/t16.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Darkblue/t18.bmp b/radio/sdcard/horus/THEMES/Darkblue/t18.bmp
new file mode 100755
index 000000000..c1220ca1b
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Darkblue/t18.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Darkblue/tx16s.bmp b/radio/sdcard/horus/THEMES/Darkblue/tx16s.bmp
new file mode 100644
index 000000000..bb44eda41
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Darkblue/tx16s.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Default/t18.bmp b/radio/sdcard/horus/THEMES/Default/t18.bmp
new file mode 100755
index 000000000..c1220ca1b
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Default/t18.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Default/tx16s.bmp b/radio/sdcard/horus/THEMES/Default/tx16s.bmp
new file mode 100644
index 000000000..8f6e2872d
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Default/tx16s.bmp differ
diff --git a/radio/sdcard/horus/WIDGETS/BattCheck/main.lua b/radio/sdcard/horus/WIDGETS/BattCheck/main.lua
index ddd83039d..58790445a 100755
--- a/radio/sdcard/horus/WIDGETS/BattCheck/main.lua
+++ b/radio/sdcard/horus/WIDGETS/BattCheck/main.lua
@@ -16,25 +16,67 @@
---- # #
---- #########################################################################
+-- Horus Widget to display the levels of lipo battery with per cell indication
+-- 3djc & Offer Shmuely
+-- Date: 2020
+-- ver: 0.5
+local version = "v0.5"
+
local _options = {
- { "Sensor", SOURCE, 0 },
- { "Color", COLOR, WHITE },
- { "Shadow", BOOL, 0 },
- { "LowestCell", BOOL, 1 }
+ { "Sensor", SOURCE, 0 }, -- default to 'Cels'
+ { "Color", COLOR, WHITE },
+ { "Shadow", BOOL, 0 },
+ { "LowestCell", BOOL, 1 } -- 0=main voltage display shows all-cell-voltage, 1=main voltage display shows lowest-cell
}
+-- Data gathered from commercial lipo sensors
+
+local _lipoPercentListSplit = {
+ { { 3, 0 }, { 3.093, 1 }, { 3.196, 2 }, { 3.301, 3 }, { 3.401, 4 }, { 3.477, 5 }, { 3.544, 6 }, { 3.601, 7 }, { 3.637, 8 }, { 3.664, 9 }, { 3.679, 10 }, { 3.683, 11 }, { 3.689, 12 }, { 3.692, 13 } },
+ { { 3.705, 14 }, { 3.71, 15 }, { 3.713, 16 }, { 3.715, 17 }, { 3.72, 18 }, { 3.731, 19 }, { 3.735, 20 }, { 3.744, 21 }, { 3.753, 22 }, { 3.756, 23 }, { 3.758, 24 }, { 3.762, 25 }, { 3.767, 26 } },
+ { { 3.774, 27 }, { 3.78, 28 }, { 3.783, 29 }, { 3.786, 30 }, { 3.789, 31 }, { 3.794, 32 }, { 3.797, 33 }, { 3.8, 34 }, { 3.802, 35 }, { 3.805, 36 }, { 3.808, 37 }, { 3.811, 38 }, { 3.815, 39 } },
+ { { 3.818, 40 }, { 3.822, 41 }, { 3.825, 42 }, { 3.829, 43 }, { 3.833, 44 }, { 3.836, 45 }, { 3.84, 46 }, { 3.843, 47 }, { 3.847, 48 }, { 3.85, 49 }, { 3.854, 50 }, { 3.857, 51 }, { 3.86, 52 } },
+ { { 3.863, 53 }, { 3.866, 54 }, { 3.87, 55 }, { 3.874, 56 }, { 3.879, 57 }, { 3.888, 58 }, { 3.893, 59 }, { 3.897, 60 }, { 3.902, 61 }, { 3.906, 62 }, { 3.911, 63 }, { 3.918, 64 } },
+ { { 3.923, 65 }, { 3.928, 66 }, { 3.939, 67 }, { 3.943, 68 }, { 3.949, 69 }, { 3.955, 70 }, { 3.961, 71 }, { 3.968, 72 }, { 3.974, 73 }, { 3.981, 74 }, { 3.987, 75 }, { 3.994, 76 } },
+ { { 4.001, 77 }, { 4.007, 78 }, { 4.014, 79 }, { 4.021, 80 }, { 4.029, 81 }, { 4.036, 82 }, { 4.044, 83 }, { 4.052, 84 }, { 4.062, 85 }, { 4.074, 86 }, { 4.085, 87 }, { 4.095, 88 } },
+ { { 4.105, 89 }, { 4.111, 90 }, { 4.116, 91 }, { 4.12, 92 }, { 4.125, 93 }, { 4.129, 94 }, { 4.135, 95 }, { 4.145, 96 }, { 4.176, 97 }, { 4.179, 98 }, { 4.193, 99 }, { 4.2, 100 } },
+}
+
+local function periodicInit(t, durationMili)
+ t.startTime = getTime();
+ t.durationMili = durationMili;
+end
+local function periodicReset(t)
+ t.startTime = getTime();
+end
+local function periodicHasPassed(t)
+ local elapsed = getTime() - t.startTime;
+ local elapsedMili = elapsed * 10;
+ if (elapsedMili < t.durationMili) then
+ return false;
+ end
+ return true;
+end
+local function periodicGetElapsedTime(t)
+ local elapsed = getTime() - t.startTime;
+ local elapsedMili = elapsed * 10;
+ return elapsedMili;
+end
+
-- This function is run once at the creation of the widget
local function create(zone, options)
local wgt = {
zone = zone,
options = options,
counter = 0,
-
shadowed = 0,
+
+ telemResetCount = 0,
+ telemResetLowestMinRSSI = 101,
no_telem_blink = 0,
isDataAvailable = 0,
- cellDataLive = {0,0,0,0,0,0},
- cellDataHistoryLowest = {0,0,0,0,0,0},
+ cellDataLive = { 0, 0, 0, 0, 0, 0 },
+ cellDataHistoryLowest = { 5, 5, 5, 5, 5, 5 },
cellDataHistoryCellLowest = 5,
cellMax = 0,
cellMin = 0,
@@ -43,7 +85,10 @@ local function create(zone, options)
cellCount = 0,
cellSum = 0,
mainValue = 0,
- secondaryValue = 0
+ secondaryValue = 0,
+ periodic1 = { startTime = getTime(), durationMili = 1000 },
+ periodicProfiler = { startTime = getTime(), durationMili = 5000 },
+ profTimes = {},
}
-- use default if user did not set, So widget is operational on "select widget"
@@ -58,7 +103,9 @@ end
-- This function allow updates when you change widgets settings
local function update(wgt, options)
- if (wgt == nil) then return end
+ if (wgt == nil) then
+ return
+ end
wgt.options = options
@@ -71,35 +118,71 @@ local function update(wgt, options)
end
--- A quick and dirty check for empty table
-local function isEmpty(self)
- for _, _ in pairs(self) do
- return false
+
+-- clear old telemetry data upon reset event
+local function onTelemetryResetEvent(wgt)
+ wgt.telemResetCount = wgt.telemResetCount + 1
+
+ wgt.cellDataLive = { 0, 0, 0, 0, 0, 0 }
+ wgt.cellDataHistoryLowest = { 5, 5, 5, 5, 5, 5 }
+ wgt.cellDataHistoryCellLowest = 5
+end
+
+
+-- workaround to detect telemetry-reset event, until a proper implementation on the lua interface will be created
+-- this workaround assume that:
+-- RSSI- is always going down
+-- RSSI- is reset on the C++ side when a telemetry-reset is pressed by user
+-- widget is calling this func on each refresh/background
+-- on event detection, the function onTelemetryResetEvent() will be trigger
+--
+local function detectResetEvent(wgt)
+
+ local currMinRSSI = getValue('RSSI-')
+ if (currMinRSSI == nil) then
+ return
end
- return true
+ if (currMinRSSI == wgt.telemResetLowestMinRSSI) then
+ return
+ end
+
+ if (currMinRSSI < wgt.telemResetLowestMinRSSI) then
+ -- rssi just got lower, record it
+ wgt.telemResetLowestMinRSSI = currMinRSSI
+ return
+ end
+
+
+ -- reset telemetry detected
+ wgt.telemResetLowestMinRSSI = 101
+
+ -- notify event
+ onTelemetryResetEvent(wgt)
+
end
--- This function return the percentage remaining in a single Lipo cel
-local function getCellPercent(cellValue)
+--- since running on long array found to be very intensive to hrous cpu, we are splitting the list to small lists
+local function getCellPercent(wgt, cellValue)
if cellValue == nil then
return 0
end
+ local result = 0;
- -- in case somehow voltage is higher, don't return nil
- if (cellValue > 4.2) then
- return 100
- end
-
- -- Data gathered from commercial lipo sensors
- local myArrayPercentList = { {3,0},{3.093,1},{3.196,2},{3.301,3},{3.401,4},{3.477,5},{3.544,6},{3.601,7},{3.637,8},{3.664,9},{3.679,10},{3.683,11},{3.689,12},{3.692,13},{3.705,14},{3.71,15},{3.713,16},{3.715,17},{3.72,18},{3.731,19},{3.735,20},{3.744,21},{3.753,22},{3.756,23},{3.758,24},{3.762,25},{3.767,26},{3.774,27},{3.78,28},{3.783,29},{3.786,30},{3.789,31},{3.794,32},{3.797,33},{3.8,34},{3.802,35},{3.805,36},{3.808,37},{3.811,38},{3.815,39},{3.818,40},{3.822,41},{3.825,42},{3.829,43},{3.833,44},{3.836,45},{3.84,46},{3.843,47},{3.847,48},{3.85,49},{3.854,50},{3.857,51},{3.86,52},{3.863,53},{3.866,54},{3.87,55},{3.874,56},{3.879,57},{3.888,58},{3.893,59},{3.897,60},{3.902,61},{3.906,62},{3.911,63},{3.918,64},{3.923,65},{3.928,66},{3.939,67},{3.943,68},{3.949,69},{3.955,70},{3.961,71},{3.968,72},{3.974,73},{3.981,74},{3.987,75},{3.994,76},{4.001,77},{4.007,78},{4.014,79},{4.021,80},{4.029,81},{4.036,82},{4.044,83},{4.052,84},{4.062,85},{4.074,86},{4.085,87},{4.095,88},{4.105,89},{4.111,90},{4.116,91},{4.12,92},{4.125,93},{4.129,94},{4.135,95},{4.145,96},{4.176,97},{4.179,98},{4.193,99},{4.2,100} }
-
- for i, v in ipairs(myArrayPercentList) do
- if v[1] >= cellValue then
- result = v[2]
- break
+ for i1, v1 in ipairs(_lipoPercentListSplit) do
+ --is the cellVal < last-value-on-sub-list? (first-val:v1[1], last-val:v1[#v1])
+ if (cellValue <= v1[#v1][1]) then
+ -- cellVal is in this sub-list, find the exact value
+ for i2, v2 in ipairs(v1) do
+ if v2[1] >= cellValue then
+ result = v2[2]
+ return result
+ end
+ end
end
end
- return result
+ -- in case somehow voltage is too high (>4.2), don't return nil
+ return 100
end
--- This function returns a table with cels values
@@ -112,56 +195,45 @@ local function calculateBatteryData(wgt)
return
end
-
- -- this is necessary for simu where cell-count can change
- if #wgt.cellDataHistoryLowest ~= #newCellData then
- wgt.cellDataHistoryLowest = {}
- for k, v in pairs(newCellData) do
- wgt.cellDataHistoryLowest[k] = v
- end
- end
- -- stores the lowest cell values in historical table
- for k, v in pairs(newCellData) do
- if v < wgt.cellDataHistoryLowest[k] then
- wgt.cellDataHistoryLowest[k] = v
- end
- end
-
- --- calc highest of all cels
local cellMax = 0
+ local cellMin = 5
+ local cellSum = 0
for k, v in pairs(newCellData) do
+ -- stores the lowest cell values in historical table
+ if v > 1 and v < wgt.cellDataHistoryLowest[k] then
+ -- min 1v to consider a valid reading
+ wgt.cellDataHistoryLowest[k] = v
+
+ --- calc history lowest of all cells
+ if v < wgt.cellDataHistoryCellLowest then
+ wgt.cellDataHistoryCellLowest = v
+ end
+
+ end
+
+ -- calc highest of all cells
if v > cellMax then
cellMax = v
end
- end
- wgt.cellMax = cellMax
- --- calc lowest of all cels
- local cellMin = 5
- for k, v in pairs(newCellData) do
- if v < cellMin and v > 1 then -- >1 to ignore invalid values
+ --- calc lowest of all cells
+ if v < cellMin and v > 1 then
+ -- min 1v to consider a valid reading
cellMin = v
end
- end
- wgt.cellMin = cellMin
-
- --- calc history lowest of all cells
- if cellMin < wgt.cellDataHistoryCellLowest and cellMin > 1 then -- >1 to ignore invalid values
- wgt.cellDataHistoryCellLowest = cellMin
- end
-
- wgt.cellCount = #newCellData
-
- --- sum of all cells
- local cellSum = 0
- for k, v in pairs(newCellData) do
+ --- sum of all cells
cellSum = cellSum + v
+
+
end
+
+ wgt.cellMin = cellMin
+ wgt.cellMax = cellMax
+ wgt.cellCount = #newCellData
wgt.cellSum = cellSum
--- average of all cells
wgt.cellAvg = wgt.cellSum / wgt.cellCount
- wgt.cellPercent = getCellPercent(wgt.cellMin)
wgt.cellDataLive = newCellData
@@ -183,13 +255,19 @@ local function calculateBatteryData(wgt)
wgt.secondaryValue = "-2"
end
-
wgt.isDataAvailable = true
+ -- calculate intensive CPU data
+ if (periodicHasPassed(wgt.periodic1) or wgt.cellPercent == 0) then
+
+ --wgt.cellPercent = getCellPercent(wgt, wgt.cellMin) -- use batt percentage by lowest cell voltage
+ wgt.cellPercent = getCellPercent(wgt, wgt.cellAvg) -- use batt percentage by average cell voltage
+
+ periodicReset(wgt.periodic1)
+ end
end
-
-- color for battery
-- This function returns green at 100%, red bellow 30% and graduate in between
local function getPercentColor(percent)
@@ -206,34 +284,46 @@ end
-- This function returns green at gvalue, red at rvalue and graduate in between
local function getRangeColor(value, green_value, red_value)
local range = math.abs(green_value - red_value)
- if range==0 then return lcd.RGB(0, 0xdf, 0) end
+ if range == 0 then
+ return lcd.RGB(0, 0xdf, 0)
+ end
+ if value == nil then
+ return lcd.RGB(0, 0xdf, 0)
+ end
if green_value > red_value then
- if value > green_value then return lcd.RGB(0, 0xdf, 0) end
- if value < red_value then return lcd.RGB(0xdf, 0, 0) end
+ if value > green_value then
+ return lcd.RGB(0, 0xdf, 0)
+ end
+ if value < red_value then
+ return lcd.RGB(0xdf, 0, 0)
+ end
g = math.floor(0xdf * (value - red_value) / range)
r = 0xdf - g
return lcd.RGB(r, g, 0)
else
- if value > green_value then return lcd.RGB(0, 0xdf, 0) end
- if value < red_value then return lcd.RGB(0xdf, 0, 0) end
+ if value > green_value then
+ return lcd.RGB(0, 0xdf, 0)
+ end
+ if value < red_value then
+ return lcd.RGB(0xdf, 0, 0)
+ end
r = math.floor(0xdf * (value - green_value) / range)
g = 0xdf - r
return lcd.RGB(r, g, 0)
end
end
-
--- Zone size: 70x39 1/8th top bar
local function refreshZoneTiny(wgt)
local myString = string.format("%2.1fV", wgt.mainValue)
- lcd.drawText(wgt.zone.x + wgt.zone.w -25, wgt.zone.y + 5, wgt.cellPercent .. "%", RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
- lcd.drawText(wgt.zone.x + wgt.zone.w -25, wgt.zone.y + 20, myString, RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
+ lcd.drawText(wgt.zone.x + wgt.zone.w - 25, wgt.zone.y + 5, wgt.cellPercent .. "%", RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
+ lcd.drawText(wgt.zone.x + wgt.zone.w - 25, wgt.zone.y + 20, myString, RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
-- draw batt
lcd.drawRectangle(wgt.zone.x + 50, wgt.zone.y + 9, 16, 25, CUSTOM_COLOR, 2)
- lcd.drawFilledRectangle(wgt.zone.x +50 + 4, wgt.zone.y + 7, 6, 3, CUSTOM_COLOR)
+ lcd.drawFilledRectangle(wgt.zone.x + 50 + 4, wgt.zone.y + 7, 6, 3, CUSTOM_COLOR)
local rect_h = math.floor(25 * wgt.cellPercent / 100)
- lcd.drawFilledRectangle(wgt.zone.x +50, wgt.zone.y + 9 + 25 - rect_h, 16, rect_h, CUSTOM_COLOR + wgt.no_telem_blink)
+ lcd.drawFilledRectangle(wgt.zone.x + 50, wgt.zone.y + 9 + 25 - rect_h, 16, rect_h, CUSTOM_COLOR + wgt.no_telem_blink)
end
--- Zone size: 160x32 1/8th
@@ -271,13 +361,13 @@ local function refreshZoneMedium(wgt)
end
-- draw values
- lcd.drawText(wgt.zone.x, wgt.zone.y + 35, string.format("%2.1fV", wgt.mainValue), DBLSIZE + CUSTOM_COLOR + wgt.shadowed + wgt.no_telem_blink)
+ lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y, string.format("%2.1fV", wgt.mainValue), DBLSIZE + CUSTOM_COLOR + RIGHT + wgt.shadowed + wgt.no_telem_blink)
-- more info if 1/4 is high enough (without trim & slider)
if wgt.zone.h > 80 then
- lcd.drawText(wgt.zone.x , wgt.zone.y + 70, string.format("%2.2fV" , wgt.secondaryValue), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
- lcd.drawText(wgt.zone.x + 50, wgt.zone.y + 70, string.format("dV %2.2fV", wgt.cellMax - wgt.cellMin), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
- lcd.drawText(wgt.zone.x , wgt.zone.y + 84, string.format("Min %2.2fV", wgt.cellDataHistoryCellLowest), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
+ --lcd.drawText(wgt.zone.x + 50 , wgt.zone.y + 70, string.format("%2.2fV" , wgt.secondaryValue), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
+ lcd.drawText(wgt.zone.x, wgt.zone.y + 70, string.format("dV %2.2fV", wgt.cellMax - wgt.cellMin), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
+ lcd.drawText(wgt.zone.x, wgt.zone.y + 84, string.format("Min %2.2fV", wgt.cellDataHistoryCellLowest), SMLSIZE + CUSTOM_COLOR + wgt.no_telem_blink)
end
-- fill batt
@@ -285,27 +375,21 @@ local function refreshZoneMedium(wgt)
lcd.drawGauge(wgt.zone.x + myBatt.x, wgt.zone.y + myBatt.y, myBatt.w, myBatt.h, wgt.cellPercent, 100, CUSTOM_COLOR)
-- draw cells
- local cellH = wgt.zone.h / wgt.cellCount
- if cellH > 20 then cellH =20 end
+ local cellH = 19
local cellX = 118
- local cellW = 58
+ local cellW = wgt.zone.w / 3
+
+ local pos = { { x = 0, y = 38 }, { x = cellW, y = 38 }, { x = 2 * cellW, y = 38 }, { x = 0, y = 57 }, { x = cellW, y = 57 }, { x = 2 * cellW, y = 57 } }
for i = 1, wgt.cellCount, 1 do
- local cellY = wgt.zone.y + (i-1)* (cellH -1)
+ local cellY = wgt.zone.y + (i - 1) * (cellH - 1)
- -- fill current value
- lcd.setColor(CUSTOM_COLOR, getRangeColor(wgt.cellDataLive[i], wgt.cellMax, wgt.cellMax - 0.2))
+ -- fill current cell
--lcd.drawFilledRectangle(wgt.zone.x + cellX , cellY, 58, cellH, CUSTOM_COLOR)
- local percentCurrent = getCellPercent(wgt.cellDataLive[i])
- local percentMin = getCellPercent(wgt.cellDataHistoryLowest[i])
-
- lcd.drawFilledRectangle(wgt.zone.x + cellX , cellY, cellW * percentCurrent / 100, cellH, CUSTOM_COLOR)
- -- fill min
- lcd.setColor(CUSTOM_COLOR, getRangeColor(wgt.cellDataHistoryLowest[i], wgt.cellMax, wgt.cellMax - 0.2))
- lcd.drawFilledRectangle(wgt.zone.x + cellX + ((percentCurrent - percentMin) / 100) , cellY, cellW - (cellW * (percentCurrent - percentMin) / 100), cellH, CUSTOM_COLOR)
-
+ lcd.setColor(CUSTOM_COLOR, getRangeColor(wgt.cellDataLive[i], wgt.cellMax, wgt.cellMax - 0.2))
+ lcd.drawFilledRectangle(wgt.zone.x + pos[i].x, wgt.zone.y + pos[i].y, cellW - 1, 20, CUSTOM_COLOR)
lcd.setColor(CUSTOM_COLOR, WHITE)
- lcd.drawText (wgt.zone.x + cellX + 10, cellY, string.format("%.2f", wgt.cellDataLive[i]), SMLSIZE + CUSTOM_COLOR + wgt.shadowed + wgt.no_telem_blink)
- lcd.drawRectangle (wgt.zone.x + cellX , cellY, 59, cellH, CUSTOM_COLOR , 1)
+ lcd.drawText(wgt.zone.x + pos[i].x + 10, wgt.zone.y + pos[i].y, string.format("%.2f", wgt.cellDataLive[i]), CUSTOM_COLOR + wgt.shadowed)
+ lcd.drawRectangle(wgt.zone.x + pos[i].x, wgt.zone.y + pos[i].y, cellW, 20, CUSTOM_COLOR, 1)
end
-- draws bat
@@ -328,7 +412,7 @@ local function refreshZoneLarge(wgt)
lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y, wgt.cellPercent .. "%", RIGHT + DBLSIZE + CUSTOM_COLOR + wgt.shadowed)
lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y + 30, string.format("%2.1fV", wgt.mainValue), RIGHT + DBLSIZE + CUSTOM_COLOR + wgt.shadowed)
- lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y + 70, string.format("%2.1fV %2.1fS", wgt.secondaryValue, wgt.cellCount), RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.shadowed)
+ lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y + 70, string.format("%2.1fV %dS", wgt.secondaryValue, wgt.cellCount), RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.shadowed)
-- fill batt
lcd.setColor(CUSTOM_COLOR, getPercentColor(wgt.cellPercent))
lcd.drawFilledRectangle(wgt.zone.x + myBatt.x, wgt.zone.y + myBatt.y + myBatt.h + myBatt.cath_h - math.floor(wgt.cellPercent / 100 * myBatt.h), myBatt.w, math.floor(wgt.cellPercent / 100 * myBatt.h), CUSTOM_COLOR)
@@ -372,7 +456,7 @@ local function refreshZoneXLarge(wgt)
lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y + myBatt.y, wgt.cellPercent .. "%", RIGHT + DBLSIZE + CUSTOM_COLOR + wgt.shadowed + wgt.no_telem_blink)
lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y + myBatt.y + 30, string.format("%2.1fV", wgt.mainValue), RIGHT + DBLSIZE + CUSTOM_COLOR + wgt.shadowed + wgt.no_telem_blink)
- lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y + myBatt.y + 105, string.format("%2.1fV %2.1fS", wgt.secondaryValue, wgt.cellCount), RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.shadowed + wgt.no_telem_blink)
+ lcd.drawText(wgt.zone.x + wgt.zone.w, wgt.zone.y + myBatt.y + 105, string.format("%2.1fV %dS", wgt.secondaryValue, wgt.cellCount), RIGHT + SMLSIZE + CUSTOM_COLOR + wgt.shadowed + wgt.no_telem_blink)
-- draw cells
local pos = { { x = 111, y = 38 }, { x = 164, y = 38 }, { x = 217, y = 38 }, { x = 111, y = 57 }, { x = 164, y = 57 }, { x = 217, y = 57 } }
@@ -410,18 +494,32 @@ end
-- This function allow recording of lowest cells when widget is in background
local function background(wgt)
- if (wgt == nil) then return end
+ if (wgt == nil) then
+ return
+ end
+
+ detectResetEvent(wgt)
calculateBatteryData(wgt)
end
local function refresh(wgt)
-
- if (wgt == nil) then return end
- if (wgt.options == nil) then return end
- if (wgt.zone == nil) then return end
- if (wgt.options.LowestCell == nil) then return end
+ if (wgt == nil) then
+ return
+ end
+ if type(wgt) ~= "table" then
+ return
+ end
+ if (wgt.options == nil) then
+ return
+ end
+ if (wgt.zone == nil) then
+ return
+ end
+ if (wgt.options.LowestCell == nil) then
+ return
+ end
if wgt.options.Shadow == 1 then
wgt.shadowed = SHADOWED
@@ -429,6 +527,7 @@ local function refresh(wgt)
wgt.shadowed = 0
end
+ detectResetEvent(wgt)
calculateBatteryData(wgt)
@@ -438,14 +537,17 @@ local function refresh(wgt)
wgt.no_telem_blink = INVERS + BLINK
end
-
- if wgt.zone.w > 380 and wgt.zone.h > 165 then refreshZoneXLarge(wgt)
- elseif wgt.zone.w > 180 and wgt.zone.h > 145 then refreshZoneLarge(wgt)
- elseif wgt.zone.w > 170 and wgt.zone.h > 65 then refreshZoneMedium(wgt)
- elseif wgt.zone.w > 150 and wgt.zone.h > 28 then refreshZoneSmall(wgt)
- elseif wgt.zone.w > 65 and wgt.zone.h > 35 then refreshZoneTiny(wgt)
+ if wgt.zone.w > 380 and wgt.zone.h > 165 then
+ refreshZoneXLarge(wgt)
+ elseif wgt.zone.w > 180 and wgt.zone.h > 145 then
+ refreshZoneLarge(wgt)
+ elseif wgt.zone.w > 170 and wgt.zone.h > 65 then
+ refreshZoneMedium(wgt)
+ elseif wgt.zone.w > 150 and wgt.zone.h > 28 then
+ refreshZoneSmall(wgt)
+ elseif wgt.zone.w > 65 and wgt.zone.h > 35 then
+ refreshZoneTiny(wgt)
end
-
end
-return { name="BattCheck", options=_options, create=create, update=update, background=background, refresh=refresh }
+return { name = "BattCheck", options = _options, create = create, update = update, background = background, refresh = refresh }
\ No newline at end of file
diff --git a/radio/sdcard/horus/WIDGETS/Timer2/main.lua b/radio/sdcard/horus/WIDGETS/Timer2/main.lua
index 6354eee4e..ee4661f2d 100644
--- a/radio/sdcard/horus/WIDGETS/Timer2/main.lua
+++ b/radio/sdcard/horus/WIDGETS/Timer2/main.lua
@@ -14,12 +14,9 @@ local function create(zone, options)
end
local function update(wgt, options)
- if (wgt==nil) then
- print("update(nil)")
- return
- end
+ if (wgt == nil) then return end
wgt.options = options
- print("TimerNumB:" .. options.Timer)
+ --print("TimerNumB:" .. options.Timer)
end
local function background(wgt)
@@ -28,11 +25,11 @@ end
------------------------------------------------------------
--- This size is for top bar wgts
+-- Zone size: top bar widgets
local function refreshZoneTiny(wgt)
end
---- Size is 160x32 1/8th
+--- Zone size: 160x32 1/8th
local function refreshZoneSmall(wgt)
local t1 = model.getTimer(wgt.options.Timer-1)
local timerInfo = string.format("T%s: ", wgt.options.Timer)
@@ -41,7 +38,8 @@ local function refreshZoneSmall(wgt)
return
end
---- Size is 225x98 1/4th (no sliders/trim)
+--- Zone size: 180x70 1/4th (with sliders/trim)
+--- Zone size: 225x98 1/4th (no sliders/trim)
local function refreshZoneMedium(wgt)
local t1 = model.getTimer(wgt.options.Timer-1)
--print(t1.value)
@@ -50,7 +48,7 @@ local function refreshZoneMedium(wgt)
lcd.drawTimer(wgt.zone.x, wgt.zone.y+3, t1.value, XXLSIZE + CUSTOM_COLOR)
end
---- Size is 192x152 1/2
+--- Zone size: 192x152 1/2
local function refreshZoneLarge(wgt)
local t1 = model.getTimer(wgt.options.Timer-1)
--print(t1.value)
@@ -59,8 +57,8 @@ local function refreshZoneLarge(wgt)
lcd.drawTimer(wgt.zone.x, wgt.zone.y+15, t1.value, XXLSIZE + CUSTOM_COLOR)
end
---- Size is 390x172 1/1
---- Size is 460x252 1/1 (no sliders/trim/topbar)
+--- Zone size: 390x172 1/1
+--- Zone size: 460x252 1/1 (no sliders/trim/topbar)
local function refreshZoneXLarge(wgt)
local t1 = model.getTimer(wgt.options.Timer-1)
--print(t1.value)
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/device.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/device.lua
index 8ccdbf285..b6115d088 100644
--- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/device.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/device.lua
@@ -72,7 +72,7 @@ local function incrField(step)
end
else
local min, max = 0, 0
- if field.type <= 5 then
+ if ((field.type <= 5) or (field.type == 8)) then
min = field.min
max = field.max
step = field.step * step
@@ -238,23 +238,21 @@ local function fieldFloatLoad(field, data, offset)
field.default = fieldGetValue(data, offset+12, 4)
fieldUnsignedToSigned(field, 4)
field.prec = data[offset+16]
- if field.prec > 2 then
- field.prec = 2
+ if field.prec > 3 then
+ field.prec = 3
end
field.step = fieldGetValue(data, offset+17, 4)
field.unit, offset = fieldGetString(data, offset+21)
end
+local function formatFloat(num, decimals)
+ local mult = 10^(decimals or 0)
+ local val = num / mult
+ return string.format("%." .. decimals .. "f", val)
+end
+
local function fieldFloatDisplay(field, y, attr)
- local attrnum
- if field.prec == 1 then
- attrnum = LEFT + attr + PREC1
- elseif field.prec == 2 then
- attrnum = LEFT + attr + PREC2
- else
- attrnum = LEFT + attr
- end
- lcd.drawNumber(89, y, field.value, attrnum)
+ lcd.drawText(89, y, formatFloat(field.value, field.prec), LEFT + attr)
lcd.drawText(lcd.getLastPos(), y, field.unit, attr)
end
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SBEC.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SBEC.lua
index 73d2b88e2..bbe819087 100644
--- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SBEC.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SBEC.lua
@@ -273,11 +273,6 @@ local function run(event)
if event == nil then
error("Cannot run as a model script!")
return 2
- elseif event == EVT_PAGE_BREAK or event == EVT_PAGEDN_FIRST or event == EVT_SHIFT_BREAK then
- --selectPage(1)
- elseif event == EVT_PAGE_LONG or event == EVT_PAGEUP_FIRST or event == EVT_SHIFT_LONG then
- --killEvents(event);
- --selectPage(-1)
end
local result = pages[page](event)
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/Graupner HoTT.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/Graupner HoTT.lua
index ff6a3254c..d0a7d4af8 100644
--- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/Graupner HoTT.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/Graupner HoTT.lua
@@ -21,19 +21,41 @@
-- To start operation:
-- Write "HoTT" at address 0..3
-- Write 0xFF at address 4 will request the buffer to be cleared
--- Write 0xDF at address 5
+-- Write 0x0F at address 5
-- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters
-- by 8 lines
--- Write at address 5 sends an order to the RX: 0xDF=start, 0xD7=prev page,
--- 0xDE=next page, 0xD9=enter, 0xDD=next or 0xDB=prev
+-- Write at address 5 sends an order to the RX: 0xXF=start, 0xX7=prev page,
+-- 0xXE=next page, 0xX9=enter, 0xXD=next or 0xXB=prev with X being the sensor
+-- to request data from 8=RX only, 9=Vario, A=GPS, B=Cust, C=ESC, D=GAM, E=EAM
-- Write at address 4 the value 0xFF will request the buffer to be cleared
-- !! Before exiting the script must write 0 at address 0 for normal operation !!
--###############################################################################
+HoTT_Sensor = 0
+Timer_128 = 100
+
local function HoTT_Release()
multiBuffer( 0, 0 )
end
+local function HoTT_Send(button)
+ multiBuffer( 5, 0x80+(HoTT_Sensor*16) + button)
+end
+
+local function HoTT_Sensor_Inc()
+ local detected_sensors=multiBuffer( 4 )
+ local a
+ if detected_sensors ~= 0xFF then
+ repeat
+ HoTT_Sensor=(HoTT_Sensor+1)%7 -- Switch to next sensor
+ if HoTT_Sensor ~= 0 then
+ a = math.floor(detected_sensors/ (2^(HoTT_Sensor-1))) -- shift right
+ end
+ until HoTT_Sensor==0 or a % 2 == 1
+ HoTT_Send( 0x0F )
+ end
+end
+
local function HoTT_Draw_LCD()
local i
local value
@@ -41,12 +63,14 @@ local function HoTT_Draw_LCD()
local result
local offset=0
+ local sensor_name = { "", "+Vario", "+GPS", "+Cust", "+ESC", "+GAM", "+EAM" }
+
lcd.clear()
if LCD_W == 480 then
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
- lcd.drawText(1, 5, "Graupner HoTT RX configuration", MENU_TITLE_COLOR)
+ lcd.drawText(1, 5, "Graupner HoTT: config RX" .. sensor_name[HoTT_Sensor+1] .. " - Menu cycle Sensors", MENU_TITLE_COLOR)
--Draw RX Menu
if multiBuffer( 4 ) == 0xFF then
lcd.drawText(10,50,"No HoTT telemetry...", BLINK)
@@ -56,9 +80,9 @@ local function HoTT_Draw_LCD()
value=multiBuffer( line*21+6+i )
if value > 0x80 then
value = value - 0x80
- lcd.drawText(10+i*16,32+16*line,string.char(value).." ",INVERS)
+ lcd.drawText(10+i*16,32+20*line,string.char(value).." ",INVERS)
else
- lcd.drawText(10+i*16,32+16*line,string.char(value))
+ lcd.drawText(10+i*16,32+20*line,string.char(value))
end
end
end
@@ -68,14 +92,23 @@ local function HoTT_Draw_LCD()
if multiBuffer( 4 ) == 0xFF then
lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE)
else
- for line = 0, 7, 1 do
- for i = 0, 21-1, 1 do
- value=multiBuffer( line*21+6+i )
- if value > 0x80 then
- value = value - 0x80
- lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
- else
- lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
+ if Timer_128 ~= 0 then
+ --Intro page
+ Timer_128 = Timer_128 - 1
+ lcd.drawScreenTitle("Graupner Hott",0,0)
+ lcd.drawText(2,17,"Configuration of RX" .. sensor_name[HoTT_Sensor+1] ,SMLSIZE)
+ lcd.drawText(2,37,"Press menu to cycle Sensors" ,SMLSIZE)
+ else
+ --Menu page
+ for line = 0, 7, 1 do
+ for i = 0, 21-1, 1 do
+ value=multiBuffer( line*21+6+i )
+ if value > 0x80 then
+ value = value - 0x80
+ lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
+ else
+ lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
+ end
end
end
end
@@ -98,7 +131,10 @@ local function HoTT_Init()
--Request init of the RX buffer
multiBuffer( 4, 0xFF )
--Request RX to send the config menu
- multiBuffer( 5, 0xDF )
+ HoTT_Send( 0x0F )
+ HoTT_Sensor = 0;
+ HoTT_Detected_Sensors=0;
+ Timer_128 = 100
end
-- Main
@@ -111,18 +147,21 @@ local function HoTT_Run(event)
return 2
else
if event == EVT_VIRTUAL_PREV_PAGE then
- killEvents(event);
- multiBuffer( 5, 0xD7 )
- elseif event == EVT_VIRTUAL_NEXT_PAGE then
- multiBuffer( 5, 0xDE )
+ killEvents(event)
+ HoTT_Send( 0x07 )
elseif event == EVT_VIRTUAL_ENTER then
- multiBuffer( 5, 0xD9 )
- elseif event == EVT_VIRTUAL_NEXT then
- multiBuffer( 5, 0xDD )
+ HoTT_Send( 0x09 )
elseif event == EVT_VIRTUAL_PREV then
- multiBuffer( 5, 0xDB )
+ HoTT_Send( 0x0B )
+ elseif event == EVT_VIRTUAL_NEXT then
+ HoTT_Send( 0x0D )
+ elseif event == EVT_VIRTUAL_NEXT_PAGE then
+ HoTT_Send( 0x0E )
+ elseif event == EVT_VIRTUAL_MENU then
+ Timer_128 = 100
+ HoTT_Sensor_Inc()
else
- multiBuffer( 5, 0xDF )
+ HoTT_Send( 0x0F )
end
HoTT_Draw_LCD()
return 0
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt
new file mode 100644
index 000000000..bf61d8ca6
--- /dev/null
+++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt
@@ -0,0 +1,157 @@
+1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
+1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
+1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL
+1,3,Flysky,V912,1,BtmBtn,TopBtn
+1,4,Flysky,CX20,0,CH5,CH6,CH7
+28,0,Flysky_AFHDS2A,PWM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+53,0,Flyzone,FZ-410,0
+2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
+2,1,Hubsan,H301,0,RTH,Light,Stab,Video
+2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
+41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
+60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
+37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
+37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
+37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
+25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
+3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
+3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8
+67,0,FrSkyL,LR12,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+67,1,FrSkyL,LR12_6CH,0,CH5,CH6
+15,0,FrSkyX,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+15,1,FrSkyX,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
+15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8
+15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
+64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8
+64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+55,1,FrSkyRX,CloneTX,0
+39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
+39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
+39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
+57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
+68,0,Skyartec,Std,0,CH5,CH6,CH7
+7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
+7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
+7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+7,3,Devo,6CH,0,CH5,CH6
+7,4,Devo,7CH,0,CH5,CH6,CH7
+30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
+30,1,WK2x01,WK2401,0
+30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
+30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
+30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
+30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
+6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
+24,0,Assan,Std,0,CH5,CH6,CH7,CH8
+14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
+14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
+14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
+14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
+14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
+59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
+42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
+42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
+34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
+13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
+12,0,CX10,Green,1,Flip,Rate
+12,1,CX10,Blue,1,Flip,Rate,Pict,Video
+12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
+12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
+12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
+12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
+33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
+45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
+45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
+45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
+16,0,ESKY,Std,0,Gyro,Pitch
+16,1,ESKY,ET4,0,Gyro,Pitch
+35,0,ESKY150,4CH,0
+35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
+20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
+20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
+23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
+32,0,GW008,FY326,1,Flip
+36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
+36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
+36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
+36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
+4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
+9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
+26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
+26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
+26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
+18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
+17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
+17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
+17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
+17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
+44,0,NCC1701,Std,1,Warp
+51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
+66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
+29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
+29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
+29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
+31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
+31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
+31,2,Q303,CX10D,1,Arm,Flip
+31,3,Q303,CX10WD,1,Arm,Flip
+50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
+50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
+11,0,SLT,V1,0,Gear,Pitch
+11,1,SLT,V2,0,CH5,CH6,CH7,CH8
+11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
+11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
+11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
+10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
+10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
+5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
+5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
+61,0,Tiger,Std,1,Flip,Light
+46,0,V911s,Std,1,Calib
+46,1,E119,Std,1,Calib
+62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
+62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
+8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
+8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
+8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
+8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
+8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
+65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8
+65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8
+56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+19,0,Shenqi,Cycle,1
+4,1,Hisky,HK310,0,Aux
+43,0,Traxxas,6519,0
+52,0,ZSX,280,1,Light
+48,0,V761,Std,1,Gyro
+49,0,KF606,Std,1,Trim
+47,0,GD00x,V1,1,Trim,LED,Rate
+47,1,GD00x,V2,1,Trim,LED,Rate
+58,0,FX816,P38,1
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
new file mode 100644
index 000000000..42de75e4f
--- /dev/null
+++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
@@ -0,0 +1,302 @@
+
+local toolName = "TNS|Multi chan namer|TNE"
+
+---- #########################################################################
+---- # #
+---- # Copyright (C) OpenTX #
+-----# #
+---- # 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. #
+---- # #
+---- #########################################################################
+
+local protocol_name = ""
+local sub_protocol_name = ""
+local bind_ch = 0
+local module_conf = {}
+local module_pos = "Internal"
+local file_ok = 0
+local done = 0
+local protocol = 0
+local sub_protocol = 0
+local f_seek = 0
+local channel_names={}
+local num_search = "Searching"
+
+local function drawScreenTitle(title)
+ if LCD_W == 480 then
+ lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
+ lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
+ else
+ lcd.drawScreenTitle(title, 0, 0)
+ end
+end
+
+function bitand(a, b)
+ local result = 0
+ local bitval = 1
+ while a > 0 and b > 0 do
+ if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
+ result = result + bitval -- set the current bit
+ end
+ bitval = bitval * 2 -- shift left
+ a = math.floor(a/2) -- shift right
+ b = math.floor(b/2)
+ end
+ return result
+end
+
+local function Multi_Draw_LCD(event)
+ local line = 0
+
+ lcd.clear()
+ drawScreenTitle("Multi channels namer")
+
+ --Display settings
+ local lcd_opt = 0
+ if LCD_W == 480 then
+ x_pos = 10
+ y_pos = 32
+ y_inc = 20
+ else
+ x_pos = 0
+ y_pos = 9
+ y_inc = 8
+ lcd_opt = SMLSIZE
+ end
+
+ --Multi Module detection
+ if module_conf["Type"] ~= 6 then
+ if LCD_W == 480 then
+ lcd.drawText(10,50,"No Multi module configured...", BLINK)
+ else
+ --Draw on LCD_W=128
+ lcd.drawText(2,17,"No Multi module configured...",SMLSIZE)
+ end
+ return
+ else
+ lcd.drawText(x_pos, y_pos+y_inc*line,module_pos .. " Multi detected.", lcd_opt)
+ line = line + 1
+ end
+
+ --Channel order
+ if (ch_order == -1) then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Channels order can't be read from Multi...", lcd_opt)
+ line = line + 1
+ end
+
+ --Can't open file MultiChan.txt
+ if file_ok == 0 then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Can't read MultiChan.txt file...", lcd_opt)
+ return
+ end
+
+ if ( protocol_name == "" or sub_protocol_name == "" ) and f_seek ~=-1 then
+ local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
+ if f == nil then return end
+ lcd.drawText(x_pos, y_pos+y_inc*line,num_search, lcd_opt)
+ num_search = num_search .. "."
+ if #num_search > 15 then
+ num_search = string.sub(num_search,1,9)
+ end
+ local proto = 0
+ local sub_proto = 0
+ local proto_name = ""
+ local sub_proto_name = ""
+ local channels = ""
+ local nbr_try = 0
+ local nbr_car = 0
+ repeat
+ io.seek(f, f_seek)
+ local data = io.read(f, 100) -- read 100 characters
+ if #data ==0 then
+ f_seek = -1 -- end of file
+ break
+ end
+ proto, sub_proto, proto_name, sub_proto_name, bind_ch, channels = string.match(data,'(%d+),(%d),([%w-_ ]+),([%w-_ ]+),(%d)(.+)')
+ if proto ~= nil and sub_proto ~= nil and protocol_name ~= nil and sub_protocol_name ~= nil and bind_ch ~= nil then
+ if tonumber(proto) == protocol and tonumber(sub_proto) == sub_protocol then
+ protocol_name = proto_name
+ sub_protocol_name = sub_proto_name
+ bind_ch = tonumber(bind_ch)
+ if channels ~= nil then
+ --extract channel names
+ nbr_car = string.find(channels, "\r")
+ if nbr_car == nil then nbr_car = string.find(channels, "\n") end
+ if nbr_car ~= nil then
+ channels = string.sub(channels,1,nbr_car-1)
+ end
+ local i = 5
+ for k in string.gmatch(channels, ",([%w-_ ]+)") do
+ channel_names[i] = k
+ i = i + 1
+ end
+ end
+ f_seek = -1 -- protocol found
+ break
+ end
+ end
+ if f_seek ~= -1 then
+ nbr_car = string.find(data, "\n")
+ if nbr_car == nil then nbr_car = string.find(data, "\r") end
+ if nbr_car == nil then
+ f_seek = -1 -- end of file
+ break
+ end
+ f_seek = f_seek + nbr_car -- seek to next line
+ nbr_try = nbr_try + 1
+ end
+ until nbr_try > 20 or f_seek == -1
+ io.close(f)
+ end
+
+ if f_seek ~= -1 then
+ return -- continue searching...
+ end
+
+ --Protocol & Sub_protocol
+ if protocol_name == "" or sub_protocol_name == "" then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Unknown protocol "..tostring(protocol).."/"..tostring(sub_protocol).." ...", lcd_opt)
+ return
+ elseif LCD_W > 128 then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name .. " / SubProtocol: " .. sub_protocol_name, lcd_opt)
+ line = line + 1
+ else
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name, lcd_opt)
+ line = line + 1
+ lcd.drawText(x_pos, y_pos+y_inc*line,"SubProtocol: " .. sub_protocol_name, lcd_opt)
+ line = line + 1
+ end
+
+ text1=""
+ text2=""
+ for i,v in ipairs(channel_names) do
+ if i<=8 then
+ if i==1 then
+ text1 = v
+ else
+ text1=text1 .. "," .. v
+ end
+ else
+ if i==9 then
+ text2 = v
+ else
+ text2=text2 .. "," .. v
+ end
+ end
+ end
+ if LCD_W > 128 then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Channels: " .. text1, lcd_opt)
+ line = line + 1
+ if text2 ~= "" then
+ lcd.drawText(x_pos*9, y_pos+y_inc*line,text2, lcd_opt)
+ line = line + 1
+ end
+ end
+
+ if event ~= EVT_VIRTUAL_ENTER and done == 0 then
+ lcd.drawText(x_pos, y_pos+y_inc*line," Save", lcd_opt + INVERS + BLINK)
+ return
+ end
+
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Setting channel names.", lcd_opt)
+ line = line + 1
+ local output, nbr
+ if done == 0 then
+ for i,v in ipairs(channel_names) do
+ output = model.getOutput(i-1)
+ output["name"] = v
+ model.setOutput(i-1,output)
+ nbr = i
+ end
+ for i = nbr, 15 do
+ output = model.getOutput(i)
+ output["name"] = "n-a"
+ model.setOutput(i,output)
+ end
+ if bind_ch == 1 then
+ output = model.getOutput(15)
+ output["name"] = "BindCH"
+ model.setOutput(15,output)
+ end
+ done = 1
+ end
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Done!", lcd_opt)
+ line = line + 1
+end
+
+-- Init
+local function Multi_Init()
+ module_conf = model.getModule(0)
+ if module_conf["Type"] ~= 6 then
+ module_pos = "External"
+ module_conf = model.getModule(1)
+ if module_conf["Type"] ~= 6 then
+ return
+ end
+ end
+
+ protocol = module_conf["protocol"]
+ sub_protocol = module_conf["subProtocol"]
+
+ --Exceptions on first 4 channels...
+ local stick_names = { "Rud", "Ele", "Thr", "Ail" }
+ if ( protocol == 4 and sub_protocol ==1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX
+ stick_names[2] = "n-a"
+ stick_names[4] = "n-a"
+ elseif protocol == 43 then -- Traxxas
+ stick_names[2] = "Aux4"
+ stick_names[4] = "Aux3"
+ elseif protocol == 48 then -- V761
+ stick_names[4] = "n-a"
+ elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
+ stick_names[1] = "n-a"
+ stick_names[2] = "n-a"
+ end
+
+ --Determine fist 4 channels order
+ local ch_order=module_conf["channelsOrder"]
+ if (ch_order == -1) then
+ channel_names[1] = stick_names[defaultChannel(0)+1]
+ channel_names[2] = stick_names[defaultChannel(1)+1]
+ channel_names[3] = stick_names[defaultChannel(2)+1]
+ channel_names[4] = stick_names[defaultChannel(3)+1]
+ else
+ channel_names[bitand(ch_order,3)+1] = stick_names[4]
+ ch_order = math.floor(ch_order/4)
+ channel_names[bitand(ch_order,3)+1] = stick_names[2]
+ ch_order = math.floor(ch_order/4)
+ channel_names[bitand(ch_order,3)+1] = stick_names[3]
+ ch_order = math.floor(ch_order/4)
+ channel_names[bitand(ch_order,3)+1] = stick_names[1]
+ end
+ --Check MultiChan.txt
+ local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
+ if f == nil then return end
+ file_ok = 1
+ io.close(f)
+end
+
+-- Main
+local function Multi_Run(event)
+ if event == nil then
+ error("Cannot be run as a model script!")
+ return 2
+ else
+ Multi_Draw_LCD(event)
+ if event == EVT_VIRTUAL_EXIT then
+ return 2
+ end
+ end
+ return 0
+end
+
+return { init=Multi_Init, run=Multi_Run }
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua
index b30185e2f..bcd9238f4 100755
--- a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua
@@ -52,10 +52,10 @@ end
local function fieldIncDec(event, value, max, force)
if edit or force==true then
- if event == EVT_ROT_LEFT or event == EVT_UP_BREAK then
+ if event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_PREV_REPT then
value = (value + max)
dirty = true
- elseif event == EVT_ROT_RIGHT or event == EVT_DOWN_BREAK then
+ elseif event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then
value = (value + max + 2)
dirty = true
end
@@ -66,12 +66,12 @@ end
local function valueIncDec(event, value, min, max)
if edit then
- if event == EVT_ROT_RIGHT or event == EVT_RIGHT_BREAK then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
if value < max then
value = (value + 1)
dirty = true
end
- elseif event == EVT_ROT_LEFT or event == EVT_LEFT_BREAK then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
if value > min then
value = (value - 1)
dirty = true
@@ -82,22 +82,22 @@ local function valueIncDec(event, value, min, max)
end
local function navigate(event, fieldMax, prevPage, nextPage)
- if event == EVT_ENTER_BREAK then
+ if event == EVT_VIRTUAL_ENTER then
edit = not edit
dirty = true
elseif edit then
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
edit = false
dirty = true
elseif not dirty then
dirty = blinkChanged()
end
else
- if event == EVT_PAGE_BREAK or event==EVT_RIGHT_BREAK then
+ if event == EVT_VIRTUAL_NEXT then
page = nextPage
field = 0
dirty = true
- elseif event == EVT_PAGE_LONG or event==EVT_LEFT_BREAK then
+ elseif event == EVT_VIRTUAL_PREV then
page = prevPage
field = 0
killEvents(event);
@@ -120,7 +120,7 @@ local function getFieldFlags(position)
end
local function channelIncDec(event, value)
- if not edit and event==EVT_MENU_BREAK then
+ if not edit and event==EVT_VIRTUAL_MENU then
servoPage = value
dirty = true
else
@@ -276,7 +276,7 @@ local function servoMenu(event)
limits.revert = fieldIncDec(event, limits.revert, 1)
end
model.setOutput(servoPage, limits)
- elseif event == EVT_EXIT_BREAK then
+ elseif event == EVT_VIRTUAL_EXIT then
servoPage = nil
dirty = true
end
@@ -348,9 +348,9 @@ local function confirmationMenu(event)
navigate(event, fieldsMax, RUDDER_PAGE, page)
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
- elseif event == EVT_ENTER_LONG then
+ elseif event == EVT_VIRTUAL_ENTER_LONG then
killEvents(event)
applySettings()
return 2
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua
index ebc7c536f..321b7324f 100755
--- a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua
@@ -58,10 +58,10 @@ end
local function fieldIncDec(event, value, max, force)
if edit or force==true then
- if event == EVT_ROT_RIGHT then
+ if event == EVT_VIRTUAL_INC then
value = (value + max)
dirty = true
- elseif event == EVT_ROT_LEFT then
+ elseif event == EVT_VIRTUAL_DEC then
value = (value + max + 2)
dirty = true
end
@@ -72,12 +72,12 @@ end
local function valueIncDec(event, value, min, max)
if edit then
- if event == EVT_ROT_RIGHT or event == EVT_RIGHT_FIRST then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
if value < max then
value = (value + 1)
dirty = true
end
- elseif event == EVT_ROT_LEFT or event == EVT_LEFT_FIRST then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
if value > min then
value = (value - 1)
dirty = true
@@ -88,11 +88,11 @@ local function valueIncDec(event, value, min, max)
end
local function navigate(event, fieldMax, prevPage, nextPage)
- if event == EVT_ENTER_BREAK then
+ if event == EVT_VIRTUAL_ENTER then
edit = not edit
dirty = true
elseif edit then
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
edit = false
dirty = true
elseif not dirty then
@@ -126,7 +126,7 @@ local function getFieldFlags(position)
end
local function channelIncDec(event, value)
- if not edit and event==EVT_MENU_BREAK then
+ if not edit and event==EVT_VIRTUAL_MENU then
servoPage = value
dirty = true
else
@@ -137,12 +137,12 @@ end
local function switchValueIncDec(event, value, min, max)
if edit then
- if event == EVT_ROT_RIGHT or event == EVT_RIGHT_FIRST then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
if value < max then
value = (value + 1)
dirty = true
end
- elseif event == EVT_ROT_LEFT or event == EVT_LEFT_FIRST then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
if value > min then
value = (value - 1)
dirty = true
@@ -153,7 +153,7 @@ local function switchValueIncDec(event, value, min, max)
end
local function switchIncDec(event, value)
- if not edit and event==EVT_MENU_BREAK then
+ if not edit and event== EVT_VIRTUAL_MENU then
servoPage = value
dirty = true
else
@@ -165,8 +165,8 @@ end
-- Init function
local function init()
thrCH1 = defaultChannel(2)
- rollCH1 = defaultChannel(0)
- yawCH1 = defaultChannel(3)
+ rollCH1 = defaultChannel(3)
+ yawCH1 = defaultChannel(0)
pitchCH1 = defaultChannel(1)
local ver, radio, maj, minor, rev = getVersion()
if string.match(radio, "x7") then
@@ -399,9 +399,9 @@ local function confirmationMenu(event)
navigate(event, fieldsMax, BEEPER_PAGE, page)
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
- elseif event == EVT_ENTER_LONG then
+ elseif event == EVT_VIRTUAL_ENTER_LONG then
killEvents(event)
applySettings()
return 2
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua
index 6558b8f12..26282cdf7 100755
--- a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua
@@ -62,10 +62,10 @@ end
local function fieldIncDec(event, value, max, force)
if edit or force==true then
- if event == EVT_ROT_LEFT or event == EVT_UP_BREAK then
+ if event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
value = (value + max)
dirty = true
- elseif event == EVT_ROT_RIGHT or event == EVT_DOWN_BREAK then
+ elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
value = (value + max + 2)
dirty = true
end
@@ -76,12 +76,12 @@ end
local function valueIncDec(event, value, min, max)
if edit then
- if event == EVT_ROT_RIGHT or event == EVT_RIGHT_BREAK then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
if value < max then
value = (value + 1)
dirty = true
end
- elseif event == EVT_ROT_LEFT or event == EVT_LEFT_BREAK then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
if value > min then
value = (value - 1)
dirty = true
@@ -92,11 +92,11 @@ local function valueIncDec(event, value, min, max)
end
local function navigate(event, fieldMax, prevPage, nextPage)
- if event == EVT_ENTER_BREAK then
+ if event == EVT_VIRTUAL_ENTER then
edit = not edit
dirty = true
elseif edit then
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
edit = false
dirty = true
elseif not dirty then
@@ -130,7 +130,7 @@ local function getFieldFlags(position)
end
local function channelIncDec(event, value)
- if not edit and event==EVT_MENU_BREAK then
+ if not edit and event==EVT_VIRTUAL_MENU then
servoPage = value
dirty = true
else
@@ -420,7 +420,7 @@ local function servoMenu(event)
limits.revert = fieldIncDec(event, limits.revert, 1)
end
model.setOutput(servoPage, limits)
- elseif event == EVT_EXIT_BREAK then
+ elseif event == EVT_VIRTUAL_EXIT then
servoPage = nil
dirty = true
end
@@ -544,9 +544,9 @@ local function confirmationMenu(event)
navigate(event, fieldsMax, TAIL_PAGE, page)
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
- elseif event == EVT_ENTER_LONG then
+ elseif event == EVT_VIRTUAL_ENTER_LONG then
killEvents(event)
applySettings()
return 2
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/wizard.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/wizard.lua
index 513ce253a..06f365c9c 100755
--- a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/wizard.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/wizard.lua
@@ -14,8 +14,6 @@
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
--- Navigation variables
-local dirty = true
-- Model types
local modelType = 0
@@ -25,12 +23,10 @@ local MODELTYPE_QUAD = 2
-- Common functions
local function fieldIncDec(event, value, max)
- if event == EVT_ROT_LEFT or event == EVT_UP_BREAK then
+ if event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
value = (value + max)
- dirty = true
- elseif event == EVT_ROT_RIGHT or event == EVT_DOWN_BREAK then
+ elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
value = (value + max + 2)
- dirty = true
end
value = (value % (max+1))
return value
@@ -38,7 +34,7 @@ end
-- Model Type Menu
local function modelTypeSurround(index)
- if(index<=1) then
+ if index <= 1 then
lcd.drawFilledRectangle(59*(index%2)+12, 13, 43, 23)
else
lcd.drawFilledRectangle(59*(index%2)+12, 34, 40, 20)
@@ -56,11 +52,8 @@ local function drawModelChoiceMenu()
end
local function modelTypeMenu(event)
- if dirty == true then
- drawModelChoiceMenu()
- dirty = false
- end
- if event == EVT_ENTER_BREAK then
+ drawModelChoiceMenu()
+ if event == EVT_VIRTUAL_ENTER then
if modelType == MODELTYPE_PLANE then
return "plane.lua"
elseif modelType == MODELTYPE_DELTA then
@@ -68,7 +61,6 @@ local function modelTypeMenu(event)
elseif modelType == MODELTYPE_QUAD then
return "multi.lua"
end
- dirty = true
else
modelType = fieldIncDec(event, modelType, 2)
end
@@ -81,7 +73,7 @@ local function run(event)
error("Cannot be run as a model script!")
end
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
end
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/snake.lua b/radio/sdcard/taranis-x7/SCRIPTS/snake.lua
index 012a9f1e1..d3a1914bb 100644
--- a/radio/sdcard/taranis-x7/SCRIPTS/snake.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/snake.lua
@@ -127,7 +127,7 @@ local function run(event)
raise("Cannot be run as a model script!")
end
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
end
diff --git a/radio/sdcard/taranis-x7/SxR Calibrate/SxR_Calibrate.lua b/radio/sdcard/taranis-x7/SxR Calibrate/SxR_Calibrate.lua
index 5b2e141a8..b9e406691 100644
--- a/radio/sdcard/taranis-x7/SxR Calibrate/SxR_Calibrate.lua
+++ b/radio/sdcard/taranis-x7/SxR Calibrate/SxR_Calibrate.lua
@@ -62,10 +62,10 @@ local function runWarningPage(event)
lcd.drawText(0, 30, "power, and a level surface.", SMLSIZE)
lcd.drawText(0, 40, "Press [Enter] when ready", SMLSIZE)
lcd.drawText(0, 50, "Press [Exit] to cancel", SMLSIZE)
- if event == EVT_ENTER_BREAK then
+ if event == EVT_VIRTUAL_ENTER then
selectPage(1)
return 0
- elseif event == EVT_EXIT_BREAK then
+ elseif event == EVT_VIRTUAL_EXIT then
return 2
end
return 0
@@ -186,9 +186,9 @@ end
-- Main
local function runFieldsPage(event)
- if event == EVT_EXIT_BREAK then -- exit script
+ if event == EVT_VIRTUAL_EXIT then -- exit script
return 2
- elseif event == EVT_ENTER_BREAK then -- toggle editing/selecting current field
+ elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
if fields[current][4] ~= nil then
edit = not edit
if edit == false then
@@ -196,15 +196,15 @@ local function runFieldsPage(event)
end
end
elseif edit then
- if event == EVT_PLUS_FIRST or event == EVT_ROT_RIGHT or event == EVT_PLUS_REPT or event == EVT_DOWN_BREAK then
+ if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REP then
addField(1)
- elseif event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT or event == EVT_MINUS_REPT or event == EVT_UP_BREAK then
+ elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_PREV_REP then
addField(-1)
end
else
- if event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT or event == EVT_UP_BREAK then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REP then
selectField(1)
- elseif event == EVT_PLUS_FIRST or event == EVT_ROT_RIGHT or event == EVT_DOWN_BREAK then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REP then
selectField(-1)
end
end
@@ -260,9 +260,9 @@ local function runCalibrationPage(event)
-- lcd.drawText(10, 19, "Done",0)
lcd.drawText(0, 56, "Press [Exit] when ready", attr)
end
- if calibrationStep > 6 and (event == EVT_ENTER_BREAK or event == EVT_EXIT_BREAK) then
+ if calibrationStep > 6 and (event == EVT_VIRTUAL_ENTER or event == EVT_VIRTUAL_EXIT) then
return 2
- elseif event == EVT_ENTER_BREAK and positionConfirmed then
+ elseif event == EVT_VIRTUAL_ENTER and positionConfirmed then
calibrationState = 1
positionConfirmed = 0
end
@@ -284,9 +284,9 @@ local function run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
- elseif event == EVT_PAGE_BREAK or event==EVT_RIGHT_BREAK then
+ elseif event == EVT_VIRTUAL_NEXT_PAGE then
selectPage(1)
- elseif event == EVT_PAGE_LONG or event==EVT_LEFT_BREAK then
+ elseif event == EVT_VIRTUAL_PREV_PAGE then
killEvents(event);
selectPage(-1)
end
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/device.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/device.lua
index 58416af36..833ec6d83 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/device.lua
+++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/device.lua
@@ -72,7 +72,7 @@ local function incrField(step)
end
else
local min, max = 0, 0
- if field.type <= 5 then
+ if ((field.type <= 5) or (field.type == 8)) then
min = field.min
max = field.max
step = field.step * step
@@ -238,23 +238,21 @@ local function fieldFloatLoad(field, data, offset)
field.default = fieldGetValue(data, offset+12, 4)
fieldUnsignedToSigned(field, 4)
field.prec = data[offset+16]
- if field.prec > 2 then
- field.prec = 2
+ if field.prec > 3 then
+ field.prec = 3
end
field.step = fieldGetValue(data, offset+17, 4)
field.unit, offset = fieldGetString(data, offset+21)
end
+local function formatFloat(num, decimals)
+ local mult = 10^(decimals or 0)
+ local val = num / mult
+ return string.format("%." .. decimals .. "f", val)
+end
+
local function fieldFloatDisplay(field, y, attr)
- local attrnum
- if field.prec == 1 then
- attrnum = LEFT + attr + PREC1
- elseif field.prec == 2 then
- attrnum = LEFT + attr + PREC2
- else
- attrnum = LEFT + attr
- end
- lcd.drawNumber(140, y, field.value, attrnum)
+ lcd.drawText(140, y, formatFloat(field.value, field.prec), LEFT + attr)
lcd.drawText(lcd.getLastPos(), y, field.unit, attr)
end
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SBEC.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SBEC.lua
index 73d2b88e2..bbe819087 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SBEC.lua
+++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SBEC.lua
@@ -273,11 +273,6 @@ local function run(event)
if event == nil then
error("Cannot run as a model script!")
return 2
- elseif event == EVT_PAGE_BREAK or event == EVT_PAGEDN_FIRST or event == EVT_SHIFT_BREAK then
- --selectPage(1)
- elseif event == EVT_PAGE_LONG or event == EVT_PAGEUP_FIRST or event == EVT_SHIFT_LONG then
- --killEvents(event);
- --selectPage(-1)
end
local result = pages[page](event)
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/Graupner HoTT.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/Graupner HoTT.lua
index ff6a3254c..d0a7d4af8 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/Graupner HoTT.lua
+++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/Graupner HoTT.lua
@@ -21,19 +21,41 @@
-- To start operation:
-- Write "HoTT" at address 0..3
-- Write 0xFF at address 4 will request the buffer to be cleared
--- Write 0xDF at address 5
+-- Write 0x0F at address 5
-- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters
-- by 8 lines
--- Write at address 5 sends an order to the RX: 0xDF=start, 0xD7=prev page,
--- 0xDE=next page, 0xD9=enter, 0xDD=next or 0xDB=prev
+-- Write at address 5 sends an order to the RX: 0xXF=start, 0xX7=prev page,
+-- 0xXE=next page, 0xX9=enter, 0xXD=next or 0xXB=prev with X being the sensor
+-- to request data from 8=RX only, 9=Vario, A=GPS, B=Cust, C=ESC, D=GAM, E=EAM
-- Write at address 4 the value 0xFF will request the buffer to be cleared
-- !! Before exiting the script must write 0 at address 0 for normal operation !!
--###############################################################################
+HoTT_Sensor = 0
+Timer_128 = 100
+
local function HoTT_Release()
multiBuffer( 0, 0 )
end
+local function HoTT_Send(button)
+ multiBuffer( 5, 0x80+(HoTT_Sensor*16) + button)
+end
+
+local function HoTT_Sensor_Inc()
+ local detected_sensors=multiBuffer( 4 )
+ local a
+ if detected_sensors ~= 0xFF then
+ repeat
+ HoTT_Sensor=(HoTT_Sensor+1)%7 -- Switch to next sensor
+ if HoTT_Sensor ~= 0 then
+ a = math.floor(detected_sensors/ (2^(HoTT_Sensor-1))) -- shift right
+ end
+ until HoTT_Sensor==0 or a % 2 == 1
+ HoTT_Send( 0x0F )
+ end
+end
+
local function HoTT_Draw_LCD()
local i
local value
@@ -41,12 +63,14 @@ local function HoTT_Draw_LCD()
local result
local offset=0
+ local sensor_name = { "", "+Vario", "+GPS", "+Cust", "+ESC", "+GAM", "+EAM" }
+
lcd.clear()
if LCD_W == 480 then
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
- lcd.drawText(1, 5, "Graupner HoTT RX configuration", MENU_TITLE_COLOR)
+ lcd.drawText(1, 5, "Graupner HoTT: config RX" .. sensor_name[HoTT_Sensor+1] .. " - Menu cycle Sensors", MENU_TITLE_COLOR)
--Draw RX Menu
if multiBuffer( 4 ) == 0xFF then
lcd.drawText(10,50,"No HoTT telemetry...", BLINK)
@@ -56,9 +80,9 @@ local function HoTT_Draw_LCD()
value=multiBuffer( line*21+6+i )
if value > 0x80 then
value = value - 0x80
- lcd.drawText(10+i*16,32+16*line,string.char(value).." ",INVERS)
+ lcd.drawText(10+i*16,32+20*line,string.char(value).." ",INVERS)
else
- lcd.drawText(10+i*16,32+16*line,string.char(value))
+ lcd.drawText(10+i*16,32+20*line,string.char(value))
end
end
end
@@ -68,14 +92,23 @@ local function HoTT_Draw_LCD()
if multiBuffer( 4 ) == 0xFF then
lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE)
else
- for line = 0, 7, 1 do
- for i = 0, 21-1, 1 do
- value=multiBuffer( line*21+6+i )
- if value > 0x80 then
- value = value - 0x80
- lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
- else
- lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
+ if Timer_128 ~= 0 then
+ --Intro page
+ Timer_128 = Timer_128 - 1
+ lcd.drawScreenTitle("Graupner Hott",0,0)
+ lcd.drawText(2,17,"Configuration of RX" .. sensor_name[HoTT_Sensor+1] ,SMLSIZE)
+ lcd.drawText(2,37,"Press menu to cycle Sensors" ,SMLSIZE)
+ else
+ --Menu page
+ for line = 0, 7, 1 do
+ for i = 0, 21-1, 1 do
+ value=multiBuffer( line*21+6+i )
+ if value > 0x80 then
+ value = value - 0x80
+ lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
+ else
+ lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
+ end
end
end
end
@@ -98,7 +131,10 @@ local function HoTT_Init()
--Request init of the RX buffer
multiBuffer( 4, 0xFF )
--Request RX to send the config menu
- multiBuffer( 5, 0xDF )
+ HoTT_Send( 0x0F )
+ HoTT_Sensor = 0;
+ HoTT_Detected_Sensors=0;
+ Timer_128 = 100
end
-- Main
@@ -111,18 +147,21 @@ local function HoTT_Run(event)
return 2
else
if event == EVT_VIRTUAL_PREV_PAGE then
- killEvents(event);
- multiBuffer( 5, 0xD7 )
- elseif event == EVT_VIRTUAL_NEXT_PAGE then
- multiBuffer( 5, 0xDE )
+ killEvents(event)
+ HoTT_Send( 0x07 )
elseif event == EVT_VIRTUAL_ENTER then
- multiBuffer( 5, 0xD9 )
- elseif event == EVT_VIRTUAL_NEXT then
- multiBuffer( 5, 0xDD )
+ HoTT_Send( 0x09 )
elseif event == EVT_VIRTUAL_PREV then
- multiBuffer( 5, 0xDB )
+ HoTT_Send( 0x0B )
+ elseif event == EVT_VIRTUAL_NEXT then
+ HoTT_Send( 0x0D )
+ elseif event == EVT_VIRTUAL_NEXT_PAGE then
+ HoTT_Send( 0x0E )
+ elseif event == EVT_VIRTUAL_MENU then
+ Timer_128 = 100
+ HoTT_Sensor_Inc()
else
- multiBuffer( 5, 0xDF )
+ HoTT_Send( 0x0F )
end
HoTT_Draw_LCD()
return 0
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt
new file mode 100644
index 000000000..bf61d8ca6
--- /dev/null
+++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt
@@ -0,0 +1,157 @@
+1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
+1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
+1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL
+1,3,Flysky,V912,1,BtmBtn,TopBtn
+1,4,Flysky,CX20,0,CH5,CH6,CH7
+28,0,Flysky_AFHDS2A,PWM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+53,0,Flyzone,FZ-410,0
+2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
+2,1,Hubsan,H301,0,RTH,Light,Stab,Video
+2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
+41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
+60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
+37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
+37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
+37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
+25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
+3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
+3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8
+67,0,FrSkyL,LR12,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+67,1,FrSkyL,LR12_6CH,0,CH5,CH6
+15,0,FrSkyX,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+15,1,FrSkyX,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
+15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8
+15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
+64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8
+64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+55,1,FrSkyRX,CloneTX,0
+39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
+39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
+39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
+57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
+68,0,Skyartec,Std,0,CH5,CH6,CH7
+7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
+7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
+7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+7,3,Devo,6CH,0,CH5,CH6
+7,4,Devo,7CH,0,CH5,CH6,CH7
+30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
+30,1,WK2x01,WK2401,0
+30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
+30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
+30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
+30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
+6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
+24,0,Assan,Std,0,CH5,CH6,CH7,CH8
+14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
+14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
+14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
+14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
+14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
+59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
+42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
+42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
+34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
+13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
+12,0,CX10,Green,1,Flip,Rate
+12,1,CX10,Blue,1,Flip,Rate,Pict,Video
+12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
+12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
+12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
+12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
+33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
+45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
+45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
+45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
+16,0,ESKY,Std,0,Gyro,Pitch
+16,1,ESKY,ET4,0,Gyro,Pitch
+35,0,ESKY150,4CH,0
+35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
+20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
+20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
+23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
+32,0,GW008,FY326,1,Flip
+36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
+36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
+36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
+36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
+4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
+9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
+26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
+26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
+26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
+18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
+17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
+17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
+17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
+17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
+17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
+44,0,NCC1701,Std,1,Warp
+51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
+66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
+29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
+29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
+29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
+31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
+31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
+31,2,Q303,CX10D,1,Arm,Flip
+31,3,Q303,CX10WD,1,Arm,Flip
+50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
+50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
+11,0,SLT,V1,0,Gear,Pitch
+11,1,SLT,V2,0,CH5,CH6,CH7,CH8
+11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
+11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
+11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
+10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
+10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
+5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
+5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
+61,0,Tiger,Std,1,Flip,Light
+46,0,V911s,Std,1,Calib
+46,1,E119,Std,1,Calib
+62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
+62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
+8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
+8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
+8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
+8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
+8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
+65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8
+65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8
+56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+19,0,Shenqi,Cycle,1
+4,1,Hisky,HK310,0,Aux
+43,0,Traxxas,6519,0
+52,0,ZSX,280,1,Light
+48,0,V761,Std,1,Gyro
+49,0,KF606,Std,1,Trim
+47,0,GD00x,V1,1,Trim,LED,Rate
+47,1,GD00x,V2,1,Trim,LED,Rate
+58,0,FX816,P38,1
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
new file mode 100644
index 000000000..42de75e4f
--- /dev/null
+++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
@@ -0,0 +1,302 @@
+
+local toolName = "TNS|Multi chan namer|TNE"
+
+---- #########################################################################
+---- # #
+---- # Copyright (C) OpenTX #
+-----# #
+---- # 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. #
+---- # #
+---- #########################################################################
+
+local protocol_name = ""
+local sub_protocol_name = ""
+local bind_ch = 0
+local module_conf = {}
+local module_pos = "Internal"
+local file_ok = 0
+local done = 0
+local protocol = 0
+local sub_protocol = 0
+local f_seek = 0
+local channel_names={}
+local num_search = "Searching"
+
+local function drawScreenTitle(title)
+ if LCD_W == 480 then
+ lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
+ lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
+ else
+ lcd.drawScreenTitle(title, 0, 0)
+ end
+end
+
+function bitand(a, b)
+ local result = 0
+ local bitval = 1
+ while a > 0 and b > 0 do
+ if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
+ result = result + bitval -- set the current bit
+ end
+ bitval = bitval * 2 -- shift left
+ a = math.floor(a/2) -- shift right
+ b = math.floor(b/2)
+ end
+ return result
+end
+
+local function Multi_Draw_LCD(event)
+ local line = 0
+
+ lcd.clear()
+ drawScreenTitle("Multi channels namer")
+
+ --Display settings
+ local lcd_opt = 0
+ if LCD_W == 480 then
+ x_pos = 10
+ y_pos = 32
+ y_inc = 20
+ else
+ x_pos = 0
+ y_pos = 9
+ y_inc = 8
+ lcd_opt = SMLSIZE
+ end
+
+ --Multi Module detection
+ if module_conf["Type"] ~= 6 then
+ if LCD_W == 480 then
+ lcd.drawText(10,50,"No Multi module configured...", BLINK)
+ else
+ --Draw on LCD_W=128
+ lcd.drawText(2,17,"No Multi module configured...",SMLSIZE)
+ end
+ return
+ else
+ lcd.drawText(x_pos, y_pos+y_inc*line,module_pos .. " Multi detected.", lcd_opt)
+ line = line + 1
+ end
+
+ --Channel order
+ if (ch_order == -1) then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Channels order can't be read from Multi...", lcd_opt)
+ line = line + 1
+ end
+
+ --Can't open file MultiChan.txt
+ if file_ok == 0 then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Can't read MultiChan.txt file...", lcd_opt)
+ return
+ end
+
+ if ( protocol_name == "" or sub_protocol_name == "" ) and f_seek ~=-1 then
+ local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
+ if f == nil then return end
+ lcd.drawText(x_pos, y_pos+y_inc*line,num_search, lcd_opt)
+ num_search = num_search .. "."
+ if #num_search > 15 then
+ num_search = string.sub(num_search,1,9)
+ end
+ local proto = 0
+ local sub_proto = 0
+ local proto_name = ""
+ local sub_proto_name = ""
+ local channels = ""
+ local nbr_try = 0
+ local nbr_car = 0
+ repeat
+ io.seek(f, f_seek)
+ local data = io.read(f, 100) -- read 100 characters
+ if #data ==0 then
+ f_seek = -1 -- end of file
+ break
+ end
+ proto, sub_proto, proto_name, sub_proto_name, bind_ch, channels = string.match(data,'(%d+),(%d),([%w-_ ]+),([%w-_ ]+),(%d)(.+)')
+ if proto ~= nil and sub_proto ~= nil and protocol_name ~= nil and sub_protocol_name ~= nil and bind_ch ~= nil then
+ if tonumber(proto) == protocol and tonumber(sub_proto) == sub_protocol then
+ protocol_name = proto_name
+ sub_protocol_name = sub_proto_name
+ bind_ch = tonumber(bind_ch)
+ if channels ~= nil then
+ --extract channel names
+ nbr_car = string.find(channels, "\r")
+ if nbr_car == nil then nbr_car = string.find(channels, "\n") end
+ if nbr_car ~= nil then
+ channels = string.sub(channels,1,nbr_car-1)
+ end
+ local i = 5
+ for k in string.gmatch(channels, ",([%w-_ ]+)") do
+ channel_names[i] = k
+ i = i + 1
+ end
+ end
+ f_seek = -1 -- protocol found
+ break
+ end
+ end
+ if f_seek ~= -1 then
+ nbr_car = string.find(data, "\n")
+ if nbr_car == nil then nbr_car = string.find(data, "\r") end
+ if nbr_car == nil then
+ f_seek = -1 -- end of file
+ break
+ end
+ f_seek = f_seek + nbr_car -- seek to next line
+ nbr_try = nbr_try + 1
+ end
+ until nbr_try > 20 or f_seek == -1
+ io.close(f)
+ end
+
+ if f_seek ~= -1 then
+ return -- continue searching...
+ end
+
+ --Protocol & Sub_protocol
+ if protocol_name == "" or sub_protocol_name == "" then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Unknown protocol "..tostring(protocol).."/"..tostring(sub_protocol).." ...", lcd_opt)
+ return
+ elseif LCD_W > 128 then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name .. " / SubProtocol: " .. sub_protocol_name, lcd_opt)
+ line = line + 1
+ else
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name, lcd_opt)
+ line = line + 1
+ lcd.drawText(x_pos, y_pos+y_inc*line,"SubProtocol: " .. sub_protocol_name, lcd_opt)
+ line = line + 1
+ end
+
+ text1=""
+ text2=""
+ for i,v in ipairs(channel_names) do
+ if i<=8 then
+ if i==1 then
+ text1 = v
+ else
+ text1=text1 .. "," .. v
+ end
+ else
+ if i==9 then
+ text2 = v
+ else
+ text2=text2 .. "," .. v
+ end
+ end
+ end
+ if LCD_W > 128 then
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Channels: " .. text1, lcd_opt)
+ line = line + 1
+ if text2 ~= "" then
+ lcd.drawText(x_pos*9, y_pos+y_inc*line,text2, lcd_opt)
+ line = line + 1
+ end
+ end
+
+ if event ~= EVT_VIRTUAL_ENTER and done == 0 then
+ lcd.drawText(x_pos, y_pos+y_inc*line," Save", lcd_opt + INVERS + BLINK)
+ return
+ end
+
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Setting channel names.", lcd_opt)
+ line = line + 1
+ local output, nbr
+ if done == 0 then
+ for i,v in ipairs(channel_names) do
+ output = model.getOutput(i-1)
+ output["name"] = v
+ model.setOutput(i-1,output)
+ nbr = i
+ end
+ for i = nbr, 15 do
+ output = model.getOutput(i)
+ output["name"] = "n-a"
+ model.setOutput(i,output)
+ end
+ if bind_ch == 1 then
+ output = model.getOutput(15)
+ output["name"] = "BindCH"
+ model.setOutput(15,output)
+ end
+ done = 1
+ end
+ lcd.drawText(x_pos, y_pos+y_inc*line,"Done!", lcd_opt)
+ line = line + 1
+end
+
+-- Init
+local function Multi_Init()
+ module_conf = model.getModule(0)
+ if module_conf["Type"] ~= 6 then
+ module_pos = "External"
+ module_conf = model.getModule(1)
+ if module_conf["Type"] ~= 6 then
+ return
+ end
+ end
+
+ protocol = module_conf["protocol"]
+ sub_protocol = module_conf["subProtocol"]
+
+ --Exceptions on first 4 channels...
+ local stick_names = { "Rud", "Ele", "Thr", "Ail" }
+ if ( protocol == 4 and sub_protocol ==1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX
+ stick_names[2] = "n-a"
+ stick_names[4] = "n-a"
+ elseif protocol == 43 then -- Traxxas
+ stick_names[2] = "Aux4"
+ stick_names[4] = "Aux3"
+ elseif protocol == 48 then -- V761
+ stick_names[4] = "n-a"
+ elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
+ stick_names[1] = "n-a"
+ stick_names[2] = "n-a"
+ end
+
+ --Determine fist 4 channels order
+ local ch_order=module_conf["channelsOrder"]
+ if (ch_order == -1) then
+ channel_names[1] = stick_names[defaultChannel(0)+1]
+ channel_names[2] = stick_names[defaultChannel(1)+1]
+ channel_names[3] = stick_names[defaultChannel(2)+1]
+ channel_names[4] = stick_names[defaultChannel(3)+1]
+ else
+ channel_names[bitand(ch_order,3)+1] = stick_names[4]
+ ch_order = math.floor(ch_order/4)
+ channel_names[bitand(ch_order,3)+1] = stick_names[2]
+ ch_order = math.floor(ch_order/4)
+ channel_names[bitand(ch_order,3)+1] = stick_names[3]
+ ch_order = math.floor(ch_order/4)
+ channel_names[bitand(ch_order,3)+1] = stick_names[1]
+ end
+ --Check MultiChan.txt
+ local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
+ if f == nil then return end
+ file_ok = 1
+ io.close(f)
+end
+
+-- Main
+local function Multi_Run(event)
+ if event == nil then
+ error("Cannot be run as a model script!")
+ return 2
+ else
+ Multi_Draw_LCD(event)
+ if event == EVT_VIRTUAL_EXIT then
+ return 2
+ end
+ end
+ return 0
+end
+
+return { init=Multi_Init, run=Multi_Run }
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/delta.lua b/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/delta.lua
index 06af19541..cf559c6b2 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/delta.lua
+++ b/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/delta.lua
@@ -52,10 +52,10 @@ end
local function fieldIncDec(event, value, max, force)
if edit or force==true then
- if event == EVT_PLUS_BREAK or event == EVT_ROT_LEFT then
+ if event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
value = (value + max)
dirty = true
- elseif event == EVT_MINUS_BREAK or event == EVT_ROT_RIGHT then
+ elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
value = (value + max + 2)
dirty = true
end
@@ -66,12 +66,12 @@ end
local function valueIncDec(event, value, min, max)
if edit then
- if event == EVT_PLUS_FIRST or event == EVT_PLUS_REPT or event == EVT_ROT_RIGHT then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
if value < max then
value = (value + 1)
dirty = true
end
- elseif event == EVT_MINUS_FIRST or event == EVT_MINUS_REPT or event == EVT_ROT_LEFT then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
if value > min then
value = (value - 1)
dirty = true
@@ -82,11 +82,11 @@ local function valueIncDec(event, value, min, max)
end
local function navigate(event, fieldMax, prevPage, nextPage)
- if event == EVT_ENTER_BREAK then
+ if event == EVT_VIRTUAL_ENTER then
edit = not edit
dirty = true
elseif edit then
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
edit = false
dirty = true
elseif not dirty then
@@ -120,7 +120,7 @@ local function getFieldFlags(position)
end
local function channelIncDec(event, value)
- if not edit and event==EVT_MENU_BREAK then
+ if not edit and event == EVT_VIRTUAL_MENU then
servoPage = value
dirty = true
else
@@ -284,7 +284,7 @@ local function servoMenu(event)
limits.revert = fieldIncDec(event, limits.revert, 1)
end
model.setOutput(servoPage, limits)
- elseif event == EVT_EXIT_BREAK then
+ elseif event == EVT_VIRTUAL_EXIT then
servoPage = nil
dirty = true
end
@@ -357,9 +357,9 @@ local function confirmationMenu(event)
navigate(event, fieldsMax, RUDDER_PAGE, page)
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
- elseif event == EVT_ENTER_LONG then
+ elseif event == EVT_VIRTUAL_ENTER_LONG then
killEvents(event)
applySettings()
return 2
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/multi.lua b/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/multi.lua
index 773abafad..c78b982a9 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/multi.lua
+++ b/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/multi.lua
@@ -57,10 +57,10 @@ end
local function fieldIncDec(event, value, max, force)
if edit or force==true then
- if event == EVT_PLUS_BREAK or event == EVT_ROT_LEFT then
+ if event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
value = (value + max)
dirty = true
- elseif event == EVT_MINUS_BREAK or event == EVT_ROT_RIGHT then
+ elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
value = (value + max + 2)
dirty = true
end
@@ -71,12 +71,12 @@ end
local function valueIncDec(event, value, min, max)
if edit then
- if event == EVT_PLUS_FIRST or event == EVT_PLUS_REPT or event == EVT_ROT_RIGHT then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
if value < max then
value = (value + 1)
dirty = true
end
- elseif event == EVT_MINUS_FIRST or event == EVT_MINUS_REPT or event == EVT_ROT_LEFT then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
if value > min then
value = (value - 1)
dirty = true
@@ -87,11 +87,11 @@ local function valueIncDec(event, value, min, max)
end
local function navigate(event, fieldMax, prevPage, nextPage)
- if event == EVT_ENTER_BREAK then
+ if event == EVT_VIRTUAL_ENTER then
edit = not edit
dirty = true
elseif edit then
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
edit = false
dirty = true
elseif not dirty then
@@ -125,7 +125,7 @@ local function getFieldFlags(position)
end
local function channelIncDec(event, value)
- if not edit and event==EVT_MENU_BREAK then
+ if not edit and event == EVT_VIRTUAL_MENU then
servoPage = value
dirty = true
else
@@ -136,12 +136,12 @@ end
local function switchValueIncDec(event, value, min, max)
if edit then
- if event == EVT_PLUS_FIRST or event == EVT_PLUS_REPT or event == EVT_ROT_RIGHT then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
if value < max then
value = (value + 1)
dirty = true
end
- elseif event == EVT_MINUS_FIRST or event == EVT_MINUS_REPT or event == EVT_ROT_LEFT then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
if value > min then
value = (value - 1)
dirty = true
@@ -152,7 +152,7 @@ local function switchValueIncDec(event, value, min, max)
end
local function switchIncDec(event, value)
- if not edit and event==EVT_MENU_BREAK then
+ if not edit and event == EVT_VIRTUAL_MENU then
servoPage = value
dirty = true
else
@@ -164,8 +164,8 @@ end
-- Init function
local function init()
thrCH1 = defaultChannel(2)
- rollCH1 = defaultChannel(0)
- yawCH1 = defaultChannel(3)
+ rollCH1 = defaultChannel(3)
+ yawCH1 = defaultChannel(0)
pitchCH1 = defaultChannel(1)
local ver, radio, maj, minor, rev = getVersion()
-- if string.match(radio, "x7") then
@@ -415,9 +415,9 @@ local function confirmationMenu(event)
navigate(event, fieldsMax, BEEPER_PAGE, page)
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
- elseif event == EVT_ENTER_LONG then
+ elseif event == EVT_VIRTUAL_ENTER_LONG then
killEvents(event)
applySettings()
return 2
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/plane.lua b/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/plane.lua
index 5a75fbcc1..7d20bd97e 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/plane.lua
+++ b/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/plane.lua
@@ -62,10 +62,10 @@ end
local function fieldIncDec(event, value, max, force)
if edit or force==true then
- if event == EVT_PLUS_BREAK or event == EVT_ROT_LEFT then
+ if event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
value = (value + max)
dirty = true
- elseif event == EVT_MINUS_BREAK or event == EVT_ROT_RIGHT then
+ elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
value = (value + max + 2)
dirty = true
end
@@ -76,12 +76,12 @@ end
local function valueIncDec(event, value, min, max)
if edit then
- if event == EVT_PLUS_FIRST or event == EVT_PLUS_REPT or event == EVT_ROT_RIGHT then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
if value < max then
value = (value + 1)
dirty = true
end
- elseif event == EVT_MINUS_FIRST or event == EVT_MINUS_REPT or event == EVT_ROT_LEFT then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
if value > min then
value = (value - 1)
dirty = true
@@ -92,11 +92,11 @@ local function valueIncDec(event, value, min, max)
end
local function navigate(event, fieldMax, prevPage, nextPage)
- if event == EVT_ENTER_BREAK then
+ if event == EVT_VIRTUAL_ENTER then
edit = not edit
dirty = true
elseif edit then
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
edit = false
dirty = true
elseif not dirty then
@@ -130,7 +130,7 @@ local function getFieldFlags(position)
end
local function channelIncDec(event, value)
- if not edit and event==EVT_MENU_BREAK then
+ if not edit and event == EVT_VIRTUAL_MENU then
servoPage = value
dirty = true
else
@@ -425,7 +425,7 @@ local function servoMenu(event)
limits.revert = fieldIncDec(event, limits.revert, 1)
end
model.setOutput(servoPage, limits)
- elseif event == EVT_EXIT_BREAK then
+ elseif event == EVT_VIRTUAL_EXIT then
servoPage = nil
dirty = true
end
@@ -550,9 +550,9 @@ local function confirmationMenu(event)
navigate(event, fieldsMax, TAIL_PAGE, page)
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
- elseif event == EVT_ENTER_LONG then
+ elseif event == EVT_VIRTUAL_ENTER_LONG then
killEvents(event)
applySettings()
return 2
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/wizard.lua b/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/wizard.lua
index 463522765..7d330daae 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/wizard.lua
+++ b/radio/sdcard/taranis-x9/SCRIPTS/WIZARD/wizard.lua
@@ -25,10 +25,10 @@ local MODELTYPE_QUAD = 2
-- Common functions
local function fieldIncDec(event, value, max)
- if event == EVT_PLUS_BREAK or event == EVT_ROT_LEFT or event == EVT_PLUS_REPT then
+ if event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
value = (value + max)
dirty = true
- elseif event == EVT_MINUS_BREAK or event == EVT_ROT_RIGHT or event == EVT_MINUS_REPT then
+ elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
value = (value + max + 2)
dirty = true
end
@@ -56,7 +56,7 @@ local function modelTypeMenu(event)
drawModelChoiceMenu()
dirty = false
end
- if event == EVT_ENTER_BREAK then
+ if event == EVT_VIRTUAL_ENTER then
if modelType == MODELTYPE_PLANE then
return "plane.lua"
elseif modelType == MODELTYPE_DELTA then
@@ -77,7 +77,7 @@ local function run(event)
error("Cannot be run as a model script!")
end
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
end
return modelTypeMenu(event)
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/snake.lua b/radio/sdcard/taranis-x9/SCRIPTS/snake.lua
index 012a9f1e1..d3a1914bb 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/snake.lua
+++ b/radio/sdcard/taranis-x9/SCRIPTS/snake.lua
@@ -127,7 +127,7 @@ local function run(event)
raise("Cannot be run as a model script!")
end
- if event == EVT_EXIT_BREAK then
+ if event == EVT_VIRTUAL_EXIT then
return 2
end
diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/SxR_Calibrate.lua b/radio/sdcard/taranis-x9/SxR Calibrate/SxR_Calibrate.lua
index 5a03b1db0..a9c636f30 100644
--- a/radio/sdcard/taranis-x9/SxR Calibrate/SxR_Calibrate.lua
+++ b/radio/sdcard/taranis-x9/SxR Calibrate/SxR_Calibrate.lua
@@ -60,10 +60,10 @@ local function runWarningPage(event)
lcd.drawText(0, 30, "power supply and a flat level surface (desk,...)", SMLSIZE)
lcd.drawText(0, 40, "Press [Enter] when ready", SMLSIZE)
lcd.drawText(0, 50, "Press [Exit] when cancel", SMLSIZE)
- if event == EVT_ENTER_BREAK then
+ if event == EVT_VIRTUAL_ENTER then
selectPage(1)
return 0
- elseif event == EVT_EXIT_BREAK then
+ elseif event == EVT_VIRTUAL_EXIT then
return 2
end
return 0
@@ -184,9 +184,9 @@ end
-- Main
local function runFieldsPage(event)
- if event == EVT_EXIT_BREAK then -- exit script
+ if event == EVT_VIRTUAL_EXIT then -- exit script
return 2
- elseif event == EVT_ENTER_BREAK then -- toggle editing/selecting current field
+ elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
if fields[current][4] ~= nil then
edit = not edit
if edit == false then
@@ -194,15 +194,15 @@ local function runFieldsPage(event)
end
end
elseif edit then
- if event == EVT_PLUS_FIRST or event == EVT_ROT_RIGHT or event == EVT_PLUS_REPT then
+ if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REP then
addField(1)
- elseif event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT or event == EVT_MINUS_REPT then
+ elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_PREV_REP then
addField(-1)
end
else
- if event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REP then
selectField(1)
- elseif event == EVT_PLUS_FIRST or event == EVT_ROT_RIGHT then
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REP then
selectField(-1)
end
end
@@ -235,11 +235,11 @@ local function runCalibrationPage(event)
lcd.drawPixmap(10, 19, "bmp/done.bmp")
lcd.drawText(0, 56, "Press [Exit] when ready", attr)
end
- if calibrationStep > 6 and (event == EVT_ENTER_BREAK or event == EVT_EXIT_BREAK) then
+ if calibrationStep > 6 and (event == EVT_VIRTUAL_ENTER or event == EVT_VIRTUAL_EXIT) then
return 2
- elseif event == EVT_ENTER_BREAK then
+ elseif event == EVT_VIRTUAL_ENTER then
calibrationState = 1
- elseif event == EVT_EXIT_BREAK then
+ elseif event == EVT_VIRTUAL_EXIT then
if calibrationStep > 0 then
calibrationStep = 0
end
@@ -261,9 +261,9 @@ local function run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
- elseif event == EVT_PAGE_BREAK then
+ elseif event == EVT_VIRTUAL_NEXT_PAGE then
selectPage(1)
- elseif event == EVT_PAGE_LONG then
+ elseif event == EVT_VIRTUAL_PREV_PAGE then
killEvents(event);
selectPage(-1)
end
diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt
index 311c6dbd1..989457f92 100644
--- a/radio/src/CMakeLists.txt
+++ b/radio/src/CMakeLists.txt
@@ -47,12 +47,14 @@ option(TRACE_SIMPGMSPACE "Turn on traces in simpgmspace.cpp" ON)
option(TRACE_LUA_INTERNALS "Turn on traces for Lua internals" OFF)
option(FRSKY_STICKS "Reverse sticks for FrSky sticks" OFF)
option(NANO "Use nano newlib and binalloc")
-option(NIGHTLY_BUILD_WARNING "Warn this is a nightly build" OFF)
+option(TEST_BUILD_WARNING "Warn this is a test build" OFF)
option(MODULE_PROTOCOL_FCC "Add support for FCC modules" ON)
option(MODULE_PROTOCOL_LBT "Add support for EU/LBT modules" ON)
option(MODULE_PROTOCOL_FLEX "Add support for non certified FLEX modules" OFF)
option(MODULE_PROTOCOL_D8 "Add support for D8 modules" ON)
option(FRSKY_RELEASE "Used to build FrSky released firmware" OFF)
+option(TBS_RELEASE "Used to build TBS released firmware" OFF)
+option(ALLOW_TRAINER_MULTI "Allow multi trainer" OFF)
# since we reset all default CMAKE compiler flags for firmware builds, provide an alternate way for user to specify additional flags.
set(FIRMWARE_C_FLAGS "" CACHE STRING "Additional flags for firmware target c compiler (note: all CMAKE_C_FLAGS[_*] are ignored for firmware/bootloader).")
@@ -146,7 +148,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR}/bitmaps/${GUI_DIR})
-add_subdirectory(lua)
include(gui/CMakeLists.txt)
if(RTC_BACKUP_RAM)
@@ -315,8 +316,8 @@ if(EEPROM_VARIANT_NEEDED)
add_definitions(-DEEPROM_VARIANT=${EEPROM_VARIANT})
endif()
-if(NIGHTLY_BUILD_WARNING)
- add_definitions(-DNIGHTLY_BUILD_WARNING)
+if(TEST_BUILD_WARNING)
+ add_definitions(-DTEST_BUILD_WARNING)
endif()
if(MODULE_PROTOCOL_FCC)
@@ -339,13 +340,32 @@ if(JUMPER_RELEASE)
add_definitions(-DJUMPER_RELEASE)
endif()
+if(RADIOMASTER_RELEASE)
+ add_definitions(-DRADIOMASTER_RELEASE)
+endif()
+
+if(TBS_RELEASE)
+ add_definitions(-DTBS_RELEASE)
+endif()
+
if(FRSKY_RELEASE)
add_definitions(-DFRSKY_RELEASE)
set(POPUP_LEVEL 3)
endif()
+if(ALLOW_TRAINER_MULTI)
+ add_definitions(-DALLOW_TRAINER_MULTI)
+endif()
+
add_definitions(-DPOPUP_LEVEL=${POPUP_LEVEL})
+if(INTERNAL_MODULE_MULTI)
+ set(DEFAULT_TEMPLATE_SETUP 21 CACHE STRING "")
+else()
+ set(DEFAULT_TEMPLATE_SETUP 0 CACHE STRING "")
+endif()
+add_definitions(-DDEFAULT_TEMPLATE_SETUP=${DEFAULT_TEMPLATE_SETUP})
+
set(SRC
${SRC}
opentx.cpp
@@ -405,7 +425,6 @@ endif()
set(SRC ${SRC} ${FIRMWARE_SRC})
-
##### firmware target #####
option(FIRMWARE_TARGET "Configure Firmware target (can be turned of for compiling Companion only)" ON)
@@ -551,3 +570,7 @@ if(NOT MSVC)
PrintTargetReport("firmware")
endif(NOT MSVC)
+# Include the lua subdirectory after CMAKE_C_COMPILER has been
+# set. Otherwise, the custom commands it includes will use the
+# default CMAKE_C_COMPILER instead of the one we set manually
+add_subdirectory(lua)
diff --git a/radio/src/audio.h b/radio/src/audio.h
index ac356863a..ab6228616 100644
--- a/radio/src/audio.h
+++ b/radio/src/audio.h
@@ -18,8 +18,8 @@
* GNU General Public License for more details.
*/
-#ifndef _AUDIO_ARM_H_
-#define _AUDIO_ARM_H_
+#ifndef _AUDIO_H_
+#define _AUDIO_H_
#include
#include "ff.h"
@@ -64,8 +64,11 @@ template class BitField {
#define INDEX_LOGICAL_SWITCH_AUDIO_FILE(index, event) (2*(index)+(event))
#define INDEX_PHASE_AUDIO_FILE(index, event) (2*(index)+(event))
+// max length (example: /SOUNDS/fr/123456789012/1234567890-off.wav)
+constexpr uint8_t AUDIO_MODEL_FILENAME_MAXLEN = (sizeof("/SOUNDS/fr/") - 1) + LEN_MODEL_NAME + 1 + LEN_FLIGHT_MODE_NAME + (sizeof("-off.wav") - 1);
+constexpr uint8_t AUDIO_LUA_FILENAME_MAXLEN = 42; // Some scripts use long audio paths, even on 128x64 boards
+constexpr uint8_t AUDIO_FILENAME_MAXLEN = (AUDIO_LUA_FILENAME_MAXLEN > AUDIO_MODEL_FILENAME_MAXLEN ? AUDIO_LUA_FILENAME_MAXLEN : AUDIO_MODEL_FILENAME_MAXLEN);
-#define AUDIO_FILENAME_MAXLEN (42) // max length (example: /SOUNDS/fr/123456789012/1234567890-off.wav)
#define AUDIO_QUEUE_LENGTH (16) // must be a power of 2!
#define AUDIO_SAMPLE_RATE (32000)
@@ -83,8 +86,6 @@ template class BitField {
#define BEEP_MIN_FREQ (150)
#define BEEP_MAX_FREQ (15000)
#define BEEP_DEFAULT_FREQ (2250)
-#define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+150)
-#define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-150)
#if defined(AUDIO_DUAL_BUFFER)
enum AudioBufferState
@@ -512,6 +513,9 @@ class AudioQueue {
bool isEmpty() const { return fragmentsFifo.empty(); };
void wakeup();
bool started() const { return _started; };
+#if defined(AUDIO_UNMUTE_DELAY)
+ tmr10ms_t lastAudioPlayTime = 0;
+#endif
AudioBufferFifo buffersFifo;
@@ -650,4 +654,4 @@ void referenceModelAudioFiles();
bool isAudioFileReferenced(uint32_t i, char * filename/*at least AUDIO_FILENAME_MAXLEN+1 long*/);
-#endif // _AUDIO_ARM_H_
+#endif // _AUDIO_H_
diff --git a/radio/src/bitmaps/480x272/CMakeLists.txt b/radio/src/bitmaps/480x272/CMakeLists.txt
index 9337292af..4ae20e970 100644
--- a/radio/src/bitmaps/480x272/CMakeLists.txt
+++ b/radio/src/bitmaps/480x272/CMakeLists.txt
@@ -1,6 +1,9 @@
if(PCB STREQUAL X12S)
set(BITMAP_TARGET_PREFIX x12s)
set(BITMAP_FMT_SUFFIX "")
+elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T18)
+ set(BITMAP_TARGET_PREFIX x10)
+ set(BITMAP_FMT_SUFFIX "")
else()
set(BITMAP_TARGET_PREFIX x10)
set(BITMAP_FMT_SUFFIX "-R")
diff --git a/radio/src/bitmaps/480x272/mask_txbat.png b/radio/src/bitmaps/480x272/mask_txbat.png
index fd5939190..001d2751c 100644
Binary files a/radio/src/bitmaps/480x272/mask_txbat.png and b/radio/src/bitmaps/480x272/mask_txbat.png differ
diff --git a/radio/src/bitmaps/480x272/mask_txbat_charging.png b/radio/src/bitmaps/480x272/mask_txbat_charging.png
new file mode 100644
index 000000000..fa8ab8154
Binary files /dev/null and b/radio/src/bitmaps/480x272/mask_txbat_charging.png differ
diff --git a/radio/src/bluetooth.cpp b/radio/src/bluetooth.cpp
index 18c2a43ea..22daa0c42 100644
--- a/radio/src/bluetooth.cpp
+++ b/radio/src/bluetooth.cpp
@@ -21,6 +21,10 @@
#include "opentx.h"
#include "io/frsky_firmware_update.h"
+#if defined(LOG_BLUETOOTH)
+extern FIL g_bluetoothFile;
+#endif
+
#if defined(PCBX9E)
#define BLUETOOTH_COMMAND_NAME "TTM:REN-"
#define BLUETOOTH_ANSWER_NAME "TTM:REN"
@@ -44,23 +48,24 @@ Bluetooth bluetooth;
void Bluetooth::write(const uint8_t * data, uint8_t length)
{
- TRACE_NOCRLF("BT>");
- for (int i=0; i");
+ for (int i = 0; i < length; i++) {
+ BLUETOOTH_TRACE(" %02X", data[i]);
+ btTxFifo.push(data[i]);
}
- btTxFifo.push(data[i]);
+ BLUETOOTH_TRACE(CRLF);
}
- TRACE_NOCRLF("\r\n");
+ else {
+ BLUETOOTH_TRACE("[BT] TX fifo full!" CRLF);
+ }
+
bluetoothWriteWakeup();
}
void Bluetooth::writeString(const char * str)
{
- TRACE("BT> %s", str);
+ BLUETOOTH_TRACE("BT> %s" CRLF, str);
while (*str != 0) {
btTxFifo.push(*str++);
}
@@ -77,19 +82,19 @@ char * Bluetooth::readline(bool error_reset)
if (!btRxFifo.pop(byte)) {
#if defined(PCBX9E)
// X9E BT module can get unresponsive
- TRACE("NO RESPONSE FROM BT MODULE");
+ BLUETOOTH_TRACE("NO RESPONSE FROM BT MODULE" CRLF);
#endif
return nullptr;
}
- TRACE_NOCRLF("%02X ", byte);
+ BLUETOOTH_TRACE("%02X ", byte);
#if 0
if (error_reset && byte == 'R' && bufferIndex == 4 && memcmp(buffer, "ERRO", 4)) {
#if defined(PCBX9E) // X9E enter BT reset loop if following code is implemented
- TRACE("BT Error...");
+ BLUETOOTH_TRACE("BT Error..." CRLF);
#else
- TRACE("BT Reset...");
+ BLUETOOTH_TRACE("BT Reset..." CRLF);
bufferIndex = 0;
bluetoothDisable();
state = BLUETOOTH_STATE_OFF;
@@ -104,12 +109,12 @@ char * Bluetooth::readline(bool error_reset)
if (bufferIndex > 2 && buffer[bufferIndex-1] == '\r') {
buffer[bufferIndex-1] = '\0';
bufferIndex = 0;
- TRACE("BT< %s", buffer);
+ BLUETOOTH_TRACE("BT< %s" CRLF, buffer);
if (error_reset && !strcmp((char *)buffer, "ERROR")) {
#if defined(PCBX9E) // X9E enter BT reset loop if following code is implemented
- TRACE("BT Error...");
+ BLUETOOTH_TRACE("BT Error..." CRLF);
#else
- TRACE("BT Reset...");
+ BLUETOOTH_TRACE("BT Reset..." CRLF);
bluetoothDisable();
state = BLUETOOTH_STATE_OFF;
wakeupTime = get_tmr10ms() + 100; /* 1s */
@@ -137,7 +142,7 @@ char * Bluetooth::readline(bool error_reset)
void Bluetooth::processTrainerFrame(const uint8_t * buffer)
{
- TRACE("");
+ BLUETOOTH_TRACE(CRLF);
for (uint8_t channel=0, i=1; channel<8; channel+=2, i+=3) {
// +-500 != 512, but close enough.
@@ -155,7 +160,7 @@ void Bluetooth::appendTrainerByte(uint8_t data)
// we check for "DisConnected", but the first byte could be altered (if received in state STATE_DATA_XOR)
if (data == '\n') {
if (!strncmp((char *)&buffer[bufferIndex-13], "isConnected", 11)) {
- TRACE("BT< DisConnected");
+ BLUETOOTH_TRACE("BT< DisConnected" CRLF);
state = BLUETOOTH_STATE_DISCONNECTED;
bufferIndex = 0;
wakeupTime += 200; // 1s
@@ -171,7 +176,7 @@ void Bluetooth::processTrainerByte(uint8_t data)
switch (dataState) {
case STATE_DATA_START:
if (data == START_STOP) {
- dataState = STATE_DATA_IN_FRAME ;
+ dataState = STATE_DATA_IN_FRAME;
bufferIndex = 0;
}
else {
@@ -184,7 +189,7 @@ void Bluetooth::processTrainerByte(uint8_t data)
dataState = STATE_DATA_XOR; // XOR next byte
}
else if (data == START_STOP) {
- dataState = STATE_DATA_IN_FRAME ;
+ dataState = STATE_DATA_IN_FRAME;
bufferIndex = 0;
}
else {
@@ -285,7 +290,7 @@ void Bluetooth::receiveTrainer()
return;
}
- TRACE_NOCRLF("%02X ", byte);
+ BLUETOOTH_TRACE("%02X ", byte);
processTrainerByte(byte);
}
diff --git a/radio/src/bluetooth.h b/radio/src/bluetooth.h
index 2f4f2e1c6..51d5cf468 100644
--- a/radio/src/bluetooth.h
+++ b/radio/src/bluetooth.h
@@ -46,8 +46,17 @@ enum BluetoothStates {
#define LEN_BLUETOOTH_ADDR 16
#define MAX_BLUETOOTH_DISTANT_ADDR 6
-#define BLUETOOTH_PACKET_SIZE 14
-#define BLUETOOTH_LINE_LENGTH 32
+#define BLUETOOTH_PACKET_SIZE 14
+#define BLUETOOTH_LINE_LENGTH 32
+
+#if defined(LOG_BLUETOOTH)
+ #define BLUETOOTH_TRACE(...) \
+ f_printf(&g_bluetoothFile, __VA_ARGS__); \
+ TRACE_NOCRLF(__VA_ARGS__);
+#else
+ #define BLUETOOTH_TRACE(...) \
+ TRACE_NOCRLF(__VA_ARGS__);
+#endif
class Bluetooth
{
diff --git a/radio/src/buzzer.h b/radio/src/buzzer.h
index aa13746f8..f0c545d5e 100644
--- a/radio/src/buzzer.h
+++ b/radio/src/buzzer.h
@@ -22,8 +22,6 @@
#define _BUZZER_H_
#if defined(BUZZER)
-extern uint8_t g_beepCnt;
-extern uint8_t beepAgain;
extern uint8_t beepAgainOrig;
extern uint8_t beepOn;
extern bool warble;
diff --git a/radio/src/curves.cpp b/radio/src/curves.cpp
index 3a1bf1f27..2606611c9 100644
--- a/radio/src/curves.cpp
+++ b/radio/src/curves.cpp
@@ -20,8 +20,6 @@
#include "opentx.h"
-uint8_t s_curveChan;
-
int8_t * curveEnd[MAX_CURVES];
void loadCurves()
{
@@ -317,8 +315,8 @@ int applyCustomCurve(int x, uint8_t idx)
point_t getPoint(uint8_t i)
{
point_t result = {0, 0};
- CurveInfo & crv = g_model.curves[s_curveChan];
- int8_t * points = curveAddress(s_curveChan);
+ CurveInfo & crv = g_model.curves[s_currIdxSubMenu];
+ int8_t * points = curveAddress(s_currIdxSubMenu);
bool custom = (crv.type == CURVE_TYPE_CUSTOM);
uint8_t count = 5+crv.points;
if (i < count) {
@@ -333,5 +331,5 @@ point_t getPoint(uint8_t i)
int applyCurrentCurve(int x)
{
- return applyCustomCurve(x, s_curveChan);
+ return applyCustomCurve(x, s_currIdxSubMenu);
}
diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h
index c747b39bb..d47b0eeae 100644
--- a/radio/src/dataconstants.h
+++ b/radio/src/dataconstants.h
@@ -168,6 +168,7 @@ enum MainViews {
VIEW_OUTPUTS_BARS,
VIEW_INPUTS,
VIEW_TIMER2,
+ VIEW_CHAN_MONITOR,
VIEW_COUNT
};
#endif
@@ -191,6 +192,8 @@ enum TrainerMode {
#if defined(PCBTARANIS)
TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE,
TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE,
+#endif
+#if defined(PCBTARANIS) || defined(AUX_SERIAL)
TRAINER_MODE_MASTER_BATTERY_COMPARTMENT,
#endif
TRAINER_MODE_MASTER_BLUETOOTH,
@@ -205,7 +208,7 @@ enum TrainerMode {
};
#endif
-#if defined(RADIO_T16)
+#if defined(RADIO_FAMILY_T16) || (defined(RADIO_T12) && defined(INTERNAL_MODULE_MULTI)) || defined(ALLOW_TRAINER_MULTI)
#define TRAINER_MODE_MAX() TRAINER_MODE_MULTI
#elif defined(BLUETOOTH)
#define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE_BLUETOOTH
@@ -266,7 +269,8 @@ enum TelemetryProtocol
PROTOCOL_TELEMETRY_HITEC,
PROTOCOL_TELEMETRY_HOTT,
PROTOCOL_TELEMETRY_MULTIMODULE,
- PROTOCOL_TELEMETRY_LAST=PROTOCOL_TELEMETRY_MULTIMODULE,
+ PROTOCOL_TELEMETRY_AFHDS3,
+ PROTOCOL_TELEMETRY_LAST=PROTOCOL_TELEMETRY_AFHDS3,
PROTOCOL_TELEMETRY_LUA
};
@@ -581,7 +585,7 @@ enum SwitchSources {
#define SWSRC_TRAINER SWSRC_LAST_SWITCH,
#endif
-#define SWSRC_LAST_TRIM (SWSRC_FIRST_TRIM + 2*NUM_TRIMS - 1)
+#define SWSRC_LAST_TRIM (SWSRC_FIRST_TRIM + 2 * NUM_TRIMS - 1)
enum MixSources {
MIXSRC_NONE,
diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h
index 5733c7f86..9f114c5f8 100644
--- a/radio/src/datastructs.h
+++ b/radio/src/datastructs.h
@@ -26,6 +26,7 @@
#include "dataconstants.h"
#include "definitions.h"
#include "bitfield.h"
+#include "globals.h"
#if defined(PCBTARANIS)
#define N_TARANIS_FIELD(x)
@@ -328,10 +329,10 @@ PACK(struct TelemetrySensor {
NOBACKUP(uint16_t persistentValue);
};
union {
- PACK(struct {
+ NOBACKUP(PACK(struct {
uint8_t physID:5;
uint8_t rxIndex:3; // 1 bit for module index, 2 bits for receiver index
- }) frskyInstance;
+ }) frskyInstance);
uint8_t instance;
NOBACKUP(uint8_t formula);
};
@@ -380,20 +381,7 @@ PACK(struct TelemetrySensor {
bool isPrecConfigurable() const;
int32_t getPrecMultiplier() const;
int32_t getPrecDivisor() const;
- bool isSameInstance(TelemetryProtocol protocol, uint8_t instance)
- {
- if (this->instance == instance)
- return true;
-
- if (protocol == PROTOCOL_TELEMETRY_FRSKY_SPORT) {
- if (((this->instance ^ instance) & 0x9F) == 0 && (this->instance >> 5) != TELEMETRY_ENDPOINT_SPORT && (instance >> 5) != TELEMETRY_ENDPOINT_SPORT) {
- this->instance = instance; // update the instance in case we had telemetry switching
- return true;
- }
- }
-
- return false;
- }
+ bool isSameInstance(TelemetryProtocol protocol, uint8_t instance);
);
});
@@ -444,6 +432,9 @@ PACK(struct ModuleData {
uint8_t autoBindMode:1;
uint8_t lowPowerMode:1;
int8_t optionValue;
+ uint8_t receiverTelemetryOff:1;
+ uint8_t receiverHigherChannels:1;
+ uint8_t spare:6;
} multi);
NOBACKUP(struct {
uint8_t power:2; // 0=10 mW, 1=100 mW, 2=500 mW, 3=1W
@@ -463,15 +454,33 @@ PACK(struct ModuleData {
uint8_t receivers; // 5 bits spare
char receiverName[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME];
}) pxx2);
+ NOBACKUP(PACK(struct {
+ uint8_t bindPower:3;
+ uint8_t runPower:3;
+ uint8_t emi:1;
+ uint8_t telemetry:1;
+ uint16_t failsafeTimeout;
+ uint8_t rx_freq[2];
+ uint16_t rxFreq()
+ {
+ return (uint16_t)rx_freq[0] | (((uint16_t)rx_freq[1]) << 8);
+ }
+
+ void setRxFreq(uint16_t value)
+ {
+ rx_freq[0] = value & 0xFF;
+ rx_freq[1] = value >> 8;
+ }
+ } afhds3));
};
// Helper functions to set both of the rfProto protocol at the same time
NOBACKUP(inline uint8_t getMultiProtocol() {
- return ((uint8_t) (rfProtocol & 0x0f)) + (multi.rfProtocolExtra << 4);
+ return ((uint8_t) (rfProtocol & 0x0F)) + (multi.rfProtocolExtra << 4);
})
NOBACKUP(inline void setMultiProtocol(uint8_t proto) {
- rfProtocol = (uint8_t) (proto & 0x0f);
+ rfProtocol = (uint8_t) (proto & 0x0F);
multi.rfProtocolExtra = (proto & 0x70) >> 4;
})
});
@@ -480,8 +489,6 @@ PACK(struct ModuleData {
* Model structure
*/
-typedef uint16_t BeepANACenter;
-
#if LEN_BITMAP_NAME > 0
#define MODEL_HEADER_BITMAP_FIELD NOBACKUP(char bitmap[LEN_BITMAP_NAME]);
#else
@@ -664,7 +671,8 @@ PACK(struct TrainerData {
#if defined(PCBHORUS)
#define EXTRA_GENERAL_FIELDS \
- NOBACKUP(uint8_t auxSerialMode); \
+ NOBACKUP(uint8_t auxSerialMode:4); \
+ NOBACKUP(uint8_t aux2SerialMode:4); \
swconfig_t switchConfig; \
uint16_t potsConfig; /* two bits per pot */ \
uint8_t slidersConfig; /* 1 bit per slider */ \
@@ -736,7 +744,8 @@ PACK(struct RadioData {
uint8_t backlightMode:3;
int8_t antennaMode:2;
uint8_t disableRtcWarning:1;
- int8_t spare1:2;
+ uint8_t keysBacklight:1;
+ int8_t spare1:1;
NOBACKUP(TrainerData trainer);
NOBACKUP(uint8_t view); // index of view in main screen
NOBACKUP(BUZZER_FIELD); /* 2bits */
@@ -780,7 +789,7 @@ PACK(struct RadioData {
NOBACKUP(uint8_t disableRssiPoweroffAlarm:1);
NOBACKUP(uint8_t USBMode:2);
NOBACKUP(uint8_t jackMode:2);
- NOBACKUP(uint8_t spare3:1);
+ NOBACKUP(uint8_t sportUpdatePower:1);
NOBACKUP(char ttsLanguage[2]);
NOBACKUP(int8_t beepVolume:4);
NOBACKUP(int8_t wavVolume:4);
@@ -938,4 +947,4 @@ static inline void check_struct()
#undef CHKSIZE
}
-#endif /* BACKUP */
+#endif /* BACKUP */
diff --git a/radio/src/debug.h b/radio/src/debug.h
index 3a5303ef3..e73c73f29 100644
--- a/radio/src/debug.h
+++ b/radio/src/debug.h
@@ -24,6 +24,9 @@
#include
#include "rtc.h"
#include "dump.h"
+
+#define CRLF "\r\n"
+
#if defined(CLI)
#include "cli.h"
#else
@@ -35,6 +38,7 @@ extern "C" {
#endif
uint8_t auxSerialTracesEnabled();
+uint8_t aux2SerialTracesEnabled();
#if defined(SIMU)
typedef void (*traceCallbackFunc)(const char * text);
@@ -56,7 +60,7 @@ uint8_t auxSerialTracesEnabled();
#endif
#define TRACE_NOCRLF(...) debugPrintf(__VA_ARGS__)
-#define TRACE(f_, ...) debugPrintf((f_ "\r\n"), ##__VA_ARGS__)
+#define TRACE(f_, ...) debugPrintf((f_ CRLF), ##__VA_ARGS__)
#define DUMP(data, size) dump(data, size)
#define TRACE_DEBUG(...) debugPrintf("-D- " __VA_ARGS__)
#define TRACE_DEBUG_WP(...) debugPrintf(__VA_ARGS__)
@@ -67,7 +71,7 @@ uint8_t auxSerialTracesEnabled();
#define TRACE_ERROR(...) debugPrintf("-E- " __VA_ARGS__)
#if defined(TRACE_LUA_INTERNALS_ENABLED)
- #define TRACE_LUA_INTERNALS(f_, ...) debugPrintf(("[LUA INT] " f_ "\r\n"), ##__VA_ARGS__)
+ #define TRACE_LUA_INTERNALS(f_, ...) debugPrintf(("[LUA INT] " f_ CRLF), ##__VA_ARGS__)
#define TRACE_LUA_INTERNALS_WITH_LINEINFO(L, f_, ...) do { \
lua_Debug ar; \
@@ -75,7 +79,7 @@ uint8_t auxSerialTracesEnabled();
lua_getinfo(L, ">Sl", &ar); \
debugPrintf("%s:%d: ", ar.short_src, ar.currentline); \
} \
- debugPrintf(("[LUA INT] " f_ "\r\n"), ##__VA_ARGS__); \
+ debugPrintf(("[LUA INT] " f_ CRLF), ##__VA_ARGS__); \
} while(0)
#else
#define TRACE_LUA_INTERNALS(...)
diff --git a/radio/src/dump.cpp b/radio/src/dump.cpp
index 60152a3af..12a6b3459 100644
--- a/radio/src/dump.cpp
+++ b/radio/src/dump.cpp
@@ -40,14 +40,14 @@ void dumpBody(const void *data, unsigned int size)
dumpPrintf("%.2X ", ((uint8_t *)data)[i]);
dumpPosition++;
if ((dumpPosition & (32-1)) == 0) {
- dumpPrintf("\r\n");
+ dumpPrintf(CRLF);
}
}
}
void dumpEnd()
{
- dumpPrintf("\r\n");
+ dumpPrintf(CRLF);
}
#if defined(DEBUG) || defined(CLI)
diff --git a/radio/src/fifo.h b/radio/src/fifo.h
index 9aff60f57..8ef67be66 100644
--- a/radio/src/fifo.h
+++ b/radio/src/fifo.h
@@ -71,7 +71,7 @@ class Fifo
return (ridx == widx);
}
- bool isFull()
+ bool isFull() const
{
uint32_t next = nextIndex(widx);
return (next == ridx);
@@ -82,7 +82,7 @@ class Fifo
return (N + widx - ridx) & (N - 1);
}
- uint32_t hasSpace(uint32_t n) const
+ bool hasSpace(uint32_t n) const
{
return (N > (size() + n));
}
@@ -103,7 +103,7 @@ class Fifo
volatile uint32_t widx;
volatile uint32_t ridx;
- inline uint32_t nextIndex(uint32_t idx)
+ static inline uint32_t nextIndex(uint32_t idx)
{
return (idx + 1) & (N - 1);
}
diff --git a/radio/src/fonts/480x272/CMakeLists.txt b/radio/src/fonts/480x272/CMakeLists.txt
index 09a68efdb..a8b57384e 100644
--- a/radio/src/fonts/480x272/CMakeLists.txt
+++ b/radio/src/fonts/480x272/CMakeLists.txt
@@ -10,12 +10,12 @@ set(FONT_OFFSET 1)
#set(FONT_BOLD "Ubuntu/Ubuntu-Bold")
#set(FONT_OFFSET 1)
-add_truetype_font_target(480x272 tinsize ${FONT} 9 ${FONT_OFFSET})
-add_truetype_font_target(480x272 smlsize ${FONT} 13 ${FONT_OFFSET})
-add_truetype_font_target(480x272 stdsize ${FONT} 16 ${FONT_OFFSET})
-add_truetype_font_target(480x272 stdsizebold ${FONT_BOLD} 16 ${FONT_OFFSET})
-add_truetype_font_target(480x272 midsize ${FONT} 24 ${FONT_OFFSET})
-add_truetype_font_target(480x272 dblsize ${FONT_BOLD} 32 ${FONT_OFFSET})
-add_truetype_font_target(480x272 xxlsize ${FONT_BOLD} 64 ${FONT_OFFSET})
+add_truetype_font_target(480x272 tinsize ${FONT} 9 0)
+add_truetype_font_target(480x272 smlsize ${FONT} 13 0)
+add_truetype_font_target(480x272 stdsize ${FONT} 16 1)
+add_truetype_font_target(480x272 stdsizebold ${FONT_BOLD} 16 1)
+add_truetype_font_target(480x272 midsize ${FONT} 24 0)
+add_truetype_font_target(480x272 dblsize ${FONT_BOLD} 32 0)
+add_truetype_font_target(480x272 xxlsize ${FONT_BOLD} 64 0)
add_custom_target(ttf_horus_fonts DEPENDS ${ttf_480x272_fonts_targets})
diff --git a/radio/src/fonts/480x272/font_dblsize.png b/radio/src/fonts/480x272/font_dblsize.png
index 174c70f9b..b8d7d4717 100644
Binary files a/radio/src/fonts/480x272/font_dblsize.png and b/radio/src/fonts/480x272/font_dblsize.png differ
diff --git a/radio/src/fonts/480x272/font_dblsize.specs b/radio/src/fonts/480x272/font_dblsize.specs
index 07d83c610..e3ec4d016 100644
--- a/radio/src/fonts/480x272/font_dblsize.specs
+++ b/radio/src/fonts/480x272/font_dblsize.specs
@@ -1 +1 @@
-0,4,14,25,45,64,89,111,117,129,141,157,175,184,197,207,220,239,258,277,296,315,334,353,372,391,410,420,429,446,465,483,500,513,536,557,579,601,620,639,662,686,696,715,737,755,784,808,831,853,876,897,918,939,961,983,1012,1033,1054,1074,1084,1100,1110,1125,1141,1153,1171,1190,1208,1227,1245,1258,1277,1296,1305,1314,1333,1342,1371,1390,1409,1428,1447,1460,1477,1489,1508,1525,1550,1568,1585,1602,1624,1633,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1651,1669,1687,1705,1717,1735,1758,1776,1799,1818,1840,1859,1880,1898,1915,1933,1947,1964,1981,1999,2011,2029,2048,2067,2086,2105,2129,2144,2163,2184,2206,2227,2247,2268,2291,2303,2322,2346,2369,2391,2413,2435,2456,2480,2499,2517,2535,2554,2577,2600,2623,2641,2660,2678,2696,2714,2725,2744,2763,2780,2797,2814,2837,2859,2878,2897,2921,2944,2965,2985,3005,3023,3041,3060,3083,3106,3129
\ No newline at end of file
+0,4,14,25,45,64,89,111,117,129,141,157,175,184,197,207,221,240,259,278,297,316,335,354,373,392,411,421,430,447,466,484,501,514,537,558,580,602,621,640,663,687,697,716,738,756,785,809,832,854,877,898,919,940,962,984,1013,1034,1055,1075,1085,1101,1111,1126,1142,1154,1172,1191,1209,1228,1246,1259,1278,1297,1306,1317,1336,1345,1374,1393,1412,1431,1450,1463,1480,1492,1511,1528,1553,1571,1589,1606,1628,1637,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1655,1673,1691,1709,1723,1741,1764,1782,1805,1824,1846,1865,1886,1904,1921,1939,1953,1970,1988,2006,2018,2036,2055,2074,2093,2112,2135,2150,2169,2190,2212,2233,2253,2274,2297,2309,2328,2352,2375,2397,2419,2441,2462,2486,2505,2528,2546,2565,2583,2595,2607,2630,2649,2671,2690,2708,2726,2745,2768,2791,2814,2832,2851,2869,2887,2905,2916,2935,2954,2971,2988,3005,3028,3050,3069,3088,3112,3135,3156,3176,3196,3219,3237,3260,3278,3301,3319,3342,3360,3382,3400,3419,3437,3456,3474,3486,3498,3521,3540,3563,3582,3605,3624,3646,3665
\ No newline at end of file
diff --git a/radio/src/fonts/480x272/font_midsize.png b/radio/src/fonts/480x272/font_midsize.png
index 3391516af..4bc901499 100644
Binary files a/radio/src/fonts/480x272/font_midsize.png and b/radio/src/fonts/480x272/font_midsize.png differ
diff --git a/radio/src/fonts/480x272/font_midsize.specs b/radio/src/fonts/480x272/font_midsize.specs
index 9e98f5af3..466a5a1a5 100644
--- a/radio/src/fonts/480x272/font_midsize.specs
+++ b/radio/src/fonts/480x272/font_midsize.specs
@@ -1 +1 @@
-0,4,11,20,36,50,69,85,90,99,108,119,134,140,148,155,166,180,194,208,222,236,250,264,278,292,306,313,319,332,346,360,372,382,399,415,432,449,464,478,495,513,521,535,552,566,588,606,624,640,658,674,689,704,721,737,759,775,791,806,814,825,832,843,855,863,877,891,905,920,934,944,958,972,979,986,1000,1007,1029,1043,1058,1072,1087,1096,1109,1118,1132,1145,1164,1177,1189,1202,1219,1226,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1240,1254,1268,1282,1290,1304,1321,1335,1353,1368,1385,1399,1414,1428,1441,1455,1465,1478,1490,1504,1512,1526,1540,1555,1569,1583,1599,1609,1624,1639,1656,1672,1687,1703,1720,1729,1744,1762,1780,1797,1814,1831,1846,1864,1878,1892,1906,1921,1938,1955,1973,1987,2001,2015,2029,2043,2051,2065,2080,2093,2106,2119,2136,2153,2168,2182,2200,2218,2233,2248,2263,2277,2291,2306,2323,2340,2358
\ No newline at end of file
+0,4,11,20,36,50,69,85,90,99,108,119,134,140,148,155,166,180,194,208,222,236,250,264,278,292,306,313,319,332,346,360,372,382,399,415,432,449,464,478,495,513,521,535,552,566,588,606,624,640,658,674,689,704,721,737,759,775,791,806,814,825,832,843,855,863,877,891,905,920,934,944,958,972,979,987,1001,1008,1030,1044,1059,1073,1088,1097,1110,1119,1133,1146,1165,1178,1191,1204,1221,1228,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1242,1256,1270,1284,1293,1307,1324,1338,1356,1371,1388,1402,1417,1431,1444,1458,1468,1481,1494,1508,1516,1530,1544,1559,1573,1587,1604,1614,1629,1644,1661,1677,1692,1708,1725,1733,1748,1766,1784,1801,1818,1835,1850,1868,1882,1899,1913,1928,1942,1950,1958,1976,1991,2008,2022,2036,2050,2065,2082,2099,2117,2131,2145,2159,2173,2187,2195,2209,2224,2237,2250,2263,2280,2297,2312,2326,2344,2362,2377,2392,2407,2424,2438,2455,2469,2486,2500,2517,2531,2548,2562,2577,2591,2606,2620,2628,2636,2654,2669,2687,2702,2720,2735,2752,2766
\ No newline at end of file
diff --git a/radio/src/fonts/480x272/font_smlsize.png b/radio/src/fonts/480x272/font_smlsize.png
index 30aef1915..0c9dde7bd 100644
Binary files a/radio/src/fonts/480x272/font_smlsize.png and b/radio/src/fonts/480x272/font_smlsize.png differ
diff --git a/radio/src/fonts/480x272/font_smlsize.specs b/radio/src/fonts/480x272/font_smlsize.specs
index 8802a9945..55bac8f44 100644
--- a/radio/src/fonts/480x272/font_smlsize.specs
+++ b/radio/src/fonts/480x272/font_smlsize.specs
@@ -1 +1 @@
-0,4,8,13,22,30,41,51,54,60,66,73,81,85,90,94,100,108,116,124,132,141,149,157,165,173,181,185,189,197,205,213,220,226,236,245,254,264,272,280,290,300,305,313,323,331,343,353,363,372,382,391,400,409,418,427,440,449,458,467,472,479,483,489,496,501,509,517,525,533,541,547,555,563,567,571,579,583,595,603,611,619,627,633,641,646,654,661,672,680,687,695,705,709,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,725,733,741,746,754,764,772,782,790,799,807,816,824,832,840,846,854,861,869,874,882,890,898,906,914,924,931,939,948,957,966,975,984,994,999,1007,1017,1027,1036,1045,1055,1064,1074,1082,1090,1098,1106,1116,1126,1136,1144,1152,1160,1168,1176,1181,1189,1197,1205,1213,1221,1231,1240,1248,1256,1266,1276,1285,1294,1303,1311,1319,1327,1337,1347,1357
\ No newline at end of file
+0,4,8,13,22,30,41,51,54,60,66,73,81,85,90,94,100,108,116,124,132,141,149,157,165,173,181,185,189,197,205,213,220,226,236,245,254,264,272,280,290,300,305,313,323,331,343,353,363,372,382,391,400,409,418,428,441,450,459,468,473,480,484,490,497,502,510,518,526,534,542,548,556,564,568,573,581,585,597,605,613,621,629,635,643,648,656,664,675,683,690,698,708,712,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,728,736,744,750,758,768,776,786,794,803,811,820,828,836,844,850,858,865,873,878,886,894,902,910,918,928,934,942,951,960,969,978,987,997,1002,1010,1020,1030,1039,1048,1058,1067,1077,1085,1095,1103,1111,1119,1124,1129,1139,1147,1156,1164,1172,1180,1188,1198,1208,1218,1226,1234,1242,1250,1258,1263,1271,1279,1287,1295,1303,1313,1322,1330,1338,1348,1358,1367,1376,1385,1395,1403,1413,1421,1431,1439,1449,1457,1466,1474,1482,1490,1498,1506,1511,1516,1526,1534,1544,1552,1562,1570,1579,1587
\ No newline at end of file
diff --git a/radio/src/fonts/480x272/font_stdsize.png b/radio/src/fonts/480x272/font_stdsize.png
index 48646859e..afd1e98b5 100644
Binary files a/radio/src/fonts/480x272/font_stdsize.png and b/radio/src/fonts/480x272/font_stdsize.png differ
diff --git a/radio/src/fonts/480x272/font_stdsize.specs b/radio/src/fonts/480x272/font_stdsize.specs
index 4b75e6d0d..3534008a7 100644
--- a/radio/src/fonts/480x272/font_stdsize.specs
+++ b/radio/src/fonts/480x272/font_stdsize.specs
@@ -1 +1 @@
-0,4,9,15,26,36,49,60,64,71,78,86,96,100,106,111,119,129,139,149,159,169,179,189,199,209,219,224,228,237,247,256,265,272,284,295,306,318,328,338,350,362,367,377,389,399,414,426,438,449,461,472,483,494,505,516,531,542,553,564,570,578,583,591,600,606,616,626,635,645,654,661,671,681,686,691,701,706,721,731,741,751,761,767,776,782,792,801,814,823,832,841,853,858,867,880,893,906,919,932,945,958,971,984,999,1014,1029,1044,1059,1074,1089,1104,1119,1134,1149,1164,1173,1182,1192,1198,1207,1219,1229,1241,1251,1262,1272,1283,1292,1301,1310,1317,1326,1335,1345,1351,1360,1370,1380,1390,1400,1412,1419,1429,1440,1451,1462,1473,1484,1496,1502,1512,1524,1536,1547,1558,1570,1581,1593,1603,1613,1623,1633,1645,1657,1669,1679,1689,1699,1708,1717,1723,1733,1743,1752,1761,1770,1782,1793,1803,1813,1825,1837,1848,1859,1870,1880,1890,1900,1912,1924,1936
\ No newline at end of file
+0,4,9,15,26,36,49,60,64,71,78,86,96,100,106,111,119,129,139,149,159,169,179,189,199,209,219,224,228,237,247,256,265,272,284,295,306,318,328,338,350,362,367,377,389,399,414,426,438,449,461,472,483,494,505,516,531,542,553,564,570,578,583,591,600,606,616,626,635,645,654,661,671,681,686,692,702,707,722,732,742,752,762,769,778,784,794,803,816,825,834,843,855,860,869,882,895,908,921,934,947,960,973,986,1001,1016,1031,1046,1061,1076,1091,1106,1121,1136,1151,1166,1175,1184,1194,1201,1210,1222,1232,1244,1254,1265,1275,1286,1295,1304,1313,1320,1329,1338,1348,1354,1363,1373,1383,1393,1403,1415,1422,1432,1443,1454,1465,1476,1487,1499,1505,1515,1527,1539,1550,1561,1573,1584,1596,1606,1618,1628,1638,1647,1653,1659,1671,1681,1692,1702,1712,1722,1732,1744,1756,1768,1778,1788,1798,1807,1816,1822,1832,1842,1851,1860,1869,1881,1892,1902,1912,1924,1936,1947,1958,1969,1981,1991,2003,2013,2025,2035,2047,2057,2068,2077,2087,2096,2106,2115,2121,2127,2139,2149,2161,2171,2183,2193,2204,2214
\ No newline at end of file
diff --git a/radio/src/fonts/480x272/font_stdsizebold.png b/radio/src/fonts/480x272/font_stdsizebold.png
index 5dfd2a49b..6af34b96a 100644
Binary files a/radio/src/fonts/480x272/font_stdsizebold.png and b/radio/src/fonts/480x272/font_stdsizebold.png differ
diff --git a/radio/src/fonts/480x272/font_stdsizebold.specs b/radio/src/fonts/480x272/font_stdsizebold.specs
index ac4ebc21b..d7c4b278a 100644
--- a/radio/src/fonts/480x272/font_stdsizebold.specs
+++ b/radio/src/fonts/480x272/font_stdsizebold.specs
@@ -1 +1 @@
-0,4,9,15,26,36,49,61,65,72,79,88,98,103,110,116,123,133,143,153,163,173,183,193,203,213,223,229,234,243,253,262,271,278,290,301,312,323,333,343,355,367,373,383,395,405,420,432,444,455,467,478,489,500,512,524,539,550,561,572,578,587,592,600,609,615,625,635,644,654,664,671,681,691,696,701,711,716,731,741,751,761,771,778,787,793,803,812,825,835,844,853,864,869,878,891,904,917,930,943,956,969,982,995,1010,1025,1040,1055,1070,1085,1100,1115,1130,1145,1160,1175,1185,1195,1205,1211,1220,1232,1242,1254,1264,1276,1286,1297,1307,1316,1325,1332,1341,1350,1360,1366,1376,1386,1396,1406,1416,1428,1436,1446,1457,1468,1479,1490,1501,1513,1519,1529,1541,1553,1565,1577,1588,1599,1611,1621,1631,1641,1651,1663,1675,1687,1697,1707,1717,1726,1736,1742,1752,1762,1771,1780,1789,1801,1812,1822,1832,1844,1856,1867,1878,1889,1899,1909,1919,1931,1943,1955
\ No newline at end of file
+0,4,9,15,26,36,49,61,65,72,79,88,98,103,110,116,124,134,144,154,164,174,184,194,204,214,224,230,235,244,254,263,272,279,291,302,313,324,334,344,356,368,374,384,396,406,421,433,445,456,468,479,490,501,513,525,540,551,562,573,579,588,593,601,610,616,626,636,645,655,665,672,682,692,697,703,713,718,733,743,753,763,773,780,789,796,806,815,828,838,848,857,868,873,882,895,908,921,934,947,960,973,986,999,1014,1029,1044,1059,1074,1089,1104,1119,1134,1149,1164,1179,1189,1199,1209,1217,1226,1238,1248,1260,1270,1282,1292,1303,1313,1322,1331,1339,1348,1358,1368,1375,1385,1395,1405,1415,1425,1437,1445,1455,1466,1477,1488,1499,1510,1522,1529,1539,1551,1563,1575,1587,1598,1609,1621,1631,1643,1653,1663,1673,1680,1687,1699,1709,1721,1731,1741,1751,1761,1773,1785,1797,1807,1817,1827,1836,1846,1852,1862,1872,1881,1890,1899,1911,1922,1932,1942,1954,1966,1977,1988,1999,2011,2021,2033,2043,2055,2065,2077,2087,2098,2107,2117,2127,2137,2147,2154,2161,2173,2183,2195,2205,2217,2227,2239,2249
\ No newline at end of file
diff --git a/radio/src/fonts/480x272/font_tinsize.png b/radio/src/fonts/480x272/font_tinsize.png
index 66a09bd54..1d5c7b32b 100644
Binary files a/radio/src/fonts/480x272/font_tinsize.png and b/radio/src/fonts/480x272/font_tinsize.png differ
diff --git a/radio/src/fonts/480x272/font_tinsize.specs b/radio/src/fonts/480x272/font_tinsize.specs
index 1f6806bfc..4152878fe 100644
--- a/radio/src/fonts/480x272/font_tinsize.specs
+++ b/radio/src/fonts/480x272/font_tinsize.specs
@@ -1 +1 @@
-0,4,7,11,18,24,32,39,42,46,50,55,61,64,68,71,76,82,88,94,100,106,112,118,124,130,136,139,142,148,154,160,165,169,176,183,190,197,203,209,216,223,226,232,239,245,254,261,268,275,282,289,295,302,309,316,325,332,339,346,350,355,358,363,369,373,379,385,391,397,403,408,414,420,423,426,432,435,444,450,456,462,468,472,478,482,488,493,501,507,513,519,526,529,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,541,547,553,557,563,570,576,583,589,596,602,608,614,620,626,631,637,643,649,653,659,665,671,677,683,690,695,701,707,714,721,728,735,742,746,752,759,766,773,780,787,794,801,807,813,819,825,832,839,846,852,858,864,870,876,880,886,892,898,904,910,917,924,930,936,943,950,956,963,970,976,982,988,995,1002,1009
\ No newline at end of file
+0,4,7,11,18,24,32,39,42,46,50,55,61,64,68,71,76,82,88,94,100,106,112,118,124,130,136,139,142,148,154,160,165,169,176,183,190,197,203,209,216,223,226,232,239,245,254,261,268,275,282,289,295,302,309,316,325,332,339,346,350,355,358,363,369,373,379,385,391,397,403,408,414,420,423,427,433,436,445,451,457,463,469,473,479,483,489,495,503,509,515,521,528,531,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,543,549,555,560,566,573,579,586,592,599,605,611,617,623,629,634,640,646,652,656,662,668,674,680,686,693,698,704,710,717,724,731,738,745,749,755,762,769,776,783,790,797,804,810,817,823,829,835,839,843,850,856,863,869,875,881,887,894,901,908,914,920,926,932,938,942,948,954,960,966,972,979,986,992,998,1005,1012,1018,1025,1032,1039,1045,1052,1058,1065,1071,1078,1084,1091,1097,1103,1109,1115,1121,1125,1129,1136,1142,1149,1155,1162,1168,1175,1181
\ No newline at end of file
diff --git a/radio/src/fonts/480x272/font_xxlsize.png b/radio/src/fonts/480x272/font_xxlsize.png
index c9a16dfe4..cd38d5e6d 100644
Binary files a/radio/src/fonts/480x272/font_xxlsize.png and b/radio/src/fonts/480x272/font_xxlsize.png differ
diff --git a/radio/src/fonts/480x272/font_xxlsize.specs b/radio/src/fonts/480x272/font_xxlsize.specs
index ac4d4eb30..3343a5bb3 100644
--- a/radio/src/fonts/480x272/font_xxlsize.specs
+++ b/radio/src/fonts/480x272/font_xxlsize.specs
@@ -1 +1 @@
-0,4,22,44,83,121,169,212,223,246,270,300,336,353,379,399,424,462,500,538,576,614,652,690,728,766,804,823,841,875,913,947,980,1006,1050,1092,1135,1178,1215,1251,1296,1342,1362,1399,1442,1478,1535,1581,1626,1668,1713,1755,1795,1836,1879,1922,1979,2021,2062,2102,2121,2151,2170,2199,2229,2251,2286,2323,2357,2394,2430,2454,2492,2529,2547,2565,2601,2619,2675,2712,2749,2786,2823,2847,2881,2904,2941,2974,3022,3056,3089,3123,3166,3183,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3217,3253,3289,3324,3346,3380,3424,3459,3504,3541,3584,3621,3662,3698,3732,3766,3793,3827,3860,3895,3917,3953,3990,4027,4064,4101,4146,4174,4211,4251,4294,4336,4376,4417,4461,4484,4521,4567,4612,4655,4698,4741,4782,4828,4865,4900,4935,4972,5016,5060,5105,5140,5177,5212,5246,5282,5303,5340,5377,5411,5445,5479,5523,5566,5603,5640,5686,5731,5771,5811,5851,5886,5921,5958,6002,6046,6091
\ No newline at end of file
+0,4,22,44,83,121,169,212,223,246,270,300,336,353,379,399,425,463,501,539,577,615,653,691,729,767,805,824,842,876,914,948,981,1007,1051,1093,1136,1179,1216,1252,1297,1343,1363,1400,1443,1479,1536,1582,1627,1669,1714,1756,1796,1837,1880,1923,1980,2022,2063,2103,2122,2152,2171,2200,2230,2252,2287,2324,2358,2395,2431,2455,2493,2530,2548,2569,2605,2623,2679,2716,2753,2790,2827,2851,2885,2908,2945,2978,3026,3060,3094,3128,3171,3188,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3222,3258,3294,3329,3355,3389,3433,3468,3513,3550,3593,3630,3671,3707,3741,3775,3802,3836,3870,3905,3927,3963,4000,4037,4074,4111,4156,4184,4221,4261,4304,4346,4386,4427,4471,4493,4530,4576,4621,4664,4707,4750,4791,4837,4874,4918,4953,4990,5026,5048,5070,5115,5152,5195,5232,5267,5302,5339,5383,5427,5472,5507,5544,5579,5613,5649,5670,5707,5744,5778,5812,5846,5890,5933,5970,6007,6053,6098,6138,6178,6218,6262,6297,6341,6376,6420,6455,6499,6534,6577,6611,6648,6684,6721,6757,6779,6801,6846,6883,6928,6965,7010,7047,7090,7127
\ No newline at end of file
diff --git a/radio/src/fonts/sqt5/font_es_04x06.png b/radio/src/fonts/sqt5/font_es_04x06.png
index 23425282a..64c5040a8 100644
Binary files a/radio/src/fonts/sqt5/font_es_04x06.png and b/radio/src/fonts/sqt5/font_es_04x06.png differ
diff --git a/radio/src/fonts/sqt5/font_es_05x07.png b/radio/src/fonts/sqt5/font_es_05x07.png
index d23e8b850..55ec15e4f 100644
Binary files a/radio/src/fonts/sqt5/font_es_05x07.png and b/radio/src/fonts/sqt5/font_es_05x07.png differ
diff --git a/radio/src/fonts/sqt5/font_es_08x10.png b/radio/src/fonts/sqt5/font_es_08x10.png
index 6f520ee2a..c2c9b9465 100644
Binary files a/radio/src/fonts/sqt5/font_es_08x10.png and b/radio/src/fonts/sqt5/font_es_08x10.png differ
diff --git a/radio/src/fonts/sqt5/font_es_10x14.png b/radio/src/fonts/sqt5/font_es_10x14.png
index d66da4460..bfaa3b87e 100644
Binary files a/radio/src/fonts/sqt5/font_es_10x14.png and b/radio/src/fonts/sqt5/font_es_10x14.png differ
diff --git a/radio/src/fonts/std/font_es_04x06.png b/radio/src/fonts/std/font_es_04x06.png
index 876bc5b7a..b3cff8c78 100644
Binary files a/radio/src/fonts/std/font_es_04x06.png and b/radio/src/fonts/std/font_es_04x06.png differ
diff --git a/radio/src/fonts/std/font_es_05x07.png b/radio/src/fonts/std/font_es_05x07.png
index 50a64fe6c..066e7cab5 100644
Binary files a/radio/src/fonts/std/font_es_05x07.png and b/radio/src/fonts/std/font_es_05x07.png differ
diff --git a/radio/src/fonts/std/font_es_08x10.png b/radio/src/fonts/std/font_es_08x10.png
index d88578f1f..78a166085 100644
Binary files a/radio/src/fonts/std/font_es_08x10.png and b/radio/src/fonts/std/font_es_08x10.png differ
diff --git a/radio/src/fonts/std/font_es_10x14.png b/radio/src/fonts/std/font_es_10x14.png
index 72383b448..05411cc13 100644
Binary files a/radio/src/fonts/std/font_es_10x14.png and b/radio/src/fonts/std/font_es_10x14.png differ
diff --git a/radio/src/globals.h b/radio/src/globals.h
new file mode 100644
index 000000000..cf67dbc4a
--- /dev/null
+++ b/radio/src/globals.h
@@ -0,0 +1,97 @@
+/*
+ * 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 _GLOBALS_H_
+#define _GLOBALS_H_
+
+#include "definitions.h"
+#include "dataconstants.h"
+
+PACK(struct GlobalData {
+ uint8_t unexpectedShutdown:1;
+ uint8_t externalAntennaEnabled:1;
+ uint8_t authenticationCount:2;
+ uint8_t upgradeModulePopup:1;
+ uint8_t internalModuleVersionChecked:1;
+ uint8_t spare:2;
+});
+
+extern GlobalData globalData;
+
+extern uint16_t sessionTimer;
+extern uint16_t s_timeCumThr;
+extern uint16_t s_timeCum16ThrP;
+
+#if defined(OVERRIDE_CHANNEL_FUNCTION)
+#define OVERRIDE_CHANNEL_UNDEFINED -4096
+extern safetych_t safetyCh[MAX_OUTPUT_CHANNELS];
+#endif
+
+extern uint8_t trimsCheckTimer;
+extern uint8_t trimsDisplayTimer;
+extern uint8_t trimsDisplayMask;
+extern uint16_t maxMixerDuration;
+
+extern uint8_t requiredSpeakerVolume;
+
+enum MainRequest {
+ REQUEST_SCREENSHOT,
+ REQUEST_FLIGHT_RESET,
+};
+
+extern uint8_t mainRequestFlags;
+
+#define DELAY_POS_MARGIN 3
+typedef int16_t delayval_t;
+PACK(struct SwOn {
+ uint16_t delay:14; // max = 2550
+ uint8_t activeMix:1;
+ uint8_t activeExpo:1;
+ int16_t now; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
+ int16_t prev;
+});
+
+extern SwOn swOn[MAX_MIXERS];
+extern int32_t act[MAX_MIXERS];
+
+// static variables used in evalFlightModeMixes - moved here so they don't interfere with the stack
+// It's also easier to initialize them here.
+extern int8_t virtualInputsTrims[MAX_INPUTS];
+
+extern int16_t anas [MAX_INPUTS];
+extern int16_t trims[NUM_TRIMS];
+extern int32_t chans[MAX_OUTPUT_CHANNELS];
+extern int16_t ex_chans[MAX_OUTPUT_CHANNELS]; // Outputs (before LIMITS) of the last perMain
+extern int16_t channelOutputs[MAX_OUTPUT_CHANNELS];
+
+typedef uint16_t BeepANACenter;
+extern BeepANACenter bpanaCenter;
+
+extern uint8_t s_mixer_first_run_done;
+
+extern int16_t calibratedAnalogs[NUM_CALIBRATED_ANALOGS];
+
+extern uint8_t g_beepCnt;
+extern uint8_t beepAgain;
+extern uint16_t lightOffCounter;
+extern uint8_t flashCounter;
+extern uint8_t mixWarning;
+
+#endif
diff --git a/radio/src/gui/128x64/gui.h b/radio/src/gui/128x64/gui.h
index 329a9c3a4..1e48d6746 100644
--- a/radio/src/gui/128x64/gui.h
+++ b/radio/src/gui/128x64/gui.h
@@ -40,6 +40,7 @@
#define drawFieldLabel(x, y, str) lcdDrawTextAlignedLeft(y, str)
#define NUM_BODY_LINES (LCD_LINES-1)
+#define TEXT_VIEWER_LINES NUM_BODY_LINES
#define MENU_HEADER_HEIGHT FH
#define CURVE_SIDE_WIDTH (LCD_H/2)
@@ -215,7 +216,7 @@ extern uint8_t s_copyMode;
extern int8_t s_copySrcRow;
extern int8_t s_copyTgtOfs;
extern uint8_t s_currIdx;
-extern uint8_t s_curveChan;
+extern uint8_t s_currIdxSubMenu;
extern uint8_t s_copySrcIdx;
extern uint8_t s_copySrcCh;
extern int8_t s_currCh;
@@ -235,6 +236,9 @@ void pushMenuTextView(const char *filename);
void pushModelNotes();
void readModelNotes();
+void menuChannelsView(event_t event);
+void menuChannelsViewCommon(event_t event);
+
#define CURSOR_MOVED_LEFT(event) (IS_ROTARY_LEFT(event) || EVT_KEY_MASK(event) == KEY_LEFT)
#define CURSOR_MOVED_RIGHT(event) (IS_ROTARY_RIGHT(event) || EVT_KEY_MASK(event) == KEY_RIGHT)
@@ -294,6 +298,7 @@ void drawProgressScreen(const char * title, const char * message, int num, int d
void drawSleepBitmap();
void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible);
+void drawGauge(coord_t x, coord_t y, coord_t w, coord_t h, int32_t val, int32_t max);
void drawAlertBox(const char * title, const char * text, const char * action);
void showAlertBox(const char * title, const char * text, const char * action , uint8_t sound);
@@ -302,8 +307,8 @@ void showAlertBox(const char * title, const char * text, const char * action , u
#define LOAD_MODEL_BITMAP()
#define IS_MAIN_VIEW_DISPLAYED() menuHandlers[0] == menuMainView
-#define IS_TELEMETRY_VIEW_DISPLAYED() menuHandlers[0] == menuViewTelemetryFrsky
-#define IS_OTHER_VIEW_DISPLAYED() false
+#define IS_TELEMETRY_VIEW_DISPLAYED() menuHandlers[0] == menuViewTelemetry
+#define IS_OTHER_VIEW_DISPLAYED() menuHandlers[0] == menuChannelsView
void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags);
diff --git a/radio/src/gui/128x64/lcd.cpp b/radio/src/gui/128x64/lcd.cpp
index 15d543e72..9118fef5d 100644
--- a/radio/src/gui/128x64/lcd.cpp
+++ b/radio/src/gui/128x64/lcd.cpp
@@ -18,9 +18,10 @@
* GNU General Public License for more details.
*/
+#include
#include "opentx.h"
-display_t displayBuf[DISPLAY_BUFFER_SIZE];
+display_t displayBuf[DISPLAY_BUFFER_SIZE] __DMA;
void lcdClear()
{
@@ -115,7 +116,6 @@ void lcdPutPattern(coord_t x, coord_t y, const uint8_t * pattern, uint8_t width,
}
}
-#if !defined(BOOT)
struct PatternData
{
uint8_t width;
@@ -142,10 +142,11 @@ uint8_t getPatternWidth(const PatternData * pattern)
void getCharPattern(PatternData * pattern, unsigned char c, LcdFlags flags)
{
+#if !defined(BOOT)
uint32_t fontsize = FONTSIZE(flags);
unsigned char c_remapped = 0;
- if (fontsize == DBLSIZE || (flags&BOLD)) {
+ if (fontsize == DBLSIZE || (flags & BOLD)) {
// To save space only some DBLSIZE and BOLD chars are available
// c has to be remapped. All non existing chars mapped to 0 (space)
if (c>=',' && c<=':')
@@ -202,6 +203,11 @@ void getCharPattern(PatternData * pattern, unsigned char c, LcdFlags flags)
pattern->height = 7;
pattern->data = (c < 0xC0) ? &font_5x7[(c-0x20)*5] : &font_5x7_extra[(c-0xC0)*5];
}
+#else
+ pattern->width = 5;
+ pattern->height = 7;
+ pattern->data = &font_5x7[(c-0x20)*5];
+#endif
}
uint8_t getCharWidth(char c, LcdFlags flags)
@@ -210,7 +216,6 @@ uint8_t getCharWidth(char c, LcdFlags flags)
getCharPattern(&pattern, c, flags);
return getPatternWidth(&pattern);
}
-#endif
void lcdDrawChar(coord_t x, coord_t y, const unsigned char c, LcdFlags flags)
{
@@ -287,12 +292,15 @@ void lcdDrawChar(coord_t x, coord_t y, const unsigned char c)
lcdDrawChar(x, y, c, 0);
}
-#if !defined(BOOT)
uint8_t getTextWidth(const char * s, uint8_t len, LcdFlags flags)
{
uint8_t width = 0;
- for (int i=0; len==0 || i 0 ? 3 + crv.points : -3 - crv.points)) {
+ if (moveCurve(s_currIdxSubMenu, checkIncDec_Ret > 0 ? 3 + crv.points : -3 - crv.points)) {
if (newType == CURVE_TYPE_CUSTOM) {
resetCustomCurveX(points, 5 + crv.points);
}
@@ -125,14 +125,17 @@ void menuModelCurveOne(event_t event)
lcdDrawNumber(INDENT_WIDTH, 6*FH+1, 5+crv.points, LEFT|attr);
lcdDrawText(lcdLastRightPos, 6*FH+1, STR_PTS, attr);
if (attr) {
+#if defined(ROTARY_ENCODER_NAVIGATION)
+ rotencSpeed = ROTENC_LOWSPEED;
+#endif
int8_t count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts
if (checkIncDec_Ret) {
int8_t newPoints[MAX_POINTS_PER_CURVE];
newPoints[0] = points[0];
newPoints[4 + count] = points[4 + crv.points];
for (int i = 1; i < 4 + count; i++)
- newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(getCurveX(5 + count, i)), s_curveChan));
- if (moveCurve(s_curveChan, checkIncDec_Ret * (crv.type == CURVE_TYPE_CUSTOM ? 2 : 1))) {
+ newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(getCurveX(5 + count, i)), s_currIdxSubMenu));
+ if (moveCurve(s_currIdxSubMenu, checkIncDec_Ret * (crv.type == CURVE_TYPE_CUSTOM ? 2 : 1))) {
for (int i = 0; i < 5 + count; i++) {
points[i] = newPoints[i];
if (crv.type == CURVE_TYPE_CUSTOM && i != 0 && i != 4 + count)
@@ -161,6 +164,18 @@ void menuModelCurveOne(event_t event)
POPUP_MENU_START(onCurveOneMenu);
}
break;
+
+#if defined(NAVIGATION_X7)
+ case EVT_KEY_LONG(KEY_MENU):
+ pushMenu(menuChannelsView);
+ killEvents(event);
+ break;
+#elif defined(NAVIGATION_XLITE)
+ case EVT_KEY_LONG(KEY_SHIFT):
+ pushMenu(menuChannelsView);
+ killEvents(event);
+ break;
+#endif
}
drawCurve(0);
diff --git a/radio/src/gui/128x64/model_failsafe.cpp b/radio/src/gui/128x64/model_failsafe.cpp
index f0a926074..7648cd9f3 100644
--- a/radio/src/gui/128x64/model_failsafe.cpp
+++ b/radio/src/gui/128x64/model_failsafe.cpp
@@ -51,7 +51,7 @@ void menuModelFailsafe(event_t event)
SIMPLE_SUBMENU_NOTITLE(sentModuleChannels(g_moduleIdx));
- lcdDrawTextAlignedCenter(0, TR_FAILSAFESET);
+ lcdDrawText(LCD_W / 2, 0, STR_FAILSAFESET, CENTERED);
lcdInvertLine(0);
for (uint8_t i=0; i=ITEM_MODEL_FLIGHT_MODE_SWITCH) sub += VERTICAL_SHIFT;
+ if (s_currIdx == 0 && sub>=ITEM_MODEL_FLIGHT_MODE_SWITCH)
+ sub += VERTICAL_SHIFT;
for (uint8_t k=0; k 0 && attr && menuHorizontalPosition == t) {
+#else
if (s_editMode >= 0 && attr && menuHorizontalPosition == t) {
+#endif
trim_t & v = fm->trim[t];
v.mode = checkIncDec(event, v.mode==TRIM_MODE_NONE ? -1 : v.mode, -1, k==0 ? 0 : 2*MAX_FLIGHT_MODES-1, EE_MODEL, isTrimModeAvailable);
}
@@ -143,7 +148,7 @@ void menuModelFlightModeOne(event_t event)
drawStringWithIndex(INDENT_WIDTH, y, STR_GV, idx+1, posHorz==0 ? attr : 0);
lcdDrawSizedText(4*FW, y,g_model.gvars[idx].name, LEN_GVAR_NAME, ZCHAR);
if (attr && editMode>0 && posHorz==0) {
- s_currIdx = sub - ITEM_MODEL_FLIGHT_MODE_GV1;
+ s_currIdxSubMenu = sub - ITEM_MODEL_FLIGHT_MODE_GV1;
editMode = 0;
pushMenu(menuModelGVarOne);
}
diff --git a/radio/src/gui/128x64/model_gvars.cpp b/radio/src/gui/128x64/model_gvars.cpp
index 4299469fe..f2e25875a 100644
--- a/radio/src/gui/128x64/model_gvars.cpp
+++ b/radio/src/gui/128x64/model_gvars.cpp
@@ -64,10 +64,10 @@ enum GVarFields {
void menuModelGVarOne(event_t event)
{
- GVarData * gvar = &g_model.gvars[s_currIdx];
+ GVarData * gvar = &g_model.gvars[s_currIdxSubMenu];
- drawStringWithIndex(PSIZE(TR_GVARS)*FW+FW, 0, STR_GV, s_currIdx+1, 0);
- drawGVarValue(32*FW, 0, s_currIdx, getGVarValue(s_currIdx, getFlightMode()));
+ drawStringWithIndex(PSIZE(TR_GVARS)*FW+FW, 0, STR_GV, s_currIdxSubMenu+1, 0);
+ drawGVarValue(32*FW, 0, s_currIdxSubMenu, getGVarValue(s_currIdxSubMenu, getFlightMode()));
lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID);
SIMPLE_SUBMENU(STR_GVARS, GVAR_FIELD_LAST);
@@ -92,13 +92,13 @@ void menuModelGVarOne(event_t event)
case GVAR_FIELD_MIN:
lcdDrawText(0, y, STR_MIN);
- drawGVarValue(GVAR_2ND_COLUMN, y, s_currIdx, GVAR_MIN+gvar->min, LEFT|attr);
+ drawGVarValue(GVAR_2ND_COLUMN, y, s_currIdxSubMenu, GVAR_MIN+gvar->min, LEFT|attr);
if (attr) gvar->min = checkIncDec(event, GVAR_MIN+gvar->min, GVAR_MIN, GVAR_MAX-gvar->max, EE_MODEL) - GVAR_MIN;
break;
case GVAR_FIELD_MAX:
lcdDrawText(0, y, STR_MAX);
- drawGVarValue(GVAR_2ND_COLUMN, y, s_currIdx, GVAR_MAX-gvar->max, LEFT|attr);
+ drawGVarValue(GVAR_2ND_COLUMN, y, s_currIdxSubMenu, GVAR_MAX-gvar->max, LEFT|attr);
if (attr) gvar->max = GVAR_MAX - checkIncDec(event, GVAR_MAX-gvar->max, GVAR_MIN+gvar->min, GVAR_MAX, EE_MODEL);
break;
@@ -108,7 +108,7 @@ void menuModelGVarOne(event_t event)
default:
drawStringWithIndex(0, y, STR_FM, k-GVAR_FIELD_FM0);
- editGVarValue(GVAR_2ND_COLUMN, y, event, s_currIdx, k-GVAR_FIELD_FM0, LEFT|attr);
+ editGVarValue(GVAR_2ND_COLUMN, y, event, s_currIdxSubMenu, k-GVAR_FIELD_FM0, LEFT|attr);
break;
}
}
diff --git a/radio/src/gui/128x64/model_input_edit.cpp b/radio/src/gui/128x64/model_input_edit.cpp
index 29889e0ca..a2423189b 100644
--- a/radio/src/gui/128x64/model_input_edit.cpp
+++ b/radio/src/gui/128x64/model_input_edit.cpp
@@ -72,6 +72,17 @@ enum ExposFields {
void menuModelExpoOne(event_t event)
{
+#if defined(NAVIGATION_X7)
+ if (event == EVT_KEY_LONG(KEY_MENU)) {
+ pushMenu(menuChannelsView);
+ killEvents(event);
+ }
+#elif defined(NAVIGATION_XLITE)
+ if (event == EVT_KEY_LONG(KEY_SHIFT)) {
+ pushMenu(menuChannelsView);
+ killEvents(event);
+ }
+#endif
ExpoData * ed = expoAddress(s_currIdx);
drawSource(PSIZE(TR_MENUINPUTS)*FW+FW, 0, MIXSRC_FIRST_INPUT+ed->chn, 0);
diff --git a/radio/src/gui/128x64/model_inputs_mixes.cpp b/radio/src/gui/128x64/model_inputs_mixes.cpp
index 03bdfb411..953ee64b1 100644
--- a/radio/src/gui/128x64/model_inputs_mixes.cpp
+++ b/radio/src/gui/128x64/model_inputs_mixes.cpp
@@ -271,7 +271,7 @@ void menuModelExpoOne(event_t event)
CHECK_INCDEC_MODELVAR_ZERO(event, ed->curveParam, CURVE_BASE+MAX_CURVES-1);
if (ed->curveParam) ed->curveMode = MODE_CURVE;
if (ed->curveParam>=CURVE_BASE && event==EVT_KEY_LONG(KEY_ENTER)) {
- s_curveChan = ed->curveParam - CURVE_BASE;
+ s_currIdxSubMenu = ed->curveParam - CURVE_BASE;
pushMenu(menuModelCurveOne);
}
}
@@ -442,7 +442,7 @@ void menuModelMixOne(event_t event)
drawCurveName(COLUMN_X+MIXES_2ND_COLUMN, y, curveParam, attr);
if (attr) {
if (event==EVT_KEY_LONG(KEY_ENTER) && (curveParam<0 || curveParam>=CURVE_BASE)){
- s_curveChan = (curveParam<0 ? -curveParam-1 : curveParam-CURVE_BASE);
+ s_currIdxSubMenu = (curveParam<0 ? -curveParam-1 : curveParam-CURVE_BASE);
pushMenu(menuModelCurveOne);
}
else {
diff --git a/radio/src/gui/128x64/model_logical_switches.cpp b/radio/src/gui/128x64/model_logical_switches.cpp
index 90fc08481..b0acc2ae4 100644
--- a/radio/src/gui/128x64/model_logical_switches.cpp
+++ b/radio/src/gui/128x64/model_logical_switches.cpp
@@ -83,7 +83,7 @@ void menuModelLogicalSwitchOne(event_t event)
uint8_t new_cstate = lswFamily(cs->func);
if (cstate != new_cstate) {
if (new_cstate == LS_FAMILY_TIMER) {
- cs->v1 = cs->v2 = 0;
+ cs->v1 = cs->v2 = -119;
}
else if (new_cstate == LS_FAMILY_EDGE) {
cs->v1 = 0; cs->v2 = -129; cs->v3 = 0;
@@ -254,12 +254,13 @@ void menuModelLogicalSwitches(event_t event)
uint8_t k = 0;
int8_t sub = menuVerticalPosition - HEADER_LINE;
- if (event==EVT_KEY_FIRST(KEY_ENTER)) {
+ if (event == EVT_KEY_FIRST(KEY_ENTER)) {
killEvents(event);
LogicalSwitchData * cs = lswAddress(sub);
if (cs->func)
s_currIdx = sub;
- POPUP_MENU_ADD_ITEM(STR_EDIT);
+ if (sub >= 0)
+ POPUP_MENU_ADD_ITEM(STR_EDIT);
if (cs->func || cs->v1 || cs->v2 || cs->delay || cs->duration || cs->andsw)
POPUP_MENU_ADD_ITEM(STR_COPY);
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH)
diff --git a/radio/src/gui/128x64/model_mix_edit.cpp b/radio/src/gui/128x64/model_mix_edit.cpp
index 785d8a989..a2180b6ac 100644
--- a/radio/src/gui/128x64/model_mix_edit.cpp
+++ b/radio/src/gui/128x64/model_mix_edit.cpp
@@ -85,6 +85,17 @@ void drawOffsetBar(uint8_t x, uint8_t y, MixData * md)
void menuModelMixOne(event_t event)
{
+#if defined(NAVIGATION_X7)
+ if (event == EVT_KEY_LONG(KEY_MENU)) {
+ pushMenu(menuChannelsView);
+ killEvents(event);
+ }
+#elif defined(NAVIGATION_XLITE)
+ if (event == EVT_KEY_LONG(KEY_SHIFT)) {
+ pushMenu(menuChannelsView);
+ killEvents(event);
+ }
+#endif
MixData * md2 = mixAddress(s_currIdx) ;
putsChn(PSIZE(TR_MIXES)*FW+FW, 0, md2->destCh+1,0);
@@ -139,7 +150,7 @@ void menuModelMixOne(event_t event)
case MIX_FIELD_CURVE:
lcdDrawTextAlignedLeft(y, STR_CURVE);
- editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr);
+ editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, s_editMode > 0 ? event : 0, attr);
break;
#if defined(FLIGHT_MODES)
diff --git a/radio/src/gui/128x64/model_outputs.cpp b/radio/src/gui/128x64/model_outputs.cpp
index a069e2362..0fde67159 100644
--- a/radio/src/gui/128x64/model_outputs.cpp
+++ b/radio/src/gui/128x64/model_outputs.cpp
@@ -215,6 +215,9 @@ void onLimitsMenu(const char *result)
else if (result == STR_EDIT) {
pushMenu(menuModelLimitsOne);
}
+ else if (result == STR_COPY_MIN_MAX_TO_OUTPUTS) {
+ copyMinMaxToOutputs(s_currIdx);
+ }
}
void menuModelLimits(event_t event)
@@ -240,6 +243,7 @@ void menuModelLimits(event_t event)
POPUP_MENU_ADD_ITEM(STR_RESET);
POPUP_MENU_ADD_ITEM(STR_COPY_TRIMS_TO_OFS);
POPUP_MENU_ADD_ITEM(STR_COPY_STICKS_TO_OFS);
+ POPUP_MENU_ADD_ITEM(STR_COPY_MIN_MAX_TO_OUTPUTS);
POPUP_MENU_START(onLimitsMenu);
}
diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp
index 5860bf2ca..4319ed8dc 100644
--- a/radio/src/gui/128x64/model_setup.cpp
+++ b/radio/src/gui/128x64/model_setup.cpp
@@ -85,6 +85,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_INTERNAL_MODULE_LABEL,
ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE,
#if defined(MULTIMODULE)
+ ITEM_MODEL_SETUP_INTERNAL_MODULE_PROTOCOL,
ITEM_MODEL_SETUP_INTERNAL_MODULE_SUBTYPE,
ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS,
ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS,
@@ -113,17 +114,26 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE,
#if defined(MULTIMODULE)
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_PROTOCOL,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_SUBTYPE,
-#endif
-#if defined(MULTIMODULE)
ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS,
+#endif
+#if defined(AFHDS3)
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS_PROTOCOL,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS,
#endif
ITEM_MODEL_SETUP_EXTERNAL_MODULE_CHANNELS,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_MODEL_NUM,
#if defined(PCBSKY9X) && defined(REVX)
ITEM_MODEL_SETUP_EXTERNAL_MODULE_OUTPUT_TYPE,
+#endif
+#if defined(AFHDS3)
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER,
#endif
ITEM_MODEL_SETUP_EXTERNAL_MODULE_POWER,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_OPTIONS,
@@ -132,6 +142,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING,
#endif
+
ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_REGISTER_RANGE,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_OPTIONS,
@@ -158,8 +169,6 @@ enum MenuModelSetupItems {
};
#define MODEL_SETUP_2ND_COLUMN (LCD_W-11*FW)
-#define MODEL_SETUP_BIND_OFS 2*FW+1
-#define MODEL_SETUP_RANGE_OFS 4*FW+3
#define MODEL_SETUP_SET_FAILSAFE_OFS 7*FW-2
#define IF_PXX2_MODULE(module, xxx) (isModulePXX2(module) ? (uint8_t)(xxx) : HIDDEN_ROW)
@@ -206,11 +215,6 @@ inline uint8_t MODULE_TYPE_ROWS(int moduleIdx)
{
if (isModuleXJT(moduleIdx) || isModuleR9MNonAccess(moduleIdx) || isModuleDSM2(moduleIdx))
return 1;
-#if defined(MULTIMODULE)
- else if (isModuleMultimodule(moduleIdx)) {
- return 1;
- }
-#endif
else
return 0;
}
@@ -259,7 +263,11 @@ void onModelAntennaSwitchConfirm(const char * result)
#define EXTERNAL_ANTENNA_ROW
#endif
-#if defined(PCBX7) || defined(PCBX9LITE)
+#if defined(PCBX7ACCESS)
+ #define TRAINER_BLUETOOTH_ROW (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_BLUETOOTH_M_ROW : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? TRAINER_BLUETOOTH_S_ROW : HIDDEN_ROW))
+ #define TRAINER_PPM_PARAMS_ROW (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW)
+ #define TRAINER_ROWS LABEL(Trainer), 0, IF_BT_TRAINER_ON(TRAINER_BLUETOOTH_ROW), TRAINER_CHANNELS_ROW, TRAINER_PPM_PARAMS_ROW
+#elif defined(PCBX7) || defined(PCBX9LITE)
#if defined(BLUETOOTH)
#define TRAINER_BLUETOOTH_ROW (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_BLUETOOTH_M_ROW : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? TRAINER_BLUETOOTH_S_ROW : HIDDEN_ROW)),
#else
@@ -298,23 +306,27 @@ void onBluetoothConnectMenu(const char * result)
#if defined(PXX2)
#include "common/stdlcd/model_setup_pxx2.cpp"
#endif
+#if defined(AFHDS3)
+#include "common/stdlcd/model_setup_afhds3.cpp"
+#endif
#if defined(HARDWARE_INTERNAL_MODULE)
#define INTERNAL_MODULE_ROWS \
LABEL(InternalModule), \
- MODULE_TYPE_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE*/ \
- MULTIMODULE_SUBTYPE_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_SUBTYPE*/ \
+ MODULE_TYPE_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE */ \
+ MULTIMODULE_TYPE_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PROTOCOL */ \
+ MULTIMODULE_SUBTYPE_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_SUBTYPE */ \
MULTIMODULE_STATUS_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS, ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS */ \
- MODULE_CHANNELS_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS*/ \
- IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(IF_INTERNAL_MODULE_ON(isModuleRxNumAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1))), /* *ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE */\
- IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM*/ \
+ MODULE_CHANNELS_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS */ \
+ IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, MODULE_BIND_ROWS(INTERNAL_MODULE)), /* *ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE */\
+ IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM */ \
MODULE_OPTION_ROW(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS */ \
MULTIMODULE_MODULE_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND */ \
EXTERNAL_ANTENNA_ROW /* ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA */ \
MODULE_POWER_ROW(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_POWER */ \
IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE */ \
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_REGISTER_RANGE */ \
- IF_PXX2_MODULE(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_OPTIONS*/ \
+ IF_PXX2_MODULE(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_OPTIONS */ \
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1 */ \
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_2 */ \
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_3 */
@@ -358,16 +370,20 @@ void menuModelSetup(event_t event)
LABEL(ExternalModule),
MODULE_TYPE_ROWS(EXTERNAL_MODULE),
- MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE)
+ MULTIMODULE_TYPE_ROWS(EXTERNAL_MODULE) // PROTOCOL
+ MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE) // SUBTYPE
MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE)
+ AFHDS3_PROTOCOL_ROW(EXTERNAL_MODULE)
+ AFHDS3_MODE_ROWS(EXTERNAL_MODULE)
MODULE_CHANNELS_ROWS(EXTERNAL_MODULE),
IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), // line reused for PPM: PPM settings
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum
+ AFHDS3_MODULE_ROWS(EXTERNAL_MODULE)
MODULE_POWER_ROW(EXTERNAL_MODULE),
IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)),
MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE)
- FAILSAFE_ROWS(EXTERNAL_MODULE),
- IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons
+ FAILSAFE_ROWS(EXTERNAL_MODULE), //ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE
+ IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons
IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // Module options
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 1
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 2
@@ -398,18 +414,21 @@ void menuModelSetup(event_t event)
NUM_STICKS+NUM_POTS+NUM_SLIDERS-1, // Center beeps
0, // Global functions
- LABEL(ExternalModule),
+ LABEL(ExternalModule),
MODULE_TYPE_ROWS(EXTERNAL_MODULE),
+ MULTIMODULE_TYPE_ROWS(EXTERNAL_MODULE)
MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE)
MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE)
+
MODULE_CHANNELS_ROWS(EXTERNAL_MODULE),
IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), // line reused for PPM: PPM settings
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum
+ 0, // Output type (OpenDrain / PushPull)
MODULE_POWER_ROW(EXTERNAL_MODULE),
IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)),
MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE)
FAILSAFE_ROWS(EXTERNAL_MODULE),
- IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons
+ IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons
IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // Module options
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 1
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 2
@@ -504,7 +523,7 @@ void menuModelSetup(event_t event)
break;
case 2:
qr.rem -= checkIncDecModel(event, qr.rem+2, 1, 62)-2;
- timer->start -= qr.rem ;
+ timer->start -= qr.rem;
if ((int16_t)timer->start < 0) timer->start=0;
if ((int16_t)timer->start > 5999) timer->start=32399; // 8:59:59
break;
@@ -578,7 +597,7 @@ void menuModelSetup(event_t event)
break;
case ITEM_MODEL_SETUP_THROTTLE_REVERSED:
- ON_OFF_MENU_ITEM(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEREVERSE, attr, event ) ;
+ ON_OFF_MENU_ITEM(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEREVERSE, attr, event );
break;
case ITEM_MODEL_SETUP_THROTTLE_TRACE:
@@ -724,24 +743,24 @@ void menuModelSetup(event_t event)
}
}
- for (uint8_t i=0; i>= 2;
+ c = '0' + (states & 0x03);
+ states >>= 2u;
}
else {
if ((states & 0x01) && swactive)
- attr = INVERS;
+ swattr = INVERS;
c = *(STR_VSWITCHES - 2 + 9 + (3*(i+1)));
- states >>= 1;
+ states >>= 1u;
}
if (attr && (menuHorizontalPosition == i)) {
- attr = BLINK | INVERS;
+ swattr = BLINK | INVERS;
}
- lcdDrawChar(MODEL_SETUP_2ND_COLUMN+i*FW, y, (swactive) ? c : '-', attr);
+ lcdDrawChar(MODEL_SETUP_2ND_COLUMN+i*FW, y, swactive ? c : '-', swattr);
lcdDrawText(MODEL_SETUP_2ND_COLUMN+(NUM_SWITCHES*FW), y, "<]", (menuHorizontalPosition == NUM_SWITCHES-1 && !NO_HIGHLIGHT()) ? attr : 0);
}
#endif
@@ -799,10 +818,9 @@ void menuModelSetup(event_t event)
case ITEM_MODEL_SETUP_BEEP_CENTER:
lcdDrawTextAlignedLeft(y, STR_BEEPCTR);
- for (uint8_t i=0; i 0) {
g_model.moduleData[moduleIdx].type = MODULE_TYPE_NONE;
@@ -954,18 +966,6 @@ void menuModelSetup(event_t event)
g_model.moduleData[moduleIdx].channelsCount = defaultModuleChannels_M8(moduleIdx);
}
}
-
-#if defined(MULTIMODULE)
- else if (isModuleMultimodule(moduleIdx)) {
- int multiRfProto = g_model.moduleData[moduleIdx].getMultiProtocol();
- CHECK_INCDEC_MODELVAR_CHECK(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MULTI_MAX_PROTOCOLS, isMultiProtocolSelectable);
- if (checkIncDec_Ret) {
- g_model.moduleData[moduleIdx].setMultiProtocol(multiRfProto);
- g_model.moduleData[moduleIdx].subType = 0;
- resetMultiProtocolsOptions(moduleIdx);
- }
- }
-#endif
else {
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].subType, 0, MODULE_SUBTYPE_PXX1_LAST);
}
@@ -1000,6 +1000,45 @@ void menuModelSetup(event_t event)
break;
#if defined(MULTIMODULE)
+#if defined(HARDWARE_INTERNAL_MODULE)
+ case ITEM_MODEL_SETUP_INTERNAL_MODULE_PROTOCOL:
+#endif
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PROTOCOL:
+ {
+ lcdDrawTextAlignedLeft(y, TR_TYPE);
+ int multi_rfProto = g_model.moduleData[moduleIdx].getMultiProtocol();
+ lcdDrawMultiProtocolString(MODEL_SETUP_2ND_COLUMN, y, moduleIdx, multi_rfProto, attr);
+ if (attr) {
+ int multiRfProto = g_model.moduleData[moduleIdx].getMultiProtocol();
+ MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
+ if (status.isValid()) {
+ int8_t direction = checkIncDec(event, 0, -1, 1);
+ if (direction == -1) {
+ if (multiRfProto == MODULE_SUBTYPE_MULTI_FRSKY)
+ multiRfProto = MODULE_SUBTYPE_MULTI_FRSKYX_RX;
+ else
+ multiRfProto = convertMultiToOtx(status.protocolPrev);
+ }
+ if (direction == 1) {
+ if (multiRfProto == MODULE_SUBTYPE_MULTI_FRSKY)
+ multiRfProto = MODULE_SUBTYPE_MULTI_FRSKYX2;
+ else
+ multiRfProto = convertMultiToOtx(status.protocolNext);
+ }
+ }
+ else {
+ CHECK_INCDEC_MODELVAR_CHECK(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MULTI_MAX_PROTOCOLS, isMultiProtocolSelectable);
+ }
+ if (checkIncDec_Ret) {
+ g_model.moduleData[moduleIdx].setMultiProtocol(multiRfProto);
+ g_model.moduleData[moduleIdx].subType = 0;
+ resetMultiProtocolsOptions(moduleIdx);
+ storageDirty(EE_MODEL);
+ }
+ }
+ }
+ break;
+
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_SUBTYPE:
#endif
@@ -1022,6 +1061,21 @@ void menuModelSetup(event_t event)
break;
#endif
+#if defined(AFHDS3)
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS_PROTOCOL:
+ lcdDrawTextAlignedLeft(y, TR_PROTO);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].subType, attr);
+ if (attr && s_editMode > 0 && menuHorizontalPosition == 0) {
+ CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].subType, AFHDS_SUBTYPE_FIRST, AFHDS_SUBTYPE_LAST);
+ }
+ break;
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE:
+ lcdDrawText(INDENT_WIDTH, y, TR_TELEMETRY_TYPE);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y,
+ g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry ? STR_AFHDS3_ONE_TO_ONE_TELEMETRY : TR_AFHDS3_ONE_TO_MANY);
+ break;
+#endif
+
#if defined(PCBTARANIS)
case ITEM_MODEL_SETUP_TRAINER_LABEL:
lcdDrawTextAlignedLeft(y, STR_TRAINER);
@@ -1077,7 +1131,7 @@ void menuModelSetup(event_t event)
for (uint8_t i=0; i0) {
+ if (attr && s_editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
CHECK_INCDEC_MODELVAR(event, moduleData.ppm.frameLength, -33, 35);
@@ -1286,19 +1339,17 @@ void menuModelSetup(event_t event)
}
}
else {
+ lcdDrawText(INDENT_WIDTH, y, STR_RECEIVER);
horzpos_t l_posHorz = menuHorizontalPosition;
- coord_t xOffsetBind = MODEL_SETUP_BIND_OFS;
- if (!isModuleRxNumAvailable(moduleIdx)) {
- xOffsetBind = 0;
- lcdDrawText(INDENT_WIDTH, y, STR_RECEIVER);
- if (attr) l_posHorz += 1;
+ coord_t bindButtonPos = MODEL_SETUP_2ND_COLUMN;
+ if (isModuleRxNumAvailable(moduleIdx)) {
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2);
+ bindButtonPos = lcdNextPos + 2;
}
- else {
- lcdDrawText(INDENT_WIDTH, y, STR_RECEIVER_NUM);
+ else if (attr) {
+ l_posHorz += 1;
}
if (isModuleBindRangeAvailable(moduleIdx)) {
- if (xOffsetBind)
- lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2);
if (attr && l_posHorz == 0) {
if (s_editMode > 0) {
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], getMaxRxNum(moduleIdx));
@@ -1315,8 +1366,10 @@ void menuModelSetup(event_t event)
}
}
}
- lcdDrawText(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, l_posHorz==1 ? attr : 0);
- lcdDrawText(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0);
+ lcdDrawText(bindButtonPos, y, STR_MODULE_BIND, l_posHorz == 1 ? attr : 0);
+ if (isModuleRangeAvailable(moduleIdx)) {
+ lcdDrawText(lcdNextPos + 2, y, STR_MODULE_RANGE, l_posHorz == 2 ? attr : 0);
+ }
uint8_t newFlag = 0;
#if defined(MULTIMODULE)
if (getMultiBindStatus(moduleIdx) == MULTI_BIND_FINISHED) {
@@ -1328,7 +1381,7 @@ void menuModelSetup(event_t event)
if (attr && l_posHorz > 0) {
if (s_editMode > 0) {
if (l_posHorz == 1) {
- if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx)) {
+ if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx) || isModuleAFHDS3(moduleIdx)) {
#if defined(PCBXLITE)
if (EVT_KEY_MASK(event) == KEY_ENTER) {
#elif defined(NAVIGATION_9X)
@@ -1337,6 +1390,12 @@ void menuModelSetup(event_t event)
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
#endif
killEvents(event);
+#if defined(AFHDS3)
+ if (isModuleAFHDS3(moduleIdx)) {
+ startBindMenuAfhds3(moduleIdx);
+ continue;
+ }
+#endif
startBindMenu(moduleIdx);
continue;
}
@@ -1359,7 +1418,7 @@ void menuModelSetup(event_t event)
}
}
#else
- if (attr && l_posHorz>0 && s_editMode>0) {
+ if (attr && l_posHorz > 0 && s_editMode > 0) {
if (l_posHorz == 1)
newFlag = MODULE_MODE_BIND;
else if (l_posHorz == 2)
@@ -1391,7 +1450,8 @@ void menuModelSetup(event_t event)
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE:
#endif
- case ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE: {
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE:
+ {
ModuleData &moduleData = g_model.moduleData[moduleIdx];
lcdDrawTextAlignedLeft(y, STR_FAILSAFE);
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VFAILSAFE, moduleData.failsafeMode, menuHorizontalPosition == 0 ? attr : 0);
@@ -1457,8 +1517,19 @@ void menuModelSetup(event_t event)
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
int optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
+ MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
- if (multi_proto < MODULE_SUBTYPE_MULTI_LAST) {
+
+ if (status.isValid()) {
+ MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
+ lcdDrawText(INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
+ if (attr && status.optionDisp == 2) {
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
+ lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
+ lcdDrawText(lcdLastRightPos, y, ")", LEFT);
+ }
+ }
+ else {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
if (pdef->optionsstr) {
lcdDrawText(INDENT_WIDTH, y, pdef->optionsstr);
@@ -1469,24 +1540,36 @@ void menuModelSetup(event_t event)
}
}
}
+
+ int8_t min, max;
+ getMultiOptionValues(multi_proto, min, max);
+
+ if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
+ }
+ else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) {
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
+ }
+ else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
+ optionValue = optionValue & 0x01;
+ editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event);
+ }
else {
- MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
- lcdDrawText(INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
- if (attr && status.optionDisp == 2) {
- lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
- lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
- lcdDrawText(lcdLastRightPos, y, ")", LEFT);
- }
+ if (min == 0 && max == 1)
+ editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event);
+ else
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
}
-
- if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A)
- optionValue = 50 + 5 * optionValue;
-
- lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
if (attr) {
- int8_t min, max;
- getMultiOptionValues(multi_proto, min, max);
- CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, min, max);
+ CHECK_INCDEC_MODELVAR(event, optionValue, min, max);
+ if (checkIncDec_Ret) {
+ if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
+ g_model.moduleData[moduleIdx].multi.optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0xFE) + optionValue;
+ }
+ else {
+ g_model.moduleData[moduleIdx].multi.optionValue = optionValue;
+ }
+ }
}
}
#endif
@@ -1573,9 +1656,17 @@ void menuModelSetup(event_t event)
}
#if defined(MULTIMODULE)
else if (isModuleMultimodule(moduleIdx)) {
- module.multi.lowPowerMode = editCheckBox(module.multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_LOWPOWER, attr, event);
+ module.multi.lowPowerMode = editCheckBox(module.multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, IS_RX_MULTI(moduleIdx) ? STR_MULTI_LNA_DISABLE : STR_MULTI_LOWPOWER, attr, event);
}
#endif
+#if defined(AFHDS3)
+ else if (isModuleAFHDS3(EXTERNAL_MODULE)) {
+ lcdDrawText(INDENT_WIDTH, y, STR_RFPOWER);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, g_model.moduleData[EXTERNAL_MODULE].afhds3.runPower, LEFT | attr);
+ if (attr)
+ CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].afhds3.runPower, afhds3::RUN_POWER::RUN_POWER_FIRST, afhds3::RUN_POWER::RUN_POWER_LAST);
+ }
+#endif
}
break;
@@ -1585,10 +1676,22 @@ void menuModelSetup(event_t event)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND:
#endif
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND:
- if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2)
- g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_DSM_AUTODTECT, attr, event);
- else
- g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_AUTOBIND, attr, event);
+ if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) {
+ int8_t value = (g_model.moduleData[moduleIdx].multi.optionValue & 0x02) >> 1;
+ lcdDrawText(INDENT_WIDTH, y, STR_MULTI_SERVOFREQ);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, value ? 11 : 22, attr);
+ lcdDrawText(lcdNextPos, y, "ms", attr);
+ if (attr) {
+ CHECK_INCDEC_MODELVAR(event, value, 0, 1);
+ if (checkIncDec_Ret) {
+ g_model.moduleData[moduleIdx].multi.optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0xFD) + (value << 1);
+ }
+ }
+ }
+ else {
+ g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y,
+ STR_MULTI_AUTOBIND, attr, event);
+ }
break;
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_TELEM:
@@ -1602,7 +1705,25 @@ void menuModelSetup(event_t event)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING:
g_model.moduleData[moduleIdx].multi.disableMapping = editCheckBox(g_model.moduleData[moduleIdx].multi.disableMapping, MODEL_SETUP_2ND_COLUMN, y, INDENT TR_DISABLE_CH_MAP, attr, event);
break;
+#endif
+#if defined(AFHDS3)
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ:
+ lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_RX_FREQ);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.moduleData[EXTERNAL_MODULE].afhds3.rxFreq(), attr | LEFT);
+ if (attr) {
+ uint16_t rxFreq = g_model.moduleData[EXTERNAL_MODULE].afhds3.rxFreq();
+ CHECK_INCDEC_MODELVAR(event, rxFreq, MIN_FREQ, MAX_FREQ);
+ g_model.moduleData[EXTERNAL_MODULE].afhds3.setRxFreq(rxFreq);
+ }
+ break;
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER:
+ lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_ACTUAL_POWER);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, actualAfhdsRunPower(EXTERNAL_MODULE), LEFT);
+ break;
+#endif
+
+#if defined(MULTIMODULE)
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS:
#endif
@@ -1610,7 +1731,7 @@ void menuModelSetup(event_t event)
lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS);
char statusText[64];
- getMultiModuleStatus(moduleIdx).getStatusString(statusText);
+ getModuleStatusString(moduleIdx, statusText);
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
break;
}
@@ -1619,9 +1740,26 @@ void menuModelSetup(event_t event)
#endif
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: {
lcdDrawTextAlignedLeft(y, STR_MODULE_SYNC);
+ char statusText[64];
+ getModuleSyncStatusString(moduleIdx, statusText);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
+ break;
+ }
+#endif
+
+#if defined(AFHDS3)
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS: {
+ lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS);
char statusText[64];
- getMultiSyncStatus(moduleIdx).getRefreshString(statusText);
+ getModuleStatusString(moduleIdx, statusText);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
+ break;
+ }
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS: {
+ lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_POWER_SOURCE);
+ char statusText[64];
+ getModuleSyncStatusString(moduleIdx, statusText);
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
break;
}
diff --git a/radio/src/gui/128x64/model_special_functions.cpp b/radio/src/gui/128x64/model_special_functions.cpp
index bfcee26c3..2eaad8f2b 100644
--- a/radio/src/gui/128x64/model_special_functions.cpp
+++ b/radio/src/gui/128x64/model_special_functions.cpp
@@ -147,7 +147,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
#if defined(PCBTARANIS)
#if defined(PCBXLITE)
- // ENT LONG on xlite brings up switch type menu, so this menu is activated with SHIT + ENT LONG
+ // ENT LONG on xlite brings up switch type menu, so this menu is activated with SHIFT + ENT LONG
if (menuHorizontalPosition==0 && event==EVT_KEY_LONG(KEY_ENTER) && IS_SHIFT_PRESSED() && !READ_ONLY()) {
#else
if (menuHorizontalPosition<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) {
diff --git a/radio/src/gui/128x64/model_telemetry_sensor.cpp b/radio/src/gui/128x64/model_telemetry_sensor.cpp
index d8a63079e..33dcaf60c 100644
--- a/radio/src/gui/128x64/model_telemetry_sensor.cpp
+++ b/radio/src/gui/128x64/model_telemetry_sensor.cpp
@@ -24,7 +24,7 @@ enum SensorFields {
SENSOR_FIELD_NAME,
SENSOR_FIELD_TYPE,
SENSOR_FIELD_ID,
- SENSOR_FIELD_FORMULA=SENSOR_FIELD_ID,
+ SENSOR_FIELD_FORMULA = SENSOR_FIELD_ID,
SENSOR_FILED_RECEIVER_NAME,
SENSOR_FIELD_UNIT,
SENSOR_FIELD_PRECISION,
@@ -104,7 +104,7 @@ void menuModelSensor(event_t event)
if (sensor->type == TELEM_TYPE_CUSTOM) {
lcdDrawTextAlignedLeft(y, STR_ID);
lcdDrawHexNumber(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(menuHorizontalPosition==0 ? attr : 0));
- lcdDrawHexChar(SENSOR_3RD_COLUMN, y, (sensor->instance & 0x1F) + 1, LEFT|(menuHorizontalPosition==1 ? attr : 0));
+ lcdDrawNumber(SENSOR_3RD_COLUMN, y, (sensor->instance & 0x1F) + 1, LEFT|(menuHorizontalPosition==1 ? attr : 0));
if (attr && s_editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
diff --git a/radio/src/gui/128x64/radio_calibration.cpp b/radio/src/gui/128x64/radio_calibration.cpp
index a8004c7a2..3e1a30d20 100644
--- a/radio/src/gui/128x64/radio_calibration.cpp
+++ b/radio/src/gui/128x64/radio_calibration.cpp
@@ -179,7 +179,7 @@ void menuFirstCalib(event_t event)
chainMenu(menuMainView);
}
else {
- lcdDrawTextAlignedCenter(0*FH, TR_MENUCALIBRATION);
+ lcdDrawText(LCD_W / 2, 0, STR_MENUCALIBRATION, CENTERED);
lcdInvertLine(0);
menuCommonCalib(event);
}
diff --git a/radio/src/gui/128x64/radio_diagkeys.cpp b/radio/src/gui/128x64/radio_diagkeys.cpp
index a5840754a..a3d058c3e 100644
--- a/radio/src/gui/128x64/radio_diagkeys.cpp
+++ b/radio/src/gui/128x64/radio_diagkeys.cpp
@@ -76,6 +76,6 @@ void menuRadioDiagKeys(event_t event)
#if defined(ROTARY_ENCODER_NAVIGATION)
coord_t y = MENU_HEADER_HEIGHT + 1 + FH*KEY_COUNT;
lcdDrawText(0, y, STR_ROTARY_ENCODER);
- lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue, RIGHT);
+ lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue / ROTARY_ENCODER_GRANULARITY, RIGHT);
#endif
}
diff --git a/radio/src/gui/128x64/view_channels.cpp b/radio/src/gui/128x64/view_channels.cpp
index f13b871ce..ccd8fc9b3 100644
--- a/radio/src/gui/128x64/view_channels.cpp
+++ b/radio/src/gui/128x64/view_channels.cpp
@@ -20,7 +20,30 @@
#include "opentx.h"
-void menuChannelsView(event_t event)
+constexpr coord_t CHANNEL_NAME_OFFSET = 1;
+constexpr coord_t CHANNEL_VALUE_OFFSET = CHANNEL_NAME_OFFSET + 42;
+constexpr coord_t CHANNEL_GAUGE_OFFSET = CHANNEL_VALUE_OFFSET;
+constexpr coord_t CHANNEL_BAR_WIDTH = 70;
+constexpr coord_t CHANNEL_PROPERTIES_OFFSET = CHANNEL_GAUGE_OFFSET + CHANNEL_BAR_WIDTH + 2;
+
+#if defined(NAVIGATION_X7)
+#define EVT_KEY_PREVIOUS_VIEW EVT_KEY_LONG(KEY_PAGE)
+#define EVT_KEY_NEXT_VIEW EVT_KEY_BREAK(KEY_PAGE)
+#define EVT_KEY_NEXT_PAGE EVT_ROTARY_RIGHT
+#define EVT_KEY_PREVIOUS_PAGE EVT_ROTARY_LEFT
+#elif defined(NAVIGATION_XLITE)
+#define EVT_KEY_PREVIOUS_VIEW EVT_KEY_BREAK(KEY_UP)
+#define EVT_KEY_NEXT_VIEW EVT_KEY_BREAK(KEY_DOWN)
+#define EVT_KEY_NEXT_PAGE EVT_KEY_BREAK(KEY_RIGHT)
+#define EVT_KEY_PREVIOUS_PAGE EVT_KEY_BREAK(KEY_LEFT)
+#else
+#define EVT_KEY_PREVIOUS_VIEW EVT_KEY_BREAK(KEY_UP)
+#define EVT_KEY_NEXT_VIEW EVT_KEY_BREAK(KEY_DOWN)
+#define EVT_KEY_NEXT_PAGE EVT_KEY_BREAK(KEY_RIGHT)
+#define EVT_KEY_PREVIOUS_PAGE EVT_KEY_BREAK(KEY_LEFT)
+#endif
+
+void menuChannelsViewCommon(event_t event)
{
bool newLongNames = false;
@@ -31,81 +54,81 @@ void menuChannelsView(event_t event)
memclear(&reusableBuffer.viewChannels, sizeof(reusableBuffer.viewChannels));
break;
- case EVT_KEY_BREAK(KEY_EXIT):
- popMenu();
- break;
-
- case EVT_KEY_FIRST(KEY_RIGHT):
- case EVT_KEY_FIRST(KEY_LEFT):
- reusableBuffer.viewChannels.secondPage = !reusableBuffer.viewChannels.secondPage;
- break;
-
case EVT_KEY_FIRST(KEY_ENTER):
reusableBuffer.viewChannels.mixersView = !reusableBuffer.viewChannels.mixersView;
break;
}
- if (reusableBuffer.viewChannels.secondPage)
- ch = 16;
- else
- ch = 0;
-
- if (reusableBuffer.viewChannels.mixersView) {
- lcdDrawTextAlignedCenter(0, TR_MIXERS_MONITOR);
- }
- else {
- lcdDrawTextAlignedCenter(0, TR_CHANNELS_MONITOR);
- }
+ ch = 8 * (g_eeGeneral.view / ALTERNATE_VIEW);
+ // Screen title
+ lcdDrawText(LCD_W / 2, 0, reusableBuffer.viewChannels.mixersView ? STR_MIXERS_MONITOR : STR_CHANNELS_MONITOR, CENTERED);
lcdInvertLine(0);
- // Column separator
- lcdDrawSolidVerticalLine(LCD_W/2, FH, LCD_H-FH);
+ int16_t limits = 512 * 2;
- for (uint8_t col=0; col<2; col++) {
+ // Channels
+ for (uint8_t line = 0; line < 8; line++) {
+ LimitData * ld = limitAddress(ch);
+ const uint8_t y = 9 + line * 7;
+ const int32_t val = reusableBuffer.viewChannels.mixersView ? ex_chans[ch] : channelOutputs[ch];
+ const uint8_t lenLabel = ZLEN(g_model.limitData[ch].name);
- uint8_t x = col*LCD_W/2+1;
+ // Channel name if present, number if not
+ if (lenLabel > 0) {
+ if (lenLabel > 4)
+ reusableBuffer.viewChannels.longNames = true;
+ lcdDrawSizedText(CHANNEL_NAME_OFFSET, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE);
+ }
+ else {
+ putsChn(CHANNEL_NAME_OFFSET, y, ch + 1, SMLSIZE);
+ }
- // Channels
- for (uint8_t line=0; line<8; line++) {
- uint8_t y = 9+line*7;
- int32_t val = (reusableBuffer.viewChannels.mixersView) ? ex_chans[ch] : channelOutputs[ch];
- uint8_t ofs = (col ? 0 : 1);
-
- // Channel name if present, number if not
- uint8_t lenLabel = ZLEN(g_model.limitData[ch].name);
- if (lenLabel > 4) {
- newLongNames = reusableBuffer.viewChannels.longNames = true;
- }
-
- if (lenLabel > 0)
- lcdDrawSizedText(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE);
- else
- putsChn(x+1-ofs, y, ch+1, SMLSIZE);
-
- // Value
+ // Value
#if defined(PPM_UNIT_US)
- uint8_t wbar = (reusableBuffer.viewChannels.longNames ? 54 : 64);
- lcdDrawNumber(x+LCD_W/2-3-wbar-ofs, y+1, PPM_CH_CENTER(ch)+val/2, TINSIZE|RIGHT);
+ lcdDrawNumber(CHANNEL_VALUE_OFFSET, y + 1, PPM_CH_CENTER(ch) + val / 2, TINSIZE | RIGHT);
#elif defined(PPM_UNIT_PERCENT_PREC1)
- uint8_t wbar = (reusableBuffer.viewChannels.longNames ? 48 : 58);
- lcdDrawNumber(x+LCD_W/2-3-wbar-ofs, y+1, calcRESXto1000(val), PREC1|TINSIZE|RIGHT);
+ lcdDrawNumber(CHANNEL_VALUE_OFFSET, y + 1, calcRESXto1000(val), PREC1 | TINSIZE | RIGHT);
#else
- uint8_t wbar = (reusableBuffer.viewChannels.longNames ? 54 : 64);
- lcdDrawNumber(x+LCD_W/2-3-wbar-ofs, y+1, calcRESXto1000(val)/10, TINSIZE|RIGHT);
+ lcdDrawNumber(CHANNEL_VALUE_OFFSET, y + 1, calcRESXto1000(val) / 10, TINSIZE | RIGHT);
#endif
- // Gauge
-// uint16_t lim = (g_model.extendedLimits ? (512 * (long)LIMIT_EXT_PERCENT / 100) : 512) * 2;
-//#ifdef MIXERS_MONITOR
-// if (mixersView)
-// lim = 512 * 2 * 2;
-//#endif
- // TODO ? drawGauge(x+LCD_W/2-3-wbar-ofs, y, wbar, 6, val, lim);
+ // Gauge
+ drawGauge(CHANNEL_GAUGE_OFFSET, y, CHANNEL_BAR_WIDTH, 6, val, limits);
- ch++;
+ if (!reusableBuffer.viewChannels.mixersView) {
+ // Properties
+#if defined(OVERRIDE_CHANNEL_FUNCTION)
+ if (safetyCh[ch] != OVERRIDE_CHANNEL_UNDEFINED)
+ lcdDrawText(CHANNEL_PROPERTIES_OFFSET, y, "OVR", TINSIZE);
+ else
+#endif
+ if (ld && ld->revert) {
+ lcdDrawText(CHANNEL_PROPERTIES_OFFSET, y, "INV", TINSIZE);
+ }
}
+
+ ++ch;
}
reusableBuffer.viewChannels.longNames = newLongNames;
}
+
+void menuChannelsView(event_t event)
+{
+ switch (event) {
+ case EVT_KEY_BREAK(KEY_EXIT):
+ popMenu();
+ break;
+
+ case EVT_KEY_NEXT_PAGE:
+ g_eeGeneral.view = (g_eeGeneral.view + (4 * ALTERNATE_VIEW) + ALTERNATE_VIEW) % (4 * ALTERNATE_VIEW);
+ break;
+
+ case EVT_KEY_PREVIOUS_PAGE:
+ g_eeGeneral.view = (g_eeGeneral.view + (4 * ALTERNATE_VIEW) - ALTERNATE_VIEW) % (4 * ALTERNATE_VIEW);
+ break;
+ }
+
+ menuChannelsViewCommon(event);
+}
diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp
index 308ba4290..a6f77528b 100644
--- a/radio/src/gui/128x64/view_main.cpp
+++ b/radio/src/gui/128x64/view_main.cpp
@@ -56,7 +56,7 @@ void drawExternalAntennaAndRSSI()
{
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
if (isModuleXJT(INTERNAL_MODULE) && isExternalAntennaEnabled()) {
- lcdDrawText(VBATT_X-1, VBATT_Y+8, "E", TINSIZE);
+ lcdDrawText(VBATT_X - 1, VBATT_Y + 8, "E", TINSIZE);
}
#endif
@@ -75,10 +75,10 @@ void drawExternalAntennaAndRSSI()
void drawPotsBars()
{
// Optimization by Mike Blandford
- for (uint8_t x=LCD_W/2 - (NUM_POTS+NUM_SLIDERS-1) * 5 / 2, i=NUM_STICKS; i TRIM_MAX) {
exttrim = true;
}
- if (val < -(TRIM_LEN+1)*4) {
- val = -(TRIM_LEN+1);
+ if (val < -(TRIM_LEN + 1) * 4) {
+ val = -(TRIM_LEN + 1);
}
- else if (val > (TRIM_LEN+1)*4) {
- val = TRIM_LEN+1;
+ else if (val > (TRIM_LEN + 1) * 4) {
+ val = TRIM_LEN + 1;
}
else {
val /= 4;
@@ -129,65 +129,65 @@ void displayTrims(uint8_t phase)
if (vert[i]) {
ym = 31;
- lcdDrawSolidVerticalLine(xm, ym-TRIM_LEN, TRIM_LEN*2);
- if (i!=2 || !g_model.thrTrim) {
- lcdDrawSolidVerticalLine(xm-1, ym-1, 3);
- lcdDrawSolidVerticalLine(xm+1, ym-1, 3);
+ lcdDrawSolidVerticalLine(xm, ym - TRIM_LEN, TRIM_LEN * 2);
+ if (i != 2 || !g_model.thrTrim) {
+ lcdDrawSolidVerticalLine(xm - 1, ym - 1, 3);
+ lcdDrawSolidVerticalLine(xm + 1, ym - 1, 3);
}
ym -= val;
- lcdDrawFilledRect(xm-3, ym-3, 7, 7, SOLID, att|ERASE);
+ lcdDrawFilledRect(xm - 3, ym - 3, 7, 7, SOLID, att | ERASE);
if (dir >= 0) {
- lcdDrawSolidHorizontalLine(xm-1, ym-1, 3);
+ lcdDrawSolidHorizontalLine(xm - 1, ym - 1, 3);
}
if (dir <= 0) {
- lcdDrawSolidHorizontalLine(xm-1, ym+1, 3);
+ lcdDrawSolidHorizontalLine(xm - 1, ym + 1, 3);
}
if (exttrim) {
- lcdDrawSolidHorizontalLine(xm-1, ym, 3);
+ lcdDrawSolidHorizontalLine(xm - 1, ym, 3);
}
if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && dir != 0) {
- if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<0 ? 12 : 40, xm-2, -abs(dir), TINSIZE|VERTICAL);
+ if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1 << i)))) {
+ lcdDrawNumber(dir > 0 ? 12 : 40, xm - 2, -abs(dir), TINSIZE | VERTICAL);
}
}
}
else {
ym = 60;
- lcdDrawSolidHorizontalLine(xm-TRIM_LEN, ym, TRIM_LEN*2);
- lcdDrawSolidHorizontalLine(xm-1, ym-1, 3);
- lcdDrawSolidHorizontalLine(xm-1, ym+1, 3);
+ lcdDrawSolidHorizontalLine(xm - TRIM_LEN, ym, TRIM_LEN * 2);
+ lcdDrawSolidHorizontalLine(xm - 1, ym - 1, 3);
+ lcdDrawSolidHorizontalLine(xm - 1, ym + 1, 3);
xm += val;
- lcdDrawFilledRect(xm-3, ym-3, 7, 7, SOLID, att|ERASE);
+ lcdDrawFilledRect(xm - 3, ym - 3, 7, 7, SOLID, att | ERASE);
if (dir >= 0) {
- lcdDrawSolidVerticalLine(xm+1, ym-1, 3);
+ lcdDrawSolidVerticalLine(xm + 1, ym - 1, 3);
}
if (dir <= 0) {
- lcdDrawSolidVerticalLine(xm-1, ym-1, 3);
+ lcdDrawSolidVerticalLine(xm - 1, ym - 1, 3);
}
if (exttrim) {
- lcdDrawSolidVerticalLine(xm, ym-1, 3);
+ lcdDrawSolidVerticalLine(xm, ym - 1, 3);
}
if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && dir != 0) {
- if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<0 ? TRIM_LH_POS : TRIM_LH_NEG) : (dir>0 ? TRIM_RH_POS : TRIM_RH_NEG)), ym-2, -abs(dir), TINSIZE);
+ if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1 << i)))) {
+ lcdDrawNumber((stickIndex == 0 ? (dir > 0 ? TRIM_LH_POS : TRIM_LH_NEG) : (dir > 0 ? TRIM_RH_POS : TRIM_RH_NEG)), ym - 2, -abs(dir), TINSIZE);
}
}
}
- lcdDrawSquare(xm-3, ym-3, 7, att);
+ lcdDrawSquare(xm - 3, ym - 3, 7, att);
}
}
void displayBattVoltage()
{
#if defined(BATTGRAPH)
- putsVBat(VBATT_X-8, VBATT_Y+1, RIGHT);
- lcdDrawSolidFilledRect(VBATT_X-25, VBATT_Y+9, 21, 5);
- lcdDrawSolidVerticalLine(VBATT_X-4, VBATT_Y+10, 3);
+ putsVBat(VBATT_X - 8, VBATT_Y + 1, RIGHT);
+ lcdDrawSolidFilledRect(VBATT_X - 25, VBATT_Y + 9, 21, 5);
+ lcdDrawSolidVerticalLine(VBATT_X - 4, VBATT_Y + 10, 3);
uint8_t count = GET_TXBATT_BARS(20);
- for (uint8_t i=0; i= 0) {
lcdDrawSolidHorizontalLine(x, y, width);
- lcdDrawSolidHorizontalLine(x, y+2, width);
+ lcdDrawSolidHorizontalLine(x, y + 2, width);
y += 4;
if (val > 0) {
lcdDrawSolidHorizontalLine(x, y, width);
- lcdDrawSolidHorizontalLine(x, y+2, width);
+ lcdDrawSolidHorizontalLine(x, y + 2, width);
y += 4;
}
}
- lcdDrawChar(width==5 ? x+1 : x, y, 'A'+index, SMLSIZE);
+ lcdDrawChar(width == 5 ? x + 1 : x, y, 'A' + index, SMLSIZE);
y += 7;
if (val <= 0) {
lcdDrawSolidHorizontalLine(x, y, width);
- lcdDrawSolidHorizontalLine(x, y+2, width);
+ lcdDrawSolidHorizontalLine(x, y + 2, width);
if (val < 0) {
- lcdDrawSolidHorizontalLine(x, y+4, width);
- lcdDrawSolidHorizontalLine(x, y+6, width);
+ lcdDrawSolidHorizontalLine(x, y + 4, width);
+ lcdDrawSolidHorizontalLine(x, y + 6, width);
}
}
}
@@ -320,25 +320,20 @@ void menuMainView(event_t event)
killEvents(KEY_DOWN);
break;
- /* TODO if timer2 is OFF, it's possible to use this timer2 as in er9x...
- case EVT_KEY_BREAK(KEY_MENU):
- if (view_base == VIEW_TIMER2) {
- Timer2_running = !Timer2_running;
- AUDIO_KEY_PRESS();
- }
- break;
- */
-
+ /* TODO if timer2 is OFF, it's possible to use this timer2 as in er9x...
+ case EVT_KEY_BREAK(KEY_MENU):
+ if (view_base == VIEW_TIMER2) {
+ Timer2_running = !Timer2_running;
+ AUDIO_KEY_PRESS();
+ }
+ break;
+ */
case EVT_KEY_NEXT_PAGE:
case EVT_KEY_PREVIOUS_PAGE:
- if (view_base <= VIEW_INPUTS) {
- if (view_base == VIEW_INPUTS)
- g_eeGeneral.view ^= ALTERNATE_VIEW;
- else
- g_eeGeneral.view = (g_eeGeneral.view + (4*ALTERNATE_VIEW) + ((event==EVT_KEY_PREVIOUS_PAGE) ? -ALTERNATE_VIEW : ALTERNATE_VIEW)) % (4*ALTERNATE_VIEW);
- storageDirty(EE_GENERAL);
- AUDIO_KEY_PRESS();
- }
+ if (view_base == VIEW_INPUTS)
+ g_eeGeneral.view ^= ALTERNATE_VIEW;
+ else
+ g_eeGeneral.view = (g_eeGeneral.view + (4*ALTERNATE_VIEW) + ((event==EVT_KEY_PREVIOUS_PAGE) ? -ALTERNATE_VIEW : ALTERNATE_VIEW)) % (4*ALTERNATE_VIEW);
break;
case EVT_KEY_CONTEXT_MENU:
@@ -369,7 +364,7 @@ void menuMainView(event_t event)
break;
case EVT_KEY_GENERAL_MENU:
- pushMenu(menuRadioSetup);
+ pushMenu(menuTabGeneral[0]);
killEvents(event);
break;
#endif
@@ -379,12 +374,13 @@ void menuMainView(event_t event)
case EVT_KEY_PREVIOUS_VIEW:
case EVT_KEY_NEXT_VIEW:
// TODO try to split those 2 cases on 9X
- g_eeGeneral.view = (event == EVT_KEY_PREVIOUS_VIEW ? (view_base == VIEW_COUNT-1 ? 0 : view_base+1) : (view_base == 0 ? VIEW_COUNT-1 : view_base-1));
+ g_eeGeneral.view = (event == EVT_KEY_PREVIOUS_VIEW ? (view_base == VIEW_COUNT - 1 ? 0 : view_base + 1) : (view_base == 0 ? VIEW_COUNT - 1 : view_base -
+ 1));
storageDirty(EE_GENERAL);
break;
#else
case EVT_KEY_NEXT_VIEW:
- g_eeGeneral.view = (view_base == 0 ? VIEW_COUNT-1 : view_base-1);
+ g_eeGeneral.view = (view_base == 0 ? VIEW_COUNT - 1 : view_base - 1);
storageDirty(EE_GENERAL);
break;
#endif
@@ -397,7 +393,7 @@ void menuMainView(event_t event)
#endif
case EVT_KEY_TELEMETRY:
- chainMenu(menuViewTelemetryFrsky);
+ chainMenu(menuViewTelemetry);
killEvents(event);
break;
@@ -410,53 +406,34 @@ void menuMainView(event_t event)
break;
}
- {
- // Flight Mode Name
- uint8_t mode = mixerCurrentFlightMode;
- lcdDrawSizedText(PHASE_X, PHASE_Y, g_model.flightModeData[mode].name, sizeof(g_model.flightModeData[mode].name), ZCHAR|PHASE_FLAGS);
+ switch (view_base) {
+ case VIEW_CHAN_MONITOR:
+ menuChannelsViewCommon(event);
+ break;
- // Model Name
- putsModelName(MODELNAME_X, MODELNAME_Y, g_model.header.name, g_eeGeneral.currModel, BIGSIZE);
+ case VIEW_OUTPUTS_VALUES:
+ case VIEW_OUTPUTS_BARS:
+ // scroll bar
+ lcdDrawHorizontalLine(38, 34, 54, DOTTED);
+ lcdDrawSolidHorizontalLine(38 + (g_eeGeneral.view / ALTERNATE_VIEW) * 13, 34, 13, SOLID);
+ for (uint8_t i=0; i<8; i++) {
+ uint8_t x0, y0;
+ uint8_t chan = 8 * (g_eeGeneral.view / ALTERNATE_VIEW) + i;
+ int16_t val = channelOutputs[chan];
- // Main Voltage (or alarm if any)
- displayVoltageOrAlarm();
-
- // Timer 1
- drawTimerWithMode(125, 2*FH, 0, RIGHT | DBLSIZE);
-
- // Trims sliders
- displayTrims(mode);
-
- // RSSI gauge / external antenna
- drawExternalAntennaAndRSSI();
- }
-
- if (view_base < VIEW_INPUTS) {
- // scroll bar
- lcdDrawHorizontalLine(38, 34, 54, DOTTED);
- lcdDrawSolidHorizontalLine(38 + (g_eeGeneral.view / ALTERNATE_VIEW) * 13, 34, 13, SOLID);
-
- for (uint8_t i=0; i<8; i++) {
- uint8_t x0,y0;
- uint8_t chan = 8*(g_eeGeneral.view / ALTERNATE_VIEW) + i;
-
- int16_t val = channelOutputs[chan];
-
- switch (view_base) {
- case VIEW_OUTPUTS_VALUES:
- x0 = (i%4*9+3)*FW/2;
- y0 = i/4*FH+40;
+ if (view_base == VIEW_OUTPUTS_VALUES) {
+ x0 = (i % 4 * 9 + 3) * FW / 2;
+ y0 = i / 4 * FH + 40;
#if defined(PPM_UNIT_US)
- lcdDrawNumber(x0+4*FW , y0, PPM_CH_CENTER(chan)+val/2, RIGHT);
+ lcdDrawNumber(x0 + 4 * FW, y0, PPM_CH_CENTER(chan) + val / 2, RIGHT);
#elif defined(PPM_UNIT_PERCENT_PREC1)
- lcdDrawNumber(x0+4*FW , y0, calcRESXto1000(val), RIGHT|PREC1);
+ lcdDrawNumber(x0 + 4 * FW, y0, calcRESXto1000(val), RIGHT | PREC1);
#else
lcdDrawNumber(x0+4*FW , y0, calcRESXto1000(val)/10, RIGHT); // G: Don't like the decimal part*
#endif
- break;
-
- case VIEW_OUTPUTS_BARS:
-#define WBAR2 (50/2)
+ }
+ else {
+ constexpr coord_t WBAR2 = (50/2);
x0 = i<4 ? LCD_W/4+2 : LCD_W*3/4-2;
y0 = 38+(i%4)*5;
@@ -473,99 +450,121 @@ void menuMainView(event_t event)
x0 -= len;
lcdDrawSolidHorizontalLine(x0, y0+1, len);
lcdDrawSolidHorizontalLine(x0, y0-1, len);
- break;
+ }
}
- }
- }
- else if (view_base == VIEW_INPUTS) {
- if (view == VIEW_INPUTS) {
- // Sticks + Pots
- doMainScreenGraphics();
+ break;
- // Switches
+ case VIEW_TIMER2:
+ drawTimerWithMode(87, 5 * FH, 1, RIGHT | DBLSIZE);
+ break;
+
+ case VIEW_INPUTS:
+ if (view == VIEW_INPUTS) {
+ // Sticks + Pots
+ doMainScreenGraphics();
+
+ // Switches
#if defined(PCBX9LITES)
- static const uint8_t x[NUM_SWITCHES-2] = {2*FW-2, 2*FW-2, 17*FW+1, 2*FW-2, 17*FW+1};
- static const uint8_t y[NUM_SWITCHES-2] = {4*FH+1, 5*FH+1, 5*FH+1, 6*FH+1, 6*FH+1};
- for (int i=0; i= switches/2) {
- x = 16*FW+1;
- y -= (switches/2)*FH;
+ uint8_t switches = min(NUM_SWITCHES, 6);
+ for (int i = 0; i < switches; ++i) {
+ if (SWITCH_EXISTS(i)) {
+ uint8_t x = 2 * FW - 2, y = 4 * FH + i * FH + 1;
+ if (i >= switches / 2) {
+ x = 16 * FW + 1;
+ y -= (switches / 2) * FH;
+ }
+ getvalue_t val = getValue(MIXSRC_FIRST_SWITCH + i);
+ getvalue_t sw = ((val < 0) ? 3 * i + 1 : ((val == 0) ? 3 * i + 2 : 3 * i + 3));
+ drawSwitch(x, y, sw, 0, false);
}
- getvalue_t val = getValue(MIXSRC_FIRST_SWITCH+i);
- getvalue_t sw = ((val < 0) ? 3*i+1 : ((val == 0) ? 3*i+2 : 3*i+3));
- drawSwitch(x, y, sw, 0, false);
}
- }
#else
- // The ID0 3-POS switch is merged with the TRN switch
- for (uint8_t i=SWSRC_THR; i<=SWSRC_TRN; i++) {
- int8_t sw = (i == SWSRC_TRN ? (switchState(SW_ID0) ? SWSRC_ID0 : (switchState(SW_ID1) ? SWSRC_ID1 : SWSRC_ID2)) : i);
- uint8_t x = 2*FW-2, y = i*FH+1;
- if (i >= SWSRC_AIL) {
- x = 17*FW-1;
- y -= 3*FH;
+ // The ID0 3-POS switch is merged with the TRN switch
+ for (uint8_t i=SWSRC_THR; i<=SWSRC_TRN; i++) {
+ int8_t sw = (i == SWSRC_TRN ? (switchState(SW_ID0) ? SWSRC_ID0 : (switchState(SW_ID1) ? SWSRC_ID1 : SWSRC_ID2)) : i);
+ uint8_t x = 2*FW-2, y = i*FH+1;
+ if (i >= SWSRC_AIL) {
+ x = 17*FW-1;
+ y -= 3*FH;
+ }
+ drawSwitch(x, y, sw, getSwitch(i) ? INVERS : 0, false);
}
- drawSwitch(x, y, sw, getSwitch(i) ? INVERS : 0, false);
- }
#endif
- }
- else {
- // Logical Switches
- uint8_t index = 0;
- uint8_t y = LCD_H-20;
- for (uint8_t line=0; line<2; line++) {
- for (uint8_t column=0; column0) ? x+w/2 : x+1+w/2-len;
+ for (coord_t i=h-2; i>0; i--) {
+ lcdDrawSolidHorizontalLine(x0, y+i, len);
+ }
+}
+
void title(const char * s)
{
lcdDrawText(0, 0, s, INVERS);
diff --git a/radio/src/gui/212x64/gui.h b/radio/src/gui/212x64/gui.h
index 3883a2e86..5968bd320 100644
--- a/radio/src/gui/212x64/gui.h
+++ b/radio/src/gui/212x64/gui.h
@@ -32,6 +32,7 @@
#define DEFAULT_SCROLLBAR_X (LCD_W-1)
#define NUM_BODY_LINES (LCD_LINES-1)
+#define TEXT_VIEWER_LINES NUM_BODY_LINES
#define MENU_HEADER_HEIGHT FH
#define MODEL_BITMAP_WIDTH 64
@@ -228,7 +229,6 @@ swsrc_t editSwitch(coord_t x, coord_t y, swsrc_t value, LcdFlags attr, event_t e
void gvarWeightItem(coord_t x, coord_t y, MixData * md, LcdFlags attr, event_t event);
-extern uint8_t s_curveChan;
void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags);
extern uint8_t editNameCursorPos;
@@ -246,6 +246,7 @@ extern uint8_t s_copyMode;
extern int8_t s_copySrcRow;
extern int8_t s_copyTgtOfs;
extern uint8_t s_currIdx;
+extern uint8_t s_currIdxSubMenu;
extern uint8_t s_maxLines;
extern uint8_t s_copySrcIdx;
extern uint8_t s_copySrcCh;
@@ -303,7 +304,7 @@ FlightModesType editFlightModes(coord_t x, coord_t y, event_t event, FlightModes
#endif
#define IS_MAIN_VIEW_DISPLAYED() menuHandlers[0] == menuMainView
-#define IS_TELEMETRY_VIEW_DISPLAYED() menuHandlers[0] == menuViewTelemetryFrsky
+#define IS_TELEMETRY_VIEW_DISPLAYED() menuHandlers[0] == menuViewTelemetry
#define IS_OTHER_VIEW_DISPLAYED() (menuHandlers[0] == menuMainViewChannelsMonitor || menuHandlers[0] == menuChannelsView)
#endif // _GUI_H_
diff --git a/radio/src/gui/212x64/lcd.cpp b/radio/src/gui/212x64/lcd.cpp
index c523643bb..f74c7bbeb 100644
--- a/radio/src/gui/212x64/lcd.cpp
+++ b/radio/src/gui/212x64/lcd.cpp
@@ -18,6 +18,7 @@
* GNU General Public License for more details.
*/
+#include
#include "opentx.h"
#include "timers.h"
@@ -148,9 +149,9 @@ void lcdPutPattern(coord_t x, coord_t y, const uint8_t * pattern, uint8_t width,
}
}
-#if !defined(BOOT)
void getCharPattern(PatternData * pattern, unsigned char c, LcdFlags flags)
{
+#if !defined(BOOT)
uint32_t fontsize = FONTSIZE(flags);
unsigned char c_remapped = 0;
@@ -211,6 +212,11 @@ void getCharPattern(PatternData * pattern, unsigned char c, LcdFlags flags)
pattern->height = 7;
pattern->data = (c < 0xC0) ? &font_5x7[(c-0x20)*5] : &font_5x7_extra[(c-0xC0)*5];
}
+#else
+ pattern->width = 5;
+ pattern->height = 7;
+ pattern->data = &font_5x7[(c-0x20) * 5];
+#endif
}
uint8_t getCharWidth(char c, LcdFlags flags)
@@ -219,7 +225,6 @@ uint8_t getCharWidth(char c, LcdFlags flags)
getCharPattern(&pattern, c, flags);
return getPatternWidth(&pattern);
}
-#endif
void lcdDrawChar(coord_t x, coord_t y, const unsigned char c, LcdFlags flags)
{
@@ -239,12 +244,15 @@ void lcdDrawChar(coord_t x, coord_t y, const unsigned char c)
lcdDrawChar(x, y, c, 0);
}
-#if !defined(BOOT)
uint8_t getTextWidth(const char * s, uint8_t len, LcdFlags flags)
{
uint8_t width = 0;
- for (int i=0; len==0 || i 0 ? 3 + crv.points : -3 - crv.points)) {
+ if (moveCurve(s_currIdxSubMenu, checkIncDec_Ret > 0 ? 3 + crv.points : -3 - crv.points)) {
if (newType == CURVE_TYPE_CUSTOM) {
resetCustomCurveX(points, 5 + crv.points);
}
@@ -131,14 +131,17 @@ void menuModelCurveOne(event_t event)
lcdDrawNumber(INDENT_WIDTH, 6*FH+1, 5+crv.points, LEFT|attr);
lcdDrawText(lcdLastRightPos, 6*FH+1, STR_PTS, attr);
if (attr) {
+#if defined(ROTARY_ENCODER_NAVIGATION)
+ rotencSpeed = ROTENC_LOWSPEED;
+#endif
int8_t count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts
if (checkIncDec_Ret) {
int8_t newPoints[MAX_POINTS_PER_CURVE];
newPoints[0] = points[0];
newPoints[4 + count] = points[4 + crv.points];
for (int i = 1; i < 4 + count; i++)
- newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(getCurveX(5 + count, i)), s_curveChan));
- if (moveCurve(s_curveChan, checkIncDec_Ret * (crv.type == CURVE_TYPE_CUSTOM ? 2 : 1))) {
+ newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(getCurveX(5 + count, i)), s_currIdxSubMenu));
+ if (moveCurve(s_currIdxSubMenu, checkIncDec_Ret * (crv.type == CURVE_TYPE_CUSTOM ? 2 : 1))) {
for (int i = 0; i < 5 + count; i++) {
points[i] = newPoints[i];
if (crv.type == CURVE_TYPE_CUSTOM && i != 0 && i != 4 + count)
diff --git a/radio/src/gui/212x64/model_failsafe.cpp b/radio/src/gui/212x64/model_failsafe.cpp
index 939e7927a..85ab66805 100644
--- a/radio/src/gui/212x64/model_failsafe.cpp
+++ b/radio/src/gui/212x64/model_failsafe.cpp
@@ -80,7 +80,7 @@ void menuModelFailsafe(event_t event)
}
}
- lcdDrawTextAlignedCenter(0, TR_FAILSAFESET);
+ lcdDrawText(LCD_W / 2, 0, STR_FAILSAFESET, CENTERED);
lcdInvertLine(0);
coord_t x = colW;
diff --git a/radio/src/gui/212x64/model_outputs.cpp b/radio/src/gui/212x64/model_outputs.cpp
index f3f776285..bc5f34d43 100644
--- a/radio/src/gui/212x64/model_outputs.cpp
+++ b/radio/src/gui/212x64/model_outputs.cpp
@@ -86,6 +86,9 @@ void onLimitsMenu(const char *result)
copyTrimsToOffset(ch);
storageDirty(EE_MODEL);
}
+ else if (result == STR_COPY_MIN_MAX_TO_OUTPUTS) {
+ copyMinMaxToOutputs(ch);
+ }
}
void menuModelLimits(event_t event)
@@ -142,6 +145,7 @@ void menuModelLimits(event_t event)
POPUP_MENU_ADD_ITEM(STR_RESET);
POPUP_MENU_ADD_ITEM(STR_COPY_TRIMS_TO_OFS);
POPUP_MENU_ADD_ITEM(STR_COPY_STICKS_TO_OFS);
+ POPUP_MENU_ADD_ITEM(STR_COPY_MIN_MAX_TO_OUTPUTS);
POPUP_MENU_START(onLimitsMenu);
}
@@ -208,7 +212,7 @@ void menuModelLimits(event_t event)
case ITEM_LIMITS_CURVE:
drawCurveName(LIMITS_CURVE_POS, y, ld->curve, attr);
if (attr && event==EVT_KEY_LONG(KEY_ENTER) && ld->curve>0) {
- s_curveChan = (ld->curve<0 ? -ld->curve-1 : ld->curve-1);
+ s_currIdxSubMenu = (ld->curve<0 ? -ld->curve-1 : ld->curve-1);
pushMenu(menuModelCurveOne);
}
if (active) {
diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp
index c7acddefb..36c7783bc 100644
--- a/radio/src/gui/212x64/model_setup.cpp
+++ b/radio/src/gui/212x64/model_setup.cpp
@@ -86,7 +86,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_INTERNAL_MODULE_LABEL,
ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE,
ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS,
- ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_BIND,
+ ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE,
ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM,
ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE,
ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_REGISTER_RANGE,
@@ -98,17 +98,27 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE,
#if defined (MULTIMODULE)
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_PROTOCOL,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS,
+#endif
+#if defined(AFHDS3)
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS,
#endif
ITEM_MODEL_SETUP_EXTERNAL_MODULE_CHANNELS,
- ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_BIND,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_MODEL_NUM,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_OPTIONS,
#if defined(MULTIMODULE)
ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING,
+#endif
+#if defined(AFHDS3)
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER,
#endif
ITEM_MODEL_SETUP_EXTERNAL_MODULE_POWER,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE,
@@ -130,8 +140,6 @@ enum MenuModelSetupItems {
#define MODEL_SETUP_2ND_COLUMN (LCD_W-17*FW-MENUS_SCROLLBAR_WIDTH-1)
#define MODEL_SETUP_3RD_COLUMN (MODEL_SETUP_2ND_COLUMN+6*FW)
-#define MODEL_SETUP_BIND_OFS 3*FW-2
-#define MODEL_SETUP_RANGE_OFS 7*FW
#define MODEL_SETUP_SET_FAILSAFE_OFS 10*FW-2
void copySelection(char * dst, const char * src, uint8_t size)
@@ -248,13 +256,8 @@ void editTimerCountdown(int timerIdx, coord_t y, LcdFlags attr, event_t event)
inline uint8_t EXTERNAL_MODULE_TYPE_ROW()
{
- if (isModuleXJT(EXTERNAL_MODULE) || isModuleR9MNonAccess(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE))
+ if (isModuleXJT(EXTERNAL_MODULE) || isModuleR9MNonAccess(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleAFHDS3(EXTERNAL_MODULE))
return 1;
-#if defined(MULTIMODULE)
- else if (isModuleMultimodule(EXTERNAL_MODULE)) {
- return 1 + MULTIMODULE_RFPROTO_COLUMNS(EXTERNAL_MODULE);
- }
-#endif
else
return 0;
}
@@ -310,6 +313,10 @@ void onBluetoothConnectMenu(const char * result)
#if defined(PXX2)
#include "common/stdlcd/model_setup_pxx2.cpp"
#endif
+#if defined(AFHDS3)
+#include "common/stdlcd/model_setup_afhds3.cpp"
+#endif
+
void menuModelSetup(event_t event)
{
@@ -353,10 +360,10 @@ void menuModelSetup(event_t event)
LABEL(InternalModule),
INTERNAL_MODULE_TYPE_ROWS,
MODULE_CHANNELS_ROWS(INTERNAL_MODULE),
- IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(isModuleFailsafeAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1)),
+ IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, MODULE_BIND_ROWS(INTERNAL_MODULE)), // RxNum, [Bind] and [Range] buttons
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // RxNum for ACCESS
IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), // Failsafe
- IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), // Range check and Register buttons
+ IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), // [Range] and [Register] buttons
IF_PXX2_MODULE(INTERNAL_MODULE, 0), // Module options
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // Receiver 1
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // Receiver 2
@@ -364,12 +371,15 @@ void menuModelSetup(event_t event)
LABEL(ExternalModule),
EXTERNAL_MODULE_TYPE_ROW(),
+ MULTIMODULE_TYPE_ROW(EXTERNAL_MODULE)
MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE)
+ AFHDS3_MODE_ROWS(EXTERNAL_MODULE)
MODULE_CHANNELS_ROWS(EXTERNAL_MODULE),
IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)),
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum for ACCESS
IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)),
MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE)
+ AFHDS3_MODULE_ROWS(EXTERNAL_MODULE)
MODULE_POWER_ROW(EXTERNAL_MODULE),
FAILSAFE_ROWS(EXTERNAL_MODULE),
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons
@@ -541,7 +551,7 @@ void menuModelSetup(event_t event)
break;
case ITEM_MODEL_SETUP_THROTTLE_REVERSED:
- ON_OFF_MENU_ITEM(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEREVERSE, attr, event ) ;
+ ON_OFF_MENU_ITEM(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEREVERSE, attr, event );
break;
case ITEM_MODEL_SETUP_THROTTLE_TRACE:
@@ -815,13 +825,9 @@ void menuModelSetup(event_t event)
lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0);
else if (isModuleR9MNonAccess(EXTERNAL_MODULE))
lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_R9M_REGION, g_model.moduleData[EXTERNAL_MODULE].subType, (menuHorizontalPosition==1 ? attr : 0));
-#if defined(MULTIMODULE)
- else if (isModuleMultimodule(EXTERNAL_MODULE)) {
- uint8_t multi_rfProto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol();
- // Do not use MODEL_SETUP_3RD_COLUMN here since some the protocol string are so long that we cannot afford the 2 spaces (+6) here
- lcdDrawMultiProtocolString(lcdNextPos + 3, y, EXTERNAL_MODULE, multi_rfProto, menuHorizontalPosition == 1 ? attr : 0);
- if (MULTIMODULE_HAS_SUBTYPE(EXTERNAL_MODULE))
- lcdDrawMultiSubProtocolString(lcdNextPos + 3, y, EXTERNAL_MODULE, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0);
+#if defined(AFHDS3)
+ else if (isModuleAFHDS3(EXTERNAL_MODULE)) {
+ lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_AFHDS3_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].subType, (menuHorizontalPosition==1 ? attr : 0));
}
#endif
if (attr && menuHorizontalPosition == 0) {
@@ -864,6 +870,11 @@ void menuModelSetup(event_t event)
MODULE_SUBTYPE_R9M_FCC, MODULE_SUBTYPE_R9M_LAST, EE_MODEL,
isR9MModeAvailable);
}
+#if defined(AFHDS3)
+ else if (isModuleAFHDS3(EXTERNAL_MODULE)) {
+ CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, AFHDS_SUBTYPE_FIRST, AFHDS_SUBTYPE_LAST);
+ }
+#endif
else {
g_model.moduleData[EXTERNAL_MODULE].subType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].subType,
MODULE_SUBTYPE_PXX1_ACCST_D16, MODULE_SUBTYPE_PXX1_LAST, EE_MODEL,
@@ -908,6 +919,59 @@ void menuModelSetup(event_t event)
}
break;
+#if defined(MULTIMODULE)
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PROTOCOL:
+ {
+ lcdDrawTextAlignedLeft(y, TR_TYPE);
+
+ uint8_t multi_rfProto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol();
+ lcdDrawMultiProtocolString(MODEL_SETUP_2ND_COLUMN, y, EXTERNAL_MODULE, multi_rfProto, menuHorizontalPosition == 0 ? attr : 0);
+ if (MULTIMODULE_HAS_SUBTYPE(EXTERNAL_MODULE))
+ lcdDrawMultiSubProtocolString(MODEL_SETUP_3RD_COLUMN + 15, y, EXTERNAL_MODULE, g_model.moduleData[EXTERNAL_MODULE].subType,
+ menuHorizontalPosition == 1 ? attr : 0);
+ if (attr) {
+ switch (menuHorizontalPosition) {
+ case 0: {
+ int multiRfProto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol();
+ MultiModuleStatus &status = getMultiModuleStatus(EXTERNAL_MODULE);
+ if (status.isValid()) {
+ int8_t direction = checkIncDec(event, 0, -1, 1);
+ if (direction == -1) {
+ if (multiRfProto == MODULE_SUBTYPE_MULTI_FRSKY)
+ multiRfProto = MODULE_SUBTYPE_MULTI_FRSKYX_RX;
+ else
+ multiRfProto = convertMultiToOtx(status.protocolPrev);
+ }
+ if (direction == 1) {
+ if (multiRfProto == MODULE_SUBTYPE_MULTI_FRSKY)
+ multiRfProto = MODULE_SUBTYPE_MULTI_FRSKYX2;
+ else
+ multiRfProto = convertMultiToOtx(status.protocolNext);
+ }
+ }
+ else {
+ CHECK_INCDEC_MODELVAR_CHECK(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MULTI_MAX_PROTOCOLS, isMultiProtocolSelectable);
+ }
+ if (checkIncDec_Ret) {
+ g_model.moduleData[EXTERNAL_MODULE].setMultiProtocol(multiRfProto);
+ g_model.moduleData[EXTERNAL_MODULE].subType = 0;
+ resetMultiProtocolsOptions(EXTERNAL_MODULE);
+ storageDirty(EE_MODEL);
+ }
+ }
+ break;
+
+ case 1:
+ CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, 0, getMaxMultiSubtype(EXTERNAL_MODULE));
+ if (checkIncDec_Ret) {
+ resetMultiProtocolsOptions(EXTERNAL_MODULE);
+ }
+ break;
+ }
+ }
+ }
+ break;
+#endif
case ITEM_MODEL_SETUP_TRAINER_LABEL:
lcdDrawTextAlignedLeft(y, STR_TRAINER);
break;
@@ -961,7 +1025,7 @@ void menuModelSetup(event_t event)
for (uint8_t i=0; i0) {
+ if (attr && s_editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
CHECK_INCDEC_MODELVAR(event, moduleData.ppm.frameLength, -20, 35);
@@ -1078,9 +1141,8 @@ void menuModelSetup(event_t event)
lcdDrawTextAlignedLeft(y, STR_REFRESHRATE);
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)moduleData.ppm.frameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT);
lcdDrawText(lcdLastRightPos, y, STR_MS);
- lcdDrawText(MODEL_SETUP_3RD_COLUMN, y, moduleData.sbus.noninverted ? "not inverted" : "normal", (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0);
-
- if (attr && s_editMode>0) {
+ lcdDrawText(MODEL_SETUP_3RD_COLUMN, y, moduleData.sbus.noninverted ? STR_NOT_INVERTED : STR_NORMAL, (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0);
+ if (attr && s_editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
CHECK_INCDEC_MODELVAR(event, moduleData.ppm.frameLength, -33, 35);
@@ -1092,21 +1154,19 @@ void menuModelSetup(event_t event)
}
}
else {
+ lcdDrawText(INDENT_WIDTH, y, STR_RECEIVER);
horzpos_t l_posHorz = menuHorizontalPosition;
- coord_t xOffsetBind = MODEL_SETUP_BIND_OFS;
- if (!isModuleRxNumAvailable(moduleIdx)) {
- xOffsetBind = 0;
- lcdDrawText(INDENT_WIDTH, y, STR_RECEIVER);
- if (attr) l_posHorz += 1;
+ coord_t bindButtonPos = MODEL_SETUP_2ND_COLUMN;
+ if (isModuleRxNumAvailable(moduleIdx)) {
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz == 0 ? attr : 0) | LEADING0 | LEFT, 2);
+ bindButtonPos = lcdNextPos + FW;
}
- else {
- lcdDrawText(INDENT_WIDTH, y, STR_RECEIVER_NUM);
+ else if (attr) {
+ l_posHorz += 1;
}
if (isModuleBindRangeAvailable(moduleIdx)) {
- if (xOffsetBind)
- lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2);
- if (attr && l_posHorz==0) {
- if (s_editMode>0) {
+ if (attr && l_posHorz == 0) {
+ if (s_editMode > 0) {
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], getMaxRxNum(moduleIdx));
if (checkIncDec_Ret) {
modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx];
@@ -1121,8 +1181,10 @@ void menuModelSetup(event_t event)
}
}
}
- lcdDrawText(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, l_posHorz==1 ? attr : 0);
- lcdDrawText(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0);
+ lcdDrawText(bindButtonPos, y, STR_MODULE_BIND, l_posHorz == 1 ? attr : 0);
+ if (isModuleRangeAvailable(moduleIdx)) {
+ lcdDrawText(lcdNextPos + FW, y, STR_MODULE_RANGE, l_posHorz == 2 ? attr : 0);
+ }
uint8_t newFlag = 0;
#if defined(MULTIMODULE)
if (getMultiBindStatus(moduleIdx) == MULTI_BIND_FINISHED) {
@@ -1130,11 +1192,17 @@ void menuModelSetup(event_t event)
s_editMode = 0;
}
#endif
- if (attr && l_posHorz>0) {
- if (s_editMode>0) {
+ if (attr && l_posHorz > 0) {
+ if (s_editMode > 0) {
if (l_posHorz == 1) {
- if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx)) {
+ if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx) || isModuleAFHDS3(moduleIdx)) {
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
+#if defined(AFHDS3)
+ if (isModuleAFHDS3(moduleIdx)) {
+ startBindMenuAfhds3(moduleIdx);
+ continue;
+ }
+#endif
startBindMenu(moduleIdx);
continue;
}
@@ -1158,8 +1226,9 @@ void menuModelSetup(event_t event)
}
moduleState[moduleIdx].mode = newFlag;
#if defined(MULTIMODULE)
- if (newFlag == MODULE_MODE_BIND)
+ if (newFlag == MODULE_MODE_BIND) {
setMultiBindStatus(moduleIdx, MULTI_BIND_INITIATED);
+ }
#endif
}
}
@@ -1216,8 +1285,17 @@ void menuModelSetup(event_t event)
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
int optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
+ MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
const uint8_t multi_proto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol();
- if (multi_proto < MODULE_SUBTYPE_MULTI_LAST) {
+ if (status.isValid()) {
+ lcdDrawText(INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
+ if (attr && status.optionDisp == 2) {
+ lcdDrawText(MODEL_SETUP_3RD_COLUMN+22, y, "RSSI(", LEFT);
+ lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
+ lcdDrawText(lcdLastRightPos, y, ")", LEFT);
+ }
+ }
+ else {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
if (pdef->optionsstr)
lcdDrawText(INDENT_WIDTH, y, pdef->optionsstr);
@@ -1227,23 +1305,36 @@ void menuModelSetup(event_t event)
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
}
- else {
- MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
- lcdDrawText(INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
- if (attr && status.optionDisp == 2) {
- lcdDrawText(MODEL_SETUP_3RD_COLUMN+22, y, "RSSI(", LEFT);
- lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
- lcdDrawText(lcdLastRightPos, y, ")", LEFT);
- }
- }
- if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A)
- optionValue = 50 + 5 * optionValue;
- lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
+ int8_t min, max;
+ getMultiOptionValues(multi_proto, min, max);
+
+ if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
+ }
+ else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) {
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
+ }
+ else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
+ optionValue = optionValue & 0x01;
+ editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event);
+ }
+ else {
+ if (min == 0 && max == 1)
+ editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event);
+ else
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
+ }
if (attr) {
- int8_t min, max;
- getMultiOptionValues(multi_proto, min, max);
- CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, min, max);
+ CHECK_INCDEC_MODELVAR(event, optionValue, min, max);
+ if (checkIncDec_Ret) {
+ if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
+ g_model.moduleData[moduleIdx].multi.optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0xFE) + optionValue;
+ }
+ else {
+ g_model.moduleData[moduleIdx].multi.optionValue = optionValue;
+ }
+ }
}
}
#endif
@@ -1286,7 +1377,15 @@ void menuModelSetup(event_t event)
}
#if defined (MULTIMODULE)
else if (isModuleMultimodule(moduleIdx)) {
- g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_LOWPOWER, attr, event);
+ g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, IS_RX_MULTI(moduleIdx) ? STR_MULTI_LNA_DISABLE : STR_MULTI_LOWPOWER, attr, event);
+ }
+#endif
+#if defined(AFHDS3)
+ else if (isModuleAFHDS3(EXTERNAL_MODULE)) {
+ lcdDrawText(INDENT_WIDTH, y, STR_RFPOWER);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, g_model.moduleData[EXTERNAL_MODULE].afhds3.runPower, LEFT | attr);
+ if (attr)
+ CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].afhds3.runPower, afhds3::RUN_POWER::RUN_POWER_FIRST, afhds3::RUN_POWER::RUN_POWER_LAST);
}
#endif
break;
@@ -1294,10 +1393,21 @@ void menuModelSetup(event_t event)
#if defined (MULTIMODULE)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND:
- if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2)
- g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_DSM_AUTODTECT, attr, event);
- else
+ if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) {
+ int8_t value = (g_model.moduleData[EXTERNAL_MODULE].multi.optionValue & 0x02) >> 1;
+ lcdDrawText(INDENT_WIDTH, y, STR_MULTI_SERVOFREQ);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, value ? 11 : 22, attr);
+ lcdDrawText(lcdNextPos, y, "ms", attr);
+ if (attr) {
+ CHECK_INCDEC_MODELVAR(event, value, 0, 1);
+ if (checkIncDec_Ret) {
+ g_model.moduleData[EXTERNAL_MODULE].multi.optionValue = (g_model.moduleData[EXTERNAL_MODULE].multi.optionValue & 0xFD) + (value << 1);
+ }
+ }
+ }
+ else {
g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_AUTOBIND, attr, event);
+ }
break;
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM:
@@ -1307,26 +1417,68 @@ void menuModelSetup(event_t event)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING:
g_model.moduleData[EXTERNAL_MODULE].multi.disableMapping = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.disableMapping, MODEL_SETUP_2ND_COLUMN, y, INDENT TR_DISABLE_CH_MAP, attr, event);
break;
+#endif
+#if defined(AFHDS3)
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ:
+ lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_RX_FREQ);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.moduleData[EXTERNAL_MODULE].afhds3.rxFreq(), attr | LEFT);
+ if (attr) {
+ uint16_t rxFreq = g_model.moduleData[EXTERNAL_MODULE].afhds3.rxFreq();
+ CHECK_INCDEC_MODELVAR(event, rxFreq, MIN_FREQ, MAX_FREQ);
+ g_model.moduleData[EXTERNAL_MODULE].afhds3.setRxFreq(rxFreq);
+ }
+ break;
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER:
+ lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_ACTUAL_POWER);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, actualAfhdsRunPower(EXTERNAL_MODULE), LEFT);
+ break;
+#endif
+
+#if defined (MULTIMODULE)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS:
{
- lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS);
+ lcdDrawText(INDENT_WIDTH, y, STR_MODULE_STATUS);
char statusText[64];
- getMultiModuleStatus(EXTERNAL_MODULE).getStatusString(statusText);
+ getModuleStatusString(EXTERNAL_MODULE, statusText);
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
break;
}
-
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS:
{
- lcdDrawTextAlignedLeft(y, STR_MODULE_SYNC);
+ lcdDrawText(INDENT_WIDTH, y, STR_MODULE_SYNC);
char statusText[64];
- getMultiSyncStatus(EXTERNAL_MODULE).getRefreshString(statusText);
+ getModuleSyncStatusString(EXTERNAL_MODULE, statusText);
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
break;
}
#endif
+#if defined (AFHDS3)
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE:
+ lcdDrawTextAlignedLeft(y, STR_TYPE);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y,
+ g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry ? STR_AFHDS3_ONE_TO_ONE_TELEMETRY : TR_AFHDS3_ONE_TO_MANY);
+ break;
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS:
+ {
+ lcdDrawTextAlignedLeft(y, TR_MODULE_STATUS);
+ char statusText[64];
+ getModuleStatusString(EXTERNAL_MODULE, statusText);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
+ break;
+ }
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS:
+ {
+ lcdDrawText(INDENT_WIDTH, y, STR_AFHDS3_POWER_SOURCE);
+ char statusText[64];
+ getModuleSyncStatusString(EXTERNAL_MODULE, statusText);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
+ break;
+ }
+#endif
+
+
#if defined(PXX2)
case ITEM_MODEL_SETUP_REGISTRATION_ID:
lcdDrawTextAlignedLeft(y, STR_REG_ID);
@@ -1409,15 +1561,15 @@ void menuModelSetup(event_t event)
if (old_editMode > 0 && s_editMode == 0) {
switch(menuVerticalPosition) {
- case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_BIND:
- if (menuHorizontalPosition == 0)
- checkModelIdUnique(g_eeGeneral.currModel, INTERNAL_MODULE);
- break;
+ case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE:
+ if (menuHorizontalPosition == 0)
+ checkModelIdUnique(g_eeGeneral.currModel, INTERNAL_MODULE);
+ break;
- case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_BIND:
- if (menuHorizontalPosition == 0)
- checkModelIdUnique(g_eeGeneral.currModel, EXTERNAL_MODULE);
- break;
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE:
+ if (menuHorizontalPosition == 0)
+ checkModelIdUnique(g_eeGeneral.currModel, EXTERNAL_MODULE);
+ break;
}
}
}
diff --git a/radio/src/gui/212x64/radio_calibration.cpp b/radio/src/gui/212x64/radio_calibration.cpp
index bf4c829c3..6ec060e6f 100644
--- a/radio/src/gui/212x64/radio_calibration.cpp
+++ b/radio/src/gui/212x64/radio_calibration.cpp
@@ -202,7 +202,7 @@ void menuFirstCalib(event_t event)
chainMenu(menuMainView);
}
else {
- lcdDrawTextAlignedCenter(0*FH, TR_MENUCALIBRATION);
+ lcdDrawText(LCD_W / 2, 0, STR_MENUCALIBRATION, CENTERED);
lcdInvertLine(0);
menuCommonCalib(event);
}
diff --git a/radio/src/gui/212x64/radio_diaganas.cpp b/radio/src/gui/212x64/radio_diaganas.cpp
index bea4089a4..6e1f21ced 100644
--- a/radio/src/gui/212x64/radio_diaganas.cpp
+++ b/radio/src/gui/212x64/radio_diaganas.cpp
@@ -38,12 +38,4 @@ void menuRadioDiagAnalogs(event_t event)
lcdDrawNumber(x+10*FW-1, y, (int16_t)calibratedAnalogs[CONVERT_MODE(i)]*25/256, RIGHT);
#endif
}
-
- // RAS
- if ((isModuleXJT(INTERNAL_MODULE) && IS_INTERNAL_MODULE_ON()) || (isModulePXX1(EXTERNAL_MODULE) && !IS_INTERNAL_MODULE_ON())) {
- lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+6*FH, "RAS");
- lcdDrawNumber(10*FW-1, MENU_HEADER_HEIGHT+6*FH, telemetryData.swrInternal.value(), RIGHT);
- lcdDrawText(LCD_W/2, MENU_HEADER_HEIGHT+6*FH, "XJTVER");
- lcdDrawNumber(LCD_W/2 + 10*FW-1, MENU_HEADER_HEIGHT+6*FH, telemetryData.xjtVersion, RIGHT);
- }
}
diff --git a/radio/src/gui/212x64/radio_diagkeys.cpp b/radio/src/gui/212x64/radio_diagkeys.cpp
index 7a9f42499..acb883513 100644
--- a/radio/src/gui/212x64/radio_diagkeys.cpp
+++ b/radio/src/gui/212x64/radio_diagkeys.cpp
@@ -45,7 +45,7 @@ void menuRadioDiagKeys(event_t event)
displayKeyState(5 * FW + 2, y, i);
}
- for (uint8_t i = 0, cnt = 0; i <= NUM_SWITCHES; i++) {
+ for (uint8_t i = 0, cnt = 0; i < NUM_SWITCHES; i++) {
if (SWITCH_EXISTS(i)) {
div_t qr = div(cnt++, 6);
coord_t x = 4 * FH * qr.quot;
@@ -59,6 +59,6 @@ void menuRadioDiagKeys(event_t event)
#if defined(ROTARY_ENCODER_NAVIGATION)
coord_t y = MENU_HEADER_HEIGHT + 1 + FH*KEY_COUNT;
lcdDrawText(0, y, STR_ROTARY_ENCODER);
- lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue, RIGHT);
+ lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue / ROTARY_ENCODER_GRANULARITY, RIGHT);
#endif
}
diff --git a/radio/src/gui/212x64/view_channels.cpp b/radio/src/gui/212x64/view_channels.cpp
index 4b34f7f4f..e00b3e9d0 100644
--- a/radio/src/gui/212x64/view_channels.cpp
+++ b/radio/src/gui/212x64/view_channels.cpp
@@ -61,11 +61,7 @@ void menuChannelsView(event_t event)
else if (g_model.extendedLimits)
limits *= LIMIT_EXT_PERCENT / 100;
- if (reusableBuffer.viewChannels.mixersView)
- lcdDrawTextAlignedCenter(0, TR_MIXERS_MONITOR);
- else
- lcdDrawTextAlignedCenter(0, TR_CHANNELS_MONITOR);
-
+ lcdDrawText(LCD_W / 2, 0, reusableBuffer.viewChannels.mixersView ? STR_MIXERS_MONITOR : STR_CHANNELS_MONITOR, CENTERED);
lcdInvertLine(0);
// Column separator
diff --git a/radio/src/gui/212x64/view_main.cpp b/radio/src/gui/212x64/view_main.cpp
index 56e4c22ae..659781ea6 100644
--- a/radio/src/gui/212x64/view_main.cpp
+++ b/radio/src/gui/212x64/view_main.cpp
@@ -455,7 +455,7 @@ void menuMainView(event_t event)
break;
case EVT_KEY_LONG(KEY_MENU):
- pushMenu(menuRadioSetup);
+ pushMenu(menuTabGeneral[0]);
killEvents(event);
break;
#endif
@@ -470,7 +470,7 @@ void menuMainView(event_t event)
break;
case EVT_KEY_LONG(KEY_PAGE):
- chainMenu(menuViewTelemetryFrsky);
+ chainMenu(menuViewTelemetry);
killEvents(event);
break;
diff --git a/radio/src/gui/212x64/view_telemetry.cpp b/radio/src/gui/212x64/view_telemetry.cpp
index 04dc411c5..fa8740667 100644
--- a/radio/src/gui/212x64/view_telemetry.cpp
+++ b/radio/src/gui/212x64/view_telemetry.cpp
@@ -200,65 +200,3 @@ bool displayTelemetryScreen()
return true;
}
-enum NavigationDirection {
- none,
- up,
- down
-};
-
-#define decrTelemetryScreen() direction = up
-#define incrTelemetryScreen() direction = down
-
-void menuViewTelemetryFrsky(event_t event)
-{
- enum NavigationDirection direction = none;
-
- switch (event) {
- case EVT_KEY_FIRST(KEY_EXIT):
- case EVT_KEY_LONG(KEY_EXIT):
- killEvents(event);
- chainMenu(menuMainView);
- break;
-
- case EVT_KEY_LONG(KEY_PAGE):
- killEvents(event);
- // no break;
-
- case EVT_KEY_FIRST(KEY_UP):
- decrTelemetryScreen();
- break;
-
- case EVT_KEY_BREAK(KEY_PAGE):
- case EVT_KEY_FIRST(KEY_DOWN):
- incrTelemetryScreen();
- break;
-
- case EVT_KEY_LONG(KEY_ENTER):
- killEvents(event);
- POPUP_MENU_ADD_ITEM(STR_RESET_TELEMETRY);
- POPUP_MENU_ADD_ITEM(STR_RESET_FLIGHT);
- POPUP_MENU_START(onMainViewMenu);
- break;
- }
-
- for (int i=0; i<=TELEMETRY_SCREEN_TYPE_MAX; i++) {
- if (direction == up) {
- if (s_frsky_view-- == 0)
- s_frsky_view = TELEMETRY_VIEW_MAX;
- }
- else if (direction == down) {
- if (s_frsky_view++ == TELEMETRY_VIEW_MAX)
- s_frsky_view = 0;
- }
- else {
- direction = down;
- }
- if (displayTelemetryScreen()) {
- return;
- }
- }
-
- drawTelemetryTopBar();
- lcdDrawText(8*FW, 3*FH, "No Telemetry Screens");
- displayRssiLine();
-}
diff --git a/radio/src/gui/480x272/bitmapbuffer.h b/radio/src/gui/480x272/bitmapbuffer.h
index 760215198..9cca2916a 100644
--- a/radio/src/gui/480x272/bitmapbuffer.h
+++ b/radio/src/gui/480x272/bitmapbuffer.h
@@ -25,7 +25,7 @@
#include "colors.h"
#include "rle.h"
-#if defined(PCBX10) && !defined(SIMU)
+#if defined(LCD_VERTICAL_INVERT)
#define MOVE_PIXEL_RIGHT(p, count) p -= count
#else
#define MOVE_PIXEL_RIGHT(p, count) p += count
@@ -41,6 +41,14 @@ typedef int coord_t;
typedef uint32_t LcdFlags;
typedef uint16_t display_t;
+int getTextWidth(const char * s, int len=0, LcdFlags flags=0);
+
+#if LCD_W >= 480
+#define LCD_COLS 80
+#else
+#define LCD_COLS 30
+#endif
+
enum BitmapFormats
{
BMP_RGB565,
@@ -92,7 +100,7 @@ class BitmapBufferBase
inline const display_t * getPixelPtr(coord_t x, coord_t y) const
{
-#if defined(PCBX10) && !defined(SIMU)
+#if defined(LCD_VERTICAL_INVERT)
x = width - x - 1;
y = height - y - 1;
#endif
@@ -193,7 +201,7 @@ class BitmapBuffer: public BitmapBufferBase
inline const display_t * getPixelPtr(coord_t x, coord_t y) const
{
-#if defined(PCBX10) && !defined(SIMU)
+#if defined(LCD_VERTICAL_INVERT)
x = width - x - 1;
y = height - y - 1;
#endif
@@ -202,7 +210,7 @@ class BitmapBuffer: public BitmapBufferBase
inline display_t * getPixelPtr(coord_t x, coord_t y)
{
-#if defined(PCBX10) && !defined(SIMU)
+#if defined(LCD_VERTICAL_INVERT)
x = width - x - 1;
y = height - y - 1;
#endif
@@ -275,6 +283,16 @@ class BitmapBuffer: public BitmapBufferBase
uint8_t drawCharWithCache(coord_t x, coord_t y, const BitmapBuffer * font, const uint16_t * spec, int index, LcdFlags flags);
+ void drawTextMaxWidth(coord_t x, coord_t y, const char * s, LcdFlags flags, coord_t maxWidth)
+ {
+ for (int col = LCD_COLS; col > 0; col--) {
+ if (getTextWidth(s, col, flags) <= maxWidth) {
+ drawSizedText(x, y, s, col, flags);
+ return;
+ }
+ }
+ }
+
void drawText(coord_t x, coord_t y, const char * s, LcdFlags flags)
{
drawSizedText(x, y, s, 255, flags);
diff --git a/radio/src/gui/480x272/bitmaps.cpp b/radio/src/gui/480x272/bitmaps.cpp
index f7b87a4d3..08cc8f59a 100644
--- a/radio/src/gui/480x272/bitmaps.cpp
+++ b/radio/src/gui/480x272/bitmaps.cpp
@@ -64,6 +64,10 @@ const uint8_t LBM_TOPMENU_TXBATT[] = {
#include "mask_txbat.lbm"
};
+const uint8_t LBM_TOPMENU_TXBATT_CHARGING[] = {
+#include "mask_txbat_charging.lbm"
+};
+
const uint8_t LBM_TOPMENU_ANTENNA[] = {
#include "mask_antenna.lbm"
};
diff --git a/radio/src/gui/480x272/bitmaps.h b/radio/src/gui/480x272/bitmaps.h
index fcefcbd49..b51c04551 100644
--- a/radio/src/gui/480x272/bitmaps.h
+++ b/radio/src/gui/480x272/bitmaps.h
@@ -34,6 +34,7 @@ extern const uint8_t LBM_TOPMENU_VOLUME_3[];
extern const uint8_t LBM_TOPMENU_VOLUME_4[];
extern const uint8_t LBM_TOPMENU_VOLUME_SCALE[];
extern const uint8_t LBM_TOPMENU_TXBATT[];
+extern const uint8_t LBM_TOPMENU_TXBATT_CHARGING[];
extern const uint8_t LBM_HTRIM_FRAME[];
extern const uint8_t LBM_VTRIM_FRAME[];
extern const uint8_t LBM_TRIM_SHADOW[];
diff --git a/radio/src/gui/480x272/gui.h b/radio/src/gui/480x272/gui.h
index e17858f22..17618563e 100644
--- a/radio/src/gui/480x272/gui.h
+++ b/radio/src/gui/480x272/gui.h
@@ -47,6 +47,7 @@
#define FH 20
#define NUM_BODY_LINES (MENU_BODY_HEIGHT / FH)
+#define TEXT_VIEWER_LINES ((MENU_FOOTER_TOP-MENU_HEADER_HEIGHT) / FH)
#define INVERT_HORZ_MARGIN 2
#define INVERT_VERT_MARGIN 1
diff --git a/radio/src/gui/480x272/layouts/layout1x1.cpp b/radio/src/gui/480x272/layouts/layout1x1.cpp
index 0feeb1436..79bc53739 100644
--- a/radio/src/gui/480x272/layouts/layout1x1.cpp
+++ b/radio/src/gui/480x272/layouts/layout1x1.cpp
@@ -25,8 +25,8 @@ const uint8_t LBM_LAYOUT_1x1[] = {
};
const ZoneOption OPTIONS_LAYOUT_1x1[] = {
- { "Top bar", ZoneOption::Bool },
- { "Sliders+Trims", ZoneOption::Bool },
+ { STR_TOP_BAR, ZoneOption::Bool },
+ { STR_SLIDERS_TRIMS, ZoneOption::Bool },
{ NULL, ZoneOption::Bool }
};
diff --git a/radio/src/gui/480x272/layouts/layout2+1.cpp b/radio/src/gui/480x272/layouts/layout2+1.cpp
index 39abb1a9e..860cc94f9 100644
--- a/radio/src/gui/480x272/layouts/layout2+1.cpp
+++ b/radio/src/gui/480x272/layouts/layout2+1.cpp
@@ -25,10 +25,10 @@ const uint8_t LBM_LAYOUT_2P1[] = {
};
const ZoneOption OPTIONS_LAYOUT_2P1[] = {
- { "Top bar", ZoneOption::Bool },
- { "Flight mode", ZoneOption::Bool },
- { "Sliders", ZoneOption::Bool },
- { "Trims", ZoneOption::Bool },
+ { STR_TOP_BAR, ZoneOption::Bool },
+ { STR_FLIGHT_MODE, ZoneOption::Bool },
+ { STR_SLIDERS, ZoneOption::Bool },
+ { STR_TRIMS, ZoneOption::Bool },
{ NULL, ZoneOption::Bool }
};
diff --git a/radio/src/gui/480x272/layouts/layout2x1.cpp b/radio/src/gui/480x272/layouts/layout2x1.cpp
index a96fc7006..81e196d63 100644
--- a/radio/src/gui/480x272/layouts/layout2x1.cpp
+++ b/radio/src/gui/480x272/layouts/layout2x1.cpp
@@ -25,7 +25,7 @@ const uint8_t LBM_LAYOUT_2x1[] = {
};
const ZoneOption OPTIONS_LAYOUT_2x1[] = {
- { "Top bar", ZoneOption::Bool },
+ { STR_TOP_BAR, ZoneOption::Bool },
{ NULL, ZoneOption::Bool }
};
@@ -45,7 +45,7 @@ class Layout2x1: public Layout
virtual unsigned int getZonesCount() const
{
- return 4;
+ return 2;
}
virtual Zone getZone(unsigned int index) const
diff --git a/radio/src/gui/480x272/layouts/layout2x2.cpp b/radio/src/gui/480x272/layouts/layout2x2.cpp
index 0efa2df62..7d2f16f09 100644
--- a/radio/src/gui/480x272/layouts/layout2x2.cpp
+++ b/radio/src/gui/480x272/layouts/layout2x2.cpp
@@ -25,7 +25,7 @@ const uint8_t LBM_LAYOUT_2x2[] = {
};
const ZoneOption OPTIONS_LAYOUT_2x2[] = {
- { "Top bar", ZoneOption::Bool },
+ { STR_TOP_BAR, ZoneOption::Bool },
{ NULL, ZoneOption::Bool }
};
diff --git a/radio/src/gui/480x272/layouts/layout2x4.cpp b/radio/src/gui/480x272/layouts/layout2x4.cpp
index b6e009acc..0850c7e67 100644
--- a/radio/src/gui/480x272/layouts/layout2x4.cpp
+++ b/radio/src/gui/480x272/layouts/layout2x4.cpp
@@ -25,14 +25,14 @@ const uint8_t LBM_LAYOUT_2x4[] = {
};
const ZoneOption OPTIONS_LAYOUT_2x4[] = {
- { "Top bar", ZoneOption::Bool },
- { "Flight mode", ZoneOption::Bool },
- { "Sliders", ZoneOption::Bool },
- { "Trims", ZoneOption::Bool },
- { "Panel1 background", ZoneOption::Bool },
- { " Color", ZoneOption::Color },
- { "Panel2 background", ZoneOption::Bool },
- { " Color", ZoneOption::Color },
+ { STR_TOP_BAR, ZoneOption::Bool },
+ { STR_FLIGHT_MODE, ZoneOption::Bool },
+ { STR_SLIDERS, ZoneOption::Bool },
+ { STR_TRIMS, ZoneOption::Bool },
+ { STR_PANEL1_BACKGROUND, ZoneOption::Bool },
+ { INDENT TR_COLOR, ZoneOption::Color },
+ { STR_PANEL2_BACKGROUND, ZoneOption::Bool },
+ { INDENT TR_COLOR, ZoneOption::Color },
{ NULL, ZoneOption::Bool }
};
diff --git a/radio/src/gui/480x272/lcd.cpp b/radio/src/gui/480x272/lcd.cpp
index f139eaa5c..e2c660f73 100644
--- a/radio/src/gui/480x272/lcd.cpp
+++ b/radio/src/gui/480x272/lcd.cpp
@@ -20,6 +20,7 @@
#include
#include
+#include
#include "opentx.h"
#include "strhelpers.h"
@@ -49,24 +50,24 @@ uint8_t getMappedChar(uint8_t c)
result = 127 + c - 0x80;
}
#elif defined(TRANSLATIONS_ES)
- else if (c >= 0x80 && c <= 0x81) {
+ else if (c >= 0x80 && c <= 0x80+12) {
result = 157 + c - 0x80;
}
#elif defined(TRANSLATIONS_FI) || defined(TRANSLATIONS_SE)
else if (c >= 0x80 && c <= 0x85) {
- result = 159 + c - 0x80;
+ result = 169 + c - 0x80;
}
#elif defined(TRANSLATIONS_IT)
else if (c >= 0x80 && c <= 0x81) {
- result = 165 + c - 0x80;
+ result = 175 + c - 0x80;
}
#elif defined(TRANSLATIONS_PL)
else if (c >= 0x80 && c <= 0x80+17) {
- result = 167 + c - 0x80;
+ result = 177 + c - 0x80;
}
#elif defined(TRANSLATIONS_PT)
else if (c >= 0x80 && c <= 0x80+21) {
- result = 185 + c - 0x80;
+ result = 195 + c - 0x80;
}
#endif
else if (c < 0xC0)
@@ -165,7 +166,19 @@ void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags, uint8_t le
int idx = 0;
int mode = MODE(flags);
bool neg = false;
+
+ if (val == INT_MAX) {
+ flags &= ~(LEADING0 | PREC1 | PREC2);
+ lcdDrawText(x, y, "INT_MAX", flags);
+ return;
+ }
+
if (val < 0) {
+ if (val == INT_MIN) {
+ flags &= ~(LEADING0 | PREC1 | PREC2);
+ lcdDrawText(x, y, "INT_MIN", flags);
+ return;
+ }
val = -val;
neg = true;
}
@@ -339,9 +352,9 @@ void drawDate(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags att)
att &= ~FONTSIZE_MASK;
lcdDrawNumber(x, y, telemetryItem.datetime.day, att|LEADING0|LEFT, 2);
lcdDrawChar(lcdNextPos-1, y, '-', att);
- lcdDrawNumber(lcdNextPos-1, y, telemetryItem.datetime.month, att|LEFT, 2);
+ lcdDrawNumber(lcdNextPos-1, y, telemetryItem.datetime.month, att|LEADING0|LEFT, 2);
lcdDrawChar(lcdNextPos-1, y, '-', att);
- lcdDrawNumber(lcdNextPos-1, y, telemetryItem.datetime.year-2000, att|LEFT);
+ lcdDrawNumber(lcdNextPos-1, y, telemetryItem.datetime.year-2000, att|LEADING0|LEFT);
y += FH;
lcdDrawNumber(x, y, telemetryItem.datetime.hour, att|LEADING0|LEFT, 2);
lcdDrawChar(lcdNextPos, y, ':', att);
@@ -352,9 +365,9 @@ void drawDate(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags att)
else {
lcdDrawNumber(x, y, telemetryItem.datetime.day, att|LEADING0|LEFT, 2);
lcdDrawChar(lcdNextPos-1, y, '-', att);
- lcdDrawNumber(lcdNextPos, y, telemetryItem.datetime.month, att|LEFT, 2);
+ lcdDrawNumber(lcdNextPos, y, telemetryItem.datetime.month, att|LEADING0|LEFT, 2);
lcdDrawChar(lcdNextPos-1, y, '-', att);
- lcdDrawNumber(lcdNextPos, y, telemetryItem.datetime.year-2000, att|LEFT);
+ lcdDrawNumber(lcdNextPos, y, telemetryItem.datetime.year-2000, att|LEADING0|LEFT);
lcdDrawNumber(lcdNextPos+11, y, telemetryItem.datetime.hour, att|LEADING0|LEFT, 2);
lcdDrawChar(lcdNextPos, y, ':', att);
lcdDrawNumber(lcdNextPos, y, telemetryItem.datetime.min, att|LEADING0|LEFT, 2);
@@ -422,7 +435,11 @@ void lcdDrawPoint(coord_t x, coord_t y, LcdFlags att)
{
display_t * p = PIXEL_PTR(x, y);
display_t color = lcdColorTable[COLOR_IDX(att)];
+#if defined(PCBX10)
+ if (p >= displayBuf && x < LCD_W) { // x10 screen is reversed, so overflow are happening the other way around
+#else
if (p < DISPLAY_END) {
+#endif
*p = color;
}
}
diff --git a/radio/src/gui/480x272/lcd.h b/radio/src/gui/480x272/lcd.h
index c66865d85..d6c8dfa11 100644
--- a/radio/src/gui/480x272/lcd.h
+++ b/radio/src/gui/480x272/lcd.h
@@ -24,12 +24,6 @@
#include "bitmapbuffer.h"
#include "opentx_types.h"
-#if LCD_W >= 480
- #define LCD_COLS 40
-#else
- #define LCD_COLS 30
-#endif
-
#define CENTER
/* lcd common flags */
@@ -162,7 +156,7 @@ void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags attr);
#define DOTTED 0x55
#define STASHED 0x33
-#if defined(PCBX10) && !defined(SIMU)
+#if defined(LCD_VERTICAL_INVERT)
#define PIXEL_PTR(x, y) &displayBuf[(LCD_H*LCD_W-1) - (y)*LCD_W - (x)]
#else
#define PIXEL_PTR(x, y) &displayBuf[(y)*LCD_W + (x)]
@@ -254,7 +248,6 @@ inline int getBitmapHeight(const uint8_t * bmp)
uint8_t getMappedChar(uint8_t c);
uint8_t getFontHeight(LcdFlags flags);
-int getTextWidth(const char * s, int len=0, LcdFlags flags=0);
inline void lcdDrawBitmapPattern(coord_t x, coord_t y, const uint8_t * img, LcdFlags flags=0, coord_t offset=0, coord_t width=0)
{
diff --git a/radio/src/gui/480x272/menu_model.cpp b/radio/src/gui/480x272/menu_model.cpp
index 761bc9180..09ce6523f 100644
--- a/radio/src/gui/480x272/menu_model.cpp
+++ b/radio/src/gui/480x272/menu_model.cpp
@@ -151,6 +151,7 @@ void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, ui
}
uint8_t s_currIdx;
+uint8_t s_currIdxSubMenu;
void copySelection(char * dst, const char * src, uint8_t size)
{
diff --git a/radio/src/gui/480x272/menu_radio.cpp b/radio/src/gui/480x272/menu_radio.cpp
index 42327fc6f..e50486b0d 100644
--- a/radio/src/gui/480x272/menu_radio.cpp
+++ b/radio/src/gui/480x272/menu_radio.cpp
@@ -21,11 +21,11 @@
#include "opentx.h"
const MenuHandlerFunc menuTabGeneral[MENU_RADIO_PAGES_COUNT] = {
- menuRadioSetup,
- menuRadioSdManager,
-#if defined(LUA) || defined(PXX2)
+#if defined(RADIO_TOOLS)
menuRadioTools,
#endif
+ menuRadioSdManager,
+ menuRadioSetup,
menuRadioSpecialFunctions,
menuRadioTrainer,
menuRadioHardware,
diff --git a/radio/src/gui/480x272/menus.cpp b/radio/src/gui/480x272/menus.cpp
index 44af61725..e88c02a25 100644
--- a/radio/src/gui/480x272/menus.cpp
+++ b/radio/src/gui/480x272/menus.cpp
@@ -55,8 +55,10 @@ void pushMenu(MenuHandlerFunc newMenu)
killEvents(KEY_ENTER);
if (menuLevel == 0) {
- if (newMenu == menuRadioSetup)
+#if defined(RADIO_TOOLS)
+ if (newMenu == menuRadioTools)
menuVerticalPositions[0] = 1;
+#endif
if (newMenu == menuModelSetup)
menuVerticalPositions[0] = 0;
}
diff --git a/radio/src/gui/480x272/menus.h b/radio/src/gui/480x272/menus.h
index 836029bd4..290ff43ac 100644
--- a/radio/src/gui/480x272/menus.h
+++ b/radio/src/gui/480x272/menus.h
@@ -151,7 +151,6 @@ const uint8_t STATS_ICONS[] = {
ICON_STATS,
ICON_STATS_THROTTLE_GRAPH,
ICON_STATS_DEBUG,
- ICON_STATS_ANALOGS,
#if defined(DEBUG_TRACE_BUFFER)
ICON_STATS_TIMERS
#endif
@@ -190,11 +189,11 @@ bool menuRadioDiagAnalogs(event_t event);
extern const MenuHandlerFunc menuTabModel[MENU_MODEL_PAGES_COUNT];
enum EnumTabRadio {
- MENU_RADIO_SETUP,
- MENU_RADIO_SD_MANAGER,
-#if defined(LUA) || defined(PXX2)
+#if defined(RADIO_TOOLS)
MENU_RADIO_TOOLS,
#endif
+ MENU_RADIO_SD_MANAGER,
+ MENU_RADIO_SETUP,
MENU_RADIO_SPECIAL_FUNCTIONS,
MENU_RADIO_TRAINER,
MENU_RADIO_HARDWARE,
@@ -204,11 +203,11 @@ enum EnumTabRadio {
const uint8_t RADIO_ICONS[MENU_RADIO_PAGES_COUNT + 1] = {
ICON_RADIO,
- ICON_RADIO_SETUP,
- ICON_RADIO_SD_MANAGER,
-#if defined(LUA) || defined(PXX2)
+#if defined(RADIO_TOOLS)
ICON_RADIO_TOOLS,
#endif
+ ICON_RADIO_SD_MANAGER,
+ ICON_RADIO_SETUP,
ICON_RADIO_GLOBAL_FUNCTIONS,
ICON_RADIO_TRAINER,
ICON_RADIO_HARDWARE,
@@ -240,13 +239,11 @@ enum MenuRadioIndexes
bool menuStatsGraph(event_t event);
bool menuStatsDebug(event_t event);
-bool menuStatsAnalogs(event_t event);
bool menuStatsTraces(event_t event);
static const MenuHandlerFunc menuTabStats[] = {
menuStatsGraph,
menuStatsDebug,
- menuStatsAnalogs,
#if defined(DEBUG_TRACE_BUFFER)
menuStatsTraces,
#endif
@@ -440,8 +437,6 @@ void editName(coord_t x, coord_t y, char *name, uint8_t size, event_t event, uin
uint8_t editDelay(coord_t x, coord_t y, event_t event, uint8_t attr, uint8_t delay);
void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags);
-extern uint8_t s_curveChan;
-
enum
{
WARNING_TYPE_WAIT,
@@ -464,6 +459,7 @@ extern uint8_t s_copyMode;
extern int8_t s_copySrcRow;
extern int8_t s_copyTgtOfs;
extern uint8_t s_currIdx;
+extern uint8_t s_currIdxSubMenu;
extern int8_t s_currCh;
extern uint8_t s_copySrcIdx;
extern uint8_t s_copySrcCh;
@@ -506,6 +502,7 @@ inline void DISPLAY_WARNING(event_t event)
#define MENU_MAX_DISPLAY_LINES 9
#define MENU_LINE_LENGTH (LEN_MODEL_NAME+12)
+extern const char * popupMenuTitle;
extern const char * popupMenuItems[POPUP_MENU_MAX_LINES];
extern uint16_t popupMenuItemsCount;
extern uint16_t popupMenuOffset;
@@ -547,6 +544,11 @@ inline void POPUP_MENU_SELECT_ITEM(uint8_t index)
popupMenuSelectedItem = (index > 0 ? (index < popupMenuItemsCount ? index : popupMenuItemsCount - 1) : 0);
}
+inline void POPUP_MENU_TITLE(const char * s)
+{
+ popupMenuTitle = s;
+}
+
inline void POPUP_MENU_START(PopupMenuHandler handler)
{
if (handler != popupMenuHandler) {
@@ -560,8 +562,11 @@ inline void CLEAR_POPUP()
{
warningText = nullptr;
warningInfoText = nullptr;
+ popupMenuTitle = nullptr;
popupMenuHandler = nullptr;
popupMenuItemsCount = 0;
+ // TODO ? popupFunc = nullptr;
+ putEvent(EVT_REFRESH);
}
inline void POPUP_WAIT(const char * s)
@@ -572,6 +577,15 @@ inline void POPUP_WAIT(const char * s)
popupFunc = runPopupWarning;
}
+inline void DRAW_POPUP_WAIT(const char * s)
+{
+ warningText = s;
+ warningInfoText = nullptr;
+ warningType = WARNING_TYPE_WAIT;
+ runPopupWarning(0);
+ warningText = nullptr;
+}
+
inline void POPUP_INFORMATION(const char * s)
{
warningText = s;
diff --git a/radio/src/gui/480x272/model_curves.cpp b/radio/src/gui/480x272/model_curves.cpp
index 7d15edcaf..e53f9aad4 100644
--- a/radio/src/gui/480x272/model_curves.cpp
+++ b/radio/src/gui/480x272/model_curves.cpp
@@ -52,8 +52,8 @@ void runPopupCurvePreset(event_t event)
if (warningResult) {
warningResult = 0;
- CurveInfo & crv = g_model.curves[s_curveChan];
- int8_t * points = curveAddress(s_curveChan);
+ CurveInfo & crv = g_model.curves[s_currIdxSubMenu];
+ int8_t * points = curveAddress(s_currIdxSubMenu);
int k = 25 * reusableBuffer.curveEdit.preset;
int dx = 2000 / (5+crv.points-1);
for (uint8_t i=0; i<5+crv.points; i++) {
@@ -73,14 +73,14 @@ void onCurveOneMenu(const char * result)
POPUP_INPUT(STR_PRESET, runPopupCurvePreset);
}
else if (result == STR_MIRROR) {
- CurveInfo & crv = g_model.curves[s_curveChan];
- int8_t * points = curveAddress(s_curveChan);
+ CurveInfo & crv = g_model.curves[s_currIdxSubMenu];
+ int8_t * points = curveAddress(s_currIdxSubMenu);
for (int i=0; i<5+crv.points; i++)
points[i] = -points[i];
}
else if (result == STR_CLEAR) {
- CurveInfo & crv = g_model.curves[s_curveChan];
- int8_t * points = curveAddress(s_curveChan);
+ CurveInfo & crv = g_model.curves[s_currIdxSubMenu];
+ int8_t * points = curveAddress(s_currIdxSubMenu);
for (int i=0; i<5+crv.points; i++)
points[i] = 0;
if (crv.type == CURVE_TYPE_CUSTOM) {
@@ -105,11 +105,11 @@ enum MenuModelCurveOneItems {
bool menuModelCurveOne(event_t event)
{
static uint8_t pointsOfs = 0;
- CurveData & crv = g_model.curves[s_curveChan];
- int8_t * points = curveAddress(s_curveChan);
+ CurveData & crv = g_model.curves[s_currIdxSubMenu];
+ int8_t * points = curveAddress(s_currIdxSubMenu);
SUBMENU_WITH_OPTIONS(STR_MENUCURVE, ICON_MODEL_CURVES, IS_COORDS1_LINE_NEEDED() ? 6 : 5, OPTION_MENU_NO_FOOTER, { 0, 0, 0, 0, uint8_t(5+crv.points-1), uint8_t(5+crv.points-1) });
- drawStringWithIndex(50, 3+FH, STR_CV, s_curveChan+1, MENU_TITLE_COLOR);
+ drawStringWithIndex(50, 3+FH, STR_CV, s_currIdxSubMenu+1, MENU_TITLE_COLOR);
lcdDrawSolidFilledRect(0, MENU_FOOTER_TOP, 250, MENU_FOOTER_HEIGHT, HEADER_BGCOLOR);
if (IS_COORDS1_LINE_NEEDED() && menuVerticalPosition == ITEM_CURVE_COORDS1) {
@@ -133,15 +133,15 @@ bool menuModelCurveOne(event_t event)
// Curve type
LcdFlags attr = (menuVerticalPosition==ITEM_CURVE_TYPE ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0);
- lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, "Type");
+ lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, STR_TYPE);
lcdDrawTextAtIndex(MODEL_CURVE_ONE_2ND_COLUMN, MENU_CONTENT_TOP, STR_CURVE_TYPES, crv.type, attr);
if (attr) {
uint8_t newType = checkIncDecModelZero(event, crv.type, CURVE_TYPE_LAST);
if (newType != crv.type) {
for (int i = 1; i < 4 + crv.points; i++) {
- points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i * 200 / (4 + crv.points)), s_curveChan));
+ points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i * 200 / (4 + crv.points)), s_currIdxSubMenu));
}
- if (moveCurve(s_curveChan, checkIncDec_Ret > 0 ? 3 + crv.points : -3 - crv.points)) {
+ if (moveCurve(s_currIdxSubMenu, checkIncDec_Ret > 0 ? 3 + crv.points : -3 - crv.points)) {
if (newType == CURVE_TYPE_CUSTOM) {
resetCustomCurveX(points, 5 + crv.points);
}
@@ -155,14 +155,17 @@ bool menuModelCurveOne(event_t event)
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + FH, STR_COUNT);
lcdDrawNumber(MODEL_CURVE_ONE_2ND_COLUMN, MENU_CONTENT_TOP + FH, 5+crv.points, LEFT|attr, 0, NULL, STR_PTS);
if (attr) {
+#if defined(ROTARY_ENCODER_NAVIGATION)
+ rotencSpeed = ROTENC_LOWSPEED;
+#endif
int count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts
if (checkIncDec_Ret) {
int newPoints[MAX_POINTS_PER_CURVE];
newPoints[0] = points[0];
newPoints[4+count] = points[4+crv.points];
for (int i=1; i<4+count; i++)
- newPoints[i] = calcRESXto100(applyCustomCurve(-RESX + (i * 2 * RESX) / (4 + count), s_curveChan));
- if (moveCurve(s_curveChan, checkIncDec_Ret*(crv.type==CURVE_TYPE_CUSTOM ? 2 :1))) {
+ newPoints[i] = calcRESXto100(applyCustomCurve(-RESX + (i * 2 * RESX) / (4 + count), s_currIdxSubMenu));
+ if (moveCurve(s_currIdxSubMenu, checkIncDec_Ret*(crv.type==CURVE_TYPE_CUSTOM ? 2 :1))) {
for (int i = 0; i < 5 + count; i++) {
points[i] = newPoints[i];
if (crv.type == CURVE_TYPE_CUSTOM && i != 0 && i != 4 + count)
@@ -298,7 +301,7 @@ void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlag
drawCurveName(lcdNextPos+10, y, curve.value, (menuHorizontalPosition==1 ? attr : 0));
if (attr && menuHorizontalPosition==1) {
if (event==EVT_KEY_LONG(KEY_ENTER) && curve.value!=0) {
- s_curveChan = (curve.value<0 ? -curve.value-1 : curve.value-1);
+ s_currIdxSubMenu = (curve.value<0 ? -curve.value-1 : curve.value-1);
pushMenu(menuModelCurveOne);
}
else {
@@ -316,7 +319,7 @@ bool menuModelCurvesAll(event_t event)
{
SIMPLE_MENU(STR_MENUCURVES, MODEL_ICONS, menuTabModel, MENU_MODEL_CURVES, MAX_CURVES);
- s_curveChan = menuVerticalPosition;
+ s_currIdxSubMenu = menuVerticalPosition;
switch (event) {
case EVT_KEY_BREAK(KEY_ENTER):
diff --git a/radio/src/gui/480x272/model_failsafe.cpp b/radio/src/gui/480x272/model_failsafe.cpp
index 269cfad75..706c36f4b 100644
--- a/radio/src/gui/480x272/model_failsafe.cpp
+++ b/radio/src/gui/480x272/model_failsafe.cpp
@@ -60,7 +60,7 @@ bool menuModelFailsafe(event_t event)
}
SIMPLE_SUBMENU_WITH_OPTIONS("FAILSAFE", ICON_STATS_ANALOGS, sentModuleChannels(g_moduleIdx)+1, OPTION_MENU_NO_SCROLLBAR);
- drawStringWithIndex(50, 3+FH, "Module", g_moduleIdx+1, MENU_TITLE_COLOR);
+ drawStringWithIndex(50, 3+FH, STR_MODULE, g_moduleIdx+1, MENU_TITLE_COLOR);
for (uint8_t col=0; col < cols; col++) {
for (uint8_t line=0; line < 8; line++) {
diff --git a/radio/src/gui/480x272/model_mixes.cpp b/radio/src/gui/480x272/model_mixes.cpp
index 0f98dc9d9..da1b74f78 100644
--- a/radio/src/gui/480x272/model_mixes.cpp
+++ b/radio/src/gui/480x272/model_mixes.cpp
@@ -607,6 +607,8 @@ bool menuModelMixAll(event_t event)
if (!s_copyMode) {
attr = INVERS;
}
+ if (g_model.limitData[ch-1].name[0] != '\0')
+ lcdDrawSizedText(MENUS_MARGIN_LEFT, MENU_FOOTER_TOP, g_model.limitData[ch-1].name, sizeof(g_model.limitData[ch-1].name), MENU_TITLE_COLOR | LEFT | ZCHAR);
}
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
putsChn(MENUS_MARGIN_LEFT, y, ch, attr); // show CHx
diff --git a/radio/src/gui/480x272/model_outputs.cpp b/radio/src/gui/480x272/model_outputs.cpp
index af5128fd7..300f8909b 100644
--- a/radio/src/gui/480x272/model_outputs.cpp
+++ b/radio/src/gui/480x272/model_outputs.cpp
@@ -80,6 +80,9 @@ void onLimitsMenu(const char *result)
copyTrimsToOffset(ch);
storageDirty(EE_MODEL);
}
+ else if (result == STR_COPY_MIN_MAX_TO_OUTPUTS) {
+ copyMinMaxToOutputs(ch);
+ }
}
bool menuModelLimits(event_t event)
@@ -133,6 +136,7 @@ bool menuModelLimits(event_t event)
POPUP_MENU_ADD_ITEM(STR_RESET);
POPUP_MENU_ADD_ITEM(STR_COPY_TRIMS_TO_OFS);
POPUP_MENU_ADD_ITEM(STR_COPY_STICKS_TO_OFS);
+ POPUP_MENU_ADD_ITEM(STR_COPY_MIN_MAX_TO_OUTPUTS);
POPUP_MENU_START(onLimitsMenu);
}
@@ -197,7 +201,7 @@ bool menuModelLimits(event_t event)
case ITEM_LIMITS_CURVE:
drawCurveName(LIMITS_CURVE_POS, y, ld->curve, attr);
if (attr && event==EVT_KEY_LONG(KEY_ENTER) && ld->curve>0) {
- s_curveChan = (ld->curve<0 ? -ld->curve-1 : ld->curve-1);
+ s_currIdxSubMenu = (ld->curve<0 ? -ld->curve-1 : ld->curve-1);
pushMenu(menuModelCurveOne);
}
if (active) {
diff --git a/radio/src/gui/480x272/model_receiver_options.cpp b/radio/src/gui/480x272/model_receiver_options.cpp
index b1ab35036..90db6f7e3 100644
--- a/radio/src/gui/480x272/model_receiver_options.cpp
+++ b/radio/src/gui/480x272/model_receiver_options.cpp
@@ -46,14 +46,18 @@ void onRxOptionsUpdateConfirm(const char * result)
enum {
ITEM_RECEIVER_SETTINGS_PWM_RATE,
ITEM_RECEIVER_SETTINGS_TELEMETRY,
+ ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW,
ITEM_RECEIVER_SETTINGS_SPORT_FPORT,
ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1,
ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED2,
ITEM_RECEIVER_SETTINGS_PINMAP_FIRST
};
+#define IS_RECEIVER_CAPABILITY_ENABLED(capability) (reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilities & (1 << capability))
+#define IF_RECEIVER_CAPABILITY(capability, count) uint8_t(IS_RECEIVER_CAPABILITY_ENABLED(capability) ? count : HIDDEN_ROW)
-#define IF_RECEIVER_CAPABILITY(capability, count) uint8_t((reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilities & (1 << capability)) ? count : HIDDEN_ROW)
+#define CH_ENABLE_SPORT 4
+#define CH_ENABLE_SBUS 5
bool menuModelReceiverOptions(event_t event)
{
@@ -76,6 +80,7 @@ bool menuModelReceiverOptions(event_t event)
SUBMENU(STR_RECEIVER_OPTIONS, ICON_MODEL_SETUP, ITEM_RECEIVER_SETTINGS_PINMAP_FIRST + outputsCount, {
0, // PWM rate
isModuleR9MAccess(g_moduleIdx) && receiverVariant == PXX2_VARIANT_EU && reusableBuffer.hardwareAndSettings.moduleSettings.txPower > 14 /*25mW*/ ? READONLY_ROW : (uint8_t)0, // Telemetry
+ IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_TELEMETRY_25MW, 0),
IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_FPORT, 0),
uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW),
uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW),
@@ -156,6 +161,14 @@ bool menuModelReceiverOptions(event_t event)
}
break;
+ case ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW:
+ lcdDrawText(MENUS_MARGIN_LEFT, y, "25mw Tele");
+ reusableBuffer.hardwareAndSettings.receiverSettings.telemetry25mw = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.telemetry25mw, RECEIVER_OPTIONS_2ND_COLUMN, y, attr, event);
+ if (attr && checkIncDec_Ret) {
+ reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY;
+ }
+ break;
+
case ITEM_RECEIVER_SETTINGS_SPORT_FPORT:
lcdDrawText(MENUS_MARGIN_LEFT, y, "F.Port");
reusableBuffer.hardwareAndSettings.receiverSettings.fport = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.fport, RECEIVER_OPTIONS_2ND_COLUMN, y, attr, event);
@@ -182,21 +195,43 @@ bool menuModelReceiverOptions(event_t event)
int32_t channelValue = channelOutputs[channel];
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_PIN);
lcdDrawNumber(lcdNextPos + 1, y, pin + 1);
- putsChn(100, y, channel + 1, attr);
+
+ uint8_t channelMax = sentModuleChannels(g_moduleIdx) - 1;
+ uint8_t selectionMax = channelMax;
+
+ if (IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6)) {
+ if (CH_ENABLE_SPORT == pin || CH_ENABLE_SBUS == pin) {
+ selectionMax += 1;
+ }
+ if (CH_ENABLE_SPORT == pin && selectionMax == channel) {
+ lcdDrawText(100, y, "S.PORT", attr);
+ }
+ else if (CH_ENABLE_SBUS == pin && selectionMax == channel) {
+ lcdDrawText(100, y, "SBUS", attr);
+ }
+ else {
+ putsChn(100, y, channel + 1, attr);
+ }
+ }
+ else {
+ putsChn(100, y, channel + 1, attr);
+ }
// Channel
if (attr) {
- mapping = checkIncDec(event, mapping, 0, sentModuleChannels(g_moduleIdx) - 1);
+ mapping = checkIncDec(event, mapping, 0, selectionMax);
if (checkIncDec_Ret) {
reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY;
}
}
// Bargraph
- lcdDrawRect(RECEIVER_OPTIONS_2ND_COLUMN, y + 4, wbar + 1, 10);
- const uint8_t lenChannel = limit(1, (abs(channelValue) * wbar / 2 + lim / 2) / lim, wbar / 2);
- const coord_t xChannel = (channelValue > 0) ? RECEIVER_OPTIONS_2ND_COLUMN + wbar / 2 : RECEIVER_OPTIONS_2ND_COLUMN + wbar / 2 + 1 - lenChannel;
- lcdDrawSolidFilledRect(xChannel, y + 5, lenChannel, 8, TEXT_INVERTED_BGCOLOR);
+ if (channel <= channelMax) {
+ lcdDrawRect(RECEIVER_OPTIONS_2ND_COLUMN, y + 4, wbar + 1, 10);
+ auto lenChannel = limit(1, (abs(channelValue) * wbar / 2 + lim / 2) / lim, wbar / 2);
+ auto xChannel = (channelValue > 0) ? RECEIVER_OPTIONS_2ND_COLUMN + wbar / 2 : RECEIVER_OPTIONS_2ND_COLUMN + wbar / 2 + 1 - lenChannel;
+ lcdDrawSolidFilledRect(xChannel, y + 5, lenChannel, 8, TEXT_INVERTED_BGCOLOR);
+ }
}
break;
}
diff --git a/radio/src/gui/480x272/model_select.cpp b/radio/src/gui/480x272/model_select.cpp
index 5f6615041..36dac8ba8 100644
--- a/radio/src/gui/480x272/model_select.cpp
+++ b/radio/src/gui/480x272/model_select.cpp
@@ -62,7 +62,7 @@ void drawModel(coord_t x, coord_t y, ModelCell * model, bool current, bool selec
if (selected) {
lcdDrawSolidRect(x, y, MODELCELL_WIDTH+2, MODELCELL_HEIGHT+2, 1, TITLE_BGCOLOR);
drawShadow(x, y, MODELCELL_WIDTH+2, MODELCELL_HEIGHT+2);
- if (selectMode == MODE_MOVE_MODEL) {
+ if (selectMode == MODE_MOVE_MODEL && modelselModelMoveBackground) {
lcd->drawMask(x+MODELCELL_WIDTH+2-modelselModelMoveBackground->getWidth(), y, modelselModelMoveBackground, TITLE_BGCOLOR);
lcd->drawMask(x+MODELCELL_WIDTH+2-modelselModelMoveBackground->getWidth()+12, y+5, modelselModelMoveIcon, TEXT_BGCOLOR);
}
@@ -95,11 +95,10 @@ void setCurrentCategory(unsigned int index)
if (currentCategory->size() > 0)
setCurrentModel(0);
else
- currentModel = NULL;
+ currentModel = nullptr;
}
#if defined(LUA)
-
#define MAX_WIZARD_NAME_LEN (sizeof(WIZARD_PATH)+20)
#define WIZARD_SPACING 40
#define WIZARD_LEFT_SPACING 30
@@ -248,6 +247,7 @@ void onModelSelectMenu(const char * result)
storageCheck(true);
memcpy(g_eeGeneral.currModelFilename, currentModel->modelFilename, LEN_MODEL_FILENAME);
modelslist.setCurrentModel(currentModel);
+ modelslist.setCurrentCategory(currentCategory);
loadModel(g_eeGeneral.currModelFilename, true);
storageDirty(EE_GENERAL);
storageCheck(true);
@@ -264,6 +264,7 @@ void onModelSelectMenu(const char * result)
selectMode = MODE_SELECT_MODEL;
setCurrentModel(currentCategory->size() - 1);
modelslist.setCurrentModel(currentModel);
+ modelslist.setCurrentCategory(currentCategory);
modelslist.onNewModelCreated(currentModel, &g_model);
#if defined(LUA)
chainMenu(menuModelWizard);
@@ -274,12 +275,12 @@ void onModelSelectMenu(const char * result)
memcpy(duplicatedFilename, currentModel->modelFilename, sizeof(duplicatedFilename));
if (findNextFileIndex(duplicatedFilename, LEN_MODEL_FILENAME, MODELS_PATH)) {
sdCopyFile(currentModel->modelFilename, MODELS_PATH, duplicatedFilename, MODELS_PATH);
- ModelCell* dup_model = modelslist.addModel(currentCategory, duplicatedFilename);
+ ModelCell * dup_model = modelslist.addModel(currentCategory, duplicatedFilename);
dup_model->fetchRfData();
setCurrentModel(currentCategory->size() - 1);
}
else {
- POPUP_WARNING("Invalid File");
+ POPUP_WARNING(STR_INVALID_FILE);
}
}
else if (result == STR_MOVE_MODEL) {
@@ -344,7 +345,7 @@ void initModelsList()
bool menuModelSelect(event_t event)
{
const std::list& cats = modelslist.getCategories();
- switch(event) {
+ switch (event) {
case 0:
// no need to refresh the screen
return false;
@@ -387,7 +388,7 @@ bool menuModelSelect(event_t event)
categoriesVerticalPosition -= 1;
setCurrentCategory(categoriesVerticalPosition);
modelslist.moveModel(model, previous_category, currentCategory);
- setCurrentModel(currentCategory->size()-1);
+ setCurrentModel(currentCategory->size() - 1);
}
killEvents(event);
break;
diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp
index 93fed1953..556b1f2bf 100644
--- a/radio/src/gui/480x272/model_setup.cpp
+++ b/radio/src/gui/480x272/model_setup.cpp
@@ -98,15 +98,24 @@ enum MenuModelSetupItems {
#if defined(MULTIMODULE)
ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS,
+#endif
+#if defined(AFHDS3)
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS,
#endif
ITEM_MODEL_SETUP_EXTERNAL_MODULE_CHANNELS,
- ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_BIND,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_MODEL_NUM,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_OPTIONS,
#if defined(MULTIMODULE)
ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING,
+#endif
+#if defined(AFHDS3)
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ,
+ ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER,
#endif
ITEM_MODEL_SETUP_EXTERNAL_MODULE_POWER,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE,
@@ -115,7 +124,6 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_1,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_2,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_3,
-
ITEM_MODEL_SETUP_TRAINER_LABEL,
ITEM_MODEL_SETUP_TRAINER_MODE,
#if defined(BLUETOOTH)
@@ -129,8 +137,6 @@ enum MenuModelSetupItems {
#define MODEL_SETUP_2ND_COLUMN 200
#define MODEL_SETUP_3RD_COLUMN 270
#define MODEL_SETUP_4TH_COLUMN 350
-#define MODEL_SETUP_BIND_OFS 40
-#define MODEL_SETUP_RANGE_OFS 80
#define MODEL_SETUP_SET_FAILSAFE_OFS 100
#define MODEL_SETUP_SLIDPOT_SPACING 45
@@ -158,6 +164,10 @@ void onBluetoothConnectMenu(const char * result)
#include "common/stdlcd/model_setup_pxx1.cpp"
+#if defined(AFHDS3)
+#include "common/stdlcd/model_setup_afhds3.cpp"
+#endif
+
void onPXX2R9MBindModeMenu(const char * result)
{
if (result == STR_16CH_WITH_TELEMETRY) {
@@ -352,10 +362,10 @@ void runPopupRegister(event_t event)
// loop index (will be removed in future)
lcdDrawText(REGISTER_COLUMN_1, REGISTER_TOP + 8 + FH, "UID");
- lcdDrawNumber(REGISTER_COLUMN_2, REGISTER_TOP + 8 + FH, reusableBuffer.moduleSetup.pxx2.registerLoopIndex, menuVerticalPosition == ITEM_REGISTER_MODULE_INDEX ? (s_editMode ? INVERS + BLINK : INVERS) : 0);
if (menuVerticalPosition == ITEM_REGISTER_MODULE_INDEX && s_editMode) {
CHECK_INCDEC_MODELVAR_ZERO(event, reusableBuffer.moduleSetup.pxx2.registerLoopIndex, 2);
}
+ lcdDrawNumber(REGISTER_COLUMN_2, REGISTER_TOP + 8 + FH, reusableBuffer.moduleSetup.pxx2.registerLoopIndex, menuVerticalPosition == ITEM_REGISTER_MODULE_INDEX ? (s_editMode ? INVERS : INVERS) : 0);
// RX name
if (reusableBuffer.moduleSetup.pxx2.registerStep < REGISTER_RX_NAME_RECEIVED) {
@@ -397,7 +407,7 @@ void checkModelIdUnique(uint8_t moduleIdx)
// cannot rely exactly on WARNING_LINE_LEN so using WARNING_LINE_LEN-2
size_t warn_buf_len = sizeof(reusableBuffer.moduleSetup.msg) - WARNING_LINE_LEN - 2;
- if (!modelslist.isModelIdUnique(moduleIdx,warn_buf,warn_buf_len)) {
+ if (!modelslist.isModelIdUnique(moduleIdx, warn_buf, warn_buf_len)) {
if (warn_buf[0] != 0) {
POPUP_WARNING(STR_MODELIDUSED);
SET_WARNING_INFO(warn_buf, sizeof(reusableBuffer.moduleSetup.msg), 0);
@@ -504,7 +514,7 @@ int getSwitchWarningsCount()
inline uint8_t MODULE_TYPE_ROWS(int moduleIdx)
{
- if (isModuleXJT(moduleIdx) || isModuleR9MNonAccess(moduleIdx) || isModuleDSM2(moduleIdx) || isModulePXX2(moduleIdx))
+ if (isModuleXJT(moduleIdx) || isModuleR9MNonAccess(moduleIdx) || isModuleDSM2(moduleIdx) || isModulePXX2(moduleIdx) || isModuleAFHDS3(moduleIdx))
return 1;
#if defined(MULTIMODULE)
else if (isModuleMultimodule(moduleIdx)) {
@@ -525,7 +535,6 @@ inline uint8_t MODULE_TYPE_ROWS(int moduleIdx)
#if defined(BLUETOOTH)
#define TRAINER_CHANNELS_ROW (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)1 : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? (uint8_t)0 : HIDDEN_ROW))
-#define TRAINER_PPM_PARAMS_ROW (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW)
#define IF_BT_TRAINER_ON(x) (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER ? (uint8_t)(x) : HIDDEN_ROW)
#define TRAINER_BLUETOOTH_M_ROW ((bluetooth.distantAddr[0] == '\0' || bluetooth.state == BLUETOOTH_STATE_CONNECTED) ? (uint8_t)0 : (uint8_t)1)
#define TRAINER_BLUETOOTH_S_ROW (bluetooth.distantAddr[0] == '\0' ? HIDDEN_ROW : LABEL())
@@ -533,9 +542,9 @@ inline uint8_t MODULE_TYPE_ROWS(int moduleIdx)
#define TRAINER_ROWS LABEL(Trainer), 0, IF_BT_TRAINER_ON(TRAINER_BLUETOOTH_ROW), TRAINER_CHANNELS_ROW, TRAINER_PPM_PARAMS_ROW
#else
#define TRAINER_CHANNELS_ROW (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)1 : HIDDEN_ROW)
-#define TRAINER_PPM_PARAMS_ROW (HIDDEN_ROW)
#define TRAINER_ROWS LABEL(Trainer), 0, TRAINER_CHANNELS_ROW, TRAINER_PPM_PARAMS_ROW
#endif
+#define TRAINER_PPM_PARAMS_ROW (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW)
#if defined(PXX2)
#define REGISTRATION_ID_ROWS uint8_t((isDefaultModelRegistrationID() || (warningText && popupFunc == runPopupRegister)) ? HIDDEN_ROW : READONLY_ROW),
@@ -624,11 +633,13 @@ bool menuModelSetup(event_t event)
LABEL(ExternalModule),
MODULE_TYPE_ROWS(EXTERNAL_MODULE),
MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE)
+ AFHDS3_MODE_ROWS(EXTERNAL_MODULE)
MODULE_CHANNELS_ROWS(EXTERNAL_MODULE),
IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)),
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum for ACCESS
IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)),
MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE)
+ AFHDS3_MODULE_ROWS(EXTERNAL_MODULE)
MODULE_POWER_ROW(EXTERNAL_MODULE),
FAILSAFE_ROWS(EXTERNAL_MODULE),
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons
@@ -788,7 +799,7 @@ bool menuModelSetup(event_t event)
case ITEM_MODEL_SETUP_DISPLAY_TRIMS:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_DISPLAY_TRIMS);
- g_model.displayTrims = editChoice(MODEL_SETUP_2ND_COLUMN, y, "\006No\0 ChangeYes", g_model.displayTrims, 0, 2, attr, event);
+ g_model.displayTrims = editChoice(MODEL_SETUP_2ND_COLUMN, y, STR_VDISPLAYTRIMS, g_model.displayTrims, 0, 2, attr, event);
break;
case ITEM_MODEL_SETUP_TRIM_INC:
@@ -1030,6 +1041,7 @@ bool menuModelSetup(event_t event)
}
else if (isModulePXX2(INTERNAL_MODULE)) {
g_model.moduleData[INTERNAL_MODULE].subType = checkIncDec(event, g_model.moduleData[INTERNAL_MODULE].subType, 0, MODULE_SUBTYPE_ISRM_PXX2_ACCST_D16, EE_MODEL);
+ resetAccessAuthenticationCount();
}
}
break;
@@ -1075,6 +1087,11 @@ bool menuModelSetup(event_t event)
if (MULTIMODULE_HAS_SUBTYPE(moduleIdx))
lcdDrawMultiSubProtocolString(MODEL_SETUP_4TH_COLUMN, y, moduleIdx, g_model.moduleData[moduleIdx].subType, menuHorizontalPosition==2 ? attr : 0);
}
+#endif
+#if defined(AFHDS3)
+ else if (isModuleAFHDS3(moduleIdx)) {
+ lcdDrawTextAtIndex(lcdNextPos + 15, y, STR_AFHDS3_PROTOCOLS, g_model.moduleData[moduleIdx].subType, (menuHorizontalPosition==1 ? attr : 0));
+ }
#endif
if (attr && menuHorizontalPosition == 0 && moduleIdx == EXTERNAL_MODULE) {
if (s_editMode > 0) {
@@ -1111,13 +1128,32 @@ bool menuModelSetup(event_t event)
if (isModuleDSM2(moduleIdx))
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX);
#if defined(MULTIMODULE)
- else if (isModuleMultimodule(moduleIdx)) {
+ else if (isModuleMultimodule(moduleIdx)) {
int multiRfProto = g_model.moduleData[moduleIdx].getMultiProtocol();
- CHECK_INCDEC_MODELVAR_CHECK(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MULTI_MAX_PROTOCOLS, isMultiProtocolSelectable);
+ MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
+ if (status.isValid()) {
+ int8_t direction = checkIncDec(event, 0, -1, 1);
+ if (direction == -1) {
+ if (multiRfProto == MODULE_SUBTYPE_MULTI_FRSKY)
+ multiRfProto = MODULE_SUBTYPE_MULTI_FRSKYX_RX;
+ else
+ multiRfProto = convertMultiToOtx(status.protocolPrev);
+ }
+ if (direction == 1) {
+ if (multiRfProto == MODULE_SUBTYPE_MULTI_FRSKY)
+ multiRfProto = MODULE_SUBTYPE_MULTI_FRSKYX2;
+ else
+ multiRfProto = convertMultiToOtx(status.protocolNext);
+ }
+ }
+ else {
+ CHECK_INCDEC_MODELVAR_CHECK(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MULTI_MAX_PROTOCOLS, isMultiProtocolSelectable);
+ }
if (checkIncDec_Ret) {
g_model.moduleData[moduleIdx].setMultiProtocol(multiRfProto);
g_model.moduleData[moduleIdx].subType = 0;
resetMultiProtocolsOptions(moduleIdx);
+ storageDirty(EE_MODEL);
}
}
#endif
@@ -1125,6 +1161,11 @@ bool menuModelSetup(event_t event)
g_model.moduleData[moduleIdx].subType = checkIncDec(event, g_model.moduleData[moduleIdx].subType, MODULE_SUBTYPE_R9M_FCC,
MODULE_SUBTYPE_R9M_LAST, EE_MODEL, isR9MModeAvailable);
}
+#if defined(AFHDS3)
+ else if (isModuleAFHDS3(moduleIdx)) {
+ CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].subType, AFHDS_SUBTYPE_FIRST, AFHDS_SUBTYPE_LAST);
+ }
+#endif
else {
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].subType, MODULE_SUBTYPE_PXX1_ACCST_D16, MODULE_SUBTYPE_PXX1_LAST);
}
@@ -1328,6 +1369,7 @@ bool menuModelSetup(event_t event)
}
}
break;
+
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_REGISTER_RANGE:
#endif
@@ -1335,7 +1377,8 @@ bool menuModelSetup(event_t event)
{
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_MODULE);
drawButton(MODEL_SETUP_2ND_COLUMN, y, STR_REGISTER, (menuHorizontalPosition == 0 ? attr : 0));
- drawButton(MODEL_SETUP_2ND_COLUMN + MODEL_SETUP_SET_FAILSAFE_OFS, y, STR_MODULE_RANGE, (menuHorizontalPosition == 1 ? attr : 0));
+ if (isModuleRangeAvailable(moduleIdx))
+ drawButton(MODEL_SETUP_2ND_COLUMN + MODEL_SETUP_SET_FAILSAFE_OFS, y, STR_MODULE_RANGE, (menuHorizontalPosition == 1 ? attr : 0));
if (attr) {
if (moduleState[moduleIdx].mode == MODULE_MODE_NORMAL && s_editMode > 0) {
if (menuHorizontalPosition == 0 && event == EVT_KEY_BREAK(KEY_ENTER)) {
@@ -1353,8 +1396,9 @@ bool menuModelSetup(event_t event)
s_editMode = 0;
}
}
- }
break;
+ }
+
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_OPTIONS:
#endif
@@ -1366,6 +1410,7 @@ bool menuModelSetup(event_t event)
pushMenu(menuModelModuleOptions);
}
break;
+
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1:
case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_2:
@@ -1434,7 +1479,7 @@ bool menuModelSetup(event_t event)
for (auto rx = 0; rx < popupMenuItemsCount; rx++) {
popupMenuItems[rx] = reusableBuffer.moduleSetup.bindInformation.candidateReceiversNames[rx];
}
- // popupMenuTitle = STR_PXX2_SELECT_RX;
+ POPUP_MENU_TITLE(STR_PXX2_SELECT_RX);
POPUP_MENU_START(onPXX2BindMenu);
}
}
@@ -1450,10 +1495,11 @@ bool menuModelSetup(event_t event)
}
}
break;
+
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE:
#endif
- case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_BIND:
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE:
{
ModuleData & moduleData = g_model.moduleData[moduleIdx];
if (isModulePPM(moduleIdx)) {
@@ -1479,7 +1525,6 @@ bool menuModelSetup(event_t event)
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_REFRESHRATE);
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)moduleData.ppm.frameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT, 0, NULL, STR_MS);
lcdDrawText(MODEL_SETUP_3RD_COLUMN, y, moduleData.sbus.noninverted ? "not inverted" : "normal", (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0);
-
if (attr && s_editMode>0) {
switch (menuHorizontalPosition) {
case 0:
@@ -1492,21 +1537,19 @@ bool menuModelSetup(event_t event)
}
}
else {
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_RECEIVER);
int l_posHorz = menuHorizontalPosition;
- coord_t xOffsetBind = MODEL_SETUP_BIND_OFS;
- if (!isModuleRxNumAvailable(moduleIdx)) {
- xOffsetBind = 0;
- lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_RECEIVER);
- if (attr) l_posHorz += 1;
+ coord_t bindButtonPos = MODEL_SETUP_2ND_COLUMN;
+ if (isModuleRxNumAvailable(moduleIdx)) {
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0 | LEFT, 2);
+ bindButtonPos += 40;
}
- else {
- lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_RECEIVER_NUM);
+ else if (attr) {
+ l_posHorz += 1;
}
if (isModuleBindRangeAvailable(moduleIdx)) {
- if (xOffsetBind)
- lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0 | LEFT, 2);
- if (attr && l_posHorz==0) {
- if (s_editMode>0) {
+ if (attr && l_posHorz == 0) {
+ if (s_editMode > 0) {
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], getMaxRxNum(moduleIdx));
if (event == EVT_KEY_LONG(KEY_ENTER)) {
killEvents(event);
@@ -1518,8 +1561,10 @@ bool menuModelSetup(event_t event)
}
}
}
- drawButton(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, (moduleState[moduleIdx].mode == MODULE_MODE_BIND ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==1 ? attr : 0));
- drawButton(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==2 ? attr : 0));
+ drawButton(bindButtonPos, y, STR_MODULE_BIND, (moduleState[moduleIdx].mode == MODULE_MODE_BIND ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==1 ? attr : 0));
+ if (isModuleRangeAvailable(moduleIdx)) {
+ drawButton(bindButtonPos + 80, y, STR_MODULE_RANGE, (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==2 ? attr : 0));
+ }
uint8_t newFlag = 0;
#if defined(MULTIMODULE)
if (getMultiBindStatus(moduleIdx) == MULTI_BIND_FINISHED) {
@@ -1530,8 +1575,14 @@ bool menuModelSetup(event_t event)
if (attr && l_posHorz>0) {
if (s_editMode>0) {
if (l_posHorz == 1) {
- if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx)) {
+ if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx) || isModuleAFHDS3(moduleIdx) || IS_R9_MULTI(moduleIdx)) {
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
+#if defined(AFHDS3)
+ if (isModuleAFHDS3(moduleIdx)) {
+ startBindMenuAfhds3(moduleIdx);
+ continue;
+ }
+#endif
startBindMenu(moduleIdx);
continue;
}
@@ -1613,31 +1664,53 @@ bool menuModelSetup(event_t event)
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
int optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
+ MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
- if (multi_proto < MODULE_SUBTYPE_MULTI_LAST) {
+ if (status.isValid()) {
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
+ if (attr && status.optionDisp == 2) {
+ lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")");
+ }
+ }
+ else {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
if (pdef->optionsstr) {
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, pdef->optionsstr);
- if (attr && pdef->optionsstr == STR_MULTI_RFTUNE) {
+ if (attr && pdef->optionsstr == STR_MULTI_RFTUNE) {
lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")");
}
}
}
- else {
- MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
- lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
- if (attr && status.optionDisp == 2) {
- lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")");
- }
- }
- if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A)
- optionValue = 50 + 5 * optionValue;
- lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
+ int8_t min, max;
+ getMultiOptionValues(multi_proto, min, max);
+
+ if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
+ }
+ else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) {
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
+ }
+ else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
+ optionValue = optionValue & 0x01;
+ editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, LEFT | attr, event);
+ }
+ else {
+ if (min == 0 && max == 1)
+ editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, LEFT | attr, event);
+ else
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
+ }
if (attr) {
- int8_t min, max;
- getMultiOptionValues(multi_proto, min, max);
- CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, min, max);
+ CHECK_INCDEC_MODELVAR(event, optionValue, min, max);
+ if (checkIncDec_Ret) {
+ if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
+ g_model.moduleData[moduleIdx].multi.optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0xFE) + optionValue;
+ }
+ else {
+ g_model.moduleData[moduleIdx].multi.optionValue = optionValue;
+ }
+ }
}
}
#endif
@@ -1649,8 +1722,12 @@ bool menuModelSetup(event_t event)
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_MODULE_TELEM_ON);
}
else if (isModuleSBUS(moduleIdx)) {
+#if defined(RADIO_TX16S) // TX16S has 5v output on CPPM pin
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_WARN_5VOLTS);
+#else
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_WARN_BATTVOLTAGE);
drawValueWithUnit(MODEL_SETUP_4TH_COLUMN, y, getBatteryVoltage(), UNIT_VOLTS, attr|PREC2|LEFT);
+#endif
}
break;
}
@@ -1681,9 +1758,17 @@ bool menuModelSetup(event_t event)
}
#if defined(MULTIMODULE)
else if (isModuleMultimodule(moduleIdx)) {
- lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MULTI_LOWPOWER);
+ lcdDrawText(MENUS_MARGIN_LEFT, y, IS_RX_MULTI(moduleIdx) ? STR_MULTI_LNA_DISABLE : STR_MULTI_LOWPOWER);
g_model.moduleData[moduleIdx].multi.lowPowerMode = editCheckBox(g_model.moduleData[moduleIdx].multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, attr, event);
}
+#endif
+#if defined(AFHDS3)
+ else if (isModuleAFHDS3(moduleIdx)) {
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_RFPOWER);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, g_model.moduleData[moduleIdx].afhds3.runPower, LEFT | attr);
+ if (attr)
+ CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].afhds3.runPower, afhds3::RUN_POWER::RUN_POWER_FIRST, afhds3::RUN_POWER::RUN_POWER_LAST);
+ }
#endif
}
break;
@@ -1693,13 +1778,22 @@ bool menuModelSetup(event_t event)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND:
#endif
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND:
- if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2)
- lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MULTI_DSM_AUTODTECT);
- else
+ if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) {
+ int8_t value = (g_model.moduleData[moduleIdx].multi.optionValue & 0x02) >> 1;
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_MULTI_SERVOFREQ);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, value ? 11 : 22, attr, 0, "", "ms");
+ if (attr) {
+ CHECK_INCDEC_MODELVAR(event, value, 0, 1);
+ if (checkIncDec_Ret) {
+ g_model.moduleData[moduleIdx].multi.optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0xFD) + (value << 1);
+ }
+ }
+ }
+ else {
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MULTI_AUTOBIND);
- g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, attr, event);
+ g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, attr, event);
+ }
break;
-
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_TELEM:
#endif
@@ -1707,7 +1801,6 @@ bool menuModelSetup(event_t event)
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_DISABLE_TELEM);
g_model.moduleData[moduleIdx].multi.disableTelemetry = editCheckBox(g_model.moduleData[moduleIdx].multi.disableTelemetry, MODEL_SETUP_2ND_COLUMN, y, attr, event);
break;
-
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_MAPPING:
#endif
@@ -1715,29 +1808,69 @@ bool menuModelSetup(event_t event)
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_DISABLE_CH_MAP);
g_model.moduleData[moduleIdx].multi.disableMapping = editCheckBox(g_model.moduleData[moduleIdx].multi.disableMapping, MODEL_SETUP_2ND_COLUMN, y, attr, event);
break;
+#endif
-#if defined(HARDWARE_INTERNAL_MODULE)
+#if defined(AFHDS3)
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE:
+ lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TYPE);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y,
+ g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry ? STR_AFHDS3_ONE_TO_ONE_TELEMETRY : TR_AFHDS3_ONE_TO_MANY);
+ break;
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ:
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_AFHDS3_RX_FREQ);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.moduleData[moduleIdx].afhds3.rxFreq(), attr | LEFT, 0, NULL, "Hz");
+ if (attr) {
+ uint16_t rxFreq = g_model.moduleData[moduleIdx].afhds3.rxFreq();
+ CHECK_INCDEC_MODELVAR(event, rxFreq, MIN_FREQ, MAX_FREQ);
+ g_model.moduleData[moduleIdx].afhds3.setRxFreq(rxFreq);
+ }
+ break;
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER:
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_AFHDS3_ACTUAL_POWER);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_POWERS, actualAfhdsRunPower(moduleIdx), LEFT);
+ break;
+#endif
+
+#if defined(MULTIMODULE) || defined(AFHDS3)
+#if defined(MULTIMODULE) && defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS:
#endif
+#if defined(AFHDS3)
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS:
+#endif
+#if defined(MULTIMODULE)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS:
+#endif
{
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODULE_STATUS);
char statusText[64];
- getMultiModuleStatus(moduleIdx).getStatusString(statusText);
+ getModuleStatusString(moduleIdx, statusText);
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
break;
}
-#if defined(HARDWARE_INTERNAL_MODULE)
+#if defined(MULTIMODULE) && defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS:
#endif
+#if defined(AFHDS3)
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS:
+#endif
+#if defined(MULTIMODULE)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS:
+#endif
{
- lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODULE_SYNC);
-
+#if defined(AFHDS3)
+ if (isModuleAFHDS3(moduleIdx)) {
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_AFHDS3_POWER_SOURCE);
+ }
+ else
+#endif
+ {
+ lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODULE_SYNC);
+ }
char statusText[64];
- getMultiSyncStatus(moduleIdx).getRefreshString(statusText);
+ getModuleSyncStatusString(moduleIdx, statusText);
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText);
break;
}
@@ -1753,7 +1886,7 @@ bool menuModelSetup(event_t event)
// some field just finished being edited
if (old_editMode > 0 && s_editMode == 0) {
- ModelCell* mod_cell = modelslist.getCurrentModel();
+ ModelCell * mod_cell = modelslist.getCurrentModel();
if (mod_cell) {
switch(menuVerticalPosition) {
case ITEM_MODEL_SETUP_NAME:
@@ -1768,7 +1901,7 @@ bool menuModelSetup(event_t event)
checkModelIdUnique(INTERNAL_MODULE);
break;
#endif
- case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_BIND:
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE:
if (menuHorizontalPosition != 0)
break;
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE:
diff --git a/radio/src/gui/480x272/popups.cpp b/radio/src/gui/480x272/popups.cpp
index 25a28779e..d95eea7cd 100644
--- a/radio/src/gui/480x272/popups.cpp
+++ b/radio/src/gui/480x272/popups.cpp
@@ -27,6 +27,7 @@ uint8_t warningType;
uint8_t warningResult = 0;
uint8_t warningInfoFlags = ZCHAR;
PopupFunc popupFunc = nullptr;
+const char * popupMenuTitle = nullptr;
const char *popupMenuItems[POPUP_MENU_MAX_LINES];
uint8_t popupMenuSelectedItem = 0;
uint16_t popupMenuItemsCount = 0;
@@ -46,7 +47,7 @@ void showAlertBox(const char * title, const char * text, const char * action, ui
lcdRefresh();
lcdSetContrast();
waitKeysReleased();
- backlightOn();
+ resetBacklightTimeout();
checkBacklight();
}
@@ -61,6 +62,10 @@ void drawPopupBackgroundAndBorder(coord_t x, coord_t y, coord_t w, coord_t h)
{
lcdDrawSolidFilledRect(x + 1, y + 1, w - 2, h - 2, TEXT_BGCOLOR);
lcdDrawSolidRect(x, y, w, h, 1, ALARM_COLOR);
+ if (popupMenuTitle) {
+ lcdDrawSolidFilledRect(x, y - FH, w, FH, TEXT_INVERTED_BGCOLOR);
+ lcdDrawText(x + w / 2, y - FH, popupMenuTitle, BOLD | CENTERED | TEXT_INVERTED_COLOR);
+ }
}
void runPopupWarning(event_t event)
@@ -167,14 +172,13 @@ const char * runPopupMenu(event_t event)
break;
}
- int y = (LCD_H - (display_count*(FH+1))) / 2;
+ int y = (LCD_H - (display_count*(FH + 1)) + (popupMenuTitle ? FH : 0) + FH) / 2;
- drawPopupBackgroundAndBorder(MENU_X, y, MENU_W, display_count * (FH+1) + 2);
+ drawPopupBackgroundAndBorder(MENU_X, y, MENU_W, display_count * (FH + 1) + 2);
for (uint8_t i=0; i
+#endif
constexpr coord_t LEFT_NAME_COLUMN = MENUS_MARGIN_LEFT;
constexpr coord_t RIGHT_NAME_COLUMN = LCD_W / 2;
constexpr coord_t ANA_OFFSET = 150;
-constexpr coord_t RAS_TOP_POSITION = LCD_H - 45;
bool menuRadioDiagAnalogs(event_t event)
{
SIMPLE_SUBMENU(STR_MENU_RADIO_ANALOGS, ICON_MODEL_SETUP, 0);
- for (uint8_t i = 0; i < NUM_STICKS + NUM_POTS + NUM_SLIDERS; i++) {
+#if defined(HARDWARE_TOUCH)
+ if (event == EVT_ENTRY || event == EVT_ENTRY_UP) {
+ touchPanelInit();
+ }
+ else if (menuEvent) {
+ touchPanelDeInit();
+ return false;
+ }
+#endif
+
+ for (uint8_t i = 0; i < NUM_ANALOGS; i++) {
coord_t y = MENU_HEADER_HEIGHT + 1 + (i / 2) * FH;
uint8_t x = i & 1 ? LCD_W / 2 + 10 : LEFT_NAME_COLUMN;
lcdDrawNumber(x, y, i + 1, LEADING0 | LEFT, 2);
@@ -40,16 +53,33 @@ bool menuRadioDiagAnalogs(event_t event)
lcdDrawNumber(x + ANA_OFFSET + 30 - 1, y, avgJitter[i].get(), RIGHT);
lcdDrawNumber(x + ANA_OFFSET + 70 - 1, y, (int16_t) calibratedAnalogs[CONVERT_MODE(i)] * 25 / 256, RIGHT);
#else
- lcdDrawNumber(x + ANA_OFFSET - 1, y, (int16_t) calibratedAnalogs[CONVERT_MODE(i)] * 25 / 256, RIGHT);
+ if (i < NUM_STICKS + NUM_POTS + NUM_SLIDERS)
+ lcdDrawNumber(x + ANA_OFFSET - 1, y, (int16_t) calibratedAnalogs[CONVERT_MODE(i)] * 25 / 256, RIGHT);
+#if NUM_MOUSE_ANALOGS > 0
+ else if (i >= MOUSE1)
+ lcdDrawNumber(x + ANA_OFFSET - 1, y, (int16_t) calibratedAnalogs[CALIBRATED_MOUSE1 + i - MOUSE1] * 25 / 256, RIGHT);
+#endif
#endif
}
- // RAS
- if ((isModuleXJT(INTERNAL_MODULE) && IS_INTERNAL_MODULE_ON()) || (isModulePXX1(EXTERNAL_MODULE) && !IS_INTERNAL_MODULE_ON())) {
- lcdDrawText(MENUS_MARGIN_LEFT, RAS_TOP_POSITION, "RAS : ");
- lcdDrawNumber(lcdNextPos, RAS_TOP_POSITION, telemetryData.swrInternal.value(), 0);
- lcdDrawText(LCD_W / 2, RAS_TOP_POSITION, "XJTVER : ");
- lcdDrawNumber(lcdNextPos, RAS_TOP_POSITION, telemetryData.xjtVersion, 0);
+#if defined(SIMU) || NUM_PWMSTICKS > 0
+ lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 8 * FH, STICKS_PWM_ENABLED() ? "Sticks: PWM" : "Sticks: ANA");
+#endif
+
+#if defined(HARDWARE_TOUCH)
+ if (HAS_TOUCH_PANEL()) {
+ lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 7 * FH, STR_TOUCH_PANEL);
}
+
+ if (touchPanelEvent) {
+ touchPanelRead();
+ lcdDrawNumber(lcdNextPos + 1, MENU_CONTENT_TOP + 7 * FH, touchState.x);
+ lcdDrawText(lcdNextPos, MENU_CONTENT_TOP + 7 * FH, ", ");
+ lcdDrawNumber(lcdNextPos + 1, MENU_CONTENT_TOP + 7 * FH, touchState.y);
+ lcdDrawLine(touchState.x - 10, touchState.y - 8, touchState.x + 10, touchState.y + 8, SOLID);
+ lcdDrawLine(touchState.x - 10, touchState.y + 8, touchState.x + 10, touchState.y - 8, SOLID);
+ }
+#endif
+
return true;
}
diff --git a/radio/src/gui/480x272/radio_diagkeys.cpp b/radio/src/gui/480x272/radio_diagkeys.cpp
index c952775a9..31a3941a4 100644
--- a/radio/src/gui/480x272/radio_diagkeys.cpp
+++ b/radio/src/gui/480x272/radio_diagkeys.cpp
@@ -61,7 +61,7 @@ bool menuRadioDiagKeys(event_t event)
displayKeyState(70, y, i);
}
- for (uint8_t i = 0; i <= NUM_SWITCHES; i++) {
+ for (uint8_t i = 0; i < NUM_SWITCHES; i++) {
if (SWITCH_EXISTS(i)) {
coord_t y = MENU_HEADER_HEIGHT + 1 + FH * i;
getvalue_t val = getValue(MIXSRC_FIRST_SWITCH + i);
@@ -73,7 +73,7 @@ bool menuRadioDiagKeys(event_t event)
#if defined(ROTARY_ENCODER_NAVIGATION)
coord_t y = MENU_HEADER_HEIGHT + FH * (8 - KEY_START);
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ROTARY_ENCODER);
- lcdDrawNumber(70, y, rotencValue, 0);
+ lcdDrawNumber(70, y, rotencValue / ROTARY_ENCODER_GRANULARITY, 0);
#endif
return true;
diff --git a/radio/src/gui/480x272/radio_hardware.cpp b/radio/src/gui/480x272/radio_hardware.cpp
index fbf4db3fd..8020bf983 100644
--- a/radio/src/gui/480x272/radio_hardware.cpp
+++ b/radio/src/gui/480x272/radio_hardware.cpp
@@ -70,19 +70,32 @@ enum MenuRadioHardwareItems {
#if defined(AUX_SERIAL)
ITEM_RADIO_HARDWARE_AUX_SERIAL_MODE,
#endif
-
+#if defined(AUX2_SERIAL)
+ ITEM_RADIO_HARDWARE_AUX2_SERIAL_MODE,
+#endif
ITEM_RADIO_HARDWARE_JITTER_FILTER,
+ ITEM_RADIO_HARDWARE_RAS,
+
+#if defined(SPORT_UPDATE_PWR_GPIO)
+ ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER,
+#endif
ITEM_RADIO_HARDWARE_DEBUG,
ITEM_RADIO_HARDWARE_MAX
};
-#define HW_SETTINGS_COLUMN 150
+#define HW_SETTINGS_COLUMN1 150
+#define HW_SETTINGS_COLUMN2 200
#if defined(AUX_SERIAL)
#define AUX_SERIAL_ROW 0,
#else
#define AUX_SERIAL_ROW
#endif
+#if defined(AUX2_SERIAL)
+#define AUX2_SERIAL_ROW 0,
+#else
+#define AUX2_SERIAL_ROW
+#endif
#define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
#define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
@@ -113,6 +126,18 @@ void onHardwareAntennaSwitchConfirm(const char * result)
#define EXTERNAL_ANTENNA_ROW
#endif
+#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000
+ #define MAX_BAUDRATE_ROW 0
+#else
+ #define MAX_BAUDRATE_ROW HIDDEN_ROW
+#endif
+
+#if defined(SPORT_UPDATE_PWR_GPIO)
+ #define SPORT_POWER_ROWS 0,
+#else
+ #define SPORT_POWER_ROWS
+#endif
+
bool menuRadioHardware(event_t event)
{
MENU(STR_HARDWARE, RADIO_ICONS, menuTabGeneral, MENU_RADIO_HARDWARE, ITEM_RADIO_HARDWARE_MAX, {
@@ -134,14 +159,17 @@ bool menuRadioHardware(event_t event)
READONLY_ROW, /* RTC */
0, /* RTC check */
- 0, /* max baudrate */
+ MAX_BAUDRATE_ROW, /* max baudrate */
BLUETOOTH_ROWS
EXTERNAL_ANTENNA_ROW
AUX_SERIAL_ROW /* aux serial mode */
+ AUX2_SERIAL_ROW /* aux2 serial mode */
0, /* ADC filter */
+ READONLY_ROW /* RAS */,
+ SPORT_POWER_ROWS
1, /* Debug */
});
@@ -167,7 +195,7 @@ bool menuRadioHardware(event_t event)
LcdFlags attr = (sub == k ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
switch (k) {
case ITEM_RADIO_HARDWARE_CALIBRATION:
- lcdDrawText(MENUS_MARGIN_LEFT, y, "Calibration", attr);
+ lcdDrawText(MENUS_MARGIN_LEFT, y, STR_CALIBRATION, attr);
if (attr && s_editMode>0) {
pushMenu(menuRadioCalibration);
}
@@ -181,7 +209,7 @@ bool menuRadioHardware(event_t event)
case ITEM_RADIO_HARDWARE_STICK2:
case ITEM_RADIO_HARDWARE_STICK3:
case ITEM_RADIO_HARDWARE_STICK4:
- editStickHardwareSettings(HW_SETTINGS_COLUMN, y, k - ITEM_RADIO_HARDWARE_STICK1, event, attr);
+ editStickHardwareSettings(HW_SETTINGS_COLUMN1, y, k - ITEM_RADIO_HARDWARE_STICK1, event, attr);
break;
case ITEM_RADIO_HARDWARE_LS:
@@ -195,11 +223,11 @@ bool menuRadioHardware(event_t event)
uint8_t mask = (0x01 << idx);
lcdDrawTextAtIndex(INDENT_WIDTH, y, STR_VSRCRAW, NUM_STICKS+NUM_POTS+idx+1, menuHorizontalPosition < 0 ? attr : 0);
if (ZEXIST(g_eeGeneral.anaNames[NUM_STICKS+NUM_POTS+idx]) || (attr && menuHorizontalPosition == 0))
- editName(HW_SETTINGS_COLUMN, y, g_eeGeneral.anaNames[NUM_STICKS+NUM_POTS+idx], LEN_ANA_NAME, event, attr && menuHorizontalPosition == 0);
+ editName(HW_SETTINGS_COLUMN1, y, g_eeGeneral.anaNames[NUM_STICKS+NUM_POTS+idx], LEN_ANA_NAME, event, attr && menuHorizontalPosition == 0);
else
- lcdDrawMMM(HW_SETTINGS_COLUMN, y, 0);
+ lcdDrawMMM(HW_SETTINGS_COLUMN1, y, 0);
uint8_t potType = (g_eeGeneral.slidersConfig & mask) >> idx;
- potType = editChoice(HW_SETTINGS_COLUMN+50, y, STR_SLIDERTYPES, potType, SLIDER_NONE, SLIDER_WITH_DETENT, menuHorizontalPosition == 1 ? attr : 0, event);
+ potType = editChoice(HW_SETTINGS_COLUMN2, y, STR_SLIDERTYPES, potType, SLIDER_NONE, SLIDER_WITH_DETENT, menuHorizontalPosition == 1 ? attr : 0, event);
g_eeGeneral.slidersConfig &= ~mask;
g_eeGeneral.slidersConfig |= (potType << idx);
break;
@@ -220,11 +248,11 @@ bool menuRadioHardware(event_t event)
int index = k - ITEM_RADIO_HARDWARE_POT1;
lcdDrawTextAtIndex(INDENT_WIDTH, y, STR_VSRCRAW, NUM_STICKS+index+1, menuHorizontalPosition < 0 ? attr : 0);
if (ZEXIST(g_eeGeneral.anaNames[NUM_STICKS+index]) || (attr && menuHorizontalPosition == 0))
- editName(HW_SETTINGS_COLUMN, y, g_eeGeneral.anaNames[NUM_STICKS+index], LEN_ANA_NAME, event, attr && menuHorizontalPosition == 0);
+ editName(HW_SETTINGS_COLUMN1, y, g_eeGeneral.anaNames[NUM_STICKS+index], LEN_ANA_NAME, event, attr && menuHorizontalPosition == 0);
else
- lcdDrawMMM(HW_SETTINGS_COLUMN, y, 0);
+ lcdDrawMMM(HW_SETTINGS_COLUMN1, y, 0);
uint32_t potType = bfGet(g_eeGeneral.potsConfig, 2*(index), 2);
- potType = editChoice(HW_SETTINGS_COLUMN+50, y, STR_POTTYPES, potType, POT_NONE, POT_WITHOUT_DETENT, menuHorizontalPosition == 1 ? attr : 0, event);
+ potType = editChoice(HW_SETTINGS_COLUMN2, y, STR_POTTYPES, potType, POT_NONE, POT_WITHOUT_DETENT, menuHorizontalPosition == 1 ? attr : 0, event);
g_eeGeneral.potsConfig = bfSet(g_eeGeneral.potsConfig, potType, 2*index, 2);
break;
}
@@ -248,10 +276,10 @@ bool menuRadioHardware(event_t event)
int config = SWITCH_CONFIG(index);
lcdDrawTextAtIndex(INDENT_WIDTH, y, STR_VSRCRAW, MIXSRC_FIRST_SWITCH-MIXSRC_Rud+index+1, menuHorizontalPosition < 0 ? attr : 0);
if (ZEXIST(g_eeGeneral.switchNames[index]) || (attr && menuHorizontalPosition == 0))
- editName(HW_SETTINGS_COLUMN, y, g_eeGeneral.switchNames[index], LEN_SWITCH_NAME, event, menuHorizontalPosition == 0 ? attr : 0);
+ editName(HW_SETTINGS_COLUMN1, y, g_eeGeneral.switchNames[index], LEN_SWITCH_NAME, event, menuHorizontalPosition == 0 ? attr : 0);
else
- lcdDrawMMM(HW_SETTINGS_COLUMN, y, 0);
- config = editChoice(HW_SETTINGS_COLUMN+50, y, STR_SWTYPES, config, SWITCH_NONE, SWITCH_TYPE_MAX(index), menuHorizontalPosition == 1 ? attr : 0, event);
+ lcdDrawMMM(HW_SETTINGS_COLUMN1, y, 0);
+ config = editChoice(HW_SETTINGS_COLUMN2, y, STR_SWTYPES, config, SWITCH_NONE, SWITCH_TYPE_MAX(index), menuHorizontalPosition == 1 ? attr : 0, event);
if (attr && checkIncDec_Ret) {
g_eeGeneral.switchConfig = bfSet(g_eeGeneral.switchConfig, config, 2*index, 2);
}
@@ -260,18 +288,18 @@ bool menuRadioHardware(event_t event)
case ITEM_RADIO_HARDWARE_BATTERY_CALIB:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_BATT_CALIB);
- lcdDrawNumber(HW_SETTINGS_COLUMN+50, y, getBatteryVoltage(), attr|PREC2, 0, NULL, "V");
+ lcdDrawNumber(HW_SETTINGS_COLUMN2, y, getBatteryVoltage(), attr|PREC2, 0, NULL, "V");
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.txVoltageCalibration, -127, 127);
break;
case ITEM_RADIO_HARDWARE_RTC_BATTERY:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_RTC_BATT);
- lcdDrawNumber(HW_SETTINGS_COLUMN+50, y, getRTCBatteryVoltage(), attr|PREC2, 0, NULL, "V");
+ lcdDrawNumber(HW_SETTINGS_COLUMN2, y, getRTCBatteryVoltage(), attr|PREC2, 0, NULL, "V");
break;
case ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MAXBAUDRATE);
- lcdDrawNumber(HW_SETTINGS_COLUMN+50, y, CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate], attr|LEFT);
+ lcdDrawNumber(HW_SETTINGS_COLUMN2, y, CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate], attr|LEFT);
if (attr) {
g_eeGeneral.telemetryBaudrate = DIM(CROSSFIRE_BAUDRATES) - 1 - checkIncDecModel(event, DIM(CROSSFIRE_BAUDRATES) - 1 - g_eeGeneral.telemetryBaudrate, 0, DIM(CROSSFIRE_BAUDRATES) - 1);
if (checkIncDec_Ret && IS_EXTERNAL_MODULE_ON()) {
@@ -291,40 +319,40 @@ bool menuRadioHardware(event_t event)
{
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_RTC_CHECK);
uint8_t b = 1 - g_eeGeneral.disableRtcWarning;
- g_eeGeneral.disableRtcWarning = 1 - editCheckBox(b, HW_SETTINGS_COLUMN + 50, y, attr, event);
+ g_eeGeneral.disableRtcWarning = 1 - editCheckBox(b, HW_SETTINGS_COLUMN2, y, attr, event);
break;
}
#if defined(BLUETOOTH)
case ITEM_RADIO_HARDWARE_BLUETOOTH_MODE:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_BLUETOOTH);
- g_eeGeneral.bluetoothMode = editChoice(HW_SETTINGS_COLUMN+50, y, STR_BLUETOOTH_MODES, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_TRAINER, attr, event);
+ g_eeGeneral.bluetoothMode = editChoice(HW_SETTINGS_COLUMN2, y, STR_BLUETOOTH_MODES, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_TRAINER, attr, event);
break;
case ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE:
lcdDrawText(INDENT_WIDTH, y, STR_BLUETOOTH_PIN_CODE);
- lcdDrawText(HW_SETTINGS_COLUMN+50, y, "000000", 0);
+ lcdDrawText(HW_SETTINGS_COLUMN2, y, "000000", 0);
break;
case ITEM_RADIO_HARDWARE_BLUETOOTH_LOCAL_ADDR:
lcdDrawText(INDENT_WIDTH, y, STR_BLUETOOTH_LOCAL_ADDR);
- lcdDrawText(HW_SETTINGS_COLUMN+50, y, bluetooth.localAddr[0] == '\0' ? "---" : bluetooth.localAddr);
+ lcdDrawText(HW_SETTINGS_COLUMN2, y, bluetooth.localAddr[0] == '\0' ? "---" : bluetooth.localAddr);
break;
case ITEM_RADIO_HARDWARE_BLUETOOTH_DISTANT_ADDR:
lcdDrawText(INDENT_WIDTH, y, STR_BLUETOOTH_DIST_ADDR);
- lcdDrawText(HW_SETTINGS_COLUMN+50, y, bluetooth.distantAddr[0] == '\0' ? "---" : bluetooth.distantAddr);
+ lcdDrawText(HW_SETTINGS_COLUMN2, y, bluetooth.distantAddr[0] == '\0' ? "---" : bluetooth.distantAddr);
break;
case ITEM_RADIO_HARDWARE_BLUETOOTH_NAME:
lcdDrawText(INDENT_WIDTH, y, STR_NAME);
- editName(HW_SETTINGS_COLUMN+50, y, g_eeGeneral.bluetoothName, LEN_BLUETOOTH_NAME, event, attr);
+ editName(HW_SETTINGS_COLUMN2, y, g_eeGeneral.bluetoothName, LEN_BLUETOOTH_NAME, event, attr);
break;
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
case ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ANTENNA);
- reusableBuffer.radioHardware.antennaMode = editChoice(HW_SETTINGS_COLUMN+50, y, STR_ANTENNA_MODES, reusableBuffer.radioHardware.antennaMode, ANTENNA_MODE_INTERNAL, ANTENNA_MODE_EXTERNAL, attr, event);
+ reusableBuffer.radioHardware.antennaMode = editChoice(HW_SETTINGS_COLUMN2, y, STR_ANTENNA_MODES, reusableBuffer.radioHardware.antennaMode, ANTENNA_MODE_INTERNAL, ANTENNA_MODE_EXTERNAL, attr, event);
if (!s_editMode && reusableBuffer.radioHardware.antennaMode != g_eeGeneral.antennaMode) {
if (!isExternalAntennaEnabled() && (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_EXTERNAL || (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_PER_MODEL && g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode == ANTENNA_MODE_EXTERNAL))) {
POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onHardwareAntennaSwitchConfirm);
@@ -341,24 +369,68 @@ bool menuRadioHardware(event_t event)
#if defined(AUX_SERIAL)
case ITEM_RADIO_HARDWARE_AUX_SERIAL_MODE:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_AUX_SERIAL_MODE);
- g_eeGeneral.auxSerialMode = editChoice(HW_SETTINGS_COLUMN+50, y, STR_AUX_SERIAL_MODES, g_eeGeneral.auxSerialMode, 0, UART_MODE_MAX, attr, event);
+#if defined(RADIO_TX16S)
+ lcdDrawText(lcdNextPos, y, " (TTL)");
+#endif
+ g_eeGeneral.auxSerialMode = editChoice(HW_SETTINGS_COLUMN2, y, STR_AUX_SERIAL_MODES, g_eeGeneral.auxSerialMode, 0, UART_MODE_MAX, attr, event, isAux1ModeAvailable);
if (attr && checkIncDec_Ret) {
auxSerialInit(g_eeGeneral.auxSerialMode, modelTelemetryProtocol());
}
break;
#endif
+#if defined(AUX2_SERIAL)
+ case ITEM_RADIO_HARDWARE_AUX2_SERIAL_MODE:
+ lcdDrawText(MENUS_MARGIN_LEFT, y, STR_AUX2_SERIAL_MODE);
+#if defined(RADIO_TX16S)
+ lcdDrawText(lcdNextPos, y, " (TTL)");
+#endif
+ g_eeGeneral.aux2SerialMode = editChoice(HW_SETTINGS_COLUMN2, y, STR_AUX_SERIAL_MODES, g_eeGeneral.aux2SerialMode, 0, UART_MODE_MAX, attr, event, isAux2ModeAvailable);
+ if (attr && checkIncDec_Ret) {
+ aux2SerialInit(g_eeGeneral.aux2SerialMode, modelTelemetryProtocol());
+ }
+ break;
+#endif
+
case ITEM_RADIO_HARDWARE_JITTER_FILTER:
{
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_JITTER_FILTER);
uint8_t b = 1 - g_eeGeneral.jitterFilter;
- g_eeGeneral.jitterFilter = 1 - editCheckBox(b, HW_SETTINGS_COLUMN+50, y, attr, event);
+ g_eeGeneral.jitterFilter = 1 - editCheckBox(b, HW_SETTINGS_COLUMN2, y, attr, event);
break;
}
+ case ITEM_RADIO_HARDWARE_RAS:
+#if defined(HARDWARE_INTERNAL_RAS)
+ lcdDrawText(MENUS_MARGIN_LEFT, y, "RAS");
+ if (telemetryData.swrInternal.isFresh())
+ lcdDrawNumber(HW_SETTINGS_COLUMN2, y, telemetryData.swrInternal.value());
+ else
+ lcdDrawText(HW_SETTINGS_COLUMN2, y, "---");
+ lcdDrawText(lcdNextPos, y, "/");
+#else
+ lcdDrawText(MENUS_MARGIN_LEFT, y, "Ext. RAS");
+ lcdNextPos = HW_SETTINGS_COLUMN2;
+#endif
+ if (telemetryData.swrExternal.isFresh())
+ lcdDrawNumber(lcdNextPos, y, telemetryData.swrExternal.value());
+ else
+ lcdDrawText(lcdNextPos, y, "---");
+ break;
+
+#if defined(SPORT_UPDATE_PWR_GPIO)
+ case ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER:
+ lcdDrawText(MENUS_MARGIN_LEFT, y, STR_SPORT_UPDATE_POWER_MODE);
+ g_eeGeneral.sportUpdatePower = editChoice(HW_SETTINGS_COLUMN2, y, STR_SPORT_UPDATE_POWER_MODES, g_eeGeneral.sportUpdatePower, 0, 1, attr, event);
+ if (attr && checkIncDec_Ret) {
+ SPORT_UPDATE_POWER_INIT();
+ }
+ break;
+#endif
+
case ITEM_RADIO_HARDWARE_DEBUG:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_DEBUG);
- lcdDrawText(HW_SETTINGS_COLUMN + 50, y, STR_ANALOGS_BTN, menuHorizontalPosition == 0 ? attr : 0);
+ lcdDrawText(HW_SETTINGS_COLUMN2, y, STR_ANALOGS_BTN, menuHorizontalPosition == 0 ? attr : 0);
lcdDrawText(lcdNextPos + 10, y, STR_KEYS_BTN, menuHorizontalPosition == 1 ? attr : 0);
if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) {
if (menuHorizontalPosition == 0)
diff --git a/radio/src/gui/480x272/radio_power_meter.cpp b/radio/src/gui/480x272/radio_power_meter.cpp
index e20755ba9..c1f6ac316 100644
--- a/radio/src/gui/480x272/radio_power_meter.cpp
+++ b/radio/src/gui/480x272/radio_power_meter.cpp
@@ -50,6 +50,7 @@ bool menuRadioPowerMeter(event_t event)
lcdDrawCenteredText(LCD_H/2, STR_STOPPING);
lcdRefresh();
moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID);
+ resetAccessAuthenticationCount();
/* wait 1s to resume normal operation before leaving */
watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000);
diff --git a/radio/src/gui/480x272/radio_sdmanager.cpp b/radio/src/gui/480x272/radio_sdmanager.cpp
index d4da41e3b..708af82a2 100644
--- a/radio/src/gui/480x272/radio_sdmanager.cpp
+++ b/radio/src/gui/480x272/radio_sdmanager.cpp
@@ -18,7 +18,6 @@
* GNU General Public License for more details.
*/
-#include
#include "io/frsky_firmware_update.h"
#include "io/multi_firmware_update.h"
#include "opentx.h"
@@ -91,6 +90,50 @@ void onSdFormatConfirm(const char * result)
}
}
+#if defined(PXX2)
+void onUpdateConfirmation(const char * result)
+{
+ if (result == STR_OK) {
+ OtaUpdateInformation * destination = moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].otaUpdateInformation;
+ Pxx2OtaUpdate otaUpdate(reusableBuffer.sdManager.otaUpdateInformation.module, destination->candidateReceiversNames[destination->selectedReceiverIndex]);
+ otaUpdate.flashFirmware(destination->filename);
+ putEvent(EVT_REFRESH);
+ }
+ else {
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
+ }
+}
+
+void onUpdateStateChanged()
+{
+ if (reusableBuffer.sdManager.otaUpdateInformation.step == BIND_INFO_REQUEST) {
+ uint8_t modelId = reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.modelID;
+ if (modelId > 0 && modelId < DIM(PXX2ReceiversNames)) {
+ if (isPXX2ReceiverOptionAvailable(modelId, RECEIVER_OPTION_OTA)) {
+ POPUP_CONFIRMATION(getPXX2ReceiverName(modelId), onUpdateConfirmation);
+ char *tmp = strAppend(reusableBuffer.sdManager.otaReceiverVersion, TR_CURRENT_VERSION);
+ tmp = strAppendUnsigned(tmp, 1 + reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.swVersion.major);
+ *tmp++ = '.';
+ tmp = strAppendUnsigned(tmp, reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.swVersion.minor);
+ *tmp++ = '.';
+ tmp = strAppendUnsigned(tmp, reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.swVersion.revision);
+ SET_WARNING_INFO(reusableBuffer.sdManager.otaReceiverVersion, tmp - reusableBuffer.sdManager.otaReceiverVersion, 0);
+ }
+ else {
+ POPUP_WARNING(STR_OTA_UPDATE_ERROR);
+ SET_WARNING_INFO(STR_UNSUPPORTED_RX, sizeof(TR_UNSUPPORTED_RX) - 1, 0);
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
+ }
+ }
+ else {
+ POPUP_WARNING(STR_OTA_UPDATE_ERROR);
+ SET_WARNING_INFO(STR_UNKNOWN_RX, sizeof(TR_UNKNOWN_RX) - 1, 0);
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
+ }
+ }
+}
+#endif
+
void onSdManagerMenu(const char * result)
{
TCHAR lfn[_MAX_LFN+1];
@@ -203,6 +246,14 @@ void onSdManagerMenu(const char * result)
multiFlashFirmware(EXTERNAL_MODULE, lfn);
}
#endif
+#if defined(PXX2)
+ else if (result == STR_FLASH_RECEIVER_OTA_BY_INTERNAL || result == STR_FLASH_RECEIVER_OTA_BY_EXTERNAL) {
+ memclear(&reusableBuffer.sdManager.otaUpdateInformation, sizeof(OtaUpdateInformation));
+ getSelectionFullPath(reusableBuffer.sdManager.otaUpdateInformation.filename);
+ reusableBuffer.sdManager.otaUpdateInformation.module = result == STR_FLASH_RECEIVER_OTA_BY_INTERNAL ? INTERNAL_MODULE : EXTERNAL_MODULE;
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].startBind(&reusableBuffer.sdManager.otaUpdateInformation, onUpdateStateChanged);
+ }
+#endif
#if defined(LUA)
else if (result == STR_EXECUTE_FILE) {
getSelectionFullPath(lfn);
@@ -211,20 +262,47 @@ void onSdManagerMenu(const char * result)
#endif
}
+#if defined(PXX2)
+void onUpdateReceiverSelection(const char * result)
+{
+ if (result != STR_EXIT) {
+ reusableBuffer.sdManager.otaUpdateInformation.selectedReceiverIndex = (result - reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversNames[0]) / sizeof(reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversNames[0]);
+ reusableBuffer.sdManager.otaUpdateInformation.step = BIND_INFO_REQUEST;
+#if defined(SIMU)
+ reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.modelID = 0x01;
+ onUpdateStateChanged();
+#endif
+ }
+ else {
+ // the user pressed [Exit]
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
+ }
+}
+#endif
+
bool menuRadioSdManager(event_t _event)
{
+#if defined(PXX2)
+ if (EVT_KEY_MASK(_event) == KEY_EXIT && moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode == MODULE_MODE_BIND) {
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
+ CLEAR_POPUP();
+ killEvents(KEY_EXIT);
+ _event = 0;
+ }
+#endif
+
event_t event = (EVT_KEY_MASK(_event) == KEY_ENTER ? 0 : _event);
SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, RADIO_ICONS, menuTabGeneral, MENU_RADIO_SD_MANAGER, reusableBuffer.sdManager.count);
int index = menuVerticalPosition - menuVerticalOffset;
- switch(_event) {
+ switch (_event) {
case EVT_ENTRY:
f_chdir(ROOT_PATH);
// no break;
case EVT_ENTRY_UP:
- memset(&reusableBuffer.sdManager, 0, sizeof(reusableBuffer.sdManager));
+ memclear(&reusableBuffer.sdManager, sizeof(reusableBuffer.sdManager));
menuVerticalPosition = 0;
REFRESH_FILES();
break;
@@ -300,8 +378,12 @@ bool menuRadioSdManager(event_t _event)
if (HAS_SPORT_UPDATE_CONNECTOR() && (information.productFamily == FIRMWARE_FAMILY_RECEIVER || information.productFamily == FIRMWARE_FAMILY_SENSOR))
POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_DEVICE);
#if defined(PXX2)
- if (information.productFamily == FIRMWARE_FAMILY_RECEIVER)
- POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA);
+ if (information.productFamily == FIRMWARE_FAMILY_RECEIVER) {
+ if (isReceiverOTAEnabledFromModule(INTERNAL_MODULE, information.productId))
+ POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA_BY_INTERNAL);
+ if (isReceiverOTAEnabledFromModule(EXTERNAL_MODULE, information.productId))
+ POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA_BY_EXTERNAL);
+ }
#endif
#if defined(BLUETOOTH)
if (information.productFamily == FIRMWARE_FAMILY_BLUETOOTH_CHIP)
@@ -337,9 +419,11 @@ bool menuRadioSdManager(event_t _event)
}
#endif
+#if defined(LUA)
if (isExtensionMatching(ext, SCRIPTS_EXT)) {
POPUP_MENU_ADD_ITEM(STR_EXECUTE_FILE);
}
+#endif
if (isExtensionMatching(ext, TEXT_EXT) || isExtensionMatching(ext, SCRIPTS_EXT)) {
POPUP_MENU_ADD_ITEM(STR_VIEW_TEXT);
@@ -439,7 +523,7 @@ bool menuRadioSdManager(event_t _event)
reusableBuffer.sdManager.offset = menuVerticalOffset;
- for (uint8_t i=0; i 0) {
+ if (reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversCount != popupMenuItemsCount) {
+ CLEAR_POPUP();
+ popupMenuItemsCount = min(reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversCount, PXX2_MAX_RECEIVERS_PER_MODULE);
+ for (auto rx = 0; rx < popupMenuItemsCount; rx++) {
+ popupMenuItems[rx] = reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversNames[rx];
+ }
+ POPUP_MENU_TITLE(STR_PXX2_SELECT_RX);
+ POPUP_MENU_START(onUpdateReceiverSelection);
+ }
+ }
+ else {
+ DRAW_POPUP_WAIT(STR_WAITING_FOR_RX);
+ }
+ }
+ }
+#endif
+
const char * ext = getFileExtension(reusableBuffer.sdManager.lines[index]);
if (ext && isExtensionMatching(ext, BITMAPS_EXT)) {
if (currentBitmapIndex != menuVerticalPosition) {
diff --git a/radio/src/gui/480x272/radio_setup.cpp b/radio/src/gui/480x272/radio_setup.cpp
index 0eb630928..f3cdb9a61 100644
--- a/radio/src/gui/480x272/radio_setup.cpp
+++ b/radio/src/gui/480x272/radio_setup.cpp
@@ -65,6 +65,9 @@ enum menuRadioSetupItems {
ITEM_SETUP_BACKLIGHT_DELAY,
ITEM_SETUP_BRIGHTNESS,
ITEM_SETUP_DIM_LEVEL,
+#if defined(KEYS_BACKLIGHT_GPIO)
+ ITEM_SETUP_KEYS_BACKLIGHT,
+#endif
ITEM_SETUP_FLASH_BEEP,
CASE_PWR_BUTTON_PRESS(ITEM_SETUP_PWR_OFF_SPEED)
#if defined(PXX2)
@@ -110,6 +113,11 @@ bool menuRadioSetup(event_t event)
#else
#define FAI_CHOICE_ROW
#endif
+#if defined(KEYS_BACKLIGHT_GPIO)
+ #define BACKLIGHT_ROWS LABEL(BACKLIGHT), 0, 0, 0, 0, 0, 0,
+#else
+ #define BACKLIGHT_ROWS LABEL(BACKLIGHT), 0, 0, 0, 0, 0,
+#endif
MENU(STR_MENURADIOSETUP, RADIO_ICONS, menuTabGeneral, MENU_RADIO_SETUP, ITEM_SETUP_MAX, {
2|NAVIGATION_LINE_BY_LINE, 2|NAVIGATION_LINE_BY_LINE, 1|NAVIGATION_LINE_BY_LINE, // Date Time Bat range
@@ -117,7 +125,7 @@ bool menuRadioSetup(event_t event)
CASE_VARIO(LABEL(VARIO)) CASE_VARIO(0) CASE_VARIO(0) CASE_VARIO(0) CASE_VARIO(0)
CASE_HAPTIC(LABEL(HAPTIC)) CASE_HAPTIC(0) CASE_HAPTIC(0) CASE_HAPTIC(0)
LABEL(ALARMS), 0, 0, 0, 0,
- LABEL(BACKLIGHT), 0, 0, 0, 0, 0,
+ BACKLIGHT_ROWS
CASE_PWR_BUTTON_PRESS(0)
CASE_PXX2(0) // owner registration ID
CASE_GPS(LABEL(GPS))
@@ -373,7 +381,7 @@ bool menuRadioSetup(event_t event)
break;
case ITEM_SETUP_BACKLIGHT_MODE:
- lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODE);
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH , y, STR_MODE);
g_eeGeneral.backlightMode = editChoice(RADIO_SETUP_2ND_COLUMN, y, STR_VBLMODE, g_eeGeneral.backlightMode, e_backlight_mode_off, e_backlight_mode_on, attr, event);
break;
@@ -388,7 +396,6 @@ bool menuRadioSetup(event_t event)
editName(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.ownerRegistrationID, PXX2_LEN_REGISTRATION_ID, event, attr);
break;
#endif
-
case ITEM_SETUP_BACKLIGHT_DELAY:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_BLDELAY);
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.lightAutoOff*5, attr|LEFT, 0, NULL, "s");
@@ -405,6 +412,13 @@ bool menuRadioSetup(event_t event)
g_eeGeneral.blOffBright = editSlider(RADIO_SETUP_2ND_COLUMN, y, event, g_eeGeneral.blOffBright, BACKLIGHT_LEVEL_MIN, BACKLIGHT_LEVEL_MAX, attr);
break;
+#if defined(KEYS_BACKLIGHT_GPIO)
+ case ITEM_SETUP_KEYS_BACKLIGHT:
+ lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH , y, STR_KEYS_BACKLIGHT);
+ g_eeGeneral.keysBacklight = editCheckBox(g_eeGeneral.keysBacklight, RADIO_SETUP_2ND_COLUMN, y, attr, event ) ;
+ break;
+#endif
+
#if defined(PWR_BUTTON_PRESS)
case ITEM_SETUP_PWR_OFF_SPEED:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_PWR_OFF_DELAY);
diff --git a/radio/src/gui/480x272/radio_spectrum_analyser.cpp b/radio/src/gui/480x272/radio_spectrum_analyser.cpp
index be26e58d3..95e40e9db 100644
--- a/radio/src/gui/480x272/radio_spectrum_analyser.cpp
+++ b/radio/src/gui/480x272/radio_spectrum_analyser.cpp
@@ -56,8 +56,10 @@ bool menuRadioSpectrumAnalyser(event_t event)
if (menuEvent) {
lcdDrawCenteredText(LCD_H / 2, STR_STOPPING);
lcdRefresh();
- if (isModulePXX2(g_moduleIdx))
+ if (isModulePXX2(g_moduleIdx)) {
moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID);
+ resetAccessAuthenticationCount();
+ }
else if (isModuleMultimodule(g_moduleIdx)) {
if (reusableBuffer.spectrumAnalyser.moduleOFF)
setModuleType(INTERNAL_MODULE, MODULE_TYPE_NONE);
diff --git a/radio/src/gui/480x272/radio_tools.cpp b/radio/src/gui/480x272/radio_tools.cpp
index 407a5b2fe..21cabf522 100644
--- a/radio/src/gui/480x272/radio_tools.cpp
+++ b/radio/src/gui/480x272/radio_tools.cpp
@@ -91,23 +91,7 @@ bool menuRadioTools(event_t event)
uint8_t index = 0;
-#if defined(INTERNAL_MODULE_PXX2)
- if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER))
- addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
- if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
- addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE);
-#elif defined(INTERNAL_MODULE_MULTI)
- addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
-#endif
-#if defined(PXX2)|| defined(MULTIMODULE)
- if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER) || isModuleMultimodule(EXTERNAL_MODULE))
- addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE);
-#endif
-#if defined(PXX2)
- if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
- addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE);
-#endif
#if defined(LUA)
FILINFO fno;
@@ -130,6 +114,24 @@ bool menuRadioTools(event_t event)
}
#endif
+#if defined(INTERNAL_MODULE_PXX2)
+ if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER))
+ addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
+
+ if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
+ addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE);
+#elif defined(INTERNAL_MODULE_MULTI)
+ addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
+#endif
+#if defined(PXX2)|| defined(MULTIMODULE)
+ if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER) || isModuleMultimodule(EXTERNAL_MODULE))
+ addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE);
+#endif
+#if defined(PXX2)
+ if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
+ addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE);
+#endif
+
if (index == 0) {
lcdDrawCenteredText(LCD_H/2, STR_NO_TOOLS);
}
diff --git a/radio/src/gui/480x272/radio_version.cpp b/radio/src/gui/480x272/radio_version.cpp
index 33ab73607..63301619a 100644
--- a/radio/src/gui/480x272/radio_version.cpp
+++ b/radio/src/gui/480x272/radio_version.cpp
@@ -186,13 +186,13 @@ bool menuRadioVersion(event_t event)
getCPUUniqueID(id);
SIMPLE_MENU(STR_MENUVERSION, RADIO_ICONS, menuTabGeneral, MENU_RADIO_VERSION, 1);
-
- lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, vers_stamp);
- lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + FH, date_stamp);
- lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 2*FH, time_stamp);
- lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 3*FH, eeprom_stamp);
- lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 4*FH, "UID:");
- lcdDrawText(MENUS_MARGIN_LEFT + 64, MENU_CONTENT_TOP + 4*FH, id);
+ lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, fw_stamp);
+ lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + FH, vers_stamp);
+ lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 2*FH, date_stamp);
+ lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 3*FH, time_stamp);
+ lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 4*FH, eeprom_stamp);
+ lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 5*FH, "UID:");
+ lcdDrawText(MENUS_MARGIN_LEFT + 64, MENU_CONTENT_TOP + 5*FH, id);
coord_t y = MENU_CONTENT_TOP + 5*FH;
lcdDrawText(MENUS_MARGIN_LEFT, y, "OPTS:");
diff --git a/radio/src/gui/480x272/screens_setup.cpp b/radio/src/gui/480x272/screens_setup.cpp
index 749bd50c2..e73afed68 100644
--- a/radio/src/gui/480x272/screens_setup.cpp
+++ b/radio/src/gui/480x272/screens_setup.cpp
@@ -121,7 +121,7 @@ bool editZoneOption(coord_t y, const ZoneOption * option, ZoneOptionValue * valu
}
}
else if (option->type == ZoneOption::TextSize) {
- lcdDrawTextAtIndex(SCREENS_SETUP_2ND_COLUMN, y, "\010StandardTiny\0 Small\0 Mid\0 Double", value->unsignedValue, attr);
+ lcdDrawTextAtIndex(SCREENS_SETUP_2ND_COLUMN, y, STR_TEXT_SIZE, value->unsignedValue, attr);
if (attr) {
value->unsignedValue = checkIncDec(event, value->unsignedValue, 0, 4, i_flags);
}
@@ -346,7 +346,7 @@ bool menuWidgetsSetup(event_t event)
currentScreen->refresh();
- for (int i=currentContainer->getZonesCount()-1; i>=0; i--) {
+ for (int i = currentContainer->getZonesCount() - 1; i >= 0; i--) {
Zone zone = currentContainer->getZone(i);
LcdFlags color;
int padding, thickness;
@@ -558,7 +558,7 @@ bool menuScreenSetup(int index, event_t event)
currentContainer = currentScreen;
bool needsOffsetCheck = (menuVerticalPosition != 0 || menuHorizontalPosition < 0);
- char title[] = "Main view X";
+ char title[] = TR_MAIN_VIEW_X;
title[sizeof(title)-2] = '1' + index;
menuPageCount = updateMainviewsMenu();
diff --git a/radio/src/gui/480x272/themes/darkblue.cpp b/radio/src/gui/480x272/themes/darkblue.cpp
index 017175c77..02fa5055b 100644
--- a/radio/src/gui/480x272/themes/darkblue.cpp
+++ b/radio/src/gui/480x272/themes/darkblue.cpp
@@ -35,7 +35,7 @@ class DarkblueTheme: public Theme
lcdColorTable[TEXT_INVERTED_COLOR_INDEX] = WHITE;
lcdColorTable[TEXT_INVERTED_BGCOLOR_INDEX] = RGB(32, 34, 42);
lcdColorTable[TEXT_STATUSBAR_COLOR_INDEX] = WHITE;
- lcdColorTable[LINE_COLOR_INDEX] = GREY;
+ lcdColorTable[LINE_COLOR_INDEX] = LIGHTGREY;
lcdColorTable[SCROLLBOX_COLOR_INDEX] = WHITE;
lcdColorTable[MENU_TITLE_BGCOLOR_INDEX] = DARKGREY;
lcdColorTable[MENU_TITLE_COLOR_INDEX] = WHITE;
@@ -51,7 +51,7 @@ class DarkblueTheme: public Theme
lcdColorTable[TRIM_BGCOLOR_INDEX] = RGB(32, 34, 42);
lcdColorTable[TRIM_SHADOW_COLOR_INDEX] = RGB(100, 100, 100);
lcdColorTable[MAINVIEW_PANES_COLOR_INDEX] = GREY;
- lcdColorTable[MAINVIEW_GRAPHICS_COLOR_INDEX] = WHITE;
+ lcdColorTable[MAINVIEW_GRAPHICS_COLOR_INDEX] = BLUE;
lcdColorTable[HEADER_BGCOLOR_INDEX] = BLACK;
lcdColorTable[HEADER_ICON_BGCOLOR_INDEX] = BLACK;
lcdColorTable[HEADER_CURRENT_BGCOLOR_INDEX] = RGB(10, 78, 121);
@@ -137,11 +137,19 @@ class DarkblueTheme: public Theme
calibTrackpBackground = BitmapBuffer::load(getThemePath("trackp_background.png"));
delete calibHorus;
-#if defined(PCBX10)
- if (STICKS_PWM_ENABLED())
+#if defined(RADIO_T16)
+ calibHorus = BitmapBuffer::load(getThemePath("t16.bmp"));
+#elif defined(RADIO_T18)
+ calibHorus = BitmapBuffer::load(getThemePath("t18.bmp"));
+#elif defined(RADIO_TX16S)
+ calibHorus = BitmapBuffer::load(getThemePath("tx16s.bmp"));
+#elif defined(PCBX10)
+ if(STICKS_PWM_ENABLED()) {
calibHorus = BitmapBuffer::load(getThemePath("X10S.bmp"));
- else
+ }
+ else {
calibHorus = BitmapBuffer::load(getThemePath("X10.bmp"));
+ }
#else
calibHorus = BitmapBuffer::load(getThemePath("horus.bmp"));
#endif
@@ -224,6 +232,7 @@ class DarkblueTheme: public Theme
virtual void load() const
{
+ Theme::load();
loadColors();
loadMenusIcons();
loadThemeBitmaps();
@@ -259,4 +268,7 @@ class DarkblueTheme: public Theme
BitmapBuffer * DarkblueTheme::menuIconNormal[MENUS_ICONS_COUNT] = { NULL };
BitmapBuffer * DarkblueTheme::menuIconSelected[MENUS_ICONS_COUNT] = { NULL };
-const DarkblueTheme darkblueTheme;
+DarkblueTheme darkblueTheme;
+#if defined(DEFAULT_THEME_DARKBLUE)
+ Theme * theme = &darkblueTheme;
+#endif
\ No newline at end of file
diff --git a/radio/src/gui/480x272/themes/default.cpp b/radio/src/gui/480x272/themes/default.cpp
index 84b23e168..740f30e39 100644
--- a/radio/src/gui/480x272/themes/default.cpp
+++ b/radio/src/gui/480x272/themes/default.cpp
@@ -46,8 +46,7 @@ class DefaultTheme: public Theme
lcdColorTable[SCROLLBOX_COLOR_INDEX] = RED;
lcdColorTable[MENU_TITLE_BGCOLOR_INDEX] = DARKGREY;
lcdColorTable[MENU_TITLE_COLOR_INDEX] = WHITE;
- lcdColorTable[MENU_TITLE_DISABLE_COLOR_INDEX] =
- RGB(GET_RED(RED)>>1, GET_GREEN(RED)>>1, GET_BLUE(RED)>>1);
+ lcdColorTable[MENU_TITLE_DISABLE_COLOR_INDEX] = RGB(GET_RED(RED)>>1, GET_GREEN(RED)>>1, GET_BLUE(RED)>>1);
lcdColorTable[HEADER_COLOR_INDEX] = DARKGREY;
lcdColorTable[ALARM_COLOR_INDEX] = RED;
lcdColorTable[WARNING_COLOR_INDEX] = YELLOW;
@@ -91,11 +90,10 @@ class DefaultTheme: public Theme
void loadIcons() const
{
-#if defined(LOG_TELEMETRY) || !defined(WATCHDOG)
- loadMenuIcon(ICON_OPENTX, "mask_opentx_testmode.png", TEXT_COLOR);
-#else
- loadMenuIcon(ICON_OPENTX, "mask_opentx.png");
-#endif
+ if (isAsteriskDisplayed())
+ loadMenuIcon(ICON_OPENTX, "mask_opentx_testmode.png", TEXT_COLOR);
+ else
+ loadMenuIcon(ICON_OPENTX, "mask_opentx.png");
loadMenuIcon(ICON_RADIO, "mask_menu_radio.png");
loadMenuIcon(ICON_RADIO_SETUP, "mask_radio_setup.png");
loadMenuIcon(ICON_RADIO_SD_MANAGER, "mask_radio_sd_browser.png");
@@ -178,6 +176,10 @@ class DefaultTheme: public Theme
delete calibHorus;
#if defined(RADIO_T16)
calibHorus = BitmapBuffer::load(getThemePath("t16.bmp"));
+#elif defined(RADIO_T18)
+ calibHorus = BitmapBuffer::load(getThemePath("t18.bmp"));
+#elif defined(RADIO_TX16S)
+ calibHorus = BitmapBuffer::load(getThemePath("tx16s.bmp"));
#elif defined(PCBX10)
if(STICKS_PWM_ENABLED()) {
calibHorus = BitmapBuffer::load(getThemePath("X10S.bmp"));
@@ -277,16 +279,15 @@ class DefaultTheme: public Theme
virtual void update() const
{
uint32_t color = g_eeGeneral.themeData.options[1].unsignedValue;
- uint32_t bg_color = UNEXPECTED_SHUTDOWN() ? WHITE : g_eeGeneral.themeData.options[0].unsignedValue;
+ uint32_t bgColor = globalData.unexpectedShutdown ? WHITE : g_eeGeneral.themeData.options[0].unsignedValue;
- lcdColorTable[TEXT_BGCOLOR_INDEX] = bg_color;
+ lcdColorTable[TEXT_BGCOLOR_INDEX] = bgColor;
lcdColorTable[TEXT_INVERTED_BGCOLOR_INDEX] = color;
lcdColorTable[SCROLLBOX_COLOR_INDEX] = color;
lcdColorTable[CURVE_COLOR_INDEX] = color;
lcdColorTable[CURVE_CURSOR_COLOR_INDEX] = color;
lcdColorTable[TITLE_BGCOLOR_INDEX] = color;
- lcdColorTable[MENU_TITLE_DISABLE_COLOR_INDEX] =
- RGB(GET_RED(color)>>1, GET_GREEN(color)>>1, GET_BLUE(color)>>1);
+ lcdColorTable[MENU_TITLE_DISABLE_COLOR_INDEX] = RGB(GET_RED(color)>>1, GET_GREEN(color)>>1, GET_BLUE(color)>>1);
lcdColorTable[TRIM_BGCOLOR_INDEX] = color;
lcdColorTable[MAINVIEW_GRAPHICS_COLOR_INDEX] = color;
#define DARKER(x) ((x * 70) / 100)
@@ -354,4 +355,6 @@ BitmapBuffer * DefaultTheme::menuIconSelected[MENUS_ICONS_COUNT] = { NULL };
BitmapBuffer * DefaultTheme::currentMenuBackground = NULL;
DefaultTheme defaultTheme;
-Theme * theme = &defaultTheme;
+#if defined(DEFAULT_THEME_DEFAULT)
+ Theme * theme = &defaultTheme;
+#endif
diff --git a/radio/src/gui/480x272/topbar.cpp b/radio/src/gui/480x272/topbar.cpp
index 45707f542..f78174aa8 100644
--- a/radio/src/gui/480x272/topbar.cpp
+++ b/radio/src/gui/480x272/topbar.cpp
@@ -90,11 +90,19 @@ void drawTopBar()
/* Tx battery */
uint8_t bars = GET_TXBATT_BARS(5);
- lcdDrawBitmapPattern(LCD_W-130, 24, LBM_TOPMENU_TXBATT, MENU_TITLE_COLOR);
+#if defined(USB_CHARGER)
+ if (usbChargerLed()) {
+ lcdDrawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT_CHARGING, MENU_TITLE_COLOR);
+ }
+ else {
+ lcdDrawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_TITLE_COLOR);
+ }
+#else
+ lcdDrawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_TITLE_COLOR);
+#endif
for (unsigned int i = 0; i < 5; i++) {
- lcdDrawSolidFilledRect(LCD_W-122+4*i, 30, 2, 8, i >= bars ? MENU_TITLE_DISABLE_COLOR : MENU_TITLE_COLOR);
+ lcdDrawSolidFilledRect(LCD_W - 128 + 4 * i, 30, 2, 8, i >= bars ? MENU_TITLE_DISABLE_COLOR : MENU_TITLE_COLOR);
}
-
topbar->refresh();
#if 0
diff --git a/radio/src/gui/480x272/view_statistics.cpp b/radio/src/gui/480x272/view_statistics.cpp
index a0cb92392..34eb9b0c2 100644
--- a/radio/src/gui/480x272/view_statistics.cpp
+++ b/radio/src/gui/480x272/view_statistics.cpp
@@ -27,7 +27,7 @@
bool menuStatsGraph(event_t event)
{
- switch(event) {
+ switch (event) {
case EVT_KEY_LONG(KEY_ENTER):
g_eeGeneral.globalTimer = 0;
storageDirty(EE_GENERAL);
@@ -127,7 +127,7 @@ bool menuStatsDebug(event_t event)
lcdDrawText(MENU_STATS_COLUMN1, y+1, "[Duration]", HEADER_COLOR|SMLSIZE);
lcdDrawNumber(lcdNextPos+5, y, 10*maxLuaDuration, LEFT, 0, NULL, "ms");
lcdDrawText(lcdNextPos+20, y+1, "[Interval]", HEADER_COLOR|SMLSIZE);
- lcdDrawNumber(lcdNextPos+5, y, 10*maxLuaDuration, LEFT, 0, NULL, "ms");
+ lcdDrawNumber(lcdNextPos+5, y, 10*maxLuaInterval, LEFT, 0, NULL, "ms");
y += FH;
// lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "Lua memory");
@@ -188,45 +188,6 @@ bool menuStatsDebug(event_t event)
return true;
}
-bool menuStatsAnalogs(event_t event)
-{
- SIMPLE_MENU("Analogs", STATS_ICONS, menuTabStats, e_StatsAnalogs, 1);
-
- for (uint8_t i=0; i 0
- else if (i >= MOUSE1)
- lcdDrawNumber(x+100, y, (int16_t)calibratedAnalogs[CALIBRATED_MOUSE1+i-MOUSE1]*25/256);
-#endif
-#endif
- }
-
- // RAS
- if ((isModuleXJT(INTERNAL_MODULE) && IS_INTERNAL_MODULE_ON()) || (isModulePXX1(EXTERNAL_MODULE) && !IS_INTERNAL_MODULE_ON())) {
- lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+7*FH, "RAS");
- lcdDrawNumber(MENUS_MARGIN_LEFT+100, MENU_CONTENT_TOP+7*FH, telemetryData.swrInternal.value());
- lcdDrawText(MENUS_MARGIN_LEFT + LCD_W/2, MENU_CONTENT_TOP+7*FH, "XJTVER");
- lcdDrawNumber(LCD_W/2 + MENUS_MARGIN_LEFT+100, MENU_CONTENT_TOP+7*FH, telemetryData.xjtVersion);
- }
-
-#if (NUM_PWMSTICKS > 0) && !defined(SIMU)
- lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+8*FH, STICKS_PWM_ENABLED() ? "Sticks: PWM" : "Sticks: ANA");
-#endif
-
- return true;
-}
-
-
#if defined(DEBUG_TRACE_BUFFER)
#define STATS_TRACES_INDEX_POS MENUS_MARGIN_LEFT
#define STATS_TRACES_TIME_POS MENUS_MARGIN_LEFT + 4*10
diff --git a/radio/src/gui/480x272/view_text.cpp b/radio/src/gui/480x272/view_text.cpp
index 3038887bf..e09f62699 100644
--- a/radio/src/gui/480x272/view_text.cpp
+++ b/radio/src/gui/480x272/view_text.cpp
@@ -42,7 +42,7 @@ bool menuTextView(event_t event)
break;
case EVT_ROTARY_RIGHT:
- if (menuVerticalOffset + NUM_BODY_LINES >= lines_count)
+ if (menuVerticalOffset + TEXT_VIEWER_LINES >= lines_count)
break;
else
++menuVerticalOffset;
@@ -55,19 +55,11 @@ bool menuTextView(event_t event)
break;
}
- for (int i=0; idrawTextMaxWidth(MENUS_MARGIN_LEFT, MENU_HEADER_HEIGHT + i * FH, reusableBuffer.viewText.lines[i], 0, LCD_W - 2 * MENUS_MARGIN_LEFT);
}
-#if 0
- char * title = s_text_file;
-#if defined(SIMU)
- if (!strncmp(title, "./", 2)) title += 2;
-#endif
- lcdDrawTextAlignedCenter(MENU_FOOTER_TOP, title, HEADER_COLOR);
-#endif
-
- drawVerticalScrollbar(LCD_W-5, 50, 195, menuVerticalOffset, lines_count, NUM_BODY_LINES);
+ drawVerticalScrollbar(LCD_W-5, 50, 195, menuVerticalOffset, lines_count, TEXT_VIEWER_LINES);
return true;
}
diff --git a/radio/src/gui/480x272/widget.h b/radio/src/gui/480x272/widget.h
index e0b4fa771..65a19ad2e 100644
--- a/radio/src/gui/480x272/widget.h
+++ b/radio/src/gui/480x272/widget.h
@@ -22,7 +22,9 @@
#define _WIDGET_H_
#include
+#include
#include "zone.h"
+#include "debug.h"
#define MAX_WIDGET_OPTIONS 5
diff --git a/radio/src/gui/480x272/widgets/gauge.cpp b/radio/src/gui/480x272/widgets/gauge.cpp
index 5e8772540..2558f8319 100644
--- a/radio/src/gui/480x272/widgets/gauge.cpp
+++ b/radio/src/gui/480x272/widgets/gauge.cpp
@@ -28,17 +28,17 @@ class GaugeWidget: public Widget
{
}
- virtual void refresh();
+ void refresh() override;
static const ZoneOption options[];
};
const ZoneOption GaugeWidget::options[] = {
- { "Source", ZoneOption::Source, OPTION_VALUE_UNSIGNED(1) },
- { "Min", ZoneOption::Integer, OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(RESX) },
- { "Max", ZoneOption::Integer, OPTION_VALUE_SIGNED(RESX), OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(RESX) },
- { "Color", ZoneOption::Color, OPTION_VALUE_UNSIGNED(RED) },
- { NULL, ZoneOption::Bool }
+ { STR_SOURCE, ZoneOption::Source, OPTION_VALUE_UNSIGNED(1) },
+ { STR_MIN, ZoneOption::Integer, OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(RESX) },
+ { STR_MAX, ZoneOption::Integer, OPTION_VALUE_SIGNED(RESX), OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(RESX) },
+ { STR_COLOR, ZoneOption::Color, OPTION_VALUE_UNSIGNED(RED) },
+ { nullptr, ZoneOption::Bool }
};
void GaugeWidget::refresh()
@@ -64,7 +64,7 @@ void GaugeWidget::refresh()
// Gauge
lcdSetColor(color);
lcdDrawSolidFilledRect(zone.x, zone.y + 16, zone.w, 16, TEXT_INVERTED_COLOR);
- lcdDrawNumber(zone.x+zone.w/2, zone.y + 17, percent, SMLSIZE | CUSTOM_COLOR | CENTERED, 0, NULL, "%");
+ lcdDrawNumber(zone.x + zone.w/2, zone.y + 16, percent, SMLSIZE | CUSTOM_COLOR | CENTERED, 0, nullptr, "%");
lcd->invertRect(zone.x + w, zone.y + 16, zone.w - w, 16, CUSTOM_COLOR);
}
diff --git a/radio/src/gui/480x272/widgets/modelbmp.cpp b/radio/src/gui/480x272/widgets/modelbmp.cpp
index 131d59b2b..09e632ab3 100644
--- a/radio/src/gui/480x272/widgets/modelbmp.cpp
+++ b/radio/src/gui/480x272/widgets/modelbmp.cpp
@@ -63,7 +63,7 @@ class ModelBitmapWidget: public Widget
}
}
- virtual void refresh()
+ void refresh() override
{
uint32_t new_hash = hash(g_model.header.bitmap, sizeof(g_model.header.bitmap));
new_hash ^= hash(g_model.header.name, sizeof(g_model.header.name));
diff --git a/radio/src/gui/480x272/widgets/outputs.cpp b/radio/src/gui/480x272/widgets/outputs.cpp
index 1365e4f72..467657519 100644
--- a/radio/src/gui/480x272/widgets/outputs.cpp
+++ b/radio/src/gui/480x272/widgets/outputs.cpp
@@ -33,7 +33,7 @@ class OutputsWidget: public Widget
{
}
- virtual void refresh();
+ void refresh() override;
uint8_t drawChannels(const uint16_t & x, const uint16_t & y, const uint16_t & w, const uint16_t & h, const uint8_t & firstChan, const bool & bg_shown, const uint16_t & bg_color)
{
@@ -86,9 +86,9 @@ class OutputsWidget: public Widget
};
const ZoneOption OutputsWidget::options[] = {
- { "First channel", ZoneOption::Integer, OPTION_VALUE_UNSIGNED(1), OPTION_VALUE_UNSIGNED(1), OPTION_VALUE_UNSIGNED(32) },
- { "Fill Background?", ZoneOption::Bool, OPTION_VALUE_BOOL(false) },
- { "BG Color", ZoneOption::Color, OPTION_VALUE_UNSIGNED(LIGHTGREY) },
+ { STR_FIRST_CHANNEL, ZoneOption::Integer, OPTION_VALUE_UNSIGNED(1), OPTION_VALUE_UNSIGNED(1), OPTION_VALUE_UNSIGNED(32) },
+ { STR_FILL_BACKGROUND, ZoneOption::Bool, OPTION_VALUE_BOOL(false) },
+ { STR_BG_COLOR, ZoneOption::Color, OPTION_VALUE_UNSIGNED(LIGHTGREY) },
{ NULL, ZoneOption::Bool }
};
diff --git a/radio/src/gui/480x272/widgets/text.cpp b/radio/src/gui/480x272/widgets/text.cpp
index 30d593be6..f297798eb 100644
--- a/radio/src/gui/480x272/widgets/text.cpp
+++ b/radio/src/gui/480x272/widgets/text.cpp
@@ -30,16 +30,16 @@ class TextWidget: public Widget
{
}
- virtual void refresh();
+ void refresh() override;
static const ZoneOption options[];
};
const ZoneOption TextWidget::options[] = {
- { "Text", ZoneOption::String, OPTION_VALUE_STRING(TEXT_WIDGET_DEFAULT_LABEL) },
- { "Color", ZoneOption::Color, OPTION_VALUE_UNSIGNED(RED) },
- { "Size", ZoneOption::TextSize, OPTION_VALUE_UNSIGNED(0) },
- { "Shadow", ZoneOption::Bool, OPTION_VALUE_BOOL(false) },
+ { STR_TEXT, ZoneOption::String, OPTION_VALUE_STRING(TEXT_WIDGET_DEFAULT_LABEL) },
+ { STR_COLOR, ZoneOption::Color, OPTION_VALUE_UNSIGNED(RED) },
+ { STR_SIZE, ZoneOption::TextSize, OPTION_VALUE_UNSIGNED(0) },
+ { STR_SHADOW, ZoneOption::Bool, OPTION_VALUE_BOOL(false) },
{ NULL, ZoneOption::Bool }
};
diff --git a/radio/src/gui/480x272/widgets/timer.cpp b/radio/src/gui/480x272/widgets/timer.cpp
index 1293a8701..58c53c4d4 100644
--- a/radio/src/gui/480x272/widgets/timer.cpp
+++ b/radio/src/gui/480x272/widgets/timer.cpp
@@ -28,13 +28,13 @@ class TimerWidget: public Widget
{
}
- virtual void refresh();
+ void refresh() override;
static const ZoneOption options[];
};
const ZoneOption TimerWidget::options[] = {
- { "Timer source", ZoneOption::Timer, OPTION_VALUE_UNSIGNED(0) },
+ { STR_TIMER_SOURCE, ZoneOption::Timer, OPTION_VALUE_UNSIGNED(0) },
{ NULL, ZoneOption::Bool }
};
diff --git a/radio/src/gui/480x272/widgets/value.cpp b/radio/src/gui/480x272/widgets/value.cpp
index 2a36ba7f3..c7fe6ce99 100644
--- a/radio/src/gui/480x272/widgets/value.cpp
+++ b/radio/src/gui/480x272/widgets/value.cpp
@@ -28,15 +28,15 @@ class ValueWidget: public Widget
{
}
- virtual void refresh();
+ void refresh() override;
static const ZoneOption options[];
};
const ZoneOption ValueWidget::options[] = {
- { "Source", ZoneOption::Source, OPTION_VALUE_UNSIGNED(MIXSRC_Rud) },
- { "Color", ZoneOption::Color, OPTION_VALUE_UNSIGNED(WHITE) },
- { "Shadow", ZoneOption::Bool, OPTION_VALUE_BOOL(false) },
+ { STR_SOURCE, ZoneOption::Source, OPTION_VALUE_UNSIGNED(MIXSRC_Rud) },
+ { STR_COLOR, ZoneOption::Color, OPTION_VALUE_UNSIGNED(WHITE) },
+ { STR_SHADOW, ZoneOption::Bool, OPTION_VALUE_BOOL(false) },
{ NULL, ZoneOption::Bool }
};
diff --git a/radio/src/gui/common/colorlcd/draw_functions.cpp b/radio/src/gui/common/colorlcd/draw_functions.cpp
index d78424855..3fe07f0e6 100644
--- a/radio/src/gui/common/colorlcd/draw_functions.cpp
+++ b/radio/src/gui/common/colorlcd/draw_functions.cpp
@@ -18,6 +18,7 @@
* GNU General Public License for more details.
*/
+#include
#include "opentx.h"
void drawStringWithIndex(coord_t x, coord_t y, const char * str, int idx, LcdFlags flags, const char * prefix, const char * suffix)
@@ -31,7 +32,7 @@ void drawStringWithIndex(coord_t x, coord_t y, const char * str, int idx, LcdFla
lcdDrawText(x, y, s, flags);
}
-void drawValueWithUnit(coord_t x, coord_t y, int val, uint8_t unit, LcdFlags att)
+void drawValueWithUnit(coord_t x, coord_t y, int32_t val, uint8_t unit, LcdFlags att)
{
// convertUnit(val, unit);
if (!(att & NO_UNIT) && unit != UNIT_RAW) {
@@ -201,6 +202,11 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value,
return;
}
+ if (IS_FAI_FORBIDDEN(MIXSRC_FIRST_TELEM + 3 * sensor)) {
+ lcdDrawText(x, y, "FAI mode", flags);
+ return;
+ }
+
TelemetryItem & telemetryItem = telemetryItems[sensor];
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[sensor];
diff --git a/radio/src/gui/common/colorlcd/draw_functions.h b/radio/src/gui/common/colorlcd/draw_functions.h
index 8f8ab6b3b..3d925b2af 100644
--- a/radio/src/gui/common/colorlcd/draw_functions.h
+++ b/radio/src/gui/common/colorlcd/draw_functions.h
@@ -24,7 +24,7 @@
#include "lcd.h"
void drawStringWithIndex(coord_t x, coord_t y, const char * str, int idx, LcdFlags flags, const char * prefix, const char * suffix);
-void drawValueWithUnit(coord_t x, coord_t y, int val, uint8_t unit, LcdFlags att);
+void drawValueWithUnit(coord_t x, coord_t y, int32_t val, uint8_t unit, LcdFlags att);
int editChoice(coord_t x, coord_t y, const char * values, int value, int min, int max, LcdFlags attr, event_t event, IsValueAvailable isValueAvailable=nullptr);
uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, LcdFlags attr, event_t event);
swsrc_t editSwitch(coord_t x, coord_t y, swsrc_t value, LcdFlags attr, event_t event);
diff --git a/radio/src/gui/common/stdlcd/CMakeLists.txt b/radio/src/gui/common/stdlcd/CMakeLists.txt
index 0d3f726b3..f20235ced 100644
--- a/radio/src/gui/common/stdlcd/CMakeLists.txt
+++ b/radio/src/gui/common/stdlcd/CMakeLists.txt
@@ -15,6 +15,7 @@ set(GUI_SRC
../common/stdlcd/radio_hardware.cpp
../common/stdlcd/radio_version.cpp
../common/stdlcd/radio_trainer.cpp
+ ../common/stdlcd/view_telemetry.cpp
model_curve_edit.cpp
)
diff --git a/radio/src/gui/common/stdlcd/draw_functions.cpp b/radio/src/gui/common/stdlcd/draw_functions.cpp
index fe8ac60dc..524b06a7b 100644
--- a/radio/src/gui/common/stdlcd/draw_functions.cpp
+++ b/radio/src/gui/common/stdlcd/draw_functions.cpp
@@ -84,7 +84,7 @@ void drawTrimMode(coord_t x, coord_t y, uint8_t flightMode, uint8_t idx, LcdFlag
}
}
-void drawValueWithUnit(coord_t x, coord_t y, int val, uint8_t unit, LcdFlags att)
+void drawValueWithUnit(coord_t x, coord_t y, int32_t val, uint8_t unit, LcdFlags att)
{
// convertUnit(val, unit);
lcdDrawNumber(x, y, val, att & (~NO_UNIT));
@@ -353,6 +353,11 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value,
return;
}
+ if (IS_FAI_FORBIDDEN(MIXSRC_FIRST_TELEM + 3 * sensor)) {
+ lcdDrawText(x, y, "FAI mode", flags);
+ return;
+ }
+
TelemetryItem & telemetryItem = telemetryItems[sensor];
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[sensor];
@@ -370,11 +375,11 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value,
lcdDrawText(x, y, "OK", flags);
}
else {
- for (uint8_t i=0; i<16; i++) {
- if (value & (1 << i)) {
+ for (uint8_t i = 0; i < 16; i++) {
+ if (value & (1u << i)) {
char s[] = "CH__ KO";
- strAppendUnsigned(&s[2], i+1, 2);
- lcdDrawText(x, flags & DBLSIZE ? y+1 : y, s, flags & ~DBLSIZE);
+ strAppendUnsigned(&s[2], i + 1, 2);
+ lcdDrawText(x, flags & DBLSIZE ? y + 1 : y, s, flags & ~DBLSIZE);
break;
}
}
@@ -382,7 +387,7 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value,
}
else {
if (value == 0) {
- lcdDrawText(x, flags & DBLSIZE ? y+1 : y, "Rx OK", flags & ~DBLSIZE);
+ lcdDrawText(x, flags & DBLSIZE ? y + 1 : y, "Rx OK", flags & ~DBLSIZE);
}
else {
static const char * const RXS_STATUS[] = {
@@ -398,23 +403,47 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value,
"Rx1 NS",
"Rx2 NS",
};
- for (uint8_t i=0; i= RB3040_OUTPUT_FIRST_ID && telemetrySensor.id <= RB3040_OUTPUT_LAST_ID) {
+ if (telemetrySensor.subId == 0) {
+ if (value == 0) {
+ lcdDrawText(x, y, "OK", flags);
+ }
+ else {
+ for (uint8_t i = 0; i < 9; i++) {
+ if (value & (1u << i)) {
+ if (i < 8) {
+ char s[] = "CH__ KO";
+ strAppendUnsigned(&s[2], i + 17, 2);
+ lcdDrawText(x, flags & DBLSIZE ? y + 1 : y, s, flags & ~DBLSIZE);
+ break;
+ }
+ else {
+ char s[] = "S.P Ovl";
+ lcdDrawText(x, flags & DBLSIZE ? y + 1 : y, s, flags & ~DBLSIZE);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
}
}
else if (telemetrySensor.unit == UNIT_TEXT) {
- lcdDrawSizedText(x, flags & DBLSIZE ? y+1 : y, telemetryItem.text, sizeof(telemetryItem.text), flags & ~DBLSIZE);
+ lcdDrawSizedText(x, flags & DBLSIZE ? y + 1 : y, telemetryItem.text, sizeof(telemetryItem.text), flags & ~DBLSIZE);
}
else {
if (telemetrySensor.prec > 0) {
- flags |= (telemetrySensor.prec==1 ? PREC1 : PREC2);
+ flags |= (telemetrySensor.prec == 1 ? PREC1 : PREC2);
}
drawValueWithUnit(x, y, value, telemetrySensor.unit == UNIT_CELLS ? UNIT_VOLTS : telemetrySensor.unit, flags);
}
diff --git a/radio/src/gui/common/stdlcd/draw_functions.h b/radio/src/gui/common/stdlcd/draw_functions.h
index acf4a949f..7755206e3 100644
--- a/radio/src/gui/common/stdlcd/draw_functions.h
+++ b/radio/src/gui/common/stdlcd/draw_functions.h
@@ -25,7 +25,7 @@
void lcdDrawMultiProtocolString(coord_t x, coord_t y, uint8_t moduleIdx, uint8_t protocol, LcdFlags flags = 0);
void lcdDrawMultiSubProtocolString(coord_t x, coord_t y, uint8_t moduleIdx, uint8_t subType, LcdFlags flags = 0);
void drawStringWithIndex(coord_t x, coord_t y, const char * str, uint8_t idx, LcdFlags att=0);
-void drawValueWithUnit(coord_t x, coord_t y, int val, uint8_t unit, LcdFlags att=0);
+void drawValueWithUnit(coord_t x, coord_t y, int32_t val, uint8_t unit, LcdFlags att=0);
void drawPower(coord_t x, coord_t y, int8_t dBm, LcdFlags att = 0);
void drawGVarName(coord_t x, coord_t y, int8_t index, LcdFlags flags=0);
diff --git a/radio/src/gui/common/stdlcd/model_curves.cpp b/radio/src/gui/common/stdlcd/model_curves.cpp
index b650a96ab..6fd7c1d0b 100644
--- a/radio/src/gui/common/stdlcd/model_curves.cpp
+++ b/radio/src/gui/common/stdlcd/model_curves.cpp
@@ -60,7 +60,7 @@ void menuModelCurvesAll(event_t event)
#endif
case EVT_KEY_FIRST(KEY_ENTER):
if (CURVE_SELECTED() && !READ_ONLY()) {
- s_curveChan = sub;
+ s_currIdxSubMenu = sub;
pushMenu(menuModelCurveOne);
}
break;
@@ -93,7 +93,7 @@ void menuModelCurvesAll(event_t event)
}
if (CURVE_SELECTED()) {
- s_curveChan = sub;
+ s_currIdxSubMenu = sub;
#if LCD_W >= 212
drawCurve(23);
#else
@@ -142,7 +142,7 @@ void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlag
drawCurveName(x, y, curve.value, flags);
if (active && menuHorizontalPosition==1) {
if (event==EVT_KEY_LONG(KEY_ENTER) && curve.value!=0) {
- s_curveChan = (curve.value<0 ? -curve.value-1 : curve.value-1);
+ s_currIdxSubMenu = (curve.value<0 ? -curve.value-1 : curve.value-1);
pushMenu(menuModelCurveOne);
}
else {
diff --git a/radio/src/gui/common/stdlcd/model_inputs.cpp b/radio/src/gui/common/stdlcd/model_inputs.cpp
index edf245654..c396db061 100644
--- a/radio/src/gui/common/stdlcd/model_inputs.cpp
+++ b/radio/src/gui/common/stdlcd/model_inputs.cpp
@@ -26,7 +26,7 @@
uint8_t getExposCount()
{
uint8_t count = 0;
- uint8_t ch ;
+ uint8_t ch;
for (int i=MAX_EXPOS-1 ; i>=0; i--) {
ch = EXPO_VALID(expoAddress(i));
diff --git a/radio/src/gui/common/stdlcd/model_mixes.cpp b/radio/src/gui/common/stdlcd/model_mixes.cpp
index c2714a3b0..d5324e509 100644
--- a/radio/src/gui/common/stdlcd/model_mixes.cpp
+++ b/radio/src/gui/common/stdlcd/model_mixes.cpp
@@ -26,7 +26,7 @@
uint8_t getMixesCount()
{
uint8_t count = 0;
- uint8_t ch ;
+ uint8_t ch;
for (int i=MAX_MIXERS-1; i>=0; i--) {
ch = mixAddress(i)->srcRaw;
diff --git a/radio/src/gui/common/stdlcd/model_receiver_options.cpp b/radio/src/gui/common/stdlcd/model_receiver_options.cpp
index ed4dbcd48..6ce66ee29 100644
--- a/radio/src/gui/common/stdlcd/model_receiver_options.cpp
+++ b/radio/src/gui/common/stdlcd/model_receiver_options.cpp
@@ -46,14 +46,18 @@ void onRxOptionsUpdateConfirm(const char * result)
enum {
ITEM_RECEIVER_SETTINGS_PWM_RATE,
ITEM_RECEIVER_SETTINGS_TELEMETRY,
+ ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW,
ITEM_RECEIVER_SETTINGS_SPORT_FPORT,
ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1,
ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED2,
ITEM_RECEIVER_SETTINGS_PINMAP_FIRST
};
+#define IS_RECEIVER_CAPABILITY_ENABLED(capability) (reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilities & (1 << capability))
+#define IF_RECEIVER_CAPABILITY(capability, count) uint8_t(IS_RECEIVER_CAPABILITY_ENABLED(capability) ? count : HIDDEN_ROW)
-#define IF_RECEIVER_CAPABILITY(capability, count) uint8_t((reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilities & (1 << capability)) ? count : HIDDEN_ROW)
+#define CH_ENABLE_SPORT 4
+#define CH_ENABLE_SBUS 5
void menuModelReceiverOptions(event_t event)
{
@@ -76,6 +80,7 @@ void menuModelReceiverOptions(event_t event)
SUBMENU_NOTITLE(ITEM_RECEIVER_SETTINGS_PINMAP_FIRST + outputsCount, {
0, // PWM rate
isModuleR9MAccess(g_moduleIdx) && receiverVariant == PXX2_VARIANT_EU && reusableBuffer.hardwareAndSettings.moduleSettings.txPower > 14 /*25mW*/ ? READONLY_ROW : (uint8_t)0, // Telemetry
+ IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_TELEMETRY_25MW, 0),
IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_FPORT, 0),
uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW),
uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW),
@@ -139,7 +144,7 @@ void menuModelReceiverOptions(event_t event)
switch (i) {
case ITEM_RECEIVER_SETTINGS_PWM_RATE:
- reusableBuffer.hardwareAndSettings.receiverSettings.pwmRate = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.pwmRate, RECEIVER_OPTIONS_2ND_COLUMN, y, isModuleR9MAccess(g_moduleIdx) ? "6.67ms PWM": "9ms PWM", attr, event);
+ reusableBuffer.hardwareAndSettings.receiverSettings.pwmRate = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.pwmRate, RECEIVER_OPTIONS_2ND_COLUMN, y, isModuleR9MAccess(g_moduleIdx) ? "6.67ms PWM": "7ms PWM", attr, event);
if (attr && checkIncDec_Ret) {
reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY;
}
@@ -152,6 +157,13 @@ void menuModelReceiverOptions(event_t event)
}
break;
+ case ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW:
+ reusableBuffer.hardwareAndSettings.receiverSettings.telemetry25mw = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.telemetry25mw, RECEIVER_OPTIONS_2ND_COLUMN, y, "25mw Tele", attr, event);
+ if (attr && checkIncDec_Ret) {
+ reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY;
+ }
+ break;
+
case ITEM_RECEIVER_SETTINGS_SPORT_FPORT:
reusableBuffer.hardwareAndSettings.receiverSettings.fport = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.fport, RECEIVER_OPTIONS_2ND_COLUMN, y, "F.Port", attr, event);
if (attr && checkIncDec_Ret) {
@@ -174,27 +186,49 @@ void menuModelReceiverOptions(event_t event)
if (pin < reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount) {
uint8_t & mapping = reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[pin];
uint8_t channel = g_model.moduleData[g_moduleIdx].channelsStart + mapping;
- int32_t channelValue = channelOutputs[channel];
lcdDrawText(0, y, STR_PIN);
lcdDrawNumber(lcdLastRightPos + 1, y, pin + 1);
- putsChn(7 * FW, y, channel + 1, attr);
+
+ uint8_t channelMax = sentModuleChannels(g_moduleIdx) - 1;
+ uint8_t selectionMax = channelMax;
+
+ if (IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6)) {
+ if (CH_ENABLE_SPORT == pin || CH_ENABLE_SBUS == pin)
+ selectionMax += 1;
+
+ if (CH_ENABLE_SPORT == pin && selectionMax == channel) {
+ lcdDrawText(7 * FW, y, "S.PORT", attr);
+ }
+ else if (CH_ENABLE_SBUS == pin && selectionMax == channel) {
+ lcdDrawText(7 * FW, y, "SBUS", attr);
+ }
+ else {
+ putsChn(7 * FW, y, channel + 1, attr);
+ }
+ }
+ else {
+ putsChn(7 * FW, y, channel + 1, attr);
+ }
// Channel
if (attr) {
- mapping = checkIncDec(event, mapping, 0, sentModuleChannels(g_moduleIdx) - 1);
+ mapping = checkIncDec(event, mapping, 0, selectionMax);
if (checkIncDec_Ret) {
reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY;
}
}
// Bargraph
-#if !defined(PCBX7) // X7 LCD doesn't like too many horizontal lines
- lcdDrawRect(RECEIVER_OPTIONS_2ND_COLUMN, y + 2, wbar + 1, 4);
-#endif
- const uint8_t lenChannel = limit(1, (abs(channelValue) * wbar / 2 + lim / 2) / lim, wbar / 2);
- const coord_t xChannel = (channelValue > 0) ? RECEIVER_OPTIONS_2ND_COLUMN + wbar / 2 : RECEIVER_OPTIONS_2ND_COLUMN + wbar / 2 + 1 - lenChannel;
- lcdDrawHorizontalLine(xChannel, y + 3, lenChannel, SOLID, 0);
- lcdDrawHorizontalLine(xChannel, y + 4, lenChannel, SOLID, 0);
+ if (channel <= channelMax) {
+ int32_t channelValue = channelOutputs[channel];
+ #if !defined(PCBX7) // X7 LCD doesn't like too many horizontal lines
+ lcdDrawRect(RECEIVER_OPTIONS_2ND_COLUMN, y + 2, wbar + 1, 4);
+ #endif
+ auto lenChannel = limit(1, (abs(channelValue) * wbar / 2 + lim / 2) / lim, wbar / 2);
+ auto xChannel = (channelValue > 0) ? RECEIVER_OPTIONS_2ND_COLUMN + wbar / 2 : RECEIVER_OPTIONS_2ND_COLUMN + wbar / 2 + 1 - lenChannel;
+ lcdDrawHorizontalLine(xChannel, y + 3, lenChannel, SOLID, 0);
+ lcdDrawHorizontalLine(xChannel, y + 4, lenChannel, SOLID, 0);
+ }
}
break;
}
diff --git a/radio/src/gui/common/stdlcd/model_setup_afhds3.cpp b/radio/src/gui/common/stdlcd/model_setup_afhds3.cpp
new file mode 100644
index 000000000..a094ef83a
--- /dev/null
+++ b/radio/src/gui/common/stdlcd/model_setup_afhds3.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+
+void onBindMenuAfhds3(const char * result)
+{
+ uint8_t moduleIdx = CURRENT_MODULE_EDITED(menuVerticalPosition - HEADER_LINE);
+
+ if (result == STR_AFHDS3_ONE_TO_ONE_TELEMETRY) {
+ g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry = 1;
+ }
+ else if (result == STR_AFHDS3_ONE_TO_MANY) {
+ g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry = 0;
+ }
+ else {
+ return;
+ }
+
+ moduleState[moduleIdx].mode = MODULE_MODE_BIND;
+}
+
+void startBindMenuAfhds3(uint8_t moduleIdx)
+{
+ uint8_t selection = 0;
+#if defined(AFHDS3)
+ POPUP_MENU_ADD_ITEM(STR_AFHDS3_ONE_TO_ONE_TELEMETRY);
+ POPUP_MENU_ADD_ITEM(STR_AFHDS3_ONE_TO_MANY);
+#endif
+ POPUP_MENU_SELECT_ITEM(selection);
+ POPUP_MENU_START(onBindMenuAfhds3);
+}
diff --git a/radio/src/gui/common/stdlcd/model_setup_pxx1.cpp b/radio/src/gui/common/stdlcd/model_setup_pxx1.cpp
index 24091dcd7..063c50cb9 100644
--- a/radio/src/gui/common/stdlcd/model_setup_pxx1.cpp
+++ b/radio/src/gui/common/stdlcd/model_setup_pxx1.cpp
@@ -22,27 +22,37 @@
void onBindMenu(const char * result)
{
uint8_t moduleIdx = CURRENT_MODULE_EDITED(menuVerticalPosition - HEADER_LINE);
+ uint8_t receiverTelemetryOff, receiverHigherChannels;
if (result == STR_BINDING_1_8_TELEM_ON) {
- g_model.moduleData[moduleIdx].pxx.receiverTelemetryOff = false;
- g_model.moduleData[moduleIdx].pxx.receiverHigherChannels = false;
+ receiverTelemetryOff = false;
+ receiverHigherChannels = false;
}
else if (result == STR_BINDING_1_8_TELEM_OFF) {
- g_model.moduleData[moduleIdx].pxx.receiverTelemetryOff = true;
- g_model.moduleData[moduleIdx].pxx.receiverHigherChannels = false;
+ receiverTelemetryOff = true;
+ receiverHigherChannels = false;
}
else if (result == STR_BINDING_9_16_TELEM_ON) {
- g_model.moduleData[moduleIdx].pxx.receiverTelemetryOff = false;
- g_model.moduleData[moduleIdx].pxx.receiverHigherChannels = true;
+ receiverTelemetryOff = false;
+ receiverHigherChannels = true;
}
else if (result == STR_BINDING_9_16_TELEM_OFF) {
- g_model.moduleData[moduleIdx].pxx.receiverTelemetryOff = true;
- g_model.moduleData[moduleIdx].pxx.receiverHigherChannels = true;
+ receiverTelemetryOff = true;
+ receiverHigherChannels = true;
}
else {
return;
}
+ if (isModuleMultimodule(moduleIdx)) {
+ g_model.moduleData[moduleIdx].multi.receiverTelemetryOff = receiverTelemetryOff;
+ g_model.moduleData[moduleIdx].multi.receiverHigherChannels = receiverHigherChannels;
+ }
+ else {
+ g_model.moduleData[moduleIdx].pxx.receiverTelemetryOff = receiverTelemetryOff;
+ g_model.moduleData[moduleIdx].pxx.receiverHigherChannels = receiverHigherChannels;
+ }
+
moduleState[moduleIdx].mode = MODULE_MODE_BIND;
}
@@ -70,5 +80,6 @@ void startBindMenu(uint8_t moduleIdx)
selection += 1;
POPUP_MENU_SELECT_ITEM(selection);
+ POPUP_MENU_TITLE(STR_SELECT_MODE);
POPUP_MENU_START(onBindMenu);
}
diff --git a/radio/src/gui/common/stdlcd/model_setup_pxx2.cpp b/radio/src/gui/common/stdlcd/model_setup_pxx2.cpp
index 2d97f44dc..13ee54942 100644
--- a/radio/src/gui/common/stdlcd/model_setup_pxx2.cpp
+++ b/radio/src/gui/common/stdlcd/model_setup_pxx2.cpp
@@ -304,7 +304,7 @@ void modelSetupModulePxx2ReceiverLine(uint8_t moduleIdx, uint8_t receiverIdx, co
for (auto rx = 0; rx < popupMenuItemsCount; rx++) {
popupMenuItems[rx] = reusableBuffer.moduleSetup.bindInformation.candidateReceiversNames[rx];
}
- popupMenuTitle = STR_PXX2_SELECT_RX;
+ POPUP_MENU_TITLE(STR_PXX2_SELECT_RX);
POPUP_MENU_START(onPXX2BindMenu);
}
}
diff --git a/radio/src/gui/common/stdlcd/popups.cpp b/radio/src/gui/common/stdlcd/popups.cpp
index 6c86dff68..5725d0ad0 100644
--- a/radio/src/gui/common/stdlcd/popups.cpp
+++ b/radio/src/gui/common/stdlcd/popups.cpp
@@ -227,7 +227,7 @@ void showAlertBox(const char * title, const char * text, const char * action , u
lcdRefresh();
lcdSetContrast();
waitKeysReleased();
- backlightOn();
+ resetBacklightTimeout();
checkBacklight();
}
diff --git a/radio/src/gui/common/stdlcd/popups.h b/radio/src/gui/common/stdlcd/popups.h
index 64baac2f6..7c74ceacb 100644
--- a/radio/src/gui/common/stdlcd/popups.h
+++ b/radio/src/gui/common/stdlcd/popups.h
@@ -80,6 +80,7 @@ enum
{
warningText = nullptr;
warningInfoText = nullptr;
+ popupMenuTitle = nullptr;
popupMenuHandler = nullptr;
popupMenuItemsCount = 0;
}
@@ -166,6 +167,11 @@ inline void POPUP_MENU_SELECT_ITEM(uint8_t index)
popupMenuSelectedItem = (index > 0 ? (index < popupMenuItemsCount ? index : popupMenuItemsCount) : 0);
}
+inline void POPUP_MENU_TITLE(const char * s)
+{
+ popupMenuTitle = s;
+}
+
inline void POPUP_MENU_START(PopupMenuHandler handler)
{
if (handler != popupMenuHandler) {
diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp
index a64489528..dde563d6a 100644
--- a/radio/src/gui/common/stdlcd/radio_hardware.cpp
+++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp
@@ -184,6 +184,9 @@ enum {
ITEM_RADIO_HARDWARE_JITTER_FILTER,
ITEM_RADIO_HARDWARE_RAS,
+#if defined(SPORT_UPDATE_PWR_GPIO)
+ ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER,
+#endif
ITEM_RADIO_HARDWARE_DEBUG,
#if defined(EEPROM_RLC)
ITEM_RADIO_BACKUP_EEPROM,
@@ -295,6 +298,12 @@ void onHardwareAntennaSwitchConfirm(const char * result)
#define HW_SETTINGS_COLUMN2 (HW_SETTINGS_COLUMN1 + 5*FW)
#endif
+#if defined(SPORT_UPDATE_PWR_GPIO)
+ #define SPORT_POWER_ROWS 0,
+#else
+ #define SPORT_POWER_ROWS
+#endif
+
#if defined(EEPROM_RLC)
void onFactoryResetConfirm(const char * result)
{
@@ -334,7 +343,7 @@ void menuRadioHardware(event_t event)
0 /* ADC filter */,
READONLY_ROW /* RAS */,
-
+ SPORT_POWER_ROWS
1 /* debugs */,
0,
@@ -615,16 +624,16 @@ void menuRadioHardware(event_t event)
break;
case ITEM_RADIO_HARDWARE_RAS:
-#if defined(PCBX9LITE) && !defined(PCBX9LITES)
- lcdDrawTextAlignedLeft(y, "Ext. RAS");
- lcdNextPos = HW_SETTINGS_COLUMN2;
-#else
+#if defined(HARDWARE_INTERNAL_RAS)
lcdDrawTextAlignedLeft(y, "RAS");
if (telemetryData.swrInternal.isFresh())
lcdDrawNumber(HW_SETTINGS_COLUMN2, y, telemetryData.swrInternal.value());
else
lcdDrawText(HW_SETTINGS_COLUMN2, y, "---");
lcdDrawText(lcdNextPos, y, "/");
+#else
+ lcdDrawTextAlignedLeft(y, "Ext. RAS");
+ lcdNextPos = HW_SETTINGS_COLUMN2;
#endif
if (telemetryData.swrExternal.isFresh())
lcdDrawNumber(lcdNextPos, y, telemetryData.swrExternal.value());
@@ -632,6 +641,15 @@ void menuRadioHardware(event_t event)
lcdDrawText(lcdNextPos, y, "---");
break;
+#if defined(SPORT_UPDATE_PWR_GPIO)
+ case ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER:
+ g_eeGeneral.sportUpdatePower = editChoice(HW_SETTINGS_COLUMN2, y, STR_SPORT_UPDATE_POWER_MODE, STR_SPORT_UPDATE_POWER_MODES, g_eeGeneral.sportUpdatePower, 0, 1, attr, event);
+ if (attr && checkIncDec_Ret) {
+ SPORT_UPDATE_POWER_INIT();
+ }
+ break;
+#endif
+
case ITEM_RADIO_HARDWARE_DEBUG:
lcdDrawTextAlignedLeft(y, STR_DEBUG);
lcdDrawText(HW_SETTINGS_COLUMN2, y, STR_ANALOGS_BTN, menuHorizontalPosition == 0 ? attr : 0);
diff --git a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp
index d83110fbc..ffb4ff0bd 100644
--- a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp
+++ b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp
@@ -94,12 +94,12 @@ void onSdFormatConfirm(const char * result)
void onUpdateConfirmation(const char * result)
{
if (result == STR_OK) {
- OtaUpdateInformation * destination = moduleState[EXTERNAL_MODULE].otaUpdateInformation;
- Pxx2OtaUpdate otaUpdate(EXTERNAL_MODULE, destination->candidateReceiversNames[destination->selectedReceiverIndex]);
+ OtaUpdateInformation * destination = moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].otaUpdateInformation;
+ Pxx2OtaUpdate otaUpdate(reusableBuffer.sdManager.otaUpdateInformation.module, destination->candidateReceiversNames[destination->selectedReceiverIndex]);
otaUpdate.flashFirmware(destination->filename);
}
else {
- moduleState[EXTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
}
}
@@ -121,13 +121,13 @@ void onUpdateStateChanged()
else {
POPUP_WARNING(STR_OTA_UPDATE_ERROR);
SET_WARNING_INFO(STR_UNSUPPORTED_RX, sizeof(TR_UNSUPPORTED_RX) - 1, 0);
- moduleState[EXTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
}
}
else {
POPUP_WARNING(STR_OTA_UPDATE_ERROR);
SET_WARNING_INFO(STR_UNKNOWN_RX, sizeof(TR_UNKNOWN_RX) - 1, 0);
- moduleState[EXTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
}
}
}
@@ -246,10 +246,11 @@ void onSdManagerMenu(const char * result)
}
#endif
#if defined(PXX2)
- else if (result == STR_FLASH_RECEIVER_OTA) {
+ else if (result == STR_FLASH_RECEIVER_OTA_BY_INTERNAL || result == STR_FLASH_RECEIVER_OTA_BY_EXTERNAL) {
memclear(&reusableBuffer.sdManager.otaUpdateInformation, sizeof(OtaUpdateInformation));
getSelectionFullPath(reusableBuffer.sdManager.otaUpdateInformation.filename);
- moduleState[EXTERNAL_MODULE].startBind(&reusableBuffer.sdManager.otaUpdateInformation, onUpdateStateChanged);
+ reusableBuffer.sdManager.otaUpdateInformation.module = result == STR_FLASH_RECEIVER_OTA_BY_INTERNAL ? INTERNAL_MODULE : EXTERNAL_MODULE;
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].startBind(&reusableBuffer.sdManager.otaUpdateInformation, onUpdateStateChanged);
}
#endif
#endif
@@ -274,7 +275,7 @@ void onUpdateReceiverSelection(const char * result)
}
else {
// the user pressed [Exit]
- moduleState[EXTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
}
}
#endif
@@ -285,12 +286,14 @@ void menuRadioSdManager(event_t _event)
int lastPos = menuVerticalPosition;
#endif
- if (moduleState[EXTERNAL_MODULE].mode == MODULE_MODE_BIND && EVT_KEY_MASK(_event) == KEY_EXIT) {
- moduleState[EXTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
+#if defined(PXX2)
+ if (EVT_KEY_MASK(_event) == KEY_EXIT && moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode == MODULE_MODE_BIND) {
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode = MODULE_MODE_NORMAL;
CLEAR_POPUP();
killEvents(KEY_EXIT);
_event = 0;
}
+#endif
event_t event = (EVT_KEY_MASK(_event) == KEY_ENTER ? 0 : _event);
SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabGeneral, MENU_RADIO_SD_MANAGER, HEADER_LINE + reusableBuffer.sdManager.count);
@@ -298,17 +301,17 @@ void menuRadioSdManager(event_t _event)
switch (_event) {
case EVT_ENTRY:
f_chdir(ROOT_PATH);
- REFRESH_FILES();
#if LCD_DEPTH > 1
lastPos = -1;
#endif
- break;
+ // no break
case EVT_ENTRY_UP:
+ memclear(&reusableBuffer.sdManager, sizeof(reusableBuffer.sdManager));
REFRESH_FILES();
break;
-#if defined(PCBX9) || defined(RADIO_X7) // TODO NO_MENU_KEY
+#if defined(PCBX9) || defined(RADIO_X7) || defined(RADIO_X7ACCESS) // TODO NO_MENU_KEY
case EVT_KEY_LONG(KEY_MENU):
if (SD_CARD_PRESENT() && !READ_ONLY() && s_editMode == 0) {
killEvents(_event);
@@ -344,7 +347,7 @@ void menuRadioSdManager(event_t _event)
break;
case EVT_KEY_LONG(KEY_ENTER):
-#if !defined(PCBX9) && !defined(RADIO_X7) // TODO NO_HEADER_LINE
+#if !defined(PCBX9) && !defined(RADIO_X7) && !defined(RADIO_X7ACCESS) // TODO NO_HEADER_LINE
if (menuVerticalPosition < HEADER_LINE) {
killEvents(_event);
POPUP_MENU_ADD_ITEM(STR_SD_INFO);
@@ -417,8 +420,12 @@ void menuRadioSdManager(event_t _event)
POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MODULE);
}
#if defined(PXX2)
- if (information.productFamily == FIRMWARE_FAMILY_RECEIVER)
- POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA);
+ if (information.productFamily == FIRMWARE_FAMILY_RECEIVER) {
+ if (isReceiverOTAEnabledFromModule(INTERNAL_MODULE, information.productId))
+ POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA_BY_INTERNAL);
+ if (isReceiverOTAEnabledFromModule(EXTERNAL_MODULE, information.productId))
+ POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA_BY_EXTERNAL);
+ }
#endif
#if defined(BLUETOOTH)
if (information.productFamily == FIRMWARE_FAMILY_BLUETOOTH_CHIP)
@@ -564,16 +571,16 @@ void menuRadioSdManager(event_t _event)
}
#if defined(PXX2)
- if (moduleState[EXTERNAL_MODULE].mode == MODULE_MODE_BIND) {
+ if (moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].mode == MODULE_MODE_BIND) {
if (reusableBuffer.sdManager.otaUpdateInformation.step == BIND_INIT) {
if (reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversCount > 0) {
- if(reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversCount != popupMenuItemsCount) {
+ if (reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversCount != popupMenuItemsCount) {
CLEAR_POPUP();
- popupMenuItemsCount = min(reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversCount,PXX2_MAX_RECEIVERS_PER_MODULE);
+ popupMenuItemsCount = min(reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversCount, PXX2_MAX_RECEIVERS_PER_MODULE);
for (auto rx = 0; rx < popupMenuItemsCount; rx++) {
popupMenuItems[rx] = reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversNames[rx];
}
- popupMenuTitle = STR_PXX2_SELECT_RX;
+ POPUP_MENU_TITLE(STR_PXX2_SELECT_RX);
POPUP_MENU_START(onUpdateReceiverSelection);
}
}
diff --git a/radio/src/gui/common/stdlcd/radio_tools.cpp b/radio/src/gui/common/stdlcd/radio_tools.cpp
index b2d13cba5..d5bfd12d4 100644
--- a/radio/src/gui/common/stdlcd/radio_tools.cpp
+++ b/radio/src/gui/common/stdlcd/radio_tools.cpp
@@ -25,15 +25,20 @@ extern uint8_t g_moduleIdx;
bool addRadioTool(uint8_t index, const char * label)
{
- int8_t sub = menuVerticalPosition - HEADER_LINE;
- LcdFlags attr = (sub == index ? INVERS : 0);
- coord_t y = MENU_HEADER_HEIGHT + 1 + index * FH;
- lcdDrawNumber(3, y, index + 1, LEADING0|LEFT, 2);
- lcdDrawText(3*FW, y, label, (sub == index ? INVERS : 0));
- if (attr && s_editMode > 0) {
- s_editMode = 0;
- killAllEvents();
- return true;
+ if (index >= menuVerticalOffset) {
+ uint8_t lineIndex = index - menuVerticalOffset;
+ if (lineIndex < NUM_BODY_LINES) {
+ int8_t sub = menuVerticalPosition - HEADER_LINE;
+ LcdFlags attr = (sub == index ? INVERS : 0);
+ coord_t y = MENU_HEADER_HEIGHT + lineIndex * FH;
+ lcdDrawNumber(3, y, index + 1, LEADING0 | LEFT, 2);
+ lcdDrawText(3 * FW, y, label, (sub == index ? INVERS : 0));
+ if (attr && s_editMode > 0) {
+ s_editMode = 0;
+ killAllEvents();
+ return true;
+ }
+ }
}
return false;
}
@@ -82,23 +87,7 @@ void menuRadioTools(event_t event)
uint8_t index = 0;
-#if defined(INTERNAL_MODULE_PXX2)
- if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER))
- addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
- if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
- addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE);
-#elif defined(INTERNAL_MODULE_MULTI)
- addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
-#endif
-#if defined(PXX2)|| defined(MULTIMODULE)
- if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER) || isModuleMultimodule(EXTERNAL_MODULE))
- addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE);
-#endif
-#if defined(PXX2)
- if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
- addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE);
-#endif
#if defined(LUA)
FILINFO fno;
@@ -122,6 +111,24 @@ void menuRadioTools(event_t event)
}
#endif
+#if defined(INTERNAL_MODULE_PXX2)
+ if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER))
+ addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
+
+ if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
+ addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE);
+#elif defined(INTERNAL_MODULE_MULTI)
+ addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
+#endif
+#if defined(PXX2)|| defined(MULTIMODULE)
+ if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER) || isModuleMultimodule(EXTERNAL_MODULE))
+ addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE);
+#endif
+#if defined(PXX2)
+ if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
+ addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE);
+#endif
+
if (index == 0) {
lcdDrawCenteredText(LCD_H/2, STR_NO_TOOLS);
}
diff --git a/radio/src/gui/common/stdlcd/radio_trainer.cpp b/radio/src/gui/common/stdlcd/radio_trainer.cpp
index 58c338a8d..c14e27604 100644
--- a/radio/src/gui/common/stdlcd/radio_trainer.cpp
+++ b/radio/src/gui/common/stdlcd/radio_trainer.cpp
@@ -21,9 +21,9 @@
#include "opentx.h"
#if LCD_W >= 212
- #define TRAINER_CALIB_COLUMN_WIDTH 12
+ #define TRAINER_CALIB_COLUMN_WIDTH (6 * FW)
#else
- #define TRAINER_CALIB_COLUMN_WIDTH 8
+ #define TRAINER_CALIB_COLUMN_WIDTH (4 * FW + 2)
#endif
void menuRadioTrainer(event_t event)
@@ -86,8 +86,8 @@ void menuRadioTrainer(event_t event)
if (attr)
s_editMode = 0;
lcdDrawText(0*FW, MENU_HEADER_HEIGHT+1+6*FH, STR_CAL, attr);
- for (uint8_t i=0; i<4; i++) {
- uint8_t x = (i*TRAINER_CALIB_COLUMN_WIDTH + 16) * FW/2;
+ for (uint8_t i = 0; i < 4; i++) {
+ uint8_t x = 8*FW + (i * TRAINER_CALIB_COLUMN_WIDTH);
int32_t chVal = ppmInput[i] - g_eeGeneral.trainer.calib[i];
chVal *= g_eeGeneral.trainer.mix[i].studWeight * 10;
chVal /= 512;
diff --git a/radio/src/gui/common/stdlcd/radio_version.cpp b/radio/src/gui/common/stdlcd/radio_version.cpp
index ce6e30e59..d6128ecb7 100644
--- a/radio/src/gui/common/stdlcd/radio_version.cpp
+++ b/radio/src/gui/common/stdlcd/radio_version.cpp
@@ -222,7 +222,7 @@ void menuRadioModulesVersion(event_t event)
enum MenuRadioVersionItems
{
ITEM_RADIO_VERSION_FIRST = HEADER_LINE - 1,
-#if defined(PCBTARANIS) || defined(PCBHORUS)
+#if defined(PCBTARANIS)
ITEM_RADIO_FIRMWARE_OPTIONS,
#endif
#if defined(PXX2)
@@ -250,7 +250,7 @@ void menuRadioVersion(event_t event)
y += 2;
-#if defined(PCBTARANIS) || defined(PCBHORUS)
+#if defined(PCBTARANIS)
lcdDrawText(INDENT_WIDTH, y, BUTTON(TR_FIRMWARE_OPTIONS), menuVerticalPosition == ITEM_RADIO_FIRMWARE_OPTIONS ? INVERS : 0);
y += FH;
if (menuVerticalPosition == ITEM_RADIO_FIRMWARE_OPTIONS && event == EVT_KEY_BREAK(KEY_ENTER)) {
diff --git a/radio/src/gui/common/stdlcd/view_telemetry.cpp b/radio/src/gui/common/stdlcd/view_telemetry.cpp
new file mode 100644
index 000000000..61b506269
--- /dev/null
+++ b/radio/src/gui/common/stdlcd/view_telemetry.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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 "opentx.h"
+
+extern bool displayTelemetryScreen();
+extern void displayRssiLine();
+
+enum NavigationDirection {
+ NAVIGATION_DIRECTION_NONE,
+ NAVIGATION_DIRECTION_UP,
+ NAVIGATION_DIRECTION_DOWN
+};
+#define decrTelemetryScreen() direction = NAVIGATION_DIRECTION_UP
+#define incrTelemetryScreen() direction = NAVIGATION_DIRECTION_DOWN
+
+#if defined(NAVIGATION_XLITE)
+ #define EVT_KEY_PREVIOUS_VIEW(evt) (evt == EVT_KEY_LONG(KEY_LEFT) && IS_SHIFT_PRESSED())
+ #define EVT_KEY_NEXT_VIEW(evt) (evt == EVT_KEY_LONG(KEY_RIGHT) && IS_SHIFT_PRESSED())
+#elif defined(NAVIGATION_X7) || defined(NAVIGATION_X9D)
+ #define EVT_KEY_PREVIOUS_VIEW(evt) (evt == EVT_KEY_LONG(KEY_PAGE))
+ #define EVT_KEY_NEXT_VIEW(evt) (evt == EVT_KEY_BREAK(KEY_PAGE))
+#elif defined(NAVIGATION_9X)
+ #define EVT_KEY_PREVIOUS_VIEW(evt) (evt == EVT_KEY_LONG(KEY_UP))
+ #define EVT_KEY_NEXT_VIEW(evt) (evt == EVT_KEY_LONG(KEY_DOWN))
+#else
+ #define EVT_KEY_PREVIOUS_VIEW(evt) (evt == EVT_KEY_FIRST(KEY_UP))
+ #define EVT_KEY_NEXT_VIEW(evt) (evt == EVT_KEY_FIRST(KEY_DOWN))
+#endif
+
+void menuViewTelemetry(event_t event)
+{
+ enum NavigationDirection direction = NAVIGATION_DIRECTION_NONE;
+
+ if (event == EVT_KEY_FIRST(KEY_EXIT) && TELEMETRY_SCREEN_TYPE(s_frsky_view) != TELEMETRY_SCREEN_TYPE_SCRIPT) {
+ killEvents(event);
+ chainMenu(menuMainView);
+ }
+#if defined(LUA)
+ else if (event == EVT_KEY_LONG(KEY_EXIT)) {
+ killEvents(event);
+ chainMenu(menuMainView);
+ }
+#endif
+ else if (EVT_KEY_PREVIOUS_VIEW(event)) {
+ killEvents(event);
+ decrTelemetryScreen();
+ }
+ else if (EVT_KEY_NEXT_VIEW(event)) {
+ killEvents(event);
+ incrTelemetryScreen();
+ }
+ else if (event == EVT_KEY_LONG(KEY_ENTER)) {
+ killEvents(event);
+ POPUP_MENU_ADD_ITEM(STR_RESET_TELEMETRY);
+ POPUP_MENU_ADD_ITEM(STR_RESET_FLIGHT);
+ POPUP_MENU_START(onMainViewMenu);
+ }
+
+ for (int i=0; i<=TELEMETRY_SCREEN_TYPE_MAX; i++) {
+ if (direction == NAVIGATION_DIRECTION_UP) {
+ if (s_frsky_view-- == 0)
+ s_frsky_view = TELEMETRY_VIEW_MAX;
+ }
+ else if (direction == NAVIGATION_DIRECTION_DOWN) {
+ if (s_frsky_view++ == TELEMETRY_VIEW_MAX)
+ s_frsky_view = 0;
+ }
+ else {
+ direction = NAVIGATION_DIRECTION_DOWN;
+ }
+ if (displayTelemetryScreen()) {
+ return;
+ }
+ }
+
+ drawTelemetryTopBar();
+ lcdDrawText(LCD_W / 2, 3 * FH, STR_NO_TELEMETRY_SCREENS, CENTERED);
+ displayRssiLine();
+}
+
+#undef EVT_KEY_PREVIOUS_VIEW
+#undef EVT_KEY_NEXT_VIEW
diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp
index d3b826b28..b491d84b4 100644
--- a/radio/src/gui/gui_common.cpp
+++ b/radio/src/gui/gui_common.cpp
@@ -385,6 +385,24 @@ bool isSwitchAvailable(int swtch, SwitchContext context)
return true;
}
+bool isAux1ModeAvailable(int mode)
+{
+#if defined(AUX2_SERIAL)
+ if (mode == UART_MODE_SBUS_TRAINER)
+ return g_eeGeneral.aux2SerialMode != UART_MODE_SBUS_TRAINER;
+#endif
+ return true;
+}
+
+bool isAux2ModeAvailable(int mode)
+{
+#if defined(AUX_SERIAL)
+ if (mode == UART_MODE_SBUS_TRAINER)
+ return g_eeGeneral.auxSerialMode != UART_MODE_SBUS_TRAINER;
+#endif
+ return true;
+}
+
bool isSwitchAvailableInLogicalSwitches(int swtch)
{
return isSwitchAvailable(swtch, LogicalSwitchesContext);
@@ -551,6 +569,7 @@ bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType)
case MODULE_TYPE_ISRM_PXX2:
case MODULE_TYPE_R9M_LITE_PXX2:
case MODULE_TYPE_R9M_LITE_PRO_PXX2:
+ case MODULE_TYPE_AFHDS3:
return false;
case MODULE_TYPE_XJT_PXX1:
@@ -663,6 +682,11 @@ bool isExternalModuleAvailable(int moduleType)
return false;
#endif
+#if !defined(AFHDS3)
+ if (moduleType == MODULE_TYPE_AFHDS3)
+ return false;
+#endif
+
return true;
}
@@ -708,6 +732,12 @@ bool isTelemetryProtocolAvailable(int protocol)
}
#endif
+#if !defined(AFHDS3)
+ if (protocol == PROTOCOL_TELEMETRY_AFHDS3) {
+ return false;
+ }
+#endif
+
#if defined(PCBHORUS)
if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
return false;
@@ -724,6 +754,13 @@ bool isTrainerModeAvailable(int mode)
return false;
#endif
+#if defined(PCBX9E)
+ if (g_eeGeneral.bluetoothMode && mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE) {
+ // bluetooth uses the same USART than SBUS
+ return false;
+ }
+#endif
+
#if defined(PCBTARANIS) && !defined(TRAINER_BATTERY_COMPARTMENT)
if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
return false;
@@ -732,12 +769,12 @@ bool isTrainerModeAvailable(int mode)
return g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER;
#endif
-#if defined(PCBX9E)
- if (mode == TRAINER_MODE_MASTER_BLUETOOTH || mode == TRAINER_MODE_SLAVE_BLUETOOTH)
- return false;
-#elif defined(BLUETOOTH)
+#if defined(BLUETOOTH) && !defined(PCBX9E)
if (g_eeGeneral.bluetoothMode != BLUETOOTH_TRAINER && (mode == TRAINER_MODE_MASTER_BLUETOOTH || mode == TRAINER_MODE_SLAVE_BLUETOOTH))
return false;
+#elif !defined(PCBSKY9X)
+ if (mode == TRAINER_MODE_MASTER_BLUETOOTH || mode == TRAINER_MODE_SLAVE_BLUETOOTH)
+ return false;
#endif
#if defined(PCBXLITE) && !defined(PCBXLITES)
@@ -782,7 +819,7 @@ int getFirstAvailable(int min, int max, IsValueAvailable isValueAvailable)
#if defined(MULTIMODULE)
// This maps OpenTX multi type with Pascal's Multi type
-uint8_t convertMultiProtocol(uint8_t moduleIdx, uint8_t type)
+uint8_t multiConvertOtxToMulti(uint8_t moduleIdx, uint8_t type)
{
// 15 for Multimodule is FrskyX or D16 which we map as a subprotocol of 3 (FrSky)
@@ -796,7 +833,7 @@ uint8_t convertMultiProtocol(uint8_t moduleIdx, uint8_t type)
if (type == MODULE_SUBTYPE_MULTI_FRSKY) {
int subtype = g_model.moduleData[moduleIdx].subType;
- if (subtype == MM_RF_FRSKY_SUBTYPE_D8) {
+ if (subtype == MM_RF_FRSKY_SUBTYPE_D8 || subtype == MM_RF_FRSKY_SUBTYPE_D8_CLONED) {
//D8
type = 3;
}
@@ -811,6 +848,27 @@ uint8_t convertMultiProtocol(uint8_t moduleIdx, uint8_t type)
return type;
}
+// This maps multi type to OpenTX number, type ONLY (no subtype)
+int convertMultiToOtx(int type)
+{
+ if (type == 3) //FrSkyD
+ return MODULE_SUBTYPE_MULTI_FRSKY;
+
+ if (type == 15) //FrSkyX
+ return MODULE_SUBTYPE_MULTI_FRSKY;
+
+ if (type == 25) //FrSkyV
+ return MODULE_SUBTYPE_MULTI_FRSKY;
+
+ if (type > 25)
+ type = type - 1;
+
+ if (type > 15)
+ type = type - 1;
+
+ return type - 1; //Multi list starts at 1
+}
+
// Third row is number of subtypes -1 (max valid subtype)
#define NO_SUBTYPE nullptr
@@ -824,10 +882,10 @@ uint8_t convertMultiProtocol(uint8_t moduleIdx, uint8_t type)
const char STR_SUBTYPE_FLYSKY[] = "\004""Std\0""V9x9""V6x6""V912""CX20";
const char STR_SUBTYPE_HUBSAN[] = "\004""H107""H301""H501";
-const char STR_SUBTYPE_FRSKY[] = "\007""D16\0 ""D8\0 ""D16 8ch""V8\0 ""LBT(EU)""LBT 8ch";
+const char STR_SUBTYPE_FRSKY[] = "\011""D16\0 ""D8\0 ""D16 8ch\0 ""V8\0 ""LBT(EU)\0 ""LBT 8ch\0 ""D8Cloned\0""D16Cloned";
const char STR_SUBTYPE_HISKY[] = "\005""Std\0 ""HK310";
-const char STR_SUBTYPE_V2X2[] = "\006""Std\0 ""JXD506";
-const char STR_SUBTYPE_DSM[] = "\006""2 22ms""2 11ms""X 22ms""X 11ms";
+const char STR_SUBTYPE_V2X2[] = "\006""Std\0 ""JXD506""MR101\0";
+const char STR_SUBTYPE_DSM[] = "\004""2 1F""2 2F""X 1F""X 2F";
const char STR_SUBTYPE_DEVO[] = "\004""8ch\0""10ch""12ch""6ch\0""7ch\0";
const char STR_SUBTYPE_YD717[] = "\007""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 ";
const char STR_SUBTYPE_KN[] = "\006""WLtoys""FeiLun";
@@ -835,7 +893,8 @@ const char STR_SUBTYPE_SYMAX[] = "\003""Std""X5C";
const char STR_SUBTYPE_SLT[] = "\006""V1_6ch""V2_8ch""Q100\0 ""Q200\0 ""MR100\0";
const char STR_SUBTYPE_CX10[] = "\007""Green\0 ""Blue\0 ""DM007\0 ""-\0 ""JC3015a""JC3015b""MK33041";
const char STR_SUBTYPE_CG023[] = "\005""Std\0 ""YD829";
-const char STR_SUBTYPE_BAYANG[] = "\007""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4";
+const char STR_SUBTYPE_BAYANG[] = "\007""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4\0""QX100\0 ";
+const char STR_SUBTYPE_ESky[] = "\003""Std""ET4";
const char STR_SUBTYPE_MT99[] = "\006""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805";
const char STR_SUBTYPE_MJXQ[] = "\007""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
const char STR_SUBTYPE_FY326[] = "\005""Std\0 ""FY319";
@@ -845,19 +904,32 @@ const char STR_SUBTYPE_Q2X2[] = "\004""Q222""Q242""Q282";
const char STR_SUBTYPE_WK2x01[] = "\006""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
const char STR_SUBTYPE_Q303[] = "\006""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
const char STR_SUBTYPE_CABELL[] = "\007""V3\0 ""V3 Telm""-\0 ""-\0 ""-\0 ""-\0 ""F-Safe\0""Unbind\0";
+const char STR_SUBTYPE_ESKY150[] = "\003""4ch""7ch";
const char STR_SUBTYPE_H83D[] = "\007""Std\0 ""H20H\0 ""H20Mini""H30Mini";
const char STR_SUBTYPE_CORONA[] = "\005""V1\0 ""V2\0 ""FD V3";
const char STR_SUBTYPE_HITEC[] = "\007""Optima\0""Opt Hub""Minima\0";
+const char STR_SUBTYPE_WFLY[] = "\006""WFR0xS";
const char STR_SUBTYPE_BUGS_MINI[] = "\006""Std\0 ""Bugs3H";
const char STR_SUBTYPE_TRAXXAS[] = "\004""6519";
const char STR_SUBTYPE_E01X[] = "\005""E012\0""E015\0""E016H";
+const char STR_SUBTYPE_V911S[] = "\004""Std\0""E119";
const char STR_SUBTYPE_GD00X[] = "\005""GD_V1""GD_V2";
+const char STR_SUBTYPE_V761[] = "\003""3ch""4ch";
const char STR_SUBTYPE_REDPINE[] = "\004""Fast""Slow";
const char STR_SUBTYPE_POTENSIC[] = "\003""A20";
const char STR_SUBTYPE_ZSX[] = "\007""280JJRC";
const char STR_SUBTYPE_FLYZONE[] = "\005""FZ410";
+const char STR_SUBTYPE_FRSKYX_RX[] = "\007""RX\0 ""CloneTX";
+const char STR_SUBTYPE_HOTT[] = "\007""Sync\0 ""No_Sync";
const char STR_SUBTYPE_FX816[] = "\003""P38";
-const char STR_SUBTYPE_ESKY150[] = "\003""4CH""7CH";
+const char STR_SUBTYPE_PELIKAN[] = "\004""Pro\0""Lite";
+const char STR_SUBTYPE_XK[] = "\004""X450""X420";
+const char STR_SUBTYPE_XN297DUMP[] = "\004""250K""1M\0 ""2M\0 ""AUTO""NRF\0";
+const char STR_SUBTYPE_FRSKYX2[] = "\011""D16\0 ""D16 8ch\0 ""LBT(EU)\0 ""LBT 8ch\0 ""D16Cloned";
+const char STR_SUBTYPE_FRSKYR9[] = "\007""915MHz\0""868MHz\0""915 8ch""868 8ch";
+const char STR_SUBTYPE_PROPEL[] = "\004""74-Z";
+const char STR_SUBTYPE_FRSKYL[] = "\010""LR12\0 ""LR12 6ch";
+const char STR_SUBTYPE_ESKY150V2[] = "\006""150 V2";
const char* mm_options_strings::options[] = {
nullptr,
@@ -868,29 +940,32 @@ const char* mm_options_strings::options[] = {
STR_MULTI_TELEMETRY,
STR_MULTI_SERVOFREQ,
STR_MULTI_MAX_THROW,
- STR_MULTI_RFCHAN
+ STR_MULTI_RFCHAN,
+ STR_MULTI_RFPOWER
};
const mm_protocol_definition multi_protocols[] = {
// Protocol as defined in pulses\modules_constants.h, number of sub_protocols - 1, Failsafe supported, Disable channel mapping supported, Subtype string, Option type
{MODULE_SUBTYPE_MULTI_FLYSKY, 4, false, true, STR_SUBTYPE_FLYSKY, nullptr},
{MODULE_SUBTYPE_MULTI_HUBSAN, 2, false, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
- {MODULE_SUBTYPE_MULTI_FRSKY, 5, false, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_FRSKY, 7, false, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_HISKY, 1, false, true, STR_SUBTYPE_HISKY, nullptr},
- {MODULE_SUBTYPE_MULTI_V2X2, 1, false, false, STR_SUBTYPE_V2X2, nullptr},
+ {MODULE_SUBTYPE_MULTI_V2X2, 2, false, false, STR_SUBTYPE_V2X2, nullptr},
{MODULE_SUBTYPE_MULTI_DSM2, 3, false, true, STR_SUBTYPE_DSM, STR_MULTI_MAX_THROW},
{MODULE_SUBTYPE_MULTI_DEVO, 4, false, true, STR_SUBTYPE_DEVO, STR_MULTI_FIXEDID},
{MODULE_SUBTYPE_MULTI_YD717, 4, false, false, STR_SUBTYPE_YD717, nullptr},
{MODULE_SUBTYPE_MULTI_KN, 1, false, false, STR_SUBTYPE_KN, nullptr},
{MODULE_SUBTYPE_MULTI_SYMAX, 1, false, false, STR_SUBTYPE_SYMAX, nullptr},
- {MODULE_SUBTYPE_MULTI_SLT, 4, false, true, STR_SUBTYPE_SLT, nullptr},
+ {MODULE_SUBTYPE_MULTI_SLT, 4, false, true, STR_SUBTYPE_SLT, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_CX10, 6, false, false, STR_SUBTYPE_CX10, nullptr},
{MODULE_SUBTYPE_MULTI_CG023, 1, false, false, STR_SUBTYPE_CG023, nullptr},
- {MODULE_SUBTYPE_MULTI_BAYANG, 4, false, false, STR_SUBTYPE_BAYANG, STR_MULTI_TELEMETRY},
+ {MODULE_SUBTYPE_MULTI_BAYANG, 5, false, false, STR_SUBTYPE_BAYANG, STR_MULTI_TELEMETRY},
+ {MODULE_SUBTYPE_MULTI_ESky, 1, false, true, STR_SUBTYPE_ESky, nullptr},
{MODULE_SUBTYPE_MULTI_MT99XX, 4, false, false, STR_SUBTYPE_MT99, nullptr},
{MODULE_SUBTYPE_MULTI_MJXQ, 6, false, false, STR_SUBTYPE_MJXQ, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FY326, 1, false, false, STR_SUBTYPE_FY326, nullptr},
{MODULE_SUBTYPE_MULTI_SFHSS, 0, true, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_J6PRO, 0, false, true, NO_SUBTYPE, nullptr},
{MODULE_SUBTYPE_MULTI_HONTAI, 3, false, false, STR_SUBTYPE_HONTAI, nullptr},
{MODULE_SUBTYPE_MULTI_OLRS, 0, false, false, NO_SUBTYPE, STR_RFPOWER},
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 3, true, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
@@ -898,28 +973,39 @@ const mm_protocol_definition multi_protocols[] = {
{MODULE_SUBTYPE_MULTI_WK_2X01, 5, false, true, STR_SUBTYPE_WK2x01, nullptr},
{MODULE_SUBTYPE_MULTI_Q303, 3, false, false, STR_SUBTYPE_Q303, nullptr},
{MODULE_SUBTYPE_MULTI_CABELL, 7, false, false, STR_SUBTYPE_CABELL, STR_MULTI_OPTION},
+ {MODULE_SUBTYPE_MULTI_ESKY150, 1, false, false, STR_SUBTYPE_ESKY150, nullptr},
{MODULE_SUBTYPE_MULTI_H83D, 3, false, false, STR_SUBTYPE_H83D, nullptr},
{MODULE_SUBTYPE_MULTI_CORONA, 2, false, false, STR_SUBTYPE_CORONA, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_HITEC, 2, false, false, STR_SUBTYPE_HITEC, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_WFLY, 0, false, false, STR_SUBTYPE_WFLY, nullptr},
{MODULE_SUBTYPE_MULTI_BUGS_MINI, 1, false, false, STR_SUBTYPE_BUGS_MINI, nullptr},
{MODULE_SUBTYPE_MULTI_TRAXXAS, 0, false, false, STR_SUBTYPE_TRAXXAS, nullptr},
{MODULE_SUBTYPE_MULTI_E01X, 2, false, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION},
+ {MODULE_SUBTYPE_MULTI_V911S, 1, false, false, STR_SUBTYPE_V911S, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_GD00X, 1, false, false, STR_SUBTYPE_GD00X, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_V761, 1, false, false, STR_SUBTYPE_V761, nullptr},
{MODULE_SUBTYPE_MULTI_KF606, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_REDPINE, 1, false, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, false, STR_SUBTYPE_POTENSIC, nullptr},
{MODULE_SUBTYPE_MULTI_ZSX, 0, false, false, STR_SUBTYPE_ZSX, nullptr},
{MODULE_SUBTYPE_MULTI_FLYZONE, 0, false, false, STR_SUBTYPE_FLYZONE, nullptr},
- {MODULE_SUBTYPE_MULTI_FRSKYX_RX, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
- {MODULE_SUBTYPE_MULTI_ESky, 0, false, true, NO_SUBTYPE, nullptr},
- {MODULE_SUBTYPE_MULTI_J6PRO, 0, false, true, NO_SUBTYPE, nullptr},
- {MODULE_SUBTYPE_MULTI_ESKY150, 1, false, false, STR_SUBTYPE_ESKY150, nullptr},
+ {MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_HOTT, 1, true, false, STR_SUBTYPE_HOTT, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FX816, 0, false, false, STR_SUBTYPE_FX816, nullptr},
- {MODULE_SUBTYPE_MULTI_HOTT, 0, true, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, false, STR_SUBTYPE_PELIKAN, nullptr},
+ {MODULE_SUBTYPE_MULTI_XK, 1, false, false, STR_SUBTYPE_XK, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_XN297DUMP, 4, false, false, STR_SUBTYPE_XN297DUMP, STR_MULTI_RFCHAN},
+ {MODULE_SUBTYPE_MULTI_FRSKYX2, 4, true, false, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, false, STR_SUBTYPE_FRSKYR9, nullptr},
+ {MODULE_SUBTYPE_MULTI_PROPEL, 0, false, false, STR_SUBTYPE_PROPEL, nullptr},
+ {MODULE_SUBTYPE_MULTI_FRSKYL, 1, false, false, STR_SUBTYPE_FRSKYL, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_SKYARTEC, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_ESKY150V2, 0, false, true, STR_SUBTYPE_ESKY150V2, STR_MULTI_RFTUNE},
+ {MODULE_SUBTYPE_MULTI_Q90C, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MM_RF_CUSTOM_SELECTED, 7, true, true, NO_SUBTYPE, STR_MULTI_OPTION},
// Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff)
- {0xfe, 0, false, true, NO_SUBTYPE, nullptr}
+ {0xfe, 0, false, false, NO_SUBTYPE, nullptr}
};
#undef NO_SUBTYPE
diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h
index 806ceb751..d1fdb8fa1 100644
--- a/radio/src/gui/gui_common.h
+++ b/radio/src/gui/gui_common.h
@@ -70,6 +70,8 @@ bool isSourceAvailableInGlobalFunctions(int source);
bool isSourceAvailableInCustomSwitches(int source);
bool isSourceAvailableInResetSpecialFunction(int index);
bool isSourceAvailableInGlobalResetSpecialFunction(int index);
+bool isAux1ModeAvailable(int mode);
+bool isAux2ModeAvailable(int mode);
bool isSwitchAvailableInLogicalSwitches(int swtch);
bool isSwitchAvailableInCustomFunctions(int swtch);
bool isSwitchAvailableInMixes(int swtch);
@@ -122,6 +124,8 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value,
void drawSourceCustomValue(coord_t x, coord_t y, source_t channel, int32_t val, LcdFlags flags=0);
void drawSourceValue(coord_t x, coord_t y, source_t channel, LcdFlags flags=0);
+int convertMultiToOtx(int type);
+
void drawCurve(coord_t offset=0);
#if defined(COLORLCD)
@@ -139,33 +143,55 @@ void runFatalErrorScreen(const char * message);
inline uint8_t MODULE_BIND_ROWS(int moduleIdx)
{
- if (isModuleXJTD8(moduleIdx) || isModuleSBUS(moduleIdx))
+ if (isModuleMultimodule(moduleIdx)) {
+ if (IS_RX_MULTI(moduleIdx))
+ return 1;
+ else
+ return 2;
+ }
+ else if (isModuleXJTD8(moduleIdx) || isModuleSBUS(moduleIdx) || isModuleAFHDS3(moduleIdx)) {
return 1;
-
- if (isModulePPM(moduleIdx) || isModulePXX1(moduleIdx) || isModulePXX2(moduleIdx) || isModuleDSM2(moduleIdx) || isModuleMultimodule(moduleIdx))
+ }
+ else if (isModulePPM(moduleIdx) || isModulePXX1(moduleIdx) || isModulePXX2(moduleIdx) || isModuleDSM2(moduleIdx)) {
return 2;
- else
+ }
+ else {
return HIDDEN_ROW;
+ }
}
inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx)
{
- if (!IS_MODULE_ENABLED(moduleIdx))
+ if (!IS_MODULE_ENABLED(moduleIdx)) {
return HIDDEN_ROW;
-
- if (isModuleDSM2(moduleIdx) || isModuleCrossfire(moduleIdx) || isModuleSBUS(moduleIdx) || (isModuleMultimodule(moduleIdx) && g_model.moduleData[moduleIdx].getMultiProtocol() != MODULE_SUBTYPE_MULTI_DSM2))
+ }
+ else if (isModuleMultimodule(moduleIdx)) {
+ if (IS_RX_MULTI(moduleIdx))
+ return HIDDEN_ROW;
+ else if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2)
+ return 1;
+ else
+ return 0;
+ }
+ else if (isModuleDSM2(moduleIdx) || isModuleCrossfire(moduleIdx) || isModuleSBUS(moduleIdx)) {
return 0;
- else
+ }
+ else {
return 1;
+ }
}
-
#if defined(MULTIMODULE)
inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW(uint8_t moduleIdx)
{
if (!isModuleMultimodule(moduleIdx))
return HIDDEN_ROW;
+ MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
+ if (status.isValid()) {
+ return status.supportsDisableMapping() == true ? 0 : HIDDEN_ROW;
+ }
+
uint8_t protocol = g_model.moduleData[moduleIdx].getMultiProtocol();
if (protocol < MODULE_SUBTYPE_MULTI_LAST) {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(protocol);
@@ -173,11 +199,6 @@ inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW(uint8_t moduleIdx)
return 0;
}
- MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
- if (status.supportsDisableMapping() && status.isValid()) {
- return 0;
- }
-
return HIDDEN_ROW;
}
@@ -239,31 +260,57 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx)
return false;
uint8_t protocol = g_model.moduleData[moduleIdx].getMultiProtocol();
- if (protocol < MODULE_SUBTYPE_MULTI_LAST) {
- return getMultiProtocolDefinition(protocol)->optionsstr != nullptr;
- }
-
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
- return status.optionDisp;
+
+ if (status.isValid())
+ return status.optionDisp;
+
+ if (protocol < MODULE_SUBTYPE_MULTI_LAST)
+ return getMultiProtocolDefinition(protocol)->optionsstr != nullptr;
+
+ return false;
}
-#define MULTIMODULE_MODULE_ROWS(moduleIdx) MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, MULTI_DISABLE_CHAN_MAP_ROW(moduleIdx), // AUTOBIND, DISABLE TELEM, DISABLE CN.MAP
+#define MULTIMODULE_MODULE_ROWS(moduleIdx) (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) && !IS_RX_MULTI(moduleIdx)) ? (uint8_t) 0 : HIDDEN_ROW, (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) && !IS_RX_MULTI(moduleIdx)) ? (uint8_t) 0 : HIDDEN_ROW, MULTI_DISABLE_CHAN_MAP_ROW(moduleIdx), // AUTOBIND, DISABLE TELEM, DISABLE CN.MAP
+#define MULTIMODULE_TYPE_ROW(moduleIdx) isModuleMultimodule(moduleIdx) ? MULTIMODULE_RFPROTO_COLUMNS(moduleIdx) : HIDDEN_ROW,
#define MULTIMODULE_STATUS_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, (isModuleMultimodule(moduleIdx) && getMultiSyncStatus(moduleIdx).isValid()) ? TITLE_ROW : HIDDEN_ROW,
#define MULTIMODULE_MODE_ROWS(moduleIdx) (g_model.moduleData[moduleIdx].multi.customProto) ? (uint8_t) 3 : MULTIMODULE_HAS_SUBTYPE(moduleIdx) ? (uint8_t)2 : (uint8_t)1
+#define MULTIMODULE_TYPE_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW,
#define MULTIMODULE_SUBTYPE_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? MULTIMODULE_RFPROTO_COLUMNS(moduleIdx) : HIDDEN_ROW,
#define MULTIMODULE_OPTIONS_ROW(moduleIdx) (isModuleMultimodule(moduleIdx) && MULTIMODULE_HASOPTIONS(moduleIdx)) ? (uint8_t) 0: HIDDEN_ROW
+#define MODULE_POWER_ROW(moduleIdx) (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) || isModuleR9MNonAccess(moduleIdx) || isModuleAFHDS3(moduleIdx)) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW
#else
+#define MULTIMODULE_TYPE_ROWS(moduleIdx)
#define MULTIMODULE_STATUS_ROWS(moduleIdx)
#define MULTIMODULE_MODULE_ROWS(moduleIdx)
+#define MULTIMODULE_TYPE_ROW(moduleIdx)
#define MULTIMODULE_SUBTYPE_ROWS(moduleIdx)
+#define MULTIMODULE_TYPE_ROWS(moduleIdx)
#define MULTIMODULE_MODE_ROWS(moduleIdx) (uint8_t)0
#define MULTIMODULE_OPTIONS_ROW(moduleIdx) HIDDEN_ROW
+#define MODULE_POWER_ROW(moduleIdx) isModuleR9MNonAccess(moduleIdx) || isModuleAFHDS3(moduleIdx) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW
+#endif
+
+#if defined(AFHDS3)
+#define AFHDS3_PROTOCOL_ROW(moduleIdx) isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW,
+#define AFHDS3_MODE_ROWS(moduleIdx) isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW,
+#define AFHDS3_MODULE_ROWS(moduleIdx) isModuleAFHDS3(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? (uint8_t) TITLE_ROW : HIDDEN_ROW,
+#else
+#define AFHDS3_PROTOCOL_ROW(moduleIdx)
+#define AFHDS3_MODE_ROWS(moduleIdx)
+#define AFHDS3_MODULE_ROWS(moduleIdx)
#endif
#define FAILSAFE_ROWS(moduleIdx) isModuleFailsafeAvailable(moduleIdx) ? (g_model.moduleData[moduleIdx].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW
-#define MODULE_OPTION_ROW(moduleIdx) (isModuleR9MNonAccess(moduleIdx) || isModuleSBUS(moduleIdx) ? TITLE_ROW : MULTIMODULE_OPTIONS_ROW(moduleIdx))
-#define MODULE_POWER_ROW(moduleIdx) (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) || isModuleR9MNonAccess(moduleIdx)) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW
+
+inline uint8_t MODULE_OPTION_ROW(uint8_t moduleIdx) {
+ if(isModuleR9MNonAccess(moduleIdx) || isModuleSBUS(moduleIdx))
+ return TITLE_ROW;
+ if(isModuleAFHDS3(moduleIdx))
+ return HIDDEN_ROW;
+ return MULTIMODULE_OPTIONS_ROW(moduleIdx);
+}
void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event, LcdFlags flags);
diff --git a/radio/src/gui/navigation/navigation_horus.cpp b/radio/src/gui/navigation/navigation_horus.cpp
index b8729c8a3..d62d07810 100644
--- a/radio/src/gui/navigation/navigation_horus.cpp
+++ b/radio/src/gui/navigation/navigation_horus.cpp
@@ -316,9 +316,9 @@ bool check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t
if (menuTab && !menuCalibrationState) {
int cc = curr;
switch (event) {
-#if defined(PCBX12S)
+#if defined(KEYS_GPIO_REG_PGUP)
case EVT_KEY_FIRST(KEY_PGDN):
-#elif defined(PCBX10)
+#else
case EVT_KEY_BREAK(KEY_PGDN):
#endif
if (s_editMode>0)
@@ -328,8 +328,9 @@ bool check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t
cc = 0;
break;
+#if defined(KEYS_GPIO_REG_PGUP)
case EVT_KEY_FIRST(KEY_PGUP):
-#if defined(PCBX10)
+#else
case EVT_KEY_LONG(KEY_PGDN):
#endif
if (s_editMode>0)
diff --git a/radio/src/io/bootloader_flash.cpp b/radio/src/io/bootloader_flash.cpp
index 0df79800f..1dd5188b6 100644
--- a/radio/src/io/bootloader_flash.cpp
+++ b/radio/src/io/bootloader_flash.cpp
@@ -37,10 +37,13 @@ bool isBootloader(const char * filename)
void bootloaderFlash(const char * filename)
{
FIL file;
- f_open(&file, filename, FA_READ);
uint8_t buffer[1024];
UINT count;
+ pausePulses();
+
+ f_open(&file, filename, FA_READ);
+
static uint8_t unlocked = 0;
if (!unlocked) {
unlocked = 1;
@@ -69,6 +72,7 @@ void bootloaderFlash(const char * filename)
}
watchdogSuspend(0);
+ WDG_RESET();
if (unlocked) {
lockFlash();
@@ -76,4 +80,6 @@ void bootloaderFlash(const char * filename)
}
f_close(&file);
+
+ resumePulses();
}
diff --git a/radio/src/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp
index 1dca3b5a2..eb1ab0df4 100644
--- a/radio/src/io/frsky_firmware_update.cpp
+++ b/radio/src/io/frsky_firmware_update.cpp
@@ -160,7 +160,7 @@ const uint8_t * FrskyDeviceFirmwareUpdate::readFullDuplexFrame(ModuleFifo & fifo
const uint8_t * FrskyDeviceFirmwareUpdate::readHalfDuplexFrame(uint32_t timeout)
{
- for (int i=timeout; i>=0; i--) {
+ for (int i = timeout; i >= 0; i--) {
uint8_t byte ;
while (telemetryGetByte(&byte)) {
if (pushFrskyTelemetryData(byte)) {
@@ -313,12 +313,12 @@ const char * FrskyDeviceFirmwareUpdate::doFlashFirmware(const char * filename)
}
else {
#if defined(PCBHORUS)
- information.productId = FIRMWARE_ID_XJT;
+ information.productId = FIRMWARE_ID_MODULE_XJT;
#endif
}
#if defined(PCBHORUS)
- if (module == INTERNAL_MODULE && information.productId == FIRMWARE_ID_XJT) {
+ if (module == INTERNAL_MODULE && information.productId == FIRMWARE_ID_MODULE_XJT) {
INTERNAL_MODULE_ON();
RTOS_WAIT_MS(1);
intmoduleSerialStart(38400, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b);
@@ -487,6 +487,7 @@ const char * FrskyDeviceFirmwareUpdate::flashFirmware(const char * filename)
uint8_t extPwr = IS_EXTERNAL_MODULE_ON();
EXTERNAL_MODULE_OFF();
+ uint8_t spuPwr = IS_SPORT_UPDATE_POWER_ON();
SPORT_UPDATE_POWER_OFF();
drawProgressScreen(getBasename(filename), STR_DEVICE_RESET, 0, 0);
@@ -531,6 +532,10 @@ const char * FrskyDeviceFirmwareUpdate::flashFirmware(const char * filename)
setupPulsesExternalModule();
}
+ if (spuPwr) {
+ SPORT_UPDATE_POWER_ON();
+ }
+
state = SPORT_IDLE;
resumePulses();
@@ -752,6 +757,7 @@ const char * FrskyChipFirmwareUpdate::flashFirmware(const char * filename, bool
uint8_t extPwr = IS_EXTERNAL_MODULE_ON();
EXTERNAL_MODULE_OFF();
+ uint8_t spuPwr = IS_SPORT_UPDATE_POWER_ON();
SPORT_UPDATE_POWER_OFF();
if (wait) {
@@ -791,6 +797,10 @@ const char * FrskyChipFirmwareUpdate::flashFirmware(const char * filename, bool
setupPulsesExternalModule();
}
+ if (spuPwr) {
+ SPORT_UPDATE_POWER_ON();
+ }
+
resumePulses();
return result;
diff --git a/radio/src/io/frsky_firmware_update.h b/radio/src/io/frsky_firmware_update.h
index a229edb27..4690e0215 100644
--- a/radio/src/io/frsky_firmware_update.h
+++ b/radio/src/io/frsky_firmware_update.h
@@ -24,6 +24,7 @@
#include "dataconstants.h"
#include "definitions.h"
#include "frsky_pxx2.h"
+#include "pulses/modules_helpers.h"
#include "ff.h"
enum FrskyFirmwareProductFamily {
@@ -35,12 +36,65 @@ enum FrskyFirmwareProductFamily {
FIRMWARE_FAMILY_POWER_MANAGEMENT_UNIT,
};
-enum FrskyFirmwareProductId {
- FIRMWARE_ID_NONE,
- FIRMWARE_ID_XJT = 0x01,
- FIRMWARE_ID_ISRM = 0x02,
+enum FrskyFirmwareModuleProductId {
+ FIRMWARE_ID_MODULE_NONE,
+ FIRMWARE_ID_MODULE_XJT = 0x01,
+ FIRMWARE_ID_MODULE_ISRM = 0x02,
};
+enum FrskyFirmwareReceiverProductId {
+ FIRMWARE_ID_RECEIVER_NONE,
+ FIRMWARE_ID_RECEIVER_X8R = 0x01,
+ FIRMWARE_ID_RECEIVER_RX8R = 0x02,
+ FIRMWARE_ID_RECEIVER_RX8R_PRO = 0x03,
+ FIRMWARE_ID_RECEIVER_RX6R = 0x04,
+ FIRMWARE_ID_RECEIVER_RX4R = 0x05,
+ FIRMWARE_ID_RECEIVER_G_RX8 = 0x06,
+ FIRMWARE_ID_RECEIVER_G_RX6 = 0x07,
+ FIRMWARE_ID_RECEIVER_X6R = 0x08,
+ FIRMWARE_ID_RECEIVER_X4R = 0x09,
+ FIRMWARE_ID_RECEIVER_X4R_SB = 0x0A,
+ FIRMWARE_ID_RECEIVER_XSR = 0x0B,
+ FIRMWARE_ID_RECEIVER_XSR_M = 0x0C,
+ FIRMWARE_ID_RECEIVER_RXSR = 0x0D,
+ FIRMWARE_ID_RECEIVER_S6R = 0x0E,
+ FIRMWARE_ID_RECEIVER_S8R = 0x0F,
+ FIRMWARE_ID_RECEIVER_XM = 0x10,
+ FIRMWARE_ID_RECEIVER_XMP = 0x11,
+ FIRMWARE_ID_RECEIVER_XMR = 0x12,
+ FIRMWARE_ID_RECEIVER_R9 = 0x13,
+ FIRMWARE_ID_RECEIVER_R9_SLIM = 0x14,
+ FIRMWARE_ID_RECEIVER_R9_SLIMP = 0x15,
+ FIRMWARE_ID_RECEIVER_R9_MINI = 0x16,
+ FIRMWARE_ID_RECEIVER_R9_MM = 0x17,
+ FIRMWARE_ID_RECEIVER_R9_STAB = 0x18, // R9_STAB has OTA
+ FIRMWARE_ID_RECEIVER_R9_MINI_OTA = 0x19, // this one has OTA (different bootloader)
+ FIRMWARE_ID_RECEIVER_R9_MM_OTA = 0x1A, // this one has OTA (different bootloader)
+ FIRMWARE_ID_RECEIVER_R9_SLIMP_OTA = 0x1B, // this one has OTA (different bootloader)
+ FIRMWARE_ID_RECEIVER_ARCHER_X = 0x1C, // this one has OTA (internal module)
+ FIRMWARE_ID_RECEIVER_R9MX = 0x1D, // this one has OTA
+ FIRMWARE_ID_RECEIVER_R9SX = 0x1E, // this one has OTA
+};
+
+inline bool isReceiverOTAEnabledFromModule(uint8_t moduleIdx, uint8_t productId)
+{
+ switch (productId) {
+ case FIRMWARE_ID_RECEIVER_ARCHER_X:
+ return isModuleISRM(moduleIdx);
+
+ case FIRMWARE_ID_RECEIVER_R9_STAB:
+ case FIRMWARE_ID_RECEIVER_R9_MINI_OTA:
+ case FIRMWARE_ID_RECEIVER_R9_MM_OTA:
+ case FIRMWARE_ID_RECEIVER_R9_SLIMP_OTA:
+ case FIRMWARE_ID_RECEIVER_R9MX:
+ case FIRMWARE_ID_RECEIVER_R9SX:
+ return isModuleR9M(moduleIdx);
+
+ default:
+ return false;
+ }
+}
+
PACK(struct FrSkyFirmwareInformation {
uint32_t fourcc;
uint8_t headerVersion;
@@ -69,7 +123,7 @@ class FrskyDeviceFirmwareUpdate {
};
public:
- FrskyDeviceFirmwareUpdate(ModuleIndex module):
+ explicit FrskyDeviceFirmwareUpdate(ModuleIndex module):
module(module) {
}
diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp
index 6b9cc1651..82ad5d81c 100644
--- a/radio/src/io/multi_firmware_update.cpp
+++ b/radio/src/io/multi_firmware_update.cpp
@@ -520,7 +520,7 @@ bool multiFlashFirmware(uint8_t moduleIdx, const char * filename)
pausePulses();
-#if defined(INTERNAL_MODULE_MULTI)
+#if defined(HARDWARE_INTERNAL_MODULE)
uint8_t intPwr = IS_INTERNAL_MODULE_ON();
INTERNAL_MODULE_OFF();
#endif
@@ -528,13 +528,14 @@ bool multiFlashFirmware(uint8_t moduleIdx, const char * filename)
uint8_t extPwr = IS_EXTERNAL_MODULE_ON();
EXTERNAL_MODULE_OFF();
+ uint8_t spuPwr = IS_SPORT_UPDATE_POWER_ON();
SPORT_UPDATE_POWER_OFF();
drawProgressScreen(getBasename(filename), STR_DEVICE_RESET, 0, 0);
/* wait 2s off */
watchdogSuspend(500 /*5s*/);
- RTOS_WAIT_MS(2000);
+ RTOS_WAIT_MS(3000);
const char * result = driver->flashFirmware(&file, getBasename(filename));
f_close(&file);
@@ -563,7 +564,7 @@ bool multiFlashFirmware(uint8_t moduleIdx, const char * filename)
// reset telemetry protocol
telemetryInit(255);
-#if defined(INTERNAL_MODULE_MULTI)
+#if defined(HARDWARE_INTERNAL_MODULE)
if (intPwr) {
INTERNAL_MODULE_ON();
setupPulsesInternalModule();
@@ -575,6 +576,10 @@ bool multiFlashFirmware(uint8_t moduleIdx, const char * filename)
setupPulsesExternalModule();
}
+ if (spuPwr) {
+ SPORT_UPDATE_POWER_ON();
+ }
+
resumePulses();
return result == nullptr;
diff --git a/radio/src/io/multi_firmware_update.h b/radio/src/io/multi_firmware_update.h
index a4ad7156f..a4cb255fb 100644
--- a/radio/src/io/multi_firmware_update.h
+++ b/radio/src/io/multi_firmware_update.h
@@ -71,7 +71,7 @@ class MultiFirmwareInformation {
bool isMultiInternalFirmware() const
{
- return (boardType == FIRMWARE_MULTI_STM && telemetryInversion == false && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY);
+ return (boardType == FIRMWARE_MULTI_STM && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY);
}
bool isMultiExternalFirmware() const
diff --git a/radio/src/lua/CMakeLists.txt b/radio/src/lua/CMakeLists.txt
index f0ed96e94..9c5a952bb 100644
--- a/radio/src/lua/CMakeLists.txt
+++ b/radio/src/lua/CMakeLists.txt
@@ -10,21 +10,23 @@ endmacro(add_lua_export_target)
set(LUA_INCLUDES
-DCPUARM -DLUA -DLUA_INPUTS -DLUA_EXPORT_GENERATION -DSIMU
+ -I${RADIO_SRC_DIRECTORY}
-I${RADIO_SRC_DIRECTORY}/targets/${TARGET_DIR}
-I${RADIO_SRC_DIRECTORY}/thirdparty
-I${RADIO_SRC_DIRECTORY}/targets/common/arm/stm32
)
if(PYTHONINTERP_FOUND)
- add_lua_export_target(x9lite ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9LITE -DPCBX9)
- add_lua_export_target(x9lites ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9LITES -DPCBX9LITE -DPCBX9)
- add_lua_export_target(x7 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_X7)
- add_lua_export_target(xlite ${LUA_INCLUDES} -DPCBTARANIS -DPCBXLITE)
- add_lua_export_target(xlites ${LUA_INCLUDES} -DPCBTARANIS -DPCBXLITES -DPCBXLITE -DGYRO)
- add_lua_export_target(x9d ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9D -DPCBX9)
- add_lua_export_target(x9e ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9E -DPCBX9)
- add_lua_export_target(x10 ${LUA_INCLUDES} -DPCBHORUS -DPCBX10)
- add_lua_export_target(x12s ${LUA_INCLUDES} -DPCBHORUS -DPCBX12S)
- add_lua_export_target(t12 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_T12)
- add_lua_export_target(t16 ${LUA_INCLUDES} -DPCBHORUS -DPCBX10 -DRADIO_T16)
+ add_lua_export_target(x9lite ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9LITE -DPCBX9)
+ add_lua_export_target(x9lites ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9LITES -DPCBX9LITE -DPCBX9)
+ add_lua_export_target(x7 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_X7)
+ add_lua_export_target(x7access ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7ACCESS -DPCBX7 -DRADIO_X7ACCESS)
+ add_lua_export_target(xlite ${LUA_INCLUDES} -DPCBTARANIS -DPCBXLITE)
+ add_lua_export_target(xlites ${LUA_INCLUDES} -DPCBTARANIS -DPCBXLITES -DPCBXLITE -DGYRO)
+ add_lua_export_target(x9d ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9D -DPCBX9)
+ add_lua_export_target(x9e ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9E -DPCBX9)
+ add_lua_export_target(x10 ${LUA_INCLUDES} -DPCBHORUS -DPCBX10)
+ add_lua_export_target(x12s ${LUA_INCLUDES} -DPCBHORUS -DPCBX12S)
+ add_lua_export_target(t12 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_T12)
+ add_lua_export_target(t16 ${LUA_INCLUDES} -DPCBHORUS -DPCBX10 -DRADIO_T16)
endif()
diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp
index ea2ce80a4..3ee1bf1ae 100644
--- a/radio/src/lua/api_general.cpp
+++ b/radio/src/lua/api_general.cpp
@@ -28,12 +28,14 @@
#if defined(PCBX12S)
#include "lua/lua_exports_x12s.inc" // this line must be after lua headers
-#elif defined(RADIO_T16)
+#elif defined(RADIO_FAMILY_T16)
#include "lua/lua_exports_t16.inc"
#elif defined(PCBX10)
#include "lua/lua_exports_x10.inc"
#elif defined(PCBX9E)
#include "lua/lua_exports_x9e.inc"
+#elif defined(RADIO_X7ACCESS)
+ #include "lua/lua_exports_x7access.inc"
#elif defined(RADIO_X7)
#include "lua/lua_exports_x7.inc"
#elif defined(RADIO_T12)
@@ -64,6 +66,10 @@
{ "EVT_"#xxx"_LONG", EVT_KEY_LONG(yyy) }, \
{ "EVT_"#xxx"_REPT", EVT_KEY_REPT(yyy) }
+#if defined(LUA) && !defined(CLI)
+Fifo * luaRxFifo = nullptr;
+#endif
+
/*luadoc
@function getVersion()
@@ -438,13 +444,15 @@ When called without parameters, it will only return the status of the output buf
@retval boolean data queued in output buffer or not.
-@status current Introduced in 2.2.0
+@retval nil incorrect telemetry protocol.
+
+@status current Introduced in 2.2.0, retval nil added in 2.3.4
*/
static int luaSportTelemetryPush(lua_State * L)
{
if (!IS_FRSKY_SPORT_PROTOCOL()) {
- lua_pushboolean(L, false);
+ lua_pushnil(L);
return 1;
}
@@ -452,6 +460,10 @@ static int luaSportTelemetryPush(lua_State * L)
lua_pushboolean(L, outputTelemetryBuffer.isAvailable());
return 1;
}
+ else if (lua_gettop(L) > int(sizeof(SportTelemetryPacket))) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
uint16_t dataId = luaL_checkunsigned(L, 3);
@@ -635,18 +647,24 @@ When called without parameters, it will only return the status of the output buf
@retval boolean data queued in output buffer or not.
-@status current Introduced in 2.2.0
+@retval nil incorrect telemetry protocol.
+
+@status current Introduced in 2.2.0, retval nil added in 2.3.4
*/
static int luaCrossfireTelemetryPush(lua_State * L)
{
if (telemetryProtocol != PROTOCOL_TELEMETRY_CROSSFIRE) {
- lua_pushboolean(L, false);
+ lua_pushnil(L);
return 1;
}
if (lua_gettop(L) == 0) {
lua_pushboolean(L, outputTelemetryBuffer.isAvailable());
}
+ else if (lua_gettop(L) > TELEMETRY_OUTPUT_BUFFER_SIZE ) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
else if (outputTelemetryBuffer.isAvailable()) {
uint8_t command = luaL_checkunsigned(L, 1);
luaL_checktype(L, 2, LUA_TTABLE);
@@ -680,7 +698,8 @@ The list of valid sources is available:
|----------------|-------|
| 2.0 | [all](http://downloads-20.open-tx.org/firmware/lua_fields.txt) |
| 2.1 | [X9D and X9D+](http://downloads-21.open-tx.org/firmware/lua_fields_taranis.txt), [X9E](http://downloads-21.open-tx.org/firmware/lua_fields_taranis_x9e.txt) |
-| 2.2 | [X9D and X9D+](http://downloads.open-tx.org/2.2/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.2/firmware/lua_fields_x9e.txt), [Horus](http://downloads.open-tx.org/2.2/firmware/lua_fields_x12s.txt) |
+| 2.2 | [X9D and X9D+](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9e.txt), [Horus](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x12s.txt) |
+| 2.3 | [X9D and X9D+](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x9e.txt), [X7](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x7.txt), [Horus](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x12s.txt) |
@param name (string) name of the field
@@ -727,8 +746,8 @@ The list of fixed sources:
|----------------|-------|
| 2.0 | [all](http://downloads-20.open-tx.org/firmware/lua_fields.txt) |
| 2.1 | [X9D and X9D+](http://downloads-21.open-tx.org/firmware/lua_fields_taranis.txt), [X9E](http://downloads-21.open-tx.org/firmware/lua_fields_taranis_x9e.txt) |
-| 2.2 | [X9D and X9D+](http://downloads.open-tx.org/2.2/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.2/firmware/lua_fields_x9e.txt), [Horus](http://downloads.open-tx.org/2.2/firmware/lua_fields_x12s.txt) |
-
+| 2.2 | [X9D and X9D+](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9e.txt), [Horus](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x12s.txt) |
+| 2.3 | [X9D and X9D+](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x9e.txt), [X7](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x7.txt), [Horus](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x12s.txt) |
In OpenTX 2.1.x the telemetry sources no longer have a predefined name.
To get a telemetry value simply use it's sensor name. For example:
@@ -1192,11 +1211,14 @@ static int luaPopupWarning(lua_State * L)
}
/*luadoc
-@function popupConfirmation(title, event)
+@function popupConfirmation(title, event) deprecated, please replace by
+@function popupConfirmation(title, message, event)
Raises a pop-up on screen that asks for confirmation
-@param title (string) text to display
+@param title (string) title to display
+
+@param message (string) text to display
@param event (number) the event variable that is passed in from the
Run function (key pressed)
@@ -1205,13 +1227,24 @@ Run function (key pressed)
@notice Use only from stand-alone and telemetry scripts.
-@status current Introduced in 2.2.0
+@status current Introduced in 2.2.0, changed to (title, message, event) in 2.3.8
*/
static int luaPopupConfirmation(lua_State * L)
{
- event_t event = luaL_checkinteger(L, 2);
- warningText = luaL_checkstring(L, 1);
warningType = WARNING_TYPE_CONFIRM;
+ event_t event;
+
+ if (lua_isnone(L, 3)) {
+ // only two args: deprecated mode
+ warningText = luaL_checkstring(L, 1);
+ event = luaL_checkinteger(L, 2);
+ }
+ else {
+ warningText = luaL_checkstring(L, 1);
+ warningInfoText = luaL_checkstring(L, 2);
+ event = luaL_optinteger(L, 3, 0);
+ }
+
runPopupWarning(event);
if (!warningText) {
lua_pushstring(L, warningResult ? "OK" : "CANCEL");
@@ -1572,6 +1605,13 @@ static int luaSerialWrite(lua_State * L)
while(wr_len--) auxSerialPutc(*p++);
}
#endif
+#if defined(AUX2_SERIAL)
+ if (aux2SerialMode == UART_MODE_LUA) {
+ size_t wr_len = len;
+ const char* p = str;
+ while(wr_len--) aux2SerialPutc(*p++);
+ }
+#endif
#else
debugPrintf("luaSerialWrite: %.*s",len,str);
#endif
@@ -1579,6 +1619,58 @@ static int luaSerialWrite(lua_State * L)
return 0;
}
+/*luadoc
+@function serialRead([num])
+@param num (optional): maximum number of bytes to read.
+ If non-zero, serialRead will read up to num characters from the buffer.
+ If 0 or left out, serialRead will read up to and including the first newline character or the end of the buffer.
+ Note that the returned string may not end in a newline if this character is not present in the buffer.
+
+@retval str string. Empty if no new characters were available.
+
+Reads characters from the serial port. The string is allowed to contain any character, including 0.
+
+@status current Introduced in 2.3.8
+*/
+static int luaSerialRead(lua_State * L)
+{
+#if defined(LUA) && !defined(CLI)
+ int num = luaL_optunsigned(L, 1, 0);
+
+ if (!luaRxFifo) {
+ luaRxFifo = new Fifo();
+ if (!luaRxFifo) {
+ lua_pushlstring(L, "", 0);
+ return 1;
+ }
+ }
+ uint8_t str[LUA_FIFO_SIZE];
+ uint8_t *p = str;
+ while (luaRxFifo->pop(*p)) {
+ p++; // increment only when pop was successful
+ if (p - str >= LUA_FIFO_SIZE) {
+ // buffer full
+ break;
+ }
+ if (num == 0) {
+ if (*(p - 1) == '\n' || *(p - 1) == '\r') {
+ // found newline
+ break;
+ }
+ }
+ else if (p - str >= num) {
+ // requested number of characters reached
+ break;
+ }
+ }
+ lua_pushlstring(L, (const char*)str, p - str);
+#else
+ lua_pushlstring(L, "", 0);
+#endif
+
+ return 1;
+}
+
const luaL_Reg opentxLib[] = {
{ "getTime", luaGetTime },
{ "getDateTime", luaGetDateTime },
@@ -1626,6 +1718,7 @@ const luaL_Reg opentxLib[] = {
{ "multiBuffer", luaMultiBuffer },
#endif
{ "serialWrite", luaSerialWrite },
+ { "serialRead", luaSerialRead },
{ nullptr, nullptr } /* sentinel */
};
@@ -1635,6 +1728,9 @@ const luaR_value_entry opentxConstants[] = {
{ "DBLSIZE", DBLSIZE },
{ "MIDSIZE", MIDSIZE },
{ "SMLSIZE", SMLSIZE },
+#if defined(COLORLCD)
+ { "TINSIZE", TINSIZE },
+#endif
{ "INVERS", INVERS },
{ "BOLD", BOLD },
{ "BLINK", BLINK },
@@ -1646,6 +1742,7 @@ const luaR_value_entry opentxConstants[] = {
{ "VALUE", INPUT_TYPE_VALUE },
{ "SOURCE", INPUT_TYPE_SOURCE },
{ "REPLACE", MLTPX_REP },
+ { "MIXSRC_MAX", MIXSRC_MAX },
{ "MIXSRC_FIRST_INPUT", MIXSRC_FIRST_INPUT },
{ "MIXSRC_Rud", MIXSRC_Rud },
{ "MIXSRC_Ele", MIXSRC_Ele },
@@ -1737,7 +1834,7 @@ const luaR_value_entry opentxConstants[] = {
{ "EVT_VIRTUAL_INC_REPT", EVT_KEY_REPT(KEY_UP) },
#endif
-#if defined(NAVIGATION_9X) || defined(NAVIGATION_XLITE)
+#if defined(NAVIGATION_9X)
{ "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_LONG(KEY_LEFT) },
{ "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_LEFT) },
{ "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_RIGHT) },
@@ -1745,6 +1842,14 @@ const luaR_value_entry opentxConstants[] = {
{ "EVT_VIRTUAL_ENTER", EVT_KEY_BREAK(KEY_ENTER) },
{ "EVT_VIRTUAL_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) },
{ "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) },
+#elif defined(NAVIGATION_XLITE)
+ { "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_LONG(KEY_LEFT) },
+ { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_LONG(KEY_RIGHT) },
+ { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_SHIFT) },
+ { "EVT_VIRTUAL_MENU_LONG", EVT_KEY_LONG(KEY_SHIFT) },
+ { "EVT_VIRTUAL_ENTER", EVT_KEY_BREAK(KEY_ENTER) },
+ { "EVT_VIRTUAL_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) },
+ { "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) },
#elif defined(NAVIGATION_X7) || defined(NAVIGATION_X9D)
{ "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_LONG(KEY_PAGE) },
{ "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PAGE) },
@@ -1768,9 +1873,7 @@ const luaR_value_entry opentxConstants[] = {
{ "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) },
#endif
-#if defined(KEYS_GPIO_REG_EXIT)
{ "EVT_EXIT_BREAK", EVT_KEY_BREAK(KEY_EXIT) },
-#endif
#if defined(KEYS_GPIO_REG_ENTER)
KEY_EVENTS(ENTER, KEY_ENTER),
@@ -1853,8 +1956,6 @@ const luaR_value_entry opentxConstants[] = {
{ "PLAY_BACKGROUND", PLAY_BACKGROUND },
{ "TIMEHOUR", TIMEHOUR },
-#if defined(PCBHORUS)
- // Adding the unit consts for the set Telemetry function adds about 1k of flash usage
{"UNIT_RAW", UNIT_RAW },
{"UNIT_VOLTS", UNIT_VOLTS },
{"UNIT_AMPS", UNIT_AMPS },
@@ -1888,6 +1989,6 @@ const luaR_value_entry opentxConstants[] = {
{"UNIT_GPS", UNIT_GPS},
{"UNIT_BITFIELD", UNIT_BITFIELD},
{"UNIT_TEXT", UNIT_TEXT},
-#endif
+
{ nullptr, 0 } /* sentinel */
};
diff --git a/radio/src/lua/api_lcd.cpp b/radio/src/lua/api_lcd.cpp
index 039aa5547..bb9172e32 100644
--- a/radio/src/lua/api_lcd.cpp
+++ b/radio/src/lua/api_lcd.cpp
@@ -62,6 +62,20 @@ static int luaLcdClear(lua_State *L)
return 0;
}
+/*luadoc
+@function lcd.resetBacklightTimeout()
+
+Reset the backlight timeout
+
+@status current Introduced in 2.3.6
+*/
+static int luaLcdResetBacklightTimeout(lua_State * L)
+{
+ if (!luaLcdAllowed) return 0;
+ resetBacklightTimeout();
+ return 0;
+}
+
/*luadoc
@function lcd.drawPoint(x, y)
@@ -71,6 +85,8 @@ Draw a single pixel at (x,y) position
@param y (positive number) y position
+@param flags (optional) lcdflags
+
@notice Taranis has an LCD display width of 212 pixels and height of 64 pixels.
Position (0,0) is at top left. Y axis is negative, top line is 0,
bottom line is 63. Drawing on an existing black pixel produces white pixel (TODO check this!)
@@ -82,7 +98,8 @@ static int luaLcdDrawPoint(lua_State *L)
if (!luaLcdAllowed) return 0;
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
- lcdDrawPoint(x, y);
+ LcdFlags att = luaL_optunsigned(L, 3, 0);
+ lcdDrawPoint(x, y, att);
return 0;
}
@@ -95,14 +112,14 @@ Draw a straight line on LCD
@param x2,y2 (positive numbers) end coordinate
-@param pattern TODO
+@param pattern SOLID or DOTTED
-@param flags TODO
+@param flags lcdflags
@notice If the start or the end of the line is outside the LCD dimensions, then the
whole line will not be drawn (starting from OpenTX 2.1.5)
-@status current Introduced in 2.0.0
+@status current Introduced in 2.0.0, flags introduced in 2.3.6
*/
static int luaLcdDrawLine(lua_State *L)
{
@@ -858,6 +875,7 @@ static int luaRGB(lua_State *L)
const luaL_Reg lcdLib[] = {
{ "refresh", luaLcdRefresh },
{ "clear", luaLcdClear },
+ { "resetBacklightTimeout", luaLcdResetBacklightTimeout },
{ "drawPoint", luaLcdDrawPoint },
{ "drawLine", luaLcdDrawLine },
{ "drawRectangle", luaLcdDrawRectangle },
diff --git a/radio/src/lua/api_model.cpp b/radio/src/lua/api_model.cpp
index 990d477d4..8eea9d5ec 100644
--- a/radio/src/lua/api_model.cpp
+++ b/radio/src/lua/api_model.cpp
@@ -86,7 +86,24 @@ static int luaModelSetInfo(lua_State *L)
Get RF module parameters
-`subType` values:
+`Type` values:
+ * 0 NONE
+ * 1 PPM
+ * 2 XJT_PXX1
+ * 3 ISRM_PXX2
+ * 4 DSM2
+ * 5 CROSSFIRE
+ * 6 MULTIMODULE
+ * 7 R9M_PXX1
+ * 8 R9M_PXX2
+ * 9 R9M_LITE_PXX1
+ * 10 R9M_LITE_PXX2
+ * 11 R9M_LITE_PRO_PXX1
+ * 12 R9M_LITE_PRO_PXX2
+ * 13 SBUS
+ * 14 XJT_LITE_PXX2
+
+`subType` values for XJT_PXX1:
* -1 OFF
* 0 D16
* 1 D8
@@ -101,6 +118,11 @@ Get RF module parameters
* `modelId` (number) receiver number
* `firstChannel` (number) start channel (0 is CH1)
* `channelsCount` (number) number of channels sent to module
+ * `Type` (number) module type
+ * if the module type is Multi additional information are available
+ * `protocol` (number) protocol number
+ * `subProtocol` (number) sub-protocol number
+ * `channelsOrder` (number) first 4 channels expected order
@status current Introduced in TODO
*/
@@ -114,6 +136,25 @@ static int luaModelGetModule(lua_State *L)
lua_pushtableinteger(L, "modelId", g_model.header.modelId[idx]);
lua_pushtableinteger(L, "firstChannel", module.channelsStart);
lua_pushtableinteger(L, "channelsCount", module.channelsCount + 8);
+ lua_pushtableinteger(L, "Type", module.type);
+#if defined(MULTIMODULE)
+ if (module.type == MODULE_TYPE_MULTIMODULE) {
+ int protocol = g_model.moduleData[idx].getMultiProtocol() + 1;
+ int subprotocol = g_model.moduleData[idx].subType;
+ convertOtxProtocolToMulti(&protocol, &subprotocol); // Special treatment for the FrSky entry...
+ lua_pushtableinteger(L, "protocol", protocol);
+ lua_pushtableinteger(L, "subProtocol", subprotocol);
+ if (getMultiModuleStatus(idx).isValid()) {
+ if (getMultiModuleStatus(idx).ch_order == 0xFF)
+ lua_pushtableinteger(L, "channelsOrder", -1);
+ else
+ lua_pushtableinteger(L, "channelsOrder", getMultiModuleStatus(idx).ch_order);
+ }
+ else {
+ lua_pushtableinteger(L, "channelsOrder", -1);
+ }
+ }
+#endif
}
else {
lua_pushnil(L);
@@ -182,8 +223,9 @@ Get model timer parameters
* `countdownBeep` (number) countdown beep (0 = silent, 1 = beeps, 2 = voice)
* `minuteBeep` (boolean) minute beep
* `persistent` (number) persistent timer
+ * `name` (string) timer name
-@status current Introduced in 2.0.0
+@status current Introduced in 2.0.0, name added in 2.3.6
*/
static int luaModelGetTimer(lua_State *L)
{
@@ -197,6 +239,7 @@ static int luaModelGetTimer(lua_State *L)
lua_pushtableinteger(L, "countdownBeep", timer.countdownBeep);
lua_pushtableboolean(L, "minuteBeep", timer.minuteBeep);
lua_pushtableinteger(L, "persistent", timer.persistent);
+ lua_pushtablezstring(L, "name", timer.name);
}
else {
lua_pushnil(L);
@@ -216,7 +259,7 @@ Set model timer parameters
@notice If a parameter is missing from the value, then
that parameter remains unchanged.
-@status current Introduced in 2.0.0
+@status current Introduced in 2.0.0, name added in 2.3.6
*/
static int luaModelSetTimer(lua_State *L)
{
@@ -246,6 +289,10 @@ static int luaModelSetTimer(lua_State *L)
else if (!strcmp(key, "persistent")) {
timer.persistent = luaL_checkinteger(L, -1);
}
+ if (!strcmp(key, "name")) {
+ const char * name = luaL_checkstring(L, -1);
+ str2zchar(timer.name, name, sizeof(timer.name));
+ }
}
storageDirty(EE_MODEL);
}
@@ -1259,7 +1306,7 @@ static int luaModelSetOutput(lua_State *L)
}
/*luadoc
-@function model.getGlobalVariable(index [, flight_mode])
+@function model.getGlobalVariable(index, flight_mode)
Return current global variable value
diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp
index 73b71da62..a0cef2c1d 100644
--- a/radio/src/lua/interface.cpp
+++ b/radio/src/lua/interface.cpp
@@ -952,7 +952,7 @@ bool luaDoOneRunPermanentScript(event_t evt, int i, uint32_t scriptType)
TelemetryScriptData & script = g_model.screens[sid.reference-SCRIPT_TELEMETRY_FIRST].script;
filename = script.file;
#endif
- if ((scriptType & RUN_TELEM_FG_SCRIPT) && (menuHandlers[0]==menuViewTelemetryFrsky && sid.reference==SCRIPT_TELEMETRY_FIRST+s_frsky_view)) {
+ if ((scriptType & RUN_TELEM_FG_SCRIPT) && (menuHandlers[0]==menuViewTelemetry && sid.reference==SCRIPT_TELEMETRY_FIRST+s_frsky_view)) {
lua_rawgeti(lsScripts, LUA_REGISTRYINDEX, sid.run);
lua_pushunsigned(lsScripts, evt);
inputsCount = 1;
diff --git a/radio/src/lua/lua_api.h b/radio/src/lua/lua_api.h
index 71a1cef01..53ef9df04 100644
--- a/radio/src/lua/lua_api.h
+++ b/radio/src/lua/lua_api.h
@@ -41,6 +41,11 @@ extern "C" {
#endif
#endif
+#if !defined(CLI) || defined(AUX2_SERIAL)
+#define LUA_FIFO_SIZE 256
+extern Fifo * luaRxFifo;
+#endif
+
extern lua_State * lsScripts;
extern lua_State * lsWidgets;
extern bool luaLcdAllowed;
diff --git a/radio/src/lua/widgets.cpp b/radio/src/lua/widgets.cpp
index 165d95eff..4ab6b967e 100644
--- a/radio/src/lua/widgets.cpp
+++ b/radio/src/lua/widgets.cpp
@@ -265,7 +265,7 @@ class LuaWidget: public Widget
virtual void update();
- virtual void refresh();
+ void refresh() override;
virtual void background();
diff --git a/radio/src/main.cpp b/radio/src/main.cpp
index 0a4d1a346..1490fb989 100644
--- a/radio/src/main.cpp
+++ b/radio/src/main.cpp
@@ -50,6 +50,7 @@ void handleUsbConnection()
#if defined(DEBUG)
POPUP_MENU_ADD_ITEM(STR_USB_SERIAL);
#endif
+ POPUP_MENU_TITLE(STR_SELECT_MODE);
POPUP_MENU_START(onUSBConnectMenu);
}
else {
@@ -169,7 +170,8 @@ void checkEeprom()
{
#if defined(RTC_BACKUP_RAM) && !defined(SIMU)
if (TIME_TO_BACKUP_RAM()) {
- rambackupWrite();
+ if (!globalData.unexpectedShutdown)
+ rambackupWrite();
rambackupDirtyMsk = 0;
}
#endif
@@ -381,21 +383,6 @@ void handleGui(event_t event) {
}
else if (luaTask(event, RUN_TELEM_FG_SCRIPT, true)) {
// the telemetry screen is active
- // prevent events from keys MENU, UP, DOWN, ENT(short) and EXIT(short) from reaching the normal menus,
- // so Lua telemetry script can fully use them
- if (event) {
- uint8_t key = EVT_KEY_MASK(event);
-#if defined(PCBXLITE)
- // SHIFT + LEFT/RIGHT LONG used to change telemetry screen on XLITE
- if ((!IS_KEY_LONG(event) && key == KEY_RIGHT && IS_SHIFT_PRESSED()) || (!IS_KEY_LONG(event) && key == KEY_LEFT && IS_SHIFT_PRESSED()) || (!IS_KEY_LONG(event) && key == KEY_EXIT)) {
-#else
- // no need to filter out MENU and ENT(short), because they are not used by menuViewTelemetryFrsky()
- if (key == KEY_PLUS || key == KEY_MINUS || (!IS_KEY_LONG(event) && key == KEY_EXIT)) {
-#endif
- // TRACE("Telemetry script event 0x%02x killed", event);
- event = 0;
- }
- }
menuHandlers[menuLevel](event);
}
else
@@ -469,9 +456,9 @@ void guiMain(event_t evt)
lcdRefresh();
- if (mainRequestFlags & (1 << REQUEST_SCREENSHOT)) {
+ if (mainRequestFlags & (1u << REQUEST_SCREENSHOT)) {
writeScreenshot();
- mainRequestFlags &= ~(1 << REQUEST_SCREENSHOT);
+ mainRequestFlags &= ~(1u << REQUEST_SCREENSHOT);
}
}
#endif
@@ -501,10 +488,10 @@ void perMain()
periodicTick();
DEBUG_TIMER_STOP(debugTimerPerMain1);
- if (mainRequestFlags & (1 << REQUEST_FLIGHT_RESET)) {
+ if (mainRequestFlags & (1u << REQUEST_FLIGHT_RESET)) {
TRACE("Executing requested Flight Reset");
flightReset();
- mainRequestFlags &= ~(1 << REQUEST_FLIGHT_RESET);
+ mainRequestFlags &= ~(1u << REQUEST_FLIGHT_RESET);
}
checkBacklight();
diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp
index e4b701c9c..0e75f94d7 100644
--- a/radio/src/mixer.cpp
+++ b/radio/src/mixer.cpp
@@ -460,7 +460,7 @@ void evalInputs(uint8_t mode)
if (mode == e_perout_mode_normal) {
if (tmp==0 || (tmp==1 && (bpanaCenter & mask))) {
anaCenter |= mask;
- if ((g_model.beepANACenter & mask) && !(bpanaCenter & mask) && !menuCalibrationState) {
+ if ((g_model.beepANACenter & mask) && !(bpanaCenter & mask) && s_mixer_first_run_done && !menuCalibrationState) {
if (!IS_POT(i) || IS_POT_SLIDER_AVAILABLE(i)) {
AUDIO_POT_MIDDLE(i);
}
@@ -901,9 +901,7 @@ void evalMixes(uint8_t tick10ms)
static uint16_t fp_act[MAX_FLIGHT_MODES] = {0};
static uint16_t delta = 0;
- static ACTIVE_PHASES_TYPE flightModesFade = 0;
-
- LS_RECURSIVE_EVALUATION_RESET();
+ static uint16_t flightModesFade = 0;
uint8_t fm = getFlightMode();
@@ -915,7 +913,7 @@ void evalMixes(uint8_t tick10ms)
}
else {
uint8_t fadeTime = max(g_model.flightModeData[lastFlightMode].fadeOut, g_model.flightModeData[fm].fadeIn);
- ACTIVE_PHASES_TYPE transitionMask = ((ACTIVE_PHASES_TYPE)1 << lastFlightMode) + ((ACTIVE_PHASES_TYPE)1 << fm);
+ uint16_t transitionMask = (0x01u << lastFlightMode) + (0x01u << fm);
if (fadeTime) {
flightModesFade |= transitionMask;
delta = (MAX_ACT / 10) / fadeTime;
@@ -945,15 +943,13 @@ void evalMixes(uint8_t tick10ms)
if (flightModesFade) {
memclear(sum_chans512, sizeof(sum_chans512));
for (uint8_t p=0; p> 4) * fp_act[p];
+ sum_chans512[i] += limit(-0x6fff, chans[i] >> 4, 0x6fff) * fp_act[p];
weight += fp_act[p];
}
- LS_RECURSIVE_EVALUATION_RESET();
}
assert(weight);
mixerCurrentFlightMode = fm;
@@ -994,7 +990,7 @@ void evalMixes(uint8_t tick10ms)
if (tick10ms && flightModesFade) {
uint16_t tick_delta = delta * tick10ms;
for (uint8_t p=0; p tick_delta)
@@ -1015,5 +1011,4 @@ void evalMixes(uint8_t tick10ms)
}
}
}
-
}
diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp
index 75f52fb5e..77bb1b894 100644
--- a/radio/src/opentx.cpp
+++ b/radio/src/opentx.cpp
@@ -293,9 +293,7 @@ void generalDefault()
g_eeGeneral.stickMode = DEFAULT_MODE - 1;
#endif
-#if defined(FRSKY_RELEASE)
- g_eeGeneral.templateSetup = 17; /* TAER */
-#endif
+ g_eeGeneral.templateSetup = DEFAULT_TEMPLATE_SETUP;
g_eeGeneral.backlightMode = e_backlight_mode_all;
g_eeGeneral.lightAutoOff = 2;
@@ -437,36 +435,27 @@ void checkModelIdUnique(uint8_t index, uint8_t module)
uint8_t findNextUnusedModelId(uint8_t index, uint8_t module)
{
- // assume 63 is the highest Model ID
- // and use 64 bits
- uint8_t usedModelIds[8];
+ uint8_t usedModelIds[(MAX_RXNUM + 7) / 8];
memset(usedModelIds, 0, sizeof(usedModelIds));
- for (uint8_t mod_i = 0; mod_i < MAX_MODELS; mod_i++) {
-
- if (mod_i == index)
+ for (uint8_t modelIndex = 0; modelIndex < MAX_MODELS; modelIndex++) {
+ if (modelIndex == index)
continue;
- uint8_t id = modelHeaders[mod_i].modelId[module];
+ uint8_t id = modelHeaders[modelIndex].modelId[module];
if (id == 0)
continue;
- uint8_t mask = 1;
- for (uint8_t i = 1; i < (id & 7); i++)
- mask <<= 1;
-
- usedModelIds[id >> 3] |= mask;
+ uint8_t mask = 1u << (id & 7u);
+ usedModelIds[id >> 3u] |= mask;
}
- uint8_t new_id = 1;
- uint8_t tst_mask = 1;
- for (;new_id < getMaxRxNum(module); new_id++) {
- if (!(usedModelIds[new_id >> 3] & tst_mask)) {
+ for (uint8_t id = 1; id <= getMaxRxNum(module); id++) {
+ uint8_t mask = 1u << (id & 7u);
+ if (!(usedModelIds[id >> 3u] & mask)) {
// found free ID
- return new_id;
+ return id;
}
- if ((tst_mask <<= 1) == 0)
- tst_mask = 1;
}
// failed finding something...
@@ -482,7 +471,7 @@ void modelDefault(uint8_t id)
memcpy(g_model.modelRegistrationID, g_eeGeneral.ownerRegistrationID, PXX2_LEN_REGISTRATION_ID);
-#if defined(LUA) && defined(PCBTARANIS) //Horus uses menuModelWizard() for wizard
+#if defined(LUA) && defined(PCBTARANIS) // Horus uses menuModelWizard() for wizard
if (isFileAvailable(WIZARD_PATH "/" WIZARD_NAME)) {
f_chdir(WIZARD_PATH);
luaExec(WIZARD_NAME);
@@ -492,23 +481,20 @@ void modelDefault(uint8_t id)
#if defined(FRSKY_RELEASE)
g_model.moduleData[INTERNAL_MODULE].type = IS_PXX2_INTERNAL_ENABLED() ? MODULE_TYPE_ISRM_PXX2 : MODULE_TYPE_XJT_PXX1;
g_model.moduleData[INTERNAL_MODULE].channelsCount = defaultModuleChannels_M8(INTERNAL_MODULE);
+ #if defined(EEPROM)
+ g_model.header.modelId[INTERNAL_MODULE] = findNextUnusedModelId(id, INTERNAL_MODULE);
+ modelHeaders[id].modelId[INTERNAL_MODULE] = g_model.header.modelId[INTERNAL_MODULE];
+ #endif
#endif
#if defined(PCBXLITE)
g_model.trainerData.mode = TRAINER_MODE_MASTER_BLUETOOTH;
#endif
-#if defined(EEPROM)
- for (int i=0; i= tgtime-200) {
secondSplash = true;
@@ -885,7 +871,7 @@ void checkFailsafe()
void checkRSSIAlarmsDisabled()
{
if (g_model.rssiAlarms.disabled) {
-#if !defined(INTERNAL_MODULE)
+#if !defined(HARDWARE_INTERNAL_MODULE)
if (!isModuleMultimoduleDSM2(EXTERNAL_MODULE))
#else
if (!isModuleMultimoduleDSM2(INTERNAL_MODULE) && !isModuleMultimoduleDSM2(EXTERNAL_MODULE))
@@ -1566,8 +1552,8 @@ void opentxStart(const uint8_t startOptions = OPENTX_START_DEFAULT_ARGS)
}
#endif
-#if defined(NIGHTLY_BUILD_WARNING)
- ALERT(STR_NIGHTLY_WARNING, TR_NIGHTLY_NOTSAFE, AU_ERROR);
+#if defined(TEST_BUILD_WARNING)
+ ALERT(STR_TEST_WARNING, TR_TEST_NOTSAFE, AU_ERROR);
#endif
#if defined(GUI)
@@ -1737,6 +1723,25 @@ void copyTrimsToOffset(uint8_t ch)
storageDirty(EE_MODEL);
}
+void copyMinMaxToOutputs(uint8_t ch)
+{
+ LimitData *ld = limitAddress(ch);
+ int16_t min = ld->min;
+ int16_t max = ld->max;
+ int16_t center = ld->ppmCenter;
+
+ pauseMixerCalculations();
+
+ for (uint8_t chan = 0; chan < MAX_OUTPUT_CHANNELS; chan++) {
+ ld = limitAddress(chan);
+ ld->min = min;
+ ld->max = max;
+ ld->ppmCenter = center;
+ }
+
+ resumeMixerCalculations();
+ storageDirty(EE_MODEL);
+}
#if defined(STARTUP_ANIMATION)
@@ -1934,6 +1939,10 @@ void opentxInit()
auxSerialInit(g_eeGeneral.auxSerialMode, modelTelemetryProtocol());
#endif
+#if defined(AUX2_SERIAL)
+ aux2SerialInit(g_eeGeneral.aux2SerialMode, modelTelemetryProtocol());
+#endif
+
#if MENUS_LOCK == 1
getMovedSwitch();
if (TRIMS_PRESSED() && g_eeGeneral.switchUnlockStates==switches_states) {
@@ -1959,6 +1968,10 @@ void opentxInit()
btInit();
#endif
+#if defined(SPORT_UPDATE_PWR_GPIO)
+ SPORT_UPDATE_POWER_INIT();
+#endif
+
#if defined(COLORLCD)
loadTheme();
loadFontCache();
@@ -1966,7 +1979,7 @@ void opentxInit()
if (g_eeGeneral.backlightMode != e_backlight_mode_off) {
// on Tx start turn the light on
- backlightOn();
+ resetBacklightTimeout();
}
if (!globalData.unexpectedShutdown) {
@@ -1984,19 +1997,27 @@ void opentxInit()
lcdSetContrast();
#endif
- backlightOn();
+ resetBacklightTimeout();
startPulses();
WDG_ENABLE(WDG_DURATION);
}
+#if defined(SEMIHOSTING)
+extern "C" void initialise_monitor_handles();
+#endif
+
#if defined(SIMU)
void simuMain()
#else
int main()
#endif
{
+#if defined(SEMIHOSTING)
+ initialise_monitor_handles();
+#endif
+
#if defined(STM32)
TRACE("reusableBuffer: modelSel=%d, moduleSetup=%d, calib=%d, sdManager=%d, hardwareAndSettings=%d, spectrumAnalyser=%d, usb=%d",
sizeof(reusableBuffer.modelsel),
@@ -2052,6 +2073,10 @@ int main()
inline uint32_t PWR_PRESS_SHUTDOWN_DELAY()
{
+ // Instant off when both power button are pressed
+ if (pwrForcePressed())
+ return 0;
+
return (2 - g_eeGeneral.pwrOffSpeed) * 100;
}
diff --git a/radio/src/opentx.h b/radio/src/opentx.h
index cda5378d8..0d21d5df5 100644
--- a/radio/src/opentx.h
+++ b/radio/src/opentx.h
@@ -21,14 +21,12 @@
#ifndef _OPENTX_H_
#define _OPENTX_H_
-#include
-#include
-#include
#include
-#include
#include "definitions.h"
#include "opentx_types.h"
#include "debounce.h"
+#include "globals.h"
+#include "opentx_helpers.h"
#if defined(SIMU)
#include "targets/simu/simpgmspace.h"
@@ -219,6 +217,10 @@
#define IS_SLAVE_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
#endif
+#if defined(LUA) || defined(PXX2) || defined(MULTIMODULE)
+ #define RADIO_TOOLS
+#endif
+
// RESX range is used for internal calculation; The menu says -100.0 to 100.0; internally it is -1024 to 1024 to allow some optimizations
#define RESX_SHIFT 10
#define RESX 1024
@@ -251,17 +253,6 @@
#include "myeeprom.h"
-inline void memclear(void * p, size_t size)
-{
- memset(p, 0, size);
-}
-
-inline bool is_memclear(void * p, size_t size)
-{
- uint8_t * buf = (uint8_t *)p;
- return buf[0] == 0 && memcmp(buf, buf + 1, size - 1) == 0;
-}
-
void memswap(void * a, void * b, uint8_t size);
#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || defined(PCBHORUS)
@@ -481,17 +472,19 @@ extern uint8_t flightModeTransitionLast;
#if defined(SIMU)
inline int availableMemory() { return 1000; }
-#elif !defined(SIMU)
+#else
extern unsigned char *heap;
extern int _end;
extern int _heap_end;
#define availableMemory() ((unsigned int)((unsigned char *)&_heap_end - heap))
#endif
+extern uint32_t nextMixerTime[NUM_MODULES];
+
void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms);
void evalMixes(uint8_t tick10ms);
void doMixerCalculations();
-void scheduleNextMixerCalculation(uint8_t module, uint16_t period_ms);
+void scheduleNextMixerCalculation(uint8_t module, uint32_t period_ms);
void checkTrims();
void perMain();
@@ -507,7 +500,6 @@ void logicalSwitchesReset();
void evalLogicalSwitches(bool isCurrentFlightmode=true);
void logicalSwitchesCopyState(uint8_t src, uint8_t dst);
-#define LS_RECURSIVE_EVALUATION_RESET()
#if defined(PCBTARANIS) || defined(PCBHORUS)
void getSwitchesPosition(bool startup);
@@ -544,7 +536,7 @@ bool setTrimValue(uint8_t phase, uint8_t idx, int trim);
#if defined(PCBSKY9X)
#define ROTARY_ENCODER_GRANULARITY (2 << g_eeGeneral.rotarySteps)
-#elif defined(RADIO_T16)
+#elif defined(RADIO_FAMILY_T16) && !defined(RADIO_T18)
#define ROTARY_ENCODER_GRANULARITY (1)
#else
#define ROTARY_ENCODER_GRANULARITY (2)
@@ -552,34 +544,8 @@ bool setTrimValue(uint8_t phase, uint8_t idx, int trim);
#include "gvars.h"
-extern uint16_t sessionTimer;
-extern uint16_t s_timeCumThr;
-extern uint16_t s_timeCum16ThrP;
-
-#if defined(OVERRIDE_CHANNEL_FUNCTION)
-#define OVERRIDE_CHANNEL_UNDEFINED -4096
-extern safetych_t safetyCh[MAX_OUTPUT_CHANNELS];
-#endif
-
-extern uint8_t trimsCheckTimer;
-extern uint8_t trimsDisplayTimer;
-extern uint8_t trimsDisplayMask;
-
void flightReset(uint8_t check=true);
-PACK(struct GlobalData {
- uint8_t unexpectedShutdown:1;
- uint8_t externalAntennaEnabled:1;
- uint8_t authenticationCount:2;
- uint8_t upgradeModulePopup:1;
- uint8_t internalModuleVersionChecked:1;
- uint8_t spare:2;
-});
-
-extern GlobalData globalData;
-
-extern uint16_t maxMixerDuration;
-
#define DURATION_MS_PREC2(x) ((x)/20)
#if defined(THRTRACE)
@@ -640,7 +606,7 @@ static inline void GET_ADC_IF_MIXER_NOT_RUNNING()
#include "sbus.h"
-void backlightOn();
+void resetBacklightTimeout();
void checkBacklight();
#define BITMASK(bit) (1<<(bit))
@@ -712,6 +678,7 @@ inline int calcRESXto100(int x)
#if defined(COLORLCD)
+extern const char fw_stamp[];
extern const char vers_stamp[];
extern const char date_stamp[];
extern const char time_stamp[];
@@ -725,17 +692,12 @@ extern const char vers_stamp[];
* @param buffer If non-null find the firmware version in the buffer instead
* @return The opentx version string starting with "opentx-" or "no version found" if the version string is not found
*/
-const char * getOtherVersion(char * buffer);
+const char * getFirmwareVersion(const char * buffer = nullptr);
#define g_blinkTmr10ms (*(uint8_t*)&g_tmr10ms)
-extern uint8_t g_beepCnt;
#include "trainer.h"
-extern int32_t chans[MAX_OUTPUT_CHANNELS];
-extern int16_t ex_chans[MAX_OUTPUT_CHANNELS]; // Outputs (before LIMITS) of the last perMain
-extern int16_t channelOutputs[MAX_OUTPUT_CHANNELS];
-
int expo(int x, int k);
inline void getMixSrcRange(const int source, int16_t & valMin, int16_t & valMax, LcdFlags * flags = 0)
@@ -834,53 +796,22 @@ int16_t applyLimits(uint8_t channel, int32_t value);
void evalInputs(uint8_t mode);
uint16_t anaIn(uint8_t chan);
-extern int16_t calibratedAnalogs[NUM_CALIBRATED_ANALOGS];
-
#define FLASH_DURATION 20 /*200ms*/
-extern uint8_t beepAgain;
-extern uint16_t lightOffCounter;
-extern uint8_t flashCounter;
-extern uint8_t mixWarning;
-
FlightModeData * flightModeAddress(uint8_t idx);
ExpoData * expoAddress(uint8_t idx);
MixData * mixAddress(uint8_t idx);
LimitData * limitAddress(uint8_t idx);
LogicalSwitchData * lswAddress(uint8_t idx);
-// static variables used in evalFlightModeMixes - moved here so they don't interfere with the stack
-// It's also easier to initialize them here.
-extern int8_t virtualInputsTrims[MAX_INPUTS];
-
-extern int16_t anas [MAX_INPUTS];
-extern int16_t trims[NUM_TRIMS];
-extern BeepANACenter bpanaCenter;
-
-extern uint8_t s_mixer_first_run_done;
-
void applyDefaultTemplate();
-
void instantTrim();
void evalTrims();
void copyTrimsToOffset(uint8_t ch);
void copySticksToOffset(uint8_t ch);
+void copyMinMaxToOutputs(uint8_t ch);
void moveTrimsToOffsets();
-typedef uint16_t ACTIVE_PHASES_TYPE;
-#define DELAY_POS_MARGIN 3
-typedef int16_t delayval_t;
-PACK(struct SwOn {
- uint16_t delay:14; // max = 2550
- uint8_t activeMix:1;
- uint8_t activeExpo:1;
- int16_t now; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
- int16_t prev;
-});
-
-extern SwOn swOn[MAX_MIXERS];
-extern int32_t act[MAX_MIXERS];
-
#if defined(BOLD_FONT)
inline bool isExpoActive(uint8_t expo)
{
@@ -1054,15 +985,6 @@ void setMFP();
void clearMFP();
#endif
-extern uint8_t requiredSpeakerVolume;
-
-enum MainRequest {
- REQUEST_SCREENSHOT,
- REQUEST_FLIGHT_RESET,
-};
-
-extern uint8_t mainRequestFlags;
-
void checkBattery();
void opentxClose(uint8_t shutdown=true);
void opentxInit();
@@ -1364,9 +1286,7 @@ extern uint16_t s_anaFilt[NUM_ANALOGS];
#if defined(JITTER_MEASURE)
extern JitterMeter rawJitter[NUM_ANALOGS];
extern JitterMeter avgJitter[NUM_ANALOGS];
-#if defined(PCBHORUS)
- #define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuStatsAnalogs)
-#elif defined(PCBTARANIS)
+#if defined(PCBHORUS) || defined(PCBTARANIS)
#define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuRadioDiagAnalogs)
#elif defined(CLI)
#define JITTER_MEASURE_ACTIVE() (1)
@@ -1398,7 +1318,7 @@ extern uint8_t latencyToggleSwitch;
inline bool isAsteriskDisplayed()
{
-#if defined(ASTERISK) || !defined(WATCHDOG) || defined(LOG_TELEMETRY) || defined(DEBUG_LATENCY)
+#if defined(ASTERISK) || !defined(WATCHDOG) || defined(LOG_TELEMETRY) || defined(LOG_BLUETOOTH) || defined(DEBUG_LATENCY)
return true;
#endif
diff --git a/radio/src/opentx_helpers.h b/radio/src/opentx_helpers.h
index 8ddeba85e..866fdfb98 100644
--- a/radio/src/opentx_helpers.h
+++ b/radio/src/opentx_helpers.h
@@ -21,10 +21,23 @@
#ifndef _OPENTX_HELPERS_H_
#define _OPENTX_HELPERS_H_
+#include
+
template inline t min(t a, t b) { return a inline t max(t a, t b) { return a>b?a:b; }
template inline t sgn(t a) { return a>0 ? 1 : (a < 0 ? -1 : 0); }
template inline t limit(t mi, t x, t ma) { return min(max(mi,x),ma); }
template inline void SWAP(t & a, t & b) { t tmp = b; b = a; a = tmp; }
+inline void memclear(void * p, size_t size)
+{
+ memset(p, 0, size);
+}
+
+inline bool is_memclear(void * p, size_t size)
+{
+ uint8_t * buf = (uint8_t *)p;
+ return buf[0] == 0 && memcmp(buf, buf + 1, size - 1) == 0;
+}
+
#endif // _OPENTX_HELPERS_H_
diff --git a/radio/src/options.h b/radio/src/options.h
index e7ddb0caf..b9d2a0075 100644
--- a/radio/src/options.h
+++ b/radio/src/options.h
@@ -22,7 +22,7 @@
#ifndef OPENTX_OPTIONS_H
#define OPENTX_OPTIONS_H
-static const char * options[] = {
+static const char * const options[] = {
#if defined(AUTOUPDATE)
"autoupdate",
#endif
@@ -33,10 +33,10 @@ static const char * options[] = {
"eu",
#endif
#if defined(FAI)
- "faimode",
+ "FAImode",
#endif
#if defined(FAI_CHOICE)
- "faichoice",
+ "FAIchoice",
#endif
#if defined(MODULE_PROTOCOL_FLEX)
"flexr9m",
@@ -53,12 +53,18 @@ static const char * options[] = {
#if defined(HORUS_STICKS)
"horussticks",
#endif
+#if defined(INTERNAL_GPS)
+ "internalgps",
+#endif
#if defined(INTERNAL_MODULE_PPM)
"internalppm",
#endif
#if defined(INTERNAL_MODULE_MULTI)
"internalmulti",
#endif
+#if defined(INTERNAL_MODULE_PXX2)
+ "internalaccess",
+#endif
#if defined(MULTIMODULE)
"multimodule",
#endif
diff --git a/radio/src/pulses/afhds3.cpp b/radio/src/pulses/afhds3.cpp
new file mode 100644
index 000000000..bcfe8d3cf
--- /dev/null
+++ b/radio/src/pulses/afhds3.cpp
@@ -0,0 +1,706 @@
+/*
+ * 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 "afhds3.h"
+#include "../debug.h"
+#include "../definitions.h"
+#include
+
+#define FAILSAFE_HOLD 1
+#define FAILSAFE_CUSTOM 2
+#define MAX_RETRIES_AFHDS3 5
+
+extern void processFlySkySensor(const uint8_t * packet, uint8_t type);
+
+extern void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us, bool inverted);
+
+namespace afhds3
+{
+
+static const char* const moduleStateText[] =
+{
+ "Not ready",
+ "HW Error",
+ "Binding",
+ "Connecting",
+ "Connected",
+ "Standby",
+ "Waiting for update",
+ "Updating",
+ "Updating RX",
+ "Updating RX failed",
+ "Testing",
+ "Ready",
+ "HW test"
+};
+
+static const char* const powerSourceText[] =
+{
+ "Unknown",
+ "Internal",
+ "External"
+};
+
+static const COMMAND periodicRequestCommands[] =
+{
+ COMMAND::MODULE_STATE,
+ COMMAND::MODULE_POWER_STATUS,
+ COMMAND::MODULE_GET_CONFIG,
+ COMMAND::VIRTUAL_FAILSAFE
+};
+
+//Address used in transmitted frames - it constrains of target address and source address
+const uint8_t FrameAddress = DeviceAddress::TRANSMITTER | (DeviceAddress::MODULE << 4);
+
+//Static collection of afhds3 object instances by module
+PulsesData* AFHDS3PulsesData[EXTERNAL_MODULE + 1] = { nullptr, nullptr };
+
+//friends function that can access telemetry parsing method
+void processTelemetryData(uint8_t module, uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize)
+{
+ if (AFHDS3PulsesData[module]) {
+ AFHDS3PulsesData[module]->processTelemetryData(data, rxBuffer, rxBufferCount, maxSize);
+ }
+}
+
+void CommandFifo::clearCommandFifo()
+{
+ memclear(commandFifo, sizeof(commandFifo));
+ setIndex = getIndex = 0;
+}
+
+void CommandFifo::enqueueACK(COMMAND command, uint8_t frameNumber)
+{
+ uint32_t next = nextIndex(setIndex);
+ if (next != getIndex) {
+ commandFifo[setIndex].command = command;
+ commandFifo[setIndex].frameType = FRAME_TYPE::RESPONSE_ACK;
+ commandFifo[setIndex].payload = 0;
+ commandFifo[setIndex].payloadSize = 0;
+ commandFifo[setIndex].frameNumber = frameNumber;
+ commandFifo[setIndex].useFrameNumber = true;
+ setIndex = next;
+ }
+}
+
+void CommandFifo::enqueue(COMMAND command, FRAME_TYPE frameType, bool useData, uint8_t byteContent)
+{
+ uint32_t next = nextIndex(setIndex);
+ if (next != getIndex) {
+ commandFifo[setIndex].command = command;
+ commandFifo[setIndex].frameType = frameType;
+ commandFifo[setIndex].payload = byteContent;
+ commandFifo[setIndex].payloadSize = useData ? 1 : 0;
+ commandFifo[setIndex].frameNumber = 0;
+ commandFifo[setIndex].useFrameNumber = false;
+ setIndex = next;
+ }
+}
+
+void PulsesData::getStatusString(char * buffer) const
+{
+ strcpy(buffer, this->state <= ModuleState::STATE_READY ? moduleStateText[this->state] : "Unknown");
+}
+
+void PulsesData::getPowerStatus(char* buffer) const
+{
+ strcpy(buffer, this->powerSource <= MODULE_POWER_SOURCE::EXTERNAL ? powerSourceText[this->powerSource] : "Unknown");
+}
+
+void PulsesData::processTelemetryData(uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize)
+{
+ if (rxBufferCount == 0 && byte != AfhdsSpecialChars::START) {
+ TRACE("AFHDS3 [SKIP] %02X", byte);
+ this->esc_state = 0;
+ return;
+ }
+
+ if (byte == AfhdsSpecialChars::ESC) {
+ this->esc_state = rxBufferCount;
+ return;
+ }
+
+ if (rxBufferCount > 1 && byte == AfhdsSpecialChars::END) {
+ rxBuffer[rxBufferCount++] = byte;
+ parseData(rxBuffer, rxBufferCount);
+ rxBufferCount = 0;
+ return;
+ }
+
+ if (this->esc_state && byte == AfhdsSpecialChars::ESC_END) {
+ byte = AfhdsSpecialChars::END;
+ }
+ else if (esc_state && byte == AfhdsSpecialChars::ESC_ESC) {
+ byte = AfhdsSpecialChars::ESC;
+ }
+ //reset esc index
+ this->esc_state = 0;
+
+ if (rxBufferCount >= maxSize) {
+ TRACE("AFHDS3 [BUFFER OVERFLOW]");
+ rxBufferCount = 0;
+ }
+ rxBuffer[rxBufferCount++] = byte;
+}
+
+bool PulsesData::isConnectedUnicast()
+{
+ return cfg.config.telemetry == TELEMETRY::TELEMETRY_ENABLED && this->state == ModuleState::STATE_SYNC_DONE;
+}
+
+bool PulsesData::isConnectedMulticast()
+{
+ return cfg.config.telemetry == TELEMETRY::TELEMETRY_DISABLED && this->state == ModuleState::STATE_SYNC_RUNNING;
+}
+
+void PulsesData::setupFrame()
+{
+ if (operationState == State::AWAITING_RESPONSE) {
+ if (repeatCount++ < MAX_RETRIES_AFHDS3) {
+ return; //re-send
+ }
+ else
+ {
+ TRACE("AFHDS3 [NO RESP] module state %d", this->state);
+ clearFrameData();
+ this->state = ModuleState::STATE_NOT_READY;
+ }
+ }
+ else if (operationState == State::UNKNOWN) {
+ this->state = ModuleState::STATE_NOT_READY;
+ }
+ repeatCount = 0;
+ if (this->state == ModuleState::STATE_NOT_READY) {
+ TRACE("AFHDS3 [GET MODULE READY]");
+ putFrame(COMMAND::MODULE_READY, FRAME_TYPE::REQUEST_GET_DATA);
+ return;
+ }
+
+ //check waiting commands
+ if (!isEmpty()) {
+ Frame f = commandFifo[getIndex];
+ putFrame(f.command, f.frameType, &f.payload, f.payloadSize, f.useFrameNumber ? &f.frameNumber : &frame_index);
+ getIndex = nextIndex(getIndex);
+ TRACE("AFHDS3 [CMD QUEUE] cmd: %d frameType %d, useFrameNumber %d frame Number %d size %d", f.command, f.frameType, f.useFrameNumber, f.frameNumber, f.payloadSize);
+ return;
+ }
+
+ //config should be loaded already
+ if (syncSettings()) {
+ return;
+ }
+
+ //if module is ready but not started
+ if (this->state == ModuleState::STATE_READY || this->state == ModuleState::STATE_STANDBY) {
+ cmdCount = 0;
+ repeatCount = 0;
+ requestInfoAndRun(true);
+ return;
+ }
+
+ ::ModuleSettingsMode moduleMode = getModuleMode(module_index);
+
+ if (moduleMode == ::ModuleSettingsMode::MODULE_MODE_BIND) {
+ if (state != STATE_BINDING) {
+ TRACE("AFHDS3 [BIND]");
+ setConfigFromModel();
+ putFrame(COMMAND::MODULE_SET_CONFIG, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, cfg.buffer, sizeof(cfg.buffer));
+ requestedModuleMode = MODULE_MODE_E::BIND;
+ enqueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, true, requestedModuleMode);
+ return;
+ }
+ }
+ else if (moduleMode == ::ModuleSettingsMode::MODULE_MODE_RANGECHECK) {
+ if (cfg.config.runPower != RUN_POWER::RUN_POWER_FIRST) {
+ TRACE("AFHDS3 [RANGE CHECK]");
+ cfg.config.runPower = RUN_POWER::RUN_POWER_FIRST;
+ uint8_t data[] = { 0x13, 0x20, 0x02, cfg.config.runPower, 0 };
+ TRACE("AFHDS3 SET TX POWER %d", moduleData->afhds3.runPower);
+ putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
+ return;
+ }
+ }
+ else if (moduleMode == ::ModuleSettingsMode::MODULE_MODE_NORMAL) { //exit bind
+ if (state == STATE_BINDING) {
+ TRACE("AFHDS3 [EXIT BIND]");
+ requestedModuleMode = MODULE_MODE_E::RUN;
+ putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &requestedModuleMode, 1);
+ return;
+ }
+ }
+
+ bool isConnected = isConnectedUnicast() || isConnectedMulticast();
+
+ if (cmdCount++ >= 150) {
+ cmdCount = 0;
+ if (cmdIndex >= sizeof(periodicRequestCommands)) {
+ cmdIndex = 0;
+ }
+ COMMAND cmd = periodicRequestCommands[cmdIndex++];
+
+ if (cmd == COMMAND::VIRTUAL_FAILSAFE) {
+ if (isConnected) {
+ if (isConnectedMulticast()) {
+ TRACE("AFHDS ONE WAY FAILSAFE");
+ uint16_t failSafe[MAX_CHANNELS + 1] = { ((MAX_CHANNELS << 8) | CHANNELS_DATA_MODE::FAIL_SAFE), 0 };
+ setFailSafe((int16_t*) (&failSafe[1]));
+ putFrame(COMMAND::CHANNELS_FAILSAFE_DATA, FRAME_TYPE::REQUEST_SET_NO_RESP, (uint8_t*) failSafe, MAX_CHANNELS * 2 + 2);
+ }
+ else {
+ TRACE("AFHDS TWO WAYS FAILSAFE");
+ uint8_t failSafe[3 + MAX_CHANNELS * 2] = { 0x11, 0x60, MAX_CHANNELS * 2 };
+ setFailSafe((int16_t*) (failSafe + 3));
+ putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, failSafe, 3 + MAX_CHANNELS * 2);
+ }
+ }
+ else {
+ putFrame(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA);
+ }
+ }
+ else
+ {
+ putFrame(cmd, FRAME_TYPE::REQUEST_GET_DATA);
+ }
+ }
+ else if (isConnected) {
+ sendChannelsData();
+ }
+ else {
+ //default frame - request state
+ putFrame(MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA);
+ }
+}
+
+void PulsesData::init(uint8_t moduleIndex, bool resetFrameCount)
+{
+ module_index = moduleIndex;
+ AFHDS3PulsesData[module_index] = this;
+ //clear local vars because it is member of union
+ moduleData = &g_model.moduleData[module_index];
+ operationState = State::UNKNOWN;
+ state = ModuleState::STATE_NOT_READY;
+ clearFrameData();
+}
+
+void PulsesData::clearFrameData()
+{
+ TRACE("AFHDS3 clearFrameData");
+ reset();
+ clearCommandFifo();
+ repeatCount = 0;
+ cmdCount = 0;
+ cmdIndex = 0;
+ this->frame_index = 1;
+ this->timeout = 0;
+ this->esc_state = 0;
+}
+
+void PulsesData::putBytes(uint8_t* data, int length)
+{
+ for (int i = 0; i < length; i++) {
+ uint8_t byte = data[i];
+ this->crc += byte;
+ if (END == byte) {
+ sendByte(ESC);
+ sendByte(ESC_END);
+ }
+ else if (ESC == byte) {
+ sendByte(ESC);
+ sendByte(ESC_ESC);
+ }
+ else {
+ sendByte(byte);
+ }
+ }
+}
+
+void PulsesData::putFrame(COMMAND command, FRAME_TYPE frame, uint8_t* data, uint8_t dataLength, uint8_t* frameIndex)
+{
+ //header
+ operationState = State::SENDING_COMMAND;
+ reset();
+ this->crc = 0;
+ sendByte(START);
+ if (frameIndex == nullptr) {
+ frameIndex = &this->frame_index;
+ }
+ uint8_t buffer[] = {FrameAddress, *frameIndex, frame, command};
+ putBytes(buffer, 4);
+
+ //payload
+ if (dataLength > 0) {
+ putBytes(data, dataLength);
+ }
+ //footer
+ uint8_t crcValue = this->crc ^ 0xff;
+ putBytes(&crcValue, 1);
+ sendByte(END);
+ *frameIndex = *frameIndex + 1;
+
+ switch (frame) {
+ case FRAME_TYPE::REQUEST_GET_DATA:
+ case FRAME_TYPE::REQUEST_SET_EXPECT_ACK:
+ case FRAME_TYPE::REQUEST_SET_EXPECT_DATA:
+ operationState = State::AWAITING_RESPONSE;
+ break;
+ default:
+ operationState = State::IDLE;
+ }
+
+ flush();
+}
+
+bool checkCRC(const uint8_t* data, uint8_t size)
+{
+ uint8_t crc = 0;
+ //skip start byte
+ for (uint8_t i = 1; i < size; i++) {
+ crc += data[i];
+ }
+ return (crc ^ 0xff) == data[size];
+}
+
+bool containsData(enum FRAME_TYPE frameType)
+{
+ return (frameType == FRAME_TYPE::RESPONSE_DATA ||
+ frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA ||
+ frameType == FRAME_TYPE::REQUEST_SET_EXPECT_ACK ||
+ frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA ||
+ frameType == FRAME_TYPE::REQUEST_SET_NO_RESP);
+}
+
+void PulsesData::setState(uint8_t state)
+{
+ if (state == this->state) {
+ return;
+ }
+ uint8_t oldState = this->state;
+ this->state = state;
+ if (oldState == ModuleState::STATE_BINDING) {
+ setModuleMode(module_index, ::ModuleSettingsMode::MODULE_MODE_NORMAL);
+ }
+ if (state == ModuleState::STATE_NOT_READY) {
+ operationState = State::UNKNOWN;
+ }
+}
+
+void PulsesData::requestInfoAndRun(bool send)
+{
+ if (!send) {
+ enqueue(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA);
+ }
+ enqueue(COMMAND::MODULE_POWER_STATUS, FRAME_TYPE::REQUEST_GET_DATA);
+ requestedModuleMode = MODULE_MODE_E::RUN;
+ enqueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, true, (uint8_t) MODULE_MODE_E::RUN);
+ if (send) {
+ putFrame(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA);
+ }
+}
+
+void PulsesData::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount)
+{
+
+ if (!checkCRC(rxBuffer, rxBufferCount - 2)) {
+ TRACE("AFHDS3 [INVALID CRC]");
+ return;
+ }
+ AfhdsFrame* responseFrame = reinterpret_cast(rxBuffer);
+ if (containsData((enum FRAME_TYPE) responseFrame->frameType)) {
+ switch (responseFrame->command) {
+ case COMMAND::MODULE_READY:
+ TRACE("AFHDS3 [MODULE_READY] %02X", responseFrame->value);
+ if (responseFrame->value == MODULE_STATUS_READY) {
+ setState(ModuleState::STATE_READY);
+ requestInfoAndRun();
+ }
+ else {
+ setState(ModuleState::STATE_NOT_READY);
+ }
+ break;
+ case COMMAND::MODULE_GET_CONFIG:
+ std::memcpy((void*) cfg.buffer, &responseFrame->value, sizeof(cfg.buffer));
+ TRACE("AFHDS3 [MODULE_GET_CONFIG] bind power %d run power %d mode %d pwm/ppm %d ibus/sbus %d", cfg.config.bindPower, cfg.config.runPower, cfg.config.telemetry, cfg.config.pulseMode, cfg.config.serialMode);
+ break;
+ case COMMAND::MODULE_VERSION:
+ std::memcpy((void*) &version, &responseFrame->value, sizeof(version));
+ TRACE("AFHDS3 [MODULE_VERSION] Product %d, HW %d, BOOT %d, FW %d", version.productNumber, version.hardwereVersion, version.bootloaderVersion, version.firmwareVersion);
+ break;
+ case COMMAND::MODULE_POWER_STATUS:
+ powerSource = (enum MODULE_POWER_SOURCE) responseFrame->value;
+ TRACE("AFHDS3 [MODULE_POWER_STATUS], %d", powerSource);
+ break;
+ case COMMAND::MODULE_STATE:
+ TRACE("AFHDS3 [MODULE_STATE] %02X", responseFrame->value);
+ setState(responseFrame->value);
+ break;
+ case COMMAND::MODULE_MODE:
+ TRACE("AFHDS3 [MODULE_MODE] %02X", responseFrame->value);
+ if (responseFrame->value != CMD_RESULT::SUCCESS) {
+ setState(ModuleState::STATE_NOT_READY);
+ }
+ else {
+ if (requestedModuleMode == MODULE_MODE_E::RUN) {
+ enqueue(COMMAND::MODULE_GET_CONFIG, FRAME_TYPE::REQUEST_GET_DATA);
+ enqueue(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA);
+ }
+ requestedModuleMode = MODULE_MODE_UNKNOWN;
+ }
+ break;
+ case COMMAND::MODULE_SET_CONFIG:
+ if (responseFrame->value != CMD_RESULT::SUCCESS) {
+ setState(ModuleState::STATE_NOT_READY);
+ }
+ TRACE("AFHDS3 [MODULE_SET_CONFIG], %02X", responseFrame->value);
+ break;
+ case COMMAND::TELEMETRY_DATA:
+ {
+ uint8_t* telemetry = &responseFrame->value;
+
+ if (telemetry[0] == 0x22) {
+ telemetry++;
+ while (telemetry < rxBuffer + rxBufferCount) {
+ uint8_t length = telemetry[0];
+ uint8_t id = telemetry[1];
+ if (id == 0xFE) {
+ id = 0xF7; //use new id because format is different
+ }
+ if (length == 0 || telemetry + length > rxBuffer + rxBufferCount) {
+ break;
+ }
+ if (length == 4) {
+ //one byte value fill missing byte
+ uint8_t data[] = { id, telemetry[2], telemetry[3], 0 };
+ ::processFlySkySensor(data, 0xAA);
+ }
+ if (length == 5) {
+ if (id == 0xFA) {
+ telemetry[1] = 0xF8; //remap to afhds3 snr
+ }
+ ::processFlySkySensor(telemetry + 1, 0xAA);
+ }
+ else if (length == 6 && id == FRM302_STATUS) {
+ //convert to ibus
+ uint16_t t = (uint16_t) (((int16_t) telemetry[3] * 10) + 400);
+ uint8_t dataTemp[] = { ++id, telemetry[2], (uint8_t) (t & 0xFF), (uint8_t) (t >> 8) };
+ ::processFlySkySensor(dataTemp, 0xAA);
+ uint8_t dataVoltage[] = { ++id, telemetry[2], telemetry[4], telemetry[5] };
+ ::processFlySkySensor(dataVoltage, 0xAA);
+ }
+ else if (length == 7) {
+ ::processFlySkySensor(telemetry + 1, 0xAC);
+ }
+ telemetry += length;
+ }
+ }
+ }
+ break;
+ case COMMAND::COMMAND_RESULT:
+ {
+ //AfhdsFrameData* respData = responseFrame->GetData();
+ //TRACE("COMMAND RESULT %02X result %d datalen %d", respData->CommandResult.command, respData->CommandResult.result, respData->CommandResult.respLen);
+ }
+ break;
+ }
+ }
+
+ if (responseFrame->frameType == FRAME_TYPE::REQUEST_GET_DATA || responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA) {
+ TRACE("Command %02X NOT IMPLEMENTED!", responseFrame->command);
+ }
+ else if (responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_ACK) {
+ //check if such request is not queued
+ if (!isEmpty()) {
+ Frame f = commandFifo[getIndex];
+ if (f.frameType == FRAME_TYPE::RESPONSE_ACK && f.frameNumber == responseFrame->frameNumber) {
+ TRACE("ACK for frame %02X already queued", responseFrame->frameNumber);
+ return;
+ }
+ }
+ TRACE("AFHDS3 [QUEUE ACK] cmd %02X type %02X number %02X", responseFrame->command, responseFrame->frameType, responseFrame->frameNumber);
+ enqueueACK((enum COMMAND) responseFrame->command, responseFrame->frameNumber);
+ }
+ else if (responseFrame->frameType == FRAME_TYPE::RESPONSE_DATA || responseFrame->frameType == FRAME_TYPE::RESPONSE_ACK) {
+ if (operationState == State::AWAITING_RESPONSE) {
+ operationState = State::IDLE;
+ }
+ }
+}
+
+inline bool isSbus(uint8_t mode)
+{
+ return (mode & 1);
+}
+
+inline bool isPWM(uint8_t mode)
+{
+ return mode < 2;
+}
+
+RUN_POWER PulsesData::getMaxRunPower()
+{
+ if (powerSource == MODULE_POWER_SOURCE::EXTERNAL) {
+ return RUN_POWER::PLUS_33dBm;
+ }
+
+ return RUN_POWER::PLUS_27dbm;
+}
+
+RUN_POWER PulsesData::actualRunPower()
+{
+ uint8_t actualRfPower = cfg.config.runPower;
+ if (getMaxRunPower() < actualRfPower) {
+ actualRfPower = getMaxRunPower();
+ }
+ return (RUN_POWER) actualRfPower;
+}
+
+RUN_POWER PulsesData::getRunPower()
+{
+ RUN_POWER targetPower = (RUN_POWER) moduleData->afhds3.runPower;
+ if (getMaxRunPower() < targetPower) {
+ targetPower = getMaxRunPower();
+ }
+ return targetPower;
+}
+
+bool PulsesData::syncSettings()
+{
+ RUN_POWER targetPower = getRunPower();
+
+ /*not sure if we need to prevent them in bind mode*/
+ if (getModuleMode(module_index) != ::ModuleSettingsMode::MODULE_MODE_BIND && targetPower != cfg.config.runPower) {
+ cfg.config.runPower = moduleData->afhds3.runPower;
+ uint8_t data[] = { 0x13, 0x20, 0x02, moduleData->afhds3.runPower, 0 };
+ TRACE("AFHDS3 SET TX POWER %d", moduleData->afhds3.runPower);
+ putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
+ return true;
+ }
+
+ //other settings only in 2 way mode (state must be synchronized)
+ if (this->state != ModuleState::STATE_SYNC_DONE) {
+ return false;
+ }
+
+ if (moduleData->afhds3.rxFreq() != cfg.config.pwmFreq) {
+ cfg.config.pwmFreq = moduleData->afhds3.rxFreq();
+ uint8_t data[] = { 0x17, 0x70, 0x02, (uint8_t) (moduleData->afhds3.rxFreq() & 0xFF), (uint8_t) (moduleData->afhds3.rxFreq() >> 8) };
+ TRACE("AFHDS3 SET RX FREQ");
+ putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
+ return true;
+ }
+ PULSE_MODE modelPulseMode = isPWM(moduleData->subType) ? PULSE_MODE::PWM_MODE : PULSE_MODE::PPM_MODE;
+ if (modelPulseMode != cfg.config.pulseMode) {
+ cfg.config.pulseMode = modelPulseMode;
+ TRACE("AFHDS3 PWM/PPM %d", modelPulseMode);
+ uint8_t data[] = { 0x16, 0x70, 0x01, (uint8_t) (modelPulseMode) };
+ putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
+ return true;
+ }
+
+ SERIAL_MODE modelSerialMode = isSbus(moduleData->subType) ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS;
+ if (modelSerialMode != cfg.config.serialMode) {
+ cfg.config.serialMode = modelSerialMode;
+ TRACE("AFHDS3 IBUS/SBUS %d", modelSerialMode);
+ uint8_t data[] = { 0x18, 0x70, 0x01, (uint8_t) (modelSerialMode) };
+ putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
+ return true;
+ }
+
+ if (moduleData->afhds3.failsafeTimeout != cfg.config.failSafeTimout) {
+ moduleData->afhds3.failsafeTimeout = cfg.config.failSafeTimout;
+ uint8_t data[] = { 0x12, 0x60, 0x02, (uint8_t) (moduleData->afhds3.failsafeTimeout & 0xFF), (uint8_t) (moduleData->afhds3.failsafeTimeout >> 8) };
+ putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
+ TRACE("AFHDS3 FAILSAFE TMEOUT, %d", moduleData->afhds3.failsafeTimeout);
+ return true;
+ }
+ return false;
+}
+
+void PulsesData::sendChannelsData()
+{
+ uint8_t channels_start = moduleData->channelsStart;
+ uint8_t channelsCount = 8 + moduleData->channelsCount;
+ uint8_t channels_last = channels_start + channelsCount;
+ int16_t buffer[MAX_CHANNELS + 1] = { ((MAX_CHANNELS << 8) | CHANNELS_DATA_MODE::CHANNELS), 0 };
+
+ for (uint8_t channel = channels_start, index = 1; channel < channels_last; channel++, index++) {
+ int16_t channelValue = convert(::getChannelValue(channel));
+ buffer[index] = channelValue;
+ }
+ putFrame(COMMAND::CHANNELS_FAILSAFE_DATA, FRAME_TYPE::REQUEST_SET_NO_RESP, (uint8_t*) buffer, sizeof(buffer));
+}
+
+void PulsesData::stop()
+{
+ TRACE("AFHDS3 STOP");
+ requestedModuleMode = MODULE_MODE_E::STANDBY;
+ putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &requestedModuleMode, 1);
+}
+
+void PulsesData::setConfigFromModel()
+{
+ cfg.config.bindPower = moduleData->afhds3.bindPower;
+ cfg.config.runPower = getRunPower();
+ cfg.config.emiStandard = EMI_STANDARD::FCC;
+ cfg.config.telemetry = moduleData->afhds3.telemetry; //always use bidirectional mode
+ cfg.config.pwmFreq = moduleData->afhds3.rxFreq();
+ cfg.config.serialMode = isSbus(moduleData->subType) ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS;
+ cfg.config.pulseMode = isPWM(moduleData->subType) ? PULSE_MODE::PWM_MODE : PULSE_MODE::PPM_MODE;
+ //use max channels - because channel count can not be changed after bind
+ cfg.config.channelCount = MAX_CHANNELS;
+ cfg.config.failSafeTimout = moduleData->afhds3.failsafeTimeout;
+ setFailSafe(cfg.config.failSafeMode);
+}
+
+inline int16_t PulsesData::convert(int channelValue)
+{
+ //pulseValue = limit(0, 988 + ((channelValue + 1024) / 2), 0xfff);
+ //988 - 750 = 238
+ //238 * 20 = 4760
+ //2250 - 2012 = 238
+ //238 * 20 = 4760
+ // 988 ---- 2012
+ //-10240 ---- 10240
+ //-1024 ---- 1024
+ return ::limit(FAILSAFE_MIN, channelValue * 10, FAILSAFE_MAX);
+}
+
+uint8_t PulsesData::setFailSafe(int16_t* target)
+{
+ int16_t pulseValue = 0;
+ uint8_t channels_start = moduleData->channelsStart;
+ uint8_t channels_last = channels_start + 8 + moduleData->channelsCount;
+
+ for (uint8_t channel = channels_start; channel < channels_last; channel++) {
+ if (moduleData->failsafeMode == FAILSAFE_CUSTOM) {
+ pulseValue = convert(g_model.failsafeChannels[channel]);
+ }
+ else if (moduleData->failsafeMode == FAILSAFE_HOLD) {
+ pulseValue = FAILSAFE_KEEP_LAST;
+ }
+ else {
+ pulseValue = convert(::getChannelValue(channel));
+ }
+ target[channel - channels_start] = pulseValue;
+ }
+ //return max channels because channel count can not be change after bind
+ return (uint8_t) (MAX_CHANNELS);
+}
+
+}
diff --git a/radio/src/pulses/afhds3.h b/radio/src/pulses/afhds3.h
new file mode 100644
index 000000000..fab057854
--- /dev/null
+++ b/radio/src/pulses/afhds3.h
@@ -0,0 +1,595 @@
+/*
+ * 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 PULSES_AFHDS3_H_
+#define PULSES_AFHDS3_H_
+
+#include "bitfield.h"
+#include "definitions.h"
+#include "dataconstants.h"
+#include "opentx_types.h"
+#include "myeeprom.h"
+#include "opentx_helpers.h"
+#include "pulses_common.h"
+#include
+#include "fifo.h"
+
+#define AFHDS_MAX_PULSES 72
+//max number of transitions measured so far 290 + 10%
+#define AFHDS_MAX_PULSES_TRANSITIONS 320
+//#define AFHDS3_SLOW
+
+#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)
+#define AFHDS3_BAUDRATE 1500000
+#define AFHDS3_COMMAND_TIMEOUT 5
+#elif !defined(AFHDS3_SLOW)
+// 1s = 1 000 000 us
+// 1000000/115200 = 8,68 us
+// actual timer is ticking in 0,5 us = 8,68*2 = 17,36 because it must be integer take 17
+// difference 1000000 / x = 8.5 --> x = 117 647 = difference = 1.2 %
+// allowed half a bit difference on the last bit -- should be fine
+#define AFHDS3_BAUDRATE 115200
+//Because timer is ticking with 0.5us
+#define BITLEN_AFHDS (17)
+
+#define AFHDS3_COMMAND_TIMEOUT 15
+#else
+// 1000000/57600 = 17,36 us
+#define AFHDS3_BAUDRATE 57600
+// 64* 86 = 11 110
+#define AFHDS3_COMMAND_TIMEOUT 20
+#define BITLEN_AFHDS (35)
+#endif
+
+#define AFHDS3_FRAME_HALF_US AFHDS3_COMMAND_TIMEOUT * 2000
+
+//get channel value outside of afhds3 namespace
+int32_t getChannelValue(uint8_t channel);
+
+//use uint16_t instead of pulse_duration_t
+namespace afhds3
+{
+enum AfhdsSpecialChars
+{
+ END = 0xC0, //Frame end
+ START = END,
+ ESC_END = 0xDC, //Escaped frame end - in case END occurs in fame then ESC ESC_END must be used
+ ESC = 0xDB, //Escaping character
+ ESC_ESC = 0xDD, //Escaping character in case ESC occurs in fame then ESC ESC_ESC must be used
+};
+
+struct Data
+{
+#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)
+ uint8_t pulses[AFHDS_MAX_PULSES];
+ uint8_t * ptr;
+#else
+ uint32_t pulsesSize;
+ uint16_t pulses[AFHDS_MAX_PULSES_TRANSITIONS];
+ uint32_t total;
+ #endif
+
+ uint8_t frame_index;
+ uint8_t crc;
+ uint8_t state;
+ uint8_t timeout;
+ uint8_t esc_state;
+
+ void reset()
+ {
+#if !(defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO))
+ total = 0;
+#endif
+ pulsesSize = 0;
+ }
+#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)
+ void sendByte(uint8_t b)
+ {
+ *ptr++ = b;
+ }
+ const uint8_t* getData()
+ {
+ return pulses;
+ }
+ void flush()
+ {
+ }
+#else
+ inline void _send_level(uint16_t v)
+ {
+ if (pulsesSize >= AFHDS_MAX_PULSES_TRANSITIONS) {
+ return;
+ }
+ pulses[pulsesSize++] = v;
+ total += v;
+ }
+ void sendByte(uint8_t b)
+ {
+ if (pulsesSize >= AFHDS_MAX_PULSES_TRANSITIONS) {
+ return;
+ }
+ //use 8n1
+ //parity: If the parity is enabled, then the MSB bit of the data to be transmitted is changed by the parity bit
+ //start is always 0
+ bool level = 0;
+ uint16_t length = BITLEN_AFHDS; //start bit
+ for (uint8_t i = 0; i <= 8; i++)
+ { //8 data bits + Stop=1
+ bool next_level = b & 1;
+ if (level == next_level) {
+ length += BITLEN_AFHDS;
+ }
+ else {
+ _send_level(length);
+ length = BITLEN_AFHDS;
+ level = next_level;
+ }
+ b = (b >> 1) | 0x80; // shift left to get next bit, fill msb with stop bit - needed just once
+ }
+ _send_level(length); //last bit (stop)
+
+ }
+ //add remaining time of frame
+ void flush()
+ {
+ uint16_t diff = AFHDS3_FRAME_HALF_US - total;
+ pulses[pulsesSize - 1] += diff;
+ //ensure 2 ms break
+ if (pulses[pulsesSize - 1] < 4000)
+ {
+ pulses[pulsesSize - 1] = 4050;
+ }
+ total += diff;
+ }
+
+ const uint16_t* getData()
+ {
+ return pulses;
+ }
+#endif
+ uint32_t getSize()
+ {
+ return pulsesSize;
+ }
+};
+
+enum DeviceAddress
+{
+ TRANSMITTER = 0x01,
+ MODULE = 0x03,
+};
+
+enum FRAME_TYPE: uint8_t
+{
+ REQUEST_GET_DATA = 0x01, //Get data response: ACK + DATA
+ REQUEST_SET_EXPECT_DATA = 0x02, //Set data response: ACK + DATA
+ REQUEST_SET_EXPECT_ACK = 0x03, //Set data response: ACK
+ REQUEST_SET_NO_RESP = 0x05, //Set data response: none
+ RESPONSE_DATA = 0x10, //Response ACK + DATA
+ RESPONSE_ACK = 0x20, //Response ACK
+ NOT_USED = 0xff
+};
+
+enum COMMAND: uint8_t
+{
+ MODULE_READY = 0x01,
+ MODULE_STATE = 0x02,
+ MODULE_MODE = 0x03,
+ MODULE_SET_CONFIG = 0x04,
+ MODULE_GET_CONFIG = 0x06,
+ CHANNELS_FAILSAFE_DATA = 0x07,
+ TELEMETRY_DATA = 0x09,
+ SEND_COMMAND = 0x0C,
+ COMMAND_RESULT = 0x0D,
+ MODULE_POWER_STATUS = 0x0F,
+ MODULE_VERSION = 0x1F,
+ VIRTUAL_FAILSAFE = 0x99, // virtual command used to trigger failsafe
+ UNDEFINED = 0xFF
+};
+
+enum COMMAND_DIRECTION
+{
+ RADIO_TO_MODULE = 0,
+ MODULE_TO_RADIO = 1
+};
+
+enum DATA_TYPE
+{
+ READY_DT, // 8 bytes 0x01 Not ready 0x02 Ready
+ STATE_DT, // See MODULE_STATE
+ MODE_DT,
+ MOD_CONFIG_DT,
+ CHANNELS_DT,
+ TELEMETRY_DT,
+ MODULE_POWER_DT,
+ MODULE_VERSION_DT,
+ EMPTY_DT,
+};
+//enum used by command response -> translate to ModuleState
+enum MODULE_READY_E
+{
+ MODULE_STATUS_UNKNOWN = 0x00,
+ MODULE_STATUS_NOT_READY = 0x01,
+ MODULE_STATUS_READY = 0x02
+};
+
+enum ModuleState
+{
+ STATE_NOT_READY = 0x00, //virtual
+ STATE_HW_ERROR = 0x01,
+ STATE_BINDING = 0x02,
+ STATE_SYNC_RUNNING = 0x03,
+ STATE_SYNC_DONE = 0x04,
+ STATE_STANDBY = 0x05,
+ STATE_UPDATING_WAIT = 0x06,
+ STATE_UPDATING_MOD = 0x07,
+ STATE_UPDATING_RX = 0x08,
+ STATE_UPDATING_RX_FAILED = 0x09,
+ STATE_RF_TESTING = 0x0a,
+ STATE_READY = 0x0b, //virtual
+ STATE_HW_TEST = 0xff,
+};
+
+//used for set command
+enum MODULE_MODE_E
+{
+ STANDBY = 0x01,
+ BIND = 0x02, //after bind module will enter run mode
+ RUN = 0x03,
+ RX_UPDATE = 0x04, //after successful update module will enter standby mode, otherwise hw error will be raised
+ MODULE_MODE_UNKNOWN = 0xFF
+};
+
+enum CMD_RESULT
+{
+ FAILURE = 0x01,
+ SUCCESS = 0x02,
+};
+
+#define MIN_FREQ 50
+#define MAX_FREQ 400
+#define MAX_CHANNELS 18
+#define FAILSAFE_KEEP_LAST 0x8000
+#define FAILSAFE_MIN -15000
+#define FAILSAFE_MAX 15000
+
+enum BIND_POWER
+{
+ MIN_16dBm = 0x00,
+ BIND_POWER_FIRST = MIN_16dBm,
+ MIN_5dBm = 0x01,
+ MIN_0dbm = 0x02,
+ PLUS_5dBm = 0x03,
+ PLUS_14dBm = 0x04,
+ BIND_POWER_LAST = PLUS_14dBm,
+};
+
+enum RUN_POWER
+{
+ PLUS_15bBm = 0x00,
+ RUN_POWER_FIRST = PLUS_15bBm,
+ PLUS_20bBm = 0x01,
+ PLUS_27dbm = 0x02,
+ PLUS_30dBm = 0x03,
+ PLUS_33dBm = 0x04,
+ RUN_POWER_LAST = PLUS_33dBm,
+};
+
+enum EMI_STANDARD
+{
+ FCC = 0x00,
+ CE = 0x01
+};
+
+enum TELEMETRY
+{
+ TELEMETRY_DISABLED = 0x00,
+ TELEMETRY_ENABLED = 0x01
+};
+
+enum PULSE_MODE
+{
+ PWM_MODE = 0x00,
+ PPM_MODE = 0x01,
+};
+
+enum SERIAL_MODE
+{
+ IBUS = 0x00,
+ SBUS_MODE = 0x02
+};
+
+PACK(struct Config_s {
+ uint8_t bindPower;
+ uint8_t runPower;
+ uint8_t emiStandard;
+ uint8_t telemetry;
+ uint16_t pwmFreq;
+ uint8_t pulseMode;
+ uint8_t serialMode;
+ uint8_t channelCount;
+ uint16_t failSafeTimout;
+ int16_t failSafeMode[MAX_CHANNELS];
+});
+
+union Config_u
+{
+ Config_s config;
+ uint8_t buffer[sizeof(Config_s)];
+};
+
+enum CHANNELS_DATA_MODE
+{
+ CHANNELS = 0x01,
+ FAIL_SAFE = 0x02,
+};
+
+PACK(struct ChannelsData {
+ uint8_t mode;
+ uint8_t channelsNumber;
+ int16_t data[MAX_CHANNELS];
+});
+
+union ChannelsData_u
+{
+ ChannelsData data;
+ uint8_t buffer[sizeof(ChannelsData)];
+};
+
+PACK(struct TelemetryData
+{
+ uint8_t sensorType;
+ uint8_t length;
+ uint8_t type;
+ uint8_t semsorID;
+ uint8_t data[8];
+});
+
+enum MODULE_POWER_SOURCE
+{
+ INTERNAL = 0x01,
+ EXTERNAL = 0x02,
+};
+
+PACK(struct ModuleVersion
+{
+ uint32_t productNumber;
+ uint32_t hardwereVersion;
+ uint32_t bootloaderVersion;
+ uint32_t firmwareVersion;
+ uint32_t rfVersion;
+});
+
+PACK(struct CommandResult_s
+{
+ uint16_t command;
+ uint8_t result;
+ uint8_t respLen;
+});
+
+union AfhdsFrameData
+{
+ uint8_t value;
+ Config_s Config;
+ ChannelsData Channels;
+ TelemetryData Telemetry;
+ ModuleVersion Version;
+ CommandResult_s CommandResult;
+};
+
+PACK(struct AfhdsFrame
+{
+ uint8_t startByte;
+ uint8_t address;
+ uint8_t frameNumber;
+ uint8_t frameType;
+ uint8_t command;
+ uint8_t value;
+
+ AfhdsFrameData* GetData()
+ {
+ return reinterpret_cast(&value);
+ }
+});
+
+#define FRM302_STATUS 0x56
+
+enum State
+{
+ UNKNOWN = 0,
+ SENDING_COMMAND,
+ AWAITING_RESPONSE,
+ IDLE
+};
+
+//one byte frames for request queue
+struct Frame
+{
+ enum COMMAND command;
+ enum FRAME_TYPE frameType;
+ uint8_t payload;
+ uint8_t frameNumber;
+ bool useFrameNumber;
+ uint8_t payloadSize;
+};
+
+//simple fifo implementation because Pulses is used as member of union and can not be non trivial type
+struct CommandFifo
+{
+ Frame commandFifo[8];
+ volatile uint32_t setIndex;
+ volatile uint32_t getIndex;
+
+ void clearCommandFifo();
+
+ inline uint32_t nextIndex(uint32_t idx)
+ {
+ return (idx + 1) & (sizeof(commandFifo) / sizeof(commandFifo[0]) - 1);
+ }
+
+ inline uint32_t prevIndex(uint32_t idx)
+ {
+ if (idx == 0)
+ {
+ return (sizeof(commandFifo) / sizeof(commandFifo[0]) - 1);
+ }
+ return (idx - 1);
+ }
+
+ inline bool isEmpty() const
+ {
+ return (getIndex == setIndex);
+ }
+
+ inline void skip()
+ {
+ getIndex = nextIndex(getIndex);
+ }
+
+ void enqueueACK(COMMAND command, uint8_t frameNumber);
+
+ void enqueue(COMMAND command, FRAME_TYPE frameType, bool useData = false, uint8_t byteContent = 0);
+
+};
+
+void processTelemetryData(uint8_t module, uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize);
+
+class PulsesData: public Data, CommandFifo
+{
+ public:
+ /**
+ * Initialize class for operation
+ * @param moduleIndex index of module one of INTERNAL_MODULE, EXTERNAL_MODULE
+ * @param resetFrameCount flag if current frame count should be reseted
+ */
+
+ void init(uint8_t moduleIndex, bool resetFrameCount = true);
+
+ /**
+ * Fills DMA buffers with frame to be send depending on actual state
+ */
+ void setupFrame();
+
+ /**
+ * Gets actual module status into provided buffer
+ * @param statusText target buffer for status
+ */
+ void getStatusString(char * statusText) const;
+
+ /**
+ * Gets actual power source and voltage
+ */
+ void getPowerStatus(char* buffer) const;
+
+ RUN_POWER actualRunPower();
+
+ /**
+ * Sends stop command to prevent any further module operations
+ */
+ void stop();
+
+ protected:
+
+ void setConfigFromModel();
+
+ private:
+
+ inline void putBytes(uint8_t* data, int length);
+
+ inline void putFrame(COMMAND command, FRAME_TYPE frameType, uint8_t* data = nullptr, uint8_t dataLength = 0, uint8_t* frame_index = nullptr);
+
+ void parseData(uint8_t* rxBuffer, uint8_t rxBufferCount);
+
+ void setState(uint8_t state);
+
+ bool syncSettings();
+
+ void requestInfoAndRun(bool send = false);
+
+ uint8_t setFailSafe(int16_t* target);
+
+ inline int16_t convert(int channelValue);
+
+ void sendChannelsData();
+
+ void clearFrameData();
+
+ void processTelemetryData(uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize);
+
+ //friendship declaration - use for passing telemetry
+ friend void processTelemetryData(uint8_t module, uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize);
+
+ /**
+ * Returns max power that currently can be set - use it to validate before synchronization of settings
+ */
+ RUN_POWER getMaxRunPower();
+
+ RUN_POWER getRunPower();
+
+ bool isConnectedUnicast();
+
+ bool isConnectedMulticast();
+
+ /**
+ * Index of the module
+ */
+ uint8_t module_index;
+ /**
+ * Target mode to be set to the module one of MODULE_MODE_E
+ */
+ uint8_t requestedModuleMode;
+ /**
+ * Internal operation state one of UNKNOWN, SENDING_COMMAND, AWAITING_RESPONSE, IDLE
+ * Used to avoid sending commands when not allowed to
+ */
+ State operationState;
+ /**
+ * Actual repeat count for requested command/operation - incremented by every attempt sending anything
+ */
+ uint16_t repeatCount;
+ /**
+ * Command count used for counting actual number of commands sent in run mode
+ */
+ uint32_t cmdCount;
+ /**
+ * Command index of command to be send when cmdCount reached necessary value
+ */
+ uint32_t cmdIndex;
+ /**
+ * Actual power source of the module - should be requested time to time
+ * Currently requested once
+ */
+ enum MODULE_POWER_SOURCE powerSource;
+ /**
+ * Pointer to module config - it is making operations easier and faster
+ */
+ ModuleData* moduleData;
+ /**
+ * Actual module configuration - must be requested from module
+ */
+ Config_u cfg;
+
+ /**
+ * Actual module version - must be requested from module
+ */
+ ModuleVersion version;
+};
+} /* Namespace ahfds3 */
+#endif /* PULSES_AFHDS3_H_ */
diff --git a/radio/src/pulses/modules_constants.h b/radio/src/pulses/modules_constants.h
index ec0f8f819..4f391243a 100644
--- a/radio/src/pulses/modules_constants.h
+++ b/radio/src/pulses/modules_constants.h
@@ -37,6 +37,7 @@ enum ModuleType {
MODULE_TYPE_R9M_LITE_PRO_PXX2,
MODULE_TYPE_SBUS,
MODULE_TYPE_XJT_LITE_PXX2,
+ MODULE_TYPE_AFHDS3, //no more protocols possible because of 4 bits value
MODULE_TYPE_COUNT,
MODULE_TYPE_MAX = MODULE_TYPE_COUNT - 1
};
@@ -102,62 +103,76 @@ enum ModuleSubtypeR9M {
enum ModuleSubtypeMulti {
MODULE_SUBTYPE_MULTI_FIRST = 0,
MODULE_SUBTYPE_MULTI_FLYSKY = MODULE_SUBTYPE_MULTI_FIRST,
- MODULE_SUBTYPE_MULTI_HUBSAN,
- MODULE_SUBTYPE_MULTI_FRSKY,
- MODULE_SUBTYPE_MULTI_HISKY,
- MODULE_SUBTYPE_MULTI_V2X2,
- MODULE_SUBTYPE_MULTI_DSM2,
+ MODULE_SUBTYPE_MULTI_HUBSAN, //1
+ MODULE_SUBTYPE_MULTI_FRSKY, //2
+ MODULE_SUBTYPE_MULTI_HISKY, //3
+ MODULE_SUBTYPE_MULTI_V2X2, //4
+ MODULE_SUBTYPE_MULTI_DSM2, //5
MODULE_SUBTYPE_MULTI_DEVO,
MODULE_SUBTYPE_MULTI_YD717,
MODULE_SUBTYPE_MULTI_KN,
MODULE_SUBTYPE_MULTI_SYMAX,
- MODULE_SUBTYPE_MULTI_SLT,
+ MODULE_SUBTYPE_MULTI_SLT, //10
MODULE_SUBTYPE_MULTI_CX10,
MODULE_SUBTYPE_MULTI_CG023,
MODULE_SUBTYPE_MULTI_BAYANG,
MODULE_SUBTYPE_MULTI_ESky,
- MODULE_SUBTYPE_MULTI_MT99XX,
+ MODULE_SUBTYPE_MULTI_MT99XX, //15
MODULE_SUBTYPE_MULTI_MJXQ,
MODULE_SUBTYPE_MULTI_SHENQI,
MODULE_SUBTYPE_MULTI_FY326,
MODULE_SUBTYPE_MULTI_SFHSS,
- MODULE_SUBTYPE_MULTI_J6PRO,
+ MODULE_SUBTYPE_MULTI_J6PRO, //20
MODULE_SUBTYPE_MULTI_FQ777,
MODULE_SUBTYPE_MULTI_ASSAN,
MODULE_SUBTYPE_MULTI_HONTAI,
MODULE_SUBTYPE_MULTI_OLRS,
- MODULE_SUBTYPE_MULTI_FS_AFHDS2A,
+ MODULE_SUBTYPE_MULTI_FS_AFHDS2A, //25
MODULE_SUBTYPE_MULTI_Q2X2,
MODULE_SUBTYPE_MULTI_WK_2X01,
MODULE_SUBTYPE_MULTI_Q303,
MODULE_SUBTYPE_MULTI_GW008,
- MODULE_SUBTYPE_MULTI_DM002,
+ MODULE_SUBTYPE_MULTI_DM002, //30
MODULE_SUBTYPE_MULTI_CABELL,
MODULE_SUBTYPE_MULTI_ESKY150,
MODULE_SUBTYPE_MULTI_H83D,
MODULE_SUBTYPE_MULTI_CORONA,
- MODULE_SUBTYPE_MULTI_CFLIE,
+ MODULE_SUBTYPE_MULTI_CFLIE, //35
MODULE_SUBTYPE_MULTI_HITEC,
MODULE_SUBTYPE_MULTI_WFLY,
MODULE_SUBTYPE_MULTI_BUGS,
MODULE_SUBTYPE_MULTI_BUGS_MINI,
- MODULE_SUBTYPE_MULTI_TRAXXAS,
+ MODULE_SUBTYPE_MULTI_TRAXXAS, //40
MODULE_SUBTYPE_MULTI_NCC1701,
MODULE_SUBTYPE_MULTI_E01X,
MODULE_SUBTYPE_MULTI_V911S,
MODULE_SUBTYPE_MULTI_GD00X,
- MODULE_SUBTYPE_MULTI_V761,
+ MODULE_SUBTYPE_MULTI_V761, //45
MODULE_SUBTYPE_MULTI_KF606,
MODULE_SUBTYPE_MULTI_REDPINE,
MODULE_SUBTYPE_MULTI_POTENSIC,
MODULE_SUBTYPE_MULTI_ZSX,
- MODULE_SUBTYPE_MULTI_FLYZONE,
+ MODULE_SUBTYPE_MULTI_FLYZONE, //50
MODULE_SUBTYPE_MULTI_SCANNER,
MODULE_SUBTYPE_MULTI_FRSKYX_RX,
MODULE_SUBTYPE_MULTI_AFHDS2A_RX,
MODULE_SUBTYPE_MULTI_HOTT,
- MODULE_SUBTYPE_MULTI_FX816,
- MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_FX816
+ MODULE_SUBTYPE_MULTI_FX816, //55
+ MODULE_SUBTYPE_MULTI_BAYANG_RX,
+ MODULE_SUBTYPE_MULTI_PELIKAN,
+ MODULE_SUBTYPE_MULTI_TIGER,
+ MODULE_SUBTYPE_MULTI_XK,
+ MODULE_SUBTYPE_MULTI_XN297DUMP, //60
+ MODULE_SUBTYPE_MULTI_FRSKYX2,
+ MODULE_SUBTYPE_MULTI_FRSKY_R9,
+ MODULE_SUBTYPE_MULTI_PROPEL,
+ MODULE_SUBTYPE_MULTI_FRSKYL,
+ MODULE_SUBTYPE_MULTI_SKYARTEC, //65
+ MODULE_SUBTYPE_MULTI_ESKY150V2,
+ MODULE_SUBTYPE_MULTI_DSM_RX,
+ MODULE_SUBTYPE_MULTI_JJRC345,
+ MODULE_SUBTYPE_MULTI_Q90C,
+ MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_Q90C
};
#define MODULE_SUBTYPE_MULTI_XN297DP 63-3
@@ -175,7 +190,9 @@ enum MMRFrskySubtypes {
MM_RF_FRSKY_SUBTYPE_D16_8CH,
MM_RF_FRSKY_SUBTYPE_V8,
MM_RF_FRSKY_SUBTYPE_D16_LBT,
- MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH
+ MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH,
+ MM_RF_FRSKY_SUBTYPE_D8_CLONED,
+ MM_RF_FRSKY_SUBTYPE_D16_CLONED
};
enum ModuleSubtypeDSM2 {
@@ -202,4 +219,13 @@ enum AntennaModes {
ANTENNA_MODE_LAST = ANTENNA_MODE_EXTERNAL
};
+enum AfhdsModes {
+ AFHDS_SUBTYPE_FIRST,
+ AFHDS_SUBTYPE_PWM_IBUS = AFHDS_SUBTYPE_FIRST,
+ AFHDS_SUBTYPE_PWM_SBUS,
+ AFHDS_SUBTYPE_PPM_IBUS,
+ AFHDS_SUBTYPE_PPM_SBUS,
+ AFHDS_SUBTYPE_LAST = AFHDS_SUBTYPE_PPM_SBUS
+};
+
#endif // _MODULES_CONSTANTS_H_
diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h
index 2c9a64e94..e13eaf2fb 100644
--- a/radio/src/pulses/modules_helpers.h
+++ b/radio/src/pulses/modules_helpers.h
@@ -25,6 +25,9 @@
#include "definitions.h"
#include "opentx_helpers.h"
#include "telemetry/telemetry.h"
+#include "storage/storage.h"
+#include "globals.h"
+
#if defined(MULTIMODULE)
#include "telemetry/multi.h"
#endif
@@ -55,7 +58,7 @@ inline uint8_t getMaxMultiSubtype(uint8_t moduleIdx)
const mm_protocol_definition *pdef = getMultiProtocolDefinition(g_model.moduleData[moduleIdx].getMultiProtocol());
if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY) {
- return 5;
+ return 7;
}
if (g_model.moduleData[moduleIdx].getMultiProtocol() > MODULE_SUBTYPE_MULTI_LAST) {
@@ -127,7 +130,7 @@ inline bool isModuleISRMD16(uint8_t idx)
inline bool isModuleD16(uint8_t idx)
{
- return isModuleXJTD16(idx) || isModuleISRMD16(idx);
+ return isModuleXJTD16(idx) || isModuleISRMD16(idx) || IS_D16_MULTI(idx);
}
inline bool isModuleISRMAccess(uint8_t idx)
@@ -296,8 +299,32 @@ inline bool isModuleSBUS(uint8_t moduleIdx)
return g_model.moduleData[moduleIdx].type == MODULE_TYPE_SBUS;
}
+inline bool isModuleAFHDS3(uint8_t idx)
+{
+ return g_model.moduleData[idx].type == MODULE_TYPE_AFHDS3;
+}
+
+inline bool isModulePxx2(uint8_t idx)
+{
+ if (idx != EXTERNAL_MODULE)
+ return false;
+#if defined(PXX2)
+ #if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
+ if (g_model.moduleData[idx].type == MODULE_TYPE_XJT_LITE_PXX2 ||
+ g_model.moduleData[idx].type == MODULE_TYPE_R9M_LITE_PRO_PXX2)
+ return true;
+ #endif
+ #if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
+ if (g_model.moduleData[idx].type == MODULE_TYPE_R9M_LITE_PXX2)
+ return true;
+ #endif
+#endif
+ return false;
+}
+
// order is the same as in enum Protocols in myeeprom.h (none, ppm, pxx, pxx2, dsm, crossfire, multi, r9m, r9m2, sbus)
-static const int8_t maxChannelsModules[] = { 0, 8, 8, 16, -2, 8, 4, 8, 16, 8}; // relative to 8!
+//qba667 count is not matching!
+static const int8_t maxChannelsModules[] = { 0, 8, 8, 16, -2, 8, 4, 8, 16, 8, 10}; // relative to 8!
static const int8_t maxChannelsXJT[] = { 0, 8, 0, 4 }; // relative to 8!
constexpr int8_t MAX_TRAINER_CHANNELS_M8 = MAX_TRAINER_CHANNELS - 8;
@@ -322,6 +349,9 @@ inline int8_t maxModuleChannels_M8(uint8_t moduleIdx)
return 8; // always 16 channels in FCC / FLEX
}
}
+ else if (isModuleAFHDS3(moduleIdx)) {
+ return 10;
+ }
else {
return maxChannelsModules[g_model.moduleData[moduleIdx].type];
}
@@ -345,6 +375,11 @@ inline int8_t defaultModuleChannels_M8(uint8_t idx)
return maxModuleChannels_M8(idx);
}
+inline uint8_t sentModulePXXChannels(uint8_t idx)
+{
+ return 8 + g_model.moduleData[idx].channelsCount;
+}
+
inline int8_t sentModuleChannels(uint8_t idx)
{
if (isModuleCrossfire(idx))
@@ -354,7 +389,7 @@ inline int8_t sentModuleChannels(uint8_t idx)
else if (isModuleSBUS(idx))
return 16;
else
- return 8 + g_model.moduleData[idx].channelsCount;
+ return sentModulePXXChannels(idx);
}
inline bool isDefaultModelRegistrationID()
@@ -393,7 +428,7 @@ inline bool isModuleFailsafeAvailable(uint8_t moduleIdx)
return g_model.moduleData[moduleIdx].subType == MODULE_SUBTYPE_PXX1_ACCST_D16;
#if defined(MULTIMODULE)
- if (isModuleMultimodule(moduleIdx)){
+ if (isModuleMultimodule(moduleIdx)) {
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
if (status.isValid()) {
return status.supportsFailsafe();
@@ -405,6 +440,11 @@ inline bool isModuleFailsafeAvailable(uint8_t moduleIdx)
}
#endif
+#if defined(AFHDS3)
+ if (isModuleAFHDS3(moduleIdx))
+ return true;
+#endif
+
if (isModuleR9M(moduleIdx))
return true;
@@ -413,17 +453,23 @@ inline bool isModuleFailsafeAvailable(uint8_t moduleIdx)
inline bool isModuleBindRangeAvailable(uint8_t moduleIdx)
{
- return isModulePXX2(moduleIdx) || isModulePXX1(moduleIdx) || isModuleDSM2(moduleIdx) || isModuleMultimodule(moduleIdx);
+ return isModulePXX2(moduleIdx) || isModulePXX1(moduleIdx) || isModuleDSM2(moduleIdx) || isModuleMultimodule(moduleIdx) || isModuleAFHDS3(moduleIdx);
}
+inline bool isModuleRangeAvailable(uint8_t moduleIdx)
+{
+ return isModuleBindRangeAvailable(moduleIdx) && !IS_RX_MULTI(moduleIdx);
+}
+
+constexpr uint8_t MAX_RXNUM = 63;
+
inline uint8_t getMaxRxNum(uint8_t idx)
{
if (isModuleDSM2(idx))
return 20;
#if defined(MULTIMODULE)
- if (isModuleMultimodule(idx))
- {
+ if (isModuleMultimodule(idx)) {
switch (g_model.moduleData[idx].getMultiProtocol()) {
case MODULE_SUBTYPE_MULTI_OLRS:
return 4;
@@ -434,7 +480,7 @@ inline uint8_t getMaxRxNum(uint8_t idx)
}
#endif
- return 63;
+ return MAX_RXNUM;
}
inline const char * getModuleDelay(uint8_t idx)
@@ -469,7 +515,7 @@ inline bool isTelemAllowedOnBind(uint8_t moduleIndex)
{
#if defined(HARDWARE_INTERNAL_MODULE)
if (moduleIndex == INTERNAL_MODULE)
- return isModuleISRM(moduleIndex) || isSportLineUsedByInternalModule();
+ return true;
if (isSportLineUsedByInternalModule())
return false;
@@ -526,6 +572,38 @@ inline void setDefaultPpmFrameLength(uint8_t moduleIdx)
g_model.moduleData[moduleIdx].ppm.frameLength = 4 * max(0, g_model.moduleData[moduleIdx].channelsCount);
}
+inline void resetAccessAuthenticationCount()
+{
+#if defined(ACCESS_LIB)
+ // the module will reset on mode switch, we need to reset the authentication counter
+ globalData.authenticationCount = 0;
+#endif
+}
+
+inline void resetAfhds3Options(uint8_t moduleIdx)
+{
+ auto & data = g_model.moduleData[moduleIdx];
+ data.rfProtocol = 0;
+ data.subType = 0;
+#if defined(AFHDS3)
+ data.afhds3.bindPower = 0;
+ data.afhds3.runPower = 0;
+ data.afhds3.emi = 0;
+ data.afhds3.telemetry = 1;
+ data.afhds3.rx_freq[0] = 50;
+ data.afhds3.rx_freq[1] = 0;
+ data.afhds3.failsafeTimeout = 1000;
+ data.channelsCount = 14 - 8;
+ data.failsafeMode = 1;
+ //" PWM+i"" PWM+s"" PPM+i"" PPM+s"
+ data.subType = 0;
+ for (uint8_t channel = 0; channel < MAX_OUTPUT_CHANNELS; channel++) {
+ g_model.failsafeChannels[channel] = 0;
+ }
+#endif
+}
+
+
inline void setModuleType(uint8_t moduleIdx, uint8_t moduleType)
{
ModuleData & moduleData = g_model.moduleData[moduleIdx];
@@ -536,6 +614,10 @@ inline void setModuleType(uint8_t moduleIdx, uint8_t moduleType)
moduleData.sbus.refreshRate = -31;
else if (moduleData.type == MODULE_TYPE_PPM)
setDefaultPpmFrameLength(moduleIdx);
+ else if (moduleData.type == MODULE_TYPE_AFHDS3)
+ resetAfhds3Options(moduleIdx);
+ else
+ resetAccessAuthenticationCount();
}
extern bool isExternalAntennaEnabled();
@@ -557,6 +639,8 @@ inline void resetMultiProtocolsOptions(uint8_t moduleIdx)
g_model.moduleData[moduleIdx].multi.disableTelemetry = 0;
g_model.moduleData[moduleIdx].multi.disableMapping = 0;
g_model.moduleData[moduleIdx].multi.lowPowerMode = 0;
+ g_model.moduleData[moduleIdx].failsafeMode = FAILSAFE_NOT_SET;
+ g_model.header.modelId[moduleIdx] = 0;
}
inline void getMultiOptionValues(int8_t multi_proto, int8_t & min, int8_t & max)
@@ -582,6 +666,10 @@ inline void getMultiOptionValues(int8_t multi_proto, int8_t & min, int8_t & max)
min = -1;
max = 84;
break;
+ case MODULE_SUBTYPE_MULTI_FRSKY_R9:
+ min = 0; // 10mW
+ max = 5; // 300mW
+ break;
default:
min = -128;
max = 127;
diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp
index b49c61b7d..c8170f217 100644
--- a/radio/src/pulses/multi.cpp
+++ b/radio/src/pulses/multi.cpp
@@ -38,6 +38,7 @@
static void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe);
void sendChannels(uint8_t moduleIdx);
+static void sendD16BindOption(uint8_t moduleIdx);
#if defined(LUA)
static void sendSport(uint8_t moduleIdx);
static void sendHott(uint8_t moduleIdx);
@@ -174,10 +175,13 @@ void setupPulsesMulti(uint8_t moduleIdx)
| g_model.moduleData[moduleIdx].multi.disableMapping));
// Multi V1.3.X.X -> Send protocol additional data: max 9 bytes
-#if defined(LUA)
if (getMultiModuleStatus(moduleIdx).isValid()) {
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
if (status.minor >= 3 && !(status.flags & 0x80)) { //Version 1.3.x.x or more and Buffer not full
+ if ((IS_D16_MULTI(moduleIdx) || IS_R9_MULTI(moduleIdx)) && moduleState[moduleIdx].mode == MODULE_MODE_BIND) {
+ sendD16BindOption(moduleIdx);//1 byte of additional data
+ }
+#if defined(LUA)
// SPort send
if (IS_D16_MULTI(moduleIdx) && outputTelemetryBuffer.destination == TELEMETRY_ENDPOINT_SPORT && outputTelemetryBuffer.size) {
sendSport(moduleIdx); //8 bytes of additional data
@@ -185,9 +189,9 @@ void setupPulsesMulti(uint8_t moduleIdx)
else if (IS_HOTT_MULTI(moduleIdx)) {
sendHott(moduleIdx); //1 byte of additional data
}
+#endif
}
}
- #endif
}
void setupPulsesMultiExternalModule()
@@ -240,6 +244,50 @@ void sendChannels(uint8_t moduleIdx)
}
}
+void convertOtxProtocolToMulti(int *protocol, int *subprotocol)
+{
+ // Special treatment for the FrSky entry...
+ if (*protocol == MODULE_SUBTYPE_MULTI_FRSKY +1) {
+ if (*subprotocol == MM_RF_FRSKY_SUBTYPE_D8) {
+ //D8
+ *protocol = 3;
+ *subprotocol = 0;
+ }
+ else if (*subprotocol == MM_RF_FRSKY_SUBTYPE_D8_CLONED) {
+ //D8
+ *protocol = 3;
+ *subprotocol = 1;
+ }
+ else if (*subprotocol == MM_RF_FRSKY_SUBTYPE_V8) {
+ //V8
+ *protocol = 25;
+ *subprotocol = 0;
+ }
+ else {
+ *protocol = 15;
+ if (*subprotocol == MM_RF_FRSKY_SUBTYPE_D16_8CH)
+ *subprotocol = 1;
+ else if (*subprotocol == MM_RF_FRSKY_SUBTYPE_D16)
+ *subprotocol = 0; // D16
+ else if (*subprotocol == MM_RF_FRSKY_SUBTYPE_D16_LBT)
+ *subprotocol = 2;
+ else if (*subprotocol == MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH)
+ *subprotocol = 3;
+ else
+ *subprotocol = 4; // D16_CLONED
+ }
+ }
+ else {
+ // 15 for Multimodule is FrskyX or D16 which we map as a protocol of 3 (FrSky)
+ // all protos > frskyx are therefore also off by one
+ if (*protocol >= 15)
+ *protocol = *protocol + 1;
+ // 25 is again a FrSky *protocol (FrskyV) so shift again
+ if (*protocol >= 25)
+ *protocol = *protocol + 1;
+ }
+}
+
void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe)
{// byte 1+2, protocol information
@@ -264,50 +312,20 @@ void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe)
protoByte |= MULTI_SEND_RANGECHECK;
// rfProtocol
- if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) {
-
- // Autobinding should always be done in DSMX 11ms
- if (g_model.moduleData[moduleIdx].multi.autoBindMode && moduleState[moduleIdx].mode == MODULE_MODE_BIND)
- subtype = MM_RF_DSM2_SUBTYPE_AUTO;
-
- // Multi module in DSM mode wants the number of channels to be used as option value
- if (optionValue)
- optionValue = 0x80 | sentModuleChannels(moduleIdx); // Max throw
+ if (type == MODULE_SUBTYPE_MULTI_DSM2 +1 ) {
+ // Multi module in DSM mode wants the number of channels to be used as option value along with other flags
+ if (optionValue & 0x01)
+ optionValue = 0x80; // Max throw
else
- optionValue = sentModuleChannels(moduleIdx);
-}
-
- // 15 for Multimodule is FrskyX or D16 which we map as a subprotocol of 3 (FrSky)
- // all protos > frskyx are therefore also off by one
- if (type >= 15)
- type = type + 1;
-
- // 25 is again a FrSky protocol (FrskyV) so shift again
- if (type >= 25)
- type = type + 1;
-
- if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY) {
- if (subtype == MM_RF_FRSKY_SUBTYPE_D8) {
- //D8
- type = 3;
- subtype = 0;
- } else if (subtype == MM_RF_FRSKY_SUBTYPE_V8) {
- //V8
- type = 25;
- subtype = 0;
- } else {
- type = 15;
- if (subtype == MM_RF_FRSKY_SUBTYPE_D16_8CH) // D16 8ch
- subtype = 1;
- else if (subtype == MM_RF_FRSKY_SUBTYPE_D16)
- subtype = 0; // D16
- else if (subtype == MM_RF_FRSKY_SUBTYPE_D16_LBT)
- subtype = 2;
- else
- subtype = 3; // MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH
- }
+ optionValue = 0x00;
+ if (g_model.moduleData[moduleIdx].multi.optionValue & 0x02)
+ optionValue |= 0x40; // 11ms servo refresh
+ optionValue |= sentModuleChannels(moduleIdx); //add number of channels
}
+ // Special treatment for the FrSky entry...
+ convertOtxProtocolToMulti(&type, &subtype);
+
// Set the highest bit of option byte in AFHDS2A protocol to instruct MULTI to passthrough telemetry bytes instead
// of sending Frsky D telemetry
if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FS_AFHDS2A)
@@ -317,7 +335,6 @@ void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe)
if (g_model.moduleData[moduleIdx].getMultiProtocol() == MM_RF_CUSTOM_SELECTED)
type = g_model.moduleData[moduleIdx].getMultiProtocol();
-
uint8_t headerByte = 0x55;
// header, byte 0, 0x55 for proto 0-31, 0x54 for proto 32-63
if (type & 0x20)
@@ -345,6 +362,13 @@ void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe)
sendMulti(moduleIdx, (uint8_t) optionValue);
}
+void sendD16BindOption(uint8_t moduleIdx)
+{
+ uint8_t bind_opt = g_model.moduleData[moduleIdx].multi.receiverTelemetryOff ? 1 : 0;
+ bind_opt |= g_model.moduleData[moduleIdx].multi.receiverHigherChannels ? 2 : 0;
+ sendMulti(moduleIdx, bind_opt);
+}
+
#if defined(LUA)
void sendSport(uint8_t moduleIdx)
{
@@ -367,7 +391,7 @@ void sendSport(uint8_t moduleIdx)
void sendHott(uint8_t moduleIdx)
{
- if (Multi_Buffer && memcmp(Multi_Buffer, "HoTT", 4) == 0 && Multi_Buffer[5] >= 0xD7 && Multi_Buffer[5] <= 0xDF) {
+ if (Multi_Buffer && memcmp(Multi_Buffer, "HoTT", 4) == 0 && (Multi_Buffer[5] & 0x80) && (Multi_Buffer[5] & 0x0F) >= 0x07) {
// HoTT Lua script is running
sendMulti(moduleIdx, Multi_Buffer[5]);
}
diff --git a/radio/src/pulses/multi.h b/radio/src/pulses/multi.h
index a19e526eb..29e335d3a 100644
--- a/radio/src/pulses/multi.h
+++ b/radio/src/pulses/multi.h
@@ -24,6 +24,7 @@
#include "pulses_common.h"
void multiPatchCustom(uint8_t moduleIdx);
+void convertOtxProtocolToMulti(int *protocol, int *subprotocol);
class UartMultiPulses: public DataBuffer
{
diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp
index 21c4d7eee..f669f5fdb 100755
--- a/radio/src/pulses/pulses.cpp
+++ b/radio/src/pulses/pulses.cpp
@@ -28,6 +28,7 @@ InternalModulePulsesData intmodulePulsesData __DMA;
ExternalModulePulsesData extmodulePulsesData __DMA;
TrainerPulsesData trainerPulsesData __DMA;
+//use only for PXX
void ModuleState::startBind(BindInformation * destination, ModuleCallback bindCallback)
{
bindInformation = destination;
@@ -40,6 +41,56 @@ void ModuleState::startBind(BindInformation * destination, ModuleCallback bindCa
#endif
}
+void getModuleStatusString(uint8_t moduleIdx, char * statusText)
+{
+ *statusText = 0;
+#if defined(MULTIMODULE)
+ if (isModuleMultimodule(moduleIdx)) {
+ //change it
+ getMultiModuleStatus(moduleIdx).getStatusString(statusText);
+ }
+#endif
+#if defined(AFHDS3)
+ if (moduleIdx == EXTERNAL_MODULE && isModuleAFHDS3(moduleIdx)) {
+ extmodulePulsesData.afhds3.getStatusString(statusText);
+ }
+#endif
+}
+
+void getModuleSyncStatusString(uint8_t moduleIdx, char * statusText)
+{
+ *statusText = 0;
+#if defined(MULTIMODULE)
+ if (isModuleMultimodule(moduleIdx)) {
+ getMultiSyncStatus(moduleIdx).getRefreshString(statusText);
+ }
+#endif
+#if defined(AFHDS3)
+ if (moduleIdx == EXTERNAL_MODULE && isModuleAFHDS3(moduleIdx)) {
+ extmodulePulsesData.afhds3.getPowerStatus(statusText);
+ }
+#endif
+}
+
+#if defined(AFHDS3)
+uint8_t actualAfhdsRunPower(int moduleIndex)
+{
+ if (moduleIndex == EXTERNAL_MODULE && isModuleAFHDS3(moduleIndex)) {
+ return (uint8_t)extmodulePulsesData.afhds3.actualRunPower();
+ }
+ return 0;
+}
+#endif
+
+ModuleSettingsMode getModuleMode(int moduleIndex)
+{
+ return (ModuleSettingsMode)moduleState[moduleIndex].mode;
+}
+void setModuleMode(int moduleIndex, ModuleSettingsMode mode)
+{
+ moduleState[moduleIndex].mode = mode;
+}
+
uint8_t getModuleType(uint8_t module)
{
uint8_t type = g_model.moduleData[module].type;
@@ -136,6 +187,12 @@ uint8_t getRequiredProtocol(uint8_t module)
break;
#endif
+#if defined(AFHDS3)
+ case MODULE_TYPE_AFHDS3:
+ protocol = PROTOCOL_CHANNELS_AFHDS3;
+ break;
+#endif
+
default:
protocol = PROTOCOL_CHANNELS_NONE;
break;
@@ -214,26 +271,34 @@ void enablePulsesExternalModule(uint8_t protocol)
break;
#endif
+#if defined(AFHDS3)
+ case PROTOCOL_CHANNELS_AFHDS3:
+ extmodulePulsesData.afhds3.init(EXTERNAL_MODULE);
+ extmoduleSerialStart(AFHDS3_BAUDRATE, AFHDS3_COMMAND_TIMEOUT * 2000, false);
+ break;
+#endif
+
+
default:
break;
}
}
-void setupPulsesExternalModule(uint8_t protocol)
+bool setupPulsesExternalModule(uint8_t protocol)
{
switch (protocol) {
#if defined(PXX1)
case PROTOCOL_CHANNELS_PXX1_PULSES:
extmodulePulsesData.pxx.setupFrame(EXTERNAL_MODULE);
scheduleNextMixerCalculation(EXTERNAL_MODULE, PXX_PULSES_PERIOD);
- break;
+ return true;
#endif
#if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
extmodulePulsesData.pxx_uart.setupFrame(EXTERNAL_MODULE);
scheduleNextMixerCalculation(EXTERNAL_MODULE, EXTMODULE_PXX1_SERIAL_PERIOD);
- break;
+ return true;
#endif
#if defined(PXX2)
@@ -241,14 +306,14 @@ void setupPulsesExternalModule(uint8_t protocol)
case PROTOCOL_CHANNELS_PXX2_LOWSPEED:
extmodulePulsesData.pxx2.setupFrame(EXTERNAL_MODULE);
scheduleNextMixerCalculation(EXTERNAL_MODULE, PXX2_PERIOD);
- break;
+ return true;
#endif
#if defined(SBUS)
case PROTOCOL_CHANNELS_SBUS:
setupPulsesSbus();
scheduleNextMixerCalculation(EXTERNAL_MODULE, SBUS_PERIOD);
- break;
+ return true;
#endif
#if defined(DSM2)
@@ -257,32 +322,40 @@ void setupPulsesExternalModule(uint8_t protocol)
case PROTOCOL_CHANNELS_DSM2_DSMX:
setupPulsesDSM2();
scheduleNextMixerCalculation(EXTERNAL_MODULE, DSM2_PERIOD);
- break;
+ return true;
#endif
#if defined(CROSSFIRE)
case PROTOCOL_CHANNELS_CROSSFIRE:
setupPulsesCrossfire();
scheduleNextMixerCalculation(EXTERNAL_MODULE, CROSSFIRE_PERIOD);
- break;
+ return true;
#endif
#if defined(MULTIMODULE)
case PROTOCOL_CHANNELS_MULTIMODULE:
setupPulsesMultiExternalModule();
scheduleNextMixerCalculation(EXTERNAL_MODULE, MULTIMODULE_PERIOD);
- break;
+ return true;
#endif
#if defined(PPM)
case PROTOCOL_CHANNELS_PPM:
setupPulsesPPMExternalModule();
scheduleNextMixerCalculation(EXTERNAL_MODULE, PPM_PERIOD(EXTERNAL_MODULE));
- break;
+ return true;
+#endif
+
+#if defined(AFHDS3)
+ case PROTOCOL_CHANNELS_AFHDS3:
+ extmodulePulsesData.afhds3.setupFrame();
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, AFHDS3_COMMAND_TIMEOUT);
+ return true;
#endif
default:
- break;
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, 50/*ms*/);
+ return false;
}
}
@@ -307,9 +380,7 @@ static void enablePulsesInternalModule(uint8_t protocol)
#if defined(PXX2)
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
intmoduleSerialStart(PXX2_HIGHSPEED_BAUDRATE, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b);
-#if defined(HARDWARE_INTERNAL_MODULE) && defined(INTERNAL_MODULE_PXX2) && defined(ACCESS_LIB)
- globalData.authenticationCount = 0;
-#endif
+ resetAccessAuthenticationCount();
break;
#endif
@@ -320,6 +391,13 @@ static void enablePulsesInternalModule(uint8_t protocol)
intmoduleTimerStart(MULTIMODULE_PERIOD);
break;
#endif
+
+#if defined(INTERNAL_MODULE_PPM)
+ case PROTOCOL_CHANNELS_PPM:
+ intmodulePpmStart();
+ break;
+#endif
+
default:
break;
}
@@ -338,7 +416,9 @@ bool setupPulsesInternalModule(uint8_t protocol)
#if defined(PXX1) && defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
intmodulePulsesData.pxx_uart.setupFrame(INTERNAL_MODULE);
-#if !defined(INTMODULE_HEARTBEAT)
+#if defined(INTMODULE_HEARTBEAT)
+ scheduleNextMixerCalculation(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD + 1 /* backup */);
+#else
scheduleNextMixerCalculation(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
#endif
return true;
@@ -351,11 +431,13 @@ bool setupPulsesInternalModule(uint8_t protocol)
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER || moduleState[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER) {
scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_TOOLS_PERIOD);
}
-#if !defined(INTMODULE_HEARTBEAT)
else {
+#if defined(INTMODULE_HEARTBEAT)
+ scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD + 1 /* backup */);
+#else
scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD);
- }
#endif
+ }
return result;
}
#endif
@@ -375,7 +457,8 @@ bool setupPulsesInternalModule(uint8_t protocol)
#endif
default:
- return true;
+ scheduleNextMixerCalculation(INTERNAL_MODULE, 10 /*ms*/); // used for USB sim for example
+ return false;
}
}
@@ -410,8 +493,7 @@ bool setupPulsesExternalModule()
return false;
}
else {
- setupPulsesExternalModule(protocol);
- return true;
+ return setupPulsesExternalModule(protocol);
}
}
@@ -428,3 +510,8 @@ void setCustomFailsafe(uint8_t moduleIndex)
}
}
}
+
+int32_t getChannelValue(uint8_t channel) {
+ return channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
+}
+
diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h
index 7d859c075..f92629f6e 100644
--- a/radio/src/pulses/pulses.h
+++ b/radio/src/pulses/pulses.h
@@ -27,6 +27,7 @@
#include "pxx1.h"
#include "pxx2.h"
#include "multi.h"
+#include "afhds3.h"
#include "modules_helpers.h"
#include "ff.h"
@@ -56,29 +57,14 @@
#define IS_MULTIMODULE_PROTOCOL(protocol) (0)
#endif
-#define IS_SBUS_PROTOCOL(protocol) (protocol == PROTOCOL_CHANNELS_SBUS)
+#if defined(AFHDS3)
+#define IS_AFHDS3_PROTOCOL(protocol) (protocol == PROTOCOL_CHANNELS_AFHDS3)
+#else
+#define IS_AFHDS3_PROTOCOL(protocol) (0)
+#endif
extern uint8_t s_pulses_paused;
-enum ModuleSettingsMode
-{
- MODULE_MODE_NORMAL,
- MODULE_MODE_SPECTRUM_ANALYSER,
- MODULE_MODE_POWER_METER,
- MODULE_MODE_GET_HARDWARE_INFO,
- MODULE_MODE_MODULE_SETTINGS,
- MODULE_MODE_RECEIVER_SETTINGS,
- MODULE_MODE_BEEP_FIRST,
- MODULE_MODE_REGISTER = MODULE_MODE_BEEP_FIRST,
- MODULE_MODE_BIND,
- MODULE_MODE_SHARE,
- MODULE_MODE_RANGECHECK,
- MODULE_MODE_RESET,
- MODULE_MODE_AUTHENTICATION,
- MODULE_MODE_OTA_UPDATE,
-};
-
-
PACK(struct PXX2Version {
uint8_t major;
uint8_t revision:4;
@@ -121,8 +107,10 @@ class ReceiverSettings {
uint8_t receiverId;
uint8_t dirty;
uint8_t telemetryDisabled;
+ uint8_t telemetry25mw;
uint8_t pwmRate;
uint8_t fport;
+ uint8_t enablePwmCh5Ch6;
uint8_t outputsCount;
uint8_t outputsMapping[24];
};
@@ -144,6 +132,7 @@ class OtaUpdateInformation: public BindInformation {
public:
char filename[_MAX_LFN + 1];
uint32_t address;
+ uint32_t module;
};
typedef void (* ModuleCallback)();
@@ -290,6 +279,10 @@ union ExternalModulePulsesData {
Dsm2PulsesData dsm2;
#endif
+#if defined(AFHDS3)
+ afhds3::PulsesData afhds3;
+#endif
+
PpmPulsesData ppm;
CrossfirePulsesData crossfire;
@@ -327,6 +320,7 @@ void sendByteDsm2(uint8_t b);
void putDsm2Flush();
void putDsm2SerialBit(uint8_t bit);
void sendByteSbus(uint8_t b);
+void intmodulePpmStart();
void intmodulePxx1PulsesStart();
void intmodulePxx1SerialStart();
void extmodulePxx1PulsesStart();
@@ -334,6 +328,12 @@ void extmodulePxx1SerialStart();
void extmodulePpmStart();
void intmoduleStop();
void extmoduleStop();
+void getModuleStatusString(uint8_t moduleIdx, char * statusText);
+void getModuleSyncStatusString(uint8_t moduleIdx, char * statusText);
+#if defined(AFHDS3)
+uint8_t actualAfhdsRunPower(int moduleIndex);
+#endif
+void extramodulePpmStart();
inline void startPulses()
{
@@ -364,6 +364,7 @@ enum ChannelsProtocols {
PROTOCOL_CHANNELS_SBUS,
PROTOCOL_CHANNELS_PXX2_LOWSPEED,
PROTOCOL_CHANNELS_PXX2_HIGHSPEED,
+ PROTOCOL_CHANNELS_AFHDS3
};
inline void stopPulses()
@@ -429,4 +430,4 @@ inline bool isModuleInBeepMode()
return false;
}
-#endif // _PULSES_H_
\ No newline at end of file
+#endif // _PULSES_H_
diff --git a/radio/src/pulses/pulses_common.h b/radio/src/pulses/pulses_common.h
index 83058f635..80f5518a1 100644
--- a/radio/src/pulses/pulses_common.h
+++ b/radio/src/pulses/pulses_common.h
@@ -31,6 +31,27 @@
typedef uint16_t trainer_pulse_duration_t;
+enum ModuleSettingsMode
+{
+ MODULE_MODE_NORMAL,
+ MODULE_MODE_SPECTRUM_ANALYSER,
+ MODULE_MODE_POWER_METER,
+ MODULE_MODE_GET_HARDWARE_INFO,
+ MODULE_MODE_MODULE_SETTINGS,
+ MODULE_MODE_RECEIVER_SETTINGS,
+ MODULE_MODE_BEEP_FIRST,
+ MODULE_MODE_REGISTER = MODULE_MODE_BEEP_FIRST,
+ MODULE_MODE_BIND,
+ MODULE_MODE_SHARE,
+ MODULE_MODE_RANGECHECK,
+ MODULE_MODE_RESET,
+ MODULE_MODE_AUTHENTICATION,
+ MODULE_MODE_OTA_UPDATE,
+};
+
+ModuleSettingsMode getModuleMode(int moduleIndex);
+void setModuleMode(int moduleIndex, ModuleSettingsMode mode);
+
template
class DataBuffer {
public:
diff --git a/radio/src/pulses/pxx1.cpp b/radio/src/pulses/pxx1.cpp
index b9eb75c00..4dfa3be95 100644
--- a/radio/src/pulses/pxx1.cpp
+++ b/radio/src/pulses/pxx1.cpp
@@ -33,7 +33,7 @@ void Pxx1Pulses::addFlag1(uint8_t module, uint8_t sendFailsafe)
flag1 |= PXX_SEND_RANGECHECK;
}
- if (sendFailsafe && g_model.moduleData[module].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[module].failsafeMode != FAILSAFE_RECEIVER) {
+ if (sendFailsafe) {
flag1 |= PXX_SEND_FAILSAFE;
}
@@ -69,17 +69,17 @@ void Pxx1Pulses::addExtraFlags(uint8_t module)
}
template
-void Pxx1Pulses::addChannels(uint8_t port, uint8_t sendFailsafe, uint8_t sendUpperChannels)
+void Pxx1Pulses::addChannels(uint8_t moduleIdx, uint8_t sendFailsafe, uint8_t sendUpperChannels)
{
uint16_t pulseValue = 0;
uint16_t pulseValueLow = 0;
- for (int8_t i=0; i<8; i++) {
+ for (uint8_t i = 0; i < 8; i++) {
if (sendFailsafe) {
- if (g_model.moduleData[port].failsafeMode == FAILSAFE_HOLD) {
+ if (g_model.moduleData[moduleIdx].failsafeMode == FAILSAFE_HOLD) {
pulseValue = (i < sendUpperChannels ? 4095 : 2047);
}
- else if (g_model.moduleData[port].failsafeMode == FAILSAFE_NOPULSES) {
+ else if (g_model.moduleData[moduleIdx].failsafeMode == FAILSAFE_NOPULSES) {
pulseValue = (i < sendUpperChannels ? 2048 : 0);
}
else {
@@ -92,7 +92,7 @@ void Pxx1Pulses::addChannels(uint8_t port, uint8_t sendFailsafe, u
pulseValue = 2048;
}
else {
- failsafeValue += 2*PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER;
+ failsafeValue += 2*PPM_CH_CENTER(8+g_model.moduleData[moduleIdx].channelsStart+i) - 2*PPM_CENTER;
pulseValue = limit(2049, (failsafeValue * 512 / 682) + 3072, 4094);
}
}
@@ -105,7 +105,7 @@ void Pxx1Pulses::addChannels(uint8_t port, uint8_t sendFailsafe, u
pulseValue = 0;
}
else {
- failsafeValue += 2*PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER;
+ failsafeValue += 2*PPM_CH_CENTER(g_model.moduleData[moduleIdx].channelsStart+i) - 2*PPM_CENTER;
pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046);
}
}
@@ -113,12 +113,12 @@ void Pxx1Pulses::addChannels(uint8_t port, uint8_t sendFailsafe, u
}
else {
if (i < sendUpperChannels) {
- int channel = 8 + g_model.moduleData[port].channelsStart + i;
+ int channel = 8 + g_model.moduleData[moduleIdx].channelsStart + i;
int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
pulseValue = limit(2049, (value * 512 / 682) + 3072, 4094);
}
- else if (i < sentModuleChannels(port)) {
- int channel = g_model.moduleData[port].channelsStart + i;
+ else if (i < sentModulePXXChannels(moduleIdx)) {
+ int channel = g_model.moduleData[moduleIdx].channelsStart + i;
int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
pulseValue = limit(1, (value * 512 / 682) + 1024, 2046);
}
@@ -182,11 +182,11 @@ void Pxx1Pulses::setupFrame(uint8_t module)
#if defined(PXX_FREQUENCY_HIGH)
if (moduleState[module].protocol == PROTOCOL_CHANNELS_PXX1_SERIAL) {
if (moduleState[module].counter-- == 0) {
- sendFailsafe = 1;
+ sendFailsafe = (g_model.moduleData[module].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[module].failsafeMode != FAILSAFE_RECEIVER);
moduleState[module].counter = 1000;
}
add8ChannelsFrame(module, 0, sendFailsafe);
- if (sentModuleChannels(module) > 8) {
+ if (sentModulePXXChannels(module) > 8) {
add8ChannelsFrame(module, 8, sendFailsafe);
}
return;
@@ -196,12 +196,12 @@ void Pxx1Pulses::setupFrame(uint8_t module)
if (moduleState[module].counter & 0x01) {
sendUpperChannels = g_model.moduleData[module].channelsCount;
if (sendUpperChannels && moduleState[module].counter == 1) {
- sendFailsafe = 1;
+ sendFailsafe = (g_model.moduleData[module].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[module].failsafeMode != FAILSAFE_RECEIVER);
}
}
else {
if (moduleState[module].counter == 0) {
- sendFailsafe = 1;
+ sendFailsafe = (g_model.moduleData[module].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[module].failsafeMode != FAILSAFE_RECEIVER);
}
}
diff --git a/radio/src/pulses/pxx1.h b/radio/src/pulses/pxx1.h
index d2f581580..7c9dd8276 100644
--- a/radio/src/pulses/pxx1.h
+++ b/radio/src/pulses/pxx1.h
@@ -25,8 +25,12 @@
#include "crc.h"
struct HeartbeatCapture {
+#if !defined(INTMODULE_USART)
uint32_t timestamp;
+#endif
+#if defined(DEBUG_LATENCY)
uint32_t count;
+#endif
uint8_t valid;
};
diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp
index 323dc3c16..944be8a3a 100644
--- a/radio/src/pulses/pxx2.cpp
+++ b/radio/src/pulses/pxx2.cpp
@@ -223,6 +223,10 @@ void Pxx2Pulses::setupReceiverSettingsFrame(uint8_t module)
flag1 |= PXX2_RX_SETTINGS_FLAG1_FASTPWM;
if (reusableBuffer.hardwareAndSettings.receiverSettings.fport)
flag1 |= PXX2_RX_SETTINGS_FLAG1_FPORT;
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.telemetry25mw)
+ flag1 |= PXX2_RX_SETTINGS_FLAG1_TELEMETRY_25MW;
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.enablePwmCh5Ch6)
+ flag1 |= PXX2_RX_SETTINGS_FLAG1_ENABLE_PWM_CH5_CH6;
Pxx2Transport::addByte(flag1);
uint8_t outputsCount = min(24, reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount);
for (int i = 0; i < outputsCount; i++) {
@@ -355,6 +359,8 @@ void Pxx2Pulses::sendOtaUpdate(uint8_t module, const char * rxName, uint32_t add
if (module == EXTERNAL_MODULE)
extmoduleSendNextFrame();
+ else if (module == INTERNAL_MODULE)
+ intmoduleSendNextFrame();
}
void Pxx2Pulses::setupAuthenticationFrame(uint8_t module, uint8_t mode, const uint8_t * outputMessage)
@@ -464,7 +470,12 @@ const char * Pxx2OtaUpdate::nextStep(uint8_t step, const char * rxName, uint32_t
destination->address = address;
for (uint8_t retry = 0;; retry++) {
- extmodulePulsesData.pxx2.sendOtaUpdate(module, rxName, address, (const char *) buffer);
+ if (module == EXTERNAL_MODULE) {
+ extmodulePulsesData.pxx2.sendOtaUpdate(module, rxName, address, (const char *) buffer);
+ }
+ else if (module == INTERNAL_MODULE) {
+ intmodulePulsesData.pxx2.sendOtaUpdate(module, rxName, address, (const char *) buffer);
+ }
if (waitStep(step + 1, 20)) {
return nullptr;
}
diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h
index 6e3274278..2fa64dcad 100644
--- a/radio/src/pulses/pxx2.h
+++ b/radio/src/pulses/pxx2.h
@@ -53,6 +53,8 @@
#define PXX2_RX_SETTINGS_FLAG1_READONLY (1 << 6)
#define PXX2_RX_SETTINGS_FLAG1_FASTPWM (1 << 4)
#define PXX2_RX_SETTINGS_FLAG1_FPORT (1 << 3)
+#define PXX2_RX_SETTINGS_FLAG1_TELEMETRY_25MW (1 << 2)
+#define PXX2_RX_SETTINGS_FLAG1_ENABLE_PWM_CH5_CH6 (1 << 1)
#define PXX2_TX_SETTINGS_FLAG0_WRITE (1 << 6)
#define PXX2_TX_SETTINGS_FLAG1_EXTERNAL_ANTENNA (1 << 3)
@@ -81,7 +83,7 @@ enum PXX2ModuleModelID {
PXX2_MODULE_ISRM_S_X10E,
PXX2_MODULE_XJT_LITE,
PXX2_MODULE_ISRM_S_X10S,
- PXX2_MODULE_ISRM_S_X9LITE,
+ PXX2_MODULE_ISRM_X9LITES,
};
static const char * const PXX2ModulesNames[] = {
@@ -98,7 +100,7 @@ static const char * const PXX2ModulesNames[] = {
"ISRM-S-X10E",
"XJT Lite",
"ISRM-S-X10S",
- "ISRM-S-X9Lite"
+ "ISRM-X9LiteS"
};
inline const char * getPXX2ModuleName(uint8_t modelId)
@@ -140,7 +142,7 @@ static const uint8_t PXX2ModuleOptions[] = {
0b00000101, // ISRM-S-X10E
0b00000001, // XJT_LITE
0b00000101, // ISRM-S-X10S
- 0b00000101, // ISRM-S-X9LITE
+ 0b00000100, // ISRM-X9LITES
};
inline uint8_t getPXX2ModuleOptions(uint8_t modelId)
@@ -185,10 +187,13 @@ static const char * const PXX2ReceiversNames[] = {
"R9-SLIM+",
"R9-MINI",
"R9-MM",
- "R9-STAB",
+ "R9-STAB", // R9-STAB has OTA
"R9-MINI-OTA", // this one has OTA (different bootloader)
"R9-MM-OTA", // this one has OTA (different bootloader)
"R9-SLIM+-OTA", // this one has OTA (different bootloader)
+ "Archer-X", // this one has OTA (internal module)
+ "R9MX", // this one has OTA
+ "R9SX", // this one has OTA
};
inline const char * getPXX2ReceiverName(uint8_t modelId)
@@ -235,10 +240,13 @@ static const uint8_t PXX2ReceiverOptions[] = {
0b11111110, // R9-SLIM+
0b11111110, // R9-MINI
0b11111110, // R9-MM
- 0b11111110, // R9-STAB
+ 0b11111111, // R9-STAB+OTA
0b11111111, // R9-MINI+OTA
0b11111111, // R9-MM+OTA
0b11111111, // R9-SLIM+OTA
+ 0b11111111, // ARCHER-X
+ 0b11111111, // R9MX
+ 0b11111111, // R9SX
};
inline uint8_t getPXX2ReceiverOptions(uint8_t modelId)
@@ -256,6 +264,8 @@ inline bool isPXX2ReceiverOptionAvailable(uint8_t modelId, uint8_t option)
enum ReceiverCapabilities {
RECEIVER_CAPABILITY_FPORT,
+ RECEIVER_CAPABILITY_TELEMETRY_25MW,
+ RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6,
RECEIVER_CAPABILITY_COUNT
};
diff --git a/radio/src/sdcard.cpp b/radio/src/sdcard.cpp
index 3a16fde9f..42bf5491e 100644
--- a/radio/src/sdcard.cpp
+++ b/radio/src/sdcard.cpp
@@ -102,7 +102,7 @@ bool isFilePatternAvailable(const char * path, const char * file, const char * p
fplen = strlen(path);
if (fplen > LEN_FILE_PATH_MAX) {
- TRACE_ERROR("isFilePatternAvailable(%s) = error: file path too long.\n", path, file);
+ TRACE_ERROR("isFilePatternAvailable(%s) = error: path too long.\n", path);
return false;
}
@@ -412,7 +412,7 @@ bool sdListFiles(const char * path, const char * extension, const uint8_t maxlen
constexpr uint32_t TEXT_FILE_MAXSIZE = 2048;
-void sdReadTextFile(const char * filename, char lines[NUM_BODY_LINES][LCD_COLS + 1], int & lines_count)
+void sdReadTextFile(const char * filename, char lines[TEXT_VIEWER_LINES][LCD_COLS + 1], int & lines_count)
{
FIL file;
int result;
@@ -423,17 +423,17 @@ void sdReadTextFile(const char * filename, char lines[NUM_BODY_LINES][LCD_COLS +
char escape_chars[4] = {0};
int current_line = 0;
- memclear(lines, NUM_BODY_LINES * (LCD_COLS + 1));
+ memclear(lines, TEXT_VIEWER_LINES * (LCD_COLS + 1));
result = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
if (result == FR_OK) {
- for (unsigned i = 0; i < TEXT_FILE_MAXSIZE && f_read(&file, &c, 1, &sz) == FR_OK && sz == 1 && (lines_count == 0 || current_line - menuVerticalOffset < NUM_BODY_LINES); i++) {
+ for (unsigned i = 0; i < TEXT_FILE_MAXSIZE && f_read(&file, &c, 1, &sz) == FR_OK && sz == 1 && (lines_count == 0 || current_line - menuVerticalOffset < TEXT_VIEWER_LINES); i++) {
if (c == '\n') {
++current_line;
line_length = 0;
escape = 0;
}
- else if (c!='\r' && current_line>=menuVerticalOffset && current_line-menuVerticalOffset=menuVerticalOffset && current_line-menuVerticalOffsetgetKeyState(trimKeys[i]));
}
diff --git a/radio/src/stamp.cpp b/radio/src/stamp.cpp
index 842020a8c..ad28e4037 100644
--- a/radio/src/stamp.cpp
+++ b/radio/src/stamp.cpp
@@ -33,22 +33,27 @@
#endif
#if defined(FRSKY_RELEASE)
-#define DISPLAY_VERSION "FrSky"
+#define DISPLAY_VERSION "-frsky"
#elif defined(JUMPER_RELEASE)
-#define DISPLAY_VERSION "JumperRC"
+#define DISPLAY_VERSION "-jumper"
+#elif defined(RADIOMASTER_RELEASE)
+#define DISPLAY_VERSION "-radiomaster"
+#elif defined(TBS_RELEASE)
+#define DISPLAY_VERSION "-tbs"
#else
-#define DISPLAY_VERSION VERSION
+#define DISPLAY_VERSION
#endif
#if defined(COLORLCD)
- const char vers_stamp[] = "VERS" TAB ": " "opentx-" FLAVOUR "-" DISPLAY_VERSION " (" GIT_STR ")";
+ const char fw_stamp[] = "FW" TAB ": opentx-" FLAVOUR;
+ const char vers_stamp[] = "VERS" TAB ": " VERSION DISPLAY_VERSION " (" GIT_STR ")";
const char date_stamp[] = "DATE" TAB ": " DATE;
const char time_stamp[] = "TIME" TAB ": " TIME;
const char eeprom_stamp[] = "EEPR" TAB ": " EEPROM_STR;
#elif defined(BOARD_NAME)
- const char vers_stamp[] = "FW" TAB ": opentx-" BOARD_NAME "\036VERS" TAB ": " DISPLAY_VERSION " (" GIT_STR ")" "\036DATE" TAB ": " DATE " " TIME "\036EEPR" TAB ": " EEPROM_STR;
+ const char vers_stamp[] = "FW" TAB ": opentx-" BOARD_NAME "\036VERS" TAB ": " VERSION DISPLAY_VERSION " (" GIT_STR ")" "\036DATE" TAB ": " DATE " " TIME "\036EEPR" TAB ": " EEPROM_STR;
#else
- const char vers_stamp[] = "FW" TAB ": opentx-" FLAVOUR "\036VERS" TAB ": " DISPLAY_VERSION " (" GIT_STR ")" "\036DATE" TAB ": " DATE " " TIME "\036EEPR" TAB ": " EEPROM_STR;
+ const char vers_stamp[] = "FW" TAB ": opentx-" FLAVOUR "\036VERS" TAB ": " VERSION DISPLAY_VERSION " (" GIT_STR ")" "\036DATE" TAB ": " DATE " " TIME "\036EEPR" TAB ": " EEPROM_STR;
#endif
/**
@@ -56,35 +61,29 @@
* @return
*/
#if defined(STM32) && !defined(SIMU)
-
-__SECTION_USED(".fwversiondata") const char firmware_version[] = "opentx-" FLAVOUR "-" DISPLAY_VERSION " (" GIT_STR ")";
-__SECTION_USED(".bootversiondata") const char boot_version[] = "opentx-" FLAVOUR "-" DISPLAY_VERSION " (" GIT_STR ")";
+__SECTION_USED(".fwversiondata") const char firmware_version[] = "opentx-" FLAVOUR "-" VERSION DISPLAY_VERSION " (" GIT_STR ")";
+__SECTION_USED(".bootversiondata") const char boot_version[] = "opentx-" FLAVOUR "-" VERSION DISPLAY_VERSION " (" GIT_STR ")";
/**
* Tries to find opentx version in the first 1024 byte of either firmware/bootloader (the one not running) or the buffer
* @param buffer If non-null find the firmware version in the buffer instead
*/
-const char * getOtherVersion(char* buffer)
+const char * getFirmwareVersion(const char * buffer)
{
+ if (buffer == nullptr) {
#if defined(BOOT)
- const char * startother = (char*)(FIRMWARE_ADDRESS+BOOTLOADER_SIZE);
+ buffer = (const char *)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE);
#else
- const char * startother = (char*)(FIRMWARE_ADDRESS);
+ buffer = (const char *)FIRMWARE_ADDRESS;
#endif
- if (buffer != nullptr)
- startother = buffer;
+ }
- const char * other_str = nullptr;
- for (int i=0; i<1024;i++) {
- if (memcmp(startother+i, "opentx-", 7) == 0) {
- other_str = startother + i;
- break;
+ for (int i = 0; i < 1024; i++) {
+ if (memcmp(buffer + i, "opentx-", 7) == 0) {
+ return buffer + i;
}
}
- if (other_str != nullptr)
- return other_str;
- else
- return "no version found";
+ return "no version found";
}
#endif
diff --git a/radio/src/storage/conversions/conversions_218_219.cpp b/radio/src/storage/conversions/conversions_218_219.cpp
index 793d9931c..dfca770ac 100644
--- a/radio/src/storage/conversions/conversions_218_219.cpp
+++ b/radio/src/storage/conversions/conversions_218_219.cpp
@@ -249,7 +249,7 @@ void convertModelData_218_to_219(ModelData &model)
newModel.moduleData[i].type += 4;
if (newModel.moduleData[i].type == MODULE_TYPE_XJT_PXX1) {
newModel.moduleData[i].subType = newModel.moduleData[i].rfProtocol;
-#if defined(PCBX9DP) && PCBREV >= 2019
+#if defined(RADIO_X9DP2019)
if (i == INTERNAL_MODULE) {
newModel.moduleData[i].type = MODULE_TYPE_ISRM_PXX2;
newModel.moduleData[i].subType = MODULE_SUBTYPE_ISRM_PXX2_ACCST_D16;
@@ -389,7 +389,7 @@ void convertRadioData_218_to_219(RadioData & settings)
settings.backlightColor = oldSettings.backlightColor;
settings.switchUnlockStates = oldSettings.switchUnlockStates;
settings.switchConfig = oldSettings.switchConfig;
-#if defined(PCBX9DP) && PCBREV >= 2019
+#if defined(RADIO_X9DP2019)
settings.switchConfig |= SWITCH_TOGGLE << 16;
#endif
memcpy(&settings.switchNames[0], &oldSettings.switchNames[0], 8 * LEN_SWITCH_NAME);
@@ -400,7 +400,7 @@ void convertRadioData_218_to_219(RadioData & settings)
#if defined(PCBHORUS)
// 2 new pots from X10:
// - copy btw. 'chkSum' and 'auxSerialMode' (excl.)
- memcpy(&settings.chkSum, &oldSettings.chkSum, offsetof(RadioData, auxSerialMode) - offsetof(RadioData, chkSum));
+ memcpy(&settings.chkSum, &oldSettings.chkSum, offsetof(RadioData, switchConfig) - sizeof(uint8_t) - offsetof(RadioData, chkSum));
// - move calibration data
memcpy(&settings.calib[NUM_STICKS + 5], &oldSettings.calib[NUM_STICKS + 3], sizeof(CalibData) * (STORAGE_NUM_SLIDERS + STORAGE_NUM_MOUSE_ANALOGS));
memclear(&settings.calib[NUM_STICKS + 3], sizeof(CalibData) * 2);
@@ -440,7 +440,7 @@ void convertRadioData_218_to_219(RadioData & settings)
}
#endif
-#if defined(PCBX9DP) && PCBREV >= 2019
+#if defined(RADIO_X9DP2019)
// force re-calibration
settings.chkSum = 0xFFFF;
setDefaultOwnerId();
diff --git a/radio/src/storage/eeprom_rlc.cpp b/radio/src/storage/eeprom_rlc.cpp
index 3d77e3dbe..d1e28254c 100644
--- a/radio/src/storage/eeprom_rlc.cpp
+++ b/radio/src/storage/eeprom_rlc.cpp
@@ -776,6 +776,15 @@ bool eeLoadGeneral(bool allowFixes)
}
#endif
+#if defined(PCBX9LITES)
+ if (g_eeGeneral.variant == 0x0800) {
+ TRACE("Pre release EEPROM detected, variant %d instead of %d for X9LiteS radio. Loading anyway", g_eeGeneral.variant, EEPROM_VARIANT);
+ g_eeGeneral.variant = EEPROM_VARIANT;
+ storageDirty(EE_GENERAL);
+ return true;
+ }
+#endif
+
#if defined(RADIO_T12)
if (g_eeGeneral.variant != (EEPROM_VARIANT & 0xFFFE)) {
TRACE("EEPROM variant %d instead of %d", g_eeGeneral.variant, EEPROM_VARIANT);
diff --git a/radio/src/storage/modelslist.cpp b/radio/src/storage/modelslist.cpp
index e5e35d896..972e24800 100644
--- a/radio/src/storage/modelslist.cpp
+++ b/radio/src/storage/modelslist.cpp
@@ -110,7 +110,7 @@ void ModelCell::loadBitmap()
buffer->drawSizedText(5, 2, modelName, LEN_MODEL_NAME, SMLSIZE|TEXT_COLOR);
getTimerString(timer, 0);
for (uint8_t i = 0; i < MAX_TIMERS; i++) {
- if (partialmodel.timers[i].mode > 0 && partialmodel.timers[i].persistent) {
+ if (partialmodel.timers[i].mode != 0 && partialmodel.timers[i].persistent) {
getTimerString(timer, partialmodel.timers[i].value);
break;
}
@@ -288,8 +288,8 @@ ModelsList::~ModelsList()
void ModelsList::init()
{
loaded = false;
- currentCategory = NULL;
- currentModel = NULL;
+ currentCategory = nullptr;
+ currentModel = nullptr;
modelsCount = 0;
}
@@ -368,12 +368,12 @@ void ModelsList::save()
f_close(&file);
}
-void ModelsList::setCurrentCategorie(ModelsCategory* cat)
+void ModelsList::setCurrentCategory(ModelsCategory * cat)
{
currentCategory = cat;
}
-void ModelsList::setCurrentModel(ModelCell* cell)
+void ModelsList::setCurrentModel(ModelCell * cell)
{
currentModel = cell;
if (!currentModel->valid_rfData)
@@ -442,15 +442,15 @@ void ModelsList::moveModel(ModelCell * model, ModelsCategory * previous_category
bool ModelsList::isModelIdUnique(uint8_t moduleIdx, char* warn_buf, size_t warn_buf_len)
{
- ModelCell* mod_cell = modelslist.getCurrentModel();
- if (!mod_cell || !mod_cell->valid_rfData) {
+ ModelCell* modelCell = modelslist.getCurrentModel();
+ if (!modelCell || !modelCell->valid_rfData) {
// in doubt, pretend it's unique
return true;
}
- uint8_t modelId = mod_cell->modelId[moduleIdx];
- uint8_t type = mod_cell->moduleData[moduleIdx].type;
- uint8_t rfProtocol = mod_cell->moduleData[moduleIdx].rfProtocol;
+ uint8_t modelId = modelCell->modelId[moduleIdx];
+ uint8_t type = modelCell->moduleData[moduleIdx].type;
+ uint8_t rfProtocol = modelCell->moduleData[moduleIdx].rfProtocol;
uint8_t additionalOnes = 0;
char* curr = warn_buf;
@@ -458,10 +458,10 @@ bool ModelsList::isModelIdUnique(uint8_t moduleIdx, char* warn_buf, size_t warn_
bool hit_found = false;
const std::list& cats = modelslist.getCategories();
- std::list::const_iterator cat_it = cats.begin();
- for (;cat_it != cats.end(); cat_it++) {
- for (ModelsCategory::const_iterator it = (*cat_it)->begin(); it != (*cat_it)->end(); it++) {
- if (mod_cell == *it)
+ std::list::const_iterator catIt = cats.begin();
+ for (;catIt != cats.end(); catIt++) {
+ for (ModelsCategory::const_iterator it = (*catIt)->begin(); it != (*catIt)->end(); it++) {
+ if (modelCell == *it)
continue;
if (!(*it)->valid_rfData)
@@ -507,24 +507,21 @@ bool ModelsList::isModelIdUnique(uint8_t moduleIdx, char* warn_buf, size_t warn_
uint8_t ModelsList::findNextUnusedModelId(uint8_t moduleIdx)
{
- ModelCell* mod_cell = modelslist.getCurrentModel();
- if (!mod_cell || !mod_cell->valid_rfData) {
+ ModelCell * modelCell = modelslist.getCurrentModel();
+ if (!modelCell || !modelCell->valid_rfData) {
return 0;
}
- uint8_t type = mod_cell->moduleData[moduleIdx].type;
- uint8_t rfProtocol = mod_cell->moduleData[moduleIdx].rfProtocol;
+ uint8_t type = modelCell->moduleData[moduleIdx].type;
+ uint8_t rfProtocol = modelCell->moduleData[moduleIdx].rfProtocol;
- // assume 63 is the highest Model ID
- // and use 64 bits
- uint8_t usedModelIds[8];
+ uint8_t usedModelIds[(MAX_RXNUM + 7) / 8];
memset(usedModelIds, 0, sizeof(usedModelIds));
- const std::list& cats = modelslist.getCategories();
- std::list::const_iterator cat_it = cats.begin();
- for (;cat_it != cats.end(); cat_it++) {
- for (ModelsCategory::const_iterator it = (*cat_it)->begin(); it != (*cat_it)->end(); it++) {
- if (mod_cell == *it)
+ const std::list & cats = modelslist.getCategories();
+ for (auto catIt = cats.begin(); catIt != cats.end(); catIt++) {
+ for (auto it = (*catIt)->begin(); it != (*catIt)->end(); it++) {
+ if (modelCell == *it)
continue;
if (!(*it)->valid_rfData)
@@ -536,25 +533,18 @@ uint8_t ModelsList::findNextUnusedModelId(uint8_t moduleIdx)
(rfProtocol == (*it)->moduleData[moduleIdx].rfProtocol)) {
uint8_t id = (*it)->modelId[moduleIdx];
-
- uint8_t mask = 1;
- for (uint8_t i = 1; i < (id & 7); i++)
- mask <<= 1;
-
- usedModelIds[id >> 3] |= mask;
+ uint8_t mask = 1 << (id & 7u);
+ usedModelIds[id >> 3u] |= mask;
}
}
}
- uint8_t new_id = 1;
- uint8_t tst_mask = 1;
- for (;new_id < getMaxRxNum(moduleIdx); new_id++) {
- if (!(usedModelIds[new_id >> 3] & tst_mask)) {
+ for (uint8_t id = 1; id <= getMaxRxNum(moduleIdx); id++) {
+ uint8_t mask = 1u << (id & 7u);
+ if (!(usedModelIds[id >> 3u] & mask)) {
// found free ID
- return new_id;
+ return id;
}
- if ((tst_mask <<= 1) == 0)
- tst_mask = 1;
}
// failed finding something...
diff --git a/radio/src/storage/modelslist.h b/radio/src/storage/modelslist.h
index c5a157207..7da9d4b46 100644
--- a/radio/src/storage/modelslist.h
+++ b/radio/src/storage/modelslist.h
@@ -40,8 +40,8 @@ struct SimpleModuleData
class ModelCell
{
public:
- char modelFilename[LEN_MODEL_FILENAME+1];
- char modelName[LEN_MODEL_NAME+1];
+ char modelFilename[LEN_MODEL_FILENAME + 1];
+ char modelName[LEN_MODEL_NAME + 1];
BitmapBuffer * buffer;
bool valid_rfData;
@@ -51,10 +51,10 @@ public:
ModelCell(const char * name);
~ModelCell();
- void save(FIL* file);
+ void save(FIL * file);
- void setModelName(char* name);
- void setRfData(ModelData* model);
+ void setModelName(char * name);
+ void setRfData(ModelData * model);
void setModelId(uint8_t moduleIdx, uint8_t id);
void setRfModuleData(uint8_t moduleIdx, ModuleData* modData);
@@ -68,7 +68,7 @@ public:
class ModelsCategory: public std::list
{
public:
- char name[LEN_MODEL_FILENAME+1];
+ char name[LEN_MODEL_FILENAME + 1];
ModelsCategory(const char * name);
~ModelsCategory();
@@ -98,21 +98,25 @@ public:
void save();
void clear();
- const std::list& getCategories() const {
+ const std::list & getCategories() const
+ {
return categories;
}
- void setCurrentCategorie(ModelsCategory* cat);
- ModelsCategory* getCurrentCategory() const {
+ void setCurrentCategory(ModelsCategory * cat);
+ ModelsCategory * getCurrentCategory() const
+ {
return currentCategory;
}
- void setCurrentModel(ModelCell* cell);
- ModelCell* getCurrentModel() const {
+ void setCurrentModel(ModelCell * cell);
+ ModelCell * getCurrentModel() const
+ {
return currentModel;
}
- unsigned int getModelsCount() const {
+ unsigned int getModelsCount() const
+ {
return modelsCount;
}
@@ -133,7 +137,6 @@ public:
protected:
FIL file;
-
};
extern ModelsList modelslist;
diff --git a/radio/src/storage/storage_common.cpp b/radio/src/storage/storage_common.cpp
index b6ae2d301..396ede0df 100644
--- a/radio/src/storage/storage_common.cpp
+++ b/radio/src/storage/storage_common.cpp
@@ -25,7 +25,7 @@ uint8_t storageDirtyMsk;
tmr10ms_t storageDirtyTime10ms;
#if defined(RTC_BACKUP_RAM)
-uint8_t rambackupDirtyMsk;
+uint8_t rambackupDirtyMsk = EE_GENERAL | EE_MODEL;
tmr10ms_t rambackupDirtyTime10ms;
#endif
diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp
index 6067f4d8c..d3497dda7 100644
--- a/radio/src/switches.cpp
+++ b/radio/src/switches.cpp
@@ -158,11 +158,13 @@ void getSwitchesPosition(bool startup)
CHECK_2POS(SW_SH);
#endif
-#if defined(PCBX9DP) && PCBREV >= 2019
+#if defined(RADIO_X9DP2019)
CHECK_2POS(SW_SI);
#endif
-#if defined(PCBHORUS) || defined(PCBX7)
+#if defined(PCBX7ACCESS)
+ CHECK_2POS(SW_SI);
+#elif defined(PCBHORUS) || defined(PCBX7)
CHECK_2POS(SW_SI);
CHECK_2POS(SW_SJ);
#endif
@@ -640,7 +642,7 @@ void checkSwitches()
}
LED_ERROR_BEGIN();
- backlightOn();
+ resetBacklightTimeout();
// first - display warning
#if defined(PCBTARANIS) || defined(PCBHORUS)
diff --git a/radio/src/syscalls.c b/radio/src/syscalls.c
index b80ae58e9..369566877 100644
--- a/radio/src/syscalls.c
+++ b/radio/src/syscalls.c
@@ -73,7 +73,7 @@ extern int _close(int file)
extern int _fstat(int file, struct stat * st)
{
- st->st_mode = S_IFCHR ;
+ st->st_mode = S_IFCHR;
return 0;
}
@@ -97,6 +97,12 @@ extern int _write(int file, char *ptr, int len)
return 0;
}
+extern int _getpid()
+{
+ return -1;
+}
+#endif
+
extern void _exit(int status)
{
TRACE("_exit(%d)", status);
@@ -105,12 +111,5 @@ extern void _exit(int status)
extern void _kill(int pid, int sig)
{
- return ;
+ return;
}
-
-extern int _getpid()
-{
- return -1 ;
-}
-#endif
-
diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt
index 2fd540afd..3a8846dfc 100644
--- a/radio/src/targets/common/arm/CMakeLists.txt
+++ b/radio/src/targets/common/arm/CMakeLists.txt
@@ -3,6 +3,7 @@ set_property(CACHE TIMERS PROPERTY STRINGS 2 3)
option(CLI "Command Line Interface" OFF)
option(DEBUG "Debug mode" OFF)
option(LOG_TELEMETRY "Telemetry Logs on SD card" OFF)
+option(LOG_BLUETOOTH "Bluetooth Logs on SD card" OFF)
option(TRACE_SD_CARD "Traces SD enabled" OFF)
option(TRACE_FATFS "Traces FatFS enabled" OFF)
option(TRACE_AUDIO "Traces audio enabled" OFF)
@@ -30,6 +31,10 @@ if(LOG_TELEMETRY)
add_definitions(-DLOG_TELEMETRY)
endif()
+if(LOG_BLUETOOTH)
+ add_definitions(-DLOG_BLUETOOTH)
+endif()
+
if(TRACE_SD_CARD)
add_definitions(-DTRACE_SD_CARD)
set(DEBUG ON)
@@ -143,7 +148,7 @@ endif()
if(MULTIMODULE)
add_definitions(-DMULTIMODULE)
- set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/flysky_ibus.cpp telemetry/hitec.cpp telemetry/hott.cpp telemetry/multi.cpp io/multi_firmware_update.cpp)
+ set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/hitec.cpp telemetry/hott.cpp telemetry/multi.cpp io/multi_firmware_update.cpp)
endif()
if(CROSSFIRE)
@@ -158,6 +163,18 @@ if(CROSSFIRE)
)
endif()
+if(AFHDS3)
+ add_definitions(-DAFHDS3)
+ set(PULSES_SRC
+ ${PULSES_SRC}
+ afhds3.cpp
+ )
+endif()
+
+if(MULTIMODULE OR AFHDS3)
+ set(SRC ${SRC} telemetry/flysky_ibus.cpp )
+endif()
+
add_definitions(-DCPUARM)
add_definitions(-DGPS)
add_definitions(-DBOLD_FONT -DBATTGRAPH -DTHRTRACE)
diff --git a/radio/src/targets/common/arm/stm32/adc_driver.cpp b/radio/src/targets/common/arm/stm32/adc_driver.cpp
index 2a690972b..62eb5a7eb 100644
--- a/radio/src/targets/common/arm/stm32/adc_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/adc_driver.cpp
@@ -24,13 +24,17 @@
// not needed
#elif defined(RADIO_T16)
const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,1, -1,1, -1,1};
+#elif defined(RADIO_T18)
+ const int8_t adcDirection[NUM_ANALOGS] = { 1,-1,1,-1, -1,1,-1, -1,1, -1,1 };
+#elif defined(RADIO_TX16S)
+ const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,1, -1,1, -1,1};
#elif defined(PCBX10)
const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, 1,1, 1, -1};
#elif defined(PCBX9E)
#if defined(HORUS_STICKS)
- const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,-1,-1,1, -1,1,-1, -1,-1,-1};
+ const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,-1,-1,1, -1,1,1, -1,-1,-1};
#else
- const int8_t adcDirection[NUM_ANALOGS] = {1,1,-1,-1, -1,-1,-1,1, -1,1,-1, -1,-1,-1};
+ const int8_t adcDirection[NUM_ANALOGS] = {1,1,-1,-1, -1,-1,-1,1, -1,1,1, -1,-1,-1};
#endif
const uint8_t adcMapping[NUM_ANALOGS] = { 0 /*STICK1*/, 1 /*STICK2*/, 2 /*STICK3*/, 3 /*STICK4*/,
11 /*POT1*/, 4 /*POT2*/, 5 /*POT3*/, 6 /*POT4*/,
diff --git a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp
index d050382a2..a99020dda 100644
--- a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp
@@ -88,33 +88,61 @@ void dacInit()
NVIC_SetPriority(AUDIO_DMA_Stream_IRQn, 7);
}
+#if defined(AUDIO_MUTE_GPIO_PIN)
+void audioMute()
+{
+#if defined(AUDIO_UNMUTE_DELAY)
+ tmr10ms_t now = get_tmr10ms();
+ if (!audioQueue.lastAudioPlayTime) {
+ // we start the mute delay now
+ audioQueue.lastAudioPlayTime = now;
+ }
+ else if (now - audioQueue.lastAudioPlayTime > AUDIO_MUTE_DELAY / 10) {
+ // delay expired, we may mute
+ GPIO_SetBits(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN);
+ }
+#else
+ // mute
+ GPIO_SetBits(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN);
+#endif
+}
+
+void audioUnmute()
+{
+#if defined(AUDIO_UNMUTE_DELAY)
+ // if muted
+ if (GPIO_ReadOutputDataBit(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN)) {
+ // ..un-mute
+ GPIO_ResetBits(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN);
+ RTOS_WAIT_MS(AUDIO_UNMUTE_DELAY);
+ }
+ // reset the mute delay
+ audioQueue.lastAudioPlayTime = 0;
+#else
+ GPIO_ResetBits(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN);
+#endif
+}
+#endif
+
void audioConsumeCurrentBuffer()
{
if (!nextBuffer) {
nextBuffer = audioQueue.buffersFifo.getNextFilledBuffer();
if (nextBuffer) {
#if defined(AUDIO_MUTE_GPIO_PIN)
- // if muted
- if (GPIO_ReadOutputDataBit(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN)) {
- // ..un-mute
- GPIO_ResetBits(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN);
-#if defined(AUDIO_UNMUTE_DELAY)
- RTOS_WAIT_MS(AUDIO_UNMUTE_DELAY);
+ audioUnmute();
#endif
- }
-#endif
- AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA channel
- AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
+ AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA channel
+ AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5; // Write ones to clear bits
AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(nextBuffer->data);
AUDIO_DMA_Stream->NDTR = nextBuffer->size;
- AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel and interrupt
- DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
- DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1 ; // Enable DAC
+ AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA channel and interrupt
+ DAC->SR = DAC_SR_DMAUDR1; // Write 1 to clear flag
+ DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1; // Enable DAC
}
#if defined(AUDIO_MUTE_GPIO_PIN)
else {
- // mute
- GPIO_SetBits(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN);
+ audioMute();
}
#endif
}
diff --git a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp
index 9499e24f9..e646c30d9 100644
--- a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp
@@ -19,13 +19,18 @@
*/
#include "opentx.h"
+#include "targets/horus/board.h"
+
+#if defined(SBUS)
+extern Fifo trainerSbusFifo;
+#endif
#if defined(AUX_SERIAL)
uint8_t auxSerialMode = 0;
Fifo auxSerialTxFifo;
AuxSerialRxFifo auxSerialRxFifo __DMA (AUX_SERIAL_DMA_Stream_RX);
-void auxSerialSetup(unsigned int baudrate, bool dma)
+void auxSerialSetup(unsigned int baudrate, bool dma, uint16_t lenght = USART_WordLength_8b, uint16_t parity = USART_Parity_No, uint16_t stop = USART_StopBits_1)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
@@ -40,10 +45,17 @@ void auxSerialSetup(unsigned int baudrate, bool dma)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(AUX_SERIAL_GPIO, &GPIO_InitStructure);
+#if defined(AUX_SERIAL_PWR_GPIO)
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Pin = AUX_SERIAL_PWR_GPIO_PIN;
+ GPIO_Init(AUX_SERIAL_PWR_GPIO, &GPIO_InitStructure);
+#endif
+
USART_InitStructure.USART_BaudRate = baudrate;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No;
+ USART_InitStructure.USART_WordLength = lenght;
+ USART_InitStructure.USART_StopBits = stop;
+ USART_InitStructure.USART_Parity = parity;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(AUX_SERIAL_USART, &USART_InitStructure);
@@ -93,26 +105,36 @@ void auxSerialInit(unsigned int mode, unsigned int protocol)
#if defined(CROSSFIRE)
if (protocol == PROTOCOL_TELEMETRY_CROSSFIRE) {
auxSerialSetup(CROSSFIRE_TELEM_MIRROR_BAUDRATE, false);
+ AUX_SERIAL_POWER_ON();
break;
}
#endif
- auxSerialSetup(FRSKY_SPORT_BAUDRATE, false);
+ auxSerialSetup(FRSKY_TELEM_MIRROR_BAUDRATE, false);
+ AUX_SERIAL_POWER_ON();
break;
#if defined(DEBUG) || defined(CLI)
case UART_MODE_DEBUG:
auxSerialSetup(DEBUG_BAUDRATE, false);
+ AUX_SERIAL_POWER_OFF();
break;
#endif
case UART_MODE_TELEMETRY:
if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
auxSerialSetup(FRSKY_D_BAUDRATE, true);
+ AUX_SERIAL_POWER_ON();
}
break;
+ case UART_MODE_SBUS_TRAINER:
+ auxSerialSetup(SBUS_BAUDRATE, false, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b
+ AUX_SERIAL_POWER_ON();
+ break;
+
case UART_MODE_LUA:
auxSerialSetup(DEBUG_BAUDRATE, false);
+ AUX_SERIAL_POWER_ON();
}
}
@@ -131,8 +153,7 @@ void auxSerialPutc(char c)
void auxSerialSbusInit()
{
- auxSerialSetup(SBUS_BAUDRATE, true);
- AUX_SERIAL_USART->CR1 |= USART_CR1_M | USART_CR1_PCE ;
+ auxSerialInit(UART_MODE_SBUS_TRAINER, 0);
}
void auxSerialStop()
@@ -182,7 +203,229 @@ extern "C" void AUX_SERIAL_USART_IRQHandler(void)
status = AUX_SERIAL_USART->SR;
}
}
+#endif
+ // Receive
+ uint32_t status = AUX_SERIAL_USART->SR;
+ while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
+ uint8_t data = AUX_SERIAL_USART->DR;
+ UNUSED(data);
+ if (!(status & USART_FLAG_ERRORS)) {
+#if defined(LUA) & !defined(CLI)
+ if (luaRxFifo && auxSerialMode == UART_MODE_LUA)
+ luaRxFifo->push(data);
+#endif
+#if !defined(BOOT)
+ if (auxSerialMode == UART_MODE_SBUS_TRAINER)
+ trainerSbusFifo.push(data);
+#endif
+ }
+ status = AUX_SERIAL_USART->SR;
+ }
#endif
}
#endif
-#endif // AUX_SERIAL
+
+#if defined(AUX2_SERIAL)
+uint8_t aux2SerialMode = 0;
+Fifo aux2SerialTxFifo;
+AuxSerialRxFifo aux2SerialRxFifo __DMA (AUX2_SERIAL_DMA_Stream_RX);
+
+void aux2SerialSetup(unsigned int baudrate, bool dma, uint16_t lenght = USART_WordLength_8b, uint16_t parity = USART_Parity_No, uint16_t stop = USART_StopBits_1)
+{
+ USART_InitTypeDef USART_InitStructure;
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ GPIO_PinAFConfig(AUX2_SERIAL_GPIO, AUX2_SERIAL_GPIO_PinSource_RX, AUX2_SERIAL_GPIO_AF);
+ GPIO_PinAFConfig(AUX2_SERIAL_GPIO, AUX2_SERIAL_GPIO_PinSource_TX, AUX2_SERIAL_GPIO_AF);
+
+ GPIO_InitStructure.GPIO_Pin = AUX2_SERIAL_GPIO_PIN_TX | AUX2_SERIAL_GPIO_PIN_RX;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_Init(AUX2_SERIAL_GPIO, &GPIO_InitStructure);
+
+#if defined(AUX2_SERIAL_PWR_GPIO)
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Pin = AUX2_SERIAL_PWR_GPIO_PIN;
+ GPIO_Init(AUX2_SERIAL_PWR_GPIO, &GPIO_InitStructure);
+#endif
+
+ USART_InitStructure.USART_BaudRate = baudrate;
+ USART_InitStructure.USART_WordLength = lenght;
+ USART_InitStructure.USART_StopBits = stop;
+ USART_InitStructure.USART_Parity = parity;
+ USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+ USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
+ USART_Init(AUX2_SERIAL_USART, &USART_InitStructure);
+
+ if (dma) {
+ DMA_InitTypeDef DMA_InitStructure;
+ aux2SerialRxFifo.clear();
+ USART_ITConfig(AUX2_SERIAL_USART, USART_IT_RXNE, DISABLE);
+ USART_ITConfig(AUX2_SERIAL_USART, USART_IT_TXE, DISABLE);
+ DMA_InitStructure.DMA_Channel = AUX2_SERIAL_DMA_Channel_RX;
+ DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&AUX2_SERIAL_USART->DR);
+ DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(aux2SerialRxFifo.buffer());
+ DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
+ DMA_InitStructure.DMA_BufferSize = aux2SerialRxFifo.size();
+ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+ DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+ DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
+ DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
+ DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
+ DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
+ DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
+ DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
+ DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+ DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
+ DMA_Init(AUX2_SERIAL_DMA_Stream_RX, &DMA_InitStructure);
+ USART_DMACmd(AUX2_SERIAL_USART, USART_DMAReq_Rx, ENABLE);
+ USART_Cmd(AUX2_SERIAL_USART, ENABLE);
+ DMA_Cmd(AUX2_SERIAL_DMA_Stream_RX, ENABLE);
+ }
+ else {
+ USART_Cmd(AUX2_SERIAL_USART, ENABLE);
+ USART_ITConfig(AUX2_SERIAL_USART, USART_IT_RXNE, ENABLE);
+ USART_ITConfig(AUX2_SERIAL_USART, USART_IT_TXE, DISABLE);
+ NVIC_SetPriority(AUX2_SERIAL_USART_IRQn, 7);
+ NVIC_EnableIRQ(AUX2_SERIAL_USART_IRQn);
+ }
+}
+
+void aux2SerialInit(unsigned int mode, unsigned int protocol)
+{
+ aux2SerialStop();
+
+ aux2SerialMode = mode;
+
+ switch (mode) {
+ case UART_MODE_TELEMETRY_MIRROR:
+#if defined(CROSSFIRE)
+ if (protocol == PROTOCOL_TELEMETRY_CROSSFIRE) {
+ aux2SerialSetup(CROSSFIRE_TELEM_MIRROR_BAUDRATE, false);
+ AUX2_SERIAL_POWER_ON();
+ break;
+ }
+#endif
+ aux2SerialSetup(FRSKY_TELEM_MIRROR_BAUDRATE, false);
+ AUX2_SERIAL_POWER_ON();
+ break;
+
+#if defined(DEBUG) || defined(CLI)
+ case UART_MODE_DEBUG:
+ aux2SerialSetup(DEBUG_BAUDRATE, false);
+ AUX2_SERIAL_POWER_OFF();
+ break;
+#endif
+
+ case UART_MODE_TELEMETRY:
+ if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
+ aux2SerialSetup(FRSKY_D_BAUDRATE, true);
+ AUX2_SERIAL_POWER_ON();
+ }
+ break;
+
+ case UART_MODE_SBUS_TRAINER:
+ aux2SerialSetup(SBUS_BAUDRATE, false, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b
+ AUX2_SERIAL_POWER_ON();
+ break;
+
+ case UART_MODE_LUA:
+ aux2SerialSetup(DEBUG_BAUDRATE, false);
+ AUX2_SERIAL_POWER_ON();
+ }
+}
+
+void aux2SerialPutc(char c)
+{
+#if !defined(SIMU)
+ int n = 0;
+ while (aux2SerialTxFifo.isFull()) {
+ delay_ms(1);
+ if (++n > 100) return;
+ }
+ aux2SerialTxFifo.push(c);
+ USART_ITConfig(AUX2_SERIAL_USART, USART_IT_TXE, ENABLE);
+#endif
+}
+
+void aux2SerialSbusInit()
+{
+ aux2SerialInit(UART_MODE_SBUS_TRAINER, 0);
+}
+
+void aux2SerialStop()
+{
+ DMA_DeInit(AUX2_SERIAL_DMA_Stream_RX);
+ USART_DeInit(AUX2_SERIAL_USART);
+}
+
+uint8_t aux2SerialTracesEnabled()
+{
+#if defined(DEBUG)
+ return (aux2SerialMode == UART_MODE_DEBUG);
+#else
+ return false;
+#endif
+}
+
+#if !defined(SIMU)
+extern "C" void AUX2_SERIAL_USART_IRQHandler(void)
+{
+ DEBUG_INTERRUPT(INT_SER2);
+ // Send
+ if (USART_GetITStatus(AUX2_SERIAL_USART, USART_IT_TXE) != RESET) {
+ uint8_t txchar;
+ if (aux2SerialTxFifo.pop(txchar)) {
+ /* Write one byte to the transmit data register */
+ USART_SendData(AUX2_SERIAL_USART, txchar);
+ }
+ else {
+ USART_ITConfig(AUX2_SERIAL_USART, USART_IT_TXE, DISABLE);
+ }
+ }
+
+#if defined(CLI)
+ if (getSelectedUsbMode() != USB_SERIAL_MODE) {
+ // Receive
+ uint32_t status = AUX2_SERIAL_USART->SR;
+ while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
+ uint8_t data = AUX2_SERIAL_USART->DR;
+ if (!(status & USART_FLAG_ERRORS)) {
+ switch (aux2SerialMode) {
+ case UART_MODE_DEBUG:
+ cliRxFifo.push(data);
+ break;
+ }
+ }
+ status = AUX2_SERIAL_USART->SR;
+ }
+ }
+#endif
+#if defined(AUX2_SERIAL)
+ // Receive
+ uint32_t status = AUX2_SERIAL_USART->SR;
+ while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
+ uint8_t data = AUX2_SERIAL_USART->DR;
+ UNUSED(data);
+ if (!(status & USART_FLAG_ERRORS)) {
+#if defined(LUA) & !defined(CLI)
+ if (luaRxFifo && aux2SerialMode == UART_MODE_LUA) {
+ luaRxFifo->push(data);
+ }
+#endif
+#if !defined(BOOT)
+ if (aux2SerialMode == UART_MODE_SBUS_TRAINER) {
+ trainerSbusFifo.push(data);
+ }
+#endif
+ }
+ status = AUX2_SERIAL_USART->SR;
+ }
+}
+#endif
+
+#endif
+#endif // AUX_SERIAL
\ No newline at end of file
diff --git a/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp b/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp
index 1d861e1d6..cbb9821c0 100644
--- a/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp
@@ -24,7 +24,7 @@
Fifo btTxFifo;
Fifo btRxFifo;
-#if defined(PCBX7) || defined(PCBXLITE)
+#if defined(BLUETOOTH_PROBE)
volatile uint8_t btChipPresent = 0;
#endif
@@ -107,6 +107,12 @@ void bluetoothInit(uint32_t baudrate, bool enable)
void bluetoothDisable()
{
GPIO_SetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); // close bluetooth (recent modules will go to bootloader mode)
+ USART_ITConfig(BT_USART, USART_IT_RXNE, DISABLE);
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.GPIO_Pin = BT_RX_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+ GPIO_Init(BT_USART_GPIO, &GPIO_InitStructure);
+ USART_DeInit(BT_USART);
}
extern "C" void BT_USART_IRQHandler(void)
@@ -117,7 +123,7 @@ extern "C" void BT_USART_IRQHandler(void)
uint8_t byte = USART_ReceiveData(BT_USART);
btRxFifo.push(byte);
TRACE("BT %02X", byte);
-#if defined(PCBX7) || defined(PCBXLITE)
+#if defined(BLUETOOTH_PROBE)
if (!btChipPresent) {
// This is to differentiate X7 and X7S and X-Lite with/without BT
btChipPresent = 1;
diff --git a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt
index 8e4e8160a..b94180761 100644
--- a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt
+++ b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt
@@ -75,7 +75,7 @@ set(BOOTLOADER_SRC
../../../../../targets/${TARGET_DIR}/keys_driver.cpp
../../../../../targets/${TARGET_DIR}/diskio.cpp
../../../../../targets/${TARGET_DIR}/board.cpp
- ../../../../../targets/${TARGET_DIR}/pwr_driver.cpp
+ ../pwr_driver.cpp
../../../../../targets/${TARGET_DIR}/bootloader/boot_menu.cpp
../usbd_usr.cpp
../usbd_storage_msd.cpp
@@ -116,11 +116,20 @@ if(PCB STREQUAL X10 OR PCB STREQUAL X12S)
../../../../../syscalls.c
)
+if(USB_CHARGER)
+ set(BOOTLOADER_SRC
+ ${BOOTLOADER_SRC}
+ ../../../../../targets/${TARGET_DIR}/usb_charger_driver.cpp
+ ../../../../../targets/${TARGET_DIR}/led_driver.cpp
+ )
+ endif()
+
if(DEBUG)
set(BOOTLOADER_SRC
${BOOTLOADER_SRC}
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_usart.c
../../../../../serial.cpp
+ ../../../../../targets/common/arm/stm32/aux_serial_driver.cpp
)
endif()
else()
@@ -134,6 +143,7 @@ endif()
remove_definitions(-DDISK_CACHE)
remove_definitions(-DLUA)
remove_definitions(-DCLI)
+remove_definitions(-DSEMIHOSTING)
remove_definitions(-DUSB_SERIAL)
remove_definitions(-DWATCHDOG)
diff --git a/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp b/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp
index 3684f45d7..7120ae76f 100644
--- a/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp
+++ b/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp
@@ -117,10 +117,10 @@ FRESULT openBinFile(MemoryType mt, unsigned int index)
void extractFirmwareVersion(VersionTag* tag)
{
- const char* vers = getOtherVersion((char*)Block_buffer);
+ const char * vers = getFirmwareVersion((const char *)Block_buffer);
if (!vers || (vers[0] == 'n' && vers[1] == 'o')) { // "no version found"
- memcpy(tag->flavour, "unknown", sizeof("unknown"));
- tag->version = "unknown";
+ memcpy(tag->flavour, "unknown", sizeof("unknown"));
+ tag->version = "unknown";
}
// skip "opentx-"
diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp
index 106734a2f..cd337fb7f 100644
--- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp
+++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp
@@ -197,15 +197,16 @@ int main()
RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph |
LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph |
- AUX_SERIAL_RCC_AHB1Periph | I2C_RCC_AHB1Periph |
+ AUX_SERIAL_RCC_AHB1Periph | AUX2_SERIAL_RCC_AHB1Periph |
+ I2C_RCC_AHB1Periph | KEYS_BACKLIGHT_RCC_AHB1Periph |
SD_RCC_AHB1Periph, ENABLE);
RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph | LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph |
INTERRUPT_xMS_RCC_APB1Periph | I2C_RCC_APB1Periph |
- AUX_SERIAL_RCC_APB1Periph |
+ AUX_SERIAL_RCC_APB1Periph | AUX2_SERIAL_RCC_APB1Periph |
SD_RCC_APB1Periph, ENABLE);
- RCC_APB2PeriphClockCmd(LCD_RCC_APB2Periph | BACKLIGHT_RCC_APB2Periph | RCC_APB2Periph_SYSCFG, ENABLE);
+ RCC_APB2PeriphClockCmd(LCD_RCC_APB2Periph | BACKLIGHT_RCC_APB2Periph | RCC_APB2Periph_SYSCFG | AUX_SERIAL_RCC_APB2Periph | AUX2_SERIAL_RCC_APB2Periph, ENABLE);
pwrInit();
keysInit();
@@ -234,6 +235,9 @@ int main()
#if defined(DEBUG) && defined(AUX_SERIAL)
auxSerialInit(UART_MODE_DEBUG, 0); // default serial mode (None if DEBUG not defined)
#endif
+#if defined(DEBUG) && defined(AUX2_SERIAL)
+ aux2SerialInit(UART_MODE_DEBUG, 0); // default serial mode (None if DEBUG not defined)
+#endif
__enable_irq();
diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.h b/radio/src/targets/common/arm/stm32/bootloader/boot.h
index 4f8e7edc7..c9e36269b 100644
--- a/radio/src/targets/common/arm/stm32/bootloader/boot.h
+++ b/radio/src/targets/common/arm/stm32/bootloader/boot.h
@@ -24,7 +24,7 @@
#include "stamp.h"
#if LCD_W < 212
- #define BOOTLOADER_TITLE " OTX Bootloader - " VERSION
+ #define BOOTLOADER_TITLE " Bootloader - " VERSION
#else
#define BOOTLOADER_TITLE " OpenTX Bootloader - " VERSION
#endif
@@ -34,12 +34,12 @@
#if LCD_W >= 480
#define STR_INVALID_FIRMWARE "Not a valid firmware file"
#elif LCD_W >= 212
- #define STR_OR_PLUGIN_USB_CABLE INDENT "Or plug in a USB cable for mass storage"
+ #define STR_OR_PLUGIN_USB_CABLE "Or plug in a USB cable for mass storage"
#define STR_HOLD_ENTER_TO_START "\012Hold [ENT] to start writing"
#define STR_INVALID_FIRMWARE "\011Not a valid firmware file! "
#define STR_INVALID_EEPROM "\011Not a valid EEPROM file! "
#else
- #define STR_OR_PLUGIN_USB_CABLE INDENT "Or plug in a USB cable"
+ #define STR_OR_PLUGIN_USB_CABLE "Or plug in a USB cable"
#define STR_HOLD_ENTER_TO_START "\006Hold [ENT] to start"
#define STR_INVALID_FIRMWARE "\004Not a valid firmware! "
#define STR_INVALID_EEPROM "\004Not a valid EEPROM! "
diff --git a/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp b/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp
index 70ce2b394..25544c33a 100644
--- a/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp
@@ -20,9 +20,9 @@
#include "opentx.h"
+#if defined(INTMODULE_HEARTBEAT_GPIO)
volatile HeartbeatCapture heartbeatCapture;
-#if defined(INTMODULE_HEARTBEAT_GPIO)
void init_intmodule_heartbeat()
{
GPIO_InitTypeDef GPIO_InitStructure;
@@ -69,11 +69,13 @@ void check_intmodule_heartbeat()
{
if (EXTI_GetITStatus(INTMODULE_HEARTBEAT_EXTI_LINE) != RESET) {
#if defined(INTMODULE_USART)
- heartbeatCapture.timestamp = RTOS_GET_MS();
+ nextMixerTime[INTERNAL_MODULE] = RTOS_GET_MS();
#else
heartbeatCapture.timestamp = getTmr2MHz();
#endif
+#if defined(DEBUG_LATENCY)
heartbeatCapture.count++;
+#endif
EXTI_ClearITPendingBit(INTMODULE_HEARTBEAT_EXTI_LINE);
}
}
diff --git a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp
index e2f01f586..56b71d97c 100755
--- a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp
@@ -21,12 +21,18 @@
#include "opentx.h"
ModuleFifo intmoduleFifo;
+#if !defined(INTMODULE_DMA_STREAM)
+uint8_t * intmoduleTxBufferData;
+uint8_t intmoduleTxBufferRemaining;
+#endif
void intmoduleStop()
{
GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN);
+#if defined(INTMODULE_DMA_STREAM)
INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
+#endif
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN;
@@ -57,7 +63,11 @@ void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity,
INTERNAL_MODULE_ON();
NVIC_InitTypeDef NVIC_InitStructure;
+#if defined(INTMODULE_DMA_STREAM)
NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_DMA_STREAM_IRQ;
+#else
+ NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_USART_IRQn;
+#endif
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
@@ -118,8 +128,22 @@ void intmoduleTimerStart(uint32_t periodMs)
#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
extern "C" void INTMODULE_USART_IRQHandler(void)
{
- uint32_t status = INTMODULE_USART->SR;
+#if !defined(INTMODULE_DMA_STREAM)
+ // Send
+ if (USART_GetITStatus(INTMODULE_USART, USART_IT_TXE) != RESET) {
+ if (intmoduleTxBufferRemaining) {
+ USART_SendData(INTMODULE_USART, intmoduleTxBufferData[0]);
+ intmoduleTxBufferData++;
+ intmoduleTxBufferRemaining--;
+ }
+ else {
+ USART_ITConfig(INTMODULE_USART, USART_IT_TXE, DISABLE);
+ }
+ }
+#endif
+ // Receive
+ uint32_t status = INTMODULE_USART->SR;
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
uint8_t data = INTMODULE_USART->DR;
if (status & USART_FLAG_ERRORS) {
@@ -143,6 +167,7 @@ void intmoduleSendBuffer(const uint8_t * data, uint8_t size)
if (size == 0)
return;
+#if defined(INTMODULE_DMA_STREAM)
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(INTMODULE_DMA_STREAM);
DMA_InitStructure.DMA_Channel = INTMODULE_DMA_CHANNEL;
@@ -163,6 +188,11 @@ void intmoduleSendBuffer(const uint8_t * data, uint8_t size)
DMA_Init(INTMODULE_DMA_STREAM, &DMA_InitStructure);
DMA_Cmd(INTMODULE_DMA_STREAM, ENABLE);
USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE);
+#else
+ intmoduleTxBufferData = (uint8_t *)data;
+ intmoduleTxBufferRemaining = size;
+ USART_ITConfig(INTMODULE_USART, USART_IT_TXE, ENABLE);
+#endif
}
void intmoduleSendNextFrame()
diff --git a/radio/src/targets/taranis/pwr_driver.cpp b/radio/src/targets/common/arm/stm32/pwr_driver.cpp
similarity index 72%
rename from radio/src/targets/taranis/pwr_driver.cpp
rename to radio/src/targets/common/arm/stm32/pwr_driver.cpp
index 997937d9f..220b5fdfd 100644
--- a/radio/src/targets/taranis/pwr_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/pwr_driver.cpp
@@ -23,17 +23,14 @@
void pwrInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
+
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- // Board PWR
- GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN;
- GPIO_Init(PWR_ON_GPIO, &GPIO_InitStructure);
-
#if defined(INTMODULE_BOOTCMD_GPIO)
- GPIO_SetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN);
+ INIT_INTMODULE_BOOTCMD_PIN();
GPIO_InitStructure.GPIO_Pin = INTMODULE_BOOTCMD_GPIO_PIN;
GPIO_Init(INTMODULE_BOOTCMD_GPIO, &GPIO_InitStructure);
#endif
@@ -54,23 +51,40 @@ void pwrInit()
GPIO_InitStructure.GPIO_Pin = PWR_SWITCH_GPIO_PIN;
GPIO_Init(PWR_SWITCH_GPIO, &GPIO_InitStructure);
+#if defined(PWR_EXTRA_SWITCH_GPIO)
+ // PWR Extra switch
+ GPIO_InitStructure.GPIO_Pin = PWR_EXTRA_SWITCH_GPIO_PIN;
+ GPIO_Init(PWR_EXTRA_SWITCH_GPIO, &GPIO_InitStructure);
+#endif
+
+#if defined(PCBREV_HARDCODED)
+ hardwareOptions.pcbrev = PCBREV_HARDCODED;
+#elif defined(PCBREV_GPIO_PIN)
+ #if defined(PCBREV_GPIO_PULL_DOWN)
+ GPIO_ResetBits(PCBREV_GPIO, PCBREV_GPIO_PIN);
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
+ #endif
+ GPIO_InitStructure.GPIO_Pin = PCBREV_GPIO_PIN;
+ GPIO_Init(PCBREV_GPIO, &GPIO_InitStructure);
+ hardwareOptions.pcbrev = PCBREV_VALUE();
+#endif
+
#if defined(TRAINER_DETECT_GPIO_PIN)
GPIO_InitStructure.GPIO_Pin = TRAINER_DETECT_GPIO_PIN;
GPIO_Init(TRAINER_DETECT_GPIO, &GPIO_InitStructure);
#endif
+#if defined(SD_PRESENT_GPIO_PIN)
+ GPIO_ResetBits(SD_PRESENT_GPIO, SD_PRESENT_GPIO_PIN);
+ GPIO_InitStructure.GPIO_Pin = SD_PRESENT_GPIO_PIN;
+ GPIO_Init(SD_PRESENT_GPIO, &GPIO_InitStructure);
+#endif
+
#if defined(INTMODULE_USART) && defined(TRAINER_MODULE_CPPM_GPIO_PIN)
GPIO_SetBits(TRAINER_MODULE_CPPM_GPIO, TRAINER_MODULE_CPPM_GPIO_PIN);
GPIO_InitStructure.GPIO_Pin = TRAINER_MODULE_CPPM_GPIO_PIN;
GPIO_Init(TRAINER_MODULE_CPPM_GPIO, &GPIO_InitStructure);
#endif
-
-#if defined(PCBREV_GPIO_PIN)
- GPIO_ResetBits(PCBREV_GPIO, PCBREV_GPIO_PIN);
- GPIO_InitStructure.GPIO_Pin = PCBREV_GPIO_PIN;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
- GPIO_Init(PCBREV_GPIO, &GPIO_InitStructure);
-#endif
}
void pwrOn()
@@ -93,9 +107,20 @@ void pwrOff()
GPIO_ResetBits(PWR_ON_GPIO, PWR_ON_GPIO_PIN);
}
+#if defined(PWR_EXTRA_SWITCH_GPIO)
+bool pwrForcePressed()
+{
+ return (GPIO_ReadInputDataBit(PWR_SWITCH_GPIO, PWR_SWITCH_GPIO_PIN) == Bit_RESET && GPIO_ReadInputDataBit(PWR_EXTRA_SWITCH_GPIO, PWR_EXTRA_SWITCH_GPIO_PIN) == Bit_RESET);
+}
+#endif
+
bool pwrPressed()
{
+#if defined(PWR_EXTRA_SWITCH_GPIO)
+ return (GPIO_ReadInputDataBit(PWR_SWITCH_GPIO, PWR_SWITCH_GPIO_PIN) == Bit_RESET || GPIO_ReadInputDataBit(PWR_EXTRA_SWITCH_GPIO, PWR_EXTRA_SWITCH_GPIO_PIN) == Bit_RESET);
+#else
return GPIO_ReadInputDataBit(PWR_SWITCH_GPIO, PWR_SWITCH_GPIO_PIN) == Bit_RESET;
+#endif
}
void pwrResetHandler()
diff --git a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp
index f43090f04..00b3c76f8 100644
--- a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp
@@ -71,7 +71,7 @@ void rotaryEncoderInit()
void rotaryEncoderCheck()
{
-#if defined(RADIO_T16)
+#if defined(RADIO_FAMILY_T16) && !defined(RADIO_T18)
static uint8_t state = 0;
uint8_t pins = ROTARY_ENCODER_POSITION();
@@ -104,7 +104,7 @@ void rotaryEncoderCheck()
#endif
#if !defined(BOOT)
if (g_eeGeneral.backlightMode & e_backlight_mode_keys) {
- backlightOn();
+ resetBacklightTimeout();
}
inactivity.counter = 0;
#endif
diff --git a/radio/src/targets/common/arm/stm32/usbd_cdc.cpp b/radio/src/targets/common/arm/stm32/usbd_cdc.cpp
index dd0233941..4d9409ec8 100644
--- a/radio/src/targets/common/arm/stm32/usbd_cdc.cpp
+++ b/radio/src/targets/common/arm/stm32/usbd_cdc.cpp
@@ -218,11 +218,18 @@ static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len)
#if defined(CLI)
//copy data to the application FIFO
- for (uint32_t i = 0; i < Len; i++)
- {
+ for (uint32_t i = 0; i < Len; i++) {
cliRxFifo.push(Buf[i]);
}
#endif
+#if defined(LUA) && !defined(CLI)
+ // copy data to the LUA FIFO
+ if (luaRxFifo) {
+ for (uint32_t i = 0; i < Len; i++) {
+ luaRxFifo->push(Buf[i]);
+ }
+ }
+#endif
return USBD_OK;
}
diff --git a/radio/src/targets/common/arm/stm32/usbd_storage_msd.cpp b/radio/src/targets/common/arm/stm32/usbd_storage_msd.cpp
index b60e5da8f..1fbfb970a 100644
--- a/radio/src/targets/common/arm/stm32/usbd_storage_msd.cpp
+++ b/radio/src/targets/common/arm/stm32/usbd_storage_msd.cpp
@@ -408,7 +408,7 @@ const FATDirEntry_t g_DIRroot[] =
0xA302,
0x3D55,
0x0002,
- sizeof(firmware_txt) + strlen(getOtherVersion(nullptr))
+ sizeof(firmware_txt) + strlen(getFirmwareVersion())
},
{
{ 'F', 'I', 'R', 'M', 'W', 'A', 'R', 'E'},
@@ -512,13 +512,11 @@ int32_t fat12Read(uint8_t * buffer, uint16_t sector, uint16_t count)
else if (sector == 3) {
memcpy(buffer, g_DIRroot, sizeof(g_DIRroot) ) ;
}
- else if (sector == 4)
- {
+ else if (sector == 4) {
memcpy(buffer, firmware_txt, sizeof(firmware_txt));
- memcpy(buffer + sizeof(firmware_txt), getOtherVersion(nullptr), strlen(getOtherVersion(nullptr)));
+ strcpy((char *)(buffer + sizeof(firmware_txt)), getFirmwareVersion());
}
- else if (sector < RESERVED_SECTORS)
- {
+ else if (sector < RESERVED_SECTORS) {
// allocated to firmware.txt
}
else if (sector < RESERVED_SECTORS + (FLASHSIZE/BLOCK_SIZE )) {
diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt
index 987e4e81f..525c8a4ad 100644
--- a/radio/src/targets/horus/CMakeLists.txt
+++ b/radio/src/targets/horus/CMakeLists.txt
@@ -2,6 +2,7 @@ option(DISK_CACHE "Enable SD card disk cache" ON)
option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON)
option(PXX1 "PXX1 protocol support" ON)
option(PXX2 "PXX2 protocol support" OFF)
+option(AFHDS3 "AFHDS3 TX Module" ON)
option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON)
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
@@ -15,7 +16,6 @@ set(NAVIGATION_TYPE horus)
set(TARGET_DIR horus)
set(LINKER_SCRIPT targets/horus/stm32f4_flash.ld)
set(RTC_BACKUP_RAM YES)
-set(LUA YES)
set(PPM_LIMITS_SYMETRICAL YES)
set(USB_SERIAL ON CACHE BOOL "Enable USB serial (CDC)")
@@ -52,8 +52,33 @@ if (PCB STREQUAL X10)
set(FLAVOUR t16)
set(LUA_EXPORT lua_export_t16)
add_definitions(-DRADIO_T16)
+ add_definitions(-DRADIO_FAMILY_T16)
option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" OFF)
option(BLUETOOTH "Support for bluetooth module" OFF)
+ elseif (PCBREV STREQUAL TX16S)
+ set(FLAVOUR tx16s)
+ set(LUA_EXPORT lua_export_t16)
+ add_definitions(-DRADIO_TX16S)
+ add_definitions(-DRADIO_FAMILY_T16)
+ option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" ON)
+ option(BLUETOOTH "Support for bluetooth module" OFF)
+ option(INTERNAL_GPS "Support for internal ublox GPS" OFF)
+ set(HARDWARE_TOUCH YES)
+ set(USB_CHARGER YES)
+ set(DEFAULT_THEME "DARKBLUE")
+ set(SBUS_TRAINER ON)
+ set(AUX_SERIAL ON)
+ if (NOT BLUETOOTH AND NOT INTERNAL_GPS)
+ set(AUX2_SERIAL ON)
+ endif()
+ set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS")
+ elseif (PCBREV STREQUAL T18)
+ set(FLAVOUR t18)
+ set(LUA_EXPORT lua_export_t16)
+ add_definitions(-DRADIO_T18)
+ add_definitions(-DRADIO_FAMILY_T16)
+ option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" ON)
+ option(BLUETOOTH "Support for bluetooth module" OFF)
else()
set(FLAVOUR x10)
option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON)
@@ -80,7 +105,6 @@ elseif (PCB STREQUAL X12S)
${TARGET_SRC}
audio_spi_driver.cpp
x12s_adc_driver.cpp
- gps_driver.cpp
)
set(BITMAPS_TARGET x12s_bitmaps)
set(FONTS_TARGET x12s_fonts)
@@ -103,6 +127,12 @@ add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK)
add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE})
add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
+if(DEFAULT_THEME)
+ add_definitions(-DDEFAULT_THEME_${DEFAULT_THEME})
+else()
+ add_definitions(-DDEFAULT_THEME_DEFAULT)
+endif()
+
if(NOT UNEXPECTED_SHUTDOWN)
add_definitions(-DNO_UNEXPECTED_SHUTDOWN)
endif()
@@ -179,6 +209,7 @@ endif()
if(INTERNAL_GPS)
set(SRC ${SRC} gps.cpp)
+ set(TARGET_SRC ${TARGET_SRC} gps_driver.cpp)
add_definitions(-DINTERNAL_GPS)
message("Horus: Internal GPS enabled")
endif()
@@ -196,18 +227,49 @@ set(TARGET_SRC
../common/arm/stm32/rotary_encoder_driver.cpp
)
+if(HARDWARE_TOUCH)
+ set(TARGET_SRC ${TARGET_SRC}
+ tp_gt911.cpp
+ )
+ add_definitions(-DHARDWARE_TOUCH)
+endif()
+
+if(USB_CHARGER)
+ set(TARGET_SRC ${TARGET_SRC} usb_charger_driver.cpp)
+ add_definitions(-DUSB_CHARGER)
+endif()
+
if(BLUETOOTH)
add_definitions(-DBLUETOOTH)
set(TARGET_SRC ${TARGET_SRC} ../common/arm/stm32/bluetooth_driver.cpp)
set(SRC ${SRC} bluetooth.cpp)
endif()
+if (AUX_SERIAL)
+ add_definitions(-DAUX_SERIAL)
+ set(AUX_SERIAL_DRIVER ../common/arm/stm32/aux_serial_driver.cpp)
+endif()
+
+if (AUX2_SERIAL)
+ add_definitions(-DAUX2_SERIAL)
+ set(AUX_SERIAL_DRIVER ../common/arm/stm32/aux_serial_driver.cpp)
+endif()
+
+if (SBUS_TRAINER)
+ add_definitions(-DSBUS_TRAINER)
+ set(SRC
+ ${SRC}
+ sbus.cpp
+ )
+endif()
+
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
${LCD_DRIVER}
+ ${AUX_SERIAL_DRIVER}
board.cpp
backlight_driver.cpp
- pwr_driver.cpp
+ ../common/arm/stm32/pwr_driver.cpp
sdram_driver.c
startup_stm32f42_43xxx.s
../common/arm/stm32/sdio_sd.c
@@ -228,11 +290,46 @@ set(STM32LIB_SRC
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma2d.c
)
+MACRO(GET_GCC_INCLUDE_PATH gcc_include_path)
+ if (WIN32)
+ execute_process(COMMAND arm-none-eabi-gcc -v -x c -E NUL ERROR_VARIABLE _gcc_output OUTPUT_QUIET)
+ else()
+ execute_process(COMMAND arm-none-eabi-gcc -v -x c -E - INPUT_FILE /dev/null ERROR_VARIABLE _gcc_output OUTPUT_QUIET)
+ endif()
+
+ # Build an array of string from the GCC output
+ string(REPLACE "\n" ";" _gcc_output "${_gcc_output}")
+
+ set(_capture_include FALSE)
+ set(_include_path "")
+
+ # Go through the lines and capture between '"#include <...> search starts here:"' and 'End of search list.'
+ foreach(_line ${_gcc_output})
+ if(${_line} STREQUAL "End of search list.")
+ set(_capture_include FALSE)
+ endif()
+
+ if(_capture_include)
+ # Remove the leading and trailing empty characters
+ string(REPLACE "\r" "" _line ${_line})
+ string(SUBSTRING "${_line}" 1 -1 _line)
+ set(_include_path "${_include_path}" "-I${_line}")
+ endif()
+
+ if(${_line} STREQUAL "#include <...> search starts here:")
+ set(_capture_include TRUE)
+ endif()
+ endforeach()
+ set(${gcc_include_path} ${_include_path})
+ENDMACRO()
+
if(PYTHONINTERP_FOUND)
+ GET_GCC_INCLUDE_PATH(arm_gcc_include_path)
+
add_custom_command(
OUTPUT ${PROJECT_BINARY_DIR}/radio/src/datacopy.cpp
WORKING_DIRECTORY ${RADIO_DIRECTORY}/src
- COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/generate_datacopy.py datastructs.h -DPCBHORUS -DPCBX10 -DCPUARM -DCOLORLCD -DBACKUP -Itargets/horus > ${PROJECT_BINARY_DIR}/radio/src/datacopy.cpp
+ COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/generate_datacopy.py datastructs.h -DPCBHORUS -DPCBX10 -DCPUARM -DSTM32F4 -DSTM32F429_439xx -DCOLORLCD -DBACKUP -DSIMU -I. -Itargets/horus -Itargets/common/arm/stm32 -I${THIRDPARTY_DIR} -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include ${arm_gcc_include_path} > ${PROJECT_BINARY_DIR}/radio/src/datacopy.cpp
DEPENDS ${RADIO_DIRECTORY}/src/datastructs.h ${RADIO_DIRECTORY}/util/generate_datacopy.py
)
add_custom_target(datacopy
diff --git a/radio/src/targets/horus/backlight_driver.cpp b/radio/src/targets/horus/backlight_driver.cpp
index e141cf5dd..13f73f1ee 100644
--- a/radio/src/targets/horus/backlight_driver.cpp
+++ b/radio/src/targets/horus/backlight_driver.cpp
@@ -32,6 +32,15 @@ void backlightInit()
GPIO_Init(BACKLIGHT_GPIO, &GPIO_InitStructure);
GPIO_PinAFConfig(BACKLIGHT_GPIO, BACKLIGHT_GPIO_PinSource, BACKLIGHT_GPIO_AF);
+#if defined(KEYS_BACKLIGHT_GPIO)
+ GPIO_InitStructure.GPIO_Pin = KEYS_BACKLIGHT_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_Init(KEYS_BACKLIGHT_GPIO, &GPIO_InitStructure);
+#endif
+
// TIMER init
#if defined(PCBX12S) && PCBREV >= 13
BACKLIGHT_TIMER->ARR = 100;
@@ -72,6 +81,15 @@ void backlightEnable(uint8_t dutyCycle)
BACKLIGHT_TIMER->CCR3 = BACKLIGHT_LEVEL_MAX - dutyCycle;
#endif
+#if defined(KEYS_BACKLIGHT_GPIO) && !defined(BOOT)
+ if (dutyCycle == 0 || g_eeGeneral.keysBacklight == 0) {
+ GPIO_ResetBits(KEYS_BACKLIGHT_GPIO, KEYS_BACKLIGHT_GPIO_PIN);
+ }
+ else {
+ GPIO_SetBits(KEYS_BACKLIGHT_GPIO, KEYS_BACKLIGHT_GPIO_PIN);
+ }
+#endif
+
if (dutyCycle == 0) {
BACKLIGHT_TIMER->BDTR &= ~TIM_BDTR_MOE;
}
diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp
index 048817c69..cb379e6fe 100644
--- a/radio/src/targets/horus/board.cpp
+++ b/radio/src/targets/horus/board.cpp
@@ -41,11 +41,31 @@ void watchdogInit(unsigned int duration)
IWDG->KR = 0xCCCC; // start
}
-#if defined(SEMIHOSTING)
-extern "C" void initialise_monitor_handles();
+#if defined(AUX_SERIAL_PWR_GPIO)
+void auxSerialPowerOn()
+{
+ GPIO_SetBits(AUX_SERIAL_PWR_GPIO, AUX_SERIAL_PWR_GPIO_PIN);
+}
+
+void auxSerialPowerOff()
+{
+ GPIO_ResetBits(AUX_SERIAL_PWR_GPIO, AUX_SERIAL_PWR_GPIO_PIN);
+}
+#endif
+#if defined(AUX2_SERIAL_PWR_GPIO)
+void aux2SerialPowerOn()
+{
+ GPIO_SetBits(AUX2_SERIAL_PWR_GPIO, AUX2_SERIAL_PWR_GPIO_PIN);
+}
+
+void aux2SerialPowerOff()
+{
+ GPIO_ResetBits(AUX2_SERIAL_PWR_GPIO, AUX2_SERIAL_PWR_GPIO_PIN);
+}
#endif
-#if defined(PCBX10) && !defined(RADIO_T16)
+
+#if HAS_SPORT_UPDATE_CONNECTOR()
void sportUpdateInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
@@ -66,24 +86,30 @@ void sportUpdatePowerOff()
{
GPIO_ResetBits(SPORT_UPDATE_PWR_GPIO, SPORT_UPDATE_PWR_GPIO_PIN);
}
+
+void sportUpdatePowerInit()
+{
+ if (g_eeGeneral.sportUpdatePower == 1)
+ sportUpdatePowerOn();
+ else
+ sportUpdatePowerOff();
+}
#endif
void boardInit()
{
-#if defined(SEMIHOSTING)
- initialise_monitor_handles();
-#endif
-
RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph |
PCBREV_RCC_AHB1Periph |
LED_RCC_AHB1Periph |
LCD_RCC_AHB1Periph |
BACKLIGHT_RCC_AHB1Periph |
+ KEYS_BACKLIGHT_RCC_AHB1Periph |
SD_RCC_AHB1Periph |
AUDIO_RCC_AHB1Periph |
KEYS_RCC_AHB1Periph |
ADC_RCC_AHB1Periph |
AUX_SERIAL_RCC_AHB1Periph |
+ AUX2_SERIAL_RCC_AHB1Periph |
TELEMETRY_RCC_AHB1Periph |
TRAINER_RCC_AHB1Periph |
BT_RCC_AHB1Periph |
@@ -91,8 +117,11 @@ void boardInit()
HAPTIC_RCC_AHB1Periph |
INTMODULE_RCC_AHB1Periph |
EXTMODULE_RCC_AHB1Periph |
+ I2C_RCC_AHB1Periph |
GPS_RCC_AHB1Periph |
- SPORT_UPDATE_RCC_AHB1Periph,
+ SPORT_UPDATE_RCC_AHB1Periph |
+ TOUCH_INT_RCC_AHB1Periph |
+ TOUCH_RST_RCC_AHB1Periph,
ENABLE);
RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph |
@@ -101,11 +130,13 @@ void boardInit()
TIMER_2MHz_RCC_APB1Periph |
AUDIO_RCC_APB1Periph |
AUX_SERIAL_RCC_APB1Periph |
+ AUX2_SERIAL_RCC_APB1Periph |
TELEMETRY_RCC_APB1Periph |
TRAINER_RCC_APB1Periph |
AUDIO_RCC_APB1Periph |
INTMODULE_RCC_APB1Periph |
EXTMODULE_RCC_APB1Periph |
+ I2C_RCC_APB1Periph |
GPS_RCC_APB1Periph |
BACKLIGHT_RCC_APB1Periph,
ENABLE);
@@ -118,6 +149,9 @@ void boardInit()
EXTMODULE_RCC_APB2Periph |
TELEMETRY_RCC_APB2Periph |
BT_RCC_APB2Periph |
+ AUX_SERIAL_RCC_APB2Periph |
+ AUX2_SERIAL_RCC_APB2Periph |
+ GPS_RCC_APB2Periph |
BACKLIGHT_RCC_APB2Periph,
ENABLE);
@@ -127,6 +161,13 @@ void boardInit()
__enable_irq();
+#if defined(DEBUG) && defined(AUX_SERIAL)
+ auxSerialInit(UART_MODE_DEBUG, 0); // default serial mode (None if DEBUG not defined)
+#endif
+#if defined(DEBUG) && defined(AUX2_SERIAL)
+ aux2SerialInit(UART_MODE_DEBUG, 0); // default serial mode (None if DEBUG not defined)
+#endif
+
TRACE("\nHorus board started :)");
TRACE("RCC->CSR = %08x", RCC->CSR);
@@ -170,7 +211,11 @@ void boardInit()
ledInit();
-#if defined(PCBX10) && !defined(RADIO_T16)
+#if defined(USB_CHARGER)
+ usbChargerInit();
+#endif
+
+#if HAS_SPORT_UPDATE_CONNECTOR()
sportUpdateInit();
#endif
@@ -216,8 +261,14 @@ void boardOff()
pwrOff();
}
+#if defined (RADIO_TX16S)
+ #define BATTERY_DIVIDER 1495
+#else
+ #define BATTERY_DIVIDER 1629
+#endif
+
uint16_t getBatteryVoltage()
{
int32_t instant_vbat = anaIn(TX_VOLTAGE); // using filtered ADC value on purpose
- return (uint16_t)((instant_vbat * (1000 + g_eeGeneral.txVoltageCalibration)) / 1629);
+ return (uint16_t)((instant_vbat * (1000 + g_eeGeneral.txVoltageCalibration)) / BATTERY_DIVIDER);
}
diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h
index 7e36df57a..e4e99d40f 100644
--- a/radio/src/targets/horus/board.h
+++ b/radio/src/targets/horus/board.h
@@ -21,15 +21,15 @@
#ifndef _BOARD_H_
#define _BOARD_H_
-#include "../definitions.h"
-#include "../opentx_constants.h"
+#include "definitions.h"
+#include "opentx_constants.h"
#include "board_common.h"
#include "hal.h"
PACK(typedef struct {
- uint8_t pcbrev : 2;
- uint8_t sticksPwmDisabled : 1;
- uint8_t pxx2Enabled : 1;
+ uint8_t pcbrev:2;
+ uint8_t sticksPwmDisabled:1;
+ uint8_t pxx2Enabled:1;
}) HardwareOptions;
extern HardwareOptions hardwareOptions;
@@ -59,7 +59,7 @@ extern uint16_t sessionTimer;
#define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
-#if defined(PCBX10) && !defined(RADIO_T16)
+#if defined(PCBX10) && !defined(RADIO_FAMILY_T16)
#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_SET)
#else
#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_RESET)
@@ -146,6 +146,10 @@ void SDRAM_Init();
// Pulses driver
#define INTERNAL_MODULE_ON() GPIO_SetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
+#if defined(INTERNAL_MODULE_PXX1) || defined(INTERNAL_MODULE_PXX2)
+ #define HARDWARE_INTERNAL_RAS
+#endif
+
#if defined(INTMODULE_USART)
#define INTERNAL_MODULE_OFF() intmoduleStop()
#else
@@ -193,6 +197,9 @@ void stop_trainer_ppm();
void init_trainer_capture();
void stop_trainer_capture();
+// SBUS
+int sbusGetByte(uint8_t * byte);
+
// Keys driver
enum EnumKeys
{
@@ -382,7 +389,11 @@ enum Analogs {
#define SLIDER2 SLIDER_FRONT_RIGHT
#define DEFAULT_SWITCH_CONFIG (SWITCH_TOGGLE << 14) + (SWITCH_3POS << 12) + (SWITCH_2POS << 10) + (SWITCH_3POS << 8) + (SWITCH_3POS << 6) + (SWITCH_3POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0)
-#define DEFAULT_POTS_CONFIG (POT_WITH_DETENT << 4) + (POT_MULTIPOS_SWITCH << 2) + (POT_WITHOUT_DETENT << 0)
+#if defined(RADIO_FAMILY_T16)
+ #define DEFAULT_POTS_CONFIG (POT_WITH_DETENT << 4) + (POT_MULTIPOS_SWITCH << 2) + (POT_WITH_DETENT << 0)
+#else
+ #define DEFAULT_POTS_CONFIG (POT_WITH_DETENT << 4) + (POT_MULTIPOS_SWITCH << 2) + (POT_WITHOUT_DETENT << 0)
+#endif
#if defined(PCBX12S)
#define DEFAULT_SLIDERS_CONFIG (SLIDER_WITH_DETENT << 3) + (SLIDER_WITH_DETENT << 2) + (SLIDER_WITH_DETENT << 1) + (SLIDER_WITH_DETENT << 0)
@@ -488,8 +499,17 @@ void pwrOn();
void pwrOff();
void pwrResetHandler();
bool pwrPressed();
+#if defined(PWR_EXTRA_SWITCH_GPIO)
+ bool pwrForcePressed();
+#else
+ #define pwrForcePressed() false
+#endif
uint32_t pwrPressedDuration();
+// USB Charger
+void usbChargerInit();
+bool usbChargerLed();
+
// Led driver
void ledInit();
void ledOff();
@@ -527,7 +547,7 @@ void backlightEnable(uint8_t dutyCycle = 0);
#define BACKLIGHT_LEVEL_MAX 100
#if defined(PCBX12S)
#define BACKLIGHT_LEVEL_MIN 5
-#elif defined(RADIO_T16)
+#elif defined(RADIO_FAMILY_T16)
#define BACKLIGHT_LEVEL_MIN 1
#else
#define BACKLIGHT_LEVEL_MIN 46
@@ -547,6 +567,14 @@ void usbJoystickUpdate();
#define USB_NAME "Jumper T16"
#define USB_MANUFACTURER 'J', 'u', 'm', 'p', 'e', 'r', ' ', ' ' /* 8 bytes */
#define USB_PRODUCT 'T', '1', '6', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */
+#elif defined(RADIO_T18)
+ #define USB_NAME "Jumper T18"
+ #define USB_MANUFACTURER 'J', 'u', 'm', 'p', 'e', 'r', ' ', ' ' /* 8 bytes */
+ #define USB_PRODUCT 'T', '1', '8', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */
+#elif defined(RADIO_TX16S)
+ #define USB_NAME "RadioMas TX16S"
+ #define USB_MANUFACTURER 'R', 'a', 'd', 'i', 'o', 'M', 'a', 's' /* 8 bytes */
+ #define USB_PRODUCT 'T', 'X', '1', '6', 'S', ' ', ' ', ' ' /* 8 Bytes */
#elif defined(PCBX10)
#define USB_NAME "FrSky X10"
#define USB_MANUFACTURER 'F', 'r', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */
@@ -588,14 +616,58 @@ extern uint32_t telemetryErrors;
void telemetryPortInvertedInit(uint32_t baudrate);
// Sport update driver
-#if defined(PCBX10) && !defined(RADIO_T16)
+#if HAS_SPORT_UPDATE_CONNECTOR()
void sportUpdatePowerOn();
void sportUpdatePowerOff();
+void sportUpdatePowerInit();
#define SPORT_UPDATE_POWER_ON() sportUpdatePowerOn()
#define SPORT_UPDATE_POWER_OFF() sportUpdatePowerOff()
+#define SPORT_UPDATE_POWER_INIT() sportUpdatePowerInit()
+#define IS_SPORT_UPDATE_POWER_ON() (GPIO_ReadInputDataBit(SPORT_UPDATE_PWR_GPIO, SPORT_UPDATE_PWR_GPIO_PIN) == Bit_SET)
#else
#define SPORT_UPDATE_POWER_ON()
#define SPORT_UPDATE_POWER_OFF()
+#define SPORT_UPDATE_POWER_INIT()
+#define IS_SPORT_UPDATE_POWER_ON() (false)
+#endif
+
+// Aux serial port driver
+#if defined(AUX_SERIAL_GPIO)
+#define DEBUG_BAUDRATE 115200
+extern uint8_t auxSerialMode;
+void auxSerialInit(unsigned int mode, unsigned int protocol);
+void auxSerialPutc(char c);
+#define auxSerialTelemetryInit(protocol) auxSerialInit(UART_MODE_TELEMETRY, protocol)
+void auxSerialSbusInit();
+void auxSerialStop();
+void auxSerialPowerOn();
+void auxSerialPowerOff();
+#if defined(AUX_SERIAL_PWR_GPIO)
+#define AUX_SERIAL_POWER_ON() auxSerialPowerOn()
+#define AUX_SERIAL_POWER_OFF() auxSerialPowerOff()
+#else
+#define AUX_SERIAL_POWER_ON()
+#define AUX_SERIAL_POWER_OFF()
+#endif
+#endif
+
+// Aux2 serial port driver
+#if defined(AUX2_SERIAL)
+extern uint8_t aux2SerialMode;
+void aux2SerialInit(unsigned int mode, unsigned int protocol);
+void aux2SerialPutc(char c);
+#define aux2SerialTelemetryInit(protocol) aux2SerialInit(UART_MODE_TELEMETRY, protocol)
+void aux2SerialSbusInit();
+void aux2SerialStop();
+void aux2SerialPowerOn();
+void aux2SerialPowerOff();
+#if defined(AUX2_SERIAL_PWR_GPIO)
+#define AUX2_SERIAL_POWER_ON() aux2SerialPowerOn()
+#define AUX2_SERIAL_POWER_OFF() aux2SerialPowerOff()
+#else
+#define AUX2_SERIAL_POWER_ON()
+#define AUX2_SERIAL_POWER_OFF()
+#endif
#endif
// Haptic driver
@@ -619,7 +691,7 @@ void gpsSendByte(uint8_t byte);
// BT driver
#define BT_TX_FIFO_SIZE 64
-#define BT_RX_FIFO_SIZE 128
+#define BT_RX_FIFO_SIZE 256
#define BLUETOOTH_BOOTLOADER_BAUDRATE 230400
#define BLUETOOTH_FACTORY_BAUDRATE 57600
#define BLUETOOTH_DEFAULT_BAUDRATE 115200
diff --git a/radio/src/targets/horus/bootloader/boot_menu.cpp b/radio/src/targets/horus/bootloader/boot_menu.cpp
index 9e6ceaf47..911d98b43 100644
--- a/radio/src/targets/horus/bootloader/boot_menu.cpp
+++ b/radio/src/targets/horus/bootloader/boot_menu.cpp
@@ -64,27 +64,25 @@ static void bootloaderDrawFooter()
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
{
// clear screen
- lcdDrawSolidFilledRect(0, 0, LCD_W-1, LCD_H-1, TEXT_BGCOLOR);
+ lcdDrawSolidFilledRect(0, 0, LCD_W, LCD_H, TEXT_BGCOLOR);
if (st == ST_START) {
+ bootloaderDrawTitle(88, BOOTLOADER_TITLE);
- bootloaderDrawTitle(88, BOOTLOADER_TITLE);
-
- lcdDrawBitmapPattern(90, 72, LBM_FLASH, TEXT_COLOR);
- lcdDrawText(124, 75, "Write Firmware");
+ lcdDrawBitmapPattern(90, 72, LBM_FLASH, TEXT_COLOR);
+ lcdDrawText(124, 75, "Write Firmware");
- lcdDrawBitmapPattern(90, 107, LBM_EXIT, TEXT_COLOR);
- lcdDrawText(124, 110, "Exit");
+ lcdDrawBitmapPattern(90, 107, LBM_EXIT, TEXT_COLOR);
+ lcdDrawText(124, 110, "Exit");
- lcdDrawSolidRect(119, (opt == 0) ? 72 : 107, 270, 26, 2, LINE_COLOR);
-
- lcd->drawBitmap(60, 166, &BMP_PLUG_USB);
- lcdDrawText(195, 175, "Or plug in a USB cable");
- lcdDrawText(195, 200, "for mass storage");
+ lcdDrawSolidRect(119, (opt == 0) ? 72 : 107, 270, 26, 2, LINE_COLOR);
- bootloaderDrawFooter();
- lcdDrawText( 36, 242, "Current Firmware:");
- lcdDrawText(200, 242, getOtherVersion(nullptr));
+ lcd->drawBitmap(60, 166, &BMP_PLUG_USB);
+ lcdDrawText(195, 175, "Or plug in a USB cable");
+ lcdDrawText(195, 200, "for mass storage");
+
+ bootloaderDrawFooter();
+ lcdDrawText(LCD_W / 2, 242, getFirmwareVersion(), CENTERED);
}
else if (st == ST_USB) {
diff --git a/radio/src/targets/horus/diskio.cpp b/radio/src/targets/horus/diskio.cpp
index b9bcda011..3b3517af5 100644
--- a/radio/src/targets/horus/diskio.cpp
+++ b/radio/src/targets/horus/diskio.cpp
@@ -310,10 +310,15 @@ DRESULT disk_ioctl (
// TODO everything here should not be in the driver layer ...
FATFS g_FATFS_Obj __DMA; // initialized in boardInit()
+
#if defined(LOG_TELEMETRY)
FIL g_telemetryFile = {};
#endif
+#if defined(LOG_BLUETOOTH)
+FIL g_bluetoothFile = {};
+#endif
+
#if defined(BOOT)
void sdInit(void)
{
@@ -350,6 +355,13 @@ void sdMount()
f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append
}
#endif
+
+#if defined(LOG_BLUETOOTH)
+ f_open(&g_bluetoothFile, LOGS_PATH "/bluetooth.log", FA_OPEN_ALWAYS | FA_WRITE);
+ if (f_size(&g_bluetoothFile) > 0) {
+ f_lseek(&g_bluetoothFile, f_size(&g_bluetoothFile)); // append
+ }
+#endif
}
else {
TRACE("f_mount() failed");
@@ -362,9 +374,15 @@ void sdDone()
if (sdMounted()) {
audioQueue.stopSD();
+
#if defined(LOG_TELEMETRY)
f_close(&g_telemetryFile);
#endif
+
+#if defined(LOG_BLUETOOTH)
+ f_close(&g_bluetoothFile);
+#endif
+
f_mount(nullptr, "", 0); // unmount SD
}
}
diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp
index 0da9e46a5..9c04aeb21 100644
--- a/radio/src/targets/horus/extmodule_driver.cpp
+++ b/radio/src/targets/horus/extmodule_driver.cpp
@@ -316,6 +316,30 @@ void extmoduleSendNextFrame()
break;
#endif
+#if defined(AFHDS3)
+ case PROTOCOL_CHANNELS_AFHDS3:
+ {
+#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)
+ extmoduleSendBuffer(extmodulePulsesData.afhds3.getData(), extmodulePulsesData.afhds3.getSize());
+#else
+ const uint16_t* dataPtr = extmodulePulsesData.afhds3.getData();
+ uint32_t dataSize = extmodulePulsesData.afhds3.getSize();
+ //Peripheral data size
+ //we know that afdhds3 uses 2 byte values!
+ uint32_t dmaSize = (EXTMODULE_TIMER_DMA_SIZE & (DMA_SxCR_PSIZE_0 | DMA_SxCR_PSIZE_1)) | DMA_SxCR_MSIZE_0;
+
+ EXTMODULE_TIMER->CCR2 = dataPtr[dataSize -1] - 4000; // 2mS in advance
+ EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
+ EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | dmaSize | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
+ EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
+ EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(dataPtr);
+ EXTMODULE_TIMER_DMA_STREAM->NDTR = (uint32_t)dataSize;
+ EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
+#endif
+ }
+ break;
+#endif
+
#if defined(DSM2)
case PROTOCOL_CHANNELS_SBUS:
#if defined(PCBX10) || PCBREV >= 13
@@ -362,7 +386,7 @@ void extmoduleSendInvertedByte(uint8_t byte)
// wait
}
time += 34;
- for (i = 0 ; i < 8 ; i += 1) {
+ for (i = 0; i < 8; i++) {
if (byte & 1) {
GPIO_ResetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN);
}
@@ -376,7 +400,7 @@ void extmoduleSendInvertedByte(uint8_t byte)
time += 35 ;
}
GPIO_ResetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN);
- __enable_irq() ; // No need to wait for the stop bit to complete
+ __enable_irq(); // No need to wait for the stop bit to complete
while ((uint16_t) (getTmr2MHz() - time) < 34) {
// wait
}
diff --git a/radio/src/targets/horus/gps_driver.cpp b/radio/src/targets/horus/gps_driver.cpp
index 7a5e464c4..0e165b978 100644
--- a/radio/src/targets/horus/gps_driver.cpp
+++ b/radio/src/targets/horus/gps_driver.cpp
@@ -33,8 +33,8 @@ void gpsInit(uint32_t baudrate)
NVIC_InitTypeDef NVIC_InitStructure;
// RX and TX pins
- GPIO_PinAFConfig(GPIOA, GPS_TX_GPIO_PinSource, GPS_GPIO_AF);
- GPIO_PinAFConfig(GPIOA, GPS_RX_GPIO_PinSource, GPS_GPIO_AF);
+ GPIO_PinAFConfig(GPS_UART_GPIO, GPS_TX_GPIO_PinSource, GPS_GPIO_AF);
+ GPIO_PinAFConfig(GPS_UART_GPIO, GPS_RX_GPIO_PinSource, GPS_GPIO_AF);
GPIO_InitStructure.GPIO_Pin = (GPS_TX_GPIO_PIN | GPS_RX_GPIO_PIN);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
@@ -58,6 +58,14 @@ void gpsInit(uint32_t baudrate)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
+
+#if defined(GPS_PWR_GPIO)
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Pin = GPS_PWR_GPIO_PIN;
+ GPIO_Init(GPS_PWR_GPIO, &GPIO_InitStructure);
+ GPIO_SetBits(GPS_PWR_GPIO, GPS_PWR_GPIO_PIN);
+#endif
}
#if defined(DEBUG)
diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h
index e7afa6ddb..dd8f6ec70 100644
--- a/radio/src/targets/horus/hal.h
+++ b/radio/src/targets/horus/hal.h
@@ -38,6 +38,21 @@
#define KEYS_GPIO_PIN_DOWN GPIO_Pin_6 // PI.06
#define KEYS_GPIO_REG_RIGHT GPIOC->IDR
#define KEYS_GPIO_PIN_RIGHT GPIO_Pin_4 // PC.04
+#elif defined(RADIO_TX16S)
+ #define KEYS_GPIO_REG_ENTER GPIOI->IDR
+ #define KEYS_GPIO_PIN_ENTER GPIO_Pin_8 // PI.08
+ #define KEYS_GPIO_REG_PGUP GPIOC->IDR
+ #define KEYS_GPIO_PIN_PGUP GPIO_Pin_13 // PC.13
+ #define KEYS_GPIO_REG_PGDN GPIOI->IDR
+ #define KEYS_GPIO_PIN_PGDN GPIO_Pin_11 // PI.11
+ #define KEYS_GPIO_REG_UP GPIOI->IDR
+ #define KEYS_GPIO_PIN_UP GPIO_Pin_6 // PI.06
+ #define KEYS_GPIO_REG_DOWN GPIOI->IDR
+ #define KEYS_GPIO_PIN_DOWN GPIO_Pin_4 // PI.04
+ #define KEYS_GPIO_REG_LEFT GPIOI->IDR
+ #define KEYS_GPIO_PIN_LEFT GPIO_Pin_7 // PI.07
+ #define KEYS_GPIO_REG_RIGHT GPIOI->IDR
+ #define KEYS_GPIO_PIN_RIGHT GPIO_Pin_5 // PI.05
#elif defined(PCBX10)
#define KEYS_GPIO_REG_ENTER GPIOI->IDR
#define KEYS_GPIO_PIN_ENTER GPIO_Pin_8 // PI.08
@@ -120,24 +135,24 @@
// Gimbal switch left
#define STORAGE_SWITCH_I
#define HARDWARE_SWITCH_I
- #define SWITCHES_GPIO_REG_I GPIOH->IDR
- #define SWITCHES_GPIO_PIN_I GPIO_Pin_14 // PH.14
+ #define SWITCHES_GPIO_REG_I GPIOH->IDR
+ #define SWITCHES_GPIO_PIN_I GPIO_Pin_14 // PH.14
// Gimbal switch right
#define STORAGE_SWITCH_J
#define HARDWARE_SWITCH_J
- #define SWITCHES_GPIO_REG_J GPIOH->IDR
- #define SWITCHES_GPIO_PIN_J GPIO_Pin_15 // PH.15
+ #define SWITCHES_GPIO_REG_J GPIOH->IDR
+ #define SWITCHES_GPIO_PIN_J GPIO_Pin_15 // PH.15
#elif defined(PCBX12S)
// Gimbal switch left
#define STORAGE_SWITCH_I
#define HARDWARE_SWITCH_I
- #define SWITCHES_GPIO_REG_I GPIOB->IDR
- #define SWITCHES_GPIO_PIN_I GPIO_Pin_1 // PB.01
+ #define SWITCHES_GPIO_REG_I GPIOB->IDR
+ #define SWITCHES_GPIO_PIN_I GPIO_Pin_1 // PB.01
// Gimbal switch right
#define STORAGE_SWITCH_J
#define HARDWARE_SWITCH_J
- #define SWITCHES_GPIO_REG_J GPIOB->IDR
- #define SWITCHES_GPIO_PIN_J GPIO_Pin_0 // PB.00
+ #define SWITCHES_GPIO_REG_J GPIOB->IDR
+ #define SWITCHES_GPIO_PIN_J GPIO_Pin_0 // PB.00
#endif
// Trims
@@ -167,10 +182,17 @@
#define TRIMS_GPIO_REG_LSU GPIOB->IDR
#define TRIMS_GPIO_PIN_LSU GPIO_Pin_13 // PB.13
#elif defined(PCBX10)
- #define TRIMS_GPIO_REG_LHL GPIOB->IDR
- #define TRIMS_GPIO_PIN_LHL GPIO_Pin_8 // PB.08
- #define TRIMS_GPIO_REG_LHR GPIOB->IDR
- #define TRIMS_GPIO_PIN_LHR GPIO_Pin_9 // PB.09
+ #if defined(RADIO_TX16S)
+ #define TRIMS_GPIO_REG_LHL GPIOA->IDR
+ #define TRIMS_GPIO_PIN_LHL GPIO_Pin_6 // PA.06
+ #define TRIMS_GPIO_REG_LHR GPIOC->IDR
+ #define TRIMS_GPIO_PIN_LHR GPIO_Pin_4 // PC.04
+ #else
+ #define TRIMS_GPIO_REG_LHL GPIOB->IDR
+ #define TRIMS_GPIO_PIN_LHL GPIO_Pin_8 // PB.08
+ #define TRIMS_GPIO_REG_LHR GPIOB->IDR
+ #define TRIMS_GPIO_PIN_LHR GPIO_Pin_9 // PB.09
+ #endif
#define TRIMS_GPIO_REG_LVD GPIOG->IDR
#define TRIMS_GPIO_PIN_LVD GPIO_Pin_12 // PG.12
#define TRIMS_GPIO_REG_LVU GPIOJ->IDR
@@ -183,16 +205,16 @@
#define TRIMS_GPIO_PIN_RVU GPIO_Pin_12 // PJ.12
#define TRIMS_GPIO_REG_RHR GPIOD->IDR
#define TRIMS_GPIO_PIN_RHR GPIO_Pin_7 // PD.07
- #if defined(RADIO_T16)
- #define TRIMS_GPIO_REG_LSU GPIOD->IDR
- #define TRIMS_GPIO_PIN_LSU GPIO_Pin_13 // PD.13
- #define TRIMS_GPIO_REG_LSD GPIOJ->IDR
- #define TRIMS_GPIO_PIN_LSD GPIO_Pin_8 // PJ.08
+ #if defined(RADIO_FAMILY_T16)
+ #define TRIMS_GPIO_REG_LSU GPIOD->IDR
+ #define TRIMS_GPIO_PIN_LSU GPIO_Pin_13 // PD.13
+ #define TRIMS_GPIO_REG_LSD GPIOJ->IDR
+ #define TRIMS_GPIO_PIN_LSD GPIO_Pin_8 // PJ.08
#else
- #define TRIMS_GPIO_REG_LSU GPIOJ->IDR
- #define TRIMS_GPIO_PIN_LSU GPIO_Pin_8 // PJ.08
- #define TRIMS_GPIO_REG_LSD GPIOD->IDR
- #define TRIMS_GPIO_PIN_LSD GPIO_Pin_13 // PD.13
+ #define TRIMS_GPIO_REG_LSU GPIOJ->IDR
+ #define TRIMS_GPIO_PIN_LSU GPIO_Pin_8 // PJ.08
+ #define TRIMS_GPIO_REG_LSD GPIOD->IDR
+ #define TRIMS_GPIO_PIN_LSD GPIO_Pin_13 // PD.13
#endif
#define TRIMS_GPIO_REG_RSU GPIOB->IDR
#define TRIMS_GPIO_PIN_RSU GPIO_Pin_14 // PB.14
@@ -211,11 +233,21 @@
#define KEYS_GPIOI_PINS (KEYS_GPIO_PIN_PGDN | KEYS_GPIO_PIN_LEFT | KEYS_GPIO_PIN_DOWN | SWITCHES_GPIO_PIN_A_L | GPIO_Pin_4)
#define KEYS_GPIOJ_PINS (SWITCHES_GPIO_PIN_D_H | TRIMS_GPIO_PIN_RVU | TRIMS_GPIO_PIN_LVD | TRIMS_GPIO_PIN_LVU | TRIMS_GPIO_PIN_RSD)
#elif defined(PCBX10)
- #define KEYS_GPIOB_PINS (GPIO_Pin_12 | GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13 | GPIO_Pin_8 | GPIO_Pin_9)
+ #if defined(RADIO_TX16S)
+ #define KEYS_GPIOB_PINS (GPIO_Pin_12 | GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13)
+ #else
+ #define KEYS_GPIOB_PINS (GPIO_Pin_12 | GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13 | GPIO_Pin_8 | GPIO_Pin_9)
+ #endif
#define KEYS_GPIOD_PINS (GPIO_Pin_11 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_13)
#define KEYS_GPIOE_PINS (GPIO_Pin_3)
#define KEYS_GPIOG_PINS (SWITCHES_GPIO_PIN_D_L | SWITCHES_GPIO_PIN_G_H | SWITCHES_GPIO_PIN_G_L | SWITCHES_GPIO_PIN_H | TRIMS_GPIO_PIN_LVD)
+#if defined(RADIO_TX16S)
+ #define KEYS_GPIOA_PINS (GPIO_Pin_6)
+ #define KEYS_GPIOC_PINS (GPIO_Pin_4 | GPIO_Pin_13)
+ #define KEYS_GPIOH_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15)
+#else
#define KEYS_GPIOH_PINS (GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15)
+#endif
#define KEYS_GPIOI_PINS (GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_11 | GPIO_Pin_15)
#define KEYS_GPIOJ_PINS (SWITCHES_GPIO_PIN_D_H | TRIMS_GPIO_PIN_LVU | TRIMS_GPIO_PIN_RVD | TRIMS_GPIO_PIN_RVU | GPIO_Pin_8)
#endif
@@ -288,23 +320,50 @@
#define ADC_DMA_Stream DMA2_Stream0
#define ADC_SET_DMA_FLAGS() ADC_DMA->LIFCR = (DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0)
#define ADC_TRANSFER_COMPLETE() (ADC_DMA->LISR & DMA_LISR_TCIF0)
-#if defined(RADIO_T16)
- #define ADC_VREF_PREC2 300
-#else
- #define ADC_VREF_PREC2 250
-#endif
+ #if defined(RADIO_TX16S)
+ #define ADC_VREF_PREC2 330
+ #elif defined(RADIO_T16) || defined(RADIO_T18)
+ #define ADC_VREF_PREC2 300
+ #else
+ #define ADC_VREF_PREC2 250
+ #endif
#endif
// Power
+#if defined(RADIO_T18)
+#define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_GPIOB
+#define PWR_ON_GPIO GPIOJ
+#define PWR_ON_GPIO_PIN GPIO_Pin_1 // PJ.01
+#define PWR_SWITCH_GPIO GPIOJ
+#define PWR_SWITCH_GPIO_PIN GPIO_Pin_0 // PJ.00
+#define PWR_EXTRA_SWITCH_GPIO GPIOB
+#define PWR_EXTRA_SWITCH_GPIO_PIN GPIO_Pin_0 // PB.00
+#else
#define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOJ
#define PWR_ON_GPIO GPIOJ
#define PWR_ON_GPIO_PIN GPIO_Pin_1 // PJ.01
#define PWR_SWITCH_GPIO GPIOJ
#define PWR_SWITCH_GPIO_PIN GPIO_Pin_0 // PJ.00
+#endif
+
+// USB Charger
+#if defined(USB_CHARGER)
+#define USB_CHARGER_RCC_AHB1Periph RCC_AHB1Periph_GPIOG
+#define USB_CHARGER_GPIO GPIOG
+#define USB_CHARGER_GPIO_PIN GPIO_Pin_11 // PG.11
+#define USB_USBDet_GPIO_PIN GPIO_Pin_13 // PG.13
+#else
+#define USB_CHARGER_RCC_AHB1Periph 0
+#endif
// S.Port update connector
-#define SPORT_MAX_BAUDRATE 250000 // < 400000
-#if defined(PCBX10) && !defined(RADIO_T16)
+#if defined(RADIO_FAMILY_T16)
+ #define SPORT_MAX_BAUDRATE 400000
+#else
+ #define SPORT_MAX_BAUDRATE 250000 // < 400000
+#endif
+
+#if defined(PCBX10) && !defined(RADIO_FAMILY_T16)
#define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOH
#define SPORT_UPDATE_PWR_GPIO GPIOH
#define SPORT_UPDATE_PWR_GPIO_PIN GPIO_Pin_13 // PH.13
@@ -316,15 +375,15 @@
// PCBREV
#if defined(PCBX10)
-#define PCBREV_RCC_AHB1Periph RCC_AHB1Periph_GPIOH
-#define PCBREV_GPIO_PIN (GPIO_Pin_7 | GPIO_Pin_8)
-#define PCBREV_GPIO GPIOH
-#define PCBREV_VALUE() (GPIO_ReadInputDataBit(PCBREV_GPIO, GPIO_Pin_7) + (GPIO_ReadInputDataBit(PCBREV_GPIO, GPIO_Pin_8) << 1))
+ #define PCBREV_RCC_AHB1Periph RCC_AHB1Periph_GPIOH
+ #define PCBREV_GPIO_PIN (GPIO_Pin_7 | GPIO_Pin_8)
+ #define PCBREV_GPIO GPIOH
+ #define PCBREV_VALUE() (GPIO_ReadInputDataBit(PCBREV_GPIO, GPIO_Pin_7) + (GPIO_ReadInputDataBit(PCBREV_GPIO, GPIO_Pin_8) << 1))
#else
-#define PCBREV_RCC_AHB1Periph RCC_AHB1Periph_GPIOI
-#define PCBREV_GPIO GPIOI
-#define PCBREV_GPIO_PIN GPIO_Pin_11 // PI.11
-#define PCBREV_VALUE() GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN)
+ #define PCBREV_RCC_AHB1Periph RCC_AHB1Periph_GPIOI
+ #define PCBREV_GPIO GPIOI
+ #define PCBREV_GPIO_PIN GPIO_Pin_11 // PI.11
+ #define PCBREV_VALUE() GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN)
#endif
// Led
@@ -343,29 +402,77 @@
#endif
// Serial Port (DEBUG)
-#if defined(PCBX12S)
-#define AUX_SERIAL_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1)
-#define AUX_SERIAL_RCC_APB1Periph RCC_APB1Periph_USART3
-#define AUX_SERIAL_GPIO GPIOB
-#define AUX_SERIAL_GPIO_PIN_TX GPIO_Pin_10 // PB.10
-#define AUX_SERIAL_GPIO_PIN_RX GPIO_Pin_11 // PB.11
-#define AUX_SERIAL_GPIO_PinSource_TX GPIO_PinSource10
-#define AUX_SERIAL_GPIO_PinSource_RX GPIO_PinSource11
-#define AUX_SERIAL_GPIO_AF GPIO_AF_USART3
-#define AUX_SERIAL_USART USART3
-#define AUX_SERIAL_USART_IRQHandler USART3_IRQHandler
-#define AUX_SERIAL_USART_IRQn USART3_IRQn
-#define AUX_SERIAL_DMA_Stream_RX DMA1_Stream1
-#define AUX_SERIAL_DMA_Channel_RX DMA_Channel_4
+#if defined(PCBX12S) || defined(RADIO_TX16S)
+ #define AUX_SERIAL_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1)
+ #define AUX_SERIAL_RCC_APB1Periph RCC_APB1Periph_USART3
+ #define AUX_SERIAL_RCC_APB2Periph 0
+ #define AUX_SERIAL_GPIO GPIOB
+ #define AUX_SERIAL_GPIO_PIN_TX GPIO_Pin_10 // PB.10
+ #define AUX_SERIAL_GPIO_PIN_RX GPIO_Pin_11 // PB.11
+ #define AUX_SERIAL_GPIO_PinSource_TX GPIO_PinSource10
+ #define AUX_SERIAL_GPIO_PinSource_RX GPIO_PinSource11
+ #define AUX_SERIAL_GPIO_AF GPIO_AF_USART3
+ #define AUX_SERIAL_USART USART3
+ #define AUX_SERIAL_USART_IRQHandler USART3_IRQHandler
+ #define AUX_SERIAL_USART_IRQn USART3_IRQn
+ #define AUX_SERIAL_DMA_Stream_RX DMA1_Stream1
+ #define AUX_SERIAL_DMA_Channel_RX DMA_Channel_4
+ #define AUX_SERIAL_PWR_GPIO GPIOA
+ #define AUX_SERIAL_PWR_GPIO_PIN GPIO_Pin_15 // PB.00
+#if defined(RADIO_TX16S)
+ #define TRAINER_BATTERY_COMPARTMENT // allows serial port TTL trainer
+#endif
#else
-#define AUX_SERIAL_RCC_AHB1Periph 0
-#define AUX_SERIAL_RCC_APB1Periph 0
+ #define AUX_SERIAL_RCC_AHB1Periph 0
+ #define AUX_SERIAL_RCC_APB1Periph 0
+ #define AUX_SERIAL_RCC_APB2Periph 0
+#endif
+
+#if defined(AUX2_SERIAL)
+ #define AUX2_SERIAL_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_DMA2)
+ #define AUX2_SERIAL_RCC_APB1Periph 0
+ #define AUX2_SERIAL_RCC_APB2Periph RCC_APB2Periph_USART6
+ #define AUX2_SERIAL_USART USART6
+ #define AUX2_SERIAL_GPIO_AF GPIO_AF_USART6
+ #define AUX2_SERIAL_USART_IRQn USART6_IRQn
+ #define AUX2_SERIAL_GPIO GPIOG
+ #define AUX2_SERIAL_GPIO_PIN_TX GPIO_Pin_14 // PG.14
+ #define AUX2_SERIAL_GPIO_PIN_RX GPIO_Pin_9 // PG.09
+ #define AUX2_SERIAL_GPIO_PinSource_TX GPIO_PinSource14
+ #define AUX2_SERIAL_GPIO_PinSource_RX GPIO_PinSource9
+ #define AUX2_SERIAL_USART_IRQHandler USART6_IRQHandler
+ #define AUX2_SERIAL_DMA_Stream_RX DMA2_Stream6
+ #define AUX2_SERIAL_DMA_Channel_RX DMA_Channel_5
+ #define AUX2_SERIAL_PWR_GPIO GPIOB
+ #define AUX2_SERIAL_PWR_GPIO_PIN GPIO_Pin_0 // PB.00
+#elif defined(RADIO_TX16S) && defined(INTERNAL_GPS)
+ #define GPS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOG)
+ #define GPS_RCC_APB1Periph 0
+ #define GPS_RCC_APB2Periph RCC_APB2Periph_USART6
+ #define GPS_USART USART6
+ #define GPS_GPIO_AF GPIO_AF_USART6
+ #define GPS_USART_IRQn USART6_IRQn
+ #define GPS_USART_IRQHandler USART6_IRQHandler
+ #define GPS_UART_GPIO GPIOG
+ #define GPS_TX_GPIO_PIN GPIO_Pin_14 // PG.14
+ #define GPS_RX_GPIO_PIN GPIO_Pin_9 // PG.09
+ #define GPS_TX_GPIO_PinSource GPIO_PinSource14
+ #define GPS_RX_GPIO_PinSource GPIO_PinSource9
+ #define GPS_PWR_GPIO GPIOB
+ #define GPS_PWR_GPIO_PIN GPIO_Pin_0 // PB.00
+ #define AUX2_SERIAL_RCC_AHB1Periph 0
+ #define AUX2_SERIAL_RCC_APB1Periph 0
+ #define AUX2_SERIAL_RCC_APB2Periph 0
+#else
+ #define AUX2_SERIAL_RCC_AHB1Periph 0
+ #define AUX2_SERIAL_RCC_APB1Periph 0
+ #define AUX2_SERIAL_RCC_APB2Periph 0
#endif
// Telemetry
#define TELEMETRY_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1)
#define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2
-#define TELEMETRY_RCC_APB2Periph RCC_APB2Periph_TIM10
+#define TELEMETRY_RCC_APB2Periph RCC_APB2Periph_TIM11
#define TELEMETRY_DIR_GPIO GPIOD
#define TELEMETRY_DIR_GPIO_PIN GPIO_Pin_4 // PD.04
#define TELEMETRY_GPIO GPIOD
@@ -385,8 +492,8 @@
#define TELEMETRY_TIMER_IRQn TIM1_TRG_COM_TIM11_IRQn
#define TELEMETRY_TIMER_IRQHandler TIM1_TRG_COM_TIM11_IRQHandler
#if defined(PCBX12S)
-#define TELEMETRY_DMA_Stream_RX DMA1_Stream5
-#define TELEMETRY_DMA_Channel_RX DMA_Channel_4
+ #define TELEMETRY_DMA_Stream_RX DMA1_Stream5
+ #define TELEMETRY_DMA_Channel_RX DMA_Channel_4
#endif
#define TELEMETRY_DMA_Stream_TX DMA1_Stream6
#define TELEMETRY_DMA_Channel_TX DMA_Channel_4
@@ -417,6 +524,9 @@
#define LCD_GPIO_NRST GPIOI
#define LCD_GPIO_PIN_NRST GPIO_Pin_10 // PI.10
#endif
+#if defined(PCBX10) && !defined(RADIO_T18) && !defined(SIMU)
+ #define LCD_VERTICAL_INVERT
+#endif
#define LTDC_IRQ_PRIO 4
#define DMA_SCREEN_IRQ_PRIO 6
@@ -452,6 +562,14 @@
#define BACKLIGHT_GPIO_AF GPIO_AF_TIM8
#define BACKLIGHT_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
#endif
+#if defined(RADIO_T18)
+ #define KEYS_BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC
+ #define KEYS_BACKLIGHT_GPIO GPIOC
+ #define KEYS_BACKLIGHT_GPIO_PIN GPIO_Pin_4 // PC.04
+ #define KEYS_BACKLIGHT_GPIO_PinSource GPIO_PinSource4
+#else
+ #define KEYS_BACKLIGHT_RCC_AHB1Periph 0
+#endif
// SD
#define SD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
@@ -546,8 +664,36 @@
#define AUDIO_DMA DMA1
#endif
-#if defined(RADIO_T16)
- #define AUDIO_UNMUTE_DELAY 150
+#if defined(RADIO_FAMILY_T16)
+ #define AUDIO_UNMUTE_DELAY 120 // ms
+ #define AUDIO_MUTE_DELAY 500 // ms
+#endif
+
+#if defined(RADIO_TX16S)
+// Only slight noise with 868MHz > 1W, if complaints later remove and set AUDIO_UNMUTE_DELAY to 150
+ #undef AUDIO_MUTE_GPIO_PIN
+#endif
+
+// Touch
+#if defined(HARDWARE_TOUCH)
+ #define TOUCH_INT_RCC_AHB1Periph RCC_AHB1Periph_GPIOH
+ #define TOUCH_INT_GPIO GPIOH
+ #define TOUCH_INT_GPIO_PIN GPIO_Pin_2 // PH.02
+
+ #define TOUCH_RST_RCC_AHB1Periph RCC_AHB1Periph_GPIOF
+ #define TOUCH_RST_GPIO GPIOF
+ #define TOUCH_RST_GPIO_PIN GPIO_Pin_10 // PF.10
+
+ #define TOUCH_INT_EXTI_LINE1 EXTI_Line2
+ #define TOUCH_INT_EXTI_IRQn1 EXTI2_IRQn
+ #define TOUCH_INT_EXTI_IRQHandler1 EXTI2_IRQHandler
+ #define TOUCH_INT_EXTI_PortSource EXTI_PortSourceGPIOH
+ #define TOUCH_INT_EXTI_PinSource1 EXTI_PinSource2
+
+ #define TOUCH_INT_STATUS() (GPIO_ReadInputDataBit(TOUCH_INT_GPIO, TOUCH_INT_GPIO_PIN))
+#else
+ #define TOUCH_INT_RCC_AHB1Periph 0
+ #define TOUCH_RST_RCC_AHB1Periph 0
#endif
// I2C Bus
@@ -588,8 +734,8 @@
#define HAPTIC_TIMER_COMPARE_VALUE HAPTIC_GPIO_TIMER->CCR2
#endif
-#if !defined(RADIO_T16)
-#define EXTERNAL_ANTENNA
+#if !defined(RADIO_FAMILY_T16)
+ #define EXTERNAL_ANTENNA
#endif
#define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2)
#define INTMODULE_PWR_GPIO GPIOA
@@ -615,6 +761,7 @@
#define INTMODULE_BOOTCMD_GPIO GPIOI
#define INTMODULE_BOOTCMD_GPIO_PIN GPIO_Pin_9 // PI.09
#endif
+#define INIT_INTMODULE_BOOTCMD_PIN() GPIO_ResetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN);
#if defined(PCBX10) || PCBREV >= 13
#define INTMODULE_RCC_APB1Periph RCC_APB1Periph_TIM2
#define INTMODULE_RCC_APB2Periph RCC_APB2Periph_USART1
@@ -634,6 +781,7 @@
// External Module
#define EXTMODULE_PWR_GPIO GPIOB
#define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_3 // PB.03
+#define EXTERNAL_MODULE_PWR_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
#if defined(PCBX10) && defined(PCBREV_EXPRESS)
#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1)
#define EXTMODULE_RCC_APB1Periph (RCC_APB1Periph_TIM2 | RCC_APB1Periph_USART3)
@@ -707,16 +855,16 @@
#define INTMODULE_HEARTBEAT
#define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD
#define INTMODULE_HEARTBEAT_GPIO GPIOD
-#define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_12
+#define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_12 // PD.12
#define INTMODULE_HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOD
#define INTMODULE_HEARTBEAT_EXTI_PinSource GPIO_PinSource12
#define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line12
#define INTMODULE_HEARTBEAT_EXTI_IRQn EXTI15_10_IRQn
#define INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER
#if defined(PXX2)
-#define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Falling
+ #define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Falling
#else
-#define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Rising
+ #define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Rising
#endif
// Trainer Port
@@ -753,6 +901,7 @@
// Bluetooth
#define STORAGE_BLUETOOTH
+#if defined(BLUETOOTH)
#define BT_RCC_APB2Periph RCC_APB2Periph_USART6
#define BT_USART USART6
#define BT_GPIO_AF GPIO_AF_USART6
@@ -763,6 +912,9 @@
#define BT_TX_GPIO_PinSource GPIO_PinSource14
#define BT_RX_GPIO_PinSource GPIO_PinSource9
#define BT_USART_IRQHandler USART6_IRQHandler
+#else
+#define BT_RCC_APB2Periph 0
+#endif
#if defined(PCBX12S)
#if PCBREV >= 13
#define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOG)
@@ -787,6 +939,7 @@
#if defined(PCBX12S)
#define GPS_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
#define GPS_RCC_APB1Periph RCC_APB1Periph_UART4
+ #define GPS_RCC_APB2Periph 0
#define GPS_USART UART4
#define GPS_GPIO_AF GPIO_AF_UART4
#define GPS_USART_IRQn UART4_IRQn
@@ -796,9 +949,10 @@
#define GPS_RX_GPIO_PIN GPIO_Pin_1 // PA.01
#define GPS_TX_GPIO_PinSource GPIO_PinSource0
#define GPS_RX_GPIO_PinSource GPIO_PinSource1
-#else
+#elif !defined(INTERNAL_GPS)
#define GPS_RCC_AHB1Periph 0
#define GPS_RCC_APB1Periph 0
+ #define GPS_RCC_APB2Periph 0
#endif
#endif // _HAL_H_
diff --git a/radio/src/targets/horus/keys_driver.cpp b/radio/src/targets/horus/keys_driver.cpp
old mode 100644
new mode 100755
index 9879135dd..7433ee58f
--- a/radio/src/targets/horus/keys_driver.cpp
+++ b/radio/src/targets/horus/keys_driver.cpp
@@ -24,7 +24,7 @@ uint32_t readKeys()
{
uint32_t result = 0;
-#if defined(PCBX12S)
+#if defined(KEYS_GPIO_REG_PGUP)
if (~KEYS_GPIO_REG_PGUP & KEYS_GPIO_PIN_PGUP)
result |= 1 << KEY_PGUP;
#endif
@@ -107,7 +107,7 @@ void readKeysAndTrims()
if ((keys_input || trims_input) && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) {
// on keypress turn the light on
- backlightOn();
+ resetBacklightTimeout();
}
}
@@ -204,16 +204,39 @@ void keysInit()
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+#if defined(KEYS_GPIOA_PINS)
+ INIT_KEYS_PINS(GPIOA);
+#endif
+
+#if defined(KEYS_GPIOB_PINS)
INIT_KEYS_PINS(GPIOB);
+#endif
#if defined(KEYS_GPIOC_PINS)
INIT_KEYS_PINS(GPIOC);
#endif
+#if defined(KEYS_GPIOD_PINS)
INIT_KEYS_PINS(GPIOD);
+#endif
+
+#if defined(KEYS_GPIOE_PINS)
INIT_KEYS_PINS(GPIOE);
+#endif
+
+#if defined(KEYS_GPIOG_PINS)
INIT_KEYS_PINS(GPIOG);
+#endif
+
+#if defined(KEYS_GPIOH_PINS)
INIT_KEYS_PINS(GPIOH);
+#endif
+
+#if defined(KEYS_GPIOI_PINS)
INIT_KEYS_PINS(GPIOI);
+#endif
+
+#if defined(KEYS_GPIOJ_PINS)
INIT_KEYS_PINS(GPIOJ);
+#endif
}
diff --git a/radio/src/targets/horus/lcd_driver.cpp b/radio/src/targets/horus/lcd_driver.cpp
index 110db0007..751aa88cd 100644
--- a/radio/src/targets/horus/lcd_driver.cpp
+++ b/radio/src/targets/horus/lcd_driver.cpp
@@ -20,14 +20,25 @@
#include "opentx.h"
-#define HBP 42
-#define VBP 12
+#if defined(RADIO_T18)
+ #define HBP 43
+ #define VBP 12
-#define HSW 2
-#define VSW 10
+ #define HSW 2
+ #define VSW 4
-#define HFP 3
-#define VFP 2
+ #define HFP 8
+ #define VFP 8
+#else
+ #define HBP 42
+ #define VBP 12
+
+ #define HSW 2
+ #define VSW 10
+
+ #define HFP 3
+ #define VFP 2
+#endif
#define LCD_FIRST_LAYER 0
#define LCD_SECOND_LAYER 1
@@ -41,7 +52,12 @@ uint32_t CurrentLayer = LCD_FIRST_LAYER;
#define NRST_LOW() do { LCD_GPIO_NRST->BSRRH = LCD_GPIO_PIN_NRST; } while(0)
#define NRST_HIGH() do { LCD_GPIO_NRST->BSRRL = LCD_GPIO_PIN_NRST; } while(0)
-static void LCD_AF_GPIOConfig(void)
+inline bool coordsWithinScreen(coord_t x, coord_t y, coord_t w, coord_t h)
+{
+ return x >= 0 && y >= 0 && x + w <= LCD_W && y + h <= LCD_H;
+}
+
+static void LCD_AF_GPIOConfig()
{
GPIO_InitTypeDef GPIO_InitStructure;
@@ -137,6 +153,9 @@ static void delay3(uint32_t nCount)
static void lcd_reset(void)
{
+#if defined(RADIO_T18) // T18 screen has issues if NRST is ever brought low
+ NRST_HIGH();
+#else
NRST_HIGH();
delay3(1);
@@ -145,6 +164,7 @@ static void lcd_reset(void)
NRST_HIGH();
delay3(30);
+#endif
}
void LCD_Init_LTDC(void)
@@ -378,11 +398,14 @@ void lcdInit(void)
void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
{
-#if defined(PCBX10)
+#if defined(LCD_VERTICAL_INVERT)
x = destw - (x + w);
y = desth - (y + h);
#endif
+ if (dest == displayBuf && !coordsWithinScreen(x, y, w, h))
+ return;
+
DMA2D_DeInit();
DMA2D_InitTypeDef DMA2D_InitStruct;
@@ -407,13 +430,16 @@ void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, ui
void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h)
{
-#if defined(PCBX10)
+#if defined(LCD_VERTICAL_INVERT)
x = destw - (x + w);
y = desth - (y + h);
srcx = srcw - (srcx + w);
srcy = srch - (srcy + h);
#endif
+ if (dest == displayBuf && !coordsWithinScreen(x, y, w, h))
+ return;
+
DMA2D_DeInit();
DMA2D_InitTypeDef DMA2D_InitStruct;
@@ -447,13 +473,16 @@ void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x,
void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h)
{
-#if defined(PCBX10)
+#if defined(LCD_VERTICAL_INVERT)
x = destw - (x + w);
y = desth - (y + h);
srcx = srcw - (srcx + w);
srcy = srch - (srcy + h);
#endif
+ if (dest == displayBuf && !coordsWithinScreen(x, y, w, h))
+ return;
+
DMA2D_DeInit();
DMA2D_InitTypeDef DMA2D_InitStruct;
diff --git a/radio/src/targets/horus/pwr_driver.cpp b/radio/src/targets/horus/pwr_driver.cpp
deleted file mode 100644
index aa9e13497..000000000
--- a/radio/src/targets/horus/pwr_driver.cpp
+++ /dev/null
@@ -1,109 +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 "board.h"
-#include "storage/rtc_backup.h"
-
-void pwrInit()
-{
- GPIO_InitTypeDef GPIO_InitStructure;
-
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
-
- // Internal module PWR
- GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN);
- GPIO_InitStructure.GPIO_Pin = INTMODULE_PWR_GPIO_PIN;
- GPIO_Init(INTMODULE_PWR_GPIO, &GPIO_InitStructure);
-
- // External module PWR
- GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
- GPIO_InitStructure.GPIO_Pin = EXTMODULE_PWR_GPIO_PIN;
- GPIO_Init(EXTMODULE_PWR_GPIO, &GPIO_InitStructure);
-
-#if defined(INTMODULE_BOOTCMD_GPIO)
- GPIO_ResetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN);
- GPIO_InitStructure.GPIO_Pin = INTMODULE_BOOTCMD_GPIO_PIN;
- GPIO_Init(INTMODULE_BOOTCMD_GPIO, &GPIO_InitStructure);
-#endif
-
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
-
- // PWR SWITCH
- GPIO_InitStructure.GPIO_Pin = PWR_SWITCH_GPIO_PIN;
- GPIO_Init(PWR_SWITCH_GPIO, &GPIO_InitStructure);
-
- // PCBREV
-#if defined(PCBREV_GPIO_PIN)
- GPIO_InitStructure.GPIO_Pin = PCBREV_GPIO_PIN;
- GPIO_Init(PCBREV_GPIO, &GPIO_InitStructure);
- hardwareOptions.pcbrev = PCBREV_VALUE();
-#endif
-
- // SD-DETECT PIN
- GPIO_ResetBits(SD_PRESENT_GPIO, SD_PRESENT_GPIO_PIN);
- GPIO_InitStructure.GPIO_Pin = SD_PRESENT_GPIO_PIN;
- GPIO_Init(SD_PRESENT_GPIO, &GPIO_InitStructure);
-
- // TRAINER DETECT PIN
- GPIO_InitStructure.GPIO_Pin = TRAINER_DETECT_GPIO_PIN;
- GPIO_Init(TRAINER_DETECT_GPIO, &GPIO_InitStructure);
-}
-
-void pwrOn()
-{
- // we keep the init of the PIN to have pwrOn as quick as possible
-
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_Init(PWR_ON_GPIO, &GPIO_InitStructure);
-
- GPIO_SetBits(PWR_ON_GPIO, PWR_ON_GPIO_PIN);
-}
-
-void pwrOff()
-{
- GPIO_ResetBits(PWR_ON_GPIO, PWR_ON_GPIO_PIN);
-}
-
-bool pwrPressed()
-{
- return GPIO_ReadInputDataBit(PWR_ON_GPIO, PWR_SWITCH_GPIO_PIN) == Bit_RESET;
-}
-
-void pwrResetHandler()
-{
- RCC->AHB1ENR |= PWR_RCC_AHB1Periph;
-
- // these two NOPs are needed (see STM32F errata sheet) before the peripheral
- // register can be written after the peripheral clock was enabled
- __ASM volatile ("nop");
- __ASM volatile ("nop");
-
- if (WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
- pwrOn();
- }
-}
diff --git a/radio/src/targets/horus/telemetry_driver.cpp b/radio/src/targets/horus/telemetry_driver.cpp
index ecd73b6ab..23318dd7e 100644
--- a/radio/src/targets/horus/telemetry_driver.cpp
+++ b/radio/src/targets/horus/telemetry_driver.cpp
@@ -45,7 +45,8 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
USART_DeInit(TELEMETRY_USART);
return;
}
-
+ //deinit inverted mode
+ telemetryPortInvertedInit(0);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TELEMETRY_DMA_TX_Stream_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
@@ -136,6 +137,9 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
// soft serial vars
static uint8_t rxBitCount;
static uint8_t rxByte;
+// single bit length expresses in half us
+static uint16_t bitLength;
+static uint16_t probeTimeFromStartBit;
void telemetryPortInvertedInit(uint32_t baudrate)
{
@@ -155,8 +159,21 @@ void telemetryPortInvertedInit(uint32_t baudrate)
rxBitCount = 0;
+ switch(baudrate) {
+ case 115200:
+ bitLength = 17;
+ probeTimeFromStartBit = 23; //because pin is not probed immediately
+ break;
+ case 57600:
+ bitLength = 35; //34 was used before - I prefer to use use 35 because of lower error
+ probeTimeFromStartBit = 48; // 48 used in original implementation
+ break;
+ default:
+ bitLength = 2000000/baudrate; //because of 0,5 us tick
+ probeTimeFromStartBit = 3000000/baudrate;
+ }
+
// configure bit sample timer
- RCC->APB2ENR |= RCC_APB2ENR_TIM11EN;
TELEMETRY_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS
TELEMETRY_TIMER->CCER = 0;
TELEMETRY_TIMER->CCMR1 = 0;
@@ -197,7 +214,7 @@ void telemetryPortInvertedRxBit()
{
if (rxBitCount < 8) {
if (rxBitCount == 0) {
- TELEMETRY_TIMER->ARR = 34;
+ TELEMETRY_TIMER->ARR = bitLength;
rxByte = 0;
}
else {
@@ -210,7 +227,6 @@ void telemetryPortInvertedRxBit()
++rxBitCount;
}
else if (rxBitCount == 8) {
-
telemetryNoDMAFifo.push(rxByte);
rxBitCount = 0;
@@ -361,7 +377,7 @@ extern "C" void TELEMETRY_EXTI_IRQHandler(void)
if (rxBitCount == 0) {
- TELEMETRY_TIMER->ARR = 48; // 1,5 cycle from start at 57600bps
+ TELEMETRY_TIMER->ARR = probeTimeFromStartBit; // 1,5 cycle from start at 57600bps
TELEMETRY_TIMER->CR1 |= TIM_CR1_CEN;
// disable start bit interrupt
diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp
new file mode 100644
index 000000000..5c4929e95
--- /dev/null
+++ b/radio/src/targets/horus/tp_gt911.cpp
@@ -0,0 +1,412 @@
+/*
+ * 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 "tp_gt911.h"
+
+uint8_t touchGT911Flag = 0;
+uint8_t touchPanelEvent = 0;
+struct TouchData touchData;
+struct TouchState touchState;
+
+void GT911_INT_Change(void)
+{
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ GPIO_InitStructure.GPIO_Pin = TOUCH_INT_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+ GPIO_Init(TOUCH_INT_GPIO, &GPIO_InitStructure);
+}
+
+uint8_t GT911_Send_Cfg(uint8_t mode)
+{
+ uint8_t buf[2];
+ uint8_t i = 0;
+ buf[0] = 0;
+ buf[1] = mode;
+ for (i = 0; i < sizeof(GT911_Cfg); i++)
+ buf[0] += GT911_Cfg[i];//check sum
+
+ buf[0] = (~buf[0]) + 1;
+ gt911WriteRegister(GT_CFGS_REG, (uint8_t *) GT911_Cfg, sizeof(GT911_Cfg));//
+ gt911WriteRegister(GT_CHECK_REG, buf, 2);//write checksum
+ return 0;
+}
+
+static void I2C_Config(void)
+{
+ GPIO_InitTypeDef GPIO_InitStructure;
+ RCC_AHB1PeriphClockCmd(I2C_RCC_AHB1Periph, ENABLE);
+ GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN | I2C_SDA_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_Init(I2C_GPIO, &GPIO_InitStructure);
+
+ GPIO_SetBits(I2C_GPIO, I2C_SCL_GPIO_PIN | I2C_SDA_GPIO_PIN);
+}
+
+static void TOUCH_AF_ExtiStop(void)
+{
+ SYSCFG_EXTILineConfig(TOUCH_INT_EXTI_PortSource, TOUCH_INT_EXTI_PinSource1);
+
+ EXTI_InitTypeDef EXTI_InitStructure;
+ EXTI_StructInit(&EXTI_InitStructure);
+ EXTI_InitStructure.EXTI_Line = TOUCH_INT_EXTI_LINE1;
+ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
+ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
+ EXTI_InitStructure.EXTI_LineCmd = DISABLE;
+ EXTI_Init(&EXTI_InitStructure);
+
+
+ NVIC_InitTypeDef NVIC_InitStructure;
+ NVIC_InitStructure.NVIC_IRQChannel = TOUCH_INT_EXTI_IRQn1;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 9;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
+ NVIC_Init(&NVIC_InitStructure);
+}
+
+static void TOUCH_AF_ExtiConfig(void)
+{
+ SYSCFG_EXTILineConfig(TOUCH_INT_EXTI_PortSource, TOUCH_INT_EXTI_PinSource1);
+
+ EXTI_InitTypeDef EXTI_InitStructure;
+ EXTI_StructInit(&EXTI_InitStructure);
+ EXTI_InitStructure.EXTI_Line = TOUCH_INT_EXTI_LINE1;
+ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
+ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
+ EXTI_InitStructure.EXTI_LineCmd = ENABLE;
+ EXTI_Init(&EXTI_InitStructure);
+
+
+ NVIC_InitTypeDef NVIC_InitStructure;
+ NVIC_InitStructure.NVIC_IRQChannel = TOUCH_INT_EXTI_IRQn1;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 9;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&NVIC_InitStructure);
+}
+
+static void TOUCH_AF_GPIOConfig(void)
+{
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.GPIO_Pin = TOUCH_RST_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_Init(TOUCH_RST_GPIO, &GPIO_InitStructure);
+
+ GPIO_ResetBits(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN);
+
+ GPIO_InitStructure.GPIO_Pin = TOUCH_INT_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_Init(TOUCH_INT_GPIO, &GPIO_InitStructure);
+
+ GPIO_ResetBits(TOUCH_INT_GPIO, TOUCH_INT_GPIO_PIN);
+}
+
+void SDA_IN(void)
+{
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.GPIO_Pin = I2C_SDA_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_Init(I2C_GPIO, &GPIO_InitStructure);
+}
+
+void SDA_OUT(void)
+{
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.GPIO_Pin = I2C_SDA_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_Init(I2C_GPIO, &GPIO_InitStructure);
+}
+
+void I2C_Start(void)
+{
+ SDA_OUT();
+ I2C_SDA_H();
+ I2C_SCL_H();
+ delay_us(2);
+ I2C_SDA_L();//START:when CLK is high,DATA change form high to low
+ delay_us(2);
+ I2C_SCL_L();//
+ delay_us(2);
+}
+
+void I2C_Stop(void)
+{
+ SDA_OUT();
+ I2C_SCL_L();
+ I2C_SDA_L();//STOP:when CLK is high DATA change form low to high
+ delay_us(2);
+ I2C_SCL_H();
+ I2C_SDA_H();//
+ delay_us(2);
+}
+
+uint8_t I2C_Wait_Ack(void)
+{
+ uint8_t ucErrTime = 0;
+ SDA_IN();
+ I2C_SDA_H();
+ delay_us(2);
+ I2C_SCL_H();
+ while (READ_SDA) {
+ ucErrTime++;
+ if (ucErrTime > 166) {
+ I2C_Stop();
+ return 1;
+ }
+ delay_us(1);
+ }
+ I2C_SDA_L();
+ I2C_SCL_L();
+ return 0;
+}
+
+void I2C_Ack(void)
+{
+ I2C_SCL_L();
+ SDA_OUT();
+ I2C_SDA_L();
+ delay_us(2);
+ I2C_SCL_H();
+ delay_us(2);
+ I2C_SCL_L();
+}
+
+void I2C_NAck(void)
+{
+ I2C_SCL_L();
+ SDA_OUT();
+ I2C_SDA_H();
+ delay_us(2);
+ I2C_SCL_H();
+ delay_us(2);
+ I2C_SCL_L();
+}
+
+void I2C_Send_Byte(uint8_t txd)
+{
+ uint8_t t;
+
+ SDA_OUT();
+ I2C_SCL_L();
+ for (t = 0; t < 8; t++) {
+ if ((txd & 0x80) >> 7)
+ I2C_SDA_H();
+ else
+ I2C_SDA_L();
+ txd <<= 1;
+ delay_us(1);
+ I2C_SCL_H();
+ delay_us(2);
+ I2C_SCL_L();
+ delay_us(1);
+ }
+}
+
+uint8_t I2C_Read_Byte(unsigned char ack)
+{
+ unsigned char i, receive = 0;
+
+ SDA_IN();
+ for (i = 0; i < 8; i++) {
+ I2C_SCL_L();
+ delay_us(2);
+ I2C_SCL_H();
+ receive <<= 1;
+ if (READ_SDA)receive++;
+ delay_us(1);
+ }
+ if (!ack)
+ I2C_NAck();
+ else
+ I2C_Ack();
+ return receive;
+}
+
+uint8_t gt911WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len)
+{
+ {
+ uint8_t i;
+ uint8_t ret = 0;
+
+ I2C_Start();
+ I2C_Send_Byte(GT_CMD_WR); //send cmd
+ I2C_Wait_Ack();
+ I2C_Send_Byte(reg >> 8); //send hi
+ I2C_Wait_Ack();
+ I2C_Send_Byte(reg & 0XFF); //send low
+ I2C_Wait_Ack();
+ for (i = 0; i < len; i++) {
+ I2C_Send_Byte(buf[i]);
+ ret = I2C_Wait_Ack();
+ if (ret)break;
+ }
+ I2C_Stop();
+
+ return ret;
+ }
+}
+
+void gt911ReadRegister(u16 reg, uint8_t * buf, uint8_t len)
+{
+ uint8_t i;
+
+ I2C_Start();
+ I2C_Send_Byte(GT_CMD_WR); //send addr
+ I2C_Wait_Ack();
+ I2C_Send_Byte(reg >> 8); //send hi
+ I2C_Wait_Ack();
+ I2C_Send_Byte(reg & 0XFF); //send low
+ I2C_Wait_Ack();
+ I2C_Start();
+ I2C_Send_Byte(GT_CMD_RD); //send rd
+ I2C_Wait_Ack();
+
+ for (i = 0; i < len; i++) {
+ buf[i] = I2C_Read_Byte(i == (len - 1) ? 0 : 1); //send data
+ }
+ I2C_Stop();
+}
+
+void touchPanelDeInit(void)
+{
+ TOUCH_AF_ExtiStop();
+}
+
+bool touchPanelInit(void)
+{
+ uint8_t tmp[4] = {0};
+
+ TRACE("Touchpanel init start ...");
+
+ TOUCH_AF_GPIOConfig(); //SET RST=OUT INT=OUT INT=LOW
+ I2C_Config();
+
+ TPRST_LOW();
+ TPINT_HIGH();
+ delay_us(200);
+
+ TPRST_HIGH();
+ delay_ms(6);
+
+ TPINT_LOW();
+ delay_ms(55);
+
+ GT911_INT_Change(); //Set INT INPUT INT=LOW
+
+ delay_ms(50);
+
+ TRACE("Reading Touch registry");
+ gt911ReadRegister(GT_PID_REG, tmp, 4);
+
+ if (strcmp((char *) tmp, "911") == 0) //ID==9147
+ {
+ TRACE("GT911 chip detected");
+ tmp[0] = 0X02;
+ gt911WriteRegister(GT_CTRL_REG, tmp, 1);
+ gt911ReadRegister(GT_CFGS_REG, tmp, 1);
+
+ TRACE("Chip config Ver:%x\r\n",tmp[0]);
+ if (tmp[0] < GT911_CFG_NUMER) //Config ver
+ {
+ TRACE("Sending new config %d", GT911_CFG_NUMER);
+ GT911_Send_Cfg(1);
+ }
+
+ delay_ms(10);
+ tmp[0] = 0X00;
+ gt911WriteRegister(GT_CTRL_REG, tmp, 1); //end reset
+ touchGT911Flag = true;
+
+ TOUCH_AF_ExtiConfig();
+
+ return true;
+ }
+ TRACE("GT911 chip NOT FOUND");
+ return false;
+}
+
+void touchPanelRead()
+{
+ uint8_t state = 0;
+ gt911ReadRegister(GT911_READ_XY_REG, &state, 1);
+
+ touchPanelEvent = false;
+
+ if ((state & 0x80u) == 0x00) {
+ // not ready
+ return;
+ }
+
+ uint8_t pointsCount = (state & 0x0Fu);
+
+ if (pointsCount > 0 && pointsCount < GT911_MAX_TP) {
+ gt911ReadRegister(GT911_READ_XY_REG + 1, touchData.data, pointsCount * sizeof(TouchPoint));
+ if (touchData.pointsCount == 0) {
+ touchState.event = TE_DOWN;
+ touchState.startX = touchState.x = touchData.points[0].x;
+ touchState.startY = touchState.y = touchData.points[0].y;
+ }
+ else {
+ touchState.deltaX = touchData.points[0].x - touchState.x;
+ touchState.deltaY = touchData.points[0].y - touchState.y;
+ if (touchState.event == TE_SLIDE || abs(touchState.deltaX) >= SLIDE_RANGE || abs(touchState.deltaY) >= SLIDE_RANGE) {
+ touchState.event = TE_SLIDE;
+ touchState.x = touchData.points[0].x;
+ touchState.y = touchData.points[0].y;
+ }
+ }
+ touchData.pointsCount = pointsCount;
+ }
+ else {
+ if (touchData.pointsCount > 0) {
+ touchData.pointsCount = 0;
+ if (touchState.event == TE_SLIDE)
+ touchState.event = TE_SLIDE_END;
+ else
+ touchState.event = TE_UP;
+ }
+ }
+
+ uint8_t zero = 0;
+ gt911WriteRegister(GT911_READ_XY_REG, &zero, 1);
+}
+
+extern "C" void TOUCH_INT_EXTI_IRQHandler1(void)
+{
+ if (EXTI_GetITStatus(TOUCH_INT_EXTI_LINE1) != RESET) {
+ TRACE("TI");
+ touchPanelEvent = 1;
+ EXTI_ClearITPendingBit(TOUCH_INT_EXTI_LINE1);
+ }
+}
diff --git a/radio/src/targets/horus/tp_gt911.h b/radio/src/targets/horus/tp_gt911.h
new file mode 100644
index 000000000..2b5f7d32c
--- /dev/null
+++ b/radio/src/targets/horus/tp_gt911.h
@@ -0,0 +1,296 @@
+/*
+ * 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 _FT5X06_H_
+#define _FT5X06_H_
+
+#include "opentx.h"
+#include "touch.h"
+
+#define HAS_TOUCH_PANEL() touchGT911Flag == true
+
+bool touchPanelInit();
+void touchPanelDeInit();
+
+extern uint8_t touchGT911Flag;
+extern uint8_t touchPanelEvent;
+
+uint8_t gt911WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len);
+void gt911ReadRegister(uint16_t reg, uint8_t * buf, uint8_t len);
+void touchPanelRead();
+
+#define GT911_MAX_TP 5
+#define GT911_CFG_NUMER 0x6A
+
+//GT911 param table
+const uint8_t GT911_Cfg[] =
+{
+ GT911_CFG_NUMER, // 0x8047 Config version
+ 0xE0, // 0x8048 X output map : x 480
+ 0x01,
+ 0x10, // 0x804A Y ouptut max : y 272
+ 0x01,
+ GT911_MAX_TP, // 0x804C Touch number
+ 0x3C, // 0x804D Module switch 1 : bit4= xy change Int mode
+ 0x20, // 0x804E Module switch 2
+ 0x22, // 0x804F Shake_Count
+ 0x0A, // 0x8050 Filter
+ 0x28, // 0x8051 Larger touch
+ 0x0F, // 0x8052 Noise reduction
+ 0x5A, // 0x8053 Screen touch level
+ 0x3C, // 0x8054 Screen touch leave
+ 0x03, // 0x8055 Low power control
+ 0x05, // 0x8056 Refresh rate
+ 0x00, // 0x8057 X threshold
+ 0x00, // 0x8058 Y threshold
+ 0x00, // 0x8059 Reserved
+ 0x00, // 0x805A Reserved
+ 0x11, // 0x805B Space (top, bottom)
+ 0x11, // 0x805C Space (left, right)
+ 0x08, // 0x805D Mini filter
+ 0x18, // 0x805E Strech R0
+ 0x1A, // 0x805F Strech R1
+ 0x1E, // 0x8060 Strech R2
+ 0x14, // 0x8061 Strech RM
+ 0x87, // 0x8062 Drv groupA num
+ 0x29, // 0x8063 Drv groupB num
+ 0x0A, // 0x8064 Sensor num
+ 0xCF, // 0x8065 FreqA factor
+ 0xD1, // 0x8066 FreqB factor
+ 0xB2, // 0x8067 Panel bit freq
+ 0x04,
+ 0x00, // 0x8069 Reserved
+ 0x00,
+ 0x00, // 0x806B Panel tx gain
+ 0xD8, // 0x806C Panel rx gain
+ 0x02, // 0x806D Panel dump shift
+ 0x1D, // 0x806E Drv frame control
+ 0x00, // 0x806F Charging level up
+ 0x01, // 0x8070 Module switch 3
+ 0x00, // 0x8071 Gesture distance
+ 0x00, // 0x8072 Gesture long press time
+ 0x00, // 0x8073 X/Y slope adjust
+ 0x00, // 0x8074 Gesture control
+ 0x00, // 0x8075 Gesture switch 1
+ 0x00, // 0x8076 Gesture switch 2
+ 0x00, // 0x8077 Gesture refresh rate
+ 0x00, // 0x8078 Gesture touch level
+ 0x00, // 0x8079 New green wake up level
+ 0xB4, // 0x807A Freq hopping start
+ 0xEF, // 0x807B Freq hopping end
+ 0x94, // 0x807C Noise detect time
+ 0xD5, // 0x807D Hopping flag
+ 0x02, // 0x807E Hopping flag
+ 0x07, // 0x807F Noise threshold
+ 0x00, // 0x8080 Nois min threshold old
+ 0x00, // 0x8081 Reserved
+ 0x04, // 0x8082 Hopping sensor group
+ 0x6E, // 0x8083 Hopping Seg1 normalize
+ 0xB9, // 0x8084 Hopping Seg1 factor
+ 0x00, // 0x8085 Main clock adjust
+ 0x6A, // 0x8086 Hopping Seg2 normalize
+ 0xC4, // 0x8087 Hopping Seg2 factor
+ 0x00, // 0x8088 Reserved
+ 0x66, // 0x8089 Hopping Seg3 normalize
+ 0xCF, // 0x808A Hopping Seg3 factor
+ 0x00, // 0x808B Reserved
+ 0x62, // 0x808C Hopping Seg4 normalize
+ 0xDB, // 0x808D Hopping Seg4 factor
+ 0x00, // 0x808E Reserved
+ 0x5E, // 0x808F Hopping Seg5 normalize
+ 0xE8, // 0x8090 Hopping Seg5 factor
+ 0x00, // 0x8091 Reserved
+ 0x5E, // 0x8092 Hopping Seg6 normalize
+ 0x00, // 0x8093 Key1
+ 0x00, // 0x8094 Key2
+ 0x00, // 0x8095 Key3
+ 0x00, // 0x8096 Key4
+ 0x00, // 0x8097 Key area
+ 0x00, // 0x8098 Key touch level
+ 0x00, // 0x8099 Key leave level
+ 0x00, // 0x809A Key sens
+ 0x00, // 0x809B Key sens
+ 0x00, // 0x809C Key restrain
+ 0x00, // 0x809D Key restrain time
+ 0x00, // 0x809E Large gesture touch
+ 0x00, // 0x809F Reserved
+ 0x00, // 0x80A0 Reserved
+ 0x00, // 0x80A1 Hotknot noise map
+ 0x00, // 0x80A2 Link threshold
+ 0x00, // 0x80A3 Pxy threshold
+ 0x00, // 0x80A4 GHot dump shift
+ 0x00, // 0x80A5 GHot rx gain
+ 0x00, // 0x80A6 Freg gain
+ 0x00, // 0x80A7 Freg gain 1
+ 0x00, // 0x80A8 Freg gain 2
+ 0x00, // 0x80A9 Freg gain 3
+ 0x00, // 0x80AA Reserved
+ 0x00, // 0x80AB Reserved
+ 0x00, // 0x80AC Reserved
+ 0x00, // 0x80AD Reserved
+ 0x00, // 0x80AE Reserved
+ 0x00, // 0x80AF Reserved
+ 0x00, // 0x80B0 Reserved
+ 0x00, // 0x80B1 Reserved
+ 0x00, // 0x80B2 Reserved
+ 0x00, // 0x80B3 Combine dis
+ 0x00, // 0x80B4 Split set
+ 0x00, // 0x80B5 Reserved
+ 0x00, // 0x80B6 Reserved
+ 0x14, // 0x80B7 Sensor CH0
+ 0x12, // 0x80B8 Sensor CH1
+ 0x10, // 0x80B9 Sensor CH2
+ 0x0E, // 0x80BA Sensor CH3
+ 0x0C, // 0x80BB Sensor CH4
+ 0x0A, // 0x80BC Sensor CH5
+ 0x08, // 0x80BD Sensor CH6
+ 0x06, // 0x80BE Sensor CH7
+ 0x04, // 0x80BF Sensor CH8
+ 0x02, // 0x80C0 Sensor CH9
+ 0xFF, // 0x80C1 Sensor CH10
+ 0xFF, // 0x80C2 Sensor CH11
+ 0xFF, // 0x80C3 Sensor CH12
+ 0xFF, // 0x80C4 Sensor CH13
+ 0x00, // 0x80C5 Reserved
+ 0x00, // 0x80C6 Reserved
+ 0x00, // 0x80C7 Reserved
+ 0x00, // 0x80C8 Reserved
+ 0x00, // 0x80C9 Reserved
+ 0x00, // 0x80CA Reserved
+ 0x00, // 0x80CB Reserved
+ 0x00, // 0x80CC Reserved
+ 0x00, // 0x80CD Reserved
+ 0x00, // 0x80CE Reserved
+ 0x00, // 0x80CF Reserved
+ 0x00, // 0x80D0 Reserved
+ 0x00, // 0x80D1 Reserved
+ 0x00, // 0x80D2 Reserved
+ 0x00, // 0x80D3 Reserved
+ 0x00, // 0x80D4 Reserved
+ 0x28, // 0x80D5 Driver CH0
+ 0x26, // 0x80D6 Driver CH1
+ 0x24, // 0x80D7 Driver CH2
+ 0x22, // 0x80D8 Driver CH3
+ 0x21, // 0x80D9 Driver CH4
+ 0x20, // 0x80DA Driver CH5
+ 0x1F, // 0x80DB Driver CH6
+ 0x1E, // 0x80DC Driver CH7
+ 0x1D, // 0x80DD Driver CH8
+ 0x0C, // 0x80DE Driver CH9
+ 0x0A, // 0x80DF Driver CH10
+ 0x08, // 0x80E0 Driver CH11
+ 0x06, // 0x80E1 Driver CH12
+ 0x04, // 0x80E2 Driver CH13
+ 0x02, // 0x80E3 Driver CH14
+ 0x00, // 0x80E4 Driver CH15
+ 0xFF, // 0x80E5 Driver CH16
+ 0xFF, // 0x80E6 Driver CH17
+ 0xFF, // 0x80E7 Driver CH18
+ 0xFF, // 0x80E8 Driver CH19
+ 0xFF, // 0x80E9 Driver CH20
+ 0xFF, // 0x80EA Driver CH21
+ 0xFF, // 0x80EB Driver CH22
+ 0xFF, // 0x80EC Driver CH23
+ 0xFF, // 0x80ED Driver CH24
+ 0xFF, // 0x80EE Driver CH25
+ 0x00, // 0x80EF Reserved
+ 0x00, // 0x80F0 Reserved
+ 0x00, // 0x80F1 Reserved
+ 0x00, // 0x80F2 Reserved
+ 0x00, // 0x80F3 Reserved
+ 0x00, // 0x80F4 Reserved
+ 0x00, // 0x80F5 Reserved
+ 0x00, // 0x80F6 Reserved
+ 0x00, // 0x80F7 Reserved
+ 0x00, // 0x80F8 Reserved
+ 0x00, // 0x80F9 Reserved
+ 0x00, // 0x80FA Reserved
+ 0x00, // 0x80FB Reserved
+ 0x00, // 0x80FC Reserved
+ 0x00, // 0x80FD Reserved
+ 0x00 // 0x80FE Reserved
+};
+
+//I2C
+#define GT_CMD_WR 0X28
+#define GT_CMD_RD 0X29
+
+#define SLAVE_Write_Address 0X28
+
+//GT9147
+#define GT_CTRL_REG 0X8040
+#define GT_CFGS_REG 0X8047
+#define GT_CHECK_REG 0X80FF
+#define GT_PID_REG 0X8140
+
+#define GT_GSTID_REG 0X814E
+#define GT_TP1_REG 0X8150
+#define GT_TP2_REG 0X8158
+#define GT_TP3_REG 0X8160
+#define GT_TP4_REG 0X8168
+#define GT_TP5_REG 0X8170
+
+#define GT911_READ_XY_REG 0x814E
+#define GT911_CLEARBUF_REG 0x814E
+#define GT911_CONFIG_REG 0x8047
+#define GT911_COMMAND_REG 0x8040
+#define GT911_PRODUCT_ID_REG 0x8140
+#define GT911_VENDOR_ID_REG 0x814A
+#define GT911_CONFIG_VERSION_REG 0x8047
+#define GT911_CONFIG_CHECKSUM_REG 0x80FF
+#define GT911_FIRMWARE_VERSION_REG 0x8144
+
+PACK(typedef struct
+{
+ uint8_t track;
+ uint16_t x;
+ uint16_t y;
+ uint16_t size;
+ uint8_t reserved;
+}) TouchPoint;
+
+PACK(struct TouchData
+{
+ uint8_t pointsCount;
+ union
+ {
+ TouchPoint points[GT911_MAX_TP];
+ uint8_t data[GT911_MAX_TP * sizeof(TouchPoint)];
+ };
+});
+
+extern struct TouchData touchData;
+
+#define TPRST_LOW() do { TOUCH_RST_GPIO->BSRRH = TOUCH_RST_GPIO_PIN; } while(0)
+#define TPRST_HIGH() do { TOUCH_RST_GPIO->BSRRL = TOUCH_RST_GPIO_PIN; } while(0)
+
+#define TPINT_LOW() do { TOUCH_INT_GPIO->BSRRH = TOUCH_INT_GPIO_PIN; } while(0)
+#define TPINT_HIGH() do { TOUCH_INT_GPIO->BSRRL = TOUCH_INT_GPIO_PIN; } while(0)
+
+
+#define I2C_SCL_L() do { I2C_GPIO->BSRRH = I2C_SCL_GPIO_PIN; } while(0)
+#define I2C_SCL_H() do { I2C_GPIO->BSRRL = I2C_SCL_GPIO_PIN; } while(0)
+
+#define I2C_SDA_L() do { I2C_GPIO->BSRRH = I2C_SDA_GPIO_PIN; } while(0)
+#define I2C_SDA_H() do { I2C_GPIO->BSRRL = I2C_SDA_GPIO_PIN; } while(0)
+
+#define READ_SDA GPIO_ReadInputDataBit(I2C_GPIO, I2C_SDA_GPIO_PIN)
+
+#endif // _FT5X06_H_
diff --git a/radio/src/targets/horus/trainer_driver.cpp b/radio/src/targets/horus/trainer_driver.cpp
index d5b34cc1e..83ec7a542 100644
--- a/radio/src/targets/horus/trainer_driver.cpp
+++ b/radio/src/targets/horus/trainer_driver.cpp
@@ -20,6 +20,10 @@
#include "opentx.h"
+#if defined(SBUS_TRAINER)
+Fifo trainerSbusFifo;
+#endif
+
void trainerSendNextFrame();
void init_trainer_ppm()
@@ -152,3 +156,15 @@ extern "C" void TRAINER_TIMER_IRQHandler()
trainerSendNextFrame();
}
}
+
+int sbusGetByte(uint8_t * byte)
+{
+ switch (currentTrainerMode) {
+#if defined(AUX_SERIAL)
+ case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT:
+ return trainerSbusFifo.pop(*byte);
+#endif
+ default:
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/radio/src/targets/horus/usb_charger_driver.cpp b/radio/src/targets/horus/usb_charger_driver.cpp
new file mode 100644
index 000000000..be27276f0
--- /dev/null
+++ b/radio/src/targets/horus/usb_charger_driver.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 "opentx.h"
+
+void usbChargerInit()
+{
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.GPIO_Pin = USB_CHARGER_GPIO_PIN | USB_USBDet_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_Init(USB_CHARGER_GPIO, &GPIO_InitStructure);
+}
+
+bool usbChargerLed()
+{
+ return GPIO_ReadInputDataBit(USB_CHARGER_GPIO, USB_USBDet_GPIO_PIN) == 0 ? 0 : GPIO_ReadInputDataBit(USB_CHARGER_GPIO, USB_CHARGER_GPIO_PIN) == Bit_RESET;
+}
+
diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp
index 4a948da00..f7e4f80e9 100644
--- a/radio/src/targets/simu/opentxsimulator.cpp
+++ b/radio/src/targets/simu/opentxsimulator.cpp
@@ -326,7 +326,7 @@ uint8_t OpenTxSimulator::getSensorInstance(uint16_t id, uint8_t defaultValue)
if (isTelemetryFieldAvailable(i)) {
TelemetrySensor * sensor = &g_model.telemetrySensors[i];
if (sensor->id == id) {
- return sensor->instance;
+ return sensor->frskyInstance.physID + 1;
}
}
}
@@ -605,16 +605,16 @@ class OpenTxSimulatorFactory: public SimulatorFactory
return Board::BOARD_HORUS_X12S;
#elif defined(PCBX10)
return Board::BOARD_X10;
+#elif defined(PCBX7ACCESS)
+ return Board::BOARD_TARANIS_X7_ACCESS;
#elif defined(PCBX7)
return Board::BOARD_TARANIS_X7;
#elif defined(PCBX9LITES)
return Board::BOARD_TARANIS_X9LITES;
#elif defined(PCBX9LITE)
return Board::BOARD_TARANIS_X9LITE;
-#elif defined(PCBTARANIS)
- return Board::BOARD_TARANIS_X9D;
#else
- return Board::BOARD_9X_M64;
+ return Board::BOARD_TARANIS_X9D;
#endif
}
};
diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp
index 12d5342d7..fa0122175 100644
--- a/radio/src/targets/simu/simpgmspace.cpp
+++ b/radio/src/targets/simu/simpgmspace.cpp
@@ -149,7 +149,7 @@ void simuSetKey(uint8_t key, bool state)
keysStates[key] = state;
}
-bool trimsStates[NUM_TRIMS * 2] = { false };
+bool trimsStates[NUM_TRIMS_KEYS] = { false };
void simuSetTrim(uint8_t trim, bool state)
{
// TRACE("simuSetTrim(%d, %d)", trim, state);
@@ -437,6 +437,10 @@ void sportUpdatePowerOff()
{
}
+void sportUpdatePowerInit()
+{
+}
+
void boardInit()
{
}
@@ -486,18 +490,18 @@ void pwrOff()
void readKeysAndTrims()
{
uint8_t index = 0;
- uint32_t keys_input = readKeys();
- for (uint8_t i = 1; i != uint8_t(1 << TRM_BASE); i <<= 1) {
- keys[index++].input(keys_input & i);
+ auto keysInput = readKeys();
+ for (auto mask = (1 << 0); mask < (1 << TRM_BASE); mask <<= 1) {
+ keys[index++].input(keysInput & mask);
}
- uint32_t trims_input = readTrims();
- for (uint8_t i = 1; i != uint8_t(1 << 8); i <<= 1) {
- keys[index++].input(trims_input & i);
+ auto trimsInput = readTrims();
+ for (auto mask = (1 << 0); mask < (1 << NUM_TRIMS_KEYS); mask <<= 1) {
+ keys[index++].input(trimsInput & mask);
}
- if (keys_input || trims_input) {
- backlightOn();
+ if (keysInput || trimsInput) {
+ resetBacklightTimeout();
}
}
@@ -515,7 +519,7 @@ uint32_t readKeys()
{
uint32_t result = 0;
- for (int i=0; i
+#include
#define sleep(x) Sleep(x)
#define strcasecmp _stricmp
#define strncasecmp _tcsnicmp
#define chdir _chdir
#define getcwd _getcwd
+inline int __builtin_clz(unsigned x)
+{
+ return (int)__lzcnt(x);
+}
#else
#include
#define sleep(x) usleep(1000*x)
diff --git a/radio/src/targets/simu/simudisk.cpp b/radio/src/targets/simu/simudisk.cpp
index 5e8dfcd82..220b23226 100644
--- a/radio/src/targets/simu/simudisk.cpp
+++ b/radio/src/targets/simu/simudisk.cpp
@@ -214,6 +214,13 @@ void sdInit(void)
f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append
}
#endif
+
+#if defined(LOG_BLUETOOTH)
+ f_open(&g_bluetoothFile, LOGS_PATH "/bluetooth.log", FA_OPEN_ALWAYS | FA_WRITE);
+ if (f_size(&g_bluetoothFile) > 0) {
+ f_lseek(&g_bluetoothFile, f_size(&g_bluetoothFile)); // append
+ }
+#endif
}
else {
TRACE_SIMPGMSPACE("f_mount() failed");
@@ -226,6 +233,9 @@ void sdDone()
audioQueue.stopSD();
#if defined(LOG_TELEMETRY)
f_close(&g_telemetryFile);
+#endif
+#if defined(LOG_BLUETOOTH)
+ f_close(&g_bluetoothFile);
#endif
f_mount(NULL, "", 0); // unmount SD
}
diff --git a/radio/src/targets/sky9x/CMakeLists.txt b/radio/src/targets/sky9x/CMakeLists.txt
index cb207e10a..4188444fe 100644
--- a/radio/src/targets/sky9x/CMakeLists.txt
+++ b/radio/src/targets/sky9x/CMakeLists.txt
@@ -10,6 +10,7 @@ set(TARGET_DIR sky9x)
set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} 9x_bitmaps)
set(PPM_LIMITS_SYMETRICAL YES)
set(PXX1 YES)
+set(AFHDS3 NO)
add_definitions(-DDISABLE_MULTI_UPDATE)
if(PCB STREQUAL 9XRPRO)
@@ -71,6 +72,7 @@ set(GUI_SRC
radio_diaganas.cpp
view_telemetry.cpp
view_about.cpp
+ view_channels.cpp
)
if(GVARS)
diff --git a/radio/src/targets/sky9x/board.h b/radio/src/targets/sky9x/board.h
index 952e48282..8b1c7275c 100644
--- a/radio/src/targets/sky9x/board.h
+++ b/radio/src/targets/sky9x/board.h
@@ -377,6 +377,7 @@ void pwrOn();
uint32_t pwrCheck();
bool pwrPressed();
#define UNEXPECTED_SHUTDOWN() (g_eeGeneral.unexpectedShutdown)
+#define pwrForcePressed() (false)
// EEPROM driver
#define EEPROM_SIZE (4*1024*1024/8)
@@ -410,4 +411,7 @@ bool telemetrySecondPortReceive(uint8_t & data);
extern const uint8_t BootCode[];
+// Pulses driver
+#define HARDWARE_EXTRA_MODULE
+
#endif // _BOARD_SKY9X_H_
diff --git a/radio/src/targets/sky9x/keys_driver.cpp b/radio/src/targets/sky9x/keys_driver.cpp
index 9f7dac244..f37cb52b5 100644
--- a/radio/src/targets/sky9x/keys_driver.cpp
+++ b/radio/src/targets/sky9x/keys_driver.cpp
@@ -109,7 +109,7 @@ void readKeysAndTrims()
if ((keys_input || trims_input) && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) {
// on keypress turn the light on
- backlightOn();
+ resetBacklightTimeout();
}
}
diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt
index 6715cc46a..b00c7dfba 100644
--- a/radio/src/targets/taranis/CMakeLists.txt
+++ b/radio/src/targets/taranis/CMakeLists.txt
@@ -2,6 +2,7 @@ option(SHUTDOWN_CONFIRMATION "Shutdown confirmation" OFF)
option(LCD_DUAL_BUFFER "Dual LCD Buffer" OFF)
option(PXX1 "PXX1 protocol support" ON)
option(PXX2 "PXX2 protocol support" OFF)
+option(AFHDS3 "AFHDS3 TX Module" OFF)
option(INTERNAL_MODULE_PPM "Support for PPM internal module" OFF)
option(AUTOUPDATE "Auto update internal chips from SD" OFF)
@@ -36,6 +37,8 @@ if(PCB STREQUAL X9E)
set(LCD_DRIVER lcd_driver_spi.cpp)
set(GVAR_SCREEN model_gvars.cpp)
set(STATUS_LEDS NO)
+ set(BLUETOOTH YES)
+ set(ROTARY_ENCODER YES)
elseif(PCB STREQUAL X9D+)
set(HAPTIC YES)
set(LUA_EXPORT lua_export_x9d)
@@ -52,39 +55,43 @@ elseif(PCB STREQUAL X9D+)
if (${PCBREV} STREQUAL 2019)
option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF)
option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON)
- set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
+ set(FLAVOUR x9d+2019)
set(CPU_TYPE STM32F4)
set(CPU_TYPE_FULL STM32F407xE) # for size report
+ set(LINKER_SCRIPT targets/taranis/stm32f4_flash.ld)
+ set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
startup_stm32f40_41xxx.s
)
- set(LINKER_SCRIPT targets/taranis/stm32f4_flash.ld)
+ add_definitions(-DRADIO_X9DP2019)
add_definitions(-DSTM32F40_41xxx)
add_definitions(-DSOFTWARE_VOLUME -DPWR_BUTTON_${PWR_BUTTON} -DHARDWARE_POWER_MANAGEMENT_UNIT)
set(STATUS_LEDS YES)
set(PXX2 ON)
set(PXX_FREQUENCY "HIGH")
- set(FLAVOUR x9d+2019)
+ set(BLUETOOTH YES)
+ set(ROTARY_ENCODER YES)
+ set(INTERNAL_MODULE_SERIAL YES)
else()
option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON)
option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF)
+ set(FLAVOUR x9d+)
set(CPU_TYPE STM32F2)
set(CPU_TYPE_FULL STM32F205xE) # for size report
set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld)
set(AUX_SERIAL_DRIVER ../common/arm/stm32/aux_serial_driver.cpp)
set(STATUS_LEDS NO)
- set(FLAVOUR x9d+)
endif()
elseif(PCB STREQUAL X9D)
option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON)
option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF)
+ set(FLAVOUR x9d)
set(CPU_TYPE STM32F2)
set(CPU_TYPE_FULL STM32F205xE) # for size report
set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld)
option(HAPTIC "Haptic support" OFF)
set(LUA_EXPORT lua_export_x9d)
- set(FLAVOUR x9d)
add_definitions(-DPCBX9D -DPCBX9)
add_definitions(-DEEPROM_VARIANT=0)
set(GUI_DIR 212x64)
@@ -97,34 +104,72 @@ elseif(PCB STREQUAL X9D)
set(STATUS_LEDS NO)
elseif(PCB STREQUAL X7)
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
- set(CPU_TYPE STM32F2)
- set(CPU_TYPE_FULL STM32F205xE) # for size report
- set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld)
set(HAPTIC YES)
- if(PCBREV STREQUAL T12)
- set(LUA_EXPORT lua_export_t12)
- set(FLAVOUR t12)
- set(NAVIGATION_TYPE 9x)
- add_definitions(-DRADIO_T12)
- add_definitions(-DEEPROM_VARIANT=0x4001)
- option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" OFF)
- else()
- option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON)
- option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF)
- set(LUA_EXPORT lua_export_x7)
- set(FLAVOUR x7)
- set(NAVIGATION_TYPE x7)
- add_definitions(-DRADIO_X7)
- add_definitions(-DEEPROM_VARIANT=0x4000)
- endif()
- add_definitions(-DPCBX7 -DSOFTWARE_VOLUME)
- add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
set(GUI_DIR 128x64)
set(BITMAPS_TARGET 9x_bitmaps)
set(FONTS_TARGET 9x_fonts_1bit)
set(LCD_DRIVER lcd_driver_spi.cpp)
set(GVAR_SCREEN model_gvars.cpp)
set(STATUS_LEDS YES)
+ add_definitions(-DPCBX7 -DSOFTWARE_VOLUME)
+ add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
+ if(PCBREV STREQUAL T12)
+ option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" OFF)
+ set(FLAVOUR t12)
+ set(NAVIGATION_TYPE 9x)
+ set(CPU_TYPE STM32F2)
+ set(CPU_TYPE_FULL STM32F205xE) # for size report
+ set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld)
+ set(LUA_EXPORT lua_export_t12)
+ add_definitions(-DRADIO_T12)
+ add_definitions(-DEEPROM_VARIANT=0x4001)
+ elseif(PCBREV STREQUAL ACCESS)
+ option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF)
+ option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON)
+ set(FLAVOUR x7access)
+ set(NAVIGATION_TYPE x7)
+ set(CPU_TYPE STM32F4)
+ set(CPU_TYPE_FULL STM32F407xE) # for size report
+ set(LINKER_SCRIPT targets/taranis/stm32f4_flash.ld)
+ set(LUA_EXPORT lua_export_x7access)
+ add_definitions(-DRADIO_X7ACCESS)
+ add_definitions(-DEEPROM_VARIANT=0x4000)
+ add_definitions(-DPCBREV=${PCBREV})
+ add_definitions(-DPCBX7ACCESS)
+ set(FIRMWARE_TARGET_SRC
+ ${FIRMWARE_TARGET_SRC}
+ startup_stm32f40_41xxx.s
+ )
+ add_definitions(-DSTM32F40_41xxx)
+ add_definitions(-DHARDWARE_POWER_MANAGEMENT_UNIT)
+ set(PXX2 ON)
+ set(PXX_FREQUENCY "HIGH")
+ set(BLUETOOTH YES)
+ set(ROTARY_ENCODER YES)
+ set(INTERNAL_MODULE_SERIAL YES)
+ else()
+ option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON)
+ option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF)
+ set(FLAVOUR x7)
+ set(NAVIGATION_TYPE x7)
+ set(CPU_TYPE STM32F2)
+ set(CPU_TYPE_FULL STM32F205xE) # for size report
+ set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld)
+ set(LUA_EXPORT lua_export_x7)
+ add_definitions(-DRADIO_X7)
+ add_definitions(-DEEPROM_VARIANT=0x4000)
+ set(BLUETOOTH YES)
+ add_definitions(-DBLUETOOTH_PROBE)
+ set(ROTARY_ENCODER YES)
+ if(DEFINED PCBREV_HARDCODED)
+ # This *can* be used to prevent messing with PA14 (SWCLK), so stlink can be used
+ # without interruptions.
+ if(NOT ${PCBREV_HARDCODED} MATCHES "^[0-1]$")
+ message(FATAL_ERROR "PCBREV_HARDCODED must be 0 or 1, not '${PCBREV_HARDCODED}'")
+ endif()
+ add_definitions(-DPCBREV_HARDCODED=${PCBREV_HARDCODED})
+ endif()
+ endif()
elseif(PCB STREQUAL X9LITE)
option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF)
option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON)
@@ -148,6 +193,8 @@ elseif(PCB STREQUAL X9LITE)
set(LCD_DRIVER lcd_driver_spi.cpp)
set(GVAR_SCREEN model_gvars.cpp)
set(STATUS_LEDS YES)
+ set(ROTARY_ENCODER YES)
+ set(INTERNAL_MODULE_SERIAL YES)
elseif(PCB STREQUAL X9LITES)
option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF)
option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON)
@@ -161,7 +208,7 @@ elseif(PCB STREQUAL X9LITES)
set(FLAVOUR x9lites)
add_definitions(-DBOARD_NAME="x9lites")
add_definitions(-DPCBX9LITES -DPCBX9LITE -DPCBX9 -DSOFTWARE_VOLUME -DHARDWARE_POWER_MANAGEMENT_UNIT)
- add_definitions(-DEEPROM_VARIANT=0x0800)
+ add_definitions(-DEEPROM_VARIANT=0x0801)
add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
set(PXX2 ON)
set(GUI_DIR 128x64)
@@ -171,6 +218,9 @@ elseif(PCB STREQUAL X9LITES)
set(LCD_DRIVER lcd_driver_spi.cpp)
set(GVAR_SCREEN model_gvars.cpp)
set(STATUS_LEDS YES)
+ set(BLUETOOTH YES)
+ set(ROTARY_ENCODER YES)
+ set(INTERNAL_MODULE_SERIAL YES)
elseif(PCB STREQUAL XLITE)
option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON)
option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF)
@@ -193,6 +243,8 @@ elseif(PCB STREQUAL XLITE)
set(LCD_DRIVER lcd_driver_spi.cpp)
set(GVAR_SCREEN model_gvars.cpp)
set(STATUS_LEDS YES)
+ set(BLUETOOTH YES)
+ set(INTERNAL_MODULE_SERIAL YES)
elseif(PCB STREQUAL XLITES)
option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF)
option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON)
@@ -215,9 +267,12 @@ elseif(PCB STREQUAL XLITES)
set(GVAR_SCREEN model_gvars.cpp)
set(STATUS_LEDS YES)
set(PXX2 ON)
+ set(BLUETOOTH YES)
+ set(GYRO YES)
+ set(INTERNAL_MODULE_SERIAL YES)
endif()
-if(PCB STREQUAL XLITES)
+if(GYRO)
add_definitions(-DGYRO)
set(TARGET_SRC
${TARGET_SRC}
@@ -229,7 +284,7 @@ if(PCB STREQUAL XLITES)
)
endif()
-if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES OR PCB STREQUAL X9LITE OR PCB STREQUAL X9LITES OR (PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019))
+if(INTERNAL_MODULE_SERIAL)
add_definitions(-DINTERNAL_MODULE_SERIAL)
if(PXX_FREQUENCY STREQUAL HIGH)
add_definitions(-DPXX_FREQUENCY_HIGH)
@@ -245,14 +300,14 @@ elseif(NOT (PCB STREQUAL X7 AND PCBREV STREQUAL T12))
)
endif()
-if(PCB STREQUAL X9E OR (PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019) OR (PCB STREQUAL X7 AND NOT (PCBREV STREQUAL T12)) OR PCB STREQUAL X9LITE OR PCB STREQUAL X9LITES)
+if(ROTARY_ENCODER)
set(TARGET_SRC
${TARGET_SRC}
../common/arm/stm32/rotary_encoder_driver.cpp
)
endif()
-if(PCB STREQUAL X9E OR (PCB STREQUAL X7 AND NOT PCBREV STREQUAL T12) OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES OR (PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019) OR PCB STREQUAL X9LITES)
+if(BLUETOOTH)
add_definitions(-DBLUETOOTH)
set(TARGET_SRC
${TARGET_SRC}
@@ -280,6 +335,7 @@ endif()
add_definitions(-DPCBTARANIS)
add_definitions(-DAUDIO -DVOICE -DRTCLOCK)
+add_definitions(-DSBUS_TRAINER)
set(SRC
${SRC}
@@ -333,7 +389,7 @@ set(FIRMWARE_TARGET_SRC
${LCD_DRIVER}
board.cpp
i2c_driver.cpp
- pwr_driver.cpp
+ ../common/arm/stm32/pwr_driver.cpp
../common/arm/loadboot.cpp
)
diff --git a/radio/src/targets/taranis/board.cpp b/radio/src/targets/taranis/board.cpp
index 2d7a980c7..521ab1d9b 100644
--- a/radio/src/targets/taranis/board.cpp
+++ b/radio/src/targets/taranis/board.cpp
@@ -62,6 +62,14 @@ void sportUpdatePowerOff()
{
GPIO_SPORT_UPDATE_PWR_GPIO_OFF(SPORT_UPDATE_PWR_GPIO, SPORT_UPDATE_PWR_GPIO_PIN);
}
+
+void sportUpdatePowerInit()
+{
+ if (g_eeGeneral.sportUpdatePower == 1)
+ sportUpdatePowerOn();
+ else
+ sportUpdatePowerOff();
+}
#endif
void boardInit()
@@ -113,10 +121,11 @@ void boardInit()
INTMODULE_RCC_APB2Periph |
EXTMODULE_RCC_APB2Periph |
TRAINER_MODULE_RCC_APB2Periph |
- BT_RCC_APB2Periph,
+ BT_RCC_APB2Periph |
+ TELEMETRY_RCC_APB2Periph,
ENABLE);
-#if defined(BLUETOOTH)
+#if defined(BLUETOOTH) && !defined(PCBX9E)
bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE, true);
#endif
diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h
index 07b7f3dba..62ad32a5f 100644
--- a/radio/src/targets/taranis/board.h
+++ b/radio/src/targets/taranis/board.h
@@ -22,8 +22,8 @@
#define _BOARD_H_
#include
-#include "../definitions.h"
-#include "../opentx_constants.h"
+#include "definitions.h"
+#include "opentx_constants.h"
#include "board_common.h"
#include "hal.h"
@@ -61,6 +61,13 @@ void boardOff();
void init2MhzTimer();
void init5msTimer();
+// PCBREV driver
+enum {
+ // X7
+ PCBREV_X7_STD = 0,
+ PCBREV_X7_40 = 1,
+};
+
// SD driver
#define BLOCK_SIZE 512 /* Block Size in Bytes */
#if !defined(SIMU) || defined(SIMU_DISKIO)
@@ -107,12 +114,16 @@ uint32_t isBootloaderStart(const uint8_t * buffer);
#define INTERNAL_MODULE_OFF() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
#endif
+#if !defined(PCBX9LITE) || defined(PCBX9LITES)
+ #define HARDWARE_INTERNAL_RAS
+#endif
+
#define EXTERNAL_MODULE_ON() EXTERNAL_MODULE_PWR_ON()
#if defined(EXTMODULE_USART)
-#define EXTERNAL_MODULE_OFF() extmoduleStop()
+ #define EXTERNAL_MODULE_OFF() extmoduleStop()
#else
-#define EXTERNAL_MODULE_OFF() EXTERNAL_MODULE_PWR_OFF()
+ #define EXTERNAL_MODULE_OFF() EXTERNAL_MODULE_PWR_OFF()
#endif
#if defined(RADIO_T12)
@@ -333,12 +344,16 @@ enum EnumSwitchesPositions
SW_SH1,
SW_SH2,
#endif
-#if defined(PCBX9DP) && PCBREV >= 2019
+#if defined(RADIO_X9DP2019)
SW_SI0,
SW_SI1,
SW_SI2,
#endif
-#if defined(PCBX7)
+#if defined(PCBX7ACCESS)
+ SW_SI0,
+ SW_SI1,
+ SW_SI2,
+#elif defined(PCBX7)
SW_SI0,
SW_SI1,
SW_SI2,
@@ -396,6 +411,11 @@ enum EnumSwitchesPositions
#define STORAGE_NUM_SWITCHES NUM_SWITCHES
#define DEFAULT_SWITCH_CONFIG (SWITCH_2POS << 10) + (SWITCH_2POS << 8) + (SWITCH_3POS << 6) + (SWITCH_3POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0)
#define DEFAULT_POTS_CONFIG (POT_WITHOUT_DETENT << 0) + (POT_WITHOUT_DETENT << 2); // S1 = pot without detent, S2 = pot with detent
+#elif defined(PCBX7ACCESS)
+ #define NUM_SWITCHES 7
+ #define STORAGE_NUM_SWITCHES 8
+ #define DEFAULT_SWITCH_CONFIG (SWITCH_TOGGLE << 10) + (SWITCH_2POS << 8) + (SWITCH_3POS << 6) + (SWITCH_3POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0)
+ #define DEFAULT_POTS_CONFIG (POT_WITHOUT_DETENT << 0) + (POT_WITH_DETENT << 2); // S1 = pot without detent, S2 = pot with detent
#elif defined(PCBX7)
#define NUM_SWITCHES 8
#define STORAGE_NUM_SWITCHES NUM_SWITCHES
@@ -417,7 +437,7 @@ enum EnumSwitchesPositions
#define DEFAULT_SWITCH_CONFIG (SWITCH_TOGGLE << 14) + (SWITCH_3POS << 12) + (SWITCH_2POS << 10) + (SWITCH_3POS << 8) + (SWITCH_3POS << 6) + (SWITCH_3POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0)
#define DEFAULT_POTS_CONFIG (POT_WITH_DETENT << 0) + (POT_WITH_DETENT << 2); // S1 = pot without detent, S2 = pot with detent
#define DEFAULT_SLIDERS_CONFIG (SLIDER_WITH_DETENT << 3) + (SLIDER_WITH_DETENT << 2) + (SLIDER_WITH_DETENT << 1) + (SLIDER_WITH_DETENT << 0)
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019)
#define NUM_SWITCHES 9
#define STORAGE_NUM_SWITCHES NUM_SWITCHES
#define DEFAULT_SWITCH_CONFIG (SWITCH_TOGGLE << 16) + (SWITCH_TOGGLE << 14) + (SWITCH_3POS << 12) + (SWITCH_2POS << 10) + (SWITCH_3POS << 8) + (SWITCH_3POS << 6) + (SWITCH_3POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0);
@@ -520,28 +540,27 @@ enum Analogs {
#define NUM_MOUSE_ANALOGS 0
#define STORAGE_NUM_MOUSE_ANALOGS 0
+#if defined(PCBXLITE)
+ #define NUM_TRIMS_KEYS 4
+#else
+ #define NUM_TRIMS_KEYS (NUM_TRIMS * 2)
+#endif
+
#if defined(STICKS_PWM)
#define NUM_PWMSTICKS 4
#define STICKS_PWM_ENABLED() (!hardwareOptions.sticksPwmDisabled)
void sticksPwmInit();
void sticksPwmRead(uint16_t * values);
extern volatile uint32_t pwm_interrupt_count; // TODO => reusable buffer (boot section)
- #define NUM_TRIMS_KEYS 4
#else
- #define NUM_TRIMS_KEYS 8
#define STICKS_PWM_ENABLED() false
#endif
-#if NUM_PWMSTICKS > 0
PACK(typedef struct {
+ uint8_t pcbrev:2;
uint8_t sticksPwmDisabled:1;
uint8_t pxx2Enabled:1;
}) HardwareOptions;
-#else
-PACK(typedef struct {
- uint8_t pxx2Enabled:1;
-}) HardwareOptions;
-#endif
extern HardwareOptions hardwareOptions;
@@ -607,7 +626,7 @@ extern uint16_t adcValues[NUM_ANALOGS];
#define BATT_SCALE 123
#elif defined(PCBX9LITE)
#define BATT_SCALE 117
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019)
#define BATT_SCALE 117
#else
#define BATT_SCALE 150
@@ -629,6 +648,7 @@ bool pwrPressed();
uint32_t pwrPressedDuration();
#endif
void pwrResetHandler();
+#define pwrForcePressed() false
#if defined(SIMU)
#define UNEXPECTED_SHUTDOWN() false
@@ -689,8 +709,10 @@ extern uint32_t telemetryErrors;
void telemetryPortInvertedInit(uint32_t baudrate);
// PCBREV driver
-#if defined(PCBX7)
- #define IS_PCBREV_40() (GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN) == Bit_SET)
+#if defined(PCBX7ACCESS)
+ #define HAS_SPORT_UPDATE_CONNECTOR() true
+#elif defined(PCBX7)
+ #define IS_PCBREV_40() (hardwareOptions.pcbrev == PCBREV_X7_40)
#define HAS_SPORT_UPDATE_CONNECTOR() IS_PCBREV_40()
#elif defined(SPORT_UPDATE_PWR_GPIO)
#define HAS_SPORT_UPDATE_CONNECTOR() true
@@ -703,12 +725,17 @@ void telemetryPortInvertedInit(uint32_t baudrate);
void sportUpdateInit();
void sportUpdatePowerOn();
void sportUpdatePowerOff();
+void sportUpdatePowerInit();
#define SPORT_UPDATE_POWER_ON() sportUpdatePowerOn()
#define SPORT_UPDATE_POWER_OFF() sportUpdatePowerOff()
+#define SPORT_UPDATE_POWER_INIT() sportUpdatePowerInit()
+#define IS_SPORT_UPDATE_POWER_ON() (GPIO_ReadInputDataBit(SPORT_UPDATE_PWR_GPIO, SPORT_UPDATE_PWR_GPIO_PIN) == Bit_SET)
#else
#define sportUpdateInit()
#define SPORT_UPDATE_POWER_ON()
#define SPORT_UPDATE_POWER_OFF()
+#define SPORT_UPDATE_POWER_INIT()
+#define IS_SPORT_UPDATE_POWER_ON() (false)
#endif
// Audio driver
@@ -759,7 +786,7 @@ void hapticOff();
void hapticOn();
#endif
-// Second serial port driver
+// Aux serial port driver
#if defined(AUX_SERIAL_GPIO)
#define DEBUG_BAUDRATE 115200
#define AUX_SERIAL
@@ -769,6 +796,8 @@ void auxSerialPutc(char c);
#define auxSerialTelemetryInit(protocol) auxSerialInit(UART_MODE_TELEMETRY, protocol)
void auxSerialSbusInit();
void auxSerialStop();
+#define AUX_SERIAL_POWER_ON()
+#define AUX_SERIAL_POWER_OFF()
#endif
// BT driver
@@ -780,16 +809,16 @@ void auxSerialStop();
#define BLUETOOTH_FACTORY_BAUDRATE 57600
#endif
#define BT_TX_FIFO_SIZE 64
-#define BT_RX_FIFO_SIZE 128
+#define BT_RX_FIFO_SIZE 256
void bluetoothInit(uint32_t baudrate, bool enable);
void bluetoothWriteWakeup();
uint8_t bluetoothIsWriting();
void bluetoothDisable();
-#if defined(PCBX9LITES)
+#if defined(PCBX9LITES) || defined(PCBX7ACCESS)
#define IS_BLUETOOTH_CHIP_PRESENT() (true)
#elif defined(PCBX9LITE)
#define IS_BLUETOOTH_CHIP_PRESENT() (false)
-#elif (defined(PCBX7) || defined(PCBXLITE)) && !defined(SIMU)
+#elif defined(BLUETOOTH_PROBE) && !defined(SIMU)
extern volatile uint8_t btChipPresent;
#define IS_BLUETOOTH_CHIP_PRESENT() (btChipPresent)
#else
diff --git a/radio/src/targets/taranis/bootloader/boot_menu.cpp b/radio/src/targets/taranis/bootloader/boot_menu.cpp
index 4a2eb1497..b1d1a9a50 100644
--- a/radio/src/targets/taranis/bootloader/boot_menu.cpp
+++ b/radio/src/targets/taranis/bootloader/boot_menu.cpp
@@ -21,28 +21,24 @@ void bootloaderDrawFilename(const char *str, uint8_t line, bool selected)
void bootloaderDrawScreen(BootloaderState st, int opt, const char *str)
{
lcdClear();
- lcdDrawText(0, 0, BOOTLOADER_TITLE, INVERS);
+ lcdDrawText(LCD_W / 2, 0, BOOTLOADER_TITLE, CENTERED);
+ lcdInvertLine(0);
if (st == ST_START) {
- lcdDrawTextAlignedLeft(2*FH, "\010Write Firmware");
- lcdDrawTextAlignedLeft(3*FH, "\010Restore EEPROM");
- lcdDrawTextAlignedLeft(4*FH, "\010Exit");
+ lcdDrawText(3*FW, 2*FH, "Write Firmware", opt == 0 ? INVERS : 0);
+ lcdDrawText(3*FW, 3*FH, "Restore EEPROM", opt == 1 ? INVERS : 0);
+ lcdDrawText(3*FW, 4*FH, "Exit", opt == 2 ? INVERS : 0);
-#if LCD_W >= 212
- lcdDrawTextAlignedLeft(6*FH, "\001Curr FW:");
- lcdDrawText(50, 6*FH, getOtherVersion(nullptr));
-#else
- lcdDrawTextAlignedLeft(6 * FH, "\001FW:");
+ lcdDrawText(LCD_W / 2, 5 * FH + FH / 2, STR_OR_PLUGIN_USB_CABLE, CENTERED);
- // Remove opentx- from string
- const char *other_ver = getOtherVersion(nullptr);
- if (strstr(other_ver, "opentx-"))
- other_ver = other_ver + 7;
- lcdDrawText(20, 6 * FH, other_ver);
+ // Remove "opentx-" from string
+ const char * vers = getFirmwareVersion();
+#if LCD_W < 212
+ if (strncmp(vers, "opentx-", 7) == 0)
+ vers += 7;
#endif
-
- lcdInvertLine(2 + opt);
- lcdDrawTextAlignedLeft(7 * FH, STR_OR_PLUGIN_USB_CABLE);
+ lcdDrawText(LCD_W / 2, 7 * FH, vers, CENTERED);
+ lcdInvertLine(7);
}
else if (st == ST_USB) {
lcdDrawTextAlignedLeft(4 * FH, STR_USB_CONNECTED);
@@ -65,11 +61,11 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char *str)
}
else if (opt == FC_OK) {
if (memoryType == MEM_FLASH) {
- const char * vers = getOtherVersion((char *) Block_buffer);
+ const char * vers = getFirmwareVersion((const char *)Block_buffer);
#if LCD_W < 212
- // Remove opentx- from string
- if (strstr(vers, "opentx-"))
- vers = vers + 7;
+ // Remove "opentx-" from string
+ if (strncmp(vers, "opentx-", 7) == 0)
+ vers += 7;
#endif
bootloaderDrawMsg(INDENT_WIDTH, vers, 0, false);
}
diff --git a/radio/src/targets/taranis/diskio.cpp b/radio/src/targets/taranis/diskio.cpp
index 94f190aa0..f7828f21d 100644
--- a/radio/src/targets/taranis/diskio.cpp
+++ b/radio/src/targets/taranis/diskio.cpp
@@ -978,10 +978,15 @@ void sdPoll10ms()
// TODO everything here should not be in the driver layer ...
FATFS g_FATFS_Obj;
+
#if defined(LOG_TELEMETRY)
FIL g_telemetryFile = {};
#endif
+#if defined(LOG_BLUETOOTH)
+FIL g_bluetoothFile = {};
+#endif
+
#if defined(BOOT)
void sdInit(void)
{
@@ -1016,6 +1021,13 @@ void sdMount()
f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append
}
#endif
+
+#if defined(LOG_BLUETOOTH)
+ f_open(&g_bluetoothFile, LOGS_PATH "/bluetooth.log", FA_OPEN_ALWAYS | FA_WRITE);
+ if (f_size(&g_bluetoothFile) > 0) {
+ f_lseek(&g_bluetoothFile, f_size(&g_bluetoothFile)); // append
+ }
+#endif
}
}
@@ -1025,6 +1037,9 @@ void sdDone()
audioQueue.stopSD();
#if defined(LOG_TELEMETRY)
f_close(&g_telemetryFile);
+#endif
+#if defined(LOG_BLUETOOTH)
+ f_close(&g_bluetoothFile);
#endif
f_mount(nullptr, "", 0); // unmount SD
}
diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp
index 19bd04525..0910f156e 100644
--- a/radio/src/targets/taranis/extmodule_driver.cpp
+++ b/radio/src/targets/taranis/extmodule_driver.cpp
@@ -278,7 +278,25 @@ void extmoduleSendNextFrame()
extmoduleSendBuffer(extmodulePulsesData.pxx2.getData(), extmodulePulsesData.pxx2.getSize());
break;
#endif
-
+#if defined(AFHDS3)
+ case PROTOCOL_CHANNELS_AFHDS3:
+ {
+#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)
+ extmoduleSendBuffer(extmodulePulsesData.afhds3.getData(), extmodulePulsesData.afhds3.getSize());
+#else
+ const uint16_t* dataPtr = extmodulePulsesData.afhds3.getData();
+ uint32_t dataSize = extmodulePulsesData.afhds3.getSize();
+ EXTMODULE_TIMER->CCR2 = dataPtr[dataSize -1] - 4000; // 2mS in advance
+ EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
+ EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
+ EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
+ EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(dataPtr);
+ EXTMODULE_TIMER_DMA_STREAM->NDTR = dataSize;
+ EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
+#endif
+ }
+ break;
+#endif
#if defined(SBUS) || defined(DSM2) || defined(MULTIMODULE)
case PROTOCOL_CHANNELS_SBUS:
EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? 0 : EXTMODULE_TIMER_OUTPUT_POLARITY); // reverse polarity for Sbus if needed
diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h
index 235e5eefb..65462c576 100644
--- a/radio/src/targets/taranis/hal.h
+++ b/radio/src/targets/taranis/hal.h
@@ -59,7 +59,7 @@
#define KEYS_GPIO_PIN_LEFT GPIO_Pin_7 // PD.07
#define KEYS_GPIO_REG_RIGHT GPIOD->IDR
#define KEYS_GPIO_PIN_RIGHT GPIO_Pin_3 // PD.03
-#elif defined(RADIO_X7)
+#elif defined(PCBX7)
#define KEYS_GPIO_REG_PAGE GPIOD->IDR
#define KEYS_GPIO_PIN_PAGE GPIO_Pin_3 // PD.03
#define KEYS_GPIO_REG_MENU GPIOD->IDR
@@ -77,7 +77,7 @@
#define KEYS_GPIO_PIN_EXIT GPIO_Pin_9 // PE.09
#define KEYS_GPIO_REG_ENTER GPIOE->IDR
#define KEYS_GPIO_PIN_ENTER GPIO_Pin_11 // PE.11
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019)
#define KEYS_GPIO_REG_MENU GPIOD->IDR
#define KEYS_GPIO_PIN_MENU GPIO_Pin_2 // PD.02
#define KEYS_GPIO_REG_EXIT GPIOD->IDR
@@ -115,7 +115,7 @@
#define ROTARY_ENCODER_EXTI_PortSource EXTI_PortSourceGPIOD
#define ROTARY_ENCODER_EXTI_PinSource1 EXTI_PinSource12
#define ROTARY_ENCODER_EXTI_PinSource2 EXTI_PinSource13
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019)
#define ROTARY_ENCODER_NAVIGATION
#define ROTARY_ENCODER_GPIO GPIOE
#define ROTARY_ENCODER_GPIO_PIN_A GPIO_Pin_10 // PE.10
@@ -128,7 +128,7 @@
#define ROTARY_ENCODER_EXTI_PortSource EXTI_PortSourceGPIOE
#define ROTARY_ENCODER_EXTI_PinSource1 EXTI_PinSource10
#define ROTARY_ENCODER_EXTI_PinSource2 EXTI_PinSource11
-#elif defined(RADIO_X7)
+#elif defined(RADIO_X7) || defined(RADIO_X7ACCESS)
#define ROTARY_ENCODER_NAVIGATION
#define ROTARY_ENCODER_GPIO GPIOE
#define ROTARY_ENCODER_GPIO_PIN_A GPIO_Pin_9 // PE.09
@@ -193,6 +193,23 @@
#define TRIMS_GPIO_PIN_LVU GPIO_Pin_0 // PB.00
#define TRIMS_GPIO_REG_LVD GPIOB->IDR
#define TRIMS_GPIO_PIN_LVD GPIO_Pin_1 // PB.01
+#elif defined(RADIO_X7ACCESS)
+ #define TRIMS_GPIO_REG_LHR GPIOD->IDR
+ #define TRIMS_GPIO_PIN_LHR GPIO_Pin_15 // PD.15
+ #define TRIMS_GPIO_REG_LHL GPIOC->IDR
+ #define TRIMS_GPIO_PIN_LHL GPIO_Pin_1 // PC.01
+ #define TRIMS_GPIO_REG_LVD GPIOE->IDR
+ #define TRIMS_GPIO_PIN_LVD GPIO_Pin_6 // PE.06
+ #define TRIMS_GPIO_REG_LVU GPIOE->IDR
+ #define TRIMS_GPIO_PIN_LVU GPIO_Pin_5 // PE.05
+ #define TRIMS_GPIO_REG_RVD GPIOC->IDR
+ #define TRIMS_GPIO_PIN_RVD GPIO_Pin_3 // PC.03
+ #define TRIMS_GPIO_REG_RHR GPIOE->IDR
+ #define TRIMS_GPIO_PIN_RHR GPIO_Pin_3 // PE.03
+ #define TRIMS_GPIO_REG_RVU GPIOC->IDR
+ #define TRIMS_GPIO_PIN_RVU GPIO_Pin_2 // PC.02
+ #define TRIMS_GPIO_REG_RHL GPIOE->IDR
+ #define TRIMS_GPIO_PIN_RHL GPIO_Pin_4 // PE.04
#elif defined(PCBX7)
#define TRIMS_GPIO_REG_LHL GPIOD->IDR
#define TRIMS_GPIO_PIN_LHL GPIO_Pin_15 // PD.15
@@ -227,7 +244,7 @@
#define TRIMS_GPIO_PIN_RVD GPIO_Pin_14 // PE.14
#define TRIMS_GPIO_REG_RHL GPIOD->IDR
#define TRIMS_GPIO_PIN_RHL GPIO_Pin_9 // PD.09
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019)
#define TRIMS_GPIO_REG_LHL GPIOE->IDR
#define TRIMS_GPIO_PIN_LHL GPIO_Pin_3 // PE.03
#define TRIMS_GPIO_REG_LHR GPIOE->IDR
@@ -351,8 +368,13 @@
#define HARDWARE_SWITCH_C
#define SWITCHES_GPIO_REG_C_L GPIOD->IDR
#define SWITCHES_GPIO_PIN_C_L GPIO_Pin_11 // PD.11
- #define SWITCHES_GPIO_REG_C_H GPIOE->IDR
- #define SWITCHES_GPIO_PIN_C_H GPIO_Pin_0 // PE.00
+ #if defined(PCBX7ACCESS)
+ #define SWITCHES_GPIO_REG_C_H GPIOD->IDR
+ #define SWITCHES_GPIO_PIN_C_H GPIO_Pin_10 // PD.10
+ #else
+ #define SWITCHES_GPIO_REG_C_H GPIOE->IDR
+ #define SWITCHES_GPIO_PIN_C_H GPIO_Pin_0 // PE.00
+ #endif
#else
#define STORAGE_SWITCH_C
#define HARDWARE_SWITCH_C
@@ -514,7 +536,7 @@
#define SWITCHES_GPIO_PIN_H GPIO_Pin_13 // PE.13
#endif
-#if defined(PCBX9DP) && PCBREV >= 2019
+#if defined(RADIO_X9DP2019)
#define STORAGE_SWITCH_I
#define HARDWARE_SWITCH_I
#define SWITCHES_GPIO_REG_I GPIOD->IDR
@@ -524,13 +546,19 @@
#endif
// X7 P400 P401 headers additionnal momentary switches
-#if defined(PCBX7)
+#if defined(PCBX7ACCESS)
#define STORAGE_SWITCH_I
#define HARDWARE_SWITCH_I
- #define STORAGE_SWITCH_J
- #define HARDWARE_SWITCH_J
#define SWITCHES_GPIO_REG_I GPIOC->IDR
#define SWITCHES_GPIO_PIN_I GPIO_Pin_13 // PC.13
+ #define STORAGE_SWITCH_J
+#elif defined(PCBX7)
+ #define STORAGE_SWITCH_I
+ #define HARDWARE_SWITCH_I
+ #define SWITCHES_GPIO_REG_I GPIOC->IDR
+ #define SWITCHES_GPIO_PIN_I GPIO_Pin_13 // PC.13
+ #define STORAGE_SWITCH_J
+ #define HARDWARE_SWITCH_J
#define SWITCHES_GPIO_REG_J GPIOD->IDR
#define SWITCHES_GPIO_PIN_J GPIO_Pin_10 // PD.10
#endif
@@ -607,7 +635,7 @@
#define KEYS_GPIOE_PINS (TRIMS_GPIO_PIN_LVU | TRIMS_GPIO_PIN_LVD | SWITCHES_GPIO_PIN_D_H | SWITCHES_GPIO_PIN_D_L| SWITCHES_GPIO_PIN_E_H | SWITCHES_GPIO_PIN_E_L | SWITCHES_GPIO_PIN_F | SWITCHES_GPIO_PIN_I_L | SWITCHES_GPIO_PIN_L_H | SWITCHES_GPIO_PIN_L_L | SWITCHES_GPIO_PIN_M_H | SWITCHES_GPIO_PIN_O_L | SWITCHES_GPIO_PIN_R_L)
#define KEYS_GPIOF_PINS (KEYS_GPIO_PIN_ENTER | SWITCHES_GPIO_PIN_C_H | SWITCHES_GPIO_PIN_C_L | SWITCHES_GPIO_PIN_G_H | SWITCHES_GPIO_PIN_G_L | SWITCHES_GPIO_PIN_H | SWITCHES_GPIO_PIN_I_H | SWITCHES_GPIO_PIN_O_H | SWITCHES_GPIO_PIN_P_H | SWITCHES_GPIO_PIN_P_L | SWITCHES_GPIO_PIN_Q_H | SWITCHES_GPIO_PIN_Q_L)
#define KEYS_GPIOG_PINS (TRIMS_GPIO_PIN_LHL | TRIMS_GPIO_PIN_LHR| SWITCHES_GPIO_PIN_B_H | SWITCHES_GPIO_PIN_B_L | SWITCHES_GPIO_PIN_J_H | SWITCHES_GPIO_PIN_J_L | SWITCHES_GPIO_PIN_K_H | SWITCHES_GPIO_PIN_K_L)
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019)
#define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE)
#define KEYS_GPIOA_PINS (GPIO_Pin_5)
#define KEYS_GPIOB_PINS (GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5)
@@ -639,6 +667,12 @@
#define KEYS_GPIOC_PINS (GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3)
#define KEYS_GPIOD_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15)
#define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15)
+#elif defined(RADIO_X7ACCESS)
+ #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE)
+ #define KEYS_GPIOA_PINS GPIO_Pin_5
+ #define KEYS_GPIOC_PINS (GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_13)
+ #define KEYS_GPIOD_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15)
+ #define KEYS_GPIOE_PINS (GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15)
#elif defined(RADIO_X7)
#define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE)
#define KEYS_GPIOA_PINS GPIO_Pin_5
@@ -720,7 +754,7 @@
#define ADC_EXT_SET_DMA_FLAGS() ADC_DMA->LIFCR = (DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0)
#define ADC_EXT_TRANSFER_COMPLETE() (ADC_DMA->LISR & DMA_LISR_TCIF0)
#define ADC_EXT_SAMPTIME 3 // sample time = 56 cycles
- #define ADC_VREF_PREC2 200
+ #define ADC_VREF_PREC2 300
#elif defined(PCBX9DP)
#define HARDWARE_POT1
#define HARDWARE_POT2
@@ -882,7 +916,7 @@
#define PWR_ON_GPIO_PIN GPIO_Pin_0 // PD.00
#endif
-#if defined(PCBX9DP) && PCBREV >= 2019
+#if defined(RADIO_X9DP2019)
#define STATUS_LEDS
#define GPIO_LED_GPIO_ON GPIO_ResetBits
#define GPIO_LED_GPIO_OFF GPIO_SetBits
@@ -898,6 +932,14 @@
#define LED_RED_GPIO_PIN GPIO_Pin_4 // PE.04
#define LED_GREEN_GPIO GPIOE
#define LED_GREEN_GPIO_PIN GPIO_Pin_5 // PE.05
+#elif defined(PCBX7ACCESS)
+ #define STATUS_LEDS
+ #define GPIO_LED_GPIO_ON GPIO_SetBits
+ #define GPIO_LED_GPIO_OFF GPIO_ResetBits
+ #define LED_BLUE_GPIO GPIOB
+ #define LED_BLUE_GPIO_PIN GPIO_Pin_1 // PB.01
+ #define LED_RED_GPIO GPIOC
+ #define LED_RED_GPIO_PIN GPIO_Pin_4 // PC.04
#elif defined(PCBX7)
#define STATUS_LEDS
#define GPIO_LED_GPIO_ON GPIO_SetBits
@@ -944,6 +986,31 @@
#define INTMODULE_PWR_GPIO GPIOD
#define INTMODULE_PWR_GPIO_PIN GPIO_Pin_9 // PD.09
#endif
+ #define INTMODULE_GPIO GPIOB
+ #define INTMODULE_TX_GPIO_PIN GPIO_Pin_6 // PB.06
+ #define INTMODULE_RX_GPIO_PIN GPIO_Pin_7 // PB.07
+ #define INTMODULE_GPIO_PinSource_TX GPIO_PinSource6
+ #define INTMODULE_GPIO_PinSource_RX GPIO_PinSource7
+ #define INTMODULE_USART USART1
+ #define INTMODULE_GPIO_AF GPIO_AF_USART1
+ #define INTMODULE_USART_IRQHandler USART1_IRQHandler
+ #define INTMODULE_USART_IRQn USART1_IRQn
+ #define INTMODULE_DMA_STREAM DMA2_Stream7
+ #define INTMODULE_DMA_STREAM_IRQ DMA2_Stream7_IRQn
+ #define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream7_IRQHandler
+ #define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF7
+ #define INTMODULE_DMA_CHANNEL DMA_Channel_4
+ #if defined(PCBXLITES)
+ #define INTMODULE_BOOTCMD_GPIO GPIOC
+ #define INTMODULE_BOOTCMD_GPIO_PIN GPIO_Pin_8 // PC.08
+ #define INIT_INTMODULE_BOOTCMD_PIN() GPIO_SetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN);
+ #endif
+#elif defined(RADIO_X9DP2019)
+ #define INTMODULE_RCC_APB1Periph 0
+ #define INTMODULE_RCC_APB2Periph RCC_APB2Periph_USART1
+ #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2)
+ #define INTMODULE_PWR_GPIO GPIOA
+ #define INTMODULE_PWR_GPIO_PIN GPIO_Pin_7 // PA.07
#define INTMODULE_GPIO GPIOB
#define INTMODULE_TX_GPIO_PIN GPIO_Pin_6 // PB.06
#define INTMODULE_RX_GPIO_PIN GPIO_Pin_7 // PB.07
@@ -958,16 +1025,12 @@
#define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream7_IRQHandler
#define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF7
#define INTMODULE_DMA_CHANNEL DMA_Channel_4
- #if defined(PCBXLITES)
- #define INTMODULE_BOOTCMD_GPIO GPIOC
- #define INTMODULE_BOOTCMD_GPIO_PIN GPIO_Pin_8 // PC.08
- #endif
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X7ACCESS)
#define INTMODULE_RCC_APB1Periph 0
#define INTMODULE_RCC_APB2Periph RCC_APB2Periph_USART1
- #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2)
- #define INTMODULE_PWR_GPIO GPIOA
- #define INTMODULE_PWR_GPIO_PIN GPIO_Pin_7 // PA.07
+ #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2)
+ #define INTMODULE_PWR_GPIO GPIOC
+ #define INTMODULE_PWR_GPIO_PIN GPIO_Pin_5 // PC.05
#define INTMODULE_GPIO GPIOB
#define INTMODULE_TX_GPIO_PIN GPIO_Pin_6 // PB.06
#define INTMODULE_RX_GPIO_PIN GPIO_Pin_7 // PB.07
@@ -1015,11 +1078,6 @@
#define INTMODULE_GPIO_AF GPIO_AF_USART3
#define INTMODULE_USART_IRQn USART3_IRQn
#define INTMODULE_USART_IRQHandler USART3_IRQHandler
- #define INTMODULE_DMA_STREAM DMA1_Stream3
- #define INTMODULE_DMA_STREAM_IRQ DMA1_Stream3_IRQn
- #define INTMODULE_DMA_STREAM_IRQHandler DMA1_Stream3_IRQHandler
- #define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF3
- #define INTMODULE_DMA_CHANNEL DMA_Channel_4
#define INTMODULE_RCC_APB1Periph RCC_APB1Periph_TIM2
#define INTMODULE_RCC_APB2Periph RCC_APB1Periph_USART3
#define INTMODULE_TIMER TIM2
@@ -1051,9 +1109,9 @@
#endif
// External Module
-#if defined(PCBXLITE) || defined(PCBX9LITE) || (defined(PCBX9DP) && PCBREV >= 2019)
+#if defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019) || defined(PCBX7ACCESS)
#define EXTMODULE_RCC_APB2Periph (RCC_APB2Periph_TIM8 | RCC_APB2Periph_USART6)
- #if defined(PCBX9DP) && PCBREV >= 2019
+ #if defined(RADIO_X9DP2019) || defined(RADIO_X7ACCESS)
#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
#define EXTMODULE_PWR_GPIO GPIOD
#define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_8 // PD.08
@@ -1121,7 +1179,7 @@
#define EXTMODULE_TIMER_OUTPUT_ENABLE TIM_CCER_CC1NE
#define EXTMODULE_TIMER_OUTPUT_POLARITY TIM_CCER_CC1NP
#define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019)
#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
#define EXTMODULE_RCC_APB2Periph (RCC_APB2Periph_TIM8 | RCC_APB2Periph_USART6)
#define EXTMODULE_PWR_GPIO GPIOD
@@ -1243,13 +1301,15 @@
#endif
// Serial Port
-#if defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) || (defined(PCBX9DP) && PCBREV >= 2019)
+#if defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019)
#define AUX_SERIAL_RCC_AHB1Periph 0
#define AUX_SERIAL_RCC_APB1Periph 0
+ #define AUX_SERIAL_RCC_APB2Periph 0
#else
#define TRAINER_BATTERY_COMPARTMENT
#define AUX_SERIAL_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1)
#define AUX_SERIAL_RCC_APB1Periph RCC_APB1Periph_USART3
+ #define AUX_SERIAL_RCC_APB2Periph 0
#define AUX_SERIAL_GPIO GPIOB
#define AUX_SERIAL_GPIO_PIN_TX GPIO_Pin_10 // PB.10
#define AUX_SERIAL_GPIO_PIN_RX GPIO_Pin_11 // PB.11
@@ -1263,12 +1323,18 @@
#define AUX_SERIAL_DMA_Channel_RX DMA_Channel_4
#endif
+// No aux2 on taranis
+#define AUX2_SERIAL_RCC_AHB1Periph 0
+#define AUX2_SERIAL_RCC_APB1Periph 0
+#define AUX2_SERIAL_RCC_APB2Periph 0
+
// Telemetry
#define TELEMETRY_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1)
#define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2
+#define TELEMETRY_RCC_APB2Periph RCC_APB2Periph_TIM11
#define TELEMETRY_DIR_GPIO GPIOD
#define TELEMETRY_DIR_GPIO_PIN GPIO_Pin_4 // PD.04
-#if defined(PCBXLITE) || defined(PCBX9LITE) || (defined(PCBX9DP) && PCBREV >= 2019)
+#if defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019) || defined(RADIO_X7ACCESS)
#define TELEMETRY_DIR_OUTPUT() TELEMETRY_DIR_GPIO->BSRRH = TELEMETRY_DIR_GPIO_PIN
#define TELEMETRY_DIR_INPUT() TELEMETRY_DIR_GPIO->BSRRL = TELEMETRY_DIR_GPIO_PIN
#else
@@ -1295,9 +1361,9 @@
#define TELEMETRY_EXTI_IRQn EXTI9_5_IRQn
#define TELEMETRY_EXTI_TRIGGER EXTI_Trigger_Rising
-#if defined(RADIO_X7)
+#if defined(RADIO_X7) || defined(RADIO_X7ACCESS)
#define TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER
-#elif defined(PCBXLITE) || defined(PCBX9LITE) || (defined(PCBX9DP) && PCBREV >= 2019)
+#elif defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019)
#define TELEMETRY_EXTI_IRQHandler EXTI9_5_IRQHandler
#else
#define TELEMETRY_EXTI_REUSE_INTERRUPT_INTMODULE_HEARTBEAT
@@ -1312,6 +1378,8 @@
#define PCBREV_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
#define PCBREV_GPIO GPIOA
#define PCBREV_GPIO_PIN GPIO_Pin_14 // PA.14
+ #define PCBREV_GPIO_PULL_DOWN
+ #define PCBREV_VALUE() GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN)
#else
#define PCBREV_RCC_AHB1Periph 0
#endif
@@ -1324,6 +1392,13 @@
#define SPORT_UPDATE_PWR_GPIO_PIN GPIO_Pin_8 // PD.08
#define GPIO_SPORT_UPDATE_PWR_GPIO_ON GPIO_SetBits
#define GPIO_SPORT_UPDATE_PWR_GPIO_OFF GPIO_ResetBits
+#elif defined(PCBX7ACCESS)
+ #define SPORT_MAX_BAUDRATE 400000
+ #define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOB
+ #define SPORT_UPDATE_PWR_GPIO GPIOB
+ #define SPORT_UPDATE_PWR_GPIO_PIN GPIO_Pin_3 // PB.03
+ #define GPIO_SPORT_UPDATE_PWR_GPIO_ON GPIO_SetBits
+ #define GPIO_SPORT_UPDATE_PWR_GPIO_OFF GPIO_ResetBits
#elif defined(PCBX7)
#define SPORT_MAX_BAUDRATE 250000 // < 400000
#define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOB
@@ -1338,7 +1413,7 @@
#define SPORT_UPDATE_PWR_GPIO_PIN GPIO_Pin_15 // PE.15
#define GPIO_SPORT_UPDATE_PWR_GPIO_ON GPIO_SetBits
#define GPIO_SPORT_UPDATE_PWR_GPIO_OFF GPIO_ResetBits
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019)
#define SPORT_MAX_BAUDRATE 400000
#define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
#define SPORT_UPDATE_PWR_GPIO GPIOA
@@ -1372,17 +1447,27 @@
// #define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line9
// #define INTMODULE_HEARTBEAT_EXTI_IRQn EXTI9_5_IRQn
// #define INTMODULE_HEARTBEAT_EXTI_IRQHandler EXTI9_5_IRQHandler
-#elif defined(RADIO_X7)
+#elif defined(RADIO_X7ACCESS)
+ #define INTMODULE_HEARTBEAT
+ #define INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER
+ #define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
+ #define INTMODULE_HEARTBEAT_GPIO GPIOA
+ #define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_7 // PA.07
+ #define INTMODULE_HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOA
+ #define INTMODULE_HEARTBEAT_EXTI_PinSource GPIO_PinSource7
+ #define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line7
+ #define INTMODULE_HEARTBEAT_EXTI_IRQn EXTI9_5_IRQn
+#elif defined(RADIO_X7)
#define INTMODULE_HEARTBEAT
#define INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER
#define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC
#define INTMODULE_HEARTBEAT_GPIO GPIOC
- #define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_7
+ #define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_7 // PC.07
#define INTMODULE_HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOC
#define INTMODULE_HEARTBEAT_EXTI_PinSource GPIO_PinSource7
#define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line7
#define INTMODULE_HEARTBEAT_EXTI_IRQn EXTI9_5_IRQn
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019)
#define INTMODULE_HEARTBEAT
#define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOB
#define INTMODULE_HEARTBEAT_GPIO GPIOB
@@ -1554,6 +1639,7 @@
#define BACKLIGHT_GPIO_PinSource GPIO_PinSource8
#define BACKLIGHT_GPIO_AF GPIO_AF_TIM10
#endif
+#define KEYS_BACKLIGHT_RCC_AHB1Periph 0
// LCD driver
#if defined(PCBX9E)
@@ -1646,7 +1732,16 @@
#define I2C_WP_GPIO_PIN GPIO_Pin_7 // PD.07
#define I2C_SCL_GPIO_PinSource GPIO_PinSource8
#define I2C_SDA_GPIO_PinSource GPIO_PinSource9
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(PCBX7ACCESS)
+ #define I2C_RCC_AHB1Periph RCC_AHB1Periph_GPIOB
+ #define I2C_SPI_GPIO GPIOB
+ #define I2C_SDA_GPIO_PIN GPIO_Pin_9 // PB.09
+ #define I2C_SCL_GPIO_PIN GPIO_Pin_8 // PB.08
+ #define I2C_WP_GPIO GPIOB
+ #define I2C_WP_GPIO_PIN GPIO_Pin_5 // PB.05
+ #define I2C_SDA_GPIO_PinSource GPIO_PinSource9
+ #define I2C_SCL_GPIO_PinSource GPIO_PinSource8
+#elif defined(RADIO_X9DP2019)
#define I2C_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOF)
#define I2C_SPI_GPIO GPIOB
#define I2C_SDA_GPIO_PIN GPIO_Pin_9 // PB.09
@@ -1759,7 +1854,7 @@
#define HAPTIC_CCMR1 TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2
#define HAPTIC_CCER TIM_CCER_CC2E
#define BACKLIGHT_BDTR TIM_BDTR_MOE
-#elif defined(PCBX9DP) && PCBREV >= 2019
+#elif defined(RADIO_X9DP2019) || defined(RADIO_X7ACCESS)
#define HAPTIC_PWM
#define HAPTIC_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
#define HAPTIC_RCC_APB2Periph RCC_APB2Periph_TIM1
@@ -1827,7 +1922,7 @@
#define BT_TX_GPIO_PinSource GPIO_PinSource14
#define BT_RX_GPIO_PinSource GPIO_PinSource9
#define BT_USART_IRQHandler USART6_IRQHandler
-#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITES) || (defined(PCBX9DP) && PCBREV >= 2019)
+#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITES) || defined(RADIO_X9DP2019)
#define STORAGE_BLUETOOTH
#define BT_RCC_APB1Periph RCC_APB1Periph_USART3
#define BT_RCC_APB2Periph 0
diff --git a/radio/src/targets/taranis/keys_driver.cpp b/radio/src/targets/taranis/keys_driver.cpp
index ccaf60760..0699a1c50 100644
--- a/radio/src/targets/taranis/keys_driver.cpp
+++ b/radio/src/targets/taranis/keys_driver.cpp
@@ -130,7 +130,7 @@ void readKeysAndTrims()
if ((keys_input || trims_input) && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) {
#endif
// on keypress turn the light on
- backlightOn();
+ resetBacklightTimeout();
}
}
@@ -195,6 +195,12 @@ uint32_t switchState(uint8_t index)
#elif defined(PCBXLITE)
ADD_3POS_CASE(D, 3);
// no SWE, SWF, SWG and SWH on XLITE
+#elif defined(PCBX7ACCESS)
+ ADD_3POS_CASE(D, 3);
+ ADD_2POS_CASE(F);
+ ADD_2POS_CASE(H);
+ ADD_2POS_CASE(I);
+ // no SWJ on XLITE
#elif defined(PCBX7)
ADD_3POS_CASE(D, 3);
ADD_2POS_CASE(F);
@@ -209,7 +215,7 @@ uint32_t switchState(uint8_t index)
ADD_2POS_CASE(H);
#endif
-#if defined(PCBX9DP) && PCBREV >= 2019
+#if defined(RADIO_X9DP2019)
ADD_2POS_CASE(I);
#endif
diff --git a/radio/src/targets/taranis/lcd_driver_spi.cpp b/radio/src/targets/taranis/lcd_driver_spi.cpp
index 50eb13982..ca66dc1a7 100644
--- a/radio/src/targets/taranis/lcd_driver_spi.cpp
+++ b/radio/src/targets/taranis/lcd_driver_spi.cpp
@@ -311,7 +311,7 @@ void lcdInit()
issued by the other parts of the code.
*/
-#if defined(PCBX9DP) && PCBREV >= 2019
+#if defined(RADIO_X9DP2019) || defined(RADIO_X7ACCESS)
#define LCD_DELAY_NEEDED() true
#else
#define LCD_DELAY_NEEDED() (!WAS_RESET_BY_WATCHDOG_OR_SOFTWARE())
diff --git a/radio/src/targets/taranis/telemetry_driver.cpp b/radio/src/targets/taranis/telemetry_driver.cpp
index 3c9618f03..b46eca541 100644
--- a/radio/src/targets/taranis/telemetry_driver.cpp
+++ b/radio/src/targets/taranis/telemetry_driver.cpp
@@ -40,7 +40,8 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
USART_DeInit(TELEMETRY_USART);
return;
}
-
+ //deinit inverted mode
+ telemetryPortInvertedInit(0);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TELEMETRY_DMA_TX_Stream_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
@@ -87,11 +88,10 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
// soft serial vars
static uint8_t rxBitCount;
static uint8_t rxByte;
+// single bit length expresses in half us
+static uint16_t bitLength;
+static uint16_t probeTimeFromStartBit;
-//TODO:
-// - only 57600 supported for now
-// - handle other bitrates as well?
-//
void telemetryPortInvertedInit(uint32_t baudrate)
{
if (baudrate == 0) {
@@ -116,8 +116,21 @@ void telemetryPortInvertedInit(uint32_t baudrate)
rxBitCount = 0;
+ switch(baudrate) {
+ case 115200:
+ bitLength = 17;
+ probeTimeFromStartBit = 25;
+ break;
+ case 57600:
+ bitLength = 35; //34 was used before - I prefer to use use 35 because of lower error
+ probeTimeFromStartBit = 52; //round down - 48 used in original implementation
+ break;
+ default:
+ bitLength = 2000000/baudrate; //because of 0,5 us tick
+ probeTimeFromStartBit = 3000000/baudrate;
+ }
+
// configure bit sample timer
- RCC->APB2ENR |= RCC_APB2ENR_TIM11EN;
TELEMETRY_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS
TELEMETRY_TIMER->CCER = 0;
TELEMETRY_TIMER->CCMR1 = 0;
@@ -163,7 +176,7 @@ void telemetryPortInvertedRxBit()
{
if (rxBitCount < 8) {
if (rxBitCount == 0) {
- TELEMETRY_TIMER->ARR = 34;
+ TELEMETRY_TIMER->ARR = bitLength;
rxByte = 0;
}
else {
@@ -334,7 +347,7 @@ void check_telemetry_exti()
if (rxBitCount == 0) {
- TELEMETRY_TIMER->ARR = 48; // 1,5 cycle from start at 57600bps
+ TELEMETRY_TIMER->ARR = probeTimeFromStartBit; // 1,5 cycle from start at 57600bps
TELEMETRY_TIMER->CR1 |= TIM_CR1_CEN;
// disable start bit interrupt
diff --git a/radio/src/targets/taranis/trainer_driver.cpp b/radio/src/targets/taranis/trainer_driver.cpp
index 06a006899..01f6e47bf 100644
--- a/radio/src/targets/taranis/trainer_driver.cpp
+++ b/radio/src/targets/taranis/trainer_driver.cpp
@@ -329,7 +329,7 @@ void stop_trainer_module_sbus()
}
#endif
-#if defined(SBUS)
+#if defined(SBUS_TRAINER)
int sbusGetByte(uint8_t * byte)
{
switch (currentTrainerMode) {
diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp
index 9cbe9e2bd..e9dcfac45 100644
--- a/radio/src/tasks.cpp
+++ b/radio/src/tasks.cpp
@@ -73,9 +73,9 @@ bool isForcePowerOffRequested()
return false;
}
-bool isModuleSynchronous(uint8_t module)
+bool isModuleSynchronous(uint8_t moduleIdx)
{
- uint8_t protocol = moduleState[module].protocol;
+ uint8_t protocol = moduleState[moduleIdx].protocol;
if (protocol == PROTOCOL_CHANNELS_PXX2_HIGHSPEED || protocol == PROTOCOL_CHANNELS_PXX2_LOWSPEED || protocol == PROTOCOL_CHANNELS_CROSSFIRE || protocol == PROTOCOL_CHANNELS_NONE)
return true;
#if defined(INTMODULE_USART) || defined(EXTMODULE_USART)
@@ -85,16 +85,16 @@ bool isModuleSynchronous(uint8_t module)
return false;
}
-void sendSynchronousPulses()
+void sendSynchronousPulses(uint8_t runMask)
{
#if defined(HARDWARE_INTERNAL_MODULE)
- if (isModuleSynchronous(INTERNAL_MODULE)) {
+ if ((runMask & (1 << INTERNAL_MODULE)) && isModuleSynchronous(INTERNAL_MODULE)) {
if (setupPulsesInternalModule())
intmoduleSendNextFrame();
}
#endif
- if (isModuleSynchronous(EXTERNAL_MODULE)) {
+ if ((runMask & (1 << EXTERNAL_MODULE)) && isModuleSynchronous(EXTERNAL_MODULE)) {
if (setupPulsesExternalModule())
extmoduleSendNextFrame();
}
@@ -104,11 +104,10 @@ uint32_t nextMixerTime[NUM_MODULES];
TASK_FUNCTION(mixerTask)
{
- static uint32_t lastRunTime;
s_pulses_paused = true;
while (true) {
-#if defined(PCBTARANIS) && defined(SBUS)
+#if defined(SBUS_TRAINER)
// SBUS trainer
processSbusInput();
#endif
@@ -134,35 +133,22 @@ TASK_FUNCTION(mixerTask)
#endif
uint32_t now = RTOS_GET_MS();
- bool run = false;
+ uint8_t runMask = 0;
- if (now - lastRunTime >= 10) {
- // run at least every 10ms
- run = true;
- }
-
-#if defined(INTMODULE_USART) && defined(INTMODULE_HEARTBEAT)
- if ((moduleState[INTERNAL_MODULE].protocol == PROTOCOL_CHANNELS_PXX2_HIGHSPEED || moduleState[INTERNAL_MODULE].protocol == PROTOCOL_CHANNELS_PXX1_SERIAL) && heartbeatCapture.valid && heartbeatCapture.timestamp > lastRunTime) {
- run = true;
- }
-#endif
-
- if (now == nextMixerTime[0]) {
- run = true;
+ if (now >= nextMixerTime[0]) {
+ runMask |= (1 << 0);
}
#if NUM_MODULES >= 2
- if (now == nextMixerTime[1]) {
- run = true;
+ if (now >= nextMixerTime[1]) {
+ runMask |= (1 << 1);
}
#endif
- if (!run) {
+ if (!runMask) {
continue; // go back to sleep
}
- lastRunTime = now;
-
if (!s_pulses_paused) {
uint16_t t0 = getTmr2MHz();
@@ -197,12 +183,12 @@ TASK_FUNCTION(mixerTask)
if (t0 > maxMixerDuration)
maxMixerDuration = t0;
- sendSynchronousPulses();
+ sendSynchronousPulses(runMask);
}
}
}
-void scheduleNextMixerCalculation(uint8_t module, uint16_t period_ms)
+void scheduleNextMixerCalculation(uint8_t module, uint32_t period_ms)
{
// Schedule next mixer calculation time,
diff --git a/radio/src/telemetry/crossfire.cpp b/radio/src/telemetry/crossfire.cpp
index b233583a4..c71f6ce54 100644
--- a/radio/src/telemetry/crossfire.cpp
+++ b/radio/src/telemetry/crossfire.cpp
@@ -21,31 +21,32 @@
#include "opentx.h"
const CrossfireSensor crossfireSensors[] = {
- {LINK_ID, 0, ZSTR_RX_RSSI1, UNIT_DB, 0},
- {LINK_ID, 1, ZSTR_RX_RSSI2, UNIT_DB, 0},
- {LINK_ID, 2, ZSTR_RX_QUALITY, UNIT_PERCENT, 0},
- {LINK_ID, 3, ZSTR_RX_SNR, UNIT_DB, 0},
- {LINK_ID, 4, ZSTR_ANTENNA, UNIT_RAW, 0},
- {LINK_ID, 5, ZSTR_RF_MODE, UNIT_RAW, 0},
- {LINK_ID, 6, ZSTR_TX_POWER, UNIT_MILLIWATTS, 0},
- {LINK_ID, 7, ZSTR_TX_RSSI, UNIT_DB, 0},
- {LINK_ID, 8, ZSTR_TX_QUALITY, UNIT_PERCENT, 0},
- {LINK_ID, 9, ZSTR_TX_SNR, UNIT_DB, 0},
- {BATTERY_ID, 0, ZSTR_BATT, UNIT_VOLTS, 1},
- {BATTERY_ID, 1, ZSTR_CURR, UNIT_AMPS, 1},
- {BATTERY_ID, 2, ZSTR_CAPACITY, UNIT_MAH, 0},
- {GPS_ID, 0, ZSTR_GPS, UNIT_GPS_LATITUDE, 0},
- {GPS_ID, 0, ZSTR_GPS, UNIT_GPS_LONGITUDE, 0},
- {GPS_ID, 2, ZSTR_GSPD, UNIT_KMH, 1},
- {GPS_ID, 3, ZSTR_HDG, UNIT_DEGREE, 3},
- {GPS_ID, 4, ZSTR_ALT, UNIT_METERS, 0},
- {GPS_ID, 5, ZSTR_SATELLITES, UNIT_RAW, 0},
- {ATTITUDE_ID, 0, ZSTR_PITCH, UNIT_RADIANS, 3},
- {ATTITUDE_ID, 1, ZSTR_ROLL, UNIT_RADIANS, 3},
- {ATTITUDE_ID, 2, ZSTR_YAW, UNIT_RADIANS, 3},
- {FLIGHT_MODE_ID, 0, ZSTR_FLIGHT_MODE, UNIT_TEXT, 0},
- {CF_VARIO_ID, 0, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 2},
- {0, 0, "UNKNOWN", UNIT_RAW, 0},
+ {LINK_ID, 0, ZSTR_RX_RSSI1, UNIT_DB, 0},
+ {LINK_ID, 1, ZSTR_RX_RSSI2, UNIT_DB, 0},
+ {LINK_ID, 2, ZSTR_RX_QUALITY, UNIT_PERCENT, 0},
+ {LINK_ID, 3, ZSTR_RX_SNR, UNIT_DB, 0},
+ {LINK_ID, 4, ZSTR_ANTENNA, UNIT_RAW, 0},
+ {LINK_ID, 5, ZSTR_RF_MODE, UNIT_RAW, 0},
+ {LINK_ID, 6, ZSTR_TX_POWER, UNIT_MILLIWATTS, 0},
+ {LINK_ID, 7, ZSTR_TX_RSSI, UNIT_DB, 0},
+ {LINK_ID, 8, ZSTR_TX_QUALITY, UNIT_PERCENT, 0},
+ {LINK_ID, 9, ZSTR_TX_SNR, UNIT_DB, 0},
+ {BATTERY_ID, 0, ZSTR_BATT, UNIT_VOLTS, 1},
+ {BATTERY_ID, 1, ZSTR_CURR, UNIT_AMPS, 1},
+ {BATTERY_ID, 2, ZSTR_CAPACITY, UNIT_MAH, 0},
+ {BATTERY_ID, 3, ZSTR_BATT_PERCENT, UNIT_PERCENT, 0},
+ {GPS_ID, 0, ZSTR_GPS, UNIT_GPS_LATITUDE, 0},
+ {GPS_ID, 0, ZSTR_GPS, UNIT_GPS_LONGITUDE, 0},
+ {GPS_ID, 2, ZSTR_GSPD, UNIT_KMH, 1},
+ {GPS_ID, 3, ZSTR_HDG, UNIT_DEGREE, 3},
+ {GPS_ID, 4, ZSTR_ALT, UNIT_METERS, 0},
+ {GPS_ID, 5, ZSTR_SATELLITES, UNIT_RAW, 0},
+ {ATTITUDE_ID, 0, ZSTR_PITCH, UNIT_RADIANS, 3},
+ {ATTITUDE_ID, 1, ZSTR_ROLL, UNIT_RADIANS, 3},
+ {ATTITUDE_ID, 2, ZSTR_YAW, UNIT_RADIANS, 3},
+ {FLIGHT_MODE_ID, 0, ZSTR_FLIGHT_MODE, UNIT_TEXT, 0},
+ {CF_VARIO_ID, 0, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 2},
+ {0, 0, "UNKNOWN", UNIT_RAW, 0},
};
const CrossfireSensor & getCrossfireSensor(uint8_t id, uint8_t subId)
@@ -68,7 +69,7 @@ const CrossfireSensor & getCrossfireSensor(uint8_t id, uint8_t subId)
void processCrossfireTelemetryValue(uint8_t index, int32_t value)
{
- if(!TELEMETRY_STREAMING())
+ if (!TELEMETRY_STREAMING())
return;
const CrossfireSensor & sensor = crossfireSensors[index];
@@ -157,6 +158,8 @@ void processCrossfireTelemetryFrame()
processCrossfireTelemetryValue(BATT_CURRENT_INDEX, value);
if (getCrossfireTelemetryValue<3>(7, value))
processCrossfireTelemetryValue(BATT_CAPACITY_INDEX, value);
+ if (getCrossfireTelemetryValue<1>(10, value))
+ processCrossfireTelemetryValue(BATT_REMAINING_INDEX, value);
break;
case ATTITUDE_ID:
@@ -199,6 +202,12 @@ void processCrossfireTelemetryData(uint8_t data)
}
#endif
+#if defined(AUX2_SERIAL)
+ if (g_eeGeneral.aux2SerialMode == UART_MODE_TELEMETRY_MIRROR) {
+ aux2SerialPutc(data);
+ }
+#endif
+
if (telemetryRxBufferCount == 0 && data != RADIO_ADDRESS) {
TRACE("[XF] address 0x%02X error", data);
return;
diff --git a/radio/src/telemetry/crossfire.h b/radio/src/telemetry/crossfire.h
index 5f40b6f93..79cc5f025 100644
--- a/radio/src/telemetry/crossfire.h
+++ b/radio/src/telemetry/crossfire.h
@@ -64,6 +64,7 @@ enum CrossfireSensorIndexes {
BATT_VOLTAGE_INDEX,
BATT_CURRENT_INDEX,
BATT_CAPACITY_INDEX,
+ BATT_REMAINING_INDEX,
GPS_LATITUDE_INDEX,
GPS_LONGITUDE_INDEX,
GPS_GROUND_SPEED_INDEX,
@@ -81,7 +82,6 @@ enum CrossfireSensorIndexes {
void processCrossfireTelemetryData(uint8_t data);
void crossfireSetDefault(int index, uint8_t id, uint8_t subId);
-#if SPORT_MAX_BAUDRATE < 400000
const uint32_t CROSSFIRE_BAUDRATES[] = {
400000,
115200,
@@ -90,6 +90,7 @@ const uint8_t CROSSFIRE_PERIODS[] = {
4,
16,
};
+#if SPORT_MAX_BAUDRATE < 400000
#define CROSSFIRE_BAUDRATE CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate]
#define CROSSFIRE_PERIOD CROSSFIRE_PERIODS[g_eeGeneral.telemetryBaudrate]
#else
diff --git a/radio/src/telemetry/flysky_ibus.cpp b/radio/src/telemetry/flysky_ibus.cpp
index 0869fb0da..4b2d05da9 100644
--- a/radio/src/telemetry/flysky_ibus.cpp
+++ b/radio/src/telemetry/flysky_ibus.cpp
@@ -61,7 +61,8 @@ enum
AFHDS2A_ID_GPS_DIST = 0x14, // 2 bytes distance from home m unsigned
AFHDS2A_ID_ARMED = 0x15, // 2 bytes
AFHDS2A_ID_FLIGHT_MODE = 0x16, // 2 bytes
-
+ AFHDS3_FRM_TEMP = 0x57, //virtual
+ AFHDS3_FRM_EXT_V = 0x58, //virtual
AFHDS2A_ID_PRES = 0x41, // Pressure
AFHDS2A_ID_ODO1 = 0x7C, // Odometer1
AFHDS2A_ID_ODO2 = 0x7D, // Odometer2
@@ -79,8 +80,9 @@ enum
AFHDS2A_ID_S88 = 0x88,
AFHDS2A_ID_S89 = 0x89,
AFHDS2A_ID_S8a = 0x8A,
-
- AFHDS2A_ID_ALT_FLYSKY = 0xF9, // Altitude 2 bytes signed in m - used in FlySky native TX - SIGNED value
+ AFHDS2A_ID_RX_SIG_AFHDS3 = 0xF7, // SIG
+ AFHDS2A_ID_RX_SNR_AFHDS3 = 0xF8, // SNR
+ AFHDS2A_ID_ALT_FLYSKY = 0xF9, // Altitude 2 bytes signed in m - used in FlySky native TX
AFHDS2A_ID_RX_SNR = 0xFA, // SNR
AFHDS2A_ID_RX_NOISE = 0xFB, // Noise
AFHDS2A_ID_RX_RSSI = 0xFC, // RSSI
@@ -120,6 +122,8 @@ const FlySkySensor flySkySensors[] = {
{AFHDS2A_ID_FLIGHT_MODE, ZSTR_FLIGHT_MODE, UNIT_RAW, 0}, // 2 bytes index
{AFHDS2A_ID_PRES, ZSTR_PRES, UNIT_RAW, 2}, // 4 bytes In fact Temperature + Pressure -> Altitude
{AFHDS2A_ID_PRES | 0x100, ZSTR_TEMP2, UNIT_CELSIUS, 1}, // 2 bytes Temperature
+ {AFHDS3_FRM_TEMP, ZSTR_TEMP2, UNIT_CELSIUS, 1}, // 2 bytes temperature
+ {AFHDS3_FRM_EXT_V, ZSTR_TXV, UNIT_VOLTS, 2}, // 2 bytes voltage
{AFHDS2A_ID_ODO1, ZSTR_ODO1, UNIT_METERS, 2}, // 2 bytes Odometer1 -- some magic with 330 needed
{AFHDS2A_ID_ODO2, ZSTR_ODO2, UNIT_METERS, 2}, // 2 bytes Odometer2 -- some magic with 330 needed
{AFHDS2A_ID_SPE, ZSTR_ASPD, UNIT_KMH, 2}, // 2 bytes Speed km/h -- some magic with 330 needed
@@ -128,7 +132,8 @@ const FlySkySensor flySkySensors[] = {
{AFHDS2A_ID_GPS_LON, ZSTR_GPS, UNIT_RAW, 7}, // 4 bytes signed WGS84 in degrees * 1E7
{AFHDS2A_ID_GPS_ALT, ZSTR_GPSALT, UNIT_METERS, 2}, // 4 bytes signed GPS alt m*100
{AFHDS2A_ID_ALT, ZSTR_ALT, UNIT_METERS, 2}, // 4 bytes signed Alt m*100
-
+ {AFHDS2A_ID_RX_SIG_AFHDS3, ZSTR_RX_QUALITY, UNIT_RAW, 0}, // RX error rate
+ {AFHDS2A_ID_RX_SNR_AFHDS3, ZSTR_RX_SNR, UNIT_DB, 1}, // RX SNR
{AFHDS2A_ID_RX_SNR, ZSTR_RX_SNR, UNIT_DB, 0}, // RX SNR
{AFHDS2A_ID_RX_NOISE, ZSTR_RX_NOISE, UNIT_DB, 0}, // RX Noise
{AFHDS2A_ID_RX_RSSI, ZSTR_RSSI, UNIT_DB, 0}, // RX RSSI (0xfc)
@@ -140,7 +145,7 @@ const FlySkySensor flySkySensors[] = {
int32_t getALT(uint32_t value);
-static void processFlySkySensor(const uint8_t * packet, uint8_t type)
+void processFlySkySensor(const uint8_t * packet, uint8_t type)
{
uint8_t buffer[8];
uint16_t id = packet[0];
@@ -156,13 +161,17 @@ static void processFlySkySensor(const uint8_t * packet, uint8_t type)
if (id == 0) id = 0x100; // Some part of OpenTX does not like sensor with id and instance 0, remap to 0x100
if (id == AFHDS2A_ID_RX_NOISE || id == AFHDS2A_ID_RX_RSSI) {
- value = -value;
+ value = 135 - value;
}
else if (id == AFHDS2A_ID_RX_ERR_RATE) {
value = 100 - value;
telemetryData.rssi.set(value);
if (value > 0) telemetryStreaming = TELEMETRY_TIMEOUT10ms;
}
+ else if(id == AFHDS2A_ID_RX_SIG_AFHDS3) {
+ telemetryData.rssi.set(value);
+ if(value>0) telemetryStreaming = TELEMETRY_TIMEOUT10ms;
+ }
else if (id == AFHDS2A_ID_PRES && value) {
// Extract temperature to a new sensor
setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, id | 0x100, 0, instance, ((value >> 19) - 400), UNIT_CELSIUS, 1);
@@ -216,7 +225,7 @@ static void processFlySkySensor(const uint8_t * packet, uint8_t type)
for (const FlySkySensor * sensor = flySkySensors; sensor->id; sensor++) {
if (sensor->id != id) continue;
if (sensor->unit == UNIT_CELSIUS) value -= 400; // Temperature sensors have 40 degree offset
- else if (sensor->unit == UNIT_VOLTS) value = (uint16_t) value; // Voltage types are unsigned 16bit integers
+ else if (sensor->unit == UNIT_VOLTS) value = (int16_t) value; // Voltage types are unsigned 16bit integers
setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, id, 0, instance, value, sensor->unit, sensor->precision);
return;
}
@@ -282,7 +291,7 @@ void processFlySkyTelemetryData(uint8_t data, uint8_t * rxBuffer, uint8_t &rxBuf
debugPrintf("[%02X %02X %02X%02X] ", rxBuffer[i*4+2], rxBuffer[i*4 + 3],
rxBuffer[i*4 + 4], rxBuffer[i*4 + 5]);
}
- debugPrintf("\r\n");
+ debugPrintf(CRLF);
#endif
if (data == 0xAA) processFlySkyPacket(rxBuffer + 1);
else if (data == 0xAC) processFlySkyPacketAC(rxBuffer + 1);
@@ -390,4 +399,4 @@ int32_t getALT(uint32_t value)
if (neg ^ tempNegative) result = result * -1;
return result;
-}
\ No newline at end of file
+}
diff --git a/radio/src/telemetry/flysky_ibus.h b/radio/src/telemetry/flysky_ibus.h
index bfb0db640..dd30e0058 100644
--- a/radio/src/telemetry/flysky_ibus.h
+++ b/radio/src/telemetry/flysky_ibus.h
@@ -21,6 +21,8 @@
#ifndef _FLYSKY_IBUS_H
#define _FLYSKY_IBUS_H
+void processFlySkySensor(const uint8_t *packet, uint8_t type);
+
void processFlySkyTelemetryData(uint8_t data, uint8_t * rxBuffer, uint8_t &rxBufferCount);
void flySkySetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance);
diff --git a/radio/src/telemetry/frsky.cpp b/radio/src/telemetry/frsky.cpp
index 0fe1a5bfd..611ece4ac 100644
--- a/radio/src/telemetry/frsky.cpp
+++ b/radio/src/telemetry/frsky.cpp
@@ -32,6 +32,11 @@ void processFrskyTelemetryData(uint8_t data)
auxSerialPutc(data);
}
#endif
+#if defined(AUX2_SERIAL)
+ if (g_eeGeneral.aux2SerialMode == UART_MODE_TELEMETRY_MIRROR) {
+ aux2SerialPutc(data);
+ }
+#endif
if (pushFrskyTelemetryData(data)) {
if (IS_FRSKY_SPORT_PROTOCOL()) {
diff --git a/radio/src/telemetry/frsky.h b/radio/src/telemetry/frsky.h
index d4a9ab87a..751196d1c 100644
--- a/radio/src/telemetry/frsky.h
+++ b/radio/src/telemetry/frsky.h
@@ -21,9 +21,9 @@
#ifndef _FRSKY_H_
#define _FRSKY_H_
-#include "../definitions.h"
+#include "../../definitions.h"
#include "telemetry_holders.h"
-#include "../io/frsky_pxx2.h"
+#include "../../io/frsky_pxx2.h"
// Receive buffer state machine state enum
enum FrSkyDataState {
@@ -33,7 +33,12 @@ enum FrSkyDataState {
STATE_DATA_XOR,
};
-#define FRSKY_SPORT_BAUDRATE 57600
+#define FRSKY_SPORT_BAUDRATE 57600
+#if defined(RADIO_TX16S)
+#define FRSKY_TELEM_MIRROR_BAUDRATE 115200
+#else
+#define FRSKY_TELEM_MIRROR_BAUDRATE FRSKY_SPORT_BAUDRATE
+#endif
#define FRSKY_D_BAUDRATE 9600
@@ -150,6 +155,16 @@ enum FrSkyDataState {
#define ESC_RPM_CONS_LAST_ID 0x0B6f
#define ESC_TEMPERATURE_FIRST_ID 0x0B70
#define ESC_TEMPERATURE_LAST_ID 0x0B7f
+#define RB3040_OUTPUT_FIRST_ID 0x0B80
+#define RB3040_OUTPUT_LAST_ID 0x0B8F
+#define RB3040_CH1_2_FIRST_ID 0x0B90
+#define RB3040_CH1_2_LAST_ID 0x0B9F
+#define RB3040_CH3_4_FIRST_ID 0x0BA0
+#define RB3040_CH3_4_LAST_ID 0x0BAF
+#define RB3040_CH5_6_FIRST_ID 0x0BB0
+#define RB3040_CH5_6_LAST_ID 0x0BBF
+#define RB3040_CH7_8_FIRST_ID 0x0BC0
+#define RB3040_CH7_8_LAST_ID 0x0BCF
#define X8R_FIRST_ID 0x0c20
#define X8R_LAST_ID 0x0c2F
#define S6R_FIRST_ID 0x0c30
@@ -177,6 +192,7 @@ enum FrSkyDataState {
#define DIY_STREAM_FIRST_ID 0x5000
#define DIY_STREAM_LAST_ID 0x50FF
#define FACT_TEST_ID 0xF000
+#define VALID_FRAME_RATE_ID 0xF010
#define RSSI_ID 0xF101
#define ADC1_ID 0xF102
#define ADC2_ID 0xF103
@@ -282,15 +298,15 @@ inline bool isRasValueValid()
{
return true;
}
-#elif defined(PCBX10)
+#elif defined(PCBTARANIS)
inline bool isRasValueValid()
{
- return false;
+ return telemetryData.xjtVersion != 0x00FF;
}
-#elif defined(PCBX9DP) || defined(PCBX9E)
+#elif defined(PCBHORUS)
inline bool isRasValueValid()
{
- return telemetryData.xjtVersion != 0x0000 && telemetryData.xjtVersion != 0x00FF;
+ return true;
}
#else
inline bool isRasValueValid()
diff --git a/radio/src/telemetry/frsky_d.cpp b/radio/src/telemetry/frsky_d.cpp
index 67445c193..c1ad3f9d5 100644
--- a/radio/src/telemetry/frsky_d.cpp
+++ b/radio/src/telemetry/frsky_d.cpp
@@ -227,6 +227,8 @@ void processHubPacket(uint8_t id, int16_t value)
else if (id == VOLTS_ID) {
unit = UNIT_CELLS;
uint32_t cellData = (uint32_t)data;
+ if (((cellData & 0x00F0) >> 4) >= MAX_CELLS)
+ return;
data = ((cellData & 0x00F0) << 12) + (((((cellData & 0xFF00) >> 8) + ((cellData & 0x000F) << 8))) / 5);
}
else if (id == GPS_DAY_MONTH_ID) {
@@ -264,7 +266,7 @@ void processHubPacket(uint8_t id, int16_t value)
data *= 10;
}
}
-
+
setTelemetryValue(PROTOCOL_TELEMETRY_FRSKY_D, id, 0, 0, data, unit, precision);
}
@@ -326,4 +328,4 @@ void frskyDSetDefault(int index, uint16_t id)
}
storageDirty(EE_MODEL);
-}
+}
\ No newline at end of file
diff --git a/radio/src/telemetry/frsky_pxx2.cpp b/radio/src/telemetry/frsky_pxx2.cpp
index 7d596ecc4..8ed11be1c 100644
--- a/radio/src/telemetry/frsky_pxx2.cpp
+++ b/radio/src/telemetry/frsky_pxx2.cpp
@@ -86,6 +86,12 @@ void processReceiverSettingsFrame(uint8_t module, const uint8_t * frame)
if (frame[4] & PXX2_RX_SETTINGS_FLAG1_TELEMETRY_DISABLED)
destination->telemetryDisabled = 1;
+ if (frame[4] & PXX2_RX_SETTINGS_FLAG1_TELEMETRY_25MW)
+ destination->telemetry25mw = 1;
+
+ if (frame[4] & PXX2_RX_SETTINGS_FLAG1_ENABLE_PWM_CH5_CH6)
+ destination->enablePwmCh5Ch6 = 1;
+
uint8_t outputsCount = min(16, frame[0] - 4);
destination->outputsCount = outputsCount;
for (uint8_t pin = 0; pin < outputsCount; pin++) {
diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp
index d67da2559..d26946534 100644
--- a/radio/src/telemetry/frsky_sport.cpp
+++ b/radio/src/telemetry/frsky_sport.cpp
@@ -30,6 +30,7 @@ struct FrSkySportSensor {
};
const FrSkySportSensor sportSensors[] = {
+ { VALID_FRAME_RATE_ID, VALID_FRAME_RATE_ID, 0, ZSTR_VFR, UNIT_PERCENT, 0 },
{ RSSI_ID, RSSI_ID, 0, ZSTR_RSSI, UNIT_DB, 0 },
#if defined(MULTIMODULE)
{ TX_RSSI_ID, TX_RSSI_ID, 0, ZSTR_TX_RSSI , UNIT_DB , 0 },
@@ -84,6 +85,15 @@ const FrSkySportSensor sportSensors[] = {
{ GASSUIT_AVG_FLOW_FIRST_ID, GASSUIT_AVG_FLOW_LAST_ID, 0, ZSTR_GASSUIT_AVG_FLOW, UNIT_MILLILITERS_PER_MINUTE, 0 },
{ SBEC_POWER_FIRST_ID, SBEC_POWER_LAST_ID, 0, ZSTR_SBEC_VOLTAGE, UNIT_VOLTS, 2 },
{ SBEC_POWER_FIRST_ID, SBEC_POWER_LAST_ID, 1, ZSTR_SBEC_CURRENT, UNIT_AMPS, 2 },
+ { RB3040_OUTPUT_FIRST_ID, RB3040_OUTPUT_LAST_ID, 0, ZSTR_RB3040_EXTRA_STATE, UNIT_BITFIELD, 0 },
+ { RB3040_CH1_2_FIRST_ID, RB3040_CH1_2_LAST_ID, 0, ZSTR_RB3040_CHANNEL1, UNIT_AMPS, 2 },
+ { RB3040_CH1_2_FIRST_ID, RB3040_CH1_2_LAST_ID, 1, ZSTR_RB3040_CHANNEL2, UNIT_AMPS, 2 },
+ { RB3040_CH3_4_FIRST_ID, RB3040_CH3_4_LAST_ID, 0, ZSTR_RB3040_CHANNEL3, UNIT_AMPS, 2 },
+ { RB3040_CH3_4_FIRST_ID, RB3040_CH3_4_LAST_ID, 1, ZSTR_RB3040_CHANNEL4, UNIT_AMPS, 2 },
+ { RB3040_CH5_6_FIRST_ID, RB3040_CH5_6_LAST_ID, 0, ZSTR_RB3040_CHANNEL5, UNIT_AMPS, 2 },
+ { RB3040_CH5_6_FIRST_ID, RB3040_CH5_6_LAST_ID, 1, ZSTR_RB3040_CHANNEL6, UNIT_AMPS, 2 },
+ { RB3040_CH7_8_FIRST_ID, RB3040_CH7_8_LAST_ID, 0, ZSTR_RB3040_CHANNEL7, UNIT_AMPS, 2 },
+ { RB3040_CH7_8_FIRST_ID, RB3040_CH7_8_LAST_ID, 1, ZSTR_RB3040_CHANNEL8, UNIT_AMPS, 2 },
{ 0, 0, 0, NULL, UNIT_RAW, 0 } // sentinel
};
@@ -120,7 +130,7 @@ uint16_t rboxState;
void sportProcessTelemetryPacket(uint16_t id, uint8_t subId, uint8_t instance, uint32_t data, TelemetryUnit unit=UNIT_RAW)
{
const FrSkySportSensor * sensor = getFrSkySportSensor(id, subId);
- uint8_t precision = 0;
+ uint8_t precision = 255;
if (sensor) {
if (unit == UNIT_RAW)
unit = sensor->unit;
@@ -129,6 +139,8 @@ void sportProcessTelemetryPacket(uint16_t id, uint8_t subId, uint8_t instance, u
if (unit == UNIT_CELLS) {
uint8_t cellsCount = (data & 0xF0) >> 4;
uint8_t cellIndex = (data & 0x0F);
+ if (cellIndex >= MAX_CELLS)
+ return;
uint32_t mask = (cellsCount << 24) + (cellIndex << 16);
setTelemetryValue(PROTOCOL_TELEMETRY_FRSKY_SPORT, id, subId, instance, mask + (((data & 0x000FFF00) >> 8) / 5), unit, precision);
if (cellIndex+1 < cellsCount) {
@@ -167,11 +179,20 @@ void sportProcessTelemetryPacketWithoutCrc(uint8_t origin, const uint8_t * packe
if (primId == DATA_FRAME) {
uint8_t originMask;
+ uint8_t moduleIndex;
if (origin == TELEMETRY_ENDPOINT_SPORT) {
+#if defined(SIMU) && defined(INTERNAL_MODULE_PXX2)
+ // When running simu on ACCESS radio, we set the origin as internal module
+ moduleIndex = 0;
+ origin = 0;
+ originMask = 0x01;
+#else
+ moduleIndex = isSportLineUsedByInternalModule() ? 0 : 1;
originMask = 0x04;
+#endif
}
else {
- uint8_t moduleIndex = (origin >> 2);
+ moduleIndex = (origin >> 2);
originMask = 0x01 << moduleIndex;
}
uint8_t instance = physicalId + (origin << 5);
@@ -203,19 +224,29 @@ void sportProcessTelemetryPacketWithoutCrc(uint8_t origin, const uint8_t * packe
}
#endif
}
+ else if (dataId == VALID_FRAME_RATE_ID) {
+ data = 100 - SPORT_DATA_U8(packet);
+ }
else if (dataId == R9_PWR_ID) {
- uint32_t r9pwr[] = {100, 200, 500, 1000};
- data = r9pwr[SPORT_DATA_U8(packet) & 0x03];
+ // convert 'dBm' to 'mW'
+ static const uint32_t r9pwrs[][2] = {{0, 1}, {5, 3}, {10, 10}, {13, 20}, {14, 25}, {20, 100}, {23, 200}, {27, 500}, {30, 1000}};
+ uint32_t dBm = SPORT_DATA_U8(packet);
+ for (auto & r9pwr : r9pwrs) {
+ if (dBm == r9pwr[0]) {
+ data = r9pwr[1];
+ break;
+ }
+ }
}
else if (dataId == XJT_VERSION_ID) {
telemetryData.xjtVersion = HUB_DATA_U16(packet);
if (!isRasValueValid()) {
- telemetryData.setSwr(origin >> 2, 0);
+ telemetryData.setSwr(moduleIndex, 0);
}
}
else if (dataId == RAS_ID) {
if (isRasValueValid()) {
- telemetryData.setSwr(origin >> 2, SPORT_DATA_U8(packet));
+ telemetryData.setSwr(moduleIndex, SPORT_DATA_U8(packet));
}
}
@@ -302,6 +333,10 @@ void sportProcessTelemetryPacketWithoutCrc(uint8_t origin, const uint8_t * packe
}
#endif
}
+ else if (dataId >= RB3040_CH1_2_FIRST_ID && dataId <= RB3040_CH7_8_LAST_ID) {
+ sportProcessTelemetryPacket(dataId, 0, instance, data & 0xffff);
+ sportProcessTelemetryPacket(dataId, 1, instance, (data >> 16u) & 0xffff);
+ }
else {
sportProcessTelemetryPacket(dataId, 0, instance, data);
}
diff --git a/radio/src/telemetry/hitec.cpp b/radio/src/telemetry/hitec.cpp
index 3d4770b81..febf32900 100644
--- a/radio/src/telemetry/hitec.cpp
+++ b/radio/src/telemetry/hitec.cpp
@@ -401,7 +401,7 @@ void processHitecTelemetryData(uint8_t data, uint8_t * rxBuffer, uint8_t &rxBuff
for (int i=0; i<5; i++) {
debugPrintf("%02X ", rxBuffer[4+i]);
}
- debugPrintf("\r\n");
+ debugPrintf(CRLF);
#endif
processHitecPacket(rxBuffer + 1);
rxBufferCount = 0;
diff --git a/radio/src/telemetry/hott.cpp b/radio/src/telemetry/hott.cpp
index f36236add..f35b1544d 100644
--- a/radio/src/telemetry/hott.cpp
+++ b/radio/src/telemetry/hott.cpp
@@ -16,26 +16,27 @@
#include "opentx.h"
/* Telemetry
-packet[0] = TX RSSI value
-packet[1] = TX LQI value
-packet[2] = frame number
-packet[3-12] telemetry data
+packet[0] = TX RSSI value
+packet[1] = TX LQI value
+packet[2] = Telemetry type
+packet[3] = Telemetry page
+packet[4-13] = Telemetry data
-The frame number takes the following values: 0x00, 0x01, 0x02, 0x03 and 0x04. The frames can be present or not, they also do not have to follow each others.
-Here is a description of the telemetry data for each frame number:
-- frame 0x00
-[3] = [12] = ??
-[4] = RX_Voltage*10 in V
-[5] = Temperature-20 in °C
-[6] = RX_RSSI
-[7] = RX_LQI ??
-[8] = RX_STR ??
-[9,10] = [10]*256+[9]=max lost packet time in ms, max value seems 2s=0x7D0
-[11] = 0x00 ??
-- frame 0x01 Unknown
-- frame 0x02 Unknown
-- frame 0x03 Unknown
-- frame 0x04 Unknown
+Telemetry type: 0x00 RX, 0x09 Vario, 0x0A GPS, 0x0B not seen, 0x0C ESC, 0x0D GAM, 0x0E EAM, 0x80 Text config mode
+Telemetry page: 0x00..0x04 for all telemetry except Text config mode which is 0x00..0x12. The pages can be present or not, they also do not have to follow each others.
+
+Here is a description of the RX telemetry:
+ [2] = 0x00 -> Telemetry type RX
+ [3] = 0x00 -> Telemetry page 0
+ [4] = ?? looks to be a copy of [7]
+ [5] = RX_Voltage*10 in V
+ [6] = Temperature-20 in °C
+ [7] = RX_RSSI CC2500 formated (a<128:a/2-71dBm, a>=128:(a-256)/2-71dBm)
+ [8] = RX_LQI in %
+ [9] = RX_MIN_Voltage*10 in V
+ [10,11] = [11]*256+[10]=max lost packet time in ms, max value seems 2s=0x7D0
+ [12] = 0x00 ??
+ [13] = ?? looks to be a copy of [7]
*/
struct HottSensor
@@ -49,22 +50,54 @@ struct HottSensor
// telemetry frames
enum
{
- HOTT_FRAME_00 = 0x00,
- HOTT_FRAME_01 = 0x01,
- HOTT_FRAME_02 = 0x02,
- HOTT_FRAME_03 = 0x03,
- HOTT_FRAME_04 = 0x04,
+ HOTT_PAGE_00 = 0x00,
+ HOTT_PAGE_01 = 0x01,
+ HOTT_PAGE_02 = 0x02,
+ HOTT_PAGE_03 = 0x03,
+ HOTT_PAGE_04 = 0x04,
};
-#define HOTT_TELEM_NORMAL 0x00
-#define HOTT_TELEM_BIND 0x40
-#define HOTT_TELEM_MENU 0x80
+enum
+{
+ HOTT_TELEM_RX = 0x00,
+ HOTT_TELEM_VARIO = 0x09,
+ HOTT_TELEM_GPS = 0x0A,
+ HOTT_TELEM_ESC = 0x0C,
+ HOTT_TELEM_GAM = 0x0D,
+ HOTT_TELEM_EAM = 0x0E,
+ HOTT_TELEM_TEXT = 0x80,
+};
// telemetry sensors ID
enum
{
HOTT_ID_RX_VOLTAGE = 0x0004, // RX_Batt Voltage
HOTT_ID_TEMP1 = 0x0005, // RX Temperature sensor
+ HOTT_ID_VARIO = 0x0006, // Vario sensor
+ HOTT_ID_ALT = 0x0007, // Alt sensor
+ HOTT_ID_HDG = 0x0008, // Heading sensor
+ HOTT_ID_GSPD = 0x0008, // Ground speed sensor
+ HOTT_ID_GPS_LAT_LONG = 0x0009, // GPS sensor
+ HOTT_ID_GPS_COUNT = 0x000A, // GPS sat count
+ HOTT_ID_CELS = 0x000B, // Cels L sensor
+ HOTT_ID_CELS_H = 0x000C, // Cels H sensor
+ HOTT_ID_VOLT1 = 0x000D, // Voltage sensor
+ HOTT_ID_VOLT2 = 0x000E, // Voltage sensor
+ HOTT_ID_AMP1 = 0x000F, // Amp sensor
+ HOTT_ID_AMP2 = 0x0010, // Amp sensor
+ HOTT_ID_RPM1 = 0x0011, // RPM sensor
+ HOTT_ID_RPM2 = 0x0012, // RPM sensor
+ HOTT_ID_ESC_VIN = 0x0013, // ESC Volt
+ HOTT_ID_ESC_CUR = 0x0014, // ESC Amp
+ HOTT_ID_ESC_TBEC = 0x0015, // BEC Temp
+ HOTT_ID_ESC_BCUR = 0x0016, // BEC Cur
+ HOTT_ID_ESC_VBEC = 0x0017, // BEC Volt
+ HOTT_ID_BCAPA = 0x0018, // Batt capacity
+ HOTT_ID_TEMP2 = 0x0019, // Temperature sensor 2
+ HOTT_ID_AIR_SPEED = 0x001A,
+ HOTT_ID_VOLT3 = 0x001B, // Voltage sensor
+ HOTT_ID_FUEL = 0x001C, // Fuel percentage
+
HOTT_TX_RSSI_ID = 0xFF00, // Pseudo id outside 1 byte range of Hott sensors
HOTT_TX_LQI_ID = 0xFF01, // Pseudo id outside 1 byte range of Hott sensors
HOTT_RX_RSSI_ID = 0xFF02, // Pseudo id outside 1 byte range of Hott sensors
@@ -72,18 +105,39 @@ enum
};
const HottSensor hottSensors[] = {
- //frame 00
- {HOTT_ID_RX_VOLTAGE, ZSTR_BATT, UNIT_VOLTS, 1}, // RX_Batt Voltage
- {HOTT_ID_TEMP1, ZSTR_TEMP1, UNIT_CELSIUS, 0}, // RX Temperature sensor
- //frame 01
- //frame 02
- //frame 03
- //frame 04
- {HOTT_TX_RSSI_ID, ZSTR_TX_RSSI, UNIT_RAW, 0}, // Pseudo id outside 1 byte range of Hott sensors
- {HOTT_TX_LQI_ID, ZSTR_TX_QUALITY, UNIT_RAW, 0}, // Pseudo id outside 1 byte range of Hott sensors
- {HOTT_RX_RSSI_ID, ZSTR_RSSI, UNIT_DB, 0}, // RX RSSI
- {HOTT_RX_LQI_ID, ZSTR_RX_QUALITY, UNIT_RAW, 0}, // RX LQI
- {0x00, NULL, UNIT_RAW, 0}, // sentinel
+ //HOTT_TELEM_RX
+ {HOTT_ID_RX_VOLTAGE, ZSTR_BATT, UNIT_VOLTS, 1}, // RX_Batt Voltage
+ {HOTT_ID_TEMP1, ZSTR_TEMP1, UNIT_CELSIUS, 0}, // Temperature sensor 1
+ {HOTT_ID_TEMP2, ZSTR_TEMP2, UNIT_CELSIUS, 0}, // Temperature sensor 2
+ {HOTT_ID_VARIO, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 2}, // Vario sensor
+ {HOTT_ID_ALT, ZSTR_ALT, UNIT_METERS, 0}, // Alt sensor
+ {HOTT_ID_HDG, ZSTR_HDG, UNIT_DEGREE, 0}, // Heading sensor
+ {HOTT_ID_GSPD, ZSTR_GSPD, UNIT_KMH, 0}, // Ground speed sensor
+ {HOTT_ID_GPS_LAT_LONG, ZSTR_GPS, UNIT_GPS, 0}, // GPS position
+ {HOTT_ID_GPS_COUNT, ZSTR_SATELLITES, UNIT_RAW, 0}, // GPS sat count
+ {HOTT_ID_VOLT1, ZSTR_A1, UNIT_VOLTS, 1}, // Voltage sensor 1
+ {HOTT_ID_VOLT2, ZSTR_A2, UNIT_VOLTS, 1}, // Voltage sensor 2
+ {HOTT_ID_VOLT3, ZSTR_A3, UNIT_VOLTS, 1}, // Voltage sensor 3
+ {HOTT_ID_AMP1, ZSTR_CURR, UNIT_AMPS, 1}, // Amp sensor 1
+ {HOTT_ID_AMP2, ZSTR_CURR, UNIT_AMPS, 1}, // Amp sensor 2
+ {HOTT_ID_RPM1, ZSTR_RPM, UNIT_RPMS, 0}, // RPM1
+ {HOTT_ID_RPM2, ZSTR_RPM2, UNIT_RPMS, 0}, // RPM2
+ {HOTT_ID_ESC_VIN, ZSTR_ESC_VIN, UNIT_VOLTS, 1}, // ESC VIN
+ {HOTT_ID_BCAPA, ZSTR_SMART_BAT_CAPACITY, UNIT_MAH, 0}, // Batt Capa
+ {HOTT_ID_ESC_CUR, ZSTR_ESC_CUR, UNIT_AMPS, 1}, // ESC Amp
+ {HOTT_ID_ESC_TBEC, ZSTR_ESC_TBEC, UNIT_CELSIUS, 0}, // ESC BEC Temp
+ {HOTT_ID_ESC_BCUR, ZSTR_ESC_BCUR, UNIT_AMPS, 1}, // ESC BEC Amp
+ {HOTT_ID_ESC_VBEC, ZSTR_ESC_VBEC, UNIT_VOLTS, 1}, // ESC BEC Volt
+ {HOTT_ID_CELS, ZSTR_CELLS, UNIT_CELLS, 2}, // Batt cells
+ {HOTT_ID_CELS_H, ZSTR_CELLS, UNIT_CELLS, 2}, // Batt H cells
+ {HOTT_ID_AIR_SPEED, ZSTR_ASPD, UNIT_KMH, 0}, // Air speed
+ {HOTT_ID_FUEL, ZSTR_FUEL, UNIT_PERCENT, 0}, // Fuel
+
+ {HOTT_TX_RSSI_ID, ZSTR_TX_RSSI, UNIT_DB, 0}, // Pseudo id outside 1 byte range of Hott sensors
+ {HOTT_TX_LQI_ID, ZSTR_TX_QUALITY, UNIT_RAW, 0}, // Pseudo id outside 1 byte range of Hott sensors
+ {HOTT_RX_RSSI_ID, ZSTR_RSSI, UNIT_DB, 0}, // RX RSSI
+ {HOTT_RX_LQI_ID, ZSTR_RX_QUALITY, UNIT_RAW, 0}, // RX LQI
+ {0x00, NULL, UNIT_RAW, 0}, // sentinel
};
const HottSensor * getHottSensor(uint16_t id)
@@ -95,22 +149,30 @@ const HottSensor * getHottSensor(uint16_t id)
return nullptr;
}
+int16_t processHoTTdBm(uint8_t value)
+{
+ if (value >= 128) {
+ value = 256 - value;
+ }
+ return value / 2 -71;
+}
+
void processHottPacket(const uint8_t * packet)
{
// Set TX RSSI Value
- setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_TX_RSSI_ID, 0, 0, packet[0]>>1, UNIT_RAW, 0);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_TX_RSSI_ID, 0, 0, processHoTTdBm(packet[0]), UNIT_RAW, 0);
// Set TX LQI Value
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_TX_LQI_ID, 0, 0, packet[1], UNIT_RAW, 0);
#if defined(LUA)
- #define HOTT_MENU_NBR_PAGE 0x13
+#define HOTT_MENU_NBR_PAGE 0x13
// Config menu consists of the different telem pages put all together
// [3] = config mennu page 0x00 to 0x12.
// Page X [4] = seems like all the telem pages with the same value are going together to make the full config menu text. Seen so far 'a', 'b', 'c', 'd'
// Page X [5..13] = 9 ascii chars to be displayed, char is highlighted when ascii|0x80
// Screen display is 21 characters large which means that once the first 21 chars are filled go to the begining of the next line
// Menu commands are sent through TX packets:
- // packet[28]= 0xXF=>no key press, 0xXD=>down, 0xXB=>up, 0xX9=>enter, 0xXE=>right, 0xX7=>left with X=0 or D
+ // packet[28]= 0xXF=>no key press, 0xXD=>down, 0xXB=>up, 0xX9=>enter, 0xXE=>right, 0xX7=>left with X=0, 9=Vario, A=GPS, B=Unknown, C=ESC, D=GAM, or E=EAM
// packet[29]= 0xX1/0xX9 with X=0 or X counting 0,1,1,2,2,..,9,9
if (Multi_Buffer && memcmp(Multi_Buffer, "HoTT", 4) == 0) {
// HoTT Lua script is running
@@ -118,21 +180,31 @@ void processHottPacket(const uint8_t * packet)
// Init
memset(&Multi_Buffer[6], ' ', HOTT_MENU_NBR_PAGE * 9); // Clear text buffer
}
-
- if (packet[3] < HOTT_MENU_NBR_PAGE && Multi_Buffer[5] >= 0xD7 && Multi_Buffer[5] <= 0xDF) {
- Multi_Buffer[4] = packet[4]; // Store current menu being received
+
+ if (packet[2] == HOTT_TELEM_TEXT && packet[3] < HOTT_MENU_NBR_PAGE && (Multi_Buffer[5] & 0x80) && (Multi_Buffer[5] & 0x0F) >= 0x07) {
+ Multi_Buffer[4] = packet[4]; // Store detected sensors
memcpy(&Multi_Buffer[6 + packet[3] * 9], &packet[5], 9); // Store the received page in the buffer
}
return;
}
#endif
+ struct HottGPSMinutes
+ {
+ uint16_t value: 14;
+ uint16_t isNegative: 1;
+ uint16_t spare: 1;
+ };
+
const HottSensor * sensor;
int32_t value;
+ static uint8_t prev_page = 0, prev_value = 0;
+ static HottGPSMinutes min = {};
+ int16_t deg = 0, sec = 0;
- if (packet[2] == HOTT_TELEM_NORMAL) {
- switch (packet[3]) {
- case HOTT_FRAME_00:
+ switch (packet[2]) { // Telemetry type
+ case HOTT_TELEM_RX:
+ if (packet[3] == 0) { // Telemetry page: only page 0 is for RX
// RX_VOLT
value = packet[5];
sensor = getHottSensor(HOTT_ID_RX_VOLTAGE);
@@ -142,21 +214,433 @@ void processHottPacket(const uint8_t * packet)
sensor = getHottSensor(HOTT_ID_TEMP1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP1, 0, 0, value, sensor->unit, sensor->precision);
// RX_RSSI
- setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_RX_RSSI_ID, 0, 0, packet[7], UNIT_DB, 0);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_RX_RSSI_ID, 0, 0, processHoTTdBm(packet[7]), UNIT_DB, 0);
// RX_LQI
telemetryData.rssi.set(packet[8]);
if (packet[8] > 0)
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_RX_LQI_ID, 0, 0, packet[8], UNIT_RAW, 0);
- break;
+ }
+ break;
- default:
- // unknown
- value = (packet[7] << 24) | (packet[6] << 16) | (packet[5] << 8) | packet[4];
- setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, 0xFE00 | packet[3], 0, 0, value, UNIT_RAW, 0);
- break;
- }
+ case HOTT_TELEM_VARIO:
+ // https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L240
+ switch (packet[3]) { // Telemetry page 1,2,3,4
+ case HOTT_PAGE_01:
+ // packet[6 ] uint8_t altitude_L; //#06 Altitude low uint8_t. In meters. A value of 500 means 0m
+ // packet[7 ] uint8_t altitude_H; //#07 Altitude high uint8_t
+ value = packet[6] + (packet[7] << 8) - 500;
+ sensor = getHottSensor(HOTT_ID_ALT);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ALT, 0, HOTT_TELEM_VARIO, value, sensor->unit, sensor->precision);
+
+ // packet[12] uint8_t climbrate_L; //#12 Climb rate in m/s. Steps of 0.01m/s. Value of 30000 = 0.00 m/s
+ // packet[13] uint8_t climbrate_H; //#13 Climb rate in m/s
+ value = packet[12] + (packet[13] << 8) - 30000;
+ sensor = getHottSensor(HOTT_ID_VARIO);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO, 0, HOTT_TELEM_VARIO, value, sensor->unit, sensor->precision);
+ break;
+ case HOTT_PAGE_02:
+ // packet[12] uint8_t compass_direction; //#42 Compass heading in 2� steps. 1 = 2�
+ value = packet[12] * 2;
+ sensor = getHottSensor(HOTT_ID_HDG);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_HDG, 0, HOTT_TELEM_VARIO, value, sensor->unit, sensor->precision);
+ break;
+ case HOTT_PAGE_03:
+ break;
+ case HOTT_PAGE_04:
+ break;
+ }
+ break;
+
+ case HOTT_TELEM_GPS:
+ // https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L378
+ switch (packet[3]) { // Telemetry page 1,2,3,4
+ case HOTT_PAGE_01:
+ // packet[7 ] uint8_t flight_direction; //#07 flight direction in 2 degreees/step (1 = 2degrees);
+ value = packet[7] * 2;
+ sensor = getHottSensor(HOTT_ID_HDG);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_HDG, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
+
+ // packet[8 ] uint8_t gps_speed_L; //08 km/h
+ // packet[9 ] uint8_t gps_speed_H; //#09
+ value = packet[8] + (packet[9] << 8);
+ sensor = getHottSensor(HOTT_ID_GSPD);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GSPD, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
+
+ // packet[10] uint8_t pos_NS; //#10 north = 0, south = 1
+ // packet[11] uint8_t pos_NS_dm_L; //#11 degree minutes ie N48�39�988
+ // packet[12] uint8_t pos_NS_dm_H; //#12
+ // packet[13] uint8_t pos_NS_sec_L; //#13 position seconds
+ min.value = (int16_t) (packet[11] + (packet[12] << 8));
+ if (packet[10] == 1) {
+ min.isNegative = true;
+ }
+ break;
+
+ case HOTT_PAGE_02:
+ if (prev_page == ((HOTT_TELEM_GPS << 4) | HOTT_PAGE_01)) {
+ // packet[4 ] uint8_t pos_NS_sec_H; //#14
+ deg = min.value / 100;
+ min.value = min.value - deg * 100;
+ sec = prev_value + (packet[4] << 8);
+ value = deg * 1000000 + (min.value * 1000000 + sec * 100) / 60;
+ if (min.isNegative) {
+ value = -value;
+ }
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_LAT_LONG, 0, HOTT_TELEM_GPS, value, UNIT_GPS_LATITUDE, 0);
+ }
+
+ // packet[5 ] uint8_t pos_EW; //#15 east = 0, west = 1
+ // packet[6 ] uint8_t pos_EW_dm_L; //#16 degree minutes ie. E9�25�9360
+ // packet[7 ] uint8_t pos_EW_dm_H; //#17
+ // packet[8 ] uint8_t pos_EW_sec_L; //#18 position seconds
+ // packet[9 ] uint8_t pos_EW_sec_H; //#19
+ min.value = (int16_t) (packet[6] + (packet[7] << 8));
+ sec = (int16_t) (packet[8] + (packet[9] << 8));
+ deg = min.value / 100;
+ min.value = min.value - deg * 100;
+ value = deg * 1000000 + (min.value * 1000000 + sec * 100) / 60;
+ if (packet[5] == 1) {
+ value = -value;
+ }
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_LAT_LONG, 0, HOTT_TELEM_GPS, value, UNIT_GPS_LONGITUDE, 0);
+ // packet[10] uint8_t home_distance_L; //#20 meters
+ // packet[11] uint8_t home_distance_H; //#21
+
+ // packet[12] uint8_t altitude_L; //#22 meters. Value of 500 = 0m
+ // packet[13] uint8_t altitude_H; //#23
+ value = packet[12] + (packet[13] << 8) - 500;
+ sensor = getHottSensor(HOTT_ID_ALT);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ALT, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
+ break;
+
+ case HOTT_PAGE_03:
+ // packet[4 ] uint8_t climbrate_L; //#24 m/s 0.01m/s resolution. Value of 30000 = 0.00 m/s
+ // packet[5 ] uint8_t climbrate_H; //#25
+ value = packet[4] + (packet[5] << 8) - 30000;
+ sensor = getHottSensor(HOTT_ID_VARIO);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
+
+ // packet[6 ] uint8_t climbrate3s; //#26 climbrate in m/3s resolution, value of 120 = 0 m/3s
+ // packet[7 ] uint8_t gps_satelites; //#27 sat count
+ sensor = getHottSensor(HOTT_ID_GPS_COUNT);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_COUNT, 0, HOTT_TELEM_GPS, packet[7], sensor->unit, sensor->precision);
+ // packet[8 ] uint8_t gps_fix_char; //#28 GPS fix character. display, 'D' = DGPS, '2' = 2D, '3' = 3D, '-' = no fix. Where appears this char???
+ // packet[9 ] uint8_t home_direction;//#29 direction from starting point to Model position (2 degree steps)
+ // packet[10] uint8_t angle_roll; //#30 angle roll in 2 degree steps
+ // packet[11] uint8_t angle_nick; //#31 angle in 2degree steps
+ // packet[12] uint8_t angle_compass; //#32 angle in 2degree steps. 1 = 2�, 255 = - 2� (1 uint8_t) North = 0�
+ // packet[13] uint8_t gps_time_h; //#33 UTC time hours
+ break;
+
+ case HOTT_PAGE_04:
+ // packet[4 ] uint8_t gps_time_m; //#34 UTC time minutes
+ // packet[5 ] uint8_t gps_time_s; //#35 UTC time seconds
+ // packet[6 ] uint8_t gps_time_sss; //#36 UTC time milliseconds
+ // packet[7 ] uint8_t msl_altitude_L;//#37 mean sea level altitude
+ // packet[8 ] uint8_t msl_altitude_H;//#38
+ // packet[9 ] uint8_t vibration; //#39 vibrations level in %
+ // packet[10] uint8_t free_char1; //#40 appears right to home distance
+ // packet[11] uint8_t free_char2; //#41 appears right to home direction
+ // packet[12] uint8_t free_char3; //#42 GPS ASCII D=DGPS 2=2D 3=3D -=No Fix
+ break;
+ }
+ break;
+
+ case HOTT_TELEM_ESC:
+ // https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L454
+ switch (packet[3]) { // Telemetry page 1,2,3,4
+ case HOTT_PAGE_01:
+ // packet[7 ] uint8_t input_v_L; //#07 Input voltage low byte
+ // packet[8 ] uint8_t input_v_H; //#08
+ value = packet[7] + (packet[8] << 8);
+ sensor = getHottSensor(HOTT_ID_ESC_VIN);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_VIN, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
+ // packet[11] uint8_t batt_cap_L; //#11 battery capacity in 10mAh steps
+ // packet[12] uint8_t batt_cap_H; //#12
+ value = (packet[11] + (packet[12] << 8)) * 10;
+ sensor = getHottSensor(HOTT_ID_BCAPA);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_BCAPA, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
+ // packet[13] uint8_t esc_temp; //#13 ESC temperature
+ value = packet[13] - 20;
+ sensor = getHottSensor(HOTT_ID_TEMP1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP1, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
+ break;
+
+ case HOTT_PAGE_02:
+ // packet[5 ] uint8_t current_L; //#15 Current in 0.1 steps
+ // packet[6 ] uint8_t current_H; //#16
+ value = packet[5] + (packet[6] << 8);
+ sensor = getHottSensor(HOTT_ID_ESC_CUR);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_CUR, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
+ // packet[9 ] uint8_t rpm_L; //#19 RPM in 10U/min steps
+ // packet[10] uint8_t rpm_H; //#20
+ value = (packet[9] + (packet[10] << 8)) * 10;
+ sensor = getHottSensor(HOTT_ID_RPM1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RPM1, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
+ break;
+
+ case HOTT_PAGE_03:
+ // packet[8 ] uint8_t bec_v; //#28 BEC voltage
+ value = packet[8];
+ sensor = getHottSensor(HOTT_ID_ESC_VBEC);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_VBEC, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
+ // packet[10] uint8_t bec_current; //#30 BEC current
+ value = packet[10];
+ sensor = getHottSensor(HOTT_ID_ESC_BCUR);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_BCUR, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
+ break;
+
+ case HOTT_PAGE_04:
+ // packet[4 ] uint8_t bec_temp; //#34 BEC temperature
+ value = packet[4] - 20;
+ sensor = getHottSensor(HOTT_ID_ESC_TBEC);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_TBEC, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
+ // packet[6 ] uint8_t motor_temp; //#36 Motor or external sensor temperature
+ value = packet[6] - 20;
+ sensor = getHottSensor(HOTT_ID_TEMP2);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP2, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
+ break;
+ }
+ break;
+
+ case HOTT_TELEM_GAM:
+ // https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L151
+ switch (packet[3]) { // Telemetry page 1,2,3,4
+ case HOTT_PAGE_01:
+ sensor = getHottSensor(HOTT_ID_CELS);
+ // packet[7 ] uint8_t cell1_L; //#07 cell 1 voltage lower value. 0.02V steps, 124=2.48V
+ value = packet[7] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 0 << 16 | value, sensor->unit, sensor->precision);
+ // packet[8 ] uint8_t cell2_L; //#08
+ value = packet[8] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 1 << 16 | value, sensor->unit, sensor->precision);
+ // packet[9 ] uint8_t cell3_L; //#09
+ value = packet[9] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 2 << 16 | value, sensor->unit, sensor->precision);
+ // packet[10] uint8_t cell4_L; //#10
+ value = packet[10] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 3 << 16 | value, sensor->unit, sensor->precision);
+ // packet[11] uint8_t cell5_L; //#11
+ value = packet[11] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 4 << 16 | value, sensor->unit, sensor->precision);
+ // packet[12] uint8_t cell6_L; //#12
+ value = packet[12] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 5 << 16 | value, sensor->unit, sensor->precision);
+ // packet[13] uint8_t batt1_L; //#13 battery 1 voltage LSB value. 0.1V steps. 50 = 5.5V
+ break;
+
+ case HOTT_PAGE_02:
+ if (prev_page == ((HOTT_TELEM_GAM << 4) | HOTT_PAGE_01)) {
+ // packet[4 ] uint8_t batt1_H; //#14
+ value = prev_value + (packet[4] << 8);
+ sensor = getHottSensor(HOTT_ID_VOLT2);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT2, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ }
+ // packet[5 ] uint8_t batt2_L; //#15 battery 2 voltage LSB value. 0.1V steps. 50 = 5.5V
+ // packet[6 ] uint8_t batt2_H; //#16
+ value = packet[5] + (packet[6] << 8);
+ sensor = getHottSensor(HOTT_ID_VOLT3);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT3, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[7 ] uint8_t temperature1; //#17 temperature 1. offset of 20. a value of 20 = 0�C
+ value = packet[7] - 20;
+ sensor = getHottSensor(HOTT_ID_TEMP1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[8 ] uint8_t temperature2; //#18 temperature 2. offset of 20. a value of 20 = 0�C
+ value = packet[8] - 20;
+ sensor = getHottSensor(HOTT_ID_TEMP2);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP2, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[9 ] uint8_t fuel_procent; //#19 Fuel capacity in %. Values 0--100, graphical display ranges: 0-25% 50% 75% 100%
+ value = packet[9];
+ sensor = getHottSensor(HOTT_ID_FUEL);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_FUEL, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[10] uint8_t fuel_ml_L; //#20 Fuel in ml scale. Full = 65535!
+ // packet[11] uint8_t fuel_ml_H; //#21
+ // packet[12] uint8_t rpm_L; //#22 RPM in 10 RPM steps. 300 = 3000rpm
+ // packet[13] uint8_t rpm_H; //#23
+ value = (packet[12] + (packet[13] << 8)) * 10;
+ sensor = getHottSensor(HOTT_ID_RPM1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RPM1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ break;
+
+ case HOTT_PAGE_03:
+ // packet[4 ] uint8_t altitude_L; //#24 altitude in meters. offset of 500, 500 = 0m
+ // packet[5 ] uint8_t altitude_H; //#25
+ value = packet[4] + (packet[5] << 8) - 500;
+ sensor = getHottSensor(HOTT_ID_ALT);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ALT, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[6 ] uint8_t climbrate_L; //#26 climb rate in 0.01m/s. Value of 30000 = 0.00 m/s
+ // packet[7 ] uint8_t climbrate_H; //#27
+ value = packet[6] + (packet[7] << 8) - 30000;
+ sensor = getHottSensor(HOTT_ID_VARIO);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[8 ] uint8_t climbrate3s; //#28 climb rate in m/3sec. Value of 120 = 0m/3sec
+ // packet[9 ] uint8_t current_L; //#29 current in 0.1A steps
+ // packet[10] uint8_t current_H; //#30
+ value = packet[9] + (packet[10] << 8);
+ sensor = getHottSensor(HOTT_ID_AMP1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_AMP1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[11] uint8_t main_voltage_L; //#31 Main power voltage using 0.1V steps
+ // packet[12] uint8_t main_voltage_H; //#32
+ value = packet[11] + (packet[12] << 8);
+ sensor = getHottSensor(HOTT_ID_VOLT1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[13] uint8_t batt_cap_L; //#33 used battery capacity in 10mAh steps
+ break;
+
+ case HOTT_PAGE_04:
+ // packet[4 ] uint8_t batt_cap_H; //#34
+ if (prev_page == ((HOTT_TELEM_GAM << 4) | HOTT_PAGE_03)) {
+ value = (prev_value + (packet[4] << 8)) * 10;
+ sensor = getHottSensor(HOTT_ID_BCAPA);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_BCAPA, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ }
+ // packet[5 ] uint8_t speed_L; //#35 (air?) speed in km/h(?) we are using ground speed here per default
+ // packet[6 ] uint8_t speed_H; //#36
+ value = packet[5] + (packet[6] << 8);
+ sensor = getHottSensor(HOTT_ID_AIR_SPEED);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_AIR_SPEED, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[7 ] uint8_t min_cell_volt; //#37 minimum cell voltage in 2mV steps. 124 = 2,48V
+ // packet[8 ] uint8_t min_cell_volt_num; //#38 number of the cell with the lowest voltage
+ // packet[9 ] uint8_t rpm2_L; //#39 RPM in 10 RPM steps. 300 = 3000rpm
+ // packet[10] uint8_t rpm2_H; //#40
+ value = (packet[9] + (packet[10] << 8)) * 10;
+ sensor = getHottSensor(HOTT_ID_RPM2);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RPM2, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
+ // packet[11] uint8_t general_error_number;//#41 Voice error == 12. TODO: more docu
+ // packet[12] uint8_t pressure; //#42 Pressure up to 16bar. 0,1bar scale. 20 = 2bar
+ break;
+ }
+ break;
+
+ case HOTT_TELEM_EAM:
+ // https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L288
+ switch (packet[3]) { // Telemetry page 1,2,3,4
+ case HOTT_PAGE_01:
+ sensor = getHottSensor(HOTT_ID_CELS);
+ // packet[7 ] uint8_t cell1_L; //#07 cell 1 voltage lower value. 0.02V steps, 124=2.48V
+ value = packet[7] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 0 << 16 | value, sensor->unit, sensor->precision);
+ // packet[8 ] uint8_t cell2_L; //#08
+ value = packet[8] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 1 << 16 | value, sensor->unit, sensor->precision);
+ // packet[9 ] uint8_t cell3_L; //#09
+ value = packet[9] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 2 << 16 | value, sensor->unit, sensor->precision);
+ // packet[10] uint8_t cell4_L; //#10
+ value = packet[10] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 3 << 16 | value, sensor->unit, sensor->precision);
+ // packet[11] uint8_t cell5_L; //#11
+ value = packet[11] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 4 << 16 | value, sensor->unit, sensor->precision);
+ // packet[12] uint8_t cell6_L; //#12
+ value = packet[12] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 5 << 16 | value, sensor->unit, sensor->precision);
+ // packet[13] uint8_t cell7_L; //#13
+ // value = packet[13] << 1;
+ // if(value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 6 << 16 | value, sensor->unit, sensor->precision);
+ break;
+
+ case HOTT_PAGE_02:
+ sensor = getHottSensor(HOTT_ID_CELS);
+ // packet[4 ] uint8_t cell1_H; //#14 cell 1 voltage high value. 0.02V steps, 124=2.48V
+ value = packet[4] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 0 << 16 | value, sensor->unit, sensor->precision);
+ // packet[5 ] uint8_t cell2_H; //#15
+ value = packet[5] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 1 << 16 | value, sensor->unit, sensor->precision);
+ // packet[6 ] uint8_t cell3_H; //#16
+ value = packet[6] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 2 << 16 | value, sensor->unit, sensor->precision);
+ // packet[7 ] uint8_t cell4_H; //#17
+ value = packet[7] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 3 << 16 | value, sensor->unit, sensor->precision);
+ // packet[8 ] uint8_t cell5_H; //#18
+ value = packet[8] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 4 << 16 | value, sensor->unit, sensor->precision);
+ // packet[9 ] uint8_t cell6_H; //#19
+ value = packet[9] << 1;
+ if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 5 << 16 | value, sensor->unit, sensor->precision);
+ // packet[10] uint8_t cell7_H; //#20
+ //value = packet[10] << 1;
+ //if(value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 13 << 16 | value, sensor->unit, sensor->precision);
+ // packet[11] uint8_t batt1_voltage_L; //#21 battery 1 voltage lower value in 100mv steps, 50=5V. optionally cell8_L value 0.02V steps
+ // packet[12] uint8_t batt1_voltage_H; //#22
+ value = packet[11] + (packet[12] << 8);
+ sensor = getHottSensor(HOTT_ID_VOLT2);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT2, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+
+ // packet[13] uint8_t batt2_voltage_L; //#23 battery 2 voltage lower value in 100mv steps, 50=5V. optionally cell8_H value. 0.02V steps
+ break;
+
+ case HOTT_PAGE_03:
+ if (prev_page == ((HOTT_TELEM_EAM << 4) | HOTT_PAGE_02)) {
+ // packet[4 ] uint8_t batt2_voltage_H; //#24
+ value = prev_value + (packet[4] << 8);
+ sensor = getHottSensor(HOTT_ID_VOLT3);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT3, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+ }
+ // packet[5 ] uint8_t temp1; //#25 Temperature sensor 1. 20=0�, 46=26� - offset of 20.
+ value = packet[5] - 20;
+ sensor = getHottSensor(HOTT_ID_TEMP1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP1, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+ // packet[6 ] uint8_t temp2; //#26 temperature sensor 2
+ value = packet[6] - 20;
+ sensor = getHottSensor(HOTT_ID_TEMP2);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP2, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+
+ // packet[7 ] uint8_t altitude_L; //#27 Attitude lower value. unit: meters. Value of 500 = 0m
+ // packet[8 ] uint8_t altitude_H; //#28
+ value = packet[7] + (packet[8] << 8) - 500;
+ sensor = getHottSensor(HOTT_ID_ALT);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ALT, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+
+ // packet[9 ] uint8_t current_L; //#29 Current in 0.1 steps
+ // packet[10] uint8_t current_H; //#30
+ value = packet[9] + (packet[10] << 8);
+ sensor = getHottSensor(HOTT_ID_AMP1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_AMP1, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+ // packet[11] uint8_t main_voltage_L; //#31 Main power voltage (drive) in 0.1V steps
+ // packet[12] uint8_t main_voltage_H; //#32
+ value = packet[11] + (packet[12] << 8);
+ sensor = getHottSensor(HOTT_ID_VOLT1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT1, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+ // packet[13] uint8_t batt_cap_L; //#33 used battery capacity in 10mAh steps
+ break;
+
+ case HOTT_PAGE_04:
+ // packet[4 ] uint8_t batt_cap_H; //#34
+ if (prev_page == ((HOTT_TELEM_EAM << 4) | HOTT_PAGE_03)) {
+ value = (prev_value + (packet[4] << 8)) * 10;
+ sensor = getHottSensor(HOTT_ID_BCAPA);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_BCAPA, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+ }
+
+ // packet[5 ] uint8_t climbrate_L; //#35 climb rate in 0.01m/s. Value of 30000 = 0.00 m/s
+ // packet[6 ] uint8_t climbrate_H; //#36
+ value = packet[5] + (packet[6] << 8) - 30000;
+ sensor = getHottSensor(HOTT_ID_VARIO);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+
+ // packet[7 ] uint8_t climbrate3s; //#37 climbrate in m/3sec. Value of 120 = 0m/3sec
+ // packet[8 ] uint8_t rpm_L; //#38 RPM. Steps: 10 U/min
+ // packet[9 ] uint8_t rpm_H; //#39
+ value = (packet[8] + (packet[9] << 8)) * 10;
+ sensor = getHottSensor(HOTT_ID_RPM1);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RPM1, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+ // packet[10] uint8_t electric_min; //#40 Electric minutes. Time does start, when motor current is > 3 A
+ // packet[11] uint8_t electric_sec; //#41
+ // packet[12] uint8_t speed_L; //#42 (air?) speed in km/h. Steps 1km/h
+ // packet[13] uint8_t speed_H; //#43
+ value = packet[12] + (packet[13] << 8);
+ sensor = getHottSensor(HOTT_ID_AIR_SPEED);
+ setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_AIR_SPEED, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
+ break;
+ }
+ break;
}
+ prev_page = (packet[2] << 4) | packet[3]; // concatenate telemetry type and page
+ prev_value = packet[13]; // page overflow
}
void hottSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance)
diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp
index 77ca485fe..42f612d57 100644
--- a/radio/src/telemetry/multi.cpp
+++ b/radio/src/telemetry/multi.cpp
@@ -21,6 +21,7 @@
#include "telemetry.h"
#include "multi.h"
+constexpr int32_t MULTI_DESIRED_VERSION = (1 << 24) | (3 << 16) | (1 << 8) | 1;
#define MULTI_CHAN_BITS 11
extern uint8_t g_moduleIdx;
@@ -316,6 +317,19 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module)
uint8_t len = packet[1];
const uint8_t * data = packet + 2;
+#if defined(AUX_SERIAL)
+ if (g_eeGeneral.auxSerialMode == UART_MODE_TELEMETRY_MIRROR) {
+ for (uint8_t c=0; c < len; c++)
+ auxSerialPutc(packet[c]);
+ }
+#endif
+#if defined(AUX2_SERIAL)
+ if (g_eeGeneral.aux2SerialMode == UART_MODE_TELEMETRY_MIRROR) {
+ for (uint8_t c=0; c < len; c++)
+ aux2SerialPutc(packet[c]);
+ }
+#endif
+
// Switch type
switch (type) {
case MultiStatus:
@@ -548,7 +562,7 @@ void MultiModuleStatus::getStatusString(char * statusText) const
return;
}
- if (major == 1 && minor < 3 && SLOW_BLINK_ON_PHASE) {
+ if ((((major << 24) | (minor << 16) | (revision << 8) | patch) < MULTI_DESIRED_VERSION) && SLOW_BLINK_ON_PHASE) {
strcpy(statusText, STR_MODULE_UPGRADE);
}
else {
@@ -621,7 +635,7 @@ static void processMultiTelemetryByte(const uint8_t data, uint8_t module)
debugPrintf("[%02X%02X %02X%02X] ", rxBuffer[i*4+2], rxBuffer[i*4 + 3],
rxBuffer[i*4 + 4], rxBuffer[i*4 + 5]);
}
- debugPrintf("\r\n");
+ debugPrintf(CRLF);
#endif
// Packet is complete, process it
processMultiTelemetryPaket(rxBuffer, module);
diff --git a/radio/src/telemetry/spektrum.cpp b/radio/src/telemetry/spektrum.cpp
index 29229cf2b..aab694db0 100644
--- a/radio/src/telemetry/spektrum.cpp
+++ b/radio/src/telemetry/spektrum.cpp
@@ -24,6 +24,7 @@
/*
* Documentation of the Spektrum protocol is available under
* https://www.spektrumrc.com/ProdInfo/Files/SPM_Telemetry_Developers_Specs.pdf
+ * https://github.com/SpektrumRC/SpektrumDocumentation/blob/master/Telemetry/spektrumTelemetrySensors.h
*
* Multi module adds two byte header of 0xAA [RSSI of telemetry packet] [16 byte message]
*/
@@ -49,7 +50,18 @@
#define I2C_TEXTGEN 0x0c
#define I2C_GPS 0x17
#define I2C_GPS2 0x17
+#define I2C_ESC 0x20
#define I2C_CELLS 0x3a
+
+// SMART_BAT is using fake I2C adresses compared to official Spektrum address because of subtype used only for this I2C address
+#define I2C_SMART_BAT_BASE_ADDRESS 0x42
+#define I2C_SMART_BAT_REALTIME 0x42
+#define I2C_SMART_BAT_CELLS_1_6 0x43
+#define I2C_SMART_BAT_CELLS_7_12 0x44
+#define I2C_SMART_BAT_CELLS_13_18 0x45
+#define I2C_SMART_BAT_ID 0x4A
+#define I2C_SMART_BAT_LIMITS 0x4B
+
#define I2C_QOS 0x7f
enum SpektrumDataType : uint8_t {
@@ -62,6 +74,8 @@ enum SpektrumDataType : uint8_t {
uint8bcd,
uint16bcd,
uint32bcd,
+ uint16le,
+ uint32le,
custom
};
@@ -151,7 +165,16 @@ const SpektrumSensor spektrumSensors[] = {
{0x1b, 2, int16, ZSTR_PITCH, UNIT_DEGREE, 1},
{0x1b, 4, int16, ZSTR_YAW, UNIT_DEGREE, 1},
- // {0x20, esc}, does not exist in the wild?
+ // {0x20, esc}, Smart ESC telemetry
+ {I2C_ESC, 0, uint16, ZSTR_ESC_RPM, UNIT_RPMS, 0},
+ {I2C_ESC, 2, uint16, ZSTR_ESC_VIN, UNIT_VOLTS, 2},
+ {I2C_ESC, 4, uint16, ZSTR_ESC_TFET, UNIT_CELSIUS, 1},
+ {I2C_ESC, 6, uint16, ZSTR_ESC_CUR, UNIT_MAH, 1},
+ {I2C_ESC, 8, uint16, ZSTR_ESC_TBEC, UNIT_CELSIUS, 1},
+ {I2C_ESC, 10, uint8, ZSTR_ESC_BCUR, UNIT_AMPS, 1},
+ {I2C_ESC, 11, uint8, ZSTR_ESC_VBEC, UNIT_VOLTS, 2},
+ {I2C_ESC, 12, uint8, ZSTR_ESC_THR, UNIT_PERCENT, 1},
+ {I2C_ESC, 13, uint8, ZSTR_ESC_POUT, UNIT_PERCENT, 1},
// Dual Cell monitor (0x34)
{0x34, 0, int16, ZSTR_BATT1_CURRENT, UNIT_AMPS, 1},
@@ -178,6 +201,53 @@ const SpektrumSensor spektrumSensors[] = {
{0x40, 0, int16, ZSTR_ALT, UNIT_METERS, 1},
{0x40, 2, int16, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 1},
+ // Smartbat
+ //{I2C_SMART_BAT_REALTIME, 1, int8, ZSTR_SMART_BAT_BTMP, UNIT_CELSIUS, 0}, // disabled because sensor is a duplicate of cells sensors ones
+ {I2C_SMART_BAT_REALTIME, 2, uint32le, ZSTR_SMART_BAT_BCUR, UNIT_MAH, 0},
+ {I2C_SMART_BAT_REALTIME, 6, uint16le, ZSTR_SMART_BAT_BCAP, UNIT_MAH, 0},
+ {I2C_SMART_BAT_REALTIME, 8, uint16le, ZSTR_SMART_BAT_MIN_CEL, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_REALTIME, 10, uint16le, ZSTR_SMART_BAT_MAX_CEL, UNIT_VOLTS, 2},
+ //{I2C_SMART_BAT_REALTIME, 12, uint16le, "RFU[2]", UNIT_RAW, 0}, // disabled to save sensors slots
+
+ {I2C_SMART_BAT_CELLS_1_6, 1, int8, ZSTR_SMART_BAT_BTMP, UNIT_CELSIUS, 0},
+ {I2C_SMART_BAT_CELLS_1_6, 2, uint16le, ZSTR_CL01, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_1_6, 4, uint16le, ZSTR_CL02, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_1_6, 6, uint16le, ZSTR_CL03, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_1_6, 8, uint16le, ZSTR_CL04, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_1_6, 10, uint16le, ZSTR_CL05, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_1_6, 12, uint16le, ZSTR_CL06, UNIT_VOLTS, 2},
+
+ {I2C_SMART_BAT_CELLS_7_12, 1, int8, ZSTR_SMART_BAT_BTMP, UNIT_CELSIUS, 0},
+ {I2C_SMART_BAT_CELLS_7_12, 2, uint16le, ZSTR_CL07, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_7_12, 4, uint16le, ZSTR_CL08, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_7_12, 6, uint16le, ZSTR_CL09, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_7_12, 8, uint16le, ZSTR_CL10, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_7_12, 10, uint16le, ZSTR_CL11, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_7_12, 12, uint16le, ZSTR_CL12, UNIT_VOLTS, 2},
+
+ {I2C_SMART_BAT_CELLS_13_18, 1, int8, ZSTR_SMART_BAT_BTMP, UNIT_CELSIUS, 0},
+ {I2C_SMART_BAT_CELLS_13_18, 2, uint16le, ZSTR_CL13, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_13_18, 4, uint16le, ZSTR_CL14, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_13_18, 6, uint16le, ZSTR_CL15, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_13_18, 8, uint16le, ZSTR_CL16, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_13_18, 10, uint16le, ZSTR_CL17, UNIT_VOLTS, 2},
+ {I2C_SMART_BAT_CELLS_13_18, 12, uint16le, ZSTR_CL18, UNIT_VOLTS, 2},
+
+ //{I2C_SMART_BAT_ID, 1, uint8, "chemistery", UNIT_RAW, 0}, // disabled to save sensors slots
+ //{I2C_SMART_BAT_ID, 2, uint8, "number of cells", UNIT_RAW, 0}, // disabled to save sensors slots
+ //{I2C_SMART_BAT_ID, 3, uint8, "manufacturer code", UNIT_RAW, 0}, // disabled to save sensors slots
+ {I2C_SMART_BAT_ID, 4, uint16le, ZSTR_SMART_BAT_CYCLES, UNIT_RAW, 0},
+ //{I2C_SMART_BAT_ID, 6, uint8, "uniqueID[8]", UNIT_RAW, 0}, // disabled to save sensors slots
+
+ //{I2C_SMART_BAT_LIMITS, 1, uint8, "rfu", UNIT_RAW, 0}, // disabled to save sensors slots
+ {I2C_SMART_BAT_LIMITS, 2, uint16le, ZSTR_SMART_BAT_CAPACITY,UNIT_MAH, 0},
+ //{I2C_SMART_BAT_LIMITS, 4, uint16le, "dischargeCurrentRating", UNIT_RAW, 0}, // disabled to save sensors slots
+ //{I2C_SMART_BAT_LIMITS, 6, uint16le, "overDischarge_mV", UNIT_RAW, 0}, // disabled to save sensors slots
+ //{I2C_SMART_BAT_LIMITS, 8, uint16le, "zeroCapacity_mV", UNIT_RAW, 0}, // disabled to save sensors slots
+ //{I2C_SMART_BAT_LIMITS, 10, uint16le, "fullyCharged_mV", UNIT_RAW, 0}, // disabled to save sensors slots
+ //{I2C_SMART_BAT_LIMITS, 12, uint8, "minWorkingTemp", UNIT_RAW, 0}, // disabled to save sensors slots
+ //{I2C_SMART_BAT_LIMITS, 13, uint8, "maxWorkingTemp", UNIT_RAW, 0}, // disabled to save sensors slots
+
// 0x50-0x56 custom 3rd party sensors
//{0x50, 0, int16, ZSTR_}
@@ -248,6 +318,10 @@ static int32_t spektrumGetValue(const uint8_t *packet, int startByte, SpektrumDa
return bcdToInt8(*(uint8_t *)data);
case uint32bcd:
return bcdToInt32(*(uint32_t *)data);
+ case uint16le:
+ return (int16_t) ((uint16_t) (data[0] + (data[1] << 8)));
+ case uint32le:
+ return ((uint32_t) (data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24)));
default:
return -1;
}
@@ -274,6 +348,12 @@ void processSpektrumPacket(const uint8_t *packet)
setTelemetryValue(PROTOCOL_TELEMETRY_SPEKTRUM, (I2C_PSEUDO_TX << 8) + 0, 0, 0, packet[1], UNIT_RAW, 0);
// highest bit indicates that TM1100 is in use, ignore it
uint8_t i2cAddress = (packet[2] & 0x7f);
+
+ //SmartBat Hack
+ if (i2cAddress == I2C_SMART_BAT_BASE_ADDRESS) {
+ i2cAddress = i2cAddress + (packet[4] >> 4); // use type to create virtual I2CAddresses
+ }
+
uint8_t instance = packet[3];
if (i2cAddress == I2C_TEXTGEN) {
@@ -303,6 +383,41 @@ void processSpektrumPacket(const uint8_t *packet)
if (!isSpektrumValidValue(value, sensor->dataType))
continue;
+ // mV to VOLT PREC2 for Smart Batteries
+ if ((i2cAddress >= I2C_SMART_BAT_REALTIME && i2cAddress <= I2C_SMART_BAT_LIMITS) && sensor->unit == UNIT_VOLTS) {
+ if (value == -1) {
+ continue; // discard unavailable sensors
+ }
+ else {
+ value = value / 10;
+ }
+ }
+
+ // RPM, 10RPM (0-655340 RPM)
+ if (i2cAddress == I2C_ESC && sensor->unit == UNIT_RPMS) {
+ value = value / 10;
+ }
+
+ // Current, 10mA (0-655.34A)
+ if (i2cAddress == I2C_ESC && sensor->startByte == 6) {
+ value = value / 10;
+ }
+
+ // BEC Current, 100mA (0-25.4A)
+ if (i2cAddress == I2C_ESC && sensor->startByte == 10) {
+ value = value / 10;
+ }
+
+ // Throttle 0.5% (0-127%)
+ if (i2cAddress == I2C_ESC && sensor->startByte == 12) {
+ value = value / 2;
+ }
+
+ // Power 0.5% (0-127%)
+ if (i2cAddress == I2C_ESC && sensor->startByte == 13) {
+ value = value / 2;
+ }
+
if (i2cAddress == I2C_CELLS && sensor->unit == UNIT_VOLTS) {
// Map to FrSky style cell values
int cellIndex = (sensor->startByte / 2) << 16;
@@ -353,17 +468,17 @@ void processSpektrumPacket(const uint8_t *packet)
// "I" here means the multi module
/*
-0-3 4 bytes -> Cyrf ID of the TX xor 0xFF but you don't care as I've checked it already...
-4 1 byte -> RX version but you don't care...
+0-3 4 bytes -> Cyrf ID of the TX xor 0xFF but don't care...
+4 1 byte -> RX version but don't care...
5 1 byte -> number of channels, example 0x06=6 channels
6 1 byte -> max DSM type allowed:
- 0x01 => 22ms 1024 DSM2 1 packet => number of channels is <8 and no telemetry
- 0x02 => 22ms 1024 DSM2 2 packets => either a number of channel >7 or telemetry enable RX
- 0x12 => 11ms 2048 DSM2 2 packets => can be any number of channels with/without telemetry -> this mode might be supported following Mike's trials, note the channels should be duplicated between the packets which is not the case today
- 0xa2 => 22ms 2048 DSMX 1 packet => number of channels is <8 and no telemetry
- 0xb2 => 11ms 2048 DSMX => can be any number of channels with/without telemetry -> this mode is only half supported since the channels should be duplicated between the packets which is not the case but might be supported following Mike's trials
+ 0x01 => 1024 DSM2 1 packet => number of channels is <8 and no telemetry
+ 0x02 => 1024 DSM2 2 packets => either a number of channel >7 or telemetry enable RX
+ 0x12 => 2048 DSM2 2 packets => can be any number of channels with/without telemetry -> this mode might be supported following Mike's trials, note the channels should be duplicated between the packets which is not the case today
+ 0xa2 => 2048 DSMX 1 packet => number of channels is <8 and no telemetry
+ 0xb2 => 2048 DSMX 2 packets => can be any number of channels with/without telemetry -> this mode is only half supported since the channels should be duplicated between the packets which is not the case but might be supported following Mike's trials
7 0x00: not sure of the use of this byte since I've always seen it at 0...
-8-9 2 bytes CRC but you don't care as I've checked it already...
+8-9 2 bytes CRC but don't care...
Examples: DSM #Chan RXver
Inductrix 0xa2 07 1
@@ -373,22 +488,40 @@ void processSpektrumPacket(const uint8_t *packet)
void processDSMBindPacket(uint8_t module, const uint8_t *packet)
{
uint32_t debugval;
- if (g_model.moduleData[module].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2
- && g_model.moduleData[module].multi.autoBindMode) {
-
+ if (g_model.moduleData[module].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2 && g_model.moduleData[module].subType == MM_RF_DSM2_SUBTYPE_AUTO) {
+ // Only sets channel etc when in DSM/AUTO mode
int channels = packet[5];
- // Only sets channel etc when in DSM multi mode
- g_model.moduleData[module].channelsCount = channels - 8;
+ if (channels > 12) {
+ channels = 12;
+ }
+ else if (channels < 3) {
+ channels = 3;
+ }
- // bool use11ms = (packet[8] & 0x10) ;
- if (packet[6] >= 0xb2)
- g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_11;
- else if (packet[6] >= 0xa2)
- g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_22;
- else if (packet[6] >= 0x12)
- g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_11;
- else
- g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_22;
+ switch(packet[6]) {
+ case 0xa2:
+ g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_22;
+ break;
+ case 0x12:
+ g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_11;
+ if (channels == 7) {
+ channels = 12; // change the number of channels if 7
+ }
+ break;
+ case 0x01:
+ case 0x02:
+ g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_22;
+ break;
+ default: // 0xb2 or unknown
+ g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_11;
+ if (channels == 7) {
+ channels = 12; // change the number of channels if 7
+ }
+ break;
+ }
+
+ g_model.moduleData[module].channelsCount = channels - 8;
+ g_model.moduleData[module].multi.optionValue &= 0xFD; // clear the 11ms servo refresh rate flag
storageDirty(EE_MODEL);
}
@@ -434,7 +567,7 @@ void processSpektrumTelemetryData(uint8_t module, uint8_t data, uint8_t* rxBuffe
debugPrintf("%02X%02X %02X%02X ", rxBuffer[i], rxBuffer[i + 1],
rxBuffer[i + 2], rxBuffer[i + 3]);
}
- debugPrintf("\r\n");
+ debugPrintf(CRLF);
#endif
processSpektrumPacket(rxBuffer);
rxBufferCount = 0;
diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp
index 4e7bc8550..a5f1af94f 100644
--- a/radio/src/telemetry/telemetry.cpp
+++ b/radio/src/telemetry/telemetry.cpp
@@ -20,6 +20,7 @@
#include "opentx.h"
#include "multi.h"
+#include "pulses/afhds3.h"
uint8_t telemetryStreaming = 0;
uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1)
@@ -59,6 +60,13 @@ void processTelemetryData(uint8_t data)
}
#endif
+#if defined(AFHDS3)
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_AFHDS3) {
+ afhds3::processTelemetryData(EXTERNAL_MODULE, data, telemetryRxBuffer, telemetryRxBufferCount, TELEMETRY_RX_PACKET_SIZE);
+ return;
+ }
+#endif
+
processFrskyTelemetryData(data);
}
@@ -103,7 +111,7 @@ void telemetryWakeup()
#endif
#if defined(EXTMODULE_USART)
- while (extmoduleFifo.getFrame(frame)) {
+ while (isModulePxx2(EXTERNAL_MODULE) && extmoduleFifo.getFrame(frame)) {
processPXX2Frame(EXTERNAL_MODULE, frame);
}
#endif
@@ -294,6 +302,13 @@ void telemetryInit(uint8_t protocol)
}
#endif
+#if defined(AFHDS3) && !defined(SIMU)
+ else if (protocol == PROTOCOL_TELEMETRY_AFHDS3) {
+ telemetryPortInvertedInit(AFHDS3_BAUDRATE);
+ telemetryPortSetDirectionInput();
+ }
+#endif
+
else {
telemetryPortInit(FRSKY_SPORT_BAUDRATE, TELEMETRY_SERIAL_WITHOUT_DMA);
#if defined(LUA)
diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h
index 0c0a1c969..d35198cdc 100644
--- a/radio/src/telemetry/telemetry.h
+++ b/radio/src/telemetry/telemetry.h
@@ -23,13 +23,18 @@
#include "frsky.h"
#include "crossfire.h"
+#include "myeeprom.h"
+#include "io/frsky_sport.h"
+
#if defined(MULTIMODULE)
#include "spektrum.h"
- #include "flysky_ibus.h"
#include "hitec.h"
#include "hott.h"
#include "multi.h"
#endif
+#if defined(MULTIMODULE) || defined(AFHDS3)
+ #include "flysky_ibus.h"
+#endif
extern uint8_t telemetryStreaming; // >0 (true) == data is streaming in. 0 = no data detected for some time
@@ -51,7 +56,7 @@ constexpr uint8_t TELEMETRY_TIMEOUT10ms = 100; // 1 second
#define TELEMETRY_SERIAL_8E2 1
#define TELEMETRY_SERIAL_WITHOUT_DMA 2
-#if defined(CROSSFIRE) || defined(MULTIMODULE)
+#if defined(CROSSFIRE) || defined(MULTIMODULE) || defined(AFHDS3)
#define TELEMETRY_RX_PACKET_SIZE 128
// multi module Spektrum telemetry is 18 bytes, FlySky is 37 bytes
#else
@@ -105,17 +110,26 @@ void frskyDSetDefault(int index, uint16_t id);
extern uint8_t telemetryProtocol;
#if defined (MULTIMODULE)
-#define IS_D16_MULTI(module) ((g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY) && (g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16 || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_8CH || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH))
-#define IS_HOTT_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_HOTT)
-#if defined(HARDWARE_INTERNAL_MODULE)
-#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (IS_D16_MULTI(INTERNAL_MODULE)||IS_D16_MULTI(EXTERNAL_MODULE))))
+ #define IS_D16_MULTI(module) (((g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY) && (g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16 || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_8CH || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_CLONED)) \
+ || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKYX2))
+ #define IS_R9_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY_R9)
+ #define IS_HOTT_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_HOTT)
+ #define IS_RX_MULTI(module) ((g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_AFHDS2A_RX) || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKYX_RX) \
+ || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_BAYANG_RX) || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM_RX))
+ #if defined(HARDWARE_INTERNAL_MODULE)
+ #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (IS_D16_MULTI(INTERNAL_MODULE) || IS_D16_MULTI(EXTERNAL_MODULE) || IS_R9_MULTI(INTERNAL_MODULE) || IS_R9_MULTI(EXTERNAL_MODULE))))
+ #else
+ #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (IS_D16_MULTI(EXTERNAL_MODULE) || IS_R9_MULTI(EXTERNAL_MODULE))))
+ #endif
#else
-#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && IS_D16_MULTI(EXTERNAL_MODULE)))
+ #define IS_D16_MULTI(module) false
+ #define IS_R9_MULTI(module) false
+ #define IS_HOTT_MULTI(module) false
+ #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT)
+ #define IS_RX_MULTI(module) false
#endif
-#else
-#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT)
-#endif
-#define IS_SPEKTRUM_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM)
+
+#define IS_SPEKTRUM_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM)
#if defined(PCBTARANIS) || defined(PCBHORUS)
inline bool isSportLineUsedByInternalModule()
@@ -148,10 +162,15 @@ inline uint8_t modelTelemetryProtocol()
return PROTOCOL_TELEMETRY_MULTIMODULE;
}
#if defined(INTERNAL_MODULE_MULTI)
- if (g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE) {
+ if (g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_NONE) {
return PROTOCOL_TELEMETRY_MULTIMODULE;
}
#endif
+#endif
+#if defined(AFHDS3)
+ if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_AFHDS3) {
+ return PROTOCOL_TELEMETRY_AFHDS3;
+ }
#endif
// default choice
return PROTOCOL_TELEMETRY_FRSKY_SPORT;
@@ -168,6 +187,7 @@ void logTelemetryWriteByte(uint8_t data);
#define LOG_TELEMETRY_WRITE_START()
#define LOG_TELEMETRY_WRITE_BYTE(data)
#endif
+#define TELEMETRY_OUTPUT_BUFFER_SIZE 64
class OutputTelemetryBuffer {
public:
@@ -209,7 +229,8 @@ class OutputTelemetryBuffer {
void pushByte(uint8_t byte)
{
- data[size++] = byte;
+ if (size < TELEMETRY_OUTPUT_BUFFER_SIZE)
+ data[size++] = byte;
}
void pushByteWithBytestuffing(uint8_t byte)
@@ -241,7 +262,7 @@ class OutputTelemetryBuffer {
public:
union {
SportTelemetryPacket sport;
- uint8_t data[16];
+ uint8_t data[TELEMETRY_OUTPUT_BUFFER_SIZE];
};
uint8_t size;
uint8_t timeout;
diff --git a/radio/src/telemetry/telemetry_holders.h b/radio/src/telemetry/telemetry_holders.h
index 70b2b6a9c..3e99b27f4 100644
--- a/radio/src/telemetry/telemetry_holders.h
+++ b/radio/src/telemetry/telemetry_holders.h
@@ -22,10 +22,12 @@
#define _TELEMETRY_HOLDERS_H_
#include
+#include
#include "../timers.h"
#define TELEMETRY_AVERAGE_COUNT 3 // we actually average one more reading!
#define RAW_FRSKY_MINMAX(v) v.values[TELEMETRY_AVERAGE_COUNT-1]
+#define MAX_CELLS 6
class TelemetryValue {
public:
diff --git a/radio/src/telemetry/telemetry_sensors.cpp b/radio/src/telemetry/telemetry_sensors.cpp
index dc9742b55..d94a8471a 100644
--- a/radio/src/telemetry/telemetry_sensors.cpp
+++ b/radio/src/telemetry/telemetry_sensors.cpp
@@ -82,10 +82,16 @@ void TelemetryItem::setValue(const TelemetrySensor & sensor, int32_t val, uint32
{
int32_t newVal = val;
+ if(prec == 255) {
+ prec = sensor.prec;
+ }
+
if (unit == UNIT_CELLS) {
uint32_t data = uint32_t(newVal);
uint8_t cellsCount = (data >> 24);
uint8_t cellIndex = ((data >> 16) & 0x0F);
+ if (cellIndex >= MAX_CELLS)
+ return;
uint16_t cellValue = (data & 0xFFFF);
if (cellsCount == 0) {
cellsCount = (cellIndex >= cells.count ? cellIndex + 1 : cells.count);
@@ -493,7 +499,7 @@ int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, ui
{
bool sensorFound = false;
- for (int index=0; indexinstance == instance)
+ return true;
+
+ if (protocol == PROTOCOL_TELEMETRY_FRSKY_SPORT) {
+#if defined(SIMU)
+ if (((this->instance ^ instance) & 0x1F) == 0)
+ return true;
+#else
+ if (((this->instance ^ instance) & 0x9F) == 0 && (this->instance >> 5) != TELEMETRY_ENDPOINT_SPORT && (instance >> 5) != TELEMETRY_ENDPOINT_SPORT) {
+ this->instance = instance; // update the instance in case we had telemetry switching
+ return true;
+ }
+#endif
+ }
+
+ return false;
+}
diff --git a/radio/src/telemetry/telemetry_sensors.h b/radio/src/telemetry/telemetry_sensors.h
index def941861..6ca1c0c97 100644
--- a/radio/src/telemetry/telemetry_sensors.h
+++ b/radio/src/telemetry/telemetry_sensors.h
@@ -57,7 +57,7 @@ class TelemetryItem
} consumption;
struct {
uint8_t count;
- CellValue values[6];
+ CellValue values[MAX_CELLS];
} cells;
struct {
uint16_t year; // full year (4 digits)
diff --git a/radio/src/tests/conversions.cpp b/radio/src/tests/conversions.cpp
index 897d5cb59..26cdc159e 100644
--- a/radio/src/tests/conversions.cpp
+++ b/radio/src/tests/conversions.cpp
@@ -222,7 +222,7 @@ TEST(Conversions, ConversionX7From22)
}
#endif
-#if defined(PCBX10)
+#if defined(PCBX10) && !defined(RADIO_FAMILY_T16)
TEST(Conversions, ConversionX10From22)
{
simuFatfsSetPaths(TESTS_BUILD_PATH "/model_22_x10/", TESTS_BUILD_PATH "/model_22_x10/");
diff --git a/radio/src/tests/fonts_480x272.png b/radio/src/tests/fonts_480x272.png
index da2ac09d3..abd3e1f72 100644
Binary files a/radio/src/tests/fonts_480x272.png and b/radio/src/tests/fonts_480x272.png differ
diff --git a/radio/src/tests/gtests.h b/radio/src/tests/gtests.h
index ab5c35abd..a1f6f5d24 100644
--- a/radio/src/tests/gtests.h
+++ b/radio/src/tests/gtests.h
@@ -65,6 +65,7 @@ inline void MODEL_RESET()
memset(&anaInValues, 0, sizeof(anaInValues));
extern uint8_t s_mixer_first_run_done;
s_mixer_first_run_done = false;
+ evalMixes(1); // this is needed to reset fp_act
lastFlightMode = 255;
}
diff --git a/radio/src/tests/lcd_480x272.cpp b/radio/src/tests/lcd_480x272.cpp
index 769fccc5f..0127b4356 100644
--- a/radio/src/tests/lcd_480x272.cpp
+++ b/radio/src/tests/lcd_480x272.cpp
@@ -168,6 +168,12 @@ TEST(Lcd_480x272, fonts)
lcdDrawText(30, 200, "The quick brown fox", TEXT_COLOR|VERTICAL|NO_FONTCACHE);
// lcdDrawText(50, 200, "The quick brown fox jumps over the lazy dog", TEXT_COLOR|VERTICAL|NO_FONTCACHE);
+ lcdDrawText(50, 25, "The quick", TEXT_COLOR|TINSIZE);
+ lcdDrawText(50, 40, "The quick", TEXT_COLOR|SMLSIZE);
+ lcdDrawText(50, 55, "The quick", TEXT_COLOR|MIDSIZE);
+ lcdDrawText(50, 80, "The quick", TEXT_COLOR|DBLSIZE);
+ lcdDrawText(50, 120, "The quick", TEXT_COLOR|XXLSIZE);
+
lcdDrawText(8, 208, "The quick brown fox jumps over the lazy dog", TITLE_BGCOLOR|OPACITY(4));
lcdDrawText(5, 205, "The quick brown fox jumps over the lazy dog", TITLE_BGCOLOR|OPACITY(12));
diff --git a/radio/src/tests/mixer.cpp b/radio/src/tests/mixer.cpp
index 8d8058d31..074f7f6ca 100644
--- a/radio/src/tests/mixer.cpp
+++ b/radio/src/tests/mixer.cpp
@@ -47,6 +47,22 @@ class MixerTest : public OpenTxTest {};
} \
} while (0)
+#define CHECK_FLIGHT_MODE_TRANSITION(channel, duration, initValue, endValue) \
+ do { \
+ uint32_t delta = 0xffff / duration; \
+ int32_t weightInit = 0xffff; \
+ int32_t weightEnd = 0; \
+ for (int i = 0; i <= (duration); i++) { \
+ evalMixes(1); \
+ GTEST_ASSERT_LE( abs(((initValue) * weightInit + (endValue) * weightEnd) / 0xffff - channelOutputs[(channel)]), 1); \
+ weightInit = weightInit - delta; \
+ weightEnd = weightEnd + delta; \
+ } \
+ for (int i = 0; i < 100; i++) { /* be sure the transition is finished*/ \
+ evalMixes(1); \
+ } \
+ } while (0)
+
TEST_F(TrimsTest, throttleTrim)
{
g_model.thrTrim = 1;
@@ -659,3 +675,48 @@ TEST(Trainer, UnpluggedTest)
ppmInput[0] = 1024;
CHECK_DELAY(0, 5000);
}
+
+TEST_F(MixerTest, flightModeTransition)
+{
+ SYSTEM_RESET();
+ MODEL_RESET();
+ MIXER_RESET();
+ modelDefault(0);
+ g_model.flightModeData[1].swtch = TR(SWSRC_ID2, SWSRC_SA2);
+ g_model.flightModeData[0].fadeIn = 100;
+ g_model.flightModeData[0].fadeOut = 100;
+ g_model.flightModeData[1].fadeIn = 100;
+ g_model.flightModeData[1].fadeOut = 100;
+ g_model.mixData[0].destCh = 0;
+ g_model.mixData[0].mltpx = MLTPX_REP;
+ g_model.mixData[0].srcRaw = MIXSRC_MAX;
+ g_model.mixData[0].flightModes = 0b11110;
+ g_model.mixData[0].weight = 100;
+ g_model.mixData[1].destCh = 0;
+ g_model.mixData[1].mltpx = MLTPX_REP;
+ g_model.mixData[1].srcRaw = MIXSRC_MAX;
+ g_model.mixData[1].flightModes = 0b11101;
+ g_model.mixData[1].weight = -10;
+ evalMixes(1);
+ simuSetSwitch(0, 1);
+ CHECK_FLIGHT_MODE_TRANSITION(0, 1000, 1024, -102);
+}
+
+TEST_F(MixerTest, flightModeOverflow)
+{
+ SYSTEM_RESET();
+ MODEL_RESET();
+ MIXER_RESET();
+ modelDefault(0);
+ g_model.flightModeData[1].swtch = TR(SWSRC_ID2, SWSRC_SA2);
+ g_model.flightModeData[0].fadeIn = 100;
+ g_model.flightModeData[0].fadeOut = 100;
+ g_model.mixData[0].destCh = 0;
+ g_model.mixData[0].mltpx = MLTPX_REP;
+ g_model.mixData[0].srcRaw = MIXSRC_MAX;
+ g_model.mixData[0].flightModes = 0;
+ g_model.mixData[0].weight = 250;
+ evalMixes(1);
+ simuSetSwitch(0, 1);
+ CHECK_FLIGHT_MODE_TRANSITION(0, 1000, 1024, 1024);
+}
diff --git a/radio/src/tests/primitives_480x272.png b/radio/src/tests/primitives_480x272.png
index ae3f0b94f..68bb2f886 100644
Binary files a/radio/src/tests/primitives_480x272.png and b/radio/src/tests/primitives_480x272.png differ
diff --git a/radio/src/tests/transparency_480x272.png b/radio/src/tests/transparency_480x272.png
index b8fec6660..2b0588eb9 100644
Binary files a/radio/src/tests/transparency_480x272.png and b/radio/src/tests/transparency_480x272.png differ
diff --git a/radio/src/thirdparty/Lua/src/lauxlib.h b/radio/src/thirdparty/Lua/src/lauxlib.h
index aab96bd1c..9cd4c02d3 100644
--- a/radio/src/thirdparty/Lua/src/lauxlib.h
+++ b/radio/src/thirdparty/Lua/src/lauxlib.h
@@ -29,6 +29,7 @@ extern const luaL_Reg mathlib[];
extern const luaL_Reg bitlib[];
extern const luaL_Reg iolib[];
extern const luaL_Reg strlib[];
+extern const luaL_Reg tab_funcs[];
extern const luaL_Reg opentxLib[];
extern const luaL_Reg lcdLib[];
diff --git a/radio/src/thirdparty/Lua/src/linit.c b/radio/src/thirdparty/Lua/src/linit.c
index 940790e3d..4706a3ab7 100644
--- a/radio/src/thirdparty/Lua/src/linit.c
+++ b/radio/src/thirdparty/Lua/src/linit.c
@@ -28,7 +28,9 @@
*/
static const luaL_Reg loadedlibs[] = {
// {"_G", luaopen_base},
- // {LUA_LOADLIBNAME, luaopen_package},
+#if defined(PCBHORUS)
+ {LUA_LOADLIBNAME, luaopen_package},
+#endif
// {LUA_COLIBNAME, luaopen_coroutine},
// {LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
@@ -51,6 +53,9 @@ const luaR_table lua_rotable[] =
{LUA_STRLIBNAME, strlib, NULL},
{LUA_MATHLIBNAME, mathlib, mathlib_vals},
{LUA_BITLIBNAME, bitlib, NULL},
+#if defined(PCBHORUS)
+ {LUA_TABLIBNAME, tab_funcs, NULL},
+#endif
{NULL, NULL, NULL}
};
diff --git a/radio/src/thirdparty/Lua/src/ltablib.c b/radio/src/thirdparty/Lua/src/ltablib.c
index c61903b08..d545a5325 100644
--- a/radio/src/thirdparty/Lua/src/ltablib.c
+++ b/radio/src/thirdparty/Lua/src/ltablib.c
@@ -256,7 +256,7 @@ static int sort (lua_State *L) {
/* }====================================================== */
-static const luaL_Reg tab_funcs[] = {
+const luaL_Reg tab_funcs[] = {
{"concat", tconcat},
#if defined(LUA_COMPAT_MAXN)
{"maxn", maxn},
diff --git a/radio/src/touch.h b/radio/src/touch.h
new file mode 100644
index 000000000..fbb70e3fe
--- /dev/null
+++ b/radio/src/touch.h
@@ -0,0 +1,50 @@
+/*
+ * 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 _TOUCH_H_
+#define _TOUCH_H_
+
+enum TouchEvent
+{
+ TE_NONE,
+ TE_DOWN,
+ TE_UP,
+ TE_SLIDE,
+ TE_SLIDE_END
+};
+
+struct TouchState
+{
+ unsigned char event;
+ short x;
+ short y;
+ short startX;
+ short startY;
+ short deltaX;
+ short deltaY;
+ short lastDeltaX;
+ short lastDeltaY;
+};
+
+constexpr uint8_t SLIDE_RANGE = 6;
+
+extern TouchState touchState;
+
+#endif // _TOUCH_H_
\ No newline at end of file
diff --git a/radio/src/trainer.cpp b/radio/src/trainer.cpp
index 0af1901b7..27a237b54 100644
--- a/radio/src/trainer.cpp
+++ b/radio/src/trainer.cpp
@@ -115,9 +115,16 @@ void checkTrainerSettings()
#if defined(TRAINER_BATTERY_COMPARTMENT)
case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT:
+#if defined(AUX_SERIAL)
if (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER)
auxSerialSbusInit();
else
+#endif
+#if defined(AUX2_SERIAL)
+ if (g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER)
+ aux2SerialSbusInit();
+ else
+#endif
init_trainer_capture();
break;
#endif
diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp
index ba23c2436..4d65e6840 100644
--- a/radio/src/translations.cpp
+++ b/radio/src/translations.cpp
@@ -68,6 +68,8 @@ ISTR(XJT_ACCST_RF_PROTOCOLS);
ISTR(ISRM_RF_PROTOCOLS);
ISTR(R9M_PXX2_RF_PROTOCOLS);
ISTR(DSM_PROTOCOLS);
+ISTR(AFHDS3_PROTOCOLS);
+ISTR(AFHDS3_POWERS);
ISTR(CURVE_TYPES);
ISTR(VSENSORTYPES);
ISTR(VFORMULAS);
@@ -78,6 +80,7 @@ ISTR(SWTYPES);
ISTR(POTTYPES);
ISTR(SLIDERTYPES);
ISTR(ANTENNA_MODES);
+ISTR(SPORT_UPDATE_POWER_MODES);
#if defined(PCBSKY9X) && defined(REVX)
ISTR(VOUTPUT_TYPE);
@@ -93,12 +96,17 @@ ISTR(INPUTNAMES);
#if defined(MULTIMODULE)
ISTR(MULTI_PROTOCOLS);
+ISTR(MULTI_POWER);
#endif
#if defined(BLUETOOTH)
ISTR(BLUETOOTH_MODES);
#endif
+#if defined(PCBHORUS)
+ISTR(TEXT_SIZE);
+#endif
+
const char STR_POPUPS_ENTER_EXIT[] = TR_POPUPS_ENTER_EXIT;
const char STR_OK[] = TR_OK;
const char STR_FREE[] = TR_FREE;
@@ -283,6 +291,7 @@ const char STR_BEEP_VOLUME[] = INDENT TR_BEEP_VOLUME;
const char STR_WAV_VOLUME[] = INDENT TR_WAV_VOLUME;
const char STR_BG_VOLUME[] = INDENT TR_BG_VOLUME;
const char STR_SELECT_MODEL[] = TR_SELECT_MODEL;
+const char STR_SELECT_MODE[] = TR_SELECT_MODE;
const char STR_CREATE_CATEGORY[] = TR_CREATE_CATEGORY;
const char STR_RENAME_CATEGORY[] = TR_RENAME_CATEGORY;
const char STR_DELETE_CATEGORY[] = TR_DELETE_CATEGORY;
@@ -315,6 +324,8 @@ const char STR_RESET_BTN[] = TR_RESET_BTN;
const char STR_DEBUG[] = TR_DEBUG;
const char STR_KEYS_BTN[] = TR_KEYS_BTN;
const char STR_ANALOGS_BTN[] = TR_ANALOGS_BTN;
+const char STR_TOUCH_NOTFOUND[] = TR_TOUCH_NOTFOUND;
+const char STR_TOUCH_EXIT[] = TR_TOUCH_EXIT;
const char STR_CALIBRATION[] = TR_CALIBRATION;
const char STR_NO_TOOLS[] = TR_NO_TOOLS;
const char STR_NORMAL[] = TR_NORMAL;
@@ -346,6 +357,7 @@ const char STR_SPECTRUM_ANALYSER_EXT[] = TR_SPECTRUM_ANALYSER_EXT;
const char STR_SPECTRUM_ANALYSER_INT[] = TR_SPECTRUM_ANALYSER_INT;
const char STR_WAITING_FOR_RX[] = TR_WAITING_FOR_RX;
const char STR_WAITING_FOR_TX[] = TR_WAITING_FOR_TX;
+const char STR_WARN_5VOLTS[] = TR_WARN_5VOLTS;
const char STR_CAT_NOT_EMPTY[] = TR_CAT_NOT_EMPTY;
const char STR_WARNING[] = TR_WARNING;
const char STR_THROTTLEWARN[] = TR_THROTTLEWARN;
@@ -427,6 +439,8 @@ const char STR_FIRMWARE_UPDATE_SUCCESS[] = TR_FIRMWARE_UPDATE_SUCCESS;
const char STR_WRITING[] = TR_WRITING;
const char STR_FLASH_EXTERNAL_DEVICE[] = TR_FLASH_EXTERNAL_DEVICE;
const char STR_FLASH_RECEIVER_OTA[] = TR_FLASH_RECEIVER_OTA;
+const char STR_FLASH_RECEIVER_OTA_BY_EXTERNAL[] = TR_FLASH_RECEIVER_OTA_BY_EXTERNAL;
+const char STR_FLASH_RECEIVER_OTA_BY_INTERNAL[] = TR_FLASH_RECEIVER_OTA_BY_INTERNAL;
const char STR_FLASH_BLUETOOTH_MODULE[] = TR_FLASH_BLUETOOTH_MODULE;
const char STR_FLASH_POWER_MANAGEMENT_UNIT[] = TR_FLASH_POWER_MANAGEMENT_UNIT;
const char STR_CONFIRM_FORMAT[] = TR_CONFIRM_FORMAT;
@@ -536,6 +550,7 @@ const char STR_PT[] = TR_PT;
const char STR_PTS[] = TR_PTS;
const char STR_SMOOTH[] = TR_SMOOTH;
const char STR_COPY_STICKS_TO_OFS[] = TR_COPY_STICKS_TO_OFS;
+const char STR_COPY_MIN_MAX_TO_OUTPUTS[] = TR_COPY_MIN_MAX_TO_OUTPUTS;
const char STR_COPY_TRIMS_TO_OFS[] = TR_COPY_TRIMS_TO_OFS;
const char STR_INCDEC[] = TR_INCDEC;
const char STR_GLOBALVAR[] = TR_GLOBALVAR;
@@ -554,6 +569,7 @@ const char STR_ALTITUDE[] = TR_ALTITUDE;
const char STR_SCALE[] = TR_SCALE;
const char STR_VIEW_CHANNELS[] = TR_VIEW_CHANNELS;
const char STR_AUX_SERIAL_MODE[] = TR_AUX_SERIAL_MODE;
+const char STR_AUX2_SERIAL_MODE[] = TR_AUX2_SERIAL_MODE;
const char STR_THROTTLE_LABEL[] = TR_THROTTLE_LABEL;
const char STR_SCRIPT[] = TR_SCRIPT;
const char STR_INPUTS[] = TR_INPUTS;
@@ -579,13 +595,31 @@ const char STR_RTC_CHECK[] = TR_RTC_CHECK;
const char STR_EXIT[] = TR_EXIT;
const char STR_MODULE_RANGE[] = TR_MODULE_RANGE;
const char STR_RECEIVER_OPTIONS[] = TR_RECEIVER_OPTIONS;
+const char STR_SPORT_UPDATE_POWER_MODE[] = TR_SPORT_UPDATE_POWER_MODE;
+const char STR_TOUCH_PANEL[] = TR_TOUCH_PANEL;
#if defined(PCBHORUS)
const char STR_ASSIGN_SPLASH[] = TR_ASSIGN_SPLASH;
+const char STR_FIRST_CHANNEL[] = TR_FIRST_CHANNEL;
+const char STR_FILL_BACKGROUND[] = TR_FILL_BACKGROUND;
+const char STR_BG_COLOR[] = TR_BG_COLOR;
+const char STR_SLIDERS_TRIMS[] = TR_SLIDERS_TRIMS;
+const char STR_SLIDERS[] = TR_SLIDERS;
+const char STR_FLIGHT_MODE[] = TR_FLIGHT_MODE;
+const char STR_INVALID_FILE[] = TR_INVALID_FILE;
+const char STR_TIMER_SOURCE[] = TR_TIMER_SOURCE;
+const char STR_SIZE[] = TR_SIZE;
+const char STR_SHADOW[] = TR_SHADOW;
+const char STR_TEXT[] = TR_TEXT;
+const char STR_COLOR[] = TR_COLOR;
+const char STR_MAIN_VIEW_X[] = TR_MAIN_VIEW_X;
+const char STR_PANEL1_BACKGROUND[] = TR_PANEL1_BACKGROUND;
+const char STR_PANEL2_BACKGROUND[] = TR_PANEL2_BACKGROUND;
#endif
#if !defined(COLORLCD)
const char STR_MENUWHENDONE[] = TR_MENUWHENDONE;
+const char STR_NO_TELEMETRY_SCREENS[] = TR_NO_TELEMETRY_SCREENS;
#endif
#if defined(PCBSKY9X) && defined(REVX)
@@ -621,6 +655,7 @@ const char STR_GYRO_MAX[] = TR_GYRO_MAX;
#if defined(PWM_BACKLIGHT) || defined(COLORLCD)
const char STR_BLONBRIGHTNESS[] = TR_BLONBRIGHTNESS;
const char STR_BLOFFBRIGHTNESS[] = TR_BLOFFBRIGHTNESS;
+const char STR_KEYS_BACKLIGHT[] = TR_KEYS_BACKLIGHT;
#endif
const char STR_TIMEZONE[] = TR_TIMEZONE;
@@ -661,6 +696,7 @@ const char STR_BIND_OK[] = TR_BIND_OK;
const char STR_MULTI_CUSTOM[] = TR_MULTI_CUSTOM;
const char STR_MULTI_RFTUNE[] = TR_MULTI_RFTUNE;
+const char STR_MULTI_RFPOWER[] = TR_MULTI_RFPOWER;
const char STR_MULTI_TELEMETRY[] = TR_MULTI_TELEMETRY;
const char STR_MULTI_VIDFREQ[] = TR_MULTI_VIDFREQ;
const char STR_MULTI_OPTION[] = TR_MULTI_OPTION;
@@ -670,6 +706,7 @@ const char STR_DISABLE_CH_MAP[] = TR_DISABLE_CH_MAP;
const char STR_DISABLE_TELEM[] = TR_DISABLE_TELEM;
const char STR_MULTI_DSM_AUTODTECT[] = TR_MULTI_DSM_AUTODTECT;
const char STR_MULTI_LOWPOWER[] = TR_MULTI_LOWPOWER;
+const char STR_MULTI_LNA_DISABLE[] = TR_MULTI_LNA_DISABLE;
const char STR_MODULE_NO_SERIAL_MODE[] = TR_MODULE_NO_SERIAL_MODE;
const char STR_MODULE_NO_INPUT[] = TR_MODULE_NO_INPUT;
const char STR_MODULE_WAITFORBIND[] = TR_MODULE_WAITFORBIND;
@@ -684,8 +721,16 @@ const char STR_MULTI_SERVOFREQ[] = TR_MULTI_SERVOFREQ;
const char STR_MULTI_MAX_THROW[] = TR_MULTI_MAX_THROW;
const char STR_MULTI_RFCHAN[] = TR_MULTI_RFCHAN;
const char STR_NEEDS_FILE[] = TR_NEEDS_FILE;
-const char STR_EXT_MULTI_SPEC[] = TR_EXT_MULTI_SPEC;
-const char STR_INT_MULTI_SPEC[] = TR_INT_MULTI_SPEC;
+const char STR_EXT_MULTI_SPEC[] = TR_EXT_MULTI_SPEC;
+const char STR_INT_MULTI_SPEC[] = TR_INT_MULTI_SPEC;
+
+#if defined(AFHDS3)
+const char STR_AFHDS3_RX_FREQ[] = TR_AFHDS3_RX_FREQ;
+const char STR_AFHDS3_ACTUAL_POWER[] = TR_AFHDS3_ACTUAL_POWER;
+const char STR_AFHDS3_POWER_SOURCE[] = TR_AFHDS3_POWER_SOURCE;
+const char STR_AFHDS3_ONE_TO_ONE_TELEMETRY[] =TR_AFHDS3_ONE_TO_ONE_TELEMETRY;
+const char STR_AFHDS3_ONE_TO_MANY[] = TR_AFHDS3_ONE_TO_MANY;
+#endif
#if LCD_W < 212
const char STR_SUBTYPE[] = TR_SUBTYPE;
@@ -705,10 +750,8 @@ const char STR_MODELS_PATH[] = MODELS_PATH;
const char STR_MODELS_EXT[] = MODELS_EXT;
#endif
-#if defined(NIGHTLY_BUILD_WARNING)
-const char STR_NIGHTLY_WARNING[] = TR_NIGHTLY_WARNING;
-const char STR_NIGHTLY_NOTSAFE[] = TR_NIGHTLY_NOTSAFE;
-#endif
+const char STR_TEST_WARNING[] = TR_TEST_WARNING;
+const char STR_TEST_NOTSAFE[] = TR_TEST_NOTSAFE;
#if LCD_W >= 212
const char * const STR_PHASES_HEADERS[] = TR_PHASES_HEADERS;
diff --git a/radio/src/translations.h b/radio/src/translations.h
index e1e9e9c0f..f99520cd7 100644
--- a/radio/src/translations.h
+++ b/radio/src/translations.h
@@ -159,9 +159,17 @@ extern const char STR_XJT_ACCST_RF_PROTOCOLS[];
extern const char STR_ISRM_RF_PROTOCOLS[];
extern const char STR_R9M_PXX2_RF_PROTOCOLS[];
extern const char STR_DSM_PROTOCOLS[];
-
-#if defined(MULTIMODULE)
extern const char STR_MULTI_PROTOCOLS[];
+extern const char STR_MULTI_POWER[];
+
+#if defined(AFHDS3)
+extern const char STR_AFHDS3_ONE_TO_ONE_TELEMETRY[];
+extern const char STR_AFHDS3_ONE_TO_MANY[];
+extern const char STR_AFHDS3_PROTOCOLS[];
+extern const char STR_AFHDS3_POWERS[];
+extern const char STR_AFHDS3_RX_FREQ[];
+extern const char STR_AFHDS3_ACTUAL_POWER[];
+extern const char STR_AFHDS3_POWER_SOURCE[];
#endif
extern const char STR_CURVE_TYPES[];
@@ -169,6 +177,7 @@ extern const char STR_VSENSORTYPES[];
extern const char STR_VFORMULAS[];
extern const char STR_VPREC[];
extern const char STR_VCELLINDEX[];
+extern const char STR_TOUCH_PANEL[];
#if defined(BLUETOOTH)
extern const char STR_BLUETOOTH[];
@@ -188,6 +197,7 @@ extern const char STR_EXIT[];
#if !defined(PCBHORUS)
extern const char STR_MENUWHENDONE[];
+extern const char STR_NO_TELEMETRY_SCREENS[];
#endif
extern const char STR_FREE[];
@@ -293,6 +303,7 @@ extern const char STR_BLDELAY[];
#if defined(PWM_BACKLIGHT) || defined(COLORLCD)
extern const char STR_BLONBRIGHTNESS[];
extern const char STR_BLOFFBRIGHTNESS[];
+extern const char STR_KEYS_BACKLIGHT[];
#endif
extern const char STR_SPLASHSCREEN[];
@@ -387,12 +398,14 @@ extern const char STR_MULTI_FIXEDID[];
extern const char STR_MULTI_OPTION[];
extern const char STR_MULTI_VIDFREQ[];
extern const char STR_MULTI_RFTUNE[];
+extern const char STR_MULTI_RFPOWER[];
extern const char STR_MULTI_TELEMETRY[];
extern const char STR_MULTI_AUTOBIND[];
extern const char STR_DISABLE_CH_MAP[];
extern const char STR_DISABLE_TELEM[];
extern const char STR_MULTI_DSM_AUTODTECT[];
extern const char STR_MULTI_LOWPOWER[];
+extern const char STR_MULTI_LNA_DISABLE[];
extern const char STR_MODULE_NO_SERIAL_MODE[];
extern const char STR_MODULE_NO_INPUT[];
extern const char STR_MODULE_WAITFORBIND[];
@@ -462,6 +475,7 @@ extern const char STR_BEEP_VOLUME[];
extern const char STR_WAV_VOLUME[];
extern const char STR_BG_VOLUME[];
extern const char STR_SELECT_MODEL[];
+extern const char STR_SELECT_MODE[];
extern const char STR_CREATE_CATEGORY[];
extern const char STR_RENAME_CATEGORY[];
extern const char STR_DELETE_CATEGORY[];
@@ -494,6 +508,8 @@ extern const char STR_RESET_BTN[];
extern const char STR_DEBUG[];
extern const char STR_KEYS_BTN[];
extern const char STR_ANALOGS_BTN[];
+extern const char STR_TOUCH_NOTFOUND[];
+extern const char STR_TOUCH_EXIT[];
extern const char STR_CALIBRATION[];
extern const char STR_NO_TOOLS[];
extern const char STR_NORMAL[];
@@ -525,6 +541,7 @@ extern const char STR_SPECTRUM_ANALYSER_EXT[];
extern const char STR_SPECTRUM_ANALYSER_INT[];
extern const char STR_WAITING_FOR_RX[];
extern const char STR_WAITING_FOR_TX[];
+extern const char STR_WARN_5VOLTS[];
#if defined(SDCARD)
extern const char STR_BACKUP_MODEL[];
@@ -552,8 +569,8 @@ extern const char STR_THROTTLEWARN[];
extern const char STR_ALARMSWARN[];
extern const char STR_SWITCHWARN[];
extern const char STR_FAILSAFEWARN[];
-extern const char STR_NIGHTLY_WARNING[];
-extern const char STR_NIGHTLY_NOTSAFE[];
+extern const char STR_TEST_WARNING[];
+extern const char STR_TEST_NOTSAFE[];
extern const char STR_WRONG_SDCARDVERSION[];
extern const char STR_WARN_RTC_BATTERY_LOW[];
extern const char STR_WARN_MULTI_LOWPOWER[];
@@ -592,6 +609,22 @@ extern const char STR_PLAY_FILE[];
extern const char STR_ASSIGN_BITMAP[];
#if defined(PCBHORUS)
extern const char STR_ASSIGN_SPLASH[];
+extern const char STR_FIRST_CHANNEL[];
+extern const char STR_FILL_BACKGROUND[];
+extern const char STR_BG_COLOR[];
+extern const char STR_SLIDERS_TRIMS[];
+extern const char STR_SLIDERS[];
+extern const char STR_FLIGHT_MODE[];
+extern const char STR_INVALID_FILE[];
+extern const char STR_TIMER_SOURCE[];
+extern const char STR_TEXT_SIZE[];
+extern const char STR_SIZE[];
+extern const char STR_SHADOW[];
+extern const char STR_TEXT[];
+extern const char STR_COLOR[];
+extern const char STR_MAIN_VIEW_X[];
+extern const char STR_PANEL1_BACKGROUND[];
+extern const char STR_PANEL2_BACKGROUND[];
#endif
extern const char STR_EXECUTE_FILE[];
extern const char STR_DELETE_FILE[];
@@ -626,6 +659,8 @@ extern const char STR_VIEW_TEXT[];
extern const char STR_FLASH_BOOTLOADER[];
extern const char STR_FLASH_EXTERNAL_DEVICE[];
extern const char STR_FLASH_RECEIVER_OTA[];
+extern const char STR_FLASH_RECEIVER_OTA_BY_EXTERNAL[];
+extern const char STR_FLASH_RECEIVER_OTA_BY_INTERNAL[];
extern const char STR_FLASH_BLUETOOTH_MODULE[];
extern const char STR_FLASH_POWER_MANAGEMENT_UNIT[];
extern const char STR_CURRENT_VERSION[];
@@ -821,6 +856,7 @@ extern const char STR_PT[];
extern const char STR_PTS[];
extern const char STR_SMOOTH[];
extern const char STR_COPY_STICKS_TO_OFS[];
+extern const char STR_COPY_MIN_MAX_TO_OUTPUTS[];
extern const char STR_COPY_TRIMS_TO_OFS[];
extern const char STR_INCDEC[];
extern const char STR_GLOBALVAR[];
@@ -840,6 +876,7 @@ extern const char STR_SCALE[];
extern const char STR_VIEW_CHANNELS[];
extern const char STR_POTWARNING[];
extern const char STR_AUX_SERIAL_MODE[];
+extern const char STR_AUX2_SERIAL_MODE[];
extern const char STR_THROTTLE_LABEL[];
extern const char STR_SCRIPT[];
extern const char STR_INPUTS[];
@@ -862,6 +899,8 @@ extern const char STR_MENU_OTHER[];
extern const char STR_MENU_INVERT[];
extern const char STR_JITTER_FILTER[];
extern const char STR_RTC_CHECK[];
+extern const char STR_SPORT_UPDATE_POWER_MODE[];
+extern const char STR_SPORT_UPDATE_POWER_MODES[];
#if MENUS_LOCK == 1
extern const char STR_UNLOCKED[];
diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt
index df4261a0a..adaa7d30e 100644
--- a/radio/src/translations/cz.h.txt
+++ b/radio/src/translations/cz.h.txt
@@ -375,6 +375,9 @@
#define LEN_GYROS "\004"
#define TR_GYROS "GyrX""GyrY"
+#define LEN_TEXT_SIZE "\010"
+#define TR_TEXT_SIZE "Standard""Tiny\0 ""Small\0 ""Mid\0 ""Double\0 "
+
// ZERO TERMINATED STRINGS
#if defined(COLORLCD)
#define INDENT "\007"
@@ -438,6 +441,7 @@
#define TR_PPMFRAME INDENT "PPM modulace"
#define TR_REFRESHRATE TR(INDENT "Obnovit", INDENT "Obn. frekv.")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Výstup VBAT: ", INDENT "Varování: výstupní hodnota VBAT: ")
+#define TR_WARN_5VOLTS "Warning: output level is 5 volts"
#define TR_MS "ms"
#define TR_FREQUENCY INDENT "Frequence"
#define TR_SWITCH "Spínač"
@@ -519,6 +523,7 @@
#define TR_BLDELAY INDENT"Zhasnout po"
#define TR_BLONBRIGHTNESS TR3(INDENT"Jas Zap.", INDENT"Jas Zap.", INDENT"Jas zapnutého LCD")
#define TR_BLOFFBRIGHTNESS TR3(INDENT"Jas Vyp.", INDENT"Jas Vyp.", INDENT"Jas vypnutého LCD")
+#define TR_KEYS_BACKLIGHT "Keys backlight"
#define TR_BLCOLOR INDENT "Barva"
#define TR_SPLASHSCREEN TR("úvodní logo", "Zobrazit úvodní logo")
#define TR_PWR_ON_DELAY "Pwr On delay"
@@ -625,6 +630,7 @@
#define TR_RECEIVER_NUM TR("RX číslo", "Číslo přijímače")
#define TR_RECEIVER "Přijímač"
#define TR_MULTI_RFTUNE TR(INDENT "Ladění frek", INDENT "Jemné ladění frek. RF")
+#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_TELEMETRY "Telemetrie"
#define TR_MULTI_VIDFREQ TR(INDENT "Freq. videa", INDENT "Frekvence videa")
#define TR_RFPOWER "Výkon RF"
@@ -635,6 +641,7 @@
#define TR_DISABLE_TELEM TR("No Telem", "Disable Telemetry")
#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetekce", INDENT "Formát autodetekce")
#define TR_MULTI_LOWPOWER TR(INDENT "Nízký výkon", INDENT "Režim nízkého výkonu")
+#define TR_MULTI_LNA_DISABLE INDENT "LNA disable"
#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "S.Port link")
#define TR_MODULE_TELEM_ON TR("Zap", "Zapnuto")
#define TR_DISABLE_INTERNAL TR("Vypnout int.", "Vypnout interní RF")
@@ -644,7 +651,7 @@
#define TR_MODULE_WAITFORBIND "Párovat při zavedení protokolu"
#define TR_MODULE_BINDING TR("Bind...","Párování")
#define TR_MODULE_UPGRADE_ALERT TR3("Upg. needed", "Module upgrade required", "Module\nUpgrade required")
-#define TR_MODULE_UPGRADE TR("Upg. needed", "Module update recommended")
+#define TR_MODULE_UPGRADE TR("Upg. advised", "Module update recommended")
#define TR_REBIND "Nutno přepárovat"
#define TR_REG_OK "Registrace ok"
#define TR_BIND_OK "Úspěšné párovaní"
@@ -675,6 +682,7 @@
#define TR_VOLTAGE INDENT"Napětí"
#define TR_CURRENT INDENT"Proud"
#define TR_SELECT_MODEL "Vyber model"
+#define TR_SELECT_MODE "Select mode"
#define TR_CREATE_CATEGORY "Nová kategorie"
#define TR_RENAME_CATEGORY "Přejmenovat kategorii"
#define TR_DELETE_CATEGORY "Odstranit kategorii"
@@ -733,8 +741,8 @@
#define TR_ALARMSWARN "ALARMU"
#define TR_SWITCHWARN "POZICE"
#define TR_FAILSAFEWARN "FAILSAFE"
-#define TR_NIGHTLY_WARNING TR("NOČNÍ", "NOČNÍ SESTAVENÍ")
-#define TR_NIGHTLY_NOTSAFE "Verze není bezpečná k létání"
+#define TR_TEST_WARNING TR("NOČNÍ", "NOČNÍ SESTAVENÍ")
+#define TR_TEST_NOTSAFE "Use for tests only"
#define TR_WRONG_SDCARDVERSION "Očekávaná ver.: "
#define TR_WARN_RTC_BATTERY_LOW "Slabá RTC baterie"
#define TR_WARN_MULTI_LOWPOWER "Low power mode"
@@ -821,6 +829,8 @@
#define TR_FLASH_BOOTLOADER "Flash bootloaderu"
#define TR_FLASH_EXTERNAL_DEVICE TR("Flash S.Portem", "Flash S.Portem")
#define TR_FLASH_RECEIVER_OTA "Flash příjímače OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA"
#define TR_FLASH_BLUETOOTH_MODULE TR("Flash modulu BT", "Flash modulu Bluetooth")
#define TR_FLASH_POWER_MANAGEMENT_UNIT TR("Flash řízení spotř.", "Flash jednotky řízení spotřeby")
#define TR_CURRENT_VERSION TR("Současná ver. ", "Současná verze: ")
@@ -830,7 +840,7 @@
#define TR_FLASH_EXTERNAL_MULTI TR("Flash Ext. Multi", "Flash External Multi")
#define TR_FIRMWARE_UPDATE_ERROR TR("Chyba zápisu FW", "Chyba zápisu firmware")
#define TR_FIRMWARE_UPDATE_SUCCESS "Úspěšný zápis FW"
-#define TR_WRITING TR3("\14Zapisuji..", "\032Zapisuji..", "Zapisuji..")
+#define TR_WRITING "Zapisuji.."
#define TR_CONFIRM_FORMAT "Provést Formát?"
#define TR_INTERNALRF "Interní RF modul"
#define TR_INTERNAL_MODULE "Interní modul"
@@ -895,7 +905,7 @@
#define TR_POWERMETER_ATTN_NEEDED "Útlumový člen nutný!"
#define TR_PXX2_SELECT_RX "Vyber RX..."
#define TR_PXX2_DEFAULT ""
-#define TR_BT_SELECT_DEVICE "Vyberte zařízení..."
+#define TR_BT_SELECT_DEVICE "Vyberte zařízení"
#define TR_DISCOVER "Hledat"
#define TR_BUTTON_INIT BUTTON("Init")
#define TR_WAITING "Čekám..."
@@ -911,6 +921,8 @@
#define TR_DEBUG "Debug"
#define TR_KEYS_BTN BUTTON(TR("SW","Přepínače"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogy"))
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
#define TR_CALIBRATION "Kalibrace"
#define TR_SET BUTTON("Nast")
#define TR_TRAINER "Trenér"
@@ -926,6 +938,11 @@
#define TR_UNIT "Jednotky"
#define TR_TELEMETRY_NEWSENSOR INDENT "Přidat senzor ručně"
#define TR_CHANNELRANGE TR(INDENT "Kanály", INDENT "Rozsah kanálů")
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", TR("Power src.", "Power source"))
#define TR_ANTENNACONFIRM1 "Opravdu přepnout?"
#if defined(PCBX12S)
#define LEN_ANTENNA_MODES "\023"
@@ -962,6 +979,7 @@
#define TR_PTS " b."
#define TR_SMOOTH "Hladká"
#define TR_COPY_STICKS_TO_OFS TR("Páky do subtrimu", "Kopie pák do subtrimu")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Cpy min/max to all", "Copy min/max/center to all outputs")
#define TR_COPY_TRIMS_TO_OFS TR("Trimy do subtrimu", "Kopíe trimů do subtrimu")
#define TR_INCDEC "Zvěšit/Zmenšit"
#define TR_GLOBALVAR "Glob. proměnná"
@@ -972,6 +990,7 @@
#define TR_CHECKLIST TR(INDENT "Poznámky", INDENT "Zobrazit poznámky")
#define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Ofset")
#define TR_AUX_SERIAL_MODE "Seriový port"
+#define TR_AUX2_SERIAL_MODE "Seriový port 2"
#define TR_SCRIPT "Skript"
#define TR_INPUTS "Vstupy"
#define TR_OUTPUTS "Výstupy"
@@ -979,6 +998,11 @@
#define STR_FACTORYRESET "Tovární reset"
#define TR_CONFIRMRESET TR("Smazat vše ?", "Smazat modely a nastavení?")
#define TR_TOO_MANY_LUA_SCRIPTS "Příliš mnoho skriptů!"
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Název"
@@ -1022,6 +1046,23 @@
// Horus footer descriptions
#define TR_LSW_DESCRIPTIONS { "Typ porovnávací funkce", "První proměnná", "Druhá proměnná nebo konstanta", "Druhá proměnná nebo konstanta", "Další stav povolující tenko spínač", "Minimální doba trvání sepnutého stavu", "Minimální doba platné podmínky pro aktivaci" }
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "First channel"
+#define TR_FILL_BACKGROUND "Fill background?"
+#define TR_BG_COLOR "BG Color"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Flight mode"
+#define TR_INVALID_FILE "Invalid File"
+#define TR_TIMER_SOURCE "Timer source"
+#define TR_SIZE "Size"
+#define TR_SHADOW "Shadow"
+#define TR_TEXT "Text"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Main view X"
+#define TR_PANEL1_BACKGROUND "Panel1 background"
+#define TR_PANEL2_BACKGROUND "Panel2 background"
+
// Taranis About screen
#define TR_ABOUTUS TR(" O nás ", "O nás")
@@ -1161,6 +1202,7 @@
#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage")
#define TR_AUTH_FAILURE "Auth-failure"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1199,6 +1241,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1247,7 +1290,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1262,3 +1305,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt
index 89ad37779..e6c6eb431 100644
--- a/radio/src/translations/de.h.txt
+++ b/radio/src/translations/de.h.txt
@@ -378,6 +378,9 @@
#define LEN_GYROS "\004"
#define TR_GYROS "GyrX""GyrY"
+#define LEN_TEXT_SIZE "\010"
+#define TR_TEXT_SIZE "Standard""Tiny\0 ""Small\0 ""Mid\0 ""Double\0 "
+
// ZERO TERMINATED STRINGS
#if defined(COLORLCD)
#define INDENT " "
@@ -440,6 +443,7 @@
#define TR_PPMFRAME INDENT "PPM-Frame"
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
+#define TR_WARN_5VOLTS "Warning: output level is 5 volts"
#define TR_MS "ms"
#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH TR("Schalt.", "Schalter")
@@ -521,6 +525,7 @@
#define TR_BLDELAY INDENT "Dauer"
#define TR_BLONBRIGHTNESS INDENT "An-Helligkeit"
#define TR_BLOFFBRIGHTNESS INDENT "Aus-Helligkeit"
+#define TR_KEYS_BACKLIGHT "Keys backlight"
#define TR_BLCOLOR INDENT "Farbe"
#define TR_SPLASHSCREEN TR("Startbild Ein", "Startbild Anzeigedauer")
#define TR_PWR_ON_DELAY "Pwr On delay"
@@ -627,6 +632,7 @@
#define TR_RECEIVER_NUM TR("Empf Nr.", "Empfänger Nummer")
#define TR_RECEIVER "Empfänger"
#define TR_MULTI_RFTUNE TR(INDENT "RF Freq.", INDENT "RF Freq. Feintuning")
+#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR(INDENT "Vid. Freq.", INDENT "Video Frequenz")
#define TR_RFPOWER "RF Power"
@@ -637,6 +643,7 @@
#define TR_DISABLE_TELEM TR("No Telem", "Disable Telemetry")
#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetect", INDENT "Autodetect format")
#define TR_MULTI_LOWPOWER TR(INDENT "Low power", INDENT "Low power mode")
+#define TR_MULTI_LNA_DISABLE INDENT "LNA disable"
#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "S.Port link")
#define TR_MODULE_TELEM_ON TR("ON", "Enabled")
#define TR_DISABLE_INTERNAL TR("Disable int. RF", "Disable internal RF")
@@ -645,15 +652,15 @@
#define TR_MODULE_NO_TELEMETRY TR3( "No telmetry", "No MULTI_TELEMETRY", "No telemetry (enable MULTI_TELEMETRY)")
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
-#define TR_MODULE_UPGRADE_ALERT TR3("Upg. needed", "Module upgrade required", "Module\nUpgrade required")
-#define TR_MODULE_UPGRADE TR("Upg. needed", "Module update recommended")
+#define TR_MODULE_UPGRADE_ALERT TR3("Upg. needed", "Module upgrade required", "Modul\nUpdate nötig")
+#define TR_MODULE_UPGRADE TR("Upg. advised", "Modulupdate empfohlen")
#define TR_REBIND "Rebinding required"
#define TR_REG_OK "Registration ok"
#define TR_BIND_OK "Bind successful"
-#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
-#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
-#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
-#define TR_BINDING_CH9_16_TELEM_OFF "Ch9-16 Telem OFF"
+#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem AN"
+#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem AUS"
+#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem AN"
+#define TR_BINDING_CH9_16_TELEM_OFF "Ch9-16 Telem AUS"
#define TR_PROTOCOL_INVALID TR("Prot. invalid", "Protocol invalid")
#define TR_MODULE_STATUS TR(INDENT "Status", INDENT "Module Status")
#define TR_MODULE_SYNC TR(INDENT "Sync", INDENT "Proto Sync Status")
@@ -677,18 +684,19 @@
#define TR_VOLTAGE TR(INDENT "Spg", INDENT "Spannungsquelle") //9XR-Pro
#define TR_CURRENT TR(INDENT "Strom", INDENT "Stromquelle")
#define TR_SELECT_MODEL "Modell auswählen"
-#define TR_CREATE_CATEGORY "Modelltyp erzeugen"
+#define TR_SELECT_MODE "Select mode"
+#define TR_CREATE_CATEGORY "Modelltyp erstellen"
#define TR_RENAME_CATEGORY "Modelltyp umbenennen"
#define TR_DELETE_CATEGORY "Modelltyp löschen"
-#define TR_CREATE_MODEL "Neues Modell"
+#define TR_CREATE_MODEL TR("Neues Modell" , "Neues Modell erstellen")
#define TR_DUPLICATE_MODEL "Kopiere Modell"
#define TR_COPY_MODEL "Kopiere Modell"
#define TR_MOVE_MODEL "Verschiebe Modell"
#define TR_BACKUP_MODEL "Modell auf SD-Karte" //9XR-Pro
-#define TR_DELETE_MODEL "Modell löschen" // TODO merged into DELETEMODEL?
+#define TR_DELETE_MODEL "Lösche Modell" // TODO merged into DELETEMODEL?
#define TR_RESTORE_MODEL TR("Modell wiederher.", "Modell wiederherstellen")
-#define TR_DELETE_ERROR "Fehler beim Löschen"
-#define TR_CAT_NOT_EMPTY "Kategorie nicht leer"
+#define TR_DELETE_ERROR "Fehler beim\nLöschen"
+#define TR_CAT_NOT_EMPTY "Modelltyp nicht leer"
#define TR_SDCARD_ERROR "SD-Kartenfehler"
#define TR_NO_SDCARD "Keine SD-Karte"
#define TR_WAITING_FOR_RX "Waiting for RX..."
@@ -735,8 +743,8 @@
#define TR_ALARMSWARN "ALARM"
#define TR_SWITCHWARN "SCHALTER"
#define TR_FAILSAFEWARN "FAILSAFE"
-#define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD")
-#define TR_NIGHTLY_NOTSAFE "Nicht für Flug geeignet"
+#define TR_TEST_WARNING TR("TESTING", "TEST BUILD")
+#define TR_TEST_NOTSAFE "Use for tests only"
#define TR_WRONG_SDCARDVERSION TR("Erw. Version: ","Erwartete Version: ")
#define TR_WARN_RTC_BATTERY_LOW "RTC Battery low"
#define TR_WARN_MULTI_LOWPOWER "Low power mode"
@@ -820,19 +828,21 @@
#define TR_MIXERS_MONITOR "==>Mischer Monitor"
#define TR_PATH_TOO_LONG "Pfad zu Lang"
#define TR_VIEW_TEXT "View Text"
-#define TR_FLASH_BOOTLOADER TR("Flash bootloader","Flash bootloader selbst") //
+#define TR_FLASH_BOOTLOADER TR("Flash bootloader","Flash bootloader") //
#define TR_FLASH_EXTERNAL_DEVICE TR("Flash ext. Gerät","Flash externes Gerät")
#define TR_FLASH_RECEIVER_OTA "Flash receiver OTA"
-#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module")
+#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA"
+#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetoothmodul")
#define TR_FLASH_POWER_MANAGEMENT_UNIT TR("Flash pwr mngt unit", "Flash power management unit")
#define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ")
#define TR_FLASH_INTERNAL_MODULE TR("Flash int. XJT","Flash internes XJT-Modul")
-#define TR_FLASH_INTERNAL_MULTI TR("Flash Int. Multi", "Flash Internal Multi")
-#define TR_FLASH_EXTERNAL_MODULE TR("Flash ext. mod","Flash extern module")
-#define TR_FLASH_EXTERNAL_MULTI TR("Flash Ext. Multi", "Flash External Multi")
-#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
-#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
-#define TR_WRITING "Writing..."
+#define TR_FLASH_INTERNAL_MULTI TR("Flash Int. Multi", "Flash int. Multimodul")
+#define TR_FLASH_EXTERNAL_MODULE TR("Flash ext. mod","Flash ext. Modul")
+#define TR_FLASH_EXTERNAL_MULTI TR("Flash Ext. Multi", "Flash ext. Multimodul")
+#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware Updatefehler")
+#define TR_FIRMWARE_UPDATE_SUCCESS TR3("Flash successful","Flash successful","Update erfolgreich")
+#define TR_WRITING "Schreibe..."
#define TR_CONFIRM_FORMAT "Formatieren bestätigen?"
#define TR_INTERNALRF "Internes HF-Modul"
#define TR_INTERNAL_MODULE TR("Int. module","Internal module")
@@ -895,9 +905,9 @@
#define TR_BYTES "Bytes"
#define TR_MODULE_BIND BUTTON(TR("Bnd","Bind")) //9XR-Pro
#define TR_POWERMETER_ATTN_NEEDED "Attenuator needed"
-#define TR_PXX2_SELECT_RX "Select RX..."
+#define TR_PXX2_SELECT_RX "Select RX"
#define TR_PXX2_DEFAULT ""
-#define TR_BT_SELECT_DEVICE "Select device..."
+#define TR_BT_SELECT_DEVICE "Select device"
#define TR_DISCOVER "Discover"
#define TR_BUTTON_INIT BUTTON("Init")
#define TR_WAITING "Waiting..."
@@ -913,6 +923,8 @@
#define TR_DEBUG "Testen"
#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
#define TR_CALIBRATION "Kalibrieren"
#define TR_SET BUTTON("Set")
#define TR_TRAINER "DSC Buchse PPM In/Out"
@@ -932,6 +944,11 @@
#define TR_UNIT "Einheit"
#define TR_TELEMETRY_NEWSENSOR INDENT "Sensor hinzufügen ..."
#define TR_CHANNELRANGE TR(INDENT "Kanäle", INDENT "Ausgangs Kanäle") //wg 9XR-Pro
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source")
#define TR_ANTENNACONFIRM1 "Ant. umschalten"
#if defined(PCBX12S)
#define LEN_ANTENNA_MODES "\023"
@@ -961,14 +978,15 @@
#define TR_PRESET "Preset"
#define TR_MIRROR "Spiegeln"
#define TR_CLEAR "Löschen"
-#define TR_RESET TR("Servowert reset","Servowerte rücksetzen")
+#define TR_RESET TR("Servowert reset","Servowerte zurücksetzen")
#define TR_RESET_SUBMENU TR("Reset Werte ==>", "Reset=>Timer Flug Telem")
#define TR_COUNT "Punkte"
#define TR_PT "Pt"
#define TR_PTS "Pts"
#define TR_SMOOTH "Runden"
-#define TR_COPY_STICKS_TO_OFS TR("Copy Stk ->Subtrim", "Kopie Stick to Servo-Mitte")
-#define TR_COPY_TRIMS_TO_OFS TR("Copy Trim->Subtrim", "Kopie Trimm to Servo-Mitte") // "Trim to Subtrim"
+#define TR_COPY_STICKS_TO_OFS TR3("Copy Stk ->Subtrim", "Kopiere Stick zu Subtrim", "Kopiere Knüppelposition auf Subtrim")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR3("Cpy min/max to all", "Kopiere min/max zu allen" , "Kopiere Limits & Mitte auf alle Kanäle")
+#define TR_COPY_TRIMS_TO_OFS TR3("Copy Trim->Subtrim", "Kopiere Trimm zu Subtrim" , "Kopiere Trimmposition auf Subtrim") // "Trim to Subtrim"
#define TR_INCDEC "Inc/Decrement"
#define TR_GLOBALVAR "Global Var"
#define TR_MIXSOURCE "Mixer Quelle"
@@ -978,6 +996,7 @@
#define TR_CHECKLIST TR(INDENT "Checkliste", INDENT "Checkliste anzeigen") //9XR-Pro
#define TR_FAS_OFFSET TR(INDENT "FAS-Ofs", INDENT "FAS-Offset")
#define TR_AUX_SERIAL_MODE "Serieller Port"
+#define TR_AUX2_SERIAL_MODE "Serieller Port 2"
#define TR_SCRIPT "Lua-Skript"
#define TR_INPUTS "Eingaben"
#define TR_OUTPUTS "Ausgaben"
@@ -985,6 +1004,11 @@
#define STR_FACTORYRESET TR("Werksreset", "Auf Werkseinstellungen")
#define TR_CONFIRMRESET TR("Alles löschen? ","ALLE Modelle+Einst. löschen?")
#define TR_TOO_MANY_LUA_SCRIPTS "Zu viele Skripte!"
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis specific column headers
#define TR_PHASES_HEADERS_NAME "Name "
@@ -997,6 +1021,24 @@
#define TR_PHASES_HEADERS_CH6_TRIM "Trim 6"
#define TR_PHASES_HEADERS_FAD_IN "Langs Ein"
#define TR_PHASES_HEADERS_FAD_OUT "Langs Aus"
+
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "First channel"
+#define TR_FILL_BACKGROUND "Fill background?"
+#define TR_BG_COLOR "BG Color"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Flight mode"
+#define TR_INVALID_FILE "Invalid File"
+#define TR_TIMER_SOURCE "Timer source"
+#define TR_SIZE "Size"
+#define TR_SHADOW "Shadow"
+#define TR_TEXT "Text"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Main view X"
+#define TR_PANEL1_BACKGROUND "Panel1 background"
+#define TR_PANEL2_BACKGROUND "Panel2 background"
+
// Taranis Info Zeile Anzeigen
#define TR_LIMITS_HEADERS_NAME "Name"
#define TR_LIMITS_HEADERS_SUBTRIM "Subtrim"
@@ -1167,6 +1209,7 @@
#define TR_AUTH_FAILURE "Auth-failure"
// ----------------------------------------------------------------
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1205,6 +1248,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1253,7 +1297,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1268,3 +1312,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt
index 0cfa48682..706197f33 100644
--- a/radio/src/translations/en.h.txt
+++ b/radio/src/translations/en.h.txt
@@ -378,6 +378,9 @@
#define LEN_GYROS "\004"
#define TR_GYROS "GyrX""GyrY"
+#define LEN_TEXT_SIZE "\010"
+#define TR_TEXT_SIZE "Standard""Tiny\0 ""Small\0 ""Mid\0 ""Double\0 "
+
// ZERO TERMINATED STRINGS
#if defined(COLORLCD)
#define INDENT " "
@@ -439,6 +442,7 @@
#define TR_PPMFRAME INDENT "PPM frame"
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
+#define TR_WARN_5VOLTS "Warning: output level is 5 volts"
#define TR_MS "ms"
#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Switch"
@@ -520,6 +524,7 @@
#define TR_BLDELAY INDENT "Duration"
#define TR_BLONBRIGHTNESS INDENT "ON brightness"
#define TR_BLOFFBRIGHTNESS INDENT "OFF brightness"
+#define TR_KEYS_BACKLIGHT "Keys backlight"
#define TR_BLCOLOR INDENT "Color"
#define TR_SPLASHSCREEN "Splash screen"
#define TR_PWR_ON_DELAY "Pwr On delay"
@@ -626,6 +631,7 @@
#define TR_RECEIVER_NUM TR("RxNum", "Receiver No.")
#define TR_RECEIVER "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
+#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -636,6 +642,7 @@
#define TR_DISABLE_TELEM TR("No Telem", "Disable Telemetry")
#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetect", INDENT "Autodetect format")
#define TR_MULTI_LOWPOWER TR(INDENT "Low power", INDENT "Low power mode")
+#define TR_MULTI_LNA_DISABLE INDENT "LNA disable"
#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "S.Port link")
#define TR_MODULE_TELEM_ON TR("ON", "Enabled")
#define TR_DISABLE_INTERNAL TR("Disable int.", "Disable internal RF")
@@ -645,7 +652,7 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING TR("Bind...","Binding")
#define TR_MODULE_UPGRADE_ALERT TR3("Upg. needed", "Module upgrade required", "Module\nUpgrade required")
-#define TR_MODULE_UPGRADE TR("Upg. needed", "Module update recommended")
+#define TR_MODULE_UPGRADE TR("Upg. advised", "Module update recommended")
#define TR_REBIND "Rebinding required"
#define TR_REG_OK "Registration ok"
#define TR_BIND_OK "Bind successful"
@@ -659,6 +666,11 @@
#define TR_MULTI_SERVOFREQ TR("Servo rate", "Servo update rate")
#define TR_MULTI_MAX_THROW TR("Max. Throw", "Enable max. throw")
#define TR_MULTI_RFCHAN TR("RF Channel", "Select RF channel")
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source")
#define TR_SYNCMENU "[Sync]"
#define TR_LIMIT INDENT "Limit"
#define TR_MINRSSI "Min Rssi"
@@ -676,6 +688,7 @@
#define TR_VOLTAGE TR(INDENT "Voltage", INDENT "Voltage source")
#define TR_CURRENT TR(INDENT "Current", INDENT "Current source")
#define TR_SELECT_MODEL "Select model"
+#define TR_SELECT_MODE "Select mode"
#define TR_CREATE_CATEGORY "Create category"
#define TR_RENAME_CATEGORY "Rename category"
#define TR_DELETE_CATEGORY "Delete category"
@@ -734,8 +747,8 @@
#define TR_ALARMSWARN "ALARMS"
#define TR_SWITCHWARN TR("SWITCH", "CONTROL")
#define TR_FAILSAFEWARN "FAILSAFE"
-#define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD")
-#define TR_NIGHTLY_NOTSAFE "Version not safe to fly"
+#define TR_TEST_WARNING TR("TESTING", "TEST BUILD")
+#define TR_TEST_NOTSAFE "Use for tests only"
#define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ")
#define TR_WARN_RTC_BATTERY_LOW "RTC Battery low"
#define TR_WARN_MULTI_LOWPOWER "Low power mode"
@@ -822,6 +835,8 @@
#define TR_FLASH_BOOTLOADER "Flash bootloader"
#define TR_FLASH_EXTERNAL_DEVICE TR("Flash S.Port", "Flash S.Port device")
#define TR_FLASH_RECEIVER_OTA "Flash receiver OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA"
#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module")
#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit"
#define TR_CURRENT_VERSION TR("Curr Vers: ", "Current version: ")
@@ -834,8 +849,8 @@
#define TR_WRITING "Writing..."
#define TR_CONFIRM_FORMAT "Confirm Format?"
#define TR_INTERNALRF "Internal RF"
-#define TR_INTERNAL_MODULE TR("Int. module","Internal module")
-#define TR_EXTERNAL_MODULE TR("Ext. module","External module")
+#define TR_INTERNAL_MODULE TR("Int. module", "Internal module")
+#define TR_EXTERNAL_MODULE TR("Ext. module", "External module")
#define TR_OPENTX_UPGRADE_REQUIRED "OpenTX upgrade required"
#define TR_TELEMETRY_DISABLED "Telem. disabled"
#define TR_MORE_OPTIONS_AVAILABLE "More options available"
@@ -894,9 +909,9 @@
#define TR_BYTES "bytes"
#define TR_MODULE_BIND BUTTON(TR("Bnd", "Bind"))
#define TR_POWERMETER_ATTN_NEEDED "Attenuator needed"
-#define TR_PXX2_SELECT_RX "Select RX..."
+#define TR_PXX2_SELECT_RX "Select RX"
#define TR_PXX2_DEFAULT ""
-#define TR_BT_SELECT_DEVICE "Select device..."
+#define TR_BT_SELECT_DEVICE "Select device"
#define TR_DISCOVER "Discover"
#define TR_BUTTON_INIT BUTTON("Init")
#define TR_WAITING "Waiting..."
@@ -912,6 +927,8 @@
#define TR_DEBUG "Debug"
#define TR_KEYS_BTN BUTTON(TR("Keys", "Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Anas", "Analogs"))
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
#define TR_CALIBRATION "Calibration"
#define TR_SET BUTTON("Set")
#define TR_TRAINER "Trainer"
@@ -967,6 +984,7 @@
#define TR_PTS "pts"
#define TR_SMOOTH "Smooth"
#define TR_COPY_STICKS_TO_OFS TR("Cpy stick->subtrim", "Copy sticks to subtrim")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Cpy min/max to all", "Copy min/max/center to all outputs")
#define TR_COPY_TRIMS_TO_OFS TR("Cpy trim->subtrim", "Copy trims to subtrim")
#define TR_INCDEC "Inc/Decrement"
#define TR_GLOBALVAR "Global var"
@@ -976,7 +994,8 @@
#define TR_PREFLIGHT "Preflight Checks"
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "Display checklist")
#define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS offset")
-#define TR_AUX_SERIAL_MODE "Serial port"
+#define TR_AUX_SERIAL_MODE "Serial port"
+#define TR_AUX2_SERIAL_MODE "Serial port 2"
#define TR_SCRIPT "Script"
#define TR_INPUTS "Inputs"
#define TR_OUTPUTS "Outputs"
@@ -984,6 +1003,11 @@
#define STR_FACTORYRESET "Factory reset"
#define TR_CONFIRMRESET TR("Erase ALL", "Erase ALL models and settings?")
#define TR_TOO_MANY_LUA_SCRIPTS "Too many Lua scripts!"
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Name"
@@ -1027,6 +1051,23 @@
// Horus footer descriptions
#define TR_LSW_DESCRIPTIONS { "Comparison type or function", "First variable", "Second variable or constant", "Second variable or constant", "Additional condition for line to be enabled", "Minimum ON duration of the logical switch", "Minimum TRUE duration for the switch to become ON" }
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "First channel"
+#define TR_FILL_BACKGROUND "Fill background?"
+#define TR_BG_COLOR "BG Color"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Flight mode"
+#define TR_INVALID_FILE "Invalid File"
+#define TR_TIMER_SOURCE "Timer source"
+#define TR_SIZE "Size"
+#define TR_SHADOW "Shadow"
+#define TR_TEXT "Text"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Main view X"
+#define TR_PANEL1_BACKGROUND "Panel1 background"
+#define TR_PANEL2_BACKGROUND "Panel2 background"
+
// About screen
#define TR_ABOUTUS TR(" ABOUT ", "ABOUT")
@@ -1165,6 +1206,7 @@
#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage")
#define TR_AUTH_FAILURE "Auth-failure"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1203,6 +1245,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1251,7 +1294,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1266,3 +1309,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt
index acdc29090..714fcc217 100644
--- a/radio/src/translations/es.h.txt
+++ b/radio/src/translations/es.h.txt
@@ -19,7 +19,7 @@
*
*/
-// ES translations author: Jose Moreno
+// ES translations authors: Jose Moreno , Daniel GeA
/*
* !!!!! DO NOT EDIT es.h - EDIT es.h.txt INSTEAD !!!!!!!
@@ -49,11 +49,11 @@
#define LEN_MMMINV "\003"
#define TR_MMMINV "---""INV"
-#define LEN_VBEEPMODE "\005"
-#define TR_VBEEPMODE "Mudo ""Alarm""NoKey""Todo "
+#define LEN_VBEEPMODE "\010"
+#define TR_VBEEPMODE "Silencio""Alarma\0 ""No tecla""Todo\0 "
-#define LEN_VBLMODE "\004"
-#define TR_VBLMODE "OFF ""Keys""Stks""Both""ON\0"
+#define LEN_VBLMODE "\006"
+#define TR_VBLMODE "OFF\0 ""Teclas""Sticks""Ambos\0""ON\0 "
#define LEN_TRNMODE "\003"
#define TR_TRNMODE "OFF""+=\0"":="
@@ -63,54 +63,54 @@
#define LEN_AUX_SERIAL_MODES "\015"
#if defined(CLI) || defined(DEBUG)
-#define TR_AUX_SERIAL_MODES "Debug\0 ""Telem Mirror\0""Telemetry In\0""SBUS Trainer\0""LUA\0 "
+#define TR_AUX_SERIAL_MODES "Debug\0 ""Telem Mirror\0""Telemetría\0 ""Entrenador SBUS""LUA\0 "
#else
-#define TR_AUX_SERIAL_MODES "OFF\0 ""Telem Mirror\0""Telemetry In\0""SBUS Trainer\0""LUA\0 "
+#define TR_AUX_SERIAL_MODES "OFF\0 ""Telem Mirror\0""Telemetría\0 ""Entrenador SBUS""LUA\0 "
#endif
-#define LEN_SWTYPES "\006"
-#define TR_SWTYPES "None\0 ""Toggle""2POS\0 ""3POS\0"
+#define LEN_SWTYPES "\007"
+#define TR_SWTYPES "Nada\0 ""Palanca""2POS\0 ""3POS\0 "
#define LEN_POTTYPES TR("\013", "\017")
-#define TR_POTTYPES TR("None ""Pot w det ""Multipos ""Pot ", "None ""Pot with detent""Multipos Switch""Pot\0")
+#define TR_POTTYPES TR("Nada\0 ""Pot con fij""Multipos\0 ""Pot\0 ", "Nada\0 ""Pot con fijador""Switch multipos""Pot\0 ")
#define LEN_SLIDERTYPES "\006"
-#define TR_SLIDERTYPES "Rien\0 ""Slider"
+#define TR_SLIDERTYPES "Nada\0 ""Slider"
#define LEN_VLCD "\006"
#define TR_VLCD "NormalOptrex"
#define LEN_VPERSISTENT "\014"
-#define TR_VPERSISTENT "OFF\0 ""Flight\0 ""Manual Reset"
+#define TR_VPERSISTENT "OFF\0 ""Vuelo\0 ""Reset manual"
#define LEN_COUNTRYCODES TR("\002", "\007")
-#define TR_COUNTRYCODES TR("US""JP""EU", "America""Japon\0 ""Europa\0")
+#define TR_COUNTRYCODES TR("US""JP""EU", "América""Japón\0 ""Europa\0")
-#define LEN_USBMODES TR("\006", "\010")
-#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
+#define LEN_USBMODES "\010"
+#define TR_USBMODES "Pregunta""Joystick""SDCard\0 ""Serie\0 "
-#define LEN_JACKMODES "\007"
-#define TR_JACKMODES "Ask\0 ""Audio\0 ""Trainer"
+#define LEN_JACKMODES "\010"
+#define TR_JACKMODES "Pregunta""Audio\0 ""Entrena."
#define LEN_TELEMETRY_PROTOCOLS "\017"
-#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
+#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetr."
#define TR_MULTI_CUSTOM "Custom"
#define LEN_VTRIMINC TR("\006", "\013")
-#define TR_VTRIMINC TR("Expo ""ExFino""Fino ""Medio ""Grueso", "Exponencial""Extra Fino ""Fino ""Medio ""Grueso ")
+#define TR_VTRIMINC TR("Expo\0 ""ExFino""Fino\0 ""Medio\0""Grueso", "Exponencial""Extra fino\0""Fino\0 ""Medio\0 ""Grueso\0 ")
-#define LEN_VDISPLAYTRIMS "\006"
-#define TR_VDISPLAYTRIMS "No\0 ""Change""Yes\0"
+#define LEN_VDISPLAYTRIMS "\007"
+#define TR_VDISPLAYTRIMS "No\0 ""Cambiar""Si\0 "
-#define LEN_VBEEPCOUNTDOWN "\006"
-#define TR_VBEEPCOUNTDOWN "SilentBeeps\0Voz\0 Haptic"
+#define LEN_VBEEPCOUNTDOWN "\010"
+#define TR_VBEEPCOUNTDOWN "Silencio""Beeps\0 ""Voz\0 ""Haptic\0 "
-#define LEN_VVARIOCENTER "\006"
-#define TR_VVARIOCENTER "Tone\0 ""Silent"
+#define LEN_VVARIOCENTER "\010"
+#define TR_VVARIOCENTER "Tono\0 ""Silencio"
-#define LEN_CURVE_TYPES "\010"
-#define TR_CURVE_TYPES "Standard""Custom\0"
+#define LEN_CURVE_TYPES "\006"
+#define TR_CURVE_TYPES "Normal""Custom"
#define LEN_RETA123 "\001"
@@ -143,21 +143,21 @@
#define LEN_VMIXTRIMS "\003"
#if defined(PCBHORUS)
- #define TR_VMIXTRIMS "OFF""ON\0""Dir""Ele""Ace""Ale""T5\0""T6\0"
+ #define TR_VMIXTRIMS "OFF""ON\0""Rud""Ele""Thr""Ail""T5\0""T6\0"
#else
- #define TR_VMIXTRIMS "OFF""ON\0""Dir""Ele""Ace""Ale"
+ #define TR_VMIXTRIMS "OFF""ON\0""Rud""Ele""Thr""Ail"
#endif
-#if defined(PCBTARANIS)
+#if LCD_W >= 212
#define TR_CSWTIMER "Timer"
- #define TR_CSWSTICKY "Stcky"
- #define TR_CSWRANGE "Range"
- #define TR_CSWSTAY "Edge\0"
+ #define TR_CSWSTICKY "Pega\0"
+ #define TR_CSWRANGE "Rango"
+ #define TR_CSWSTAY "Borde"
#else
#define TR_CSWTIMER "Tim\0 "
- #define TR_CSWSTICKY "Glue\0"
- #define TR_CSWRANGE "Rnge\0"
- #define TR_CSWSTAY "Edge\0"
+ #define TR_CSWSTICKY "Pega\0"
+ #define TR_CSWRANGE "Rngo\0"
+ #define TR_CSWSTAY "Bord\0"
#endif
#define TR_CSWEQUAL "a=x\0 "
@@ -174,15 +174,15 @@
#endif
#if defined(AUDIO)
- #define TR_SOUND "Oir Sonido"
+ #define TR_SOUND "Oir sonido"
#else
#define TR_SOUND "Beep\0 "
#endif
#if defined(HAPTIC)
- #define TR_HAPTIC "Tactil\0 "
+ #define TR_HAPTIC "Haptic\0 "
#else
- #define TR_HAPTIC "[Tactil]\0 "
+ #define TR_HAPTIC "[Haptic]\0 "
#endif
#if defined(VOICE)
@@ -199,7 +199,7 @@
#define TR_PLAY_VALUE "[OirValor]"
#endif
-#define TR_SF_BG_MUSIC "BgMusica\0 ""BgMusica||"
+#define TR_SF_BG_MUSIC "BgMúsica\0 ""BgMúsica||"
#if defined(SDCARD)
#define TR_SDCLOGS "SD Logs\0 "
@@ -210,7 +210,7 @@
#if defined(GVARS)
#define TR_ADJUST_GVAR "Ajuste\0 "
#else
- #define TR_ADJUST_GVAR "[AdjustGV]"
+ #define TR_ADJUST_GVAR "[AjusteGV]"
#endif
#if defined(LUA)
@@ -231,60 +231,42 @@
#define TR_SF_SAFETY "---\0 "
#endif
-#define TR_SF_SCREENSHOT "Screenshot"
-#define TR_SF_RESERVE "[reserve]\0"
+#define TR_SF_SCREENSHOT "Captura"
+#define TR_SF_RESERVE "[reserv.]\0"
-#define TR_VFSWFUNC TR_SF_SAFETY "Aprendiz\0 ""Inst. Trim""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volumen\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Luz fondo\0" TR_SF_SCREENSHOT TR_SF_TEST
+#define TR_VFSWFUNC TR_SF_SAFETY "Entrenador""Inst. Trim""Reset\0 ""Ajuste \0 " TR_ADJUST_GVAR "Volumen\0 " "Failsafe\0 " "CheckRango" "Enl.módulo" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Luz Fondo\0" TR_SF_SCREENSHOT TR_SF_TEST
-#define LEN_VFSWRESET TR("\004", "\011")
+#define LEN_VFSWRESET TR("\004", "\012")
+#define TR_FSW_RESET_TELEM TR("Telm", "Telemetría")
-#define TR_FSW_RESET_TELEM TR("Telm", "Telemetry")
-
-#if defined(PCBTARANIS)
- #define TR_FSW_RESET_TIMERS "Timer 1\0 ""Timer 2\0 ""Timer 3\0 "
+#if LCD_W >= 212
+ #define TR_FSW_RESET_TIMERS "Timer 1\0 ""Timer 2\0 ""Timer 3\0 "
#else
#define TR_FSW_RESET_TIMERS "Tmr1""Tmr2""Tmr3"
#endif
-#define TR_VFSWRESET TR(TR_FSW_RESET_TIMERS "All\0" TR_FSW_RESET_TELEM, TR_FSW_RESET_TIMERS "All\0 " TR_FSW_RESET_TELEM)
+#define TR_VFSWRESET TR(TR_FSW_RESET_TIMERS "Todo" TR_FSW_RESET_TELEM, TR_FSW_RESET_TIMERS "Vuelo\0 " TR_FSW_RESET_TELEM)
#define LEN_FUNCSOUNDS TR("\004", "\006")
#define TR_FUNCSOUNDS TR("Bp1\0""Bp2\0""Bp3\0""Avs1""Avs2""Chee""Rata""Tick""Sirn""Ring""SciF""Robt""Chrp""Tada""Crck""Alrm", "Beep1 ""Beep2 ""Beep3 ""Aviso1""Aviso2""Cheep ""Ratata""Tick ""Sirena""Ring ""SciFi ""Robot ""Chirp ""Tada ""Crickt""AlmClk")
#define LEN_VTELEMCHNS "\004"
- #define TR_TELEM_RESERVE TR("[--]", "[---]")
- #define TR_TELEM_TIME TR("Time", "Time\0")
- #define TR_RAS TR("SWR\0", "SWR\0 ")
- #define TR_RX_BATT TR("[NA]", "[NA]\0")
- #define TR_A3_A4 TR("A3\0 ""A4\0 ", "A3\0 ""A4\0 ")
- #define TR_A3_A4_MIN TR("A3-\0""A4-\0", "A3-\0 ""A4-\0 ")
-
-#define TR_ASPD_MAX TR("ASp+", "ASpd+")
-
-#if defined(PCBTARANIS)
- #define TR_TELEM_RSSI_RX "RSSI\0"
-#else
- #define TR_TELEM_RSSI_RX TR("Rx\0 ", "Rx\0 ")
-#endif
-
- #define TR_TELEM_TIMERS TR("Tmr1""Tmr2""Tmr3", "Tmr1\0""Tmr2\0""Tmr3\0")
-
#define LENGTH_UNIT_IMP "ft\0"
#define SPEED_UNIT_IMP "mph"
#define LENGTH_UNIT_METR "m\0 "
#define SPEED_UNIT_METR "kmh"
- #define LEN_VUNITSSYSTEM TR("\006", "\010")
- #define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
- #define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz"
+#define LEN_VUNITSSYSTEM "\010"
+#define TR_VUNITSSYSTEM "Métrico\0""Imperial"
+#define LEN_VTELEMUNIT "\003"
+#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
-#define LEN_VTELEMSCREENTYPE "\004"
-#define TR_VTELEMSCREENTYPE "Nums""Bars"
+#define LEN_VTELEMSCREENTYPE "\007"
+#define TR_VTELEMSCREENTYPE "Nada\0 ""Números""Barras\0""Script\0"
#define LEN_GPSFORMAT "\004"
#define TR_GPSFORMAT "HMS NMEA"
@@ -323,12 +305,12 @@
#define LEN_VSWITCHES "\003"
#define LEN_VSRCRAW "\004"
-#define TR_STICKS_VSRCRAW "\307Dir""\307Ele""\307Thr""\307Ale"
+#define TR_STICKS_VSRCRAW "\307Rud""\307Ele""\307Thr""\307Ail"
#if defined(PCBHORUS)
- #define TR_TRIMS_VSRCRAW "\313Dir""\313Ele""\313Thr""\313Ale""\313T5\0""\313T6\0"
+ #define TR_TRIMS_VSRCRAW "\313Rud""\313Ele""\313Thr""\313Ail""\313T5\0""\313T6\0"
#else
- #define TR_TRIMS_VSRCRAW TR("TrmD" "TrmE" "TrmT" "TrmA", "\313Dir""\313Ele""\313Thr""\313Ale")
+ #define TR_TRIMS_VSRCRAW TR("TrmR" "TrmE" "TrmT" "TrmA", "\313Rud""\313Ele""\313Thr""\313Ail")
#endif
#if defined(PCBHORUS)
@@ -360,7 +342,7 @@
#endif
#define TR_RESERVE_VSRCRAW "[--]"
-#define TR_EXTRA_VSRCRAW "Batt""Time""GPS\0" TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW "Tmr1""Tmr2""Tmr3"
+#define TR_EXTRA_VSRCRAW "Bat\0""Time""GPS\0" TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW "Tmr1""Tmr2""Tmr3"
#define LEN_VTMRMODES "\003"
#define TR_VTMRMODES "OFF""ABS""THs""TH%""THt"
@@ -368,31 +350,34 @@
#define LEN_VTRAINERMODES "\022"
#define TR_VTRAINER_MASTER_JACK "Master/Jack\0 "
#define TR_VTRAINER_SLAVE_JACK "Esclav/Jack\0 "
-#define TR_VTRAINER_MASTER_SBUS_MODULE "Master/SBUS Module"
-#define TR_VTRAINER_MASTER_CPPM_MODULE "Master/CPPM Module"
-#define TR_VTRAINER_MASTER_BATTERY "Master/Serial\0 "
-#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ")
+#define TR_VTRAINER_MASTER_SBUS_MODULE "Master/Módulo SBUS"
+#define TR_VTRAINER_MASTER_CPPM_MODULE "Master/Módulo CPPM"
+#define TR_VTRAINER_MASTER_BATTERY "Master/Serie\0 "
+#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Esclavo/BT\0 ", "Master/Bluetooth\0 ""Esclavo/Bluetooth\0")
#define TR_VTRAINER_MULTI "Master/Multi"
#define LEN_VFAILSAFE "\011"
-#define TR_VFAILSAFE "Not set\0 ""Guardar\0 ""Adaptar\0 ""Sin pulso""Receiver\0"
+#define TR_VFAILSAFE "No\0 ""Hold\0 ""Custom\0 ""No pulsos""Receptor\0"
#define LEN_VSENSORTYPES "\012"
-#define TR_VSENSORTYPES "Custom\0 ""Calculated"
+#define TR_VSENSORTYPES "Custom\0 ""Calculado"
-#define LEN_VFORMULAS "\010"
-#define TR_VFORMULAS "Add\0 ""Average\0""Min\0 ""Max\0 ""Multiply""Totalize""Cell\0 ""Consumpt""Distance"
+#define LEN_VFORMULAS "\011"
+#define TR_VFORMULAS "Suma\0 ""Media\0 ""Min\0 ""Máx\0 ""Multipl. ""Total\0 ""Cell\0 ""Consumo\0 ""Distancia"
#define LEN_VPREC "\004"
#define TR_VPREC "0.--""0.0 ""0.00"
#define LEN_VCELLINDEX "\007"
-#define TR_VCELLINDEX "Lowest\0""1\0 ""2\0 ""3\0 ""4\0 ""5\0 ""6\0 ""Highest""Delta\0"
+#define TR_VCELLINDEX "Menor\0 ""1\0 ""2\0 ""3\0 ""4\0 ""5\0 ""6\0 ""Mayor\0 ""Delta\0"
#define LEN_GYROS "\004"
#define TR_GYROS "GyrX""GyrY"
+#define LEN_TEXT_SIZE "\013"
+#define TR_TEXT_SIZE "Normal\0 ""Muy pequeño""Pequeño\0 ""Medio\0 ""Doble\0 "
+
// ZERO TERMINATED STRINGS
#if defined(COLORLCD)
#define INDENT " "
@@ -431,133 +416,131 @@
#define TR_FREE "libre"
#define TR_DELETEMODEL "BORRAR MODELO"
#define TR_COPYINGMODEL "Copiando modelo.."
-#define TR_MOVINGMODEL "Mover modelo..."
-#define TR_LOADINGMODEL "Cargar modelo..."
-#define TR_NAME "Nom."
-#define TR_MODELNAME "Nom.Modelo"
-#define TR_PHASENAME "Nom.Fase "
-#define TR_MIXNAME "Nom.Mezcla"
-#define TR_INPUTNAME "Input Name"
-#if defined(PCBTARANIS)
- #define TR_EXPONAME "Line Name"
-#else
- #define TR_EXPONAME "Nom. Expo"
-#endif
-#define TR_BITMAP "Imagen Modelo"
-#define TR_TIMER TR("Reloj","Reloj ")
-#define TR_ELIMITS TR("E.Limite","Ampliar Limites")
-#define TR_ETRIMS TR("E.Trims","Ampliar Trims")
-#define TR_TRIMINC "Paso Trim"
-#define TR_DISPLAY_TRIMS "Display Trims"
-#define TR_TTRACE TR("Fuente-A", INDENT "Fuente Acelerad")
-#define TR_TTRIM TR("Trim-A", INDENT "Trim Acelerad")
-#define TR_BEEPCTR TR("Ctr Beep","Center Beep")
-#define TR_USE_GLOBAL_FUNCS "Use Global Funcs"
+#define TR_MOVINGMODEL "Moviendo modelo..."
+#define TR_LOADINGMODEL "Cargando modelo..."
+#define TR_NAME "Nombre"
+#define TR_MODELNAME TR("Nom. modelo", "Nombre modelo")
+#define TR_PHASENAME "Nombre fase "
+#define TR_MIXNAME TR("Nom. mezcla", "Nombre mezcla")
+#define TR_INPUTNAME TR("Entrada", "Nom. entrada")
+#define TR_EXPONAME TR("Nom.", "Nombre expo")
+#define TR_BITMAP "Imagen modelo"
+#define TR_TIMER TR("Timer", "Timer ")
+#define TR_ELIMITS TR("E.Límite", "Ampliar límites")
+#define TR_ETRIMS TR("E.Trims", "Ampliar trims")
+#define TR_TRIMINC "Paso trim"
+#define TR_DISPLAY_TRIMS "Ver trims"
+#define TR_TTRACE TR("Fuente-A", INDENT "Fuente acelerador")
+#define TR_TTRIM TR("Trim-A", INDENT "Trim acelerador")
+#define TR_BEEPCTR TR("Beep ctr", "Beep centro")
+#define TR_USE_GLOBAL_FUNCS TR("Funcs. glob.", "Usar func. globales")
#if defined(PCBSKY9X) && defined(REVX)
#define TR_OUTPUT_TYPE INDENT "Output"
#endif
-#define TR_PROTO TR(INDENT"Proto",INDENT"Protocol")
+#define TR_PROTO TR(INDENT"Proto",INDENT"Protocolo")
#define TR_PPMFRAME "Trama PPM"
-#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
-#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
+#define TR_REFRESHRATE TR(INDENT "Refresco", INDENT "Velocidad refresco")
+#define STR_WARN_BATTVOLTAGE TR(INDENT "Salida es VBAT: ", INDENT "Aviso: señal salida es VBAT: ")
+#define TR_WARN_5VOLTS "Warning: output level is 5 volts"
#define TR_MS "ms"
-#define TR_FREQUENCY INDENT "Frequency"
-#define TR_SWITCH "Interr"
+#define TR_FREQUENCY INDENT "Frequencia"
+#define TR_SWITCH TR("Interr.", "Interruptor")
#define TR_TRIMS "Trims"
#define TR_FADEIN "Inicio"
#define TR_FADEOUT "Final"
#define TR_DEFAULT "(defecto)"
#define TR_CHECKTRIMS CENTER "\006Check\012Trims"
#define OFS_CHECKTRIMS CENTER_OFS+(9*FW)
-#define TR_SWASHTYPE "Tipo ciclico"
-#define TR_COLLECTIVE TR("Colectivo", "Fuente Colectivo")
-#define TR_AILERON TR("Lateral cyc.", "Lateral cyc. source")
-#define TR_ELEVATOR TR("Long. cyc.", "Long. cyc. source")
+#define TR_SWASHTYPE "Tipo cíclico"
+#define TR_COLLECTIVE TR("Colectivo", "Fuente colectivo")
+#define TR_AILERON TR("Col. lateral", "Fuente col. lateral")
+#define TR_ELEVATOR TR("Col. long. ", "Fuente col. longitudinal")
#define TR_SWASHRING "Ciclico"
-#define TR_ELEDIRECTION TR("ELE Direccion","Largo cyc. direccion")
-#define TR_AILDIRECTION TR("AIL Direccion","Lateral cyc. direccion")
-#define TR_COLDIRECTION TR("PIT Direccion","Coll. pitch direccion")
+#define TR_ELEDIRECTION TR("ELE Dirección", "Largo cyc. dirección")
+#define TR_AILDIRECTION TR("AIL Dirección", "Lateral cyc. dirección")
+#define TR_COLDIRECTION TR("PIT Dirección", "Coll. pitch dirección")
#define TR_MODE "Modo"
-#define TR_SUBTYPE INDENT "Subtype"
+#define TR_SUBTYPE INDENT "Subtipo"
#define TR_NOFREEEXPO "No expo libre!"
#define TR_NOFREEMIXER "No mezcla lib!"
#define TR_SOURCE "Fuente"
#define TR_WEIGHT "Cantidad"
-#define TR_EXPO TR("Expo","Exponencial")
-#define TR_SIDE "Lado"
+#define TR_EXPO TR("Expo", "Exponencial")
+#define TR_SIDE "Zona"
#define TR_DIFFERENTIAL "Diferenc"
#define TR_OFFSET "Offset"
#define TR_TRIM "Trim"
#define TR_DREX "DRex"
#define DREX_CHBOX_OFFSET 30
#define TR_CURVE "Curva"
-#define TR_FLMODE TR("Modo","Modos")
+#define TR_FLMODE TR("Modo", "Modos")
#define TR_MIXWARNING "Aviso"
#define TR_OFF "OFF"
-#define TR_ANTENNA "Antenna"
-#define TR_NO_INFORMATION TR("No info", "No information")
-#define TR_MULTPX "Multpx"
-#define TR_DELAYDOWN "Delay Dn"
-#define TR_DELAYUP "Delay Up"
-#define TR_SLOWDOWN "Slow Dn"
-#define TR_SLOWUP "Slow Up"
-#define TR_MIXES "Mezclas"
+#define TR_ANTENNA "Antena"
+#define TR_NO_INFORMATION TR("Sin info", "Sin información")
+#define TR_MULTPX "Multipx"
+#define TR_DELAYDOWN "Atraso bajar"
+#define TR_DELAYUP "Atraso subir"
+#define TR_SLOWDOWN "Bajar lento "
+#define TR_SLOWUP "Subir lento"
+#define TR_MIXES "MIXES"
#define TR_CV "CV"
#define TR_GV TR("G", "GV")
#define TR_ACHANNEL "A\004canal"
#define TR_RANGE INDENT"Alcance"
-#define TR_CENTER INDENT "Center"
+#define TR_CENTER INDENT "Centro"
#define TR_BAR "Bar"
#define TR_ALARM INDENT"Alarma"
#define TR_USRDATA "UsrData"
#define TR_BLADES INDENT"Palas"
-#define TR_SCREEN "Pantalla"
+#define TR_SCREEN "Pant. "
#define TR_SOUND_LABEL "Sonido"
#define TR_LENGTH INDENT"Longitud"
-#define TR_BEEP_LENGTH INDENT "Beep Length"
+#define TR_BEEP_LENGTH INDENT "Duración Beep"
#define TR_SPKRPITCH INDENT"Tono"
-#define TR_HAPTIC_LABEL "Tactil"
+#define TR_HAPTIC_LABEL "Haptic"
#define TR_HAPTICSTRENGTH INDENT"Intensidad"
#define TR_GYRO_LABEL "Gyro"
#define TR_GYRO_OFFSET "Offset"
-#define TR_GYRO_MAX "Max"
+#define TR_GYRO_MAX "Máx"
#define TR_CONTRAST "Contraste"
#define TR_ALARMS_LABEL "Alarmas"
-#define TR_BATTERY_RANGE TR("Rango bateria","Rango medidor Bater")
-#define TR_BATTERYWARNING INDENT"Bateria Baja"
+#define TR_BATTERY_RANGE TR("Rango batería", "Rango medidor batería")
+#define TR_BATTERYWARNING INDENT"Batería baja"
#define TR_INACTIVITYALARM INDENT"Inactividad"
-#define TR_MEMORYWARNING INDENT"Memoria Baja"
-#define TR_ALARMWARNING INDENT"Sin Sonido"
-#define TR_RSSISHUTDOWNALARM TR(INDENT "Rssi Shutdown", INDENT "Check Rssi on Shutdown")
-#define TR_MODEL_STILL_POWERED "Model still powered"
-#define TR_MODEL_SHUTDOWN "Shutdown ?"
-#define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm"
-#define TR_THROTTLE_LABEL "Throttle"
-#define TR_THROTTLEREVERSE TR("Invert_Acel", INDENT "Invertir Acel.")
-#define TR_MINUTEBEEP TR("Minuto", "Cada Minuto")
-#define TR_BEEPCOUNTDOWN INDENT"Cuentaatras"
-#define TR_PERSISTENT TR(INDENT"Persist.", INDENT"Persistente")
-#define TR_BACKLIGHT_LABEL "Luz Fondo"
-#define TR_BLDELAY INDENT"Duracion"
-#define TR_BLONBRIGHTNESS INDENT"MAS Brillo"
-#define TR_BLOFFBRIGHTNESS INDENT"MENOS Brillo"
+#define TR_MEMORYWARNING INDENT"Memoria baja"
+#define TR_ALARMWARNING INDENT"Sin sonido"
+#define TR_RSSISHUTDOWNALARM TR(INDENT "Apagado Rssi", INDENT "Check Rssi al apagar")
+#define TR_MODEL_STILL_POWERED "Modelo aun encendido"
+#define TR_MODEL_SHUTDOWN "Apagar ?"
+#define TR_PRESS_ENTER_TO_CONFIRM "Enter para confirmar"
+#define TR_THROTTLE_LABEL "Potencia"
+#define TR_THROTTLEREVERSE TR("Invert acel", INDENT "Invertir acel.")
+#define TR_MINUTEBEEP TR("Minuto", "Cada minuto")
+#define TR_BEEPCOUNTDOWN TR(INDENT"Cta. atrás", INDENT"Cuenta atrás")
+#define TR_PERSISTENT TR(INDENT"Persisten.", INDENT"Persistente")
+#define TR_BACKLIGHT_LABEL "Luz fondo"
+#define TR_BLDELAY INDENT"Duración"
+#define TR_BLONBRIGHTNESS INDENT"MAS brillo"
+#define TR_BLOFFBRIGHTNESS INDENT"MENOS brillo"
+#define TR_KEYS_BACKLIGHT "Keys backlight"
#define TR_BLCOLOR INDENT "Color"
-#define TR_SPLASHSCREEN "Ptalla.inicio"
-#define TR_PWR_ON_DELAY "Pwr On delay"
-#define TR_PWR_OFF_DELAY "Pwr Off delay"
-#define TR_THROTTLEWARNING TR("Aviso-A", INDENT "Aviso Acelerador")
-#define TR_SWITCHWARNING TR("Aviso-I", INDENT "Aviso Intrptor")
+#define TR_SPLASHSCREEN "Pantalla inicio"
+#define TR_PWR_ON_DELAY TR("Atraso On", "Atraso encendido")
+#define TR_PWR_OFF_DELAY TR("Atraso Off", "Atraso apagado")
+#define TR_THROTTLEWARNING TR("Aviso-A", INDENT "Aviso acelerador")
+#define TR_SWITCHWARNING TR("Aviso-I", INDENT "Aviso interruptor")
#define TR_POTWARNINGSTATE TR(INDENT "Pot&Slid.", INDENT "Pots & sliders")
-#define TR_SLIDERWARNING TR(INDENT "Slid. pos.", INDENT "Slider positions")
-#define TR_POTWARNING TR("Pot Warn.", INDENT "Pot Warning")
-#define TR_TIMEZONE TR("Zona Hora", "GPS Zona Hora")
-#define TR_ADJUST_RTC TR("Adjust RTC", INDENT "Adjust RTC")
+#define TR_SLIDERWARNING TR(INDENT "Pos. slid.", INDENT "Posiciones slider")
+#define TR_POTWARNING TR("Aviso pot", INDENT "Aviso pot")
+#define TR_TIMEZONE TR("Zona horaria", INDENT "Zona horaria")
+#define TR_ADJUST_RTC TR("Ajustar RTC", INDENT "Ajustar RTC")
#define TR_GPS "GPS"
#define TR_RXCHANNELORD TR("Rx Orden canal", "Orden habitual canales")
#define TR_STICKS "Sticks"
#define TR_POTS "Pots"
#define TR_SWITCHES "Switches"
-#define TR_SWITCHES_DELAY "Switches Delay"
+#define TR_SWITCHES_DELAY TR("Atraso switch.", "Atraso switches")
#define TR_SLAVE "Esclavo"
#define TR_MODESRC "Modo\006% Fuente"
#define TR_MULTIPLIER "Multiplicar"
@@ -565,22 +548,22 @@
#define TR_VTRIM "Trim- +"
#define TR_BG "BG:"
#if defined(PCBHORUS)
- #define TR_MENUTOSTART "Press [Enter] to start"
- #define TR_SETMIDPOINT "Center sticks/pots/sliders and press [Enter]"
- #define TR_MOVESTICKSPOTS "Move sticks, pots and sliders and press [Enter]"
+ #define TR_MENUTOSTART "Presiona [Enter] para empezar"
+ #define TR_SETMIDPOINT "Centra sticks/pots/sliders y presiona [Enter]"
+ #define TR_MOVESTICKSPOTS "Mueve sticks, pots and sliders y presiona [Enter]"
#else
#define TR_MENUTOSTART CENTER "\010" TR_ENTER " EMPEZAR"
#define TR_SETMIDPOINT TR(CENTER "\007STICKS AL CENTRO",CENTER "\010STICKS AL CENTRO")
#define TR_MOVESTICKSPOTS CENTER "\006MOVER STICKS/POTS"
#endif
-#define TR_RXBATT "Rx Batt:"
+#define TR_RXBATT "Rx Bat.:"
#define TR_TXnRX "Tx:\0Rx:"
#define OFS_RX 4
#define TR_ACCEL "Acc:"
#define TR_NODATA CENTER "SIN DATOS"
#define TR_US "us"
-#define TR_TMIXMAXMS "Tmix max"
-#define TR_FREE_STACK "Free stack"
+#define TR_TMIXMAXMS "Tmix máx"
+#define TR_FREE_STACK "Stack libre"
#define TR_MENUTORESET TR_ENTER "Resetear"
#define TR_PPM_TRAINER "TR"
#define TR_CH "CH"
@@ -589,35 +572,35 @@
#define TR_MIX "MIX"
#define TR_EEPROMLOWMEM "EEPROM mem.baja"
#define TR_ALERT "\016ALERTA"
-#define TR_PRESSANYKEYTOSKIP "Pulsar tecla omitir"
+#define TR_PRESSANYKEYTOSKIP "Pulsar tecla para omitir"
#define TR_THROTTLENOTIDLE "Aceler. Activado"
#define TR_ALARMSDISABLED "Alarmas Desact."
-#define TR_PRESSANYKEY TR("\010Pulsa una Tecla", "Pulsa una Tecla")
-#define TR_BADEEPROMDATA "Datos EEprom mal"
-#define TR_BAD_RADIO_DATA "Bad Radio Data"
+#define TR_PRESSANYKEY TR("\010Pulsa una tecla", "Pulsa una tecla")
+#define TR_BADEEPROMDATA "Error datos EEPROM"
+#define TR_BAD_RADIO_DATA "Error datos radio"
#define TR_EEPROMFORMATTING "Formateo EEPROM"
-#define TR_STORAGE_FORMAT "Storage Preparation"
+#define TR_STORAGE_FORMAT "Preparación alamacenamiento"
#define TR_EEPROMOVERFLOW "Desborde EEPROM"
-#define TR_MENURADIOSETUP "CONFIGURACION"
+#define TR_MENURADIOSETUP "CONFIGURACIÓN"
#define TR_MENUDATEANDTIME "FECHA Y HORA"
-#define TR_MENUTRAINER "APRENDIZ"
-#define TR_MENUSPECIALFUNCS "GLOBAL FUNCTIONS"
-#define TR_MENUVERSION "VERSION"
-#define TR_MENU_RADIO_SWITCHES TR("INTERUPTS", "TEST INTERUP.")
-#define TR_MENU_RADIO_ANALOGS TR("ANAS", "ENTRADAS ANALOG")
-#define TR_MENUCALIBRATION "CALIBRACION"
+#define TR_MENUTRAINER "ENTRENADOR"
+#define TR_MENUSPECIALFUNCS "FUNCIONES GLOBALES"
+#define TR_MENUVERSION "VERSIÓN"
+#define TR_MENU_RADIO_SWITCHES TR("INTERUPTS", "TEST INTERRUPTORES")
+#define TR_MENU_RADIO_ANALOGS TR("ANALÓGICOS", "TEST ANALÓGICOS")
+#define TR_MENUCALIBRATION "CALIBRACIÓN"
#if defined(COLORLCD)
#define TR_TRIMS2OFFSETS "Trims => Offsets"
#else
#define TR_TRIMS2OFFSETS "\006Trims => Offsets"
#endif
-#define TR_CHANNELS2FAILSAFE "Channels=>Failsafe"
-#define TR_CHANNEL2FAILSAFE "Channel=>Failsafe"
-#define TR_MENUMODELSEL TR("MODELSEL", "SELECCION MODELO")
-#define TR_MENUSETUP TR("CONF.", "CONF.MODELO")
-#define TR_MENUFLIGHTMODE "MODO VUELO"
-#define TR_MENUFLIGHTMODES "MODOS VUELO"
-#define TR_MENUHELISETUP "CONF. HELI"
+#define TR_CHANNELS2FAILSAFE "Canales=>Failsafe"
+#define TR_CHANNEL2FAILSAFE "Canal=>Failsafe"
+#define TR_MENUMODELSEL TR("MODELOS", "SELECCIÓN MODELO")
+#define TR_MENUSETUP TR("CONFIG. MODELO", "CONFIGURACIÓN MODELO")
+#define TR_MENUFLIGHTMODE "MODO DE VUELO"
+#define TR_MENUFLIGHTMODES "MODOS DE VUELO"
+#define TR_MENUHELISETUP "CONFIGURACIÓN HELI"
// Alignment
@@ -627,149 +610,152 @@
#define TR_MENULIMITS "SERVOS"
#else
#define TR_MENUINPUTS "DR/EXPO"
- #define TR_MENULIMITS "LIMITES"
+ #define TR_MENULIMITS "LÍMITES"
#endif
#define TR_MENUCURVES "CURVAS"
#define TR_MENUCURVE "CURVA"
-#define TR_MENULOGICALSWITCH "AJTE.INTERUP."
-#define TR_MENULOGICALSWITCHES "AJTE.INTERUPTS."
-#define TR_MENUCUSTOMFUNC "AJTE. FUNCIONES"
+#define TR_MENULOGICALSWITCH "INTERRUP.LÓGICO"
+#define TR_MENULOGICALSWITCHES TR3("INTERRUP. LÓGICOS", "INTERRUP. LÓGICOS", "INTERRUPTORES LÓGICOS")
+#define TR_MENUCUSTOMFUNC TR("FUNCIONES", "FUNCIONES ESPECIALES")
#define TR_MENUCUSTOMSCRIPTS "CUSTOM SCRIPTS"
-#define TR_MENUTELEMETRY "TELEMETRIA"
+#define TR_MENUTELEMETRY "TELEMETRÍA"
#define TR_MENUTEMPLATES "PLANTILLAS"
-#define TR_MENUSTAT "STATS"
+#define TR_MENUSTAT TR("ESTAD.", "ESTADÍSTICAS")
#define TR_MENUDEBUG "DEBUG"
-#define TR_MONITOR_CHANNELS1 "CHANNELS MONITOR 1/8"
-#define TR_MONITOR_CHANNELS2 "CHANNELS MONITOR 9/16"
-#define TR_MONITOR_SWITCHES "LOGICAL SWITCHES MONITOR"
-#define TR_MONITOR_CHANNELS3 "CHANNELS MONITOR 17/24"
-#define TR_MONITOR_CHANNELS4 "CHANNELS MONITOR 25/32"
-#define TR_MONITOR_OUTPUT_DESC "Outputs"
-#define TR_MONITOR_MIXER_DESC "Mixers"
-#define TR_RECEIVER_NUM TR("RxNum", "Receptor No.")
-#define TR_RECEIVER "Receiver"
-#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
-#define TR_MULTI_TELEMETRY "Telemetry"
-#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
-#define TR_RFPOWER "RF Power"
-#define TR_MULTI_FIXEDID TR("FixedID", "Fixed ID")
-#define TR_MULTI_OPTION TR("Option", "Option value")
-#define TR_MULTI_AUTOBIND TR(INDENT "Bind Ch.",INDENT "Bind on channel")
-#define TR_DISABLE_CH_MAP TR("No Ch. map", "Disable Ch. map")
-#define TR_DISABLE_TELEM TR("No Telem", "Disable Telemetry")
-#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetect", INDENT "Autodetect format")
-#define TR_MULTI_LOWPOWER TR(INDENT "Low power", INDENT "Low power mode")
+#define TR_MONITOR_CHANNELS1 "MONITOR CANALES 1/8"
+#define TR_MONITOR_CHANNELS2 "MONITOR CANALES 9/16"
+#define TR_MONITOR_SWITCHES "MONITOR INTERRP LÓGICOS"
+#define TR_MONITOR_CHANNELS3 "MONITOR CANALES 17/24"
+#define TR_MONITOR_CHANNELS4 "MONITOR CANALES 25/32"
+#define TR_MONITOR_OUTPUT_DESC "SALIDAS"
+#define TR_MONITOR_MIXER_DESC "Mixers"
+#define TR_RECEIVER_NUM TR("Num Rx", "Receptor No.")
+#define TR_RECEIVER "Receptor"
+#define TR_MULTI_RFTUNE TR("Sint.freq.", "RF Freq. sint.fina")
+#define TR_MULTI_RFPOWER "RF power"
+#define TR_MULTI_TELEMETRY "Telemetría"
+#define TR_MULTI_VIDFREQ TR("Freq.vídeo", "Frecuencia vídeo")
+#define TR_RFPOWER "RF Power"
+#define TR_MULTI_FIXEDID TR("ID Fijo", "ID Fijo")
+#define TR_MULTI_OPTION TR("Opción", "Valor opción")
+#define TR_MULTI_AUTOBIND TR(INDENT "Emp Cnl",INDENT "Emparejar en canal")
+#define TR_DISABLE_CH_MAP TR("No ch map", "Desactivar mapa cnl")
+#define TR_DISABLE_TELEM TR("No telem", "Desactivar telem.")
+#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetect", INDENT "Autodetectar formato")
+#define TR_MULTI_LOWPOWER TR(INDENT "Baja poten.", INDENT "Modo de baja poten.")
+#define TR_MULTI_LNA_DISABLE INDENT "LNA desact."
#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "S.Port link")
-#define TR_MODULE_TELEM_ON TR("ON", "Enabled")
-#define TR_DISABLE_INTERNAL TR("Disable int. RF", "Disable internal RF")
-#define TR_MODULE_NO_SERIAL_MODE TR("!serial mode", "Not in serial mode")
-#define TR_MODULE_NO_INPUT TR("No input", "No serial input")
-#define TR_MODULE_NO_TELEMETRY TR3( "No telmetry", "No MULTI_TELEMETRY", "No telemetry (enable MULTI_TELEMETRY)")
-#define TR_MODULE_WAITFORBIND "Bind to load protocol"
-#define TR_MODULE_BINDING "Binding"
-#define TR_MODULE_UPGRADE_ALERT TR3("Upg. needed", "Module upgrade required", "Module\nUpgrade required")
-#define TR_MODULE_UPGRADE TR("Upg. needed", "Module update recommended")
-#define TR_REBIND "Rebinding required"
-#define TR_REG_OK "Registration ok"
-#define TR_BIND_OK "Bind successful"
-#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
-#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
-#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
-#define TR_BINDING_CH9_16_TELEM_OFF "Ch9-16 Telem OFF"
-#define TR_PROTOCOL_INVALID TR("Prot. invalid", "Protocol invalid")
-#define TR_MODULE_STATUS TR(INDENT "Status", INDENT "Module Status")
-#define TR_MODULE_SYNC TR(INDENT "Sync", INDENT "Proto Sync Status")
-#define TR_MULTI_SERVOFREQ TR("Servo rate", "Servo update rate")
-#define TR_MULTI_MAX_THROW TR("Max. Throw", "Enable max. throw")
-#define TR_MULTI_RFCHAN TR("RF Channel", "Select RF channel")
-#define TR_SYNCMENU "Sync " TR_ENTER
-#define TR_LIMIT INDENT"Limite"
-#define TR_MINRSSI "Min Rssi"
-#define TR_LATITUDE "Latitud"
-#define TR_LONGITUDE "Longitud"
-#define TR_GPSCOORD TR("GPS Coords", "GPS formato coordenadas")
-#define TR_VARIO TR("Vario", "Variometro")
-#define TR_PITCH_AT_ZERO INDENT "Pitch at Zero"
-#define TR_PITCH_AT_MAX INDENT "Pitch at Max"
-#define TR_REPEAT_AT_ZERO INDENT "Repeat at Zero"
-#define TR_SHUTDOWN "APAGANDO"
-#define TR_SAVEMODEL "Saving model settings"
-#define TR_BATT_CALIB "Calib.bateria"
-#define TR_CURRENT_CALIB "Calib. actual"
-#define TR_VOLTAGE INDENT"Voltaje"
-#define TR_CURRENT INDENT"Actual"
-#define TR_SELECT_MODEL "Selec Modelo"
-#define TR_CREATE_CATEGORY "Create Category"
-#define TR_RENAME_CATEGORY "Rename Category"
-#define TR_DELETE_CATEGORY "Delete Category"
-#define TR_CREATE_MODEL "Crear Modelo"
-#define TR_DUPLICATE_MODEL "Duplicate Model"
-#define TR_COPY_MODEL "Copiar Modelo"
-#define TR_MOVE_MODEL "Mover Modelo"
-#define TR_BACKUP_MODEL "Copia Sgdad Mod."
-#define TR_DELETE_MODEL "Borrar Modelo"
-#define TR_RESTORE_MODEL "Restaurar Modelo"
-#define TR_DELETE_ERROR "Delete error"
-#define TR_CAT_NOT_EMPTY "Category is not empty"
-#define TR_SDCARD_ERROR "SDCARD Error"
-#define TR_NO_SDCARD "No SDCARD"
-#define TR_WAITING_FOR_RX "Waiting for RX..."
-#define TR_WAITING_FOR_TX "Waiting for TX..."
-#define TR_NO_TOOLS "No tools available"
+#define TR_MODULE_TELEM_ON TR("ON", "Activado")
+#define TR_DISABLE_INTERNAL TR("Desac.RF int", "Desact. mód. int. RF")
+#define TR_MODULE_NO_SERIAL_MODE TR("No modo serie", "No en modo serie")
+#define TR_MODULE_NO_INPUT "Sin señal"
+#define TR_MODULE_NO_TELEMETRY TR3( "No telemetría", "No MULTI_TELEMETRY", "No telemetría (activa MULTI_TELEMETRY)")
+#define TR_MODULE_WAITFORBIND "Emparejar con protocolo"
+#define TR_MODULE_BINDING "Emparejando"
+#define TR_MODULE_UPGRADE_ALERT TR3("Actualizar", "Actualizar módulo", "Actualizar\nmódulo")
+#define TR_MODULE_UPGRADE TR("Act recom", "Actualizar módulo recomendado")
+#define TR_REBIND "Reemparejar "
+#define TR_REG_OK "Registro ok"
+#define TR_BIND_OK "Emparejado ok"
+#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
+#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
+#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
+#define TR_BINDING_CH9_16_TELEM_OFF "Ch9-16 Telem OFF"
+#define TR_PROTOCOL_INVALID TR("Prot. inválido", "Protocolo inválido")
+#define TR_MODULE_STATUS TR(INDENT "Estado", INDENT "Estado módulo")
+#define TR_MODULE_SYNC TR(INDENT "Sync", INDENT "Estado proto sync")
+#define TR_MULTI_SERVOFREQ TR("V ref serv", "Vel. refr. servo")
+#define TR_MULTI_MAX_THROW TR("Máx. Throw", "Activar máx. throw")
+#define TR_MULTI_RFCHAN TR("Canal RF", "Selecciona canal RF")
+#define TR_SYNCMENU "Sync " TR_ENTER
+#define TR_LIMIT INDENT"Límite"
+#define TR_MINRSSI "Min Rssi"
+#define TR_LATITUDE "Latitud"
+#define TR_LONGITUDE "Longitud"
+#define TR_GPSCOORD TR("Coords GPS", INDENT "Formato coordenadas")
+#define TR_VARIO TR("Vario", "Variómetro")
+#define TR_PITCH_AT_ZERO INDENT "Pitch en cero"
+#define TR_PITCH_AT_MAX INDENT "Pitch en máx"
+#define TR_REPEAT_AT_ZERO TR(INDENT "Repet. en cero", INDENT "Repetir en cero")
+#define TR_SHUTDOWN "APAGANDO"
+#define TR_SAVEMODEL "Grabando modelo"
+#define TR_BATT_CALIB TR("Calib.bat.", "Calibración batería")
+#define TR_CURRENT_CALIB "Calib. actual"
+#define TR_VOLTAGE INDENT"Voltaje"
+#define TR_CURRENT INDENT"Actual"
+#define TR_SELECT_MODEL TR("Selec. modelo", "Seleccionar modelo")
+#define TR_SELECT_MODE "Select mode"
+#define TR_CREATE_CATEGORY "Crear categoría"
+#define TR_RENAME_CATEGORY "Renombrar categoría"
+#define TR_DELETE_CATEGORY "Borrar categoría"
+#define TR_CREATE_MODEL "Crear modelo"
+#define TR_DUPLICATE_MODEL "Duplicar modelo"
+#define TR_COPY_MODEL "Copiar modelo"
+#define TR_MOVE_MODEL "Mover modelo"
+#define TR_BACKUP_MODEL TR("Copia sgdad. mod.", "Copia seguridad modelo")
+#define TR_DELETE_MODEL "Borrar modelo"
+#define TR_RESTORE_MODEL "Restaurar modelo"
+#define TR_DELETE_ERROR "Error de borrado"
+#define TR_CAT_NOT_EMPTY "Categoría no esta vacía"
+#define TR_SDCARD_ERROR "Error SDCARD"
+#define TR_NO_SDCARD "No SDCARD"
+#define TR_WAITING_FOR_RX "Esperando a RX..."
+#define TR_WAITING_FOR_TX "Esperando a TX..."
+#define TR_NO_TOOLS "No hay utils"
#define TR_NORMAL "Normal"
-#define TR_NOT_INVERTED "Not inv"
-#define TR_NOT_CONNECTED "!Connected"
-#define TR_CONNECTED "Connected"
+#define TR_NOT_INVERTED "No inv"
+#define TR_NOT_CONNECTED "!Conectado"
+#define TR_CONNECTED "Conectado"
#define TR_FLEX_915 "Flex 915MHz"
#define TR_FLEX_868 "Flex 868MHz"
-#define TR_16CH_WITHOUT_TELEMETRY TR("16CH without telem.", "16CH without telemetry")
-#define TR_16CH_WITH_TELEMETRY TR("16CH with telem.", "16CH with telemetry")
-#define TR_8CH_WITH_TELEMETRY TR("8CH with telem.", "8CH with telemetry")
-#define TR_EXT_ANTENNA "Ext. antenna"
+#define TR_16CH_WITHOUT_TELEMETRY TR("16CH sin telem.", "16CH sin telemetría")
+#define TR_16CH_WITH_TELEMETRY TR("16CH con telem.", "16CH con telemetría")
+#define TR_8CH_WITH_TELEMETRY TR("8CH con telem.", "8CH con telemetría")
+#define TR_EXT_ANTENNA "Antena ext."
#define TR_PIN "Pin"
-#define TR_UPDATE_RX_OPTIONS "Update RX options?"
-#define TR_UPDATE_TX_OPTIONS "Update TX options?"
-#define TR_MODULES_RX_VERSION "Modules / RX version"
-#define TR_MENU_MODULES_RX_VERSION "MODULES / RX VERSION"
-#define TR_MENU_FIRM_OPTIONS "FIRMWARE OPTIONS"
+#define TR_UPDATE_RX_OPTIONS "Actualizar opciones RX?"
+#define TR_UPDATE_TX_OPTIONS "Actualizar opciones TX?"
+#define TR_MODULES_RX_VERSION "Módulos / versión RX"
+#define TR_MENU_MODULES_RX_VERSION "MÓDULOS / VERSIÓN RX"
+#define TR_MENU_FIRM_OPTIONS "OPCIONES FIRMWARE"
#define TR_GYRO "Gyro"
#define TR_STICKS_POTS_SLIDERS "Sticks/Pots/Sliders"
#define TR_PWM_STICKS_POTS_SLIDERS "PWM Sticks/Pots/Sliders"
-#define TR_RF_PROTOCOL "RF Protocol"
-#define TR_MODULE_OPTIONS "Module options"
-#define TR_POWER "Power"
-#define TR_NO_TX_OPTIONS "No TX options"
-#define TR_RTC_BATT "RTC Batt"
-#define TR_POWER_METER_EXT "Power Meter (EXT)"
-#define TR_POWER_METER_INT "Power Meter (INT)"
-#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
-#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
-#define TR_SDCARD_FULL "SD Card Full"
-#define TR_NEEDS_FILE "NEEDS FILE"
+#define TR_RF_PROTOCOL "Protocolo RF"
+#define TR_MODULE_OPTIONS "Opciones módulo"
+#define TR_POWER "Potencia"
+#define TR_NO_TX_OPTIONS "Sin opciones TX"
+#define TR_RTC_BATT TR("Bat. RTC", "Batería RTC")
+#define TR_POWER_METER_EXT "Medidor potencia(EXT)"
+#define TR_POWER_METER_INT "Medidor potencia(INT)"
+#define TR_SPECTRUM_ANALYSER_EXT "Espectro (EXT)"
+#define TR_SPECTRUM_ANALYSER_INT "Espectro (INT)"
+#define TR_SDCARD_FULL "SD Card llena"
+#define TR_NEEDS_FILE "NECESITA ARCHIVO"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Incompatible"
#define TR_WARNING "AVISO"
#define TR_EEPROMWARN "EEPROM"
-#define TR_STORAGE_WARNING "STORAGE"
-#define TR_EEPROM_CONVERTING "EEPROM Converting"
-#define TR_THROTTLEWARN "ACELERADOR"
+#define TR_STORAGE_WARNING "ALMAC."
+#define TR_EEPROM_CONVERTING "Convirtiendo EEPROM"
+#define TR_THROTTLEWARN TR("ACELERAD.", "ACELERADOR")
#define TR_ALARMSWARN "ALARMAS"
-#define TR_SWITCHWARN "INTERPTOR"
+#define TR_SWITCHWARN TR("INTERRUP.", "INTERRUPTOR")
#define TR_FAILSAFEWARN "FAILSAFE"
-#define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD")
-#define TR_NIGHTLY_NOTSAFE "Version not safe to fly"
-#define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ")
-#define TR_WARN_RTC_BATTERY_LOW "RTC Battery low"
-#define TR_WARN_MULTI_LOWPOWER "Low power mode"
-#define TR_BATTERY "BATTERY"
-#define TR_WRONG_PCBREV "Wrong PCB detected"
-#define TR_EMERGENCY_MODE "EMERGENCY MODE"
-#define TR_PCBREV_ERROR "PCB error"
-#define TR_NO_FAILSAFE "Failsafe not set"
-#define TR_KEYSTUCK "Key stuck"
-#define TR_INVERT_THR TR("Invertir Acel?", "Invertir Acel.?")
+#define TR_TEST_WARNING TR("TESTING", "TEST BUILD")
+#define TR_TEST_NOTSAFE "Usar solo para test"
+#define TR_WRONG_SDCARDVERSION TR("Ver esperada: ", "Versión esperada: ")
+#define TR_WARN_RTC_BATTERY_LOW "Batería RTC baja"
+#define TR_WARN_MULTI_LOWPOWER "Modo baja potencia"
+#define TR_BATTERY "BATERÍA"
+#define TR_WRONG_PCBREV "Placa PCB errónea"
+#define TR_EMERGENCY_MODE "MODO EMERGENCIA"
+#define TR_PCBREV_ERROR "Error PCB"
+#define TR_NO_FAILSAFE "Failsafe no fijado"
+#define TR_KEYSTUCK "Tecla atascada"
+#define TR_INVERT_THR TR("Invertir acel?", "Invertir acel.?")
#define TR_SPEAKER_VOLUME INDENT "Volumen"
#define TR_LCD "LCD"
#define TR_BRIGHTNESS INDENT "Brillo"
@@ -778,52 +764,52 @@
#define TR_CPU_MAH "Consumo"
#define TR_COPROC "CoProc."
#define TR_COPROC_TEMP "MB Temp. \016>"
-#define TR_CAPAWARNING INDENT "Capacidad Baja"
+#define TR_CAPAWARNING INDENT "Capacidad baja"
#define TR_TEMPWARNING INDENT "Sobrecalent"
-#define TR_FUNC "Func"
+#define TR_FUNC "Función"
#define TR_V1 "V1"
#define TR_V2 "V2"
-#define TR_DURATION "Duracion"
+#define TR_DURATION "Duración"
#define TR_DELAY "Atraso"
#define TR_SD_CARD "SD CARD"
#define TR_SDHC_CARD "SD-HC CARD"
#define TR_NO_SOUNDS_ON_SD "Sin sonidos en SD"
-#define TR_NO_MODELS_ON_SD "Sin Modelos en SD"
-#define TR_NO_BITMAPS_ON_SD "Sin imagenes en SD"
-#define TR_NO_SCRIPTS_ON_SD "No Scripts on SD"
+#define TR_NO_MODELS_ON_SD "Sin modelos en SD"
+#define TR_NO_BITMAPS_ON_SD "Sin imágenes en SD"
+#define TR_NO_SCRIPTS_ON_SD "No scripts en SD"
#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error"
#define TR_SCRIPT_PANIC "Script panic"
#define TR_SCRIPT_KILLED "Script killed"
-#define TR_SCRIPT_ERROR "Unknown error"
+#define TR_SCRIPT_ERROR "Error desconocido"
#define TR_PLAY_FILE "Play"
#define TR_DELETE_FILE "Borrar"
#define TR_COPY_FILE "Copiar"
#define TR_RENAME_FILE "Renombrar"
-#define TR_ASSIGN_BITMAP "Asignar Imagen"
-#define TR_ASSIGN_SPLASH "Splash screen"
-#define TR_EXECUTE_FILE "Execute"
+#define TR_ASSIGN_BITMAP "Asignar imagen"
+#define TR_ASSIGN_SPLASH "Pant. bienvenida"
+#define TR_EXECUTE_FILE "Ejecutar"
#define TR_REMOVED "Borrado"
-#define TR_SD_INFO "Informacion"
+#define TR_SD_INFO "Información"
#define TR_SD_FORMAT "Formatear"
#define TR_NA "N/A"
#define TR_HARDWARE "COMPONENTES"
#define TR_FORMATTING "Formateando.."
#define TR_TEMP_CALIB "Temp. Calib"
#define TR_TIME "Hora"
-#define TR_MAXBAUDRATE "Max bauds"
+#define TR_MAXBAUDRATE "Máx bauds"
#define TR_BLUETOOTH "Bluetooth"
-#define TR_BLUETOOTH_DISC "Discover"
+#define TR_BLUETOOTH_DISC "Buscar"
#define TR_BLUETOOTH_INIT "Init"
-#define TR_BLUETOOTH_DIST_ADDR "Dist addr"
-#define TR_BLUETOOTH_LOCAL_ADDR "Local addr"
-#define TR_BLUETOOTH_PIN_CODE "PIN code"
-#define TR_BAUDRATE "BT Baudrate"
-#define LEN_BLUETOOTH_MODES "\011"
+#define TR_BLUETOOTH_DIST_ADDR "Dir. remota"
+#define TR_BLUETOOTH_LOCAL_ADDR "Dir. local"
+#define TR_BLUETOOTH_PIN_CODE "Código PIN"
+#define TR_BAUDRATE "Velocidad BT"
+#define LEN_BLUETOOTH_MODES "\012"
#if defined(PCBX9E)
-#define TR_BLUETOOTH_MODES "---\0 ""Enabled\0 "
+#define TR_BLUETOOTH_MODES "---\0 ""Activo\0 "
#else
-#define TR_BLUETOOTH_MODES "---\0 ""Telemetry""Trainer\0"
+#define TR_BLUETOOTH_MODES "---\0 ""Telemetría""Entrenador"
#endif
#define TR_SD_INFO_TITLE "SD INFO"
#define TR_SD_TYPE "Tipo:"
@@ -831,222 +817,255 @@
#define TR_SD_SECTORS "Sectores:"
#define TR_SD_SIZE "Tamaño:"
#define TR_TYPE INDENT "Tipo"
-#define TR_GLOBAL_VARS "Global Variables"
-#define TR_GVARS "GLOBAL V."
-#define TR_GLOBAL_VAR "Global Variable"
-#define TR_MENUGLOBALVARS "GLOBAL VARIABLES"
-#define TR_OWN "Propio"
-#define TR_DATE "Fecha"
-#define TR_MONTHS { "Jan", "Fev", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }
-#define TR_ROTARY_ENCODER "R.E."
-#define TR_CHANNELS_MONITOR "MONITOR CANALES"
-#define TR_MIXERS_MONITOR "MIXERS MONITOR"
-#define TR_PATH_TOO_LONG "Path too long"
-#define TR_VIEW_TEXT "View text"
-#define TR_FLASH_BOOTLOADER "Flash bootloader"
-#define TR_FLASH_EXTERNAL_DEVICE "Flash External Device"
-#define TR_FLASH_RECEIVER_OTA "Flash receiver OTA"
-#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module")
-#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit"
-#define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ")
-#define TR_FLASH_INTERNAL_MODULE "Flash Internal Module"
-#define TR_FLASH_INTERNAL_MULTI TR("Flash Int. Multi", "Flash Internal Multi")
-#define TR_FLASH_EXTERNAL_MODULE "Flash external module"
-#define TR_FLASH_EXTERNAL_MULTI TR("Flash Ext. Multi", "Flash External Multi")
-#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
-#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
-#define TR_WRITING "Writing..."
-#define TR_CONFIRM_FORMAT "Confirm Format?"
-#define TR_INTERNALRF "Interna RF"
-#define TR_INTERNAL_MODULE TR("Int. module","Internal module")
-#define TR_EXTERNAL_MODULE TR("Ext. module","External module")
-#define TR_OPENTX_UPGRADE_REQUIRED "OpenTX upgrade required"
-#define TR_TELEMETRY_DISABLED "Telem. disabled"
-#define TR_MORE_OPTIONS_AVAILABLE "More options available"
-#define TR_NO_MODULE_INFORMATION "No module information"
-#define TR_EXTERNALRF "Externa RF"
-#define TR_FAILSAFE INDENT"Modo sgdad."
-#define TR_FAILSAFESET "AJUSTES SGDAD."
+#define TR_GLOBAL_VARS "Variables globales"
+#define TR_GVARS "V. GLOBAL"
+#define TR_GLOBAL_VAR "Variable global"
+#define TR_MENUGLOBALVARS "VARIABLES GLOBALES"
+#define TR_OWN "Propio"
+#define TR_DATE "Fecha"
+#define TR_MONTHS { "Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic" }
+#define TR_ROTARY_ENCODER "R.E."
+#define TR_CHANNELS_MONITOR "MONITOR CANALES"
+#define TR_MIXERS_MONITOR "MONITOR MEZCLAS"
+#define TR_PATH_TOO_LONG "Path muy largo"
+#define TR_VIEW_TEXT "Ver texto"
+#define TR_FLASH_BOOTLOADER "Flash bootloader"
+#define TR_FLASH_EXTERNAL_DEVICE "Flash disp. externo"
+#define TR_FLASH_RECEIVER_OTA "Flash RX OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX por ext. OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX por int. OTA"
+#define TR_FLASH_BLUETOOTH_MODULE TR("Flash módulo BT", "Flash módulo bluetooth")
+#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash unid. pwr mngt"
+#define TR_CURRENT_VERSION TR("Vers. actual", "Versión actual: ")
+#define TR_FLASH_INTERNAL_MODULE TR("Flash módulo int", "Flash módulo interno")
+#define TR_FLASH_INTERNAL_MULTI TR("Flash Multi int", "Flash Multi interno")
+#define TR_FLASH_EXTERNAL_MODULE TR("Flash módulo ext", "Flash módulo externo")
+#define TR_FLASH_EXTERNAL_MULTI TR("Flash Multi ext", "Flash Multi externo")
+#define TR_FIRMWARE_UPDATE_ERROR TR("Error act FW", "Error actualiz. firmware")
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash ok"
+#define TR_WRITING "Escribiendo..."
+#define TR_CONFIRM_FORMAT "Confirmar formato?"
+#define TR_INTERNALRF "RF interna"
+#define TR_INTERNAL_MODULE TR("Módulo int", "Módulo interno")
+#define TR_EXTERNAL_MODULE TR("Módulo ext", "Módulo externo")
+#define TR_OPENTX_UPGRADE_REQUIRED "Actualiz. OpenTX requerida"
+#define TR_TELEMETRY_DISABLED "Telem. inactiva"
+#define TR_MORE_OPTIONS_AVAILABLE "Más opciones disp."
+#define TR_NO_MODULE_INFORMATION "Sin información módulo"
+#define TR_EXTERNALRF "RF externa"
+#define TR_FAILSAFE INDENT"Failsafe"
+#define TR_FAILSAFESET "AJUSTES FAILSAFE"
#define TR_REG_ID "Reg. ID"
-#define TR_OWNER_ID "Owner ID"
+#define TR_OWNER_ID "Pers. ID"
#define TR_PINMAPSET "PINMAP"
-#define TR_HOLD "Hold"
+#define TR_HOLD "Hold"
#define TR_HOLD_UPPERCASE "HOLD"
-#define TR_NONE "None"
-#define TR_NONE_UPPERCASE "NONE"
-#define TR_MENUSENSOR "SENSOR"
-#define TR_POWERMETER_PEAK "Peak"
-#define TR_POWERMETER_POWER "Power"
+#define TR_NONE "Nada"
+#define TR_NONE_UPPERCASE "NADA"
+#define TR_MENUSENSOR "SENSOR"
+#define TR_POWERMETER_PEAK "Pico"
+#define TR_POWERMETER_POWER "Potencia"
#define TR_POWERMETER_ATTN "Attn"
-#define TR_POWERMETER_FREQ "Freq."
-#define TR_MENUTOOLS "TOOLS"
-#define TR_TURN_OFF_RECEIVER "Turn off receiver"
-#define TR_STOPPING "Stopping..."
-#define TR_MENU_SPECTRUM_ANALYSER "SPECTRUM ANALYSER"
-#define TR_MENU_POWER_METER "POWER METER"
-#define TR_SENSOR "SENSOR"
-#define TR_COUNTRYCODE "Codigo Pais"
-#define TR_USBMODE "USB Mode"
-#define TR_JACKMODE "Jack Mode"
-#define TR_VOICELANG "Idioma voces"
-#define TR_UNITSSYSTEM "Unidades"
-#define TR_EDIT "Editar"
-#define TR_INSERT_BEFORE "Insertar antes"
-#define TR_INSERT_AFTER "Insertar despues"
-#define TR_COPY "Copiar"
+#define TR_POWERMETER_FREQ "Frec."
+#define TR_MENUTOOLS "UTILS"
+#define TR_TURN_OFF_RECEIVER "Apaga el receptor"
+#define TR_STOPPING "Parando..."
+#define TR_MENU_SPECTRUM_ANALYSER "ANALIZADOR DE ESPECTRO"
+#define TR_MENU_POWER_METER "MEDIDOR POTENCIA"
+#define TR_SENSOR "SENSOR"
+#define TR_COUNTRYCODE "Código país"
+#define TR_USBMODE "Modo USB"
+#define TR_JACKMODE "Modo Jack"
+#define TR_VOICELANG "Idioma voces"
+#define TR_UNITSSYSTEM "Unidades"
+#define TR_EDIT "Editar"
+#define TR_INSERT_BEFORE "Insertar antes"
+#define TR_INSERT_AFTER "Insertar después"
+#define TR_COPY "Copiar"
#define TR_MOVE "Mover"
#define TR_PASTE "Pegar"
#define TR_DELETE "Borrar"
#define TR_INSERT "Insertar"
#define TR_RESET_FLIGHT "Reset Vuelo"
-#define TR_RESET_TIMER1 "Reset Reloj1"
-#define TR_RESET_TIMER2 "Reset Reloj2"
-#define TR_RESET_TIMER3 "Reset Reloj3"
-#define TR_RESET_TELEMETRY "Reset Telemetria"
-#define TR_STATISTICS "Estadisticas"
+#define TR_RESET_TIMER1 "Reset Reloj 1"
+#define TR_RESET_TIMER2 "Reset Reloj 2"
+#define TR_RESET_TIMER3 "Reset Reloj 3"
+#define TR_RESET_TELEMETRY "Reset Telemetría"
+#define TR_STATISTICS "Estadísticas"
#define TR_ABOUT_US "Nosotros"
-#define TR_USB_JOYSTICK "USB Joystick (HID)"
-#define TR_USB_MASS_STORAGE "USB Storage (SD)"
-#define TR_USB_SERIAL "USB Serial (Debug)"
-#define TR_SETUP_SCREENS "Setup screens"
-#define TR_MONITOR_SCREENS "Monitors"
-#define TR_AND_SWITCH "AND Inter."
+#define TR_USB_JOYSTICK "Joystick USB (HID)"
+#define TR_USB_MASS_STORAGE "Almaz. USB (SD)"
+#define TR_USB_SERIAL "Serie USB (Debug)"
+#define TR_SETUP_SCREENS "Pantallas config"
+#define TR_MONITOR_SCREENS "Monitores"
+#define TR_AND_SWITCH TR("Inter. AND", "Interruptor AND")
#define TR_SF "CF"
#define TR_GF "GF"
#define TR_SPEAKER INDENT"Altavoz"
#define TR_BUZZER INDENT"Zumbador"
#define TR_BYTES "bytes"
-#define TR_MODULE_BIND "[Enlace]"
-#define TR_POWERMETER_ATTN_NEEDED "Attenuator needed"
-#define TR_PXX2_SELECT_RX "Select RX..."
-#define TR_PXX2_DEFAULT ""
-#define TR_BT_SELECT_DEVICE "Select device..."
-#define TR_DISCOVER "Discover"
+#define TR_MODULE_BIND "[Enl.]"
+#define TR_POWERMETER_ATTN_NEEDED "Necesita atenuador"
+#define TR_PXX2_SELECT_RX "Selecciona RX..."
+#define TR_PXX2_DEFAULT ""
+#define TR_BT_SELECT_DEVICE "Selecciona dispositivo"
+#define TR_DISCOVER "Buscar"
#define TR_BUTTON_INIT BUTTON("Init")
-#define TR_WAITING "Waiting..."
-#define TR_RECEIVER_DELETE "Delete receiver?"
-#define TR_RECEIVER_RESET "Reset receiver?"
-#define TR_SHARE "Share"
-#define TR_BIND "Bind"
-#define TR_REGISTER TR("Reg", "Register")
-#define TR_MODULE_RANGE "[Limites]"
-#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
-#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
+#define TR_WAITING "Espera..."
+#define TR_RECEIVER_DELETE "Borrar receptor?"
+#define TR_RECEIVER_RESET "Reset receptor?"
+#define TR_SHARE "Compartido"
+#define TR_BIND "Emparejar"
+#define TR_REGISTER TR("Reg", "Registrar")
+#define TR_MODULE_RANGE "[Lim.]"
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "OPCIONES RECEPTOR")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Borrar"))
#define TR_RESET_BTN "[Reset]"
#define TR_DEBUG "Debug"
#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
-#define TR_CALIBRATION "Calibration"
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
+#define TR_CALIBRATION "Calibración"
#define TR_SET "[Ajuste]"
-#define TR_TRAINER "Aprendiz"
+#define TR_TRAINER "Entrenador"
#define TR_CHANS "Chans"
-#define TR_ANTENNAPROBLEM CENTER "¡Problema antena TX!"
+#define TR_ANTENNAPROBLEM CENTER "Problema antena TX!"
#define TR_MODELIDUSED TR("ID en uso", "ID modelo en uso")
-#define TR_MODULE "Modulo"
-#define TR_RX_NAME "Rx Name"
-#define TR_TELEMETRY_TYPE TR("Type", "Telemetry Type")
-#define TR_TELEMETRY_SENSORS "Sensors"
-#define TR_VALUE "Value"
-#define TR_TOPLCDTIMER "Top LCD Timer"
-#define TR_UNIT "Unit"
-#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
-#define TR_CHANNELRANGE INDENT "Gama de canales"
-#define TR_ANTENNACONFIRM1 "EXT. ANTENNA"
+#define TR_MODULE "Módulo"
+#define TR_RX_NAME "Nombre Rx"
+#define TR_TELEMETRY_TYPE TR("Tipo", "Tipo telemetría")
+#define TR_TELEMETRY_SENSORS "Sensores"
+#define TR_VALUE "Valor"
+#define TR_TOPLCDTIMER "Timer LCD superior"
+#define TR_UNIT "Unidad"
+#define TR_TELEMETRY_NEWSENSOR INDENT "Añadir sensor..."
+#define TR_CHANNELRANGE INDENT "Canales"
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source")
+#define TR_ANTENNACONFIRM1 "ANTENA EXT."
#if defined(PCBX12S)
-#define LEN_ANTENNA_MODES "\023"
-#define TR_ANTENNA_MODES "Internal\0 ""Ask\0 ""Per model\0 ""Internal + External"
+#define LEN_ANTENNA_MODES "\020"
+#define TR_ANTENNA_MODES "Interna\0 ""Preguntar\0 ""Por modelo\0 ""Interno + Externo\0"
#else
-#define LEN_ANTENNA_MODES "\011"
-#define TR_ANTENNA_MODES "Internal\0""Ask\0 ""Per model""External"
+#define LEN_ANTENNA_MODES "\012"
+#define TR_ANTENNA_MODES "Interna\0 ""Preguntar\0""Por modelo""Externa\0 "
#endif
-#define TR_USE_INTERNAL_ANTENNA TR("Use int. antenna", "Use internal antenna")
-#define TR_USE_EXTERNAL_ANTENNA TR("Use ext. antenna", "Use external antenna")
-#define TR_ANTENNACONFIRM2 TR("Check antenna", "Make sure antenna is installed!")
-#define TR_MODULE_PROTOCOL_FLEX_WARN_LINE1 "Requires non"
-#define TR_MODULE_PROTOCOL_FCC_WARN_LINE1 "Requires FCC"
-#define TR_MODULE_PROTOCOL_EU_WARN_LINE1 "Requires EU"
-#define TR_MODULE_PROTOCOL_WARN_LINE2 "certified firmware"
+#define TR_USE_INTERNAL_ANTENNA TR("Usa antena int.", "Usa antena interna")
+#define TR_USE_EXTERNAL_ANTENNA TR("Use antena ext.", "Usa antena externa")
+#define TR_ANTENNACONFIRM2 TR("Revisa antena", "Revisa que la antena esté instalada!")
+
+#define TR_MODULE_PROTOCOL_FLEX_WARN_LINE1 "No requerido"
+#define TR_MODULE_PROTOCOL_FCC_WARN_LINE1 "Requiere FCC"
+#define TR_MODULE_PROTOCOL_EU_WARN_LINE1 "Requiere EU"
+#define TR_MODULE_PROTOCOL_WARN_LINE2 "firmware certificado"
#define TR_LOWALARM INDENT "Alarma baja"
-#define TR_CRITICALALARM INDENT "Alarma Critica"
-#define TR_RSSIALARM_WARN TR("RSSI","TELEMETRY RSSI")
-#define TR_NO_RSSIALARM TR(INDENT "Alarms disabled", INDENT "Telemetry alarms disabled")
-#define TR_DISABLE_ALARM TR(INDENT "Disable alarms", INDENT "Disable telemetry alarms")
-#define TR_ENABLE_POPUP "Enable Popup"
-#define TR_DISABLE_POPUP "Disable Popup"
+#define TR_CRITICALALARM INDENT "Alarma crítica"
+#define TR_RSSIALARM_WARN TR("RSSI", "TELEMETRY RSSI")
+#define TR_NO_RSSIALARM TR(INDENT "Alarmas desact.", INDENT "Alarmas telemetría desact.")
+#define TR_DISABLE_ALARM TR(INDENT "Desact. alarmas", INDENT "Desact. alarmas telem.")
+#define TR_ENABLE_POPUP "Activa Popup"
+#define TR_DISABLE_POPUP "Desactiva Popup"
#define TR_POPUP "Popup"
#define TR_MIN "Min"
-#define TR_MAX "Max"
+#define TR_MAX "Máx"
#define TR_CURVE_PRESET "Preset..."
#define TR_PRESET "Preset"
#define TR_MIRROR "Mirror"
-#define TR_CLEAR "Clear"
+#define TR_CLEAR "Borrar"
#define TR_RESET "Reset"
#define TR_RESET_SUBMENU "Reset..."
-#define TR_COUNT "Count"
+#define TR_COUNT "Puntos"
#define TR_PT "pt"
#define TR_PTS "pts"
-#define TR_SMOOTH "Smooth"
-#define TR_COPY_STICKS_TO_OFS TR("Cpy stick->subtrim", "Copy Sticks To Offset")
-#define TR_COPY_TRIMS_TO_OFS TR("Cpy trim->subtrim", "Copy trims to subtrim")
+#define TR_SMOOTH TR3("Suaviz.", "Suaviz.", "Suavizado")
+#define TR_COPY_STICKS_TO_OFS TR("Copia stick->subtr", "Copia Sticks a Offset")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Copia min/máx a sal", "Copia min/máx/ctr a salidas")
+#define TR_COPY_TRIMS_TO_OFS TR("Copia trim->subtr", "Copia trims a subtrim")
#define TR_INCDEC "Inc/Decrement"
-#define TR_GLOBALVAR "Global Var"
-#define TR_MIXSOURCE "Mixer Source"
-#define TR_CONSTANT "Constant"
+#define TR_GLOBALVAR "Var global"
+#define TR_MIXSOURCE "Entrada mixer"
+#define TR_CONSTANT "Constante"
#define TR_PERSISTENT_MAH INDENT "Valor mAh"
-#define TR_PREFLIGHT "Preflight Checks"
-#define TR_CHECKLIST INDENT "Display Checklist"
+#define TR_PREFLIGHT "Chequeos prevuelo"
+#define TR_CHECKLIST TR(INDENT "Lista verif", INDENT "Lista verificación")
#define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset")
-#define TR_AUX_SERIAL_MODE "Serial port"
+#define TR_AUX_SERIAL_MODE "Puerto serie"
+#define TR_AUX2_SERIAL_MODE "Puerto serie 2"
#define TR_SCRIPT "Script"
-#define TR_INPUTS "Inputs"
-#define TR_OUTPUTS "Outputs"
-#define STR_EEBACKUP "Backup the EEPROM"
-#define STR_FACTORYRESET "Factory reset"
-#define TR_CONFIRMRESET "Erase ALL models and settings?"
-#define TR_TOO_MANY_LUA_SCRIPTS "Too many Lua scripts!"
-
+#define TR_INPUTS "Entradas"
+#define TR_OUTPUTS "Salidas"
+#define STR_EEBACKUP "Copia seg. EEPROM"
+#define STR_FACTORYRESET "Rest. fabrica"
+#define TR_CONFIRMRESET "Borrar TODOS los " LCDW_128_480_LINEBREAK "modelos y conf?"
+#define TR_TOO_MANY_LUA_SCRIPTS "Demasiados Lua scripts!"
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS TR("No hay pant. telemetría", "No hay pantallas de telemetría")
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Nombre"
#define TR_PHASES_HEADERS_SW "Interrup"
-#define TR_PHASES_HEADERS_RUD_TRIM "Rudder Trim"
-#define TR_PHASES_HEADERS_ELE_TRIM "Elevator Trim"
-#define TR_PHASES_HEADERS_THT_TRIM "Throttle Trim"
-#define TR_PHASES_HEADERS_AIL_TRIM "Aileron Trim"
+#define TR_PHASES_HEADERS_RUD_TRIM "Trim timon"
+#define TR_PHASES_HEADERS_ELE_TRIM "Trim elevador"
+#define TR_PHASES_HEADERS_THT_TRIM "Trim potencia"
+#define TR_PHASES_HEADERS_AIL_TRIM "Trim alerón"
#define TR_PHASES_HEADERS_CH5_TRIM "Trim 5"
#define TR_PHASES_HEADERS_CH6_TRIM "Trim 6"
#define TR_PHASES_HEADERS_FAD_IN "Aparecer"
#define TR_PHASES_HEADERS_FAD_OUT "Desparecer"
#define TR_LIMITS_HEADERS_NAME "Nombre"
-#define TR_LIMITS_HEADERS_SUBTRIM "Compensacion"
+#define TR_LIMITS_HEADERS_SUBTRIM "Compensación"
#define TR_LIMITS_HEADERS_MIN "Min"
-#define TR_LIMITS_HEADERS_MAX "Max"
-#define TR_LIMITS_HEADERS_DIRECTION "Direccion"
-#define TR_LIMITS_HEADERS_CURVE "Curve"
+#define TR_LIMITS_HEADERS_MAX "Máx"
+#define TR_LIMITS_HEADERS_DIRECTION "Dirección"
+#define TR_LIMITS_HEADERS_CURVE "Curva"
#define TR_LIMITS_HEADERS_PPMCENTER "Centrado PPM"
-#define TR_LIMITS_HEADERS_SUBTRIMMODE "Simetrica"
+#define TR_LIMITS_HEADERS_SUBTRIMMODE "Simétrica"
-#define TR_LSW_HEADERS_FUNCTION "Funcion"
+#define TR_LSW_HEADERS_FUNCTION "Función"
#define TR_LSW_HEADERS_V1 "V1"
#define TR_LSW_HEADERS_V2 "V2"
-#define TR_LSW_HEADERS_ANDSW "AND Interrup."
-#define TR_LSW_HEADERS_DURATION "Duracion"
+#define TR_LSW_HEADERS_ANDSW "Interrup. AND"
+#define TR_LSW_HEADERS_DURATION "Duración"
#define TR_LSW_HEADERS_DELAY "Retardo"
-#define TR_GVAR_HEADERS_NAME "Name"
-#define TR_GVAR_HEADERS_FM0 "Value on FM0"
-#define TR_GVAR_HEADERS_FM1 "Value on FM1"
-#define TR_GVAR_HEADERS_FM2 "Value on FM2"
-#define TR_GVAR_HEADERS_FM3 "Value on FM3"
-#define TR_GVAR_HEADERS_FM4 "Value on FM4"
-#define TR_GVAR_HEADERS_FM5 "Value on FM5"
-#define TR_GVAR_HEADERS_FM6 "Value on FM6"
-#define TR_GVAR_HEADERS_FM7 "Value on FM7"
-#define TR_GVAR_HEADERS_FM8 "Value on FM8"
+#define TR_GVAR_HEADERS_NAME "Nombre"
+#define TR_GVAR_HEADERS_FM0 "Valor en FM0"
+#define TR_GVAR_HEADERS_FM1 "Valor en FM1"
+#define TR_GVAR_HEADERS_FM2 "Valor en FM2"
+#define TR_GVAR_HEADERS_FM3 "Valor en FM3"
+#define TR_GVAR_HEADERS_FM4 "Valor en FM4"
+#define TR_GVAR_HEADERS_FM5 "Valor en FM5"
+#define TR_GVAR_HEADERS_FM6 "Valor en FM6"
+#define TR_GVAR_HEADERS_FM7 "Valor en FM7"
+#define TR_GVAR_HEADERS_FM8 "Valor en FM8"
// Horus footer descriptions
-#define TR_LSW_DESCRIPTIONS { "Comparison type or function", "First variable", "Second variable or constant", "Second variable or constant", "Additional condition for line to be enabled", "Minimum ON duration of the logical switch", "Minimum TRUE duration for the switch to become ON" }
+#define TR_LSW_DESCRIPTIONS { "Tipo de comparación o función", "Primera variable", "Segunda variable o constante", "Segunda variable o constante", "Condición adicional para activar línea", "Duración mínima de switch lógico", "Duración mínima TRUE para activar switch lógico" }
+
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "Primer canal"
+#define TR_FILL_BACKGROUND "Rellenar fondo"
+#define TR_BG_COLOR "Color BG"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Modo de vuelo"
+#define TR_INVALID_FILE "Fichero no valido"
+#define TR_TIMER_SOURCE "Entrada timer"
+#define TR_SIZE "Tamaño"
+#define TR_SHADOW "Sombra"
+#define TR_TEXT "Texto"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Vista principal X"
+#define TR_PANEL1_BACKGROUND "Fondo panel1"
+#define TR_PANEL2_BACKGROUND "Fondo panel2"
// Taranis About screen
#define TR_ABOUTUS "Nosotros"
@@ -1054,7 +1073,7 @@
#define TR_ABOUT_OPENTX_1 "OpenTX es open source, no-"
#define TR_ABOUT_OPENTX_2 "comercial y viene sin "
#define TR_ABOUT_OPENTX_3 "garantias. Fue desarrollado"
-#define TR_ABOUT_OPENTX_4 "libremente. Ayudas a traves"
+#define TR_ABOUT_OPENTX_4 "libremente. Ayudas a través"
#define TR_ABOUT_OPENTX_5 "de donaciones son bienvenidas!"
#define TR_ABOUT_BERTRAND_1 "Bertrand Songis"
@@ -1062,7 +1081,7 @@
#define TR_ABOUT_BERTRAND_3 "Companion codesarrollador"
#define TR_ABOUT_MIKE_1 "Mike Blandford"
-#define TR_ABOUT_MIKE_2 "Guru de codigo y drivers"
+#define TR_ABOUT_MIKE_2 "Gurú de codigo y drivers"
#define TR_ABOUT_MIKE_3 "Seguramente uno de los"
#define TR_ABOUT_MIKE_4 "mejores inspiradores"
@@ -1072,23 +1091,23 @@
#define TR_ABOUT_ANDRE_1 "Andre Bernet"
#define TR_ABOUT_ANDRE_2 "Funcionalidad, usabilidad,"
-#define TR_ABOUT_ANDRE_3 "depurado, documentacion"
+#define TR_ABOUT_ANDRE_3 "depurado, documentación"
#define TR_ABOUT_ROB_1 "Rob Thomson"
#define TR_ABOUT_ROB_2 "openrcforums webmaster"
#define TR_ABOUT_KJELL_1 "Kjell Kernen"
#define TR_ABOUT_KJELL_2 "www.open-tx.org main author"
-#define TR_ABOUT_KJELL_3 "OpenTX Recorder author"
-#define TR_ABOUT_KJELL_4 "Companion contributor"
+#define TR_ABOUT_KJELL_3 "Autor OpenTX Recorder"
+#define TR_ABOUT_KJELL_4 "Colaborador Companion"
#define TR_ABOUT_MARTIN_1 "Martin Hotar"
-#define TR_ABOUT_MARTIN_2 "Dise\201o grafico"
+#define TR_ABOUT_MARTIN_2 "Dise\201o gráfico"
#if defined(PCBTARANIS)
#define TR_ABOUT_HARDWARE_1 "FrSky"
#define TR_ABOUT_HARDWARE_2 "Productor dise\201o de hardware"
- #define TR_ABOUT_HARDWARE_3 "Firmware contributor"
+ #define TR_ABOUT_HARDWARE_3 "Colaborador firmware"
#else
#define TR_ABOUT_HARDWARE_1 "Brent Nelson"
#define TR_ABOUT_HARDWARE_2 "Sky9x dise\201ador/productor"
@@ -1110,82 +1129,83 @@
#define TR_WAV_VOLUME "Volumen Wav"
#define TR_BG_VOLUME "Volumen Bg"
-#define TR_TOP_BAR "Top Bar"
-#define TR_FLASH_ERASE "Flash erase..."
-#define TR_FLASH_WRITE "Flash write..."
-#define TR_OTA_UPDATE "OTA update..."
-#define TR_MODULE_RESET "Module reset..."
-#define TR_UNKNOWN_RX "Unknown RX"
-#define TR_UNSUPPORTED_RX "Unsupported RX"
-#define TR_OTA_UPDATE_ERROR "OTA update error"
-#define TR_DEVICE_RESET "Device reset..."
-#define TR_ALTITUDE INDENT "Altitude"
-#define TR_SCALE "Scale"
-#define TR_VIEW_CHANNELS "View Channels"
-#define TR_VIEW_NOTES "View Notes"
-#define TR_MODEL_SELECT "Model Select"
-#define TR_MODS_FORBIDDEN "Modifications forbidden!"
-#define TR_UNLOCKED "Unlocked"
+#define TR_TOP_BAR "Panel superior"
+#define TR_FLASH_ERASE "Borrar flash..."
+#define TR_FLASH_WRITE "Escribir flash..."
+#define TR_OTA_UPDATE "Actualización OTA..."
+#define TR_MODULE_RESET "Reset módulo..."
+#define TR_UNKNOWN_RX "RX desconocido"
+#define TR_UNSUPPORTED_RX "RX no soportado"
+#define TR_OTA_UPDATE_ERROR "Error actualización OTA"
+#define TR_DEVICE_RESET "Reset dispositivo..."
+#define TR_ALTITUDE INDENT "Altitud"
+#define TR_SCALE "Escala"
+#define TR_VIEW_CHANNELS "Ver Canales"
+#define TR_VIEW_NOTES "Ver Notas"
+#define TR_MODEL_SELECT "Seleccionar modelo"
+#define TR_MODS_FORBIDDEN "Modificaciones prohibidas"
+#define TR_UNLOCKED "Desbloqueado"
#define TR_ID "ID"
-#define TR_PRECISION "Precision"
+#define TR_PRECISION "Precisión"
#define TR_RATIO "Ratio"
-#define TR_FORMULA "Formula"
+#define TR_FORMULA "Fórmula"
#define TR_CELLINDEX "Cell index"
#define TR_LOGS "Logs"
-#define TR_OPTIONS "Options"
-#define TR_FIRMWARE_OPTIONS "Firmware options"
+#define TR_OPTIONS "Opciones"
+#define TR_FIRMWARE_OPTIONS "Opciones firmware"
#define TR_ALTSENSOR "Alt sensor"
#define TR_CELLSENSOR "Cell sensor"
#define TR_GPSSENSOR "GPS sensor"
#define TR_CURRENTSENSOR "Sensor"
-#define TR_AUTOOFFSET "Auto Offset"
-#define TR_ONLYPOSITIVE "Positive"
-#define TR_FILTER "Filter"
-#define TR_TELEMETRYFULL TR("All slots full!", "All telemetry slots full!")
+#define TR_AUTOOFFSET "Auto offset"
+#define TR_ONLYPOSITIVE "Positivo"
+#define TR_FILTER "Filtro"
+#define TR_TELEMETRYFULL TR("Telem. llena!", "Todas las entradas de telemetría llenas!")
#define TR_SERVOS_OK "Servos OK"
#define TR_SERVOS_KO "Servos KO"
-#define TR_INVERTED_SERIAL INDENT "Invert"
-#define TR_IGNORE_INSTANCE INDENT "Ignore instance"
-#define TR_DISCOVER_SENSORS "Discover new sensors"
-#define TR_STOP_DISCOVER_SENSORS "Stop discovery"
-#define TR_DELETE_ALL_SENSORS "Delete all sensors"
-#define TR_CONFIRMDELETE "Really " LCDW_128_480_LINEBREAK "delete all ?"
-#define TR_SELECT_WIDGET "Select widget"
-#define TR_REMOVE_WIDGET "Remove widget"
-#define TR_WIDGET_SETTINGS "Widget settings"
-#define TR_REMOVE_SCREEN "Remove screen"
-#define TR_SETUP_WIDGETS "Setup widgets"
-#define TR_USER_INTERFACE "User interface"
-#define TR_THEME "Theme"
-#define TR_SETUP "Setup"
-#define TR_MAINVIEWX "Main view X"
-#define TR_LAYOUT "Layout"
-#define TR_ADDMAINVIEW "Add main view"
-#define TR_BACKGROUND_COLOR "Background color"
-#define TR_MAIN_COLOR "Main color"
-#define TR_TEXT_VIEWER "Text Viewer"
+#define TR_INVERTED_SERIAL INDENT "Invertir"
+#define TR_IGNORE_INSTANCE TR(INDENT "No inst.", INDENT "Ignora instancias")
+#define TR_DISCOVER_SENSORS "Buscar sensores"
+#define TR_STOP_DISCOVER_SENSORS "Parar busqueda"
+#define TR_DELETE_ALL_SENSORS "Borrar sensores"
+#define TR_CONFIRMDELETE "Seguro " LCDW_128_480_LINEBREAK "borrar todo ?"
+#define TR_SELECT_WIDGET "Seleccionar widget"
+#define TR_REMOVE_WIDGET "Borrar widget"
+#define TR_WIDGET_SETTINGS "Config. widget"
+#define TR_REMOVE_SCREEN "Borrar pantalla"
+#define TR_SETUP_WIDGETS "Config. widgets"
+#define TR_USER_INTERFACE "Interfaz"
+#define TR_THEME "Tema"
+#define TR_SETUP "Configuración"
+#define TR_MAINVIEWX "Vista pral. X"
+#define TR_LAYOUT "Diseño"
+#define TR_ADDMAINVIEW "Añadir vista pral."
+#define TR_BACKGROUND_COLOR "Color de fondo"
+#define TR_MAIN_COLOR "Color principal"
+#define TR_TEXT_VIEWER "Visor de texto"
-#define TR_MENU_INPUTS "\314Inputs"
+#define TR_MENU_INPUTS "\314Entradas"
#define TR_MENU_LUA "\322Lua scripts"
#define TR_MENU_STICKS "\307Sticks"
#define TR_MENU_POTS "\310Pots"
#define TR_MENU_MAX "\315MAX"
-#define TR_MENU_HELI "\316Cyclic"
+#define TR_MENU_HELI "\316Cíclico"
#define TR_MENU_TRIMS "\313Trims"
-#define TR_MENU_SWITCHES "\312Switches"
-#define TR_MENU_LOGICAL_SWITCHES "\312Logical Switches"
-#define TR_MENU_TRAINER "\317Trainer"
-#define TR_MENU_CHANNELS "\320Channels"
+#define TR_MENU_SWITCHES "\312Interruptores"
+#define TR_MENU_LOGICAL_SWITCHES TR("\312Interr. lógicos", "\312Interruptores lógicos")
+#define TR_MENU_TRAINER "\317Entrenador"
+#define TR_MENU_CHANNELS "\320Canales"
#define TR_MENU_GVARS "\311GVars"
-#define TR_MENU_TELEMETRY "\321Telemetry"
-#define TR_MENU_DISPLAY "DISPLAY"
-#define TR_MENU_OTHER "Other"
-#define TR_MENU_INVERT "Invert"
-#define TR_JITTER_FILTER "ADC Filter"
-#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage")
-#define TR_AUTH_FAILURE "Auth-failure"
+#define TR_MENU_TELEMETRY "\321Telemetría"
+#define TR_MENU_DISPLAY "MONITOR"
+#define TR_MENU_OTHER "Otros"
+#define TR_MENU_INVERT "Invertir"
+#define TR_JITTER_FILTER "Filtro ADC"
+#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltaje")
+#define TR_AUTH_FAILURE "Fallo " LCDW_128_480_LINEBREAK "autentificación"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1224,6 +1244,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1272,7 +1293,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1287,3 +1308,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
\ No newline at end of file
diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt
index c378cb47c..90ce833cb 100644
--- a/radio/src/translations/fi.h.txt
+++ b/radio/src/translations/fi.h.txt
@@ -165,6 +165,9 @@
#define LEN_VCSWFUNC "\005"
#define TR_VCSWFUNC "---\0 " TR_CSWEQUAL "a~x\0 ""a>x\0 ""ax""|a|b\0 ""a"
-#define TR_BT_SELECT_DEVICE "Select device..."
+#define TR_BT_SELECT_DEVICE "Select device"
#define TR_DISCOVER "Discover"
#define TR_BUTTON_INIT BUTTON("Init")
#define TR_WAITING "Waiting..."
@@ -930,6 +940,8 @@
#define TR_DEBUG "Debug"
#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
#define TR_CALIBRATION "Calibration"
#define TR_SET "[Set]"
#define TR_TRAINER "Trainer"
@@ -945,6 +957,11 @@
#define TR_UNIT "Unit"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE INDENT "Channel Range"
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source")
#define TR_ANTENNACONFIRM1 "EXT. ANTENNA"
#if defined(PCBX12S)
#define LEN_ANTENNA_MODES "\023"
@@ -981,6 +998,7 @@
#define TR_PTS "pts"
#define TR_SMOOTH "Smooth"
#define TR_COPY_STICKS_TO_OFS TR("Cpy stick->subtrim", "Copy Sticks To Offset")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Cpy min/max to all", "Copy min/max/center to all outputs")
#define TR_COPY_TRIMS_TO_OFS TR("Cpy trim->subtrim", "Copy trims to subtrim")
#define TR_INCDEC "Inc/Decrement"
#define TR_GLOBALVAR "Global Var"
@@ -990,7 +1008,8 @@
#define TR_PREFLIGHT "Preflight Checks"
#define TR_CHECKLIST INDENT "Display Checklist"
#define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset")
-#define TR_AUX_SERIAL_MODE "Serial port"
+#define TR_AUX_SERIAL_MODE "Serial port"
+#define TR_AUX2_SERIAL_MODE "Serial port 2"
#define TR_SCRIPT "Script"
#define TR_INPUTS "Inputs"
#define TR_OUTPUTS "Outputs"
@@ -998,7 +1017,11 @@
#define STR_FACTORYRESET "Factory reset"
#define TR_CONFIRMRESET "Erase ALL models and settings?"
#define TR_TOO_MANY_LUA_SCRIPTS "Too many Lua scripts!"
-
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Name"
@@ -1042,6 +1065,23 @@
// Horus footer descriptions
#define TR_LSW_DESCRIPTIONS { "Comparison type or function", "First variable", "Second variable or constant", "Second variable or constant", "Additional condition for line to be enabled", "Minimum ON duration of the logical switch", "Minimum TRUE duration for the switch to become ON" }
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "First channel"
+#define TR_FILL_BACKGROUND "Fill background?"
+#define TR_BG_COLOR "BG Color"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Flight mode"
+#define TR_INVALID_FILE "Invalid File"
+#define TR_TIMER_SOURCE "Timer source"
+#define TR_SIZE "Size"
+#define TR_SHADOW "Shadow"
+#define TR_TEXT "Text"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Main view X"
+#define TR_PANEL1_BACKGROUND "Panel1 background"
+#define TR_PANEL2_BACKGROUND "Panel2 background"
+
// About screen
#define TR_ABOUTUS TR(" ABOUT ", "ABOUT")
@@ -1174,6 +1214,7 @@
#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage")
#define TR_AUTH_FAILURE "Auth-failure"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1212,6 +1253,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1260,7 +1302,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1274,3 +1316,45 @@
#define ZSTR_GASSUIT_MAX_FLOW "GMFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
\ No newline at end of file
diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt
index acf1f155f..d4a1f5f29 100644
--- a/radio/src/translations/fr.h.txt
+++ b/radio/src/translations/fr.h.txt
@@ -165,6 +165,9 @@
#define LEN_VCSWFUNC "\005"
#define TR_VCSWFUNC "---\0 " TR_CSWEQUAL "a~x\0 ""a>x\0 ""ax""|a|b\0 ""a"
-#define TR_BT_SELECT_DEVICE "Sélect appareil..."
+#define TR_BT_SELECT_DEVICE "Sélect appareil"
#define TR_DISCOVER "Découvrir"
#define TR_BUTTON_INIT BUTTON("Init")
#define TR_WAITING "Attente..."
@@ -932,6 +942,8 @@
#define TR_DEBUG "Debug"
#define TR_KEYS_BTN BUTTON(TR("Btns","Inters"))
#define TR_ANALOGS_BTN BUTTON(TR("Anas", "Analogs"))
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
#define TR_CALIBRATION "Calibration"
#define TR_SET BUTTON("Déf")
#define TR_TRAINER "Ecolage"
@@ -947,6 +959,11 @@
#define TR_UNIT "Unité"
#define TR_TELEMETRY_NEWSENSOR TR(INDENT"Nouveau capteur...", INDENT "Ajout d'un nouveau capteur...")
#define TR_CHANNELRANGE TR(INDENT "Canaux", INDENT "Plage de canaux")
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source")
#define TR_ANTENNACONFIRM1 "Vraiment changer?"
#if defined(PCBX12S)
#define LEN_ANTENNA_MODES "\021"
@@ -983,6 +1000,7 @@
#define TR_PTS "pts"
#define TR_SMOOTH "Lissage"
#define TR_COPY_STICKS_TO_OFS TR("Cpy stick->subtrim", "Manche vers subtrim")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Cpy min/max to all", "Copy min/max/center to all outputs")
#define TR_COPY_TRIMS_TO_OFS TR("Cpy trim->subtrim", "Trim vers subtrim")
#define TR_INCDEC "Inc/décrementer"
#define TR_GLOBALVAR "Var. globale"
@@ -993,6 +1011,7 @@
#define TR_CHECKLIST TR(INDENT "Notes", INDENT "Afficher notes")
#define TR_FAS_OFFSET TR(INDENT "Corr FAS", INDENT "Correction FAS")
#define TR_AUX_SERIAL_MODE "Port série"
+#define TR_AUX2_SERIAL_MODE "Port série 2"
#define TR_SCRIPT "Script"
#define TR_INPUTS "Entrées"
#define TR_OUTPUTS "Sorties"
@@ -1008,6 +1027,11 @@
#endif
#define TR_CONFIRMRESET TR("Effacer TOUT?","Effacer TOUS modèles/réglages?")
#define TR_TOO_MANY_LUA_SCRIPTS "Trop de scripts lua!"
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Nom"
@@ -1051,6 +1075,23 @@
// Horus footer descriptions
#define TR_LSW_DESCRIPTIONS { "Type de comparaison ou fonction", "Première variable", "Seconde variable ou constante", "Seconde variable ou constante", "Condition supplémentaire pour activer la ligne", "Durée minimale d'activation de l'inter logique", "Durée min de la condition avant l'activation de l'inter" }
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "First channel"
+#define TR_FILL_BACKGROUND "Fill background?"
+#define TR_BG_COLOR "BG Color"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Flight mode"
+#define TR_INVALID_FILE "Invalid File"
+#define TR_TIMER_SOURCE "Timer source"
+#define TR_SIZE "Size"
+#define TR_SHADOW "Shadow"
+#define TR_TEXT "Text"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Main view X"
+#define TR_PANEL1_BACKGROUND "Panel1 background"
+#define TR_PANEL2_BACKGROUND "Panel2 background"
+
// Taranis About screen
#define TR_ABOUTUS TR(" A PROPOS ", "A PROPOS")
@@ -1189,6 +1230,7 @@
#define TR_RTC_CHECK TR("Vérif. RTC", "Vérif. pile RTC")
#define TR_AUTH_FAILURE "Auth-failure"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1227,6 +1269,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1275,7 +1318,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1290,3 +1333,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
\ No newline at end of file
diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt
index f2852ba7b..034bcd7db 100644
--- a/radio/src/translations/it.h.txt
+++ b/radio/src/translations/it.h.txt
@@ -166,6 +166,9 @@
#define LEN_VCSWFUNC "\005"
#define TR_VCSWFUNC "---\0 " TR_CSWEQUAL "a~x\0 ""a>x\0 ""ax""|a|b\0 ""asubtrim", INDENT "Copia Sticks su Subtrim")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Cpy min/max to all", "Copy min/max/center to all outputs")
#define TR_COPY_TRIMS_TO_OFS TR(INDENT "Cp. trim->subtrim", INDENT "Copia Trims su Subtrim")
#define TR_INCDEC "Inc/Decrementa"
#define TR_GLOBALVAR "Var Globale"
@@ -992,7 +1010,8 @@
#define TR_PREFLIGHT "Controlli Prevolo"
#define TR_CHECKLIST INDENT "Mostra Checklist"
#define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset")
-#define TR_AUX_SERIAL_MODE "Porta Seriale"
+#define TR_AUX_SERIAL_MODE "Porta Seriale"
+#define TR_AUX2_SERIAL_MODE "Porta Seriale 2"
#define TR_SCRIPT "Script"
#define TR_INPUTS "Ingresso"
#define TR_OUTPUTS "Uscita"
@@ -1000,7 +1019,11 @@
#define STR_FACTORYRESET "Inizializza dati"
#define TR_CONFIRMRESET "Resettare TUTTI i dati?"
#define TR_TOO_MANY_LUA_SCRIPTS "Troppi Scripts Lua!"
-
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "Nessuno Schermo Telemetria"
+#define TR_TOUCH_PANEL "Schermo touch:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Nome"
@@ -1044,6 +1067,23 @@
// Horus footer descriptions
#define TR_LSW_DESCRIPTIONS { "Tipo o funzione di confronto", "Prima variabile", "Seconda variabile o costante", "Seconda variabile o costante", "Condizione aggiuntiva da abilitare linea", "Durata minima ON dell'interruttore logico", "Durata minima TRUE affinché l'interruttore si accenda" }
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "Primo canale"
+#define TR_FILL_BACKGROUND "Riempi lo sfondo?"
+#define TR_BG_COLOR "Colore sfondo"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Modo di volo"
+#define TR_INVALID_FILE "File invalido"
+#define TR_TIMER_SOURCE "Sorgente timer"
+#define TR_SIZE "Dimensione"
+#define TR_SHADOW "Ombra"
+#define TR_TEXT "Testo"
+#define TR_COLOR "Colore"
+#define TR_MAIN_VIEW_X "Vista principale X"
+#define TR_PANEL1_BACKGROUND "Sfondo Panello 1"
+#define TR_PANEL2_BACKGROUND "Sfondo Panello 2"
+
// About screen
#define TR_ABOUTUS TR(" INFO ", "INFO SU")
@@ -1183,6 +1223,7 @@
#define TR_RTC_CHECK TR("Controllo RTC", "Controllo voltaggio RTC")
#define TR_AUTH_FAILURE "Auth-failure"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1221,6 +1262,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1269,7 +1311,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1284,3 +1326,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt
index 2b68fe5df..64af03eea 100644
--- a/radio/src/translations/nl.h.txt
+++ b/radio/src/translations/nl.h.txt
@@ -377,6 +377,9 @@
#define LEN_GYROS "\004"
#define TR_GYROS "GyrX""GyrY"
+#define LEN_TEXT_SIZE "\010"
+#define TR_TEXT_SIZE "Standard""Tiny\0 ""Small\0 ""Mid\0 ""Double\0 "
+
// ZERO TERMINATED STRINGS
#if defined(COLORLCD)
#define INDENT " "
@@ -439,6 +442,7 @@
#define TR_PPMFRAME INDENT "PPM frame"
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
+#define TR_WARN_5VOLTS "Warning: output level is 5 volts"
#define TR_MS "ms"
#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH TR("Schak.", "Schakelaar")
@@ -522,6 +526,7 @@
#define TR_BLDELAY INDENT "Duur"
#define TR_BLONBRIGHTNESS INDENT "Aan-Helderheid"
#define TR_BLOFFBRIGHTNESS INDENT "Uit-Helderheid"
+#define TR_KEYS_BACKLIGHT "Keys backlight"
#define TR_BLCOLOR INDENT "Kleur"
#define TR_SPLASHSCREEN "Startscherm Aan"
#define TR_PWR_ON_DELAY "Pwr On delay"
@@ -632,6 +637,7 @@
#define TR_RECEIVER_NUM TR("RxNum", "Receiver Nr.")
#define TR_RECEIVER "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
+#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -642,6 +648,7 @@
#define TR_DISABLE_TELEM TR("No Telem", "Disable Telemetry")
#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetect", INDENT "Autodetect format")
#define TR_MULTI_LOWPOWER TR(INDENT "Low power", INDENT "Low power mode")
+#define TR_MULTI_LNA_DISABLE INDENT "LNA disable"
#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "S.Port link")
#define TR_MODULE_TELEM_ON TR("ON", "Enabled")
#define TR_DISABLE_INTERNAL TR("Disable int. RF", "Disable internal RF")
@@ -651,7 +658,7 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_MODULE_UPGRADE_ALERT TR3("Upg. needed", "Module upgrade required", "Module\nUpgrade required")
-#define TR_MODULE_UPGRADE TR("Upg. needed", "Module update recommended")
+#define TR_MODULE_UPGRADE TR("Upg. advised", "Module update recommended")
#define TR_REBIND "Rebinding required"
#define TR_REG_OK "Registration ok"
#define TR_BIND_OK "Bind successful"
@@ -682,6 +689,7 @@
#define TR_VOLTAGE TR(INDENT "Spg", INDENT "Spanningsbron") //9XR-Pro
#define TR_CURRENT TR(INDENT "Stroom", INDENT "Stroombron")
#define TR_SELECT_MODEL "Kies Model"
+#define TR_SELECT_MODE "Select mode"
#define TR_CREATE_CATEGORY "Create Category"
#define TR_RENAME_CATEGORY "Rename Category"
#define TR_DELETE_CATEGORY "Delete Category"
@@ -740,8 +748,8 @@
#define TR_ALARMSWARN "ALARM"
#define TR_SWITCHWARN "SCHAKELAAR"
#define TR_FAILSAFEWARN "FAILSAFE"
-#define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD")
-#define TR_NIGHTLY_NOTSAFE "Version not safe to fly"
+#define TR_TEST_WARNING TR("TESTING", "TEST BUILD")
+#define TR_TEST_NOTSAFE "Use for tests only"
#define TR_WRONG_SDCARDVERSION TR("Verwachte ver: ","Verwachte versie: ")
#define TR_WARN_RTC_BATTERY_LOW "RTC Battery low"
#define TR_WARN_MULTI_LOWPOWER "Low power mode"
@@ -828,6 +836,8 @@
#define TR_FLASH_BOOTLOADER "Flash bootloader"
#define TR_FLASH_EXTERNAL_DEVICE "Flash extern Apparaat"
#define TR_FLASH_RECEIVER_OTA "Flash receiver OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA"
#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module")
#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit"
#define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ")
@@ -837,9 +847,9 @@
#define TR_FLASH_EXTERNAL_MULTI TR("Flash Ext. Multi", "Flash External Multi")
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
-#define TR_WRITING "\032Schrijven..."
-#define TR_CONFIRM_FORMAT "Formatteren bevestigen?"
-#define TR_INTERNALRF "Interne RF"
+#define TR_WRITING "Schrijven..."
+#define TR_CONFIRM_FORMAT "Formatteren bevestigen?"
+#define TR_INTERNALRF "Interne RF"
#define TR_INTERNAL_MODULE TR("Int. module","Internal module")
#define TR_EXTERNAL_MODULE TR("Ext. module","External module")
#define TR_OPENTX_UPGRADE_REQUIRED "OpenTX upgrade required"
@@ -900,9 +910,9 @@
#define TR_BYTES "bytes"
#define TR_MODULE_BIND TR("[Bnd]", "[Bind]")
#define TR_POWERMETER_ATTN_NEEDED "Attenuator needed"
-#define TR_PXX2_SELECT_RX "Select RX..."
+#define TR_PXX2_SELECT_RX "Select RX"
#define TR_PXX2_DEFAULT ""
-#define TR_BT_SELECT_DEVICE "Select device..."
+#define TR_BT_SELECT_DEVICE "Select device"
#define TR_DISCOVER "Discover"
#define TR_BUTTON_INIT BUTTON("Init")
#define TR_WAITING "Waiting..."
@@ -918,6 +928,8 @@
#define TR_DEBUG "Debug"
#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
#define TR_CALIBRATION "Calibration"
#define TR_SET "[Set]"
#define TR_TRAINER "Trainer Poort"
@@ -933,6 +945,11 @@
#define TR_UNIT "Eenheid"
#define TR_TELEMETRY_NEWSENSOR INDENT "Sensor toevoegen ..."
#define TR_CHANNELRANGE TR(INDENT "Kanalen", INDENT "Uitgangs Kanalen") //wg 9XR-Pro
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source")
#define TR_ANTENNACONFIRM1 "Antennes wisselen?"
#if defined(PCBX12S)
#define LEN_ANTENNA_MODES "\023"
@@ -969,6 +986,7 @@
#define TR_PTS "Ptn"
#define TR_SMOOTH "Zacht"
#define TR_COPY_STICKS_TO_OFS TR("Cpy stick->subtrim", "Kopieer Sticks naar Subtrim")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Cpy min/max to all", "Copy min/max/center to all outputs")
#define TR_COPY_TRIMS_TO_OFS TR("Cpy trim->subtrim", "Kopieer Trim naar Subtrim")
#define TR_INCDEC "Inc/Decrement"
#define TR_GLOBALVAR "Globale Var"
@@ -978,7 +996,8 @@
#define TR_PREFLIGHT "Preflight Checks"
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "Toon Checklist")
#define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset")
-#define TR_AUX_SERIAL_MODE "Seriele poort"
+#define TR_AUX_SERIAL_MODE "Seriele poort"
+#define TR_AUX2_SERIAL_MODE "Seriele poort 2"
#define TR_SCRIPT "Script"
#define TR_INPUTS "Inputs"
#define TR_OUTPUTS "Outputs"
@@ -992,7 +1011,11 @@
#endif
#define TR_CONFIRMRESET TR("Wis Alles?", "Wis ALLE modellen en instellingen?")
#define TR_TOO_MANY_LUA_SCRIPTS "Te veel Lua scripts!"
-
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Name"
@@ -1036,6 +1059,23 @@
// Horus footer descriptions
#define TR_LSW_DESCRIPTIONS { "Vergelijking of Functie", "1e variabele", "2e variabele of constante", "2e variabele of constante", "Additionele conditie", "Minimale AAN duur van de logische schakelaar", "Minimale WAAR duur om AAN te gaan" }
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "First channel"
+#define TR_FILL_BACKGROUND "Fill background?"
+#define TR_BG_COLOR "BG Color"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Flight mode"
+#define TR_INVALID_FILE "Invalid File"
+#define TR_TIMER_SOURCE "Timer source"
+#define TR_SIZE "Size"
+#define TR_SHADOW "Shadow"
+#define TR_TEXT "Text"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Main view X"
+#define TR_PANEL1_BACKGROUND "Panel1 background"
+#define TR_PANEL2_BACKGROUND "Panel2 background"
+
// About screen
#define TR_ABOUTUS TR(" ABOUT ", "ABOUT")
@@ -1175,6 +1215,7 @@
#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage")
#define TR_AUTH_FAILURE "Auth-failure"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1213,6 +1254,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1261,7 +1303,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1276,3 +1318,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
\ No newline at end of file
diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt
index 0441b2418..5ba5bd258 100644
--- a/radio/src/translations/pl.h.txt
+++ b/radio/src/translations/pl.h.txt
@@ -396,6 +396,9 @@
#define LEN_GYROS "\004"
#define TR_GYROS "GyrX""GyrY"
+#define LEN_TEXT_SIZE "\010"
+#define TR_TEXT_SIZE "Standard""Tiny\0 ""Small\0 ""Mid\0 ""Double\0 "
+
// ZERO TERMINATED STRINGS
#if defined(COLORLCD)
#define INDENT "\007"
@@ -459,6 +462,7 @@
#define TR_PPMFRAME INDENT "Ramka PPM"
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
+#define TR_WARN_5VOLTS "Warning: output level is 5 volts"
#define TR_MS "ms"
#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Przełą"
@@ -540,6 +544,7 @@
#define TR_BLDELAY INDENT"Czas trwania"
#define TR_BLONBRIGHTNESS INDENT"Jasnośc wł."
#define TR_BLOFFBRIGHTNESS INDENT"Jasność wył."
+#define TR_KEYS_BACKLIGHT "Keys backlight"
#define TR_BLCOLOR INDENT "Color"
#define TR_SPLASHSCREEN "Logo ekranu"
#define TR_PWR_ON_DELAY "Pwr On delay"
@@ -645,6 +650,7 @@
#define TR_RECEIVER_NUM TR("Nr RX", "Nr odbiornika")
#define TR_RECEIVER INDENT "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
+#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -655,6 +661,7 @@
#define TR_DISABLE_TELEM TR("No Telem", "Disable Telemetry")
#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetect", INDENT "Autodetect format")
#define TR_MULTI_LOWPOWER TR(INDENT "Low power", INDENT "Low power mode")
+#define TR_MULTI_LNA_DISABLE INDENT "LNA disable"
#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "S.Port link")
#define TR_MODULE_TELEM_ON TR("ON", "Enabled")
#define TR_DISABLE_INTERNAL TR("Disable int. RF", "Disable internal RF")
@@ -664,7 +671,7 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_MODULE_UPGRADE_ALERT TR3("Upg. needed", "Module upgrade required", "Module\nUpgrade required")
-#define TR_MODULE_UPGRADE TR("Upg. needed", "Module update recommended")
+#define TR_MODULE_UPGRADE TR("Upg. advised", "Module update recommended")
#define TR_REBIND "Rebinding required"
#define TR_REG_OK "Registration ok"
#define TR_BIND_OK "Bind successful"
@@ -695,6 +702,7 @@
#define TR_VOLTAGE TR (INDENT"Napięcie",INDENT"Źródło Napięcia")
#define TR_CURRENT TR (INDENT"Prąd",INDENT"Źródło Prądu")
#define TR_SELECT_MODEL "Wybór modelu"
+#define TR_SELECT_MODE "Select mode"
#define TR_CREATE_CATEGORY "Create Category"
#define TR_RENAME_CATEGORY "Rename Category"
#define TR_DELETE_CATEGORY "Delete Category"
@@ -753,8 +761,8 @@
#define TR_ALARMSWARN "ALARM"
#define TR_SWITCHWARN TR("Przełą","Kontrola")
#define TR_FAILSAFEWARN "FAILSAFE"
-#define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD")
-#define TR_NIGHTLY_NOTSAFE "Version not safe to fly"
+#define TR_TEST_WARNING TR("TESTING", "TEST BUILD")
+#define TR_TEST_NOTSAFE "Use for tests only"
#define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ")
#define TR_WARN_RTC_BATTERY_LOW "RTC Battery low"
#define TR_WARN_MULTI_LOWPOWER "Low power mode"
@@ -841,6 +849,8 @@
#define TR_FLASH_BOOTLOADER "Flash bootloader"
#define TR_FLASH_EXTERNAL_DEVICE "Sflashuj Moduł Zewnętrzny"
#define TR_FLASH_RECEIVER_OTA "Flash receiver OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA"
#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module")
#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit"
#define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ")
@@ -850,9 +860,9 @@
#define TR_FLASH_EXTERNAL_MULTI TR("Flash Ext. Multi", "Flash External Multi")
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
-#define TR_WRITING "\032Zapis... "
-#define TR_CONFIRM_FORMAT "Zatwierdź Format?"
-#define TR_INTERNALRF "Wewn.Moduł RF"
+#define TR_WRITING "Zapis... "
+#define TR_CONFIRM_FORMAT "Zatwierdź Format?"
+#define TR_INTERNALRF "Wewn.Moduł RF"
#define TR_INTERNAL_MODULE TR("Int. module","Internal module")
#define TR_EXTERNAL_MODULE TR("Ext. module","External module")
#define TR_OPENTX_UPGRADE_REQUIRED "OpenTX upgrade required"
@@ -913,9 +923,9 @@
#define TR_BYTES "bajty"
#define TR_MODULE_BIND TR("[BND]","[Bind]")
#define TR_POWERMETER_ATTN_NEEDED "Attenuator needed"
-#define TR_PXX2_SELECT_RX "Select RX..."
+#define TR_PXX2_SELECT_RX "Select RX"
#define TR_PXX2_DEFAULT ""
-#define TR_BT_SELECT_DEVICE "Select device..."
+#define TR_BT_SELECT_DEVICE "Select device"
#define TR_DISCOVER "Discover"
#define TR_BUTTON_INIT BUTTON("Init")
#define TR_WAITING "Waiting..."
@@ -931,6 +941,8 @@
#define TR_DEBUG "Debug"
#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
#define TR_CALIBRATION "Calibration"
#define TR_SET "[Set]"
#define TR_TRAINER "Port Trenera"
@@ -946,6 +958,11 @@
#define TR_UNIT "Jedn"
#define TR_TELEMETRY_NEWSENSOR INDENT "Dodaj nowy czujnik..."
#define TR_CHANNELRANGE TR(INDENT "ZakrKn",INDENT "Zakres kanału")
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source")
#define TR_ANTENNACONFIRM1 "EXT. ANTENNA"
#if defined(PCBX12S)
#define LEN_ANTENNA_MODES "\023"
@@ -982,6 +999,7 @@
#define TR_PTS "pkty"
#define TR_SMOOTH "Gładka"
#define TR_COPY_STICKS_TO_OFS TR("Cpy stick->subtrim", "Skopiuj Drążki Do Offsetu")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Cpy min/max to all", "Copy min/max/center to all outputs")
#define TR_COPY_TRIMS_TO_OFS TR("Cpy trim->subtrim", "Skopiuj Trymery Do subtrymerów")
#define TR_INCDEC "Zwiększ/Zmnie"
#define TR_GLOBALVAR "Zm.Global."
@@ -991,7 +1009,8 @@
#define TR_PREFLIGHT "Lista Ostrzeżeń"
#define TR_CHECKLIST TR(INDENT "Czeklista",INDENT "Pokaż Listę Ostrzeżeń")
#define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset")
-#define TR_AUX_SERIAL_MODE "Port szreg."
+#define TR_AUX_SERIAL_MODE "Port szreg."
+#define TR_AUX2_SERIAL_MODE "Port szreg. 2"
#define TR_SCRIPT "Skrypt"
#define TR_INPUTS "Wejścia"
#define TR_OUTPUTS "Wyjścia"
@@ -999,7 +1018,11 @@
#define STR_FACTORYRESET "Ustaw.Fabrycz"
#define TR_CONFIRMRESET "WYkasować wszytkie modele? "
#define TR_TOO_MANY_LUA_SCRIPTS "Za dużo skryptów Lua!"
-
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Nazwa"
@@ -1043,6 +1066,23 @@
// Horus footer descriptions
#define TR_LSW_DESCRIPTIONS { "Comparison type or function", "First variable", "Second variable or constant", "Second variable or constant", "Additional condition for line to be enabled", "Minimum ON duration of the logical switch", "Minimum TRUE duration for the switch to become ON" }
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "First channel"
+#define TR_FILL_BACKGROUND "Fill background?"
+#define TR_BG_COLOR "BG Color"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Flight mode"
+#define TR_INVALID_FILE "Invalid File"
+#define TR_TIMER_SOURCE "Timer source"
+#define TR_SIZE "Size"
+#define TR_SHADOW "Shadow"
+#define TR_TEXT "Text"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Main view X"
+#define TR_PANEL1_BACKGROUND "Panel1 background"
+#define TR_PANEL2_BACKGROUND "Panel2 background"
+
// About screen
#define TR_ABOUTUS TR(" O ", " O ")
@@ -1182,6 +1222,7 @@
#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage")
#define TR_AUTH_FAILURE "Auth-failure"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1220,6 +1261,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1268,7 +1310,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1283,3 +1325,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
\ No newline at end of file
diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt
index 998a4e99a..e07e3ca78 100644
--- a/radio/src/translations/pt.h.txt
+++ b/radio/src/translations/pt.h.txt
@@ -378,6 +378,9 @@
#define LEN_GYROS "\004"
#define TR_GYROS "GyrX""GyrY"
+#define LEN_TEXT_SIZE "\010"
+#define TR_TEXT_SIZE "Standard""Tiny\0 ""Small\0 ""Mid\0 ""Double\0 "
+
// ZERO TERMINATED STRINGS
#if defined(COLORLCD)
#define INDENT " "
@@ -445,6 +448,7 @@
#define TR_PPMFRAME "PPM frame"
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
+#define TR_WARN_5VOLTS "Warning: output level is 5 volts"
#define TR_MS "ms"
#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Chave"
@@ -526,6 +530,7 @@
#define TR_BLDELAY INDENT "Tempo Backlight"
#define TR_BLONBRIGHTNESS INDENT "ON Brightness"
#define TR_BLOFFBRIGHTNESS INDENT "OFF Brightness"
+#define TR_KEYS_BACKLIGHT "Keys backlight"
#define TR_BLCOLOR INDENT "Color"
#define TR_SPLASHSCREEN "Splash screen"
#define TR_PWR_ON_DELAY "Pwr On delay"
@@ -636,6 +641,7 @@
#define TR_RECEIVER "Receiver"
#define TR_SYNCMENU "Sync [MENU]"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
+#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -646,6 +652,7 @@
#define TR_DISABLE_TELEM TR("No Telem", "Disable Telemetry")
#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetect", INDENT "Autodetect format")
#define TR_MULTI_LOWPOWER TR(INDENT "Low power", INDENT "Low power mode")
+#define TR_MULTI_LNA_DISABLE INDENT "LNA disable"
#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "S.Port link")
#define TR_MODULE_TELEM_ON TR("ON", "Enabled")
#define TR_DISABLE_INTERNAL TR("Disable int. RF", "Disable internal RF")
@@ -655,7 +662,7 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_MODULE_UPGRADE_ALERT TR3("Upg. needed", "Module upgrade required", "Module\nUpgrade required")
-#define TR_MODULE_UPGRADE TR("Upg. needed", "Module update recommended")
+#define TR_MODULE_UPGRADE TR("Upg. advised", "Module update recommended")
#define TR_REBIND "Rebinding required"
#define TR_REG_OK "Registration ok"
#define TR_BIND_OK "Bind successful"
@@ -685,6 +692,7 @@
#define TR_VOLTAGE INDENT"Volts"
#define TR_CURRENT INDENT"Amperes"
#define TR_SELECT_MODEL "Selec. Modelo"
+#define TR_SELECT_MODE "Select mode"
#define TR_CREATE_CATEGORY "Create Category"
#define TR_RENAME_CATEGORY "Rename Category"
#define TR_DELETE_CATEGORY "Delete Category"
@@ -743,8 +751,8 @@
#define TR_ALARMSWARN "ALARMES"
#define TR_SWITCHWARN "CHAVES"
#define TR_FAILSAFEWARN "FAILSAFE"
-#define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD")
-#define TR_NIGHTLY_NOTSAFE "Version not safe to fly"
+#define TR_TEST_WARNING TR("TESTING", "TEST BUILD")
+#define TR_TEST_NOTSAFE "Use for tests only"
#define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ")
#define TR_WARN_RTC_BATTERY_LOW "RTC Battery low"
#define TR_WARN_MULTI_LOWPOWER "Low power mode"
@@ -831,6 +839,8 @@
#define TR_FLASH_BOOTLOADER "Flash bootloader"
#define TR_FLASH_EXTERNAL_DEVICE "Flash External Device"
#define TR_FLASH_RECEIVER_OTA "Flash receiver OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA"
#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module")
#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit"
#define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ")
@@ -903,9 +913,9 @@
#define TR_BYTES "bytes"
#define TR_MODULE_BIND "[Bind]"
#define TR_POWERMETER_ATTN_NEEDED "Attenuator needed"
-#define TR_PXX2_SELECT_RX "Select RX..."
+#define TR_PXX2_SELECT_RX "Select RX"
#define TR_PXX2_DEFAULT ""
-#define TR_BT_SELECT_DEVICE "Select device..."
+#define TR_BT_SELECT_DEVICE "Select device"
#define TR_DISCOVER "Discover"
#define TR_BUTTON_INIT BUTTON("Init")
#define TR_WAITING "Waiting..."
@@ -921,6 +931,8 @@
#define TR_DEBUG "Debug"
#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
#define TR_CALIBRATION "Calibration"
#define TR_SET "[Set]"
#define TR_TRAINER "Trainer"
@@ -936,6 +948,11 @@
#define TR_UNIT "Unit"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE INDENT "Channel Range"
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source")
#define TR_ANTENNACONFIRM1 "EXT. ANTENNA"
#if defined(PCBX12S)
#define LEN_ANTENNA_MODES "\023"
@@ -972,6 +989,7 @@
#define TR_PTS "pts"
#define TR_SMOOTH "Smooth"
#define TR_COPY_STICKS_TO_OFS TR("Cpy stick->subtrim", "Copy Sticks To Offset")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Cpy min/max to all", "Copy min/max/center to all outputs")
#define TR_COPY_TRIMS_TO_OFS TR("Cpy trim->subtrim", "Copy trims to subtrim")
#define TR_INCDEC "Inc/Decrement"
#define TR_GLOBALVAR "Global Var"
@@ -981,7 +999,8 @@
#define TR_PREFLIGHT "Preflight Checks"
#define TR_CHECKLIST INDENT "Display Checklist"
#define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset")
-#define TR_AUX_SERIAL_MODE "Serial port"
+#define TR_AUX_SERIAL_MODE "Serial port"
+#define TR_AUX2_SERIAL_MODE "Serial port 2"
#define TR_SCRIPT "Script"
#define TR_INPUTS "Inputs"
#define TR_OUTPUTS "Outputs"
@@ -989,7 +1008,11 @@
#define STR_FACTORYRESET "Factory reset"
#define TR_CONFIRMRESET "Erase ALL models and settings?"
#define TR_TOO_MANY_LUA_SCRIPTS "Too many Lua scripts!"
-
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Name"
@@ -1033,6 +1056,23 @@
// Horus footer descriptions
#define TR_LSW_DESCRIPTIONS { "Comparison type or function", "First variable", "Second variable or constant", "Second variable or constant", "Additional condition for line to be enabled", "Minimum ON duration of the logical switch", "Minimum TRUE duration for the switch to become ON" }
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "First channel"
+#define TR_FILL_BACKGROUND "Fill background?"
+#define TR_BG_COLOR "BG Color"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Flight mode"
+#define TR_INVALID_FILE "Invalid File"
+#define TR_TIMER_SOURCE "Timer source"
+#define TR_SIZE "Size"
+#define TR_SHADOW "Shadow"
+#define TR_TEXT "Text"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Main view X"
+#define TR_PANEL1_BACKGROUND "Panel1 background"
+#define TR_PANEL2_BACKGROUND "Panel2 background"
+
// Taranis About screen
#define TR_ABOUTUS "ABOUT US"
@@ -1171,6 +1211,7 @@
#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage")
#define TR_AUTH_FAILURE "Auth-failure"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1209,6 +1250,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1257,7 +1299,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1272,3 +1314,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
\ No newline at end of file
diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt
index aeff79192..c55d64650 100644
--- a/radio/src/translations/se.h.txt
+++ b/radio/src/translations/se.h.txt
@@ -391,6 +391,9 @@
#define LEN_GYROS "\004"
#define TR_GYROS "GyrX""GyrY"
+#define LEN_TEXT_SIZE "\010"
+#define TR_TEXT_SIZE "Standard""Tiny\0 ""Small\0 ""Mid\0 ""Double\0 "
+
// ZERO TERMINATED STRINGS
#if defined(COLORLCD)
#define INDENT " "
@@ -458,6 +461,7 @@
#define TR_PPMFRAME INDENT "PPM-paket"
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
+#define TR_WARN_5VOLTS "Warning: output level is 5 volts"
#define TR_MS "ms"
#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Brytare"
@@ -539,6 +543,7 @@
#define TR_BLDELAY INDENT "Av efter"
#define TR_BLONBRIGHTNESS INDENT "På Ljusstyrka"
#define TR_BLOFFBRIGHTNESS INDENT "Av Ljusstyrka"
+#define TR_KEYS_BACKLIGHT "Keys backlight"
#define TR_SPLASHSCREEN "Startbild"
#define TR_PWR_ON_DELAY "Pwr On delay"
#define TR_PWR_OFF_DELAY "Pwr Off delay"
@@ -645,6 +650,7 @@
#define TR_RECEIVER "Receiver"
#define TR_SYNCMENU "Synk [MENU]"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
+#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -655,6 +661,7 @@
#define TR_DISABLE_TELEM TR("No Telem", "Disable Telemetry")
#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetect", INDENT "Autodetect format")
#define TR_MULTI_LOWPOWER TR(INDENT "Low power", INDENT "Low power mode")
+#define TR_MULTI_LNA_DISABLE INDENT "LNA disable"
#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "S.Port link")
#define TR_MODULE_TELEM_ON TR("ON", "Enabled")
#define TR_DISABLE_INTERNAL TR("Disable int. RF", "Disable internal RF")
@@ -664,7 +671,7 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_MODULE_UPGRADE_ALERT TR3("Upg. needed", "Module upgrade required", "Module\nUpgrade required")
-#define TR_MODULE_UPGRADE TR("Upg. needed", "Module update recommended")
+#define TR_MODULE_UPGRADE TR("Upg. advised", "Module update recommended")
#define TR_REBIND "Rebinding required"
#define TR_REG_OK "Registration ok"
#define TR_BIND_OK "Bind successful"
@@ -694,6 +701,7 @@
#define TR_VOLTAGE INDENT"Volt"
#define TR_CURRENT INDENT"Ampere"
#define TR_SELECT_MODEL "Välj Modell"
+#define TR_SELECT_MODE "Select mode"
#define TR_CREATE_CATEGORY "Skapa Kategori"
#define TR_RENAME_CATEGORY "Byt Kat.namn"
#define TR_DELETE_CATEGORY "Ta Bort Kategori"
@@ -752,8 +760,8 @@
#define TR_ALARMSWARN "ALARM"
#define TR_SWITCHWARN "BRYTARE"
#define TR_FAILSAFEWARN "FAILSAFE"
-#define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD")
-#define TR_NIGHTLY_NOTSAFE "Version not safe to fly"
+#define TR_TEST_WARNING TR("TESTING", "TEST BUILD")
+#define TR_TEST_NOTSAFE "Use for tests only"
#define TR_SDCARDVERSIONWARN "SD Card Check"
#define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ")
#define TR_WARN_RTC_BATTERY_LOW "RTC Battery low"
@@ -841,6 +849,8 @@
#define TR_FLASH_BOOTLOADER "Skriv BootLoader"
#define TR_FLASH_EXTERNAL_DEVICE "Flash External Device"
#define TR_FLASH_RECEIVER_OTA "Flash receiver OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_EXTERNAL "Flash RX by ext. OTA"
+#define TR_FLASH_RECEIVER_OTA_BY_INTERNAL "Flash RX by int. OTA"
#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module")
#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit"
#define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ")
@@ -850,9 +860,9 @@
#define TR_FLASH_EXTERNAL_MULTI TR("Flash Ext. Multi", "Flash External Multi")
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
-#define TR_WRITING "\032Skriver..."
-#define TR_CONFIRM_FORMAT "Formatera Minnet?"
-#define TR_INTERNALRF "Intern Radio"
+#define TR_WRITING "Skriver..."
+#define TR_CONFIRM_FORMAT "Formatera Minnet?"
+#define TR_INTERNALRF "Intern Radio"
#define TR_INTERNAL_MODULE TR("Int. module","Internal module")
#define TR_EXTERNAL_MODULE TR("Ext. module","External module")
#define TR_OPENTX_UPGRADE_REQUIRED "OpenTX upgrade required"
@@ -913,9 +923,9 @@
#define TR_BYTES "byte"
#define TR_MODULE_BIND TR("[Bnd]", "[Bind]")
#define TR_POWERMETER_ATTN_NEEDED "Attenuator needed"
-#define TR_PXX2_SELECT_RX "Select RX..."
+#define TR_PXX2_SELECT_RX "Select RX"
#define TR_PXX2_DEFAULT ""
-#define TR_BT_SELECT_DEVICE "Select device..."
+#define TR_BT_SELECT_DEVICE "Select device"
#define TR_DISCOVER "Discover"
#define TR_BUTTON_INIT BUTTON("Init")
#define TR_WAITING "Waiting..."
@@ -931,6 +941,8 @@
#define TR_DEBUG "Debug"
#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
+#define TR_TOUCH_NOTFOUND "Touch hardware not found"
+#define TR_TOUCH_EXIT "Touch screen to exit"
#define TR_CALIBRATION "Calibration"
#define TR_SET "[Spara]"
#define TR_TRAINER "Trainer"
@@ -946,6 +958,11 @@
#define TR_UNIT "Enhet"
#define TR_TELEMETRY_NEWSENSOR INDENT "Lägg till sensor..."
#define TR_CHANNELRANGE INDENT "Kanalområde"
+#define TR_AFHDS3_RX_FREQ TR("RX freq.", "RX frequency")
+#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetry")
+#define TR_AFHDS3_ONE_TO_MANY "Multicast"
+#define TR_AFHDS3_ACTUAL_POWER TR("Act. pow", "Actual power")
+#define TR_AFHDS3_POWER_SOURCE TR("Power src.", "Power source")
#define TR_ANTENNACONFIRM1 "EXT. ANTENNA"
#if defined(PCBX12S)
#define LEN_ANTENNA_MODES "\023"
@@ -982,6 +999,7 @@
#define TR_PTS "pkt"
#define TR_SMOOTH "Mjuk"
#define TR_COPY_STICKS_TO_OFS TR("Cpy stick->subtrim", "Spara spakar som subtrim")
+#define TR_COPY_MIN_MAX_TO_OUTPUTS TR("Cpy min/max to all", "Copy min/max/center to all outputs")
#define TR_COPY_TRIMS_TO_OFS TR("Cpy trim->subtrim", "Spara trimmar som subtrim")
#define TR_INCDEC "Inkr/Dekrement"
#define TR_GLOBALVAR "Globala Var"
@@ -991,7 +1009,8 @@
#define TR_PREFLIGHT "Startkontroller"
#define TR_CHECKLIST TR(INDENT "Checklista", INDENT "Visa Checklista")
#define TR_FAS_OFFSET TR(INDENT "FAS Ofs", INDENT "FAS Offset")
-#define TR_AUX_SERIAL_MODE "Serieporten"
+#define TR_AUX_SERIAL_MODE "Serieporten"
+#define TR_AUX2_SERIAL_MODE "Serieporten 2"
#define TR_SCRIPT "Programkod"
#define TR_INPUTS "Input"
#define TR_OUTPUTS "Outputs"
@@ -999,7 +1018,11 @@
#define STR_FACTORYRESET "Factory reset"
#define TR_CONFIRMRESET "Erase ALL models and settings?"
#define TR_TOO_MANY_LUA_SCRIPTS "För många Lua-scripts!"
-
+#define TR_SPORT_UPDATE_POWER_MODE "SP Power"
+#define LEN_SPORT_UPDATE_POWER_MODES "\004"
+#define TR_SPORT_UPDATE_POWER_MODES "AUTO""ON\0 "
+#define TR_NO_TELEMETRY_SCREENS "No Telemetry Screens"
+#define TR_TOUCH_PANEL "Touch panel:"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Namn"
@@ -1043,6 +1066,23 @@
// Horus footer descriptions
#define TR_LSW_DESCRIPTIONS { "Comparison type or function", "First variable", "Second variable or constant", "Second variable or constant", "Additional condition for line to be enabled", "Minimum ON duration of the logical switch", "Minimum TRUE duration for the switch to become ON" }
+// Horus layouts and widgets
+#define TR_FIRST_CHANNEL "First channel"
+#define TR_FILL_BACKGROUND "Fill background?"
+#define TR_BG_COLOR "BG Color"
+#define TR_SLIDERS_TRIMS "Sliders+Trims"
+#define TR_SLIDERS "Sliders"
+#define TR_FLIGHT_MODE "Flight mode"
+#define TR_INVALID_FILE "Invalid File"
+#define TR_TIMER_SOURCE "Timer source"
+#define TR_SIZE "Size"
+#define TR_SHADOW "Shadow"
+#define TR_TEXT "Text"
+#define TR_COLOR "Color"
+#define TR_MAIN_VIEW_X "Main view X"
+#define TR_PANEL1_BACKGROUND "Panel1 background"
+#define TR_PANEL2_BACKGROUND "Panel2 background"
+
// About screen
#define TR_ABOUTUS "Om Oss"
@@ -1182,6 +1222,7 @@
#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage")
#define TR_AUTH_FAILURE "Auth-failure"
+#define ZSTR_VFR "VFR"
#define ZSTR_RSSI "RSSI"
#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
@@ -1220,6 +1261,7 @@
#define ZSTR_CURR "Curr"
#define ZSTR_CAPACITY "Capa"
#define ZSTR_VFAS "VFAS"
+#define ZSTR_BATT_PERCENT "Bat%"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
@@ -1268,7 +1310,7 @@
#define ZSTR_GATE_TIME "GteT"
#define ZSTR_ESC_VOLTAGE "EscV"
#define ZSTR_ESC_CURRENT "EscA"
-#define ZSTR_ESC_RPM "EscR"
+#define ZSTR_ESC_RPM "Erpm"
#define ZSTR_ESC_CONSUMPTION "EscC"
#define ZSTR_ESC_TEMP "EscT"
#define ZSTR_SD1_CHANNEL "Chan"
@@ -1283,3 +1325,45 @@
#define ZSTR_GASSUIT_AVG_FLOW "GAFl"
#define ZSTR_SBEC_VOLTAGE "BecV"
#define ZSTR_SBEC_CURRENT "BecA"
+#define ZSTR_RB3040_EXTRA_STATE "RBES"
+#define ZSTR_RB3040_CHANNEL1 "CH1A"
+#define ZSTR_RB3040_CHANNEL2 "CH2A"
+#define ZSTR_RB3040_CHANNEL3 "CH3A"
+#define ZSTR_RB3040_CHANNEL4 "CH4A"
+#define ZSTR_RB3040_CHANNEL5 "CH5A"
+#define ZSTR_RB3040_CHANNEL6 "CH6A"
+#define ZSTR_RB3040_CHANNEL7 "CH7A"
+#define ZSTR_RB3040_CHANNEL8 "CH8A"
+#define ZSTR_ESC_VIN "EVIN"
+#define ZSTR_ESC_TFET "TFET"
+#define ZSTR_ESC_CUR "ECUR"
+#define ZSTR_ESC_TBEC "TBEC"
+#define ZSTR_ESC_BCUR "CBEC"
+#define ZSTR_ESC_VBEC "VBEC"
+#define ZSTR_ESC_THR "ETHR"
+#define ZSTR_ESC_POUT "EOUT"
+#define ZSTR_SMART_BAT_BTMP "BTmp"
+#define ZSTR_SMART_BAT_BCUR "BCur"
+#define ZSTR_SMART_BAT_BCAP "BUse"
+#define ZSTR_SMART_BAT_MIN_CEL "CLMi"
+#define ZSTR_SMART_BAT_MAX_CEL "CLMa"
+#define ZSTR_SMART_BAT_CYCLES "Cycl"
+#define ZSTR_SMART_BAT_CAPACITY "BCpT"
+#define ZSTR_CL01 "Cel1"
+#define ZSTR_CL02 "Cel2"
+#define ZSTR_CL03 "Cel3"
+#define ZSTR_CL04 "Cel4"
+#define ZSTR_CL05 "Cel5"
+#define ZSTR_CL06 "Cel6"
+#define ZSTR_CL07 "Cel7"
+#define ZSTR_CL08 "Cel8"
+#define ZSTR_CL09 "Cel9"
+#define ZSTR_CL10 "Cl10"
+#define ZSTR_CL11 "Cl11"
+#define ZSTR_CL12 "Cl12"
+#define ZSTR_CL13 "Cl13"
+#define ZSTR_CL14 "Cl14"
+#define ZSTR_CL15 "Cl15"
+#define ZSTR_CL16 "Cl16"
+#define ZSTR_CL17 "Cl17"
+#define ZSTR_CL18 "Cl18"
\ No newline at end of file
diff --git a/radio/src/translations/tts_pt.cpp b/radio/src/translations/tts_pt.cpp
index 34a3ff75b..a909227f5 100644
--- a/radio/src/translations/tts_pt.cpp
+++ b/radio/src/translations/tts_pt.cpp
@@ -96,7 +96,6 @@ I18N_PLAY_FUNCTION(pt, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
-
int8_t mode = MODE(att);
if (mode > 0) {
if (mode == 2) {
@@ -127,13 +126,20 @@ I18N_PLAY_FUNCTION(pt, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
if (number == 0)
number = -1;
}
- if (number >= 100) {
- PUSH_NUMBER_PROMPT(PT_PROMPT_CENTO + number/100);
+
+ if (number > 100) {
+ PUSH_NUMBER_PROMPT(PT_PROMPT_CEM + number/100);
number %= 100;
if (number == 0)
number = -1;
}
- PUSH_NUMBER_PROMPT(PT_PROMPT_ZERO+number);
+
+ if (number == 100) {
+ PUSH_NUMBER_PROMPT(PT_PROMPT_CEM);
+ }
+ else {
+ PUSH_NUMBER_PROMPT(PT_PROMPT_ZERO + number);
+ }
if (unit) {
PT_PUSH_UNIT_PROMPT(unit);
diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h
index e5abaedf5..32acdcb84 100644
--- a/radio/src/translations/untranslated.h
+++ b/radio/src/translations/untranslated.h
@@ -41,12 +41,12 @@
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
-#elif defined(RADIO_X7)
- #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
- #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0""\312SI\0""\312SJ\0"
#elif defined(RADIO_T12)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0"
+#elif defined(PCBX7)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0""\312SI\0""\312SJ\0"
#elif defined(PCBX9LITES)
#define TR_POTS_VSRCRAW "\310S1\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0"
@@ -68,7 +68,9 @@
#define TR_VSWITCHES "---" "ID0""ID1""ID2" "THR""RUD""ELE""AIL""GEA""TRN" TR_TRIMS_SWITCHES TR_ROTENC_SWITCHES TR_ON_ONE_SWITCHES
#endif
-#if defined(PCBHORUS)
+#if defined(PCBHORUS) && defined(AUX_SERIAL)
+ #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_BATTERY TR_VTRAINER_BLUETOOTH TR_VTRAINER_MULTI
+#elif defined(PCBHORUS)
#define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_BLUETOOTH TR_VTRAINER_MULTI
#elif defined(PCBTARANIS)
#define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_SBUS_MODULE TR_VTRAINER_MASTER_CPPM_MODULE TR_VTRAINER_MASTER_BATTERY TR_VTRAINER_BLUETOOTH TR_VTRAINER_MULTI
@@ -76,7 +78,7 @@
#define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_CPPM_MODULE TR_VTRAINER_MASTER_BATTERY TR_VTRAINER_BLUETOOTH TR_VTRAINER_MULTI
#endif
-#define TR_VSRCRAW "---\0" TR_STICKS_VSRCRAW TR_POTS_VSRCRAW TR_ROTARY_ENCODERS TR_GYR_VSRCRAW "MAX\0" TR_CYC_VSRCRAW TR_TRIMS_VSRCRAW TR_SW_VSRCRAW TR_EXTRA_VSRCRAW
+#define TR_VSRCRAW "---\0" TR_STICKS_VSRCRAW TR_POTS_VSRCRAW TR_GYR_VSRCRAW "MAX\0" TR_CYC_VSRCRAW TR_TRIMS_VSRCRAW TR_SW_VSRCRAW TR_EXTRA_VSRCRAW
#if defined(MODULE_PROTOCOL_FLEX)
#define TR_MODULE_R9M_LITE "R9ML\0 "
@@ -85,7 +87,7 @@
#endif
#define LEN_EXTERNAL_MODULE_PROTOCOLS "\014"
-#define TR_EXTERNAL_MODULE_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""ISRM\0 ""DSM2\0 ""CRSF\0 ""MULTI\0 ""R9M\0 ""R9M ACCESS\0 " TR_MODULE_R9M_LITE "R9ML ACCESS\0""R9MLP\0 ""R9MLP ACCESS""SBUS\0 ""XJT Lite"
+#define TR_EXTERNAL_MODULE_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""ISRM\0 ""DSM2\0 ""CRSF\0 ""MULTI\0 ""R9M\0 ""R9M ACCESS\0 " TR_MODULE_R9M_LITE "R9ML ACCESS\0""R9MLP\0 ""R9MLP ACCESS""SBUS\0 ""XJT Lite\0 ""AFHDS3"
#define LEN_INTERNAL_MODULE_PROTOCOLS LEN_EXTERNAL_MODULE_PROTOCOLS
#define TR_INTERNAL_MODULE_PROTOCOLS TR_EXTERNAL_MODULE_PROTOCOLS
@@ -123,4 +125,13 @@
#define TR_DSM_PROTOCOLS "LP45""DSM2""DSMX"
#define LEN_MULTI_PROTOCOLS "\007"
-#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""SFHSS\0 ""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FSky 2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""FlyZone""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 "
+#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""SFHSS\0 ""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FlSky2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""FlyZone""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 ""BayanRX""Pelikan""Tiger\0 ""XK\0 ""XN297DU""FrSkyX2""FrSkyR9""Propel\0""FrSkyL\0""Skyarte""ESky-v2""DSM RX\0""JJRC345""Q90C\0 "
+
+#define LEN_MULTI_POWER "\005"
+#define TR_MULTI_POWER "10mW\0""25mW\0""50mW\0""100mW""200mW""300mW""500mW""1W\0 ""2W\0 "
+
+#define LEN_AFHDS3_PROTOCOLS "\x008"
+#define TR_AFHDS3_PROTOCOLS "PWM/IBUS""PWM/SBUS""PPM/IBUS""PPM/SBUS"
+
+#define LEN_AFHDS3_POWERS "\006"
+#define TR_AFHDS3_POWERS "25 mW\0""100 mW""500 mW""1 W\0 ""2 W\0 "
diff --git a/radio/util/build-firmware.py b/radio/util/build-firmware.py
index be3003c88..c27e6b58a 100755
--- a/radio/util/build-firmware.py
+++ b/radio/util/build-firmware.py
@@ -5,7 +5,6 @@ import os
import sys
import subprocess
import shutil
-import filelock
from fwoptions import *
@@ -30,7 +29,7 @@ def build_target(target, path, cmake_options):
suffix = os.environ["OPENTX_VERSION_SUFFIX"]
cmd.append('-DVERSION_SUFFIX="%s"' % suffix)
if suffix.startswith("N"):
- cmd.append('-DNIGHTLY_BUILD_WARNING=YES')
+ cmd.append('-DTEST_BUILD_WARNING=YES')
cmd.append(srcdir)
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -42,7 +41,7 @@ def build_target(target, path, cmake_options):
return COMPILATION_ERROR
# Launch make
- cmd = ["make", "-j2", target]
+ cmd = ["make", "-j3", target]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = proc.communicate()
if proc.returncode == 0:
@@ -56,7 +55,7 @@ def build_target(target, path, cmake_options):
def main():
if len(sys.argv) != 3:
- exit(INVALID_FIRMWARE)
+ return INVALID_FIRMWARE
target = sys.argv[1]
directory, filename = os.path.split(sys.argv[2])
@@ -64,7 +63,7 @@ def main():
options = root.split("-")
if len(options) < 2 or options[0] != "opentx":
- exit(INVALID_FIRMWARE)
+ return INVALID_FIRMWARE
optcount = 1
cmake_options = {}
@@ -94,7 +93,14 @@ def main():
maxsize = 65536 * 8
elif options[optcount] == "x7":
cmake_options["PCB"] = "X7"
- firmware_options = options_taranis_x9dp
+ cmake_options["AFHDS3"] = "YES"
+ firmware_options = options_taranis_x7
+ maxsize = 65536 * 8
+ elif options[optcount] == "x7access":
+ cmake_options["PCB"] = "X7"
+ cmake_options["PCBREV"] = "ACCESS"
+ cmake_options["AFHDS3"] = "YES"
+ firmware_options = options_taranis_x7
maxsize = 65536 * 8
elif board_name == "xlite":
cmake_options["PCB"] = "XLITE"
@@ -115,6 +121,7 @@ def main():
elif board_name == "x9d+2019":
cmake_options["PCB"] = "X9D+"
cmake_options["PCBREV"] = "2019"
+ cmake_options["AFHDS3"] = "YES"
firmware_options = options_taranis_x9dp
maxsize = 65536 * 8
elif board_name == "x9e":
@@ -144,8 +151,18 @@ def main():
cmake_options["PCBREV"] = "T16"
firmware_options = options_jumper_t16
maxsize = 2 * 1024 * 1024
+ elif board_name == "t18":
+ cmake_options["PCB"] = "X10"
+ cmake_options["PCBREV"] = "T18"
+ firmware_options = options_jumper_t18
+ maxsize = 2 * 1024 * 1024
+ elif board_name == "tx16s":
+ cmake_options["PCB"] = "X10"
+ cmake_options["PCBREV"] = "TX16S"
+ firmware_options = options_radiomaster_tx16s
+ maxsize = 2 * 1024 * 1024
else:
- exit(INVALID_BOARD)
+ return INVALID_BOARD
if target == "firmware":
binary = "firmware.bin"
@@ -156,7 +173,7 @@ def main():
ext = ".so"
filename = "libopentx"
else:
- exit(INVALID_BOARD)
+ return INVALID_BOARD
filename += "-" + board_name
optcount += 1
@@ -188,7 +205,7 @@ def main():
if key == options[-1]:
language = key
if not language:
- exit(INVALID_LANGUAGE)
+ return INVALID_LANGUAGE
cmake_options["TRANSLATIONS"] = language.upper()
filename += "-" + language + ext
@@ -197,24 +214,16 @@ def main():
if os.path.isfile(errpath):
print(filename)
- exit(COMPILATION_ERROR)
+ return COMPILATION_ERROR
if os.path.isfile(path):
print(filename)
- exit(0)
+ return 0
- lockpath = path + ".lock"
- lock = filelock.FileLock(lockpath)
- try:
- with lock.acquire(timeout=60 * 60):
- if not os.path.isfile(path):
- result = build_target(target, path, cmake_options)
- if result != 0:
- print(filename)
- return result
- except filelock.Timeout:
+ result = build_target(target, path, cmake_options)
+ if result != 0:
print(filename)
- exit(COMPILATION_ERROR)
+ return result
if target == "firmware":
# Check binary size
@@ -226,8 +235,8 @@ def main():
shutil.move(binary, path)
print(filename)
- exit(0)
+ return 0
if __name__ == "__main__":
- main()
+ exit(main())
diff --git a/radio/util/font2png.py b/radio/util/font2png.py
index e734cc0a6..169b6b63f 100755
--- a/radio/util/font2png.py
+++ b/radio/util/font2png.py
@@ -10,7 +10,7 @@ chars_en = u""" !"#$%&'()*+,-./0123456789:;<=>?°ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
chars_fr = u"""éèàîç"""
chars_de = u"""ÄäÖöÜüß"""
chars_cz = u"""ěščřžýáíéňóůúďťĚŠČŘŽÝÁÍÉŇÓÚŮĎŤ"""
-chars_es = u"""Ññ"""
+chars_es = u"""ÑñÁáÉéÍíÓóÚú"""
chars_fi = u"""åäöÅÄÖ"""
chars_it = u"""àù"""
chars_pl = u"""ąćęłńóśżźĄĆĘŁŃÓŚŻŹ"""
@@ -19,7 +19,7 @@ chars_pt = u"""ÁáÂâÃãÀàÇçÉéÊêÍíÓóÔôÕõÚú"""
COUNT_EXTRA_CHARS = 21
chars_extra = u"".join([chr(1+i) for i in range(COUNT_EXTRA_CHARS)])
-chars = chars_en + chars_extra + chars_fr + chars_de + chars_cz + chars_es + chars_fi + chars_it + chars_pl
+chars = chars_en + chars_extra + chars_fr + chars_de + chars_cz + chars_es + chars_fi + chars_it + chars_pl + chars_pt
def createFontBitmap(filename, fontname, fontsize, fontoffset, foreground, background, coordsfile=True):
diff --git a/radio/util/fwoptions.py b/radio/util/fwoptions.py
index 1b7e5cfad..140cf4b47 100755
--- a/radio/util/fwoptions.py
+++ b/radio/util/fwoptions.py
@@ -71,13 +71,13 @@ options_taranis_x9d = {
"haptic": ("HAPTIC", "YES", "NO"),
"nogvars": ("GVARS", "NO", "YES"),
"sqt5font": ("FONT", "SQT5", None),
+ "noras": ("RAS", "NO", "YES"),
"faimode": ("FAI", "YES", None),
"faichoice": ("FAI", "CHOICE", None),
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
- "internalppm": ("INTERNAL_MODULE_PPM", "YES", "NO"),
- "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
"eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
- "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None)
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
+ "afhds3": ("AFHDS3", "YES", "NO")
}
options_taranis_x9dp = {
@@ -90,10 +90,21 @@ options_taranis_x9dp = {
"faimode": ("FAI", "YES", None),
"faichoice": ("FAI", "CHOICE", None),
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
- "internalppm": ("INTERNAL_MODULE_PPM", "YES", "NO"),
- "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
"eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
- "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None)
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
+ "afhds3": ("AFHDS3", "YES", "NO")
+}
+options_taranis_x7 = {
+ "noheli": ("HELI", "NO", "YES"),
+ "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"),
+ "lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"),
+ "nogvars": ("GVARS", "NO", "YES"),
+ "sqt5font": ("FONT", "SQT5", None),
+ "faimode": ("FAI", "YES", None),
+ "faichoice": ("FAI", "CHOICE", None),
+ "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
+ "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
}
options_taranis_x9lite = {
@@ -101,16 +112,13 @@ options_taranis_x9lite = {
"ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"),
"lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"),
"nogvars": ("GVARS", "NO", "YES"),
- "autoupdate": ("AUTOUPDATE", "YES", None),
"sqt5font": ("FONT", "SQT5", None),
- "noras": ("RAS", "NO", "YES"),
"faimode": ("FAI", "YES", None),
"faichoice": ("FAI", "CHOICE", None),
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
- "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
"eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
- "internalpxx1": ("INTERNAL_MODULE_PXX1", "YES", "NO"),
- "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None)
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
+ "afhds3": ("AFHDS3", "YES", "NO")
}
options_taranis_xlite = {
@@ -122,9 +130,9 @@ options_taranis_xlite = {
"faimode": ("FAI", "YES", None),
"faichoice": ("FAI", "CHOICE", None),
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
- "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
"eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
- "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None)
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
+ "afhds3": ("AFHDS3", "YES", "NO")
}
options_taranis_xlites = {
@@ -132,15 +140,13 @@ options_taranis_xlites = {
"ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"),
"lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"),
"nogvars": ("GVARS", "NO", "YES"),
- "autoupdate": ("AUTOUPDATE", "YES", None),
"sqt5font": ("FONT", "SQT5", None),
"faimode": ("FAI", "YES", None),
"faichoice": ("FAI", "CHOICE", None),
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
- "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
"eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
- "internalpxx1": ("INTERNAL_MODULE_PXX1", "YES", "NO"),
- "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None)
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
+ "afhds3": ("AFHDS3", "YES", "NO")
}
options_taranis_x9e = {
@@ -152,11 +158,11 @@ options_taranis_x9e = {
"faimode": ("FAI", "YES", None),
"faichoice": ("FAI", "CHOICE", None),
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
- "internalppm": ("INTERNAL_MODULE_PPM", "YES", "NO"),
"shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
"eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
"horussticks": ("STICKS", "HORUS", "STANDARD"),
- "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None)
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
+ "afhds3": ("AFHDS3", "YES", "NO")
}
options_horus_x12s = {
@@ -170,7 +176,7 @@ options_horus_x12s = {
"eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
"pcbdev": ("PCBREV", "10", None),
"flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
- "internalaccess": [("INTERNAL_MODULE_PXX1", "NO", None), ("INTERNAL_MODULE_PXX2", "YES", None)]
+ "internalaccess": [("INTERNAL_MODULE_PXX1", "NO", None), ("INTERNAL_MODULE_PXX2", "YES", None)],
}
options_horus_x10 = {
@@ -183,7 +189,7 @@ options_horus_x10 = {
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
"eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
"flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
- "internalaccess": [("INTERNAL_MODULE_PXX1", "NO", None), ("INTERNAL_MODULE_PXX2", "YES", None)]
+ "internalaccess": [("INTERNAL_MODULE_PXX1", "NO", None), ("INTERNAL_MODULE_PXX2", "YES", None)],
}
options_horus_x10express = {
@@ -196,7 +202,7 @@ options_horus_x10express = {
"faichoice": ("FAI", "CHOICE", None),
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
"eu": ("MODULE_PROTOCOL_D8", "NO", "YES"),
- "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None)
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
}
options_jumper_t12 = {
@@ -209,6 +215,7 @@ options_jumper_t12 = {
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
"flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
"internalmulti": ("INTERNAL_MODULE_MULTI", "YES", "NO"),
+ "afhds3": ("AFHDS3", "YES", "NO")
}
options_jumper_t16 = {
@@ -222,4 +229,29 @@ options_jumper_t16 = {
"flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
"internalmulti": ("INTERNAL_MODULE_MULTI", "YES", "NO"),
"bluetooth": ("BLUETOOTH", "YES", "NO"),
+}
+
+options_jumper_t18 = {
+ "noheli": ("HELI", "NO", "YES"),
+ "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"),
+ "lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"),
+ "nogvars": ("GVARS", "NO", "YES"),
+ "faimode": ("FAI", "YES", None),
+ "faichoice": ("FAI", "CHOICE", None),
+ "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
+ "bluetooth": ("BLUETOOTH", "YES", "NO"),
+}
+
+options_radiomaster_tx16s = {
+ "noheli": ("HELI", "NO", "YES"),
+ "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"),
+ "lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"),
+ "nogvars": ("GVARS", "NO", "YES"),
+ "faimode": ("FAI", "YES", None),
+ "faichoice": ("FAI", "CHOICE", None),
+ "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
+ "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None),
+ "bluetooth": ("BLUETOOTH", "YES", "NO"),
+ "internalgps": ("INTERNAL_GPS", "YES", "NO"),
}
\ No newline at end of file
diff --git a/radio/util/generate_datacopy.py b/radio/util/generate_datacopy.py
index 6da1c871b..93f7c79a5 100755
--- a/radio/util/generate_datacopy.py
+++ b/radio/util/generate_datacopy.py
@@ -1,30 +1,33 @@
#!/usr/bin/env python
-from __future__ import print_function
-
import sys
import clang.cindex
import time
import os
-if sys.platform == "darwin":
- if os.path.exists('/usr/local/Cellar/llvm/6.0.0/lib/libclang.dylib'):
- clang.cindex.Config.set_library_file('/usr/local/Cellar/llvm/6.0.0/lib/libclang.dylib')
- elif os.path.exists('/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib'):
- clang.cindex.Config.set_library_file('/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib')
- elif os.path.exists('/Library/Developer/CommandLineTools/usr/lib/libclang.dylib'):
- clang.cindex.Config.set_library_file('/Library/Developer/CommandLineTools/usr/lib/libclang.dylib')
-elif sys.platform.startswith("linux"):
- for version in ("7", "6.0", "3.8"):
- libclang = "/usr/lib/x86_64-linux-gnu/libclang-%s.so.1" % version
- if os.path.exists(libclang):
- clang.cindex.Config.set_library_file(libclang)
- break
structs = []
extrastructs = []
+def find_libclang():
+ if sys.platform == "darwin":
+ for path in ("/usr/local/Cellar/llvm/6.0.0/lib/libclang.dylib",
+ "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib",
+ "/Library/Developer/CommandLineTools/usr/lib/libclang.dylib"):
+ if os.path.exists(path):
+ return path
+ elif sys.platform.startswith("linux"):
+ for version in ("7", "6.0", "3.8"):
+ path = "/usr/lib/x86_64-linux-gnu/libclang-%s.so.1" % version
+ if os.path.exists(path):
+ return path
+ for path in ("/usr/local/lib/libclang.so",
+ "/usr/lib/libclang.so"):
+ if os.path.exists(path):
+ return path
+
+
def build_struct(cursor, anonymousUnion=False):
if not anonymousUnion:
structs.append(cursor.spelling)
@@ -98,7 +101,28 @@ def header():
print("// This file was auto-generated by %s script on %s. Do not edit this file!\n\n\n" % (os.path.basename(sys.argv[0]), time.asctime()))
-index = clang.cindex.Index.create()
-translation_unit = index.parse(sys.argv[1], ['-x', 'c++', '-std=c++11'] + sys.argv[2:])
-header()
-build(translation_unit.cursor)
+def print_translation_unit_diags(diags, prefix=''):
+ for diag in diags:
+ print(prefix + str(diag), file=sys.stderr)
+ print_translation_unit_diags(diag.children, ' ' + prefix)
+
+
+def main():
+ libclang = find_libclang()
+ if libclang:
+ # print(libclang, file=sys.stderr)
+ clang.cindex.Config.set_library_file(libclang)
+
+ index = clang.cindex.Index.create()
+ translation_unit = index.parse(sys.argv[1], ['-x', 'c++', '-std=c++11'] + sys.argv[2:])
+
+ if translation_unit.diagnostics:
+ print_translation_unit_diags(translation_unit.diagnostics)
+ sys.exit(-1)
+
+ header()
+ build(translation_unit.cursor)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/radio/util/translate.py b/radio/util/translate.py
index 53e113ca7..58525c969 100755
--- a/radio/util/translate.py
+++ b/radio/util/translate.py
@@ -70,7 +70,17 @@ translations = {'cz_reduced': [('\\200', u'á'),
('\\206', u'ß')],
'es': [('\\200', u'Ñ'),
- ('\\201', u'ñ')],
+ ('\\201', u'ñ'),
+ ('\\202', u'Á'),
+ ('\\203', u'á'),
+ ('\\204', u'É'),
+ ('\\205', u'é'),
+ ('\\206', u'Í'),
+ ('\\207', u'í'),
+ ('\\210', u'Ó'),
+ ('\\211', u'ó'),
+ ('\\212', u'Ú'),
+ ('\\213', u'ú')],
'fi': [('\\200', u'å'),
('\\201', u'ä'),
diff --git a/radio/util/tts_en.py b/radio/util/tts_en.py
index e53cfd348..dff2e29dd 100755
--- a/radio/util/tts_en.py
+++ b/radio/util/tts_en.py
@@ -72,7 +72,9 @@ for s, f in [("trim center", "midtrim"),
("receiver still connected", "modelpwr"),
]:
systemSounds.append((s, filename(f)))
-for i, (s, f) in enumerate([("gear!, up!", "gearup"),
+for i, (s, f) in enumerate([("armed", "armed"),
+ ("disarmed", "disarm"),
+ ("gear!, up!", "gearup"),
("gear!, down!", "geardn"),
("flaps!, up!", "flapup"),
("flaps!, down!", "flapdn"),
diff --git a/radio/util/tts_es.py b/radio/util/tts_es.py
index 3b436ecd6..897b6b9e4 100755
--- a/radio/util/tts_es.py
+++ b/radio/util/tts_es.py
@@ -61,23 +61,27 @@ for s, f in [("me tienes abandonada", "inactiv"),
("trim centrado", "midtrim"),
("potenciómetro centrado", "midpot"),
("trim al máximo", "maxtrim"),
- ("trim al mínima", "mintrim"),
+ ("trim al mínimo", "mintrim"),
("20 segundos", "timer20"),
("30 segundos", "timer30"),
- ("assorbimiento elevado", "highmah"),
- ("temperatura elevada", "hightemp"),
+ ("consumo alto", "highmah"),
+ ("temperatura alta", "hightemp"),
("Alarma A1", "a1_org"),
("A1 crítica", "a1_red"),
("Alarma A2", "a2_org"),
("A2 crítica", "a2_red"),
- ("recepcion de señal baja", "rssi_org"),
- ("recepción de señal crítica", "rssi_red"),
+ ("Bienvenido a open t equis", "hello"),
+ ("señal baja", "rssi_org"),
+ ("señal crítica", "rssi_red"),
("Problemas con la antena del transmisor", "swr_red"),
("Sin telemetría", "telemko"),
("Telemetría disponible", "telemok"),
- ("servo overload", "servoko"),
- ("power overload", "rxko"),
- ("receiver still connected", "modelpwr"),
+ ("sobrecarga de servo", "servoko"),
+ ("sobrecarga de potencia", "rxko"),
+ ("El receptor aún está encendido", "modelpwr"),
+ ("cronómetro uno terminado", "timovr1"),
+ ("cronómetro dos terminado", "timovr2"),
+ ("cronómetro tres terminado", "timovr3"),
]:
systemSounds.append((s, filename(f)))
for i, s in enumerate(["cronómetro", "cronómetro", "transmisión", "recepción", "A1", "A2", "altitud", "motor",
@@ -101,14 +105,14 @@ for i, (s, f) in enumerate([("tren arriba.", "gearup"),
("modo de velocidad", "spdmod"),
("modo de térmica", "thmmod"),
("modo de vuelo normal", "nrmmod"),
- ("fase de vuelo 1", "fltmd1"),
- ("fase de vuelo 2", "fltmd2"),
- ("fase de vuelo 3", "fltmd3"),
- ("fase de vuelo 4", "fltmd4"),
- ("fase de vuelo 5", "fltmd5"),
- ("fase de vuelo 6", "fltmd6"),
- ("fase de vuelo 7", "fltmd7"),
- ("fase de vuelo 8", "fltmd8"),
- ("fase de vuelo 9", "fltmd9"),
+ ("modo de vuelo 1", "fltmd1"),
+ ("modo de vuelo 2", "fltmd2"),
+ ("modo de vuelo 3", "fltmd3"),
+ ("modo de vuelo 4", "fltmd4"),
+ ("modo de vuelo 5", "fltmd5"),
+ ("modo de vuelo 6", "fltmd6"),
+ ("modo de vuelo 7", "fltmd7"),
+ ("modo de vuelo 8", "fltmd8"),
+ ("modo de vuelo 9", "fltmd9"),
]):
sounds.append((s, filename(f)))
diff --git a/radio/util/tts_fr.py b/radio/util/tts_fr.py
index 736fef4c1..9dc046fa5 100755
--- a/radio/util/tts_fr.py
+++ b/radio/util/tts_fr.py
@@ -71,9 +71,11 @@ for s, f in [("Trim centré", "midtrim"),
("Récepteur encore sous tension", "modelpwr"),
]:
systemSounds.append((s, filename(f)))
-for i, (s, f) in enumerate([("altitude", "altitude"),
+for i, (s, f) in enumerate([("armé", "armed"),
+ ("désarmé", "disarm"),
+ ("altitude", "alt"),
("température moteur", "moteur"),
- ("température contrôleur", "cntrleur"),
+ ("température contrôleur", "tctrl"),
("train rentré", "gearup"),
("train sorti", "geardn"),
("volets rentrés", "flapup"),
diff --git a/radio/util/tts_it.py b/radio/util/tts_it.py
index ea6223801..2b87dd911 100755
--- a/radio/util/tts_it.py
+++ b/radio/util/tts_it.py
@@ -14,9 +14,9 @@ systemSounds.append(("mila", filename(101)))
systemSounds.append(("mille", filename(102)))
for i, s in enumerate(["virgola", "un", "e", "meno", "ora", "ore", "minuto", "minuti", "secondo", "secondi"]):
systemSounds.append((s, filename(103 + i)))
-for i, (s, f) in enumerate([("volt", "volt0"),
- ("ampere", "amp0"),
- ("milliampere", "mamp0"),
+for i, (s, f) in enumerate([("volt", "volt0"),("volt", "volt1"),
+ ("ampere", "amp0"),("ampere", "amp1"),
+ ("milliampere", "mamp0"),("milliampere", "mamp1"),
("nodo", "knot0"), ("nodi", "knot1"),
("metri al secondo", "mps0"), ("metri al secondo", "msp1"),
("piedi al secondo", "fps0"), ("piedi al secondo", "fps1"),
diff --git a/tools/build-companion-nightly.sh b/tools/build-companion-nightly.sh
index ac2004b16..fbf8f7166 100755
--- a/tools/build-companion-nightly.sh
+++ b/tools/build-companion-nightly.sh
@@ -4,7 +4,7 @@
set -e
set -x
-JOBS=2
+JOBS=3
while [ $# -gt 0 ]
do
@@ -25,7 +25,7 @@ done
SRCDIR=$1
OUTDIR=$2
-COMMON_OPTIONS="-DALLOW_NIGHTLY_BUILDS=YES -DNIGHTLY_BUILD_WARNING=YES -DGVARS=YES -DHELI=YES -DLUA=YES -DMULTIMODULE=YES -DTELEMETRY=FRSKY -DPPM_LIMITS_SYMETRICAL=YES -DVARIO=YES -DAUTOSWITCH=YES -DAUTOSOURCE=YES -DAUDIO=YES -DGPS=YES -DPPM_CENTER_ADJUSTABLE=YES -DFLIGHT_MODES=YES -DOVERRIDE_CHANNEL_FUNCTION=YES -DFRSKY_STICKS=YES"
+COMMON_OPTIONS="-DALLOW_NIGHTLY_BUILDS=YES -DTEST_BUILD_WARNING=YES -DGVARS=YES -DHELI=YES -DLUA=YES -DMULTIMODULE=YES -DTELEMETRY=FRSKY -DPPM_LIMITS_SYMETRICAL=YES -DVARIO=YES -DAUTOSWITCH=YES -DAUTOSOURCE=YES -DAUDIO=YES -DGPS=YES -DPPM_CENTER_ADJUSTABLE=YES -DFLIGHT_MODES=YES -DOVERRIDE_CHANNEL_FUNCTION=YES -DFRSKY_STICKS=YES"
if [ "$(uname)" = "Darwin" ]; then
COMMON_OPTIONS="${COMMON_OPTIONS} -DCMAKE_PREFIX_PATH=~/Qt/5.7/clang_64/ -DCMAKE_OSX_DEPLOYMENT_TARGET='10.9'"
fi
@@ -62,6 +62,10 @@ cmake ${COMMON_OPTIONS} -DPCB=X7 ${SRCDIR}
make -j${JOBS} libsimulator
rm CMakeCache.txt
+cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=ACCESS ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=T12 ${SRCDIR}
make -j${JOBS} libsimulator
rm CMakeCache.txt
@@ -94,7 +98,15 @@ cmake ${COMMON_OPTIONS} -DPCB=X10 ${SRCDIR}
make -j${JOBS} libsimulator
rm CMakeCache.txt
-cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=T16 ${SRCDIR}
+cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=T16 -DINTERNAL_MODULE_MULTI=YES ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
+cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=TX16S ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
+cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=T18 ${SRCDIR}
make -j${JOBS} libsimulator
rm CMakeCache.txt
diff --git a/tools/build-companion-release.sh b/tools/build-companion-release.sh
index 81a20b6cd..b73ce8ed2 100755
--- a/tools/build-companion-release.sh
+++ b/tools/build-companion-release.sh
@@ -40,48 +40,83 @@ cd build
cmake ${COMMON_OPTIONS} -DPCB=AR9X ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=SKY9X ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=9XRPRO ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X9LITE ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X9LITES ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X7 ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
+cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=ACCESS ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
+cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=T12 ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X9D ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X9D+ ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X9D+ -DPCBREV=2019 ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=XLITE ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=XLITES ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X9E ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X10 ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
+cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=T16 -DINTERNAL_MODULE_MULTI=YES ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
+cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=TX16S ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
+cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=T18 ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=EXPRESS ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
cmake ${COMMON_OPTIONS} -DPCB=X12S ${SRCDIR}
make -j${JOBS} libsimulator
+rm CMakeCache.txt
make -j${JOBS} package
diff --git a/tools/build-frsky.py b/tools/build-frsky.py
index 9e538bc4a..fc33d2b80 100755
--- a/tools/build-frsky.py
+++ b/tools/build-frsky.py
@@ -11,99 +11,95 @@ import tempfile
boards = {
"XLITE_FCC": {
"PCB": "XLITE",
- "LUA": "NO_MODEL_SCRIPTS",
- "GVARS": "YES",
"MODULE_SIZE_STD": "NO",
"PPM": "NO",
"DSM2": "NO",
- "MULTIMODULE": "NO",
- "CROSSFIRE": "NO",
"SBUS": "NO",
},
"XLITE_LBT": {
"PCB": "XLITE",
"MODULE_PROTOCOL_D8": "NO",
- "LUA": "NO_MODEL_SCRIPTS",
- "GVARS": "YES",
"MODULE_SIZE_STD": "NO",
"PPM": "NO",
"DSM2": "NO",
- "MULTIMODULE": "NO",
- "CROSSFIRE": "NO",
"SBUS": "NO",
},
"XLITES": {
"PCB": "XLITES",
- "LUA": "NO_MODEL_SCRIPTS",
- "GVARS": "YES",
"AUTOUPDATE": "YES",
"PXX1": "YES",
"XJT": "NO",
"MODULE_SIZE_STD": "NO",
"PPM": "NO",
"DSM2": "NO",
- "MULTIMODULE": "NO",
- "CROSSFIRE": "NO",
"SBUS": "NO",
},
"X9LITE": {
"PCB": "X9LITE",
- "LUA": "NO_MODEL_SCRIPTS",
- "GVARS": "YES",
"AUTOUPDATE": "YES",
"PXX1": "YES",
"XJT": "NO",
"MODULE_SIZE_STD": "NO",
"PPM": "NO",
"DSM2": "NO",
- "MULTIMODULE": "NO",
- "CROSSFIRE": "NO",
"SBUS": "NO",
"DEFAULT_MODE": "2",
},
"X9LITES": {
"PCB": "X9LITES",
- "LUA": "NO_MODEL_SCRIPTS",
- "GVARS": "YES",
"AUTOUPDATE": "YES",
"PXX1": "YES",
"XJT": "NO",
"MODULE_SIZE_STD": "NO",
"PPM": "NO",
"DSM2": "NO",
- "MULTIMODULE": "NO",
- "CROSSFIRE": "NO",
"SBUS": "NO",
"DEFAULT_MODE": "2",
},
+ "X9D+2019": {
+ "PCB": "X9D+",
+ "PCBREV": "2019",
+ "AUTOUPDATE": "YES",
+ "PXX1": "YES",
+ "DEFAULT_MODE": "2",
+ },
"X9D+": {
"PCB": "X9D+",
- "PCBREV": "2019",
- "LUA": "NO_MODEL_SCRIPTS",
- "GVARS": "YES",
- "AUTOUPDATE": "YES",
- "PXX1": "YES",
- "MULTIMODULE": "NO",
- "CROSSFIRE": "NO",
+ "DEFAULT_MODE": "2",
+ },
+ "X9E": {
+ "PCB": "X9E",
"DEFAULT_MODE": "2",
},
"X7_FCC": {
"PCB": "X7",
- "LUA": "NO_MODEL_SCRIPTS",
- "GVARS": "YES",
- "MULTIMODULE": "NO",
- "CROSSFIRE": "NO",
"DEFAULT_MODE": "2",
},
"X7_LBT": {
"PCB": "X7",
"MODULE_PROTOCOL_D8": "NO",
- "LUA": "NO_MODEL_SCRIPTS",
- "GVARS": "YES",
- "MULTIMODULE": "NO",
- "CROSSFIRE": "NO",
"DEFAULT_MODE": "2",
- }
+ },
+ "X7ACCESS": {
+ "PCB": "X7",
+ "PCBREV": "ACCESS",
+ "AUTOUPDATE": "YES",
+ "PXX1": "YES",
+ "DEFAULT_MODE": "2",
+ },
+ "X10S": {
+ "PCB": "X10",
+ "DEFAULT_MODE": "2",
+ },
+ "X10SExpress": {
+ "PCB": "X10",
+ "PCBREV": "EXPRESS",
+ "DEFAULT_MODE": "2",
+ },
+ "X12S": {
+ "PCB": "X12S",
+ "DEFAULT_MODE": "2",
+ },
}
translations = [
@@ -111,19 +107,27 @@ translations = [
"CZ"
]
+common_options = {
+ "MULTIMODULE": "NO",
+ "CROSSFIRE": "NO",
+ "AFHDS3": "NO",
+ "GVARS": "YES",
+ "LUA": "NO_MODEL_SCRIPTS",
+}
+
def timestamp():
return datetime.datetime.now().strftime("%y%m%d")
def build(board, translation, srcdir):
- cmake_options = " ".join(["-D%s=%s" % (key, value) for key, value in boards[board].items()])
+ cmake_options = " ".join(["-D%s=%s" % (key, value) for key, value in list(boards[board].items()) + list(common_options.items())])
cwd = os.getcwd()
if not os.path.exists("output"):
os.mkdir("output")
path = tempfile.mkdtemp()
os.chdir(path)
- command = "cmake %s -DTRANSLATIONS=%s -DFRSKY_RELEASE=YES %s" % (cmake_options, translation, srcdir)
+ command = "cmake %s -DTRANSLATIONS=%s -DFRSKY_RELEASE=YES -DDEFAULT_TEMPLATE_SETUP=17 %s" % (cmake_options, translation, srcdir)
print(command)
os.system(command)
os.system("make firmware -j6")
diff --git a/tools/build-jumper.py b/tools/build-jumper.py
index ab3fb9e45..6e7f3d733 100755
--- a/tools/build-jumper.py
+++ b/tools/build-jumper.py
@@ -25,6 +25,12 @@ boards = {
"PCBREV": "T16",
"INTERNAL_MODULE_MULTI": "YES",
"DEFAULT_MODE": "2",
+ },
+ "T18": {
+ "PCB": "X10",
+ "PCBREV": "T18",
+ "INTERNAL_MODULE_MULTI": "YES",
+ "DEFAULT_MODE": "2",
}
}
diff --git a/tools/build-radiomaster.py b/tools/build-radiomaster.py
new file mode 100755
index 000000000..83faa31bb
--- /dev/null
+++ b/tools/build-radiomaster.py
@@ -0,0 +1,77 @@
+#!/usr/bin/python3
+
+import argparse
+import datetime
+import os
+from builtins import NotADirectoryError
+import shutil
+import tempfile
+
+
+boards = {
+ "TX16S_1": {
+ "PCB": "X10",
+ "PCBREV": "TX16S",
+ "DEFAULT_MODE": "1",
+ },
+ "TX16S_2": {
+ "PCB": "X10",
+ "PCBREV": "TX16S",
+ "DEFAULT_MODE": "2",
+ }
+}
+
+translations = [
+ "EN",
+]
+
+
+def timestamp():
+ return datetime.datetime.now().strftime("%y%m%d")
+
+
+def build(board, translation, srcdir):
+ cmake_options = " ".join(["-D%s=%s" % (key, value) for key, value in boards[board].items()])
+ cwd = os.getcwd()
+ if not os.path.exists("output"):
+ os.mkdir("output")
+ path = tempfile.mkdtemp()
+ os.chdir(path)
+ command = "cmake %s -DTRANSLATIONS=%s -DRADIOMASTER_RELEASE=YES %s" % (cmake_options, translation, srcdir)
+ print(command)
+ os.system(command)
+ os.system("make firmware -j6")
+ os.chdir(cwd)
+ index = 0
+ while 1:
+ suffix = "" if index == 0 else "_%d" % index
+ filename = "output/firmware_%s_%s_%s%s.bin" % (board.lower(), translation.lower(), timestamp(), suffix)
+ if not os.path.exists(filename):
+ shutil.copy("%s/firmware.bin" % path, filename)
+ break
+ index += 1
+ shutil.rmtree(path)
+
+
+def dir_path(string):
+ if os.path.isdir(string):
+ return string
+ else:
+ raise NotADirectoryError(string)
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Build Radiomaster firmware")
+ parser.add_argument("-b", "--boards", action="append", help="Destination boards", required=True)
+ parser.add_argument("-t", "--translations", action="append", help="Translations", required=True)
+ parser.add_argument("srcdir", type=dir_path)
+
+ args = parser.parse_args()
+
+ for board in (boards.keys() if "ALL" in args.boards else args.boards):
+ for translation in (translations if "ALL" in args.translations else args.translations):
+ build(board, translation, args.srcdir)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/build-tbs.py b/tools/build-tbs.py
new file mode 100755
index 000000000..3c5cb2d1c
--- /dev/null
+++ b/tools/build-tbs.py
@@ -0,0 +1,118 @@
+#!/usr/bin/python3
+
+import argparse
+import datetime
+import os
+from builtins import NotADirectoryError
+import shutil
+import tempfile
+
+
+boards = {
+ "XLITE": {
+ "PCB": "XLITE",
+ },
+ "XLITES": {
+ "PCB": "XLITES",
+ },
+ "X9LITE": {
+ "PCB": "X9LITE",
+ },
+ "X9LITES": {
+ "PCB": "X9LITES",
+ },
+ "X9D": {
+ "PCB": "X9D+",
+ },
+ "X9D+": {
+ "PCB": "X9D+",
+ },
+ "X9D+2019": {
+ "PCB": "X9D+",
+ "PCBREV": "2019",
+ },
+ "X9E": {
+ "PCB": "X9E",
+ },
+ "X7": {
+ "PCB": "X7",
+ },
+ "X7ACCESS": {
+ "PCB": "X7",
+ "PCBREV": "ACCESS",
+ },
+ "X10": {
+ "PCB": "X10",
+ },
+ "X10EXPRESS": {
+ "PCB": "X10",
+ "PCBREV": "EXPRESS",
+ },
+ "X12S": {
+ "PCB": "X12S",
+ },
+ "T16": {
+ "PCB": "X10",
+ "PCBREV": "T16",
+ "INTERNAL_MODULE_MULTI": "YES"
+ },
+ "T12": {
+ "PCB": "X7",
+ "PCBREV": "T12",
+ },
+}
+
+translations = [
+ "EN"
+]
+
+
+def timestamp():
+ return datetime.datetime.now().strftime("%y%m%d")
+
+
+def build(board, translation, srcdir):
+ cmake_options = " ".join(["-D%s=%s" % (key, value) for key, value in boards[board].items()])
+ cwd = os.getcwd()
+ if not os.path.exists("output"):
+ os.mkdir("output")
+ path = tempfile.mkdtemp()
+ os.chdir(path)
+ command = "cmake %s -DTRANSLATIONS=%s -DTBS_RELEASE=YES -DTEST_BUILD_WARNING=YES %s" % (cmake_options, translation, srcdir)
+ print(command)
+ os.system(command)
+ os.system("make firmware -j6")
+ os.chdir(cwd)
+ index = 0
+ while 1:
+ suffix = "" if index == 0 else "_%d" % index
+ filename = "output/firmware_%s_%s_%s%s.bin" % (board.lower(), translation.lower(), timestamp(), suffix)
+ if not os.path.exists(filename):
+ shutil.copy("%s/firmware.bin" % path, filename)
+ break
+ index += 1
+ shutil.rmtree(path)
+
+
+def dir_path(string):
+ if os.path.isdir(string):
+ return string
+ else:
+ raise NotADirectoryError(string)
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Build FrSky firmware")
+ parser.add_argument("-b", "--boards", action="append", help="Destination boards", required=True)
+ parser.add_argument("-t", "--translations", action="append", help="Translations", required=True)
+ parser.add_argument("srcdir", type=dir_path)
+
+ args = parser.parse_args()
+
+ for board in (boards.keys() if "ALL" in args.boards else args.boards):
+ for translation in (translations if "ALL" in args.translations else args.translations):
+ build(board, translation, args.srcdir)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh
index 9e470343c..c1c97237e 100755
--- a/tools/commit-tests.sh
+++ b/tools/commit-tests.sh
@@ -5,7 +5,7 @@ set -e
set -x
# Allow variable core usage, default uses all cpu cores, to set 8 cores for example : commit-tests.sh -j8
-num_cpus=$(grep 'physical id' /proc/cpuinfo | sort -u | wc -l)
+num_cpus=$(nproc)
: "${CORES:=$num_cpus}"
# Default build treats warnings as errors, set -Wno-error to override, e.g.: commit-tests.sh -Wno-error
: "${WERROR:=1}"
@@ -97,7 +97,7 @@ fi
if [[ " X9LITES X9LITE ALL " =~ \ ${FLAVOR}\ ]] ; then
# OpenTX on X9LITES
rm -rf ./*
- cmake "${COMMON_OPTIONS}" -DPCB=X9LITES -DHELI=YES -DGVARS=YES "${SRCDIR}"
+ cmake "${COMMON_OPTIONS}" -DPCB=X9LITES -DHELI=YES -DGVARS=YES -DMULTIMODULE=NO "${SRCDIR}"
make -j"${CORES}" ${FIRMARE_TARGET}
make -j"${CORES}" libsimulator
make -j"${CORES}" tests-radio
@@ -184,10 +184,28 @@ if [[ " X10 COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then
make -j"${CORES}" tests-radio
fi
+if [[ " T16 COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then
+ # OpenTX on T16 boards
+ rm -rf ./*
+ cmake "${COMMON_OPTIONS}" -DPCB=X10 -DPCBREV=T16 -DHELI=YES -DLUA=YES -DGVARS=YES -DAFHDS3=NO "${SRCDIR}"
+ make -j"${CORES}" ${FIRMARE_TARGET}
+ make -j"${CORES}" libsimulator
+ make -j"${CORES}" tests-radio
+fi
+
+if [[ " TX16S COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then
+ # OpenTX on TX16S boards
+ rm -rf ./*
+ cmake "${COMMON_OPTIONS}" -DPCB=X10 -DPCBREV=TX16S -DHELI=YES -DLUA=YES -DGVARS=YES "${SRCDIR}"
+ make -j"${CORES}" ${FIRMARE_TARGET}
+ make -j"${CORES}" libsimulator
+ make -j"${CORES}" tests-radio
+fi
+
if [[ " X12S COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then
# OpenTX on X12S
rm -rf ./*
- cmake "${COMMON_OPTIONS}" -DPCB=X12S -DHELI=YES -DLUA=YES -DGVARS=YES "${SRCDIR}"
+ cmake "${COMMON_OPTIONS}" -DPCB=X12S -DHELI=YES -DLUA=YES -DGVARS=YES -DMULTIMODULE=NO "${SRCDIR}"
make -j"${CORES}" ${FIRMARE_TARGET}
make -j"${CORES}" libsimulator
make -j"${CORES}" tests-radio