diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38b98255a..a76f6cd17 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@ set(VERSION_REVISION "0")
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX})
-set(SDCARD_REVISION "0029")
+set(SDCARD_REVISION "0034")
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 4fcf98a29..95dc3e6a3 100644
--- a/CREDITS.txt
+++ b/CREDITS.txt
@@ -8,6 +8,7 @@ Romolo Manfredini (romoloman)
Martin Hotař (mhotar)
Maxim (Max) Paperno (mpaperno)
Arne Schwabe (schwabe)
+Daniel Gorbea (dgatf)
[Translators]
[fr] Sebastien Charpentier (LapinFou)
@@ -31,6 +32,7 @@ Michael Byrne
FlySky (monthly)
JumperRC (monthly)
RadioMaster (monthly)
+HappyModel (monthly)
Aloft Hobbies
Jonathan Modellismo
WsTech
@@ -1761,3 +1763,182 @@ 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
+Jim Cukla
+Lee Taylor
+Stefan Kuster
+Barry Wright
+Steven Gilley
+Lloyd Evans
+Nolan O'Hearne
+Jeffrey James N Buffie
+James Houck
+Andreas Arlt
+William Walker
+Salvador Munoz Vinas
+Chris Geiger Photography
+John F Smith
+Robert Zecha
+Fernando Martins
+Martin Brungard
+Paul Witko
+Michael Campbell
+Stuart Posnett
+PK Doddema
+Leonard MacKey
+Andrew Peterson
+Dominik Sedlacek
+Ronald Hellstern
+Vicente Suarez
+Patrick Geerts
+Rossi Giampaolo
+Jose Luis Franco Torres
+Bart Sillen
+Antonio Moreno
+Carolina Carcione
+Lonnie Misner
+John Eppling
+Phillip Elliott
+Robin Bayer
+Jurij Peternel
+George Aandahl
+Guy Dangerfield
+Thomas Limpert
+Ismael G Zapater
+Alan Hall
+Bradley Goodwin
+Paul Dittman
+John Johnson
+Liam Mahoney
+Joseph Carr
+Fiorenzo Agnelli
+Brian Ramsey
+Angelo Movio
+Weldon Parks
+Simon Brink
+Weldon Parks
+Ralf Herzenbruch
+Ashley Pearce
+SneakIT
+Soaring Stuff
+Jörg Lemnitz
+Johann Gross
+Mark Gibson
+Rendall Assoc
+Cozyn Holdings Pty Ltd
+Tim Karsten
+Nick Hesson
+Laurent Lapassade
+Peter Deacon
+Gilles Dando
+Philippe Desrichard
+Jón Haase
+Michael Hansen
+Sylvain Vanston
+Helmut Nemecek
+Alexander Mathis
+Jay Watkins
+Patrice Oudjaoudi
+Didier Hochedez
+Robert Hunter
+Christophe Gilsoul
+Lincoln Roberts
+Johan Jurriens
+Michael Ledward
+Dave Waldesbuehl
+Dale Rhoads
+Denis Kelly
+SBEurope LTD
+Jean-Louis Mouche
+Grant Mills
+Fernando Rimoldi
+Jim Cukla
+Tomas Kirnak
+Raymond Henderson
+James Jewitt
+Martin Sauter
+Philip Hawkey
+Lonnie Misner
+Michael Hirschauer
+Brian Bracken
+Stuart Olson
+Terry McKinley
+Miklos Turcsin
+Edward Skerness
+Stefano Perinetti
+Toni Marchante
diff --git a/cmake/FindFox.cmake b/cmake/FindFox.cmake
index 1100c710d..9d76b61b0 100644
--- a/cmake/FindFox.cmake
+++ b/cmake/FindFox.cmake
@@ -56,7 +56,7 @@ else()
set(FOX_LIBRARIES ${FOX_LIBRARY})
endif()
-find_package_handle_standard_args(FOX
+find_package_handle_standard_args(Fox
DEFAULT_MSG
FOX_INCLUDE_DIR
FOX_LIBRARY
diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt
index ca278494f..7e0b62da0 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)
@@ -239,7 +237,6 @@ set(companion_SRCS
flasheepromdialog.cpp
printdialog.cpp
modelprinter.cpp
- fusesdialog.cpp
logsdialog.cpp
downloaddialog.cpp
splashlibrarydialog.cpp
@@ -259,7 +256,6 @@ set(companion_MOC_HDRS
burnconfigdialog.h
comparedialog.h
printdialog.h
- fusesdialog.h
logsdialog.h
creditsdialog.h
releasenotesdialog.h
@@ -291,7 +287,6 @@ set(companion_MOC_HDRS
set(companion_UIS
mdichild.ui
comparedialog.ui
- fusesdialog.ui
logsdialog.ui
apppreferencesdialog.ui
fwpreferencesdialog.ui
@@ -356,6 +351,8 @@ 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()
@@ -406,7 +403,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()
@@ -552,14 +549,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/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 ce172fbb7..cddc2fa3e 100644
--- a/companion/src/companion.qrc
+++ b/companion/src/companion.qrc
@@ -190,6 +190,16 @@
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
diff --git a/companion/src/firmwares/CMakeLists.txt b/companion/src/firmwares/CMakeLists.txt
index 502a04961..1b99964fa 100644
--- a/companion/src/firmwares/CMakeLists.txt
+++ b/companion/src/firmwares/CMakeLists.txt
@@ -18,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/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 cfadf5936..5e0ceeb86 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)
@@ -82,16 +77,12 @@ 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:
@@ -104,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:
@@ -134,6 +118,7 @@ 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;
}
@@ -144,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:
@@ -172,6 +150,7 @@ 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:
@@ -310,7 +289,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 0;
case MouseAnalogs:
- if (IS_FAMILY_HORUS_OR_T16(board))
+ if (IS_HORUS_X12S(board))
return 2;
else
return 0;
@@ -412,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",
@@ -496,14 +475,6 @@ 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:
@@ -540,6 +511,8 @@ 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:
diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h
index e4149a298..2ecf3c2fe 100644
--- a/companion/src/firmwares/boards.h
+++ b/companion/src/firmwares/boards.h
@@ -32,10 +32,6 @@ namespace Board {
enum Type
{
BOARD_UNKNOWN = -1,
- BOARD_9X_M64 = 0,
- BOARD_9X_M128,
- BOARD_MEGA2560,
- BOARD_GRUVIN9X,
BOARD_SKY9X,
BOARD_9XRPRO,
BOARD_AR9X,
@@ -55,9 +51,10 @@ namespace Board {
BOARD_JUMPER_T12,
BOARD_JUMPER_T16,
BOARD_RADIOMASTER_TX16S,
+ BOARD_JUMPER_T18,
};
- constexpr int BOARD_TYPE_MAX = BOARD_RADIOMASTER_TX16S ;
+ constexpr int BOARD_TYPE_MAX = BOARD_JUMPER_T18;
enum PotType
{
@@ -191,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;
@@ -231,6 +208,11 @@ 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;
@@ -238,7 +220,7 @@ inline bool IS_RADIOMASTER_TX16S(Board::Type board)
inline bool IS_FAMILY_T16(Board::Type board)
{
- return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S;
+ return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S || board == Board::BOARD_JUMPER_T18;
}
inline bool IS_TARANIS_XLITE(Board::Type board)
@@ -346,7 +328,12 @@ 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 (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")));
diff --git a/companion/src/firmwares/customfunctiondata.cpp b/companion/src/firmwares/customfunctiondata.cpp
index 9313ace5a..42d84d570 100644
--- a/companion/src/firmwares/customfunctiondata.cpp
+++ b/companion/src/firmwares/customfunctiondata.cpp
@@ -46,7 +46,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32)
return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model));
else if (func == FuncTrainer)
- return tr("Trainer");
+ return tr("Trainer Sticks");
else if (func == FuncTrainerRUD)
return tr("Trainer RUD");
else if (func == FuncTrainerELE)
@@ -112,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);
@@ -132,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);
@@ -162,24 +159,24 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
if (func <= FuncInstantTrim) {
return QString("%1").arg(param);
}
- else if (func==FuncLogs) {
+ else if (func == FuncLogs) {
return QString("%1").arg(param/10.0) + tr("s");
}
- else if (func==FuncPlaySound) {
+ else if (func == FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs);
if (param>=0 && param<(int)qs.count())
return qs.at(param);
else
return tr("Inconsistent parameter");
}
- else if (func==FuncPlayHaptic) {
+ else if (func == FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs);
if (param>=0 && param<(int)qs.count())
return qs.at(param);
else
return tr("Inconsistent parameter");
}
- else if (func==FuncReset) {
+ else if (func == FuncReset) {
QComboBox cb;
CustomFunctionData::populateResetParams(model, &cb);
int pos = cb.findData(param);
@@ -188,11 +185,11 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
else
return tr("Inconsistent parameter");
}
- else if ((func==FuncVolume)|| (func==FuncPlayValue)) {
+ else if (func == FuncVolume || func == FuncPlayValue || func == FuncBacklight) {
RawSource item(param);
return item.toString(model);
}
- else if ((func==FuncPlayPrompt) || (func==FuncPlayBoth)) {
+ else if (func == FuncPlayPrompt || func == FuncPlayBoth) {
if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) {
return QString("%1").arg(param);
}
@@ -200,7 +197,7 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
return paramarm;
}
}
- else if ((func>=FuncAdjustGV1) && (func= FuncAdjustGV1 && func < FuncCount) {
switch (adjustMode) {
case FUNC_ADJUST_GVAR_CONSTANT:
return tr("Value ")+QString("%1").arg(param);
@@ -210,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);
}
}
@@ -233,18 +224,19 @@ 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);
}
}
QString CustomFunctionData::enabledToString() const
{
- if ((func>=FuncOverrideCH1 && func<=FuncOverrideCH32) ||
- (func>=FuncAdjustGV1 && func<=FuncAdjustGVLast) ||
- (func==FuncReset) ||
- (func>=FuncSetTimer1 && func<=FuncSetTimer2) ||
- (func==FuncVolume) ||
+ if ((func >= FuncOverrideCH1 && func <= FuncOverrideCH32) ||
+ (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) ||
+ (func == FuncReset) ||
+ (func >= FuncSetTimer1 && func <= FuncSetTimer2) ||
+ (func == FuncVolume) ||
+ (func == FuncBacklight) ||
(func <= FuncInstantTrim)) {
if (!enabled) {
return tr("DISABLED");
@@ -258,7 +250,7 @@ void CustomFunctionData::convert(RadioDataConversionState & cstate)
cstate.setComponent(tr("CFN"), 8);
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
swtch.convert(cstate);
- if (func == FuncVolume || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) {
+ if (func == FuncVolume || func == FuncBacklight || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) {
param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue();
}
}
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 c2bf0dafa..b3680b4ba 100644
--- a/companion/src/firmwares/eeprominterface.h
+++ b/companion/src/firmwares/eeprominterface.h
@@ -235,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 9c38391c7..f307dbf26 100644
--- a/companion/src/firmwares/generalsettings.cpp
+++ b/companion/src/firmwares/generalsettings.cpp
@@ -110,9 +110,7 @@ GeneralSettings::GeneralSettings()
backlightOffBright = 20;
}
- if (IS_ARM(board)) {
- speakerVolume = 12;
- }
+ speakerVolume = 12;
if (IS_JUMPER_T16(board))
strcpy(bluetoothName, "t16");
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/modeldata.cpp b/companion/src/firmwares/modeldata.cpp
index 3386ba41d..e38958249 100644
--- a/companion/src/firmwares/modeldata.cpp
+++ b/companion/src/firmwares/modeldata.cpp
@@ -43,6 +43,11 @@ 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*/);
}
+QString TimerData::nameToString(int index) const
+{
+ return RadioData::getElementName(tr("TMR", "as in Timer"), index + 1, name);
+}
+
/*
* ModelData
*/
@@ -207,36 +212,25 @@ bool ModelData::isEmpty() const
void ModelData::setDefaultInputs(const GeneralSettings & settings)
{
- Board::Type board = getCurrentBoard();
- if (IS_ARM(board)) {
- for (int i = 0; i < CPN_MAX_STICKS; i++) {
- ExpoData * expo = &expoData[i];
- expo->chn = i;
- expo->mode = INPUT_MODE_BOTH;
- expo->srcRaw = settings.getDefaultSource(i);
- expo->weight = 100;
- strncpy(inputNames[i], 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; i < CPN_MAX_STICKS; i++) {
MixData * mix = &mixData[i];
mix->destCh = i + 1;
mix->weight = 100;
- if (IS_ARM(board)) {
- mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i);
- }
- else {
- mix->srcRaw = RawSource(SOURCE_TYPE_STICK, i);
- }
+ mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i);
}
}
@@ -538,6 +532,8 @@ int ModelData::updateReference()
Firmware *fw = getCurrentFirmware();
+ updRefInfo.occurences = 1;
+
switch (updRefInfo.type)
{
case REF_UPD_TYPE_CHANNEL:
@@ -572,6 +568,7 @@ int ModelData::updateReference()
updRefInfo.srcType = SOURCE_TYPE_TELEMETRY;
updRefInfo.swtchType = SWITCH_TYPE_SENSOR;
updRefInfo.maxindex = fw->getCapability(Sensors);
+ updRefInfo.occurences = 3;
break;
case REF_UPD_TYPE_TIMER:
updRefInfo.srcType = SOURCE_TYPE_SPECIAL;
@@ -662,6 +659,8 @@ int ModelData::updateReference()
}
}
}
+ if (updRefInfo.type == REF_UPD_TYPE_CHANNEL)
+ sortMixes();
//s1.report("Mixes");
for (int i = 0; i < CPN_MAX_CHNOUT; i++) {
@@ -724,7 +723,7 @@ int ModelData::updateReference()
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))) {
+ if (cfd->func == FuncVolume || cfd->func == FuncBacklight || 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();
@@ -773,15 +772,35 @@ int ModelData::updateReference()
//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) {
+ if (!sd->isEmpty() && sd->type == SensorData::TELEM_TYPE_CALCULATED) {
+ if (sd->formula == SensorData::TELEM_FORMULA_CELL) {
+ updateTelemetryRef(sd->source);
+ if (sd->source == 0) {
+ sd->clear();
+ appendUpdateReferenceParams(REF_UPD_TYPE_SENSOR, REF_UPD_ACT_CLEAR, i);
+ }
+ }
+ else if (sd->formula == SensorData::TELEM_FORMULA_DIST) {
+ updateTelemetryRef(sd->gps);
+ updateTelemetryRef(sd->alt);
+ }
+ else if (sd->formula == SensorData::TELEM_FORMULA_CONSUMPTION || sd->formula == SensorData::TELEM_FORMULA_TOTALIZE) {
+ updateTelemetryRef(sd->amps);
+ if (sd->amps == 0) {
+ sd->clear();
+ appendUpdateReferenceParams(REF_UPD_TYPE_SENSOR, REF_UPD_ACT_CLEAR, i);
+ }
+ }
+ else {
+ for (unsigned int i = 0; i < 4; i++) {
+ updateTelemetryRef(sd->sources[i]);
+ }
+ }
}
}
- s1.report("Telemetry Sensors");
- */
+ //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
/*
@@ -817,38 +836,40 @@ void ModelData::updateTypeIndexRef(R & curRef, const T type, const int idxAdj, c
newRef.type = curRef.type;
newRef.index = abs(curRef.index);
+ div_t idx = div(newRef.index, updRefInfo.occurences);
+
switch (updRefInfo.action)
{
case REF_UPD_ACT_CLEAR:
- if (newRef.index != (updRefInfo.index1 + idxAdj))
+ if (idx.quot != (updRefInfo.index1 + idxAdj))
return;
if (defClear)
newRef.clear();
else {
newRef.type = (T)defType;
- newRef.index = defIndex;
+ newRef.index = defIndex + idxAdj;
}
break;
case REF_UPD_ACT_SHIFT:
- if (newRef.index < (updRefInfo.index1 + idxAdj))
+ if (idx.quot < (updRefInfo.index1 + idxAdj))
return;
newRef.index += updRefInfo.shift;
- if (newRef.index < (updRefInfo.index1 + idxAdj) || newRef.index > (updRefInfo.maxindex + idxAdj)) {
+ if (idx.quot < (updRefInfo.index1 + idxAdj) || idx.quot > (updRefInfo.maxindex + idxAdj)) {
if (defClear)
newRef.clear();
else {
newRef.type = (T)defType;
- newRef.index = defIndex;
+ newRef.index = defIndex + idxAdj;
}
}
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;
+ if (idx.quot == updRefInfo.index1 + idxAdj)
+ newRef.index = ((updRefInfo.index2 + idxAdj) * updRefInfo.occurences) + idx.rem;
+ else if (idx.quot == updRefInfo.index2 + idxAdj)
+ newRef.index = ((updRefInfo.index1 + idxAdj) * updRefInfo.occurences) + idx.rem;
break;
default:
qDebug() << "Error - unhandled action:" << updRefInfo.action;
@@ -883,7 +904,7 @@ void ModelData::updateTypeValueRef(R & curRef, const T type, const int idxAdj, c
newRef.clear();
else {
newRef.type = (T)defType;
- newRef.value = defValue;
+ newRef.value = defValue + idxAdj;
}
break;
case REF_UPD_ACT_SHIFT:
@@ -897,7 +918,7 @@ void ModelData::updateTypeValueRef(R & curRef, const T type, const int idxAdj, c
newRef.clear();
else {
newRef.type = (T)defType;
- newRef.value = defValue;
+ newRef.value = defValue + idxAdj;
}
}
break;
@@ -1126,13 +1147,14 @@ void ModelData::updateFlightModeFlags(unsigned int & curRef)
}
}
-void ModelData::updateTelemetryRef(unsigned int & curRef)
+void ModelData::updateTelemetryRef(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:
@@ -1160,13 +1182,23 @@ void ModelData::updateTelemetryRef(unsigned int & curRef)
return;
}
- if (curRef != static_cast(newRef)) {
+ if (curRef != newRef) {
//qDebug() << "Updated reference:" << curRef << " -> " << newRef;
curRef = newRef;
updRefInfo.updcnt++;
}
}
+void ModelData::updateTelemetryRef(unsigned int & curRef)
+{
+ int newRef = (int)curRef;
+ updateTelemetryRef(newRef);
+
+ if (curRef != static_cast(newRef)) {
+ curRef = (unsigned int)newRef;
+ }
+}
+
void ModelData::updateModuleFailsafes(ModuleData * md)
{
if (updRefInfo.type != REF_UPD_TYPE_CHANNEL)
@@ -1300,3 +1332,45 @@ 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();
}
+
+void ModelData::sortMixes()
+{
+ unsigned int lastchn = 0;
+ bool sortreq = false;
+
+ for (int i = 0; i < CPN_MAX_MIXERS; i++) {
+ MixData *md = &mixData[i];
+ if (!md->isEmpty()) {
+ if (md->destCh < lastchn) {
+ sortreq = true;
+ break;
+ }
+ else
+ lastchn = md->destCh;
+ }
+ }
+
+ if (!sortreq)
+ return;
+
+ // QMap automatically sorts based on key
+ QMap map;
+ for (int i = 0; i < CPN_MAX_MIXERS; i++) {
+ MixData *md = &mixData[i];
+ if (!md->isEmpty()) {
+ // destCh may not be unique so build a compound sort key
+ map.insert(md->destCh * (CPN_MAX_MIXERS + 1) + i, i);
+ }
+ }
+
+ MixData sortedMixData[CPN_MAX_MIXERS];
+ int destidx = 0;
+
+ QMap::const_iterator i;
+ for (i = map.constBegin(); i != map.constEnd(); ++i) {
+ memcpy(&sortedMixData[destidx], &mixData[i.value()], sizeof(MixData));
+ destidx++;
+ }
+
+ memcpy(&mixData[0], &sortedMixData[0], CPN_MAX_MIXERS * sizeof(MixData));
+}
diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h
index 93e98588e..0afc66b72 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;
@@ -78,6 +75,7 @@ class TimerData {
void convert(RadioDataConversionState & cstate);
bool isEmpty();
bool isModeOff() { return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
+ QString nameToString(int index) const;
};
#define CPN_MAX_SCRIPTS 9
@@ -184,6 +182,7 @@ class ModelData {
unsigned int thrTraceSrc;
uint64_t switchWarningStates;
unsigned int switchWarningEnable;
+ unsigned int thrTrimSwitch;
unsigned int potsWarningMode;
bool potsWarnEnabled[CPN_MAX_POTS];
int potsWarnPosition[CPN_MAX_POTS];
@@ -300,6 +299,7 @@ class ModelData {
int shift;
int updcnt;
int maxindex;
+ int occurences;
RawSourceType srcType;
RawSwitchType swtchType;
};
@@ -317,6 +317,7 @@ class ModelData {
void updateDestCh(MixData * md);
void updateLimitCurveRef(CurveReference & crv);
void updateFlightModeFlags(unsigned int & flags);
+ void updateTelemetryRef(int & idx);
void updateTelemetryRef(unsigned int & idx);
void updateModuleFailsafes(ModuleData * md);
inline void updateSourceRef(RawSource & src) { updateTypeIndexRef(src, updRefInfo.srcType); }
@@ -336,6 +337,7 @@ class ModelData {
if (value != swtch.toValue())
value = swtch.toValue();
}
+ void sortMixes();
};
#endif // MODELDATA_H
diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp
index 370a6979b..b36d88e04 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)
@@ -65,6 +66,7 @@ bool ModuleData::supportRxNum() const
case PULSES_PXX_R9M_LITE:
case PULSES_PXX_R9M_LITE_PRO:
case PULSES_MULTIMODULE:
+ case PULSES_CROSSFIRE:
case PULSES_ACCESS_ISRM:
case PULSES_ACCST_ISRM_D16:
case PULSES_ACCESS_R9M:
@@ -87,7 +89,6 @@ QString ModuleData::rfProtocolToString() const
switch (protocol) {
case PULSES_MULTIMODULE:
return Multiprotocols::protocolToString((int)multi.rfProtocol);
-
default:
return CPN_STR_UNKNOWN_ITEM;
}
@@ -108,10 +109,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 +120,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 +160,16 @@ 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",
+ "ImmersionRC Ghost"
};
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,12 +177,21 @@ 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
@@ -193,7 +205,8 @@ bool ModuleData::hasFailsafes(Firmware * fw) const
protocol == PULSES_ACCESS_R9M_LITE ||
protocol == PULSES_ACCESS_R9M_LITE_PRO ||
protocol == PULSES_XJT_LITE_X16 ||
- protocol == PULSES_MULTIMODULE
+ protocol == PULSES_MULTIMODULE ||
+ protocol == PULSES_AFHDS3
);
}
@@ -210,6 +223,7 @@ int ModuleData::getMaxChannelCount()
case PULSES_XJT_LITE_X16:
case PULSES_PXX_XJT_X16:
case PULSES_CROSSFIRE:
+ case PULSES_GHOST:
case PULSES_SBUS:
case PULSES_PPM:
return 16;
@@ -230,6 +244,8 @@ int ModuleData::getMaxChannelCount()
else
return 16;
break;
+ case PULSES_AFHDS3:
+ return 18;
case PULSES_OFF:
break;
default:
diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h
index 86614b392..e22c167e3 100644
--- a/companion/src/firmwares/moduledata.h
+++ b/companion/src/firmwares/moduledata.h
@@ -58,6 +58,8 @@ enum PulsesProtocol {
PULSES_XJT_LITE_X16,
PULSES_XJT_LITE_D8,
PULSES_XJT_LITE_LR12,
+ PULSES_AFHDS3,
+ PULSES_GHOST,
PULSES_PROTOCOL_LAST
};
@@ -190,6 +192,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
@@ -213,7 +220,7 @@ 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();
};
diff --git a/companion/src/firmwares/multiprotocols.cpp b/companion/src/firmwares/multiprotocols.cpp
index 737bd36ed..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")
@@ -41,8 +41,8 @@ static const QStringList STR_SUBTYPE_FLYSKY {"Standard", "V9x9", "V6x6", "V91
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", "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"};
@@ -71,6 +71,7 @@ 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"};
@@ -80,7 +81,7 @@ 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"};
+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"};
@@ -97,7 +98,7 @@ const Multiprotocols multiProtocols {
{MODULE_SUBTYPE_MULTI_HUBSAN, 2, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
{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},
@@ -130,6 +131,7 @@ const Multiprotocols multiProtocols {
{MODULE_SUBTYPE_MULTI_E01X, 2, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION},
{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},
@@ -140,7 +142,7 @@ const Multiprotocols multiProtocols {
{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, 3, false, STR_SUBTYPE_XN297DUMP, nullptr},
+ {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},
diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp
index 17c5b03a5..fcf0fc732 100644
--- a/companion/src/firmwares/opentx/opentxeeprom.cpp
+++ b/companion/src/firmwares/opentx/opentxeeprom.cpp
@@ -128,6 +128,14 @@ inline int SWITCHES_CONFIG_SIZE(Board::Type board, int version)
return 16;
}
+inline int MAX_MOUSE_ANALOG_SOURCES(Board::Type board, int version)
+{
+ if (IS_FAMILY_HORUS_OR_T16(board))
+ return 2;
+ else
+ return 0;
+}
+
#define MAX_ROTARY_ENCODERS(board) 0
#define MAX_FLIGHT_MODES(board, version) 9
#define MAX_TIMERS(board, version) 3
@@ -300,7 +308,7 @@ class SourcesConversionTable: public ConversionTable {
}
}
- for (int i=0; i= CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version))
offset += 2;
@@ -721,13 +729,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;
}
}
}
@@ -751,11 +753,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)
@@ -2113,6 +2111,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):
@@ -2173,8 +2205,10 @@ class ModuleUnionField: public UnionField {
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));
@@ -2387,7 +2421,8 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new UnsignedField<2>(this, modelData.potsWarningMode));
}
else {
- internalField.Append(new SpareBitsField<6>(this));
+ internalField.Append(new SpareBitsField<3>(this));
+ internalField.Append(new UnsignedField<3>(this, modelData.thrTrimSwitch));
internalField.Append(new UnsignedField<2>(this, modelData.potsWarningMode));
}
@@ -2543,7 +2578,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
generalData(generalData),
board(board),
version(version),
- inputsCount(CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version) + MAX_SLIDERS_STORAGE(board, version) + Boards::getCapability(board, Board::MouseAnalogs))
+ inputsCount(CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version) + MAX_SLIDERS_STORAGE(board, version) + MAX_MOUSE_ANALOG_SOURCES(board, version))
{
qCDebug(eepromImport) << QString("OpenTxGeneralData::OpenTxGeneralData(board: %1, version:%2, variant:%3)").arg(board).arg(version).arg(variant);
@@ -2581,7 +2616,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]));
diff --git a/companion/src/firmwares/opentx/opentxeeprom.h b/companion/src/firmwares/opentx/opentxeeprom.h
index ac1cf09dc..bb55b5687 100644
--- a/companion/src/firmwares/opentx/opentxeeprom.h
+++ b/companion/src/firmwares/opentx/opentxeeprom.h
@@ -37,9 +37,6 @@
#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);
@@ -99,7 +96,7 @@ class ProtocolsConversionTable: public ConversionTable
addConversion(PULSES_ACCESS_R9M, val++);
addConversion(PULSES_PXX_R9M_LITE, val++);
addConversion(PULSES_ACCESS_R9M_LITE, val++);
- addConversion(PULSES_PXX_R9M_LITE_PRO, val++);
+ addConversion(PULSES_GHOST, val++);
addConversion(PULSES_ACCESS_R9M_LITE_PRO, val++);
addConversion(PULSES_SBUS, val++);
@@ -107,6 +104,10 @@ 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 2fed78ab4..1d00c99ad 100644
--- a/companion/src/firmwares/opentx/opentxinterface.cpp
+++ b/companion/src/firmwares/opentx/opentxinterface.cpp
@@ -58,18 +58,12 @@ 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:
@@ -280,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)
@@ -325,10 +310,7 @@ 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)) {
@@ -445,43 +427,26 @@ int OpenTxFirmware::getCapability(::Capability capability)
case Models:
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_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:
@@ -493,7 +458,7 @@ 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:
@@ -501,66 +466,48 @@ int OpenTxFirmware::getCapability(::Capability capability)
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:
@@ -571,7 +518,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
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;
@@ -583,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:
@@ -593,29 +540,26 @@ int OpenTxFirmware::getCapability(::Capability capability)
case Simulation:
return 1;
case NumCurves:
- return (HAS_LARGE_LCD(board) ? 32 : (IS_ARM(board) ? 16 : 8));
+ return 32;
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_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:
@@ -627,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:
@@ -639,35 +583,35 @@ 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_FAMILY_HORUS_OR_T16(board))
return 480;
@@ -694,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:
@@ -715,17 +659,13 @@ 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;
@@ -744,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);
@@ -777,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)
@@ -793,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) && !IS_FAMILY_T16(board);
+ 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")) && !IS_FAMILY_T16(board);
- 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") || IS_RADIOMASTER_TX16S(board);
+ return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board) || IS_JUMPER_T18(board);
default:
return false;
}
@@ -823,9 +759,11 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
case PULSES_SBUS:
case PULSES_MULTIMODULE:
case PULSES_CROSSFIRE:
+ case PULSES_AFHDS3:
+ case PULSES_GHOST:
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_FAMILY_HORUS_OR_T16(board) && id.contains("internalaccess"));
+ return IS_ACCESS_RADIO(board, id);
case PULSES_PXX_R9M_LITE:
case PULSES_ACCESS_R9M_LITE:
case PULSES_ACCESS_R9M_LITE_PRO:
@@ -946,14 +884,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
@@ -973,21 +906,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;
}
@@ -1079,9 +998,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);
@@ -1184,19 +1100,25 @@ void addOpenTxCommonOptions(OpenTxFirmware * firmware)
enum RfOptions {
NONE = 0,
EU = 1 << 0,
- FLEX = 1 << 1
+ 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 (options == EU + 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 if (options == EU)
+ else if ((options & EU) != 0)
firmware->addOption(opt_eu);
- else if (options == FLEX)
+ else if ((options & FLEX) != 0)
firmware->addOption(opt_fl);
+ if ((options & AFHDS3) != 0)
+ firmware->addOption(opt_afhds3);
}
void addOpenTxFontOptions(OpenTxFirmware * firmware)
@@ -1245,7 +1167,7 @@ void registerOpenTxFirmwares()
firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
- addOpenTxRfOptions(firmware, EU + FLEX);
+ 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);
@@ -1259,7 +1181,7 @@ void registerOpenTxFirmwares()
firmware->addOption("haptic", Firmware::tr("Haptic module installed"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
- addOpenTxRfOptions(firmware, EU + FLEX);
+ addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3);
/* FrSky Taranis X9E board */
firmware = new OpenTxFirmware("opentx-x9e", Firmware::tr("FrSky Taranis X9E"), BOARD_TARANIS_X9E);
@@ -1267,19 +1189,19 @@ void registerOpenTxFirmwares()
firmware->addOption("horussticks", Firmware::tr("Horus gimbals installed (Hall sensors)"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
- addOpenTxRfOptions(firmware, EU + FLEX);
+ 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);
+ 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);
+ addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* FrSky X7 board */
firmware = new OpenTxFirmware("opentx-x7", Firmware::tr("FrSky Taranis X7 / X7S"), BOARD_TARANIS_X7);
@@ -1297,7 +1219,7 @@ void registerOpenTxFirmwares()
firmware = new OpenTxFirmware("opentx-xlites", Firmware::tr("FrSky Taranis X-Lite S/PRO"), BOARD_TARANIS_XLITES);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
- addOpenTxRfOptions(firmware, FLEX);
+ addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* FrSky X-Lite board */
firmware = new OpenTxFirmware("opentx-xlite", Firmware::tr("FrSky Taranis X-Lite"), BOARD_TARANIS_XLITE);
@@ -1336,7 +1258,7 @@ void registerOpenTxFirmwares()
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
- addOpenTxRfOptions(firmware, FLEX);
+ addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* Jumper T16 board */
firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16);
@@ -1347,7 +1269,7 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware);
/* Radiomaster TX16S board */
- firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16s / TX16s Hall / TX16s Masterfire"), BOARD_RADIOMASTER_TX16S);
+ firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16S / SE / Hall / Masterfire"), BOARD_RADIOMASTER_TX16S);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
static const Firmware::Option opt_bt("bluetooth", Firmware::tr("Support for bluetooth module"));
@@ -1355,6 +1277,13 @@ void registerOpenTxFirmwares()
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);
@@ -1372,14 +1301,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/rawsource.cpp b/companion/src/firmwares/rawsource.cpp
index 401eb9781..92377fe0a 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;
@@ -328,21 +140,6 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"),
};
- static const QString telemetry[] = {
- tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"),
- tr("RAS"), tr("RSSI Tx"), tr("RSSI Rx"),
- tr("A1"), tr("A2"), tr("A3"), tr("A4"),
- tr("Alt"), tr("Rpm"), tr("Fuel"), tr("T1"), tr("T2"),
- tr("Speed"), tr("Dist"), tr("GPS Alt"),
- tr("Cell"), tr("Cells"), tr("Vfas"), tr("Curr"), tr("Cnsp"), tr("Powr"),
- tr("AccX"), tr("AccY"), tr("AccZ"),
- tr("Hdg "), tr("VSpd"), tr("AirSpeed"), tr("dTE"),
- tr("A1-"), tr("A2-"), tr("A3-"), tr("A4-"),
- tr("Alt-"), tr("Alt+"), tr("Rpm+"), tr("T1+"), tr("T2+"), tr("Speed+"), tr("Dist+"), tr("AirSpeed+"),
- tr("Cell-"), tr("Cells-"), tr("Vfas-"), tr("Curr+"), tr("Powr+"),
- tr("ACC"), tr("GPS Time"),
- };
-
static const QString rotary[] = { tr("REa"), tr("REb") };
if (index<0) {
@@ -411,10 +208,22 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
return LimitData().nameToString(index);
case SOURCE_TYPE_SPECIAL:
- return CHECK_IN_ARRAY(special, index);
+ result = CHECK_IN_ARRAY(special, index);
+ // TODO refactor timers into own source type
+ if (result.startsWith("Timer")) {
+ bool ok;
+ int n = result.right(1).toInt(&ok);
+ if (ok) {
+ if (model)
+ result = model->timers[n - 1].nameToString(n - 1);
+ else
+ result = TimerData().nameToString(n - 1);
+ }
+ }
+ return result;
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 +233,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 +292,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 +316,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;
- }
}
}
@@ -555,111 +344,40 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
RadioDataConversionState::LogField oldData(index, toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType));
if (type == SOURCE_TYPE_STICK) {
- if (cstate.toBoard.getCapability(Board::Sliders)) {
- if (index >= cstate.fromBoard.getCapability(Board::Sticks) + cstate.fromBoard.getCapability(Board::Pots)) {
- // 1st slider alignment
- index += cstate.toBoard.getCapability(Board::Pots) - cstate.fromBoard.getCapability(Board::Pots);
- }
-
- if (isSlider(0, cstate.fromType)) {
- // LS and RS sliders are after 2 aux sliders on X12 and X9E
- if ((IS_HORUS_X12S(cstate.toType) || IS_TARANIS_X9E(cstate.toType)) && !IS_HORUS_X12S(cstate.fromType) && !IS_TARANIS_X9E(cstate.fromType)) {
- if (index >= 7) {
- index += 2; // LS/RS to LS/RS
- }
- }
- else if (!IS_TARANIS_X9E(cstate.toType) && !IS_HORUS_X12S(cstate.toType) && (IS_HORUS_X12S(cstate.fromType) || IS_TARANIS_X9E(cstate.fromType))) {
- if (index >= 7 && index <= 8) {
- index += 2; // aux sliders to spare analogs (which may not exist, this is validated later)
- evt = RadioDataConversionState::EVT_CVRT;
- }
- else if (index >= 9 && index <= 10) {
- index -= 2; // LS/RS to LS/RS
- }
- }
- }
- }
-
- if (IS_TARANIS(cstate.toType) && IS_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_FAMILY_HORUS_OR_T16(cstate.toType) && IS_TARANIS(cstate.fromType) && index == 5)
- {
- index = 6; // pot S2 to S2
- }
-
- } // SOURCE_TYPE_STICK
+ QStringList fromStickList(getStickList(cstate.fromBoard));
+ QStringList toStickList(getStickList(cstate.toBoard));
+ index = toStickList.indexOf(fromStickList.at(oldData.id));
+ // index set to -1 if no match found
+ // perform forced mapping
+ }
if (type == SOURCE_TYPE_SWITCH) {
- // SWI to SWR don't exist on !X9E board
- if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) {
- if (index >= 8) {
- index = index % 8;
- evt = RadioDataConversionState::EVT_CVRT;
+ QStringList fromSwitchList(getSwitchList(cstate.fromBoard));
+ QStringList toSwitchList(getSwitchList(cstate.toBoard));
+ index = toSwitchList.indexOf(fromSwitchList.at(oldData.id));
+ // index set to -1 if no match found
+ // perform forced mapping
+ if (index < 0) {
+ 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
+ index = toSwitchList.indexOf("SD");
+ if (index >= 0)
+ evt = RadioDataConversionState::EVT_CVRT;
+ }
+ 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
+ index = toSwitchList.indexOf("SD");
+ if (index >= 0)
+ evt = RadioDataConversionState::EVT_CVRT;
}
}
-
- 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
- evt = RadioDataConversionState::EVT_CVRT;
- }
- else if (index == 5) {
- index = 4; // SF to SF
- }
- else if (index == 7) {
- index = 5; // SH to SH
- }
- }
- 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
- evt = RadioDataConversionState::EVT_CVRT;
- }
- else if (index == 5) {
- index = 4; // SF to SF
- }
- else if (index == 7) {
- index = 5; // SH to SH
- }
- }
- // Compensate for SE and SG on X9/Horus board if converting from X7
- else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) {
- if (index == 4) {
- index = 5; // SF to SF
- }
- else if (index == 5) {
- index = 7; // SH to SH
- }
- }
- 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
- }
- else if (index == 5) {
- index = 7; // SH to SH
- }
- }
- 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
- }
- else if (index == 5) {
- index = 7; // SH to SH
- }
- }
- } // SOURCE_TYPE_SWITCH
+ }
// final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted)
- if (!isAvailable(NULL, cstate.toGS(), cstate.toType)) {
+ if (index < 0 || !isAvailable(NULL, cstate.toGS(), cstate.toType)) {
cstate.setInvalid(oldData);
- index = -1; // TODO: better way to flag invalid sources?
- type = MAX_SOURCE_TYPE;
+ // no source is safer than an invalid one
+ clear();
}
else if (evt == RadioDataConversionState::EVT_CVRT) {
cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toModel(), cstate.toGS(), cstate.toType)));
@@ -671,3 +389,24 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
return *this;
}
+
+QStringList RawSource::getStickList(Boards board) const
+{
+ QStringList ret;
+
+ for (int i = 0; i < board.getCapability(Board::MaxAnalogs); i++) {
+ ret.append(board.getAnalogInputName(i));
+ }
+ return ret;
+}
+
+QStringList RawSource::getSwitchList(Boards board) const
+{
+ QStringList ret;
+
+ for (int i = 0; i < board.getCapability(Board::Switches); i++) {
+ ret.append(board.getSwitchInfo(i).name);
+ }
+ return ret;
+}
+
diff --git a/companion/src/firmwares/rawsource.h b/companion/src/firmwares/rawsource.h
index f59ab70f5..9d0b19450 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,
@@ -256,6 +252,8 @@ class RawSource {
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; }
+ QStringList getStickList(Boards board) const;
+ QStringList getSwitchList(Boards board) const;
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 a689ceea7..8c1685a25 100644
--- a/companion/src/firmwares/rawswitch.cpp
+++ b/companion/src/firmwares/rawswitch.cpp
@@ -184,77 +184,39 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
RadioDataConversionState::EventType evt = RadioDataConversionState::EVT_NONE;
RadioDataConversionState::LogField oldData(index, toString(cstate.fromType, cstate.fromGS(), cstate.fromModel()));
+ int newIdx = 0;
+
if (type == SWITCH_TYPE_SWITCH) {
- int srcIdx = div(abs(index)-1, 3).quot; // raw source index
- int delta = 0;
-
- // SWI to SWR don't exist on !X9E board
- if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) {
- if (srcIdx > 7) {
- index %= 24;
- evt = RadioDataConversionState::EVT_CVRT;
- }
- }
-
- // No SE and SG on X7 board
- 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)
+ div_t swtch = div(abs(index) - 1, 3); // rawsource index
+ QStringList fromSwitchList(getSwitchList(cstate.fromBoard));
+ QStringList toSwitchList(getSwitchList(cstate.toBoard));
+ // set to -1 if no match found
+ newIdx = toSwitchList.indexOf(fromSwitchList.at(swtch.quot));
+ // perform forced mapping
+ if (newIdx < 0) {
+ 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
+ newIdx = toSwitchList.indexOf("SD");
+ if (newIdx >= 0)
evt = RadioDataConversionState::EVT_CVRT;
}
- else if (srcIdx == 6) {
- delta = 9; // SG to SD
- evt = RadioDataConversionState::EVT_CVRT;
- }
- else if (srcIdx == 7) {
- delta = 6; // SH to SH
- }
- }
- 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)
+ 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
+ newIdx = toSwitchList.indexOf("SD");
+ if (newIdx >= 0)
evt = RadioDataConversionState::EVT_CVRT;
}
- else if (srcIdx == 6) {
- delta = 9; // SG to SD
- evt = RadioDataConversionState::EVT_CVRT;
- }
- else if (srcIdx == 7) {
- delta = 6; // SH to SH
- }
- }
- // Compensate for SE and SG on X9/Horus board if converting from X7
- 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
- }
- else if (srcIdx == 5) {
- delta = -6; // SH to SH
- }
- }
- 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
- }
- else if (srcIdx == 5) {
- delta = -6; // SH to SH
- }
}
- if (index < 0) {
- delta = -delta; // invert for !switch
- }
-
- index -= delta;
-
+ if (newIdx >= 0)
+ index = (newIdx * 3 + 1 + swtch.rem) * (index < 0 ? -1 : 1);
} // SWITCH_TYPE_SWITCH
// final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted)
- if (!isAvailable(NULL, cstate.toGS(), cstate.toType)) {
+ if (newIdx < 0 || !isAvailable(NULL, cstate.toGS(), cstate.toType)) {
cstate.setInvalid(oldData);
- type = MAX_SWITCH_TYPE; // TODO: better way to flag invalid switches?
+ // no switch is safer than an invalid one
+ clear();
}
else if (evt == RadioDataConversionState::EVT_CVRT) {
cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toType, cstate.toGS(), cstate.toModel())));
@@ -266,3 +228,13 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
return *this;
}
+
+QStringList RawSwitch::getSwitchList(Boards board) const
+{
+ QStringList ret;
+
+ for (int i = 0; i < board.getCapability(Board::Switches); i++) {
+ ret.append(board.getSwitchInfo(i).name);
+ }
+ return ret;
+}
diff --git a/companion/src/firmwares/rawswitch.h b/companion/src/firmwares/rawswitch.h
index d79ac0aa6..7c0707a6a 100644
--- a/companion/src/firmwares/rawswitch.h
+++ b/companion/src/firmwares/rawswitch.h
@@ -89,6 +89,7 @@ class RawSwitch {
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; }
+ QStringList getSwitchList(Boards board) const;
bool operator== ( const RawSwitch& other) const {
return (this->type == other.type) && (this->index == other.index);
diff --git a/companion/src/firmwares/sensordata.cpp b/companion/src/firmwares/sensordata.cpp
index 0a7e7eada..a9b8d7640 100644
--- a/companion/src/firmwares/sensordata.cpp
+++ b/companion/src/firmwares/sensordata.cpp
@@ -84,6 +84,12 @@ QString SensorData::unitString() const
return tr("V");
case UNIT_MILLILITERS_PER_MINUTE:
return tr("ml/minute");
+ case UNIT_HERZ:
+ return tr("Hertz");
+ case UNIT_MS:
+ return tr("mS");
+ case UNIT_US:
+ return tr("uS");
default:
return "";
}
@@ -98,7 +104,7 @@ QString SensorData::getOrigin(const ModelData * model) const
{
if (type != TELEM_TYPE_CUSTOM || !id)
return QString();
-
+
const ModuleData & module = model->moduleData[moduleIdx];
if (module.isPxx2Module() && rxIdx <= 2 && module.access.receivers & (1 << rxIdx)) {
return QString(module.access.receiverName[rxIdx]);
@@ -107,3 +113,8 @@ QString SensorData::getOrigin(const ModelData * model) const
return QString();
}
}
+
+bool SensorData::isEmpty() const
+{
+ return (!isAvailable() && type == 0 && id == 0 && subid == 0 && instance == 0 && rxIdx == 0 && moduleIdx == 0 && unit == 0 && ratio == 0 && prec == 0 && offset == 0 && autoOffset == 0 && filter == 0 && onlyPositive == 0 && logs == 0);
+}
diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h
index 3f995ea3e..a2b993bcc 100644
--- a/companion/src/firmwares/sensordata.h
+++ b/companion/src/firmwares/sensordata.h
@@ -24,6 +24,7 @@
#include
constexpr int CPN_MAX_SENSORS = 60;
+constexpr int SENSOR_LABEL_LEN = 4;
class ModelData;
@@ -94,10 +95,10 @@ class SensorData {
UNIT_MILLILITERS,
UNIT_FLOZ,
UNIT_MILLILITERS_PER_MINUTE,
- UNIT_MAX = UNIT_MILLILITERS_PER_MINUTE,
- UNIT_SPARE1,
- UNIT_SPARE2,
- UNIT_SPARE3,
+ UNIT_HERZ,
+ UNIT_MS,
+ UNIT_US,
+ UNIT_MAX = UNIT_US,
UNIT_SPARE4,
UNIT_SPARE5,
UNIT_SPARE6,
@@ -133,7 +134,7 @@ class SensorData {
unsigned int moduleIdx;
unsigned int persistentValue;
unsigned int formula;
- char label[4+1];
+ char label[SENSOR_LABEL_LEN + 1];
unsigned int unit;
unsigned int prec;
bool autoOffset;
@@ -166,6 +167,7 @@ class SensorData {
QString nameToString(int index) const;
QString getOrigin(const ModelData* model) const;
void clear() { memset(this, 0, sizeof(SensorData)); }
+ bool isEmpty() const;
};
#endif // SENSORDATA_H
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 4650cd4c0..fc45a89ff 100644
--- a/companion/src/flashfirmwaredialog.cpp
+++ b/companion/src/flashfirmwaredialog.cpp
@@ -275,11 +275,12 @@ void FlashFirmwareDialog::startFlash(const QString &filename)
ProgressDialog progressDialog(this, tr("Write Firmware to Radio"), CompanionIcon("write_flash.png"));
// check hardware compatibility if requested
+ bool checkPassed = true;
if (g.checkHardwareCompatibility()) {
QString tempFirmware = generateProcessUniqueTempFileName("flash-check.bin");
if (!readFirmware(tempFirmware, progressDialog.progress())) {
QMessageBox::warning(this, tr("Firmware check failed"), tr("Could not check firmware from radio"));
- return;
+ checkPassed = false;
}
FirmwareInterface previousFirmware(tempFirmware);
qunlink(tempFirmware);
@@ -291,41 +292,44 @@ void FlashFirmwareDialog::startFlash(const QString &filename)
qDebug() << "startFlash: removing temporary file" << filename;
qunlink(filename);
}
- return;
+ checkPassed = false;
}
}
- // backup if requested
- bool result = true;
- QString backupFilename;
- QString backupPath;
- if (backup) {
- backupPath = g.profile[g.id()].pBackupDir();
- if (backupPath.isEmpty()) {
- backupPath=g.backupDir();
+ if (checkPassed) {
+ // backup if requested
+ bool result = true;
+ QString backupFilename;
+ QString backupPath;
+ if (backup) {
+ backupPath = g.profile[g.id()].pBackupDir();
+ if (backupPath.isEmpty()) {
+ backupPath=g.backupDir();
+ }
+ backupFilename = backupPath + "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin";
+ result = readEeprom(backupFilename, progressDialog.progress());
+ sleep(2);
}
- backupFilename = backupPath + "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin";
- result = readEeprom(backupFilename, progressDialog.progress());
- sleep(2);
+
+ // flash
+ result = (result && writeFirmware(filename, progressDialog.progress()));
+
+ // restore if backup requested
+ if (backup && result) {
+ sleep(2);
+ QString restoreFilename = generateProcessUniqueTempFileName("restore.bin");
+ if (!convertEEprom(backupFilename, restoreFilename, filename)) {
+ QMessageBox::warning(this, tr("Conversion failed"), tr("Cannot convert Models and Settings for use with this firmware, original data will be used"));
+ restoreFilename = backupFilename;
+ }
+ if (!writeEeprom(restoreFilename, progressDialog.progress())) {
+ QMessageBox::warning(this, tr("Restore failed"), tr("Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1").arg(backupFilename));
+ }
+ }
+
+ progressDialog.progress()->setInfo(tr("Flashing done"));
}
-
- // flash
- result = (result && writeFirmware(filename, progressDialog.progress()));
-
- // restore if backup requested
- if (backup && result) {
- sleep(2);
- QString restoreFilename = generateProcessUniqueTempFileName("restore.bin");
- if (!convertEEprom(backupFilename, restoreFilename, filename)) {
- QMessageBox::warning(this, tr("Conversion failed"), tr("Cannot convert Models and Settings for use with this firmware, original data will be used"));
- restoreFilename = backupFilename;
- }
- if (!writeEeprom(restoreFilename, progressDialog.progress())) {
- QMessageBox::warning(this, tr("Restore failed"), tr("Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1").arg(backupFilename));
- }
- }
-
- progressDialog.progress()->setInfo(tr("Flashing done"));
+
progressDialog.exec();
if (isTempFileName(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 1f74e2734..5404a8ccb 100644
--- a/companion/src/generaledit/generalsetup.cpp
+++ b/companion/src/generaledit/generalsetup.cpp
@@ -158,7 +158,7 @@ ui(new Ui::GeneralSetup)
ui->usbModeLabel->hide();
ui->usbModeCB->hide();
}
-
+
if (firmware->getCapability(HasSwitchableJack)) {
ui->jackModeCB->setCurrentIndex(generalSettings.jackMode);
}
@@ -197,6 +197,12 @@ ui(new Ui::GeneralSetup)
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,12 +240,7 @@ 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_FAMILY_HORUS_OR_T16(firmware->getBoard())) {
ui->splashScreenChkB->hide();
@@ -265,7 +266,7 @@ ui(new Ui::GeneralSetup)
ui->pwrOnDelayLabel->hide();
ui->pwrOnDelay->hide();
}
-
+
setValues();
lock = false;
@@ -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)) {
@@ -510,13 +505,13 @@ void GeneralSetupPanel::on_splashScreenDuration_currentIndexChanged(int index)
emit modified();
}
-void GeneralSetupPanel::on_pwrOnDelay_valueChanged()
+void GeneralSetupPanel::on_pwrOnDelay_valueChanged(int)
{
generalSettings.pwrOnSpeed = 2 - ui->pwrOnDelay->value();
emit modified();
}
-void GeneralSetupPanel::on_pwrOffDelay_valueChanged()
+void GeneralSetupPanel::on_pwrOffDelay_valueChanged(int)
{
generalSettings.pwrOffSpeed = 2 - ui->pwrOffDelay->value();
emit modified();
@@ -655,7 +650,7 @@ void GeneralSetupPanel::on_backlightautoSB_editingFinished()
}
}
-void GeneralSetupPanel::on_switchesDelay_valueChanged()
+void GeneralSetupPanel::on_switchesDelay_valueChanged(int)
{
generalSettings.switchesDelay = (ui->switchesDelay->value() / 10) - 15;
emit modified();
diff --git a/companion/src/generaledit/generalsetup.h b/companion/src/generaledit/generalsetup.h
index 34aeaaa71..43e098aee 100644
--- a/companion/src/generaledit/generalsetup.h
+++ b/companion/src/generaledit/generalsetup.h
@@ -65,7 +65,7 @@ class GeneralSetupPanel : public GeneralPanel
void on_mavbaud_CB_currentIndexChanged(int index);
void on_voiceLang_CB_currentIndexChanged(int index);
void stickReverseEdited();
- void on_switchesDelay_valueChanged();
+ void on_switchesDelay_valueChanged(int);
void on_blAlarm_ChkB_stateChanged();
void unlockSwitchEdited();
void on_beepVolume_SL_valueChanged();
@@ -89,8 +89,8 @@ class GeneralSetupPanel : public GeneralPanel
void on_contrastSB_editingFinished();
void on_registrationId_editingFinished();
- void on_pwrOnDelay_valueChanged();
- void on_pwrOffDelay_valueChanged();
+ void on_pwrOnDelay_valueChanged(int);
+ void on_pwrOffDelay_valueChanged(int);
private:
Ui::GeneralSetup *ui;
diff --git a/companion/src/generaledit/generalsetup.ui b/companion/src/generaledit/generalsetup.ui
index 98f9e76dd..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
- -
-
-
- nnnnnnNN
+
-
+
+
+ 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 4f530aa78..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_FAMILY_HORUS_OR_T16(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);
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/mainwindow.cpp b/companion/src/mainwindow.cpp
index 4753e0b71..9d490da39 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"
@@ -131,15 +130,9 @@ MainWindow::MainWindow():
else {
if (!g.previousVersion().isEmpty())
g.warningId(g.warningId() | AppMessages::MSG_UPGRADED);
+
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);
+ chooseProfile();
}
}
QTimer::singleShot(updateDelay, this, SLOT(displayWarnings()));
@@ -185,6 +178,11 @@ MainWindow::MainWindow():
if (printing) {
QTimer::singleShot(0, this, SLOT(autoClose()));
}
+
+ if (checkProfileRadioExists(g.sessionId()))
+ QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates()));
+ else
+ g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
}
MainWindow::~MainWindow()
@@ -939,10 +937,8 @@ void MainWindow::readEeprom()
QString tempFile;
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;
@@ -1029,14 +1025,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()
@@ -1065,7 +1053,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"));
@@ -1232,8 +1220,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"));
@@ -1295,7 +1281,6 @@ 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()));
@@ -1400,10 +1385,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);
@@ -1823,10 +1804,8 @@ void MainWindow::chooseProfile()
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
+
+ if (!checkProfileRadioExists(g.sessionId()))
g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
}
}
diff --git a/companion/src/mainwindow.h b/companion/src/mainwindow.h
index 9369dacac..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();
@@ -210,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/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 450f785fd..6442cc2fb 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 {
@@ -349,8 +349,11 @@ void Channels::cmCopy()
void Channels::cmCut()
{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
cmCopy();
- cmClear();
+ cmClear(false);
}
void Channels::onCustomContextMenuRequested(QPoint pos)
@@ -412,10 +415,12 @@ void Channels::cmMoveDown()
swapData(selectedIndex, selectedIndex + 1);
}
-void Channels::cmClear()
+void Channels::cmClear(bool prompt)
{
- if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
- return;
+ if (prompt) {
+ 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);
diff --git a/companion/src/modeledit/channels.h b/companion/src/modeledit/channels.h
index caa0fca38..d20923a35 100644
--- a/companion/src/modeledit/channels.h
+++ b/companion/src/modeledit/channels.h
@@ -75,7 +75,7 @@ class Channels : public ModelPanel
void cmMoveUp();
void cmMoveDown();
void cmInsert();
- void cmClear();
+ void cmClear(bool prompt = true);
void cmClearAll();
void onCustomContextMenuRequested(QPoint pos);
diff --git a/companion/src/modeledit/curves.cpp b/companion/src/modeledit/curves.cpp
index 5759e60e6..662dc61c4 100644
--- a/companion/src/modeledit/curves.cpp
+++ b/companion/src/modeledit/curves.cpp
@@ -699,10 +699,12 @@ bool Curves::moveUpAllowed() const
return selectedIndex > 0;
}
-void Curves::cmClear()
+void Curves::cmClear(bool prompt)
{
- if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
- return;
+ if (prompt) {
+ 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);
@@ -734,8 +736,10 @@ void Curves::cmCopy()
void Curves::cmCut()
{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
cmCopy();
- cmClear();
+ cmClear(false);
}
void Curves::cmDelete()
diff --git a/companion/src/modeledit/curves.h b/companion/src/modeledit/curves.h
index d9a5364a6..34d1a675e 100644
--- a/companion/src/modeledit/curves.h
+++ b/companion/src/modeledit/curves.h
@@ -81,7 +81,7 @@ class Curves : public ModelPanel
void onPointSizeEdited();
void onNodeDelete();
void onCustomContextMenuRequested(QPoint pos);
- void cmClear();
+ void cmClear(bool prompt = true);
void cmClearAll();
void cmCopy();
void cmCut();
diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp
index 34f05a707..36dba9c97 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++;
@@ -422,29 +422,20 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
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 {
@@ -471,7 +462,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
else if (func >= FuncSetFailsafeInternalModule && func <= FuncBindExternalModule) {
widgetsMask |= CUSTOM_FUNCTION_ENABLE;
}
- else if (func == FuncVolume) {
+ else if (func == FuncVolume || func == FuncBacklight) {
if (modified)
cfn.param = fswtchParamT[i]->currentData().toInt();
populateFuncParamCB(fswtchParamT[i], func, cfn.param);
@@ -563,12 +554,6 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
}
Helpers::populateFileComboBox(fswtchParamArmT[i], scriptsSet, cfn.paramarm);
}
- else if (func == FuncBacklight && IS_TARANIS_PLUS(getCurrentBoard())) {
- if (modified)
- cfn.param = (uint8_t)fswtchBLcolor[i]->value();
- fswtchBLcolor[i]->setValue(cfn.param);
- widgetsMask |= CUSTOM_FUNCTION_BL_COLOR;
- }
else {
if (modified)
cfn.param = fswtchParam[i]->value();
@@ -602,7 +587,7 @@ void CustomFunctionsPanel::update()
{
updateDataModels();
lock = true;
- for (int i=0; iclear();
- for (unsigned int i=0; i=FuncOverrideCH1 && i<=FuncOverrideCH32) && (!model || !firmware->getCapability(SafetyChannelCustomFunction))) ||
((i==FuncVolume || i==FuncBackgroundMusic || i==FuncBackgroundMusicPause) && !firmware->getCapability(HasVolume)) ||
((i==FuncPlayScript && !IS_HORUS_OR_TARANIS(firmware->getBoard()))) ||
((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))) ||
@@ -691,7 +677,7 @@ void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value)
else {
b->addItem(CustomFunctionData(AssignFunc(i)).funcToString(model), i);
if (i == value) {
- b->setCurrentIndex(b->count()-1);
+ b->setCurrentIndex(b->count() - 1);
}
}
}
@@ -711,28 +697,28 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi
{
QStringList qs;
b->setModel(new QStandardItemModel(b)); // clear combo box but not any shared item model
- if (function==FuncPlaySound) {
+ if (function == FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs);
b->addItems(qs);
b->setCurrentIndex(value);
}
- else if (function==FuncPlayHaptic) {
+ else if (function == FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs);
b->addItems(qs);
b->setCurrentIndex(value);
}
- else if (function==FuncReset) {
+ else if (function == FuncReset) {
CustomFunctionData::populateResetParams(model, b, value);
}
- else if (function==FuncVolume) {
+ else if (function == FuncVolume || function == FuncBacklight) {
b->setModel(rawSrcInputsItemModel);
b->setCurrentIndex(b->findData(value));
}
- else if (function==FuncPlayValue) {
+ else if (function == FuncPlayValue) {
b->setModel(rawSrcAllItemModel);
b->setCurrentIndex(b->findData(value));
}
- else if (function>=FuncAdjustGV1 && function<=FuncAdjustGVLast) {
+ else if (function >= FuncAdjustGV1 && function <= FuncAdjustGVLast) {
switch (adjustmode) {
case 1:
b->setModel(rawSrcInputsItemModel);
@@ -759,10 +745,12 @@ void CustomFunctionsPanel::cmMoveDown()
swapData(selectedIndex, selectedIndex + 1);
}
-void CustomFunctionsPanel::cmClear()
+void CustomFunctionsPanel::cmClear(bool prompt)
{
- if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Special Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
- return;
+ if (prompt) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+ }
functions[selectedIndex].clear();
resetCBsAndRefresh(selectedIndex);
@@ -771,10 +759,10 @@ void CustomFunctionsPanel::cmClear()
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)
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Functions. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
- for (int i=0; icurves[fswCapability - 1].isEmpty()));
+ return ((selectedIndex < fswCapability - 1) && (functions[fswCapability - 1].isEmpty()));
}
bool CustomFunctionsPanel::moveDownAllowed() const
diff --git a/companion/src/modeledit/customfunctions.h b/companion/src/modeledit/customfunctions.h
index 1c93f3e96..54a83ddcf 100644
--- a/companion/src/modeledit/customfunctions.h
+++ b/companion/src/modeledit/customfunctions.h
@@ -82,7 +82,7 @@ class CustomFunctionsPanel : public GenericPanel
void cmMoveUp();
void cmMoveDown();
void cmInsert();
- void cmClear();
+ void cmClear(bool prompt = true);
void cmClearAll();
private:
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/flightmodes.cpp b/companion/src/modeledit/flightmodes.cpp
index 1634aed3a..12082091d 100644
--- a/companion/src/modeledit/flightmodes.cpp
+++ b/companion/src/modeledit/flightmodes.cpp
@@ -708,10 +708,12 @@ bool FlightModePanel::moveUpAllowed() const
return phaseIdx > 0;
}
-void FlightModePanel::cmClear()
+void FlightModePanel::cmClear(bool prompt)
{
- if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
- return;
+ if (prompt) {
+ 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);
@@ -780,8 +782,10 @@ void FlightModePanel::cmCopy()
void FlightModePanel::cmCut()
{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
cmCopy();
- cmClear();
+ cmClear(false);
}
void FlightModePanel::cmDelete()
@@ -1059,7 +1063,7 @@ void FlightModePanel::gvOnCustomContextMenuRequested(QPoint pos)
bool FlightModePanel::gvHasClipboardData() const
{
- if (gvHasDefnClipboardData() || gvHasValueClipboardData())
+ if ((phaseIdx == 0 && gvHasDefnClipboardData() && gvHasAllValuesClipboardData()) || (phaseIdx > 0 && gvHasValueClipboardData()))
return true;
return false;
}
@@ -1092,6 +1096,20 @@ bool FlightModePanel::gvHasValueClipboardData(QByteArray * data) const
return false;
}
+bool FlightModePanel::gvHasAllValuesClipboardData(QByteArray * data) const
+{
+ const QClipboard * clipboard = QApplication::clipboard();
+ const QMimeData * mimeData = clipboard->mimeData();
+ if (phaseIdx == 0 && mimeData->hasFormat(MIMETYPE_GVAR_ALL_VALUES)) {
+ if (data) {
+ data->clear();
+ data->append(mimeData->data(MIMETYPE_GVAR_ALL_VALUES));
+ }
+ return true;
+ }
+ return false;
+}
+
bool FlightModePanel::gvDeleteAllowed() const
{
return phaseIdx == 0;
@@ -1124,11 +1142,13 @@ bool FlightModePanel::gvMoveUpAllowed() const
return (phaseIdx == 0 && gvIdx > 0);
}
-void FlightModePanel::gvCmClear()
+void FlightModePanel::gvCmClear(bool prompt)
{
if (phaseIdx == 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;
+ if (prompt) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear 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);
@@ -1136,6 +1156,10 @@ void FlightModePanel::gvCmClear()
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, gvIdx);
}
else {
+ if (prompt) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+ }
phase.gvars[gvIdx] = phase.linkedGVarFlightModeZero(phaseIdx);
}
emit datachanged();
@@ -1173,38 +1197,58 @@ void FlightModePanel::gvCmCopy()
if (phaseIdx == 0) {
data.append((char*)&model->gvarData[gvIdx], sizeof(GVarData));
mimeData->setData(MIMETYPE_GVAR_PARAMS, data);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+
+ data.clear();
+ for (int j = 0; j < fmCount; j++) {
+ data.append((char*)&model->flightModeData[j].gvars[gvIdx], sizeof(phase.gvars[0]));
+ }
+ mimeData->setData(MIMETYPE_GVAR_ALL_VALUES, data);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+
+ mimeData->removeFormat(MIMETYPE_GVAR_VALUE);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
}
else {
mimeData->removeFormat(MIMETYPE_GVAR_PARAMS);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+
+ mimeData->removeFormat(MIMETYPE_GVAR_ALL_VALUES);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+
+ data.clear();
+ 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);
}
- 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();
+ if (phaseIdx == 0) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
}
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();
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
}
+
+ gvCmCopy();
+ gvCmClear(false);
}
void FlightModePanel::gvCmDelete()
{
if (phaseIdx > 0)
return;
+
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
int maxidx = gvCount - 1;
for (int i = gvIdx; i < maxidx; i++) {
memcpy(&model->gvarData[i], &model->gvarData[i + 1], sizeof(GVarData));
@@ -1254,11 +1298,20 @@ void FlightModePanel::gvCmMoveUp()
void FlightModePanel::gvCmPaste()
{
QByteArray data;
- if (phaseIdx == 0 && gvHasDefnClipboardData(&data)) {
- GVarData *gvd = &model->gvarData[gvIdx];
- memcpy(gvd, data.constData(), sizeof(GVarData));
+ if (phaseIdx == 0) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Paste to selected Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+ if (gvHasDefnClipboardData(&data)) {
+ memcpy(&model->gvarData[gvIdx], data.constData(), sizeof(GVarData));
+ }
+ if (gvHasAllValuesClipboardData(&data)) {
+ for (int j = 0; j < fmCount; j++) {
+ int *gvar = &model->flightModeData[j].gvars[gvIdx];
+ memcpy(gvar, data.mid(j * sizeof(phase.gvars[0]), sizeof(phase.gvars[0])).constData(), sizeof(phase.gvars[0]));
+ }
+ }
}
- if (gvHasValueClipboardData(&data)) {
+ else if (gvHasValueClipboardData(&data)) {
int val = data.toInt();
if (val > GVAR_MAX_VALUE) {
if (phaseIdx > 0)
diff --git a/companion/src/modeledit/flightmodes.h b/companion/src/modeledit/flightmodes.h
index 1986f1e46..61e25c59a 100644
--- a/companion/src/modeledit/flightmodes.h
+++ b/companion/src/modeledit/flightmodes.h
@@ -29,6 +29,7 @@ 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";
+constexpr char MIMETYPE_GVAR_ALL_VALUES[] = "application/x-companion-gvar-all-values";
namespace Ui {
class FlightMode;
@@ -67,7 +68,7 @@ class FlightModePanel : public ModelPanel
void phaseREValue_editingFinished();
void phaseREUse_currentIndexChanged(int index);
void onCustomContextMenuRequested(QPoint pos);
- void cmClear();
+ void cmClear(bool prompt = true);
void cmClearAll();
void cmCopy();
void cmCut();
@@ -77,7 +78,7 @@ class FlightModePanel : public ModelPanel
void cmMoveDown();
void cmMoveUp();
void gvOnCustomContextMenuRequested(QPoint pos);
- void gvCmClear();
+ void gvCmClear(bool prompt = true);
void gvCmClearAll();
void gvCmCopy();
void gvCmCut();
@@ -127,6 +128,7 @@ class FlightModePanel : public ModelPanel
bool gvHasClipboardData() const;
bool gvHasDefnClipboardData(QByteArray * data = nullptr) const;
bool gvHasValueClipboardData(QByteArray * data = nullptr) const;
+ bool gvHasAllValuesClipboardData(QByteArray * data = nullptr) const;
bool gvDeleteAllowed() const;
bool gvInsertAllowed() const;
bool gvMoveDownAllowed() const;
diff --git a/companion/src/modeledit/inputs.cpp b/companion/src/modeledit/inputs.cpp
index 806de54fc..2e65c788c 100644
--- a/companion/src/modeledit/inputs.cpp
+++ b/companion/src/modeledit/inputs.cpp
@@ -227,26 +227,27 @@ void InputsPanel::setSelectedByExpoList(QList list)
}
}
-void InputsPanel::exposDelete(bool ask)
+void InputsPanel::exposDelete(bool prompt)
{
QList list = createExpoListFromSelected();
if (list.isEmpty())
return;
- QMessageBox::StandardButton ret = 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 (prompt) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete selected Input lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
}
+
+ exposDeleteList(list, prompt);
+ emit modified();
+ update();
}
void InputsPanel::exposCut()
{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut selected Input lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
exposCopy();
exposDelete(false);
}
@@ -317,7 +318,6 @@ void InputsPanel::pasteExpoMimeData(const QMimeData * mimeData, int destIdx)
}
}
-
void InputsPanel::exposPaste()
{
const QClipboard *clipboard = QApplication::clipboard();
@@ -515,7 +515,7 @@ void InputsPanel::exposDeleteList(QList list, bool clearName)
void InputsPanel::clearExpos()
{
- if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Input lines. 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);
@@ -559,7 +559,7 @@ bool InputsPanel::cmInputMoveUpAllowed() const
void InputsPanel::cmInputClear()
{
- if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all lines for the selected Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
for (int i = CPN_MAX_EXPOS - 1; i >= 0; i--) {
@@ -574,7 +574,7 @@ void InputsPanel::cmInputClear()
void InputsPanel::cmInputDelete()
{
- if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Input. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete all lines for the selected Inputs. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
for (int i = 0; i < CPN_MAX_EXPOS; i++) {
diff --git a/companion/src/modeledit/inputs.h b/companion/src/modeledit/inputs.h
index 884573fef..9922f2873 100644
--- a/companion/src/modeledit/inputs.h
+++ b/companion/src/modeledit/inputs.h
@@ -46,7 +46,7 @@ class InputsPanel : public ModelPanel
void expolistWidget_customContextMenuRequested(QPoint pos);
void expolistWidget_doubleClicked(QModelIndex index);
void expolistWidget_KeyPress(QKeyEvent *event);
- void exposDelete(bool ask=true);
+ void exposDelete(bool prompt = true);
void exposCut();
void exposCopy();
void exposPaste();
diff --git a/companion/src/modeledit/logicalswitches.cpp b/companion/src/modeledit/logicalswitches.cpp
index 13e20b8f6..e70d63568 100644
--- a/companion/src/modeledit/logicalswitches.cpp
+++ b/companion/src/modeledit/logicalswitches.cpp
@@ -479,10 +479,6 @@ void LogicalSwitchesPanel::populateFunctionCB(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);
@@ -490,27 +486,7 @@ void LogicalSwitchesPanel::populateFunctionCB(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);
}
@@ -557,8 +533,10 @@ void LogicalSwitchesPanel::cmCopy()
void LogicalSwitchesPanel::cmCut()
{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Logical Switch. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
cmCopy();
- cmClear();
+ cmClear(false);
}
// TODO make something generic here!
@@ -621,8 +599,13 @@ void LogicalSwitchesPanel::cmMoveDown()
swapData(selectedIndex, selectedIndex + 1);
}
-void LogicalSwitchesPanel::cmClear()
+void LogicalSwitchesPanel::cmClear(bool prompt)
{
+ if (prompt) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Logical Switch. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+ }
+
model->logicalSw[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
update();
diff --git a/companion/src/modeledit/logicalswitches.h b/companion/src/modeledit/logicalswitches.h
index 2aea300c5..62aa69f30 100644
--- a/companion/src/modeledit/logicalswitches.h
+++ b/companion/src/modeledit/logicalswitches.h
@@ -59,7 +59,7 @@ class LogicalSwitchesPanel : public ModelPanel
void cmMoveUp();
void cmMoveDown();
void cmInsert();
- void cmClear();
+ void cmClear(bool prompt = true);
void cmClearAll();
private:
diff --git a/companion/src/modeledit/mixes.cpp b/companion/src/modeledit/mixes.cpp
index c92105ec6..4d0f5f4cd 100644
--- a/companion/src/modeledit/mixes.cpp
+++ b/companion/src/modeledit/mixes.cpp
@@ -253,28 +253,27 @@ void MixesPanel::setSelectedByMixList(QList list)
}
-void MixesPanel::mixersDelete(bool ask)
+void MixesPanel::mixersDelete(bool prompt)
{
QList list = createMixListFromSelected();
- if(list.isEmpty()) return;
+ if(list.isEmpty())
+ return;
- QMessageBox::StandardButton ret = QMessageBox::No;
-
- if(ask) {
- ret = QMessageBox::warning(this, "companion",
- tr("Delete Selected Mixes?"),
- QMessageBox::Yes | QMessageBox::No);
+ if (prompt) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete selected Mix lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
}
- if ((ret == QMessageBox::Yes) || (!ask)) {
- mixersDeleteList(list);
- emit modified();
- update();
- }
+ mixersDeleteList(list);
+ emit modified();
+ update();
}
void MixesPanel::mixersCut()
{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut selected Mix lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
mixersCopy();
mixersDelete(false);
}
diff --git a/companion/src/modeledit/mixes.h b/companion/src/modeledit/mixes.h
index 46a51a21a..95765465e 100644
--- a/companion/src/modeledit/mixes.h
+++ b/companion/src/modeledit/mixes.h
@@ -39,7 +39,7 @@ class MixesPanel : public ModelPanel
private slots:
// TODO all slots?
void clearMixes();
- void mixersDelete(bool ask=true);
+ void mixersDelete(bool prompt = true);
void mixersCut();
void mixersCopy();
void mixersPaste();
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 43eaf11fe..5d4dfec79 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);
@@ -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());
@@ -192,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;
@@ -207,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);
@@ -271,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()));
@@ -391,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:
@@ -425,6 +424,8 @@ void ModulePanel::update()
max_rx_num = 20;
break;
case PULSES_CROSSFIRE:
+ mask |= MASK_CHANNELS_RANGE | MASK_RX_NUMBER;
+ case PULSES_GHOST:
mask |= MASK_CHANNELS_RANGE;
module.channelsCount = 16;
break;
@@ -450,6 +451,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:
@@ -516,16 +522,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
@@ -542,6 +548,9 @@ void ModulePanel::update()
if (firmware->getCapability(HasModuleR9MFlex))
i = 2;
break;
+ case PULSES_AFHDS3:
+ numEntries = 4;
+ break;
default:
break;
}
@@ -563,7 +572,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"));
@@ -606,6 +615,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()) {
@@ -635,6 +646,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)
@@ -666,9 +680,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;
}
}
@@ -766,12 +785,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);
@@ -1176,13 +1204,7 @@ 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); i < firmware->getCapability(NumModules); i++) {
modules[i] = new ModulePanel(this, model, model.moduleData[i], generalSettings, firmware, i);
@@ -1254,6 +1276,14 @@ void SetupPanel::on_throttleSource_currentIndexChanged(int index)
}
}
+void SetupPanel::on_throttleTrimSwitch_currentIndexChanged(int index)
+{
+ if (!lock) {
+ model->thrTrimSwitch = ui->throttleTrimSwitch->currentData().toUInt();
+ emit modified();
+ }
+}
+
void SetupPanel::on_name_editingFinished()
{
if (QString(model->name) != ui->name->text()) {
@@ -1326,11 +1356,29 @@ void SetupPanel::populateThrottleSourceCB()
lock = false;
}
+void SetupPanel::populateThrottleTrimSwitchCB()
+{
+ Board::Type board = firmware->getBoard();
+ lock = true;
+ ui->throttleTrimSwitch->clear();
+ int idx=0;
+ for (int i=0; ithrottleTrimSwitch->addItem(trim, idx);
+ }
+
+ int thrTrimSwitchIdx = ui->throttleTrimSwitch->findData(model->thrTrimSwitch);
+ ui->throttleTrimSwitch->setCurrentIndex(thrTrimSwitchIdx);
+ lock = false;
+}
+
void SetupPanel::update()
{
ui->name->setText(model->name);
ui->throttleReverse->setChecked(model->throttleReversed);
populateThrottleSourceCB();
+ populateThrottleTrimSwitchCB();
ui->throttleWarning->setChecked(!model->disableThrottleWarning);
ui->trimIncrement->setCurrentIndex(model->trimInc+2);
ui->throttleTrim->setChecked(model->thrTrim);
@@ -1570,10 +1618,12 @@ bool SetupPanel::moveTimerUpAllowed() const
return selectedTimerIndex > 0;
}
-void SetupPanel::cmTimerClear()
+void SetupPanel::cmTimerClear(bool prompt)
{
- if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
- return;
+ if (prompt) {
+ 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);
@@ -1605,8 +1655,10 @@ void SetupPanel::cmTimerCopy()
void SetupPanel::cmTimerCut()
{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
cmTimerCopy();
- cmTimerClear();
+ cmTimerClear(false);
}
void SetupPanel::cmTimerDelete()
diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h
index 1470e4e2f..e0c3df507 100644
--- a/companion/src/modeledit/setup.h
+++ b/companion/src/modeledit/setup.h
@@ -97,6 +97,7 @@ class ModulePanel : public ModelPanel
void onFailsafeUsecChanged(int value);
void onFailsafePercentChanged(double value);
void onFailsafesDisplayValueTypeChanged(int type);
+ void onRfFreqChanged(int freq);
void updateFailsafe(unsigned channel);
void on_optionValue_editingFinished();
void onClearAccessRxClicked();
@@ -137,6 +138,7 @@ class SetupPanel : public ModelPanel
private slots:
void on_name_editingFinished();
void on_throttleSource_currentIndexChanged(int index);
+ void on_throttleTrimSwitch_currentIndexChanged(int index);
void on_throttleTrim_toggled(bool checked);
void on_extendedLimits_toggled(bool checked);
void on_extendedTrims_toggled(bool checked);
@@ -153,7 +155,7 @@ class SetupPanel : public ModelPanel
void on_potWarningMode_currentIndexChanged(int index);
void on_editText_clicked();
void onTimerCustomContextMenuRequested(QPoint pos);
- void cmTimerClear();
+ void cmTimerClear(bool prompt = true);
void cmTimerClearAll();
void cmTimerCopy();
void cmTimerCut();
@@ -175,6 +177,7 @@ class SetupPanel : public ModelPanel
void updatePotWarnings();
void updateBeepCenter();
void populateThrottleSourceCB();
+ void populateThrottleTrimSwitchCB();
int timersCount;
int selectedTimerIndex;
bool hasTimerClipboardData(QByteArray * data = nullptr) const;
diff --git a/companion/src/modeledit/setup.ui b/companion/src/modeledit/setup.ui
index fc499ad63..8b2409191 100644
--- a/companion/src/modeledit/setup.ui
+++ b/companion/src/modeledit/setup.ui
@@ -6,7 +6,7 @@
0
0
- 893
+ 1007
405
@@ -32,22 +32,6 @@
- -
-
-
-
- 50
- false
-
-
-
- Top LCD Timer
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
-
@@ -149,6 +133,106 @@
+ -
+
+
+
+ 75
+ true
+
+
+
+ Model
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+ Timer 3
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
-
+
+
+
+ 50
+ false
+
+
+
+ Throttle Source
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+ Trim Step
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+ Trims Display
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+ Top LCD Timer
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
-
@@ -171,6 +255,66 @@
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
-
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+ Timer 2
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
-
-
@@ -275,44 +419,8 @@
- -
-
-
-
- 75
- true
-
-
-
- Model
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
+
-
+
Qt::Horizontal
@@ -334,86 +442,13 @@
- -
-
-
- Qt::Horizontal
-
-
-
-
-
-
-
-
-
- Qt::LeftToRight
-
-
- Display Checklist
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
- Never
-
-
- -
-
- On change
-
-
- -
-
- Always
-
-
-
-
- -
-
-
- Qt::LeftToRight
-
-
- Throttle Trim Idle Only
-
-
-
- -
-
-
- Global Functions
-
-
-
- -
-
-
- Qt::LeftToRight
-
-
- Throttle Warning
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
+
+
+ 6
+
+
-
+
-
@@ -450,6 +485,81 @@
+ -
+
+
+
+ 0
+ 0
+
+
+
-
+
+ Never
+
+
+ -
+
+ On change
+
+
+ -
+
+ Always
+
+
+
+
+ -
+
+
+ Qt::LeftToRight
+
+
+ Throttle Warning
+
+
+
+ -
+
+
+ Qt::LeftToRight
+
+
+ Display Checklist
+
+
+
+ -
+
+
+ Global Functions
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Edit Checklist...
+
+
+
+ -
+
+
+ Qt::LeftToRight
+
+
+ Throttle Trim Idle Only
+
+
+
-
@@ -466,16 +576,10 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
- -
-
-
-
- 0
- 0
-
-
+
-
+
- Edit Checklist...
+ Throttle trim switch
@@ -499,7 +603,17 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
- -
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ -
Qt::Horizontal
@@ -514,107 +628,6 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
- -
-
-
-
-
-
-
- 50
- false
-
-
-
- Throttle Source
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 50
- false
-
-
-
- Trim Step
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 50
- false
-
-
-
- Trims Display
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
-
- 50
- false
-
-
-
- Timer 2
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 50
- false
-
-
-
- Timer 3
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
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 83565c03e..b34caa89e 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,294 +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;
-}
-
-/******************************************************/
-
TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawSourceFilterItemModel * srcModel):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::TelemetryCustomScreen),
@@ -324,17 +35,17 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model,
{
ui->setupUi(this);
- for (int l=0; l<4; l++) {
- for (int c=0; cgetCapability(TelemetryCustomScreensFieldsPerLine); c++) {
+ for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensLines); l++) {
+ for (int c = 0; c < firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) {
fieldsCB[l][c] = new QComboBox(this);
- fieldsCB[l][c]->setProperty("index", c + (l<<8));
+ fieldsCB[l][c]->setProperty("index", c + (l << 8));
fieldsCB[l][c]->setModel(srcModel);
ui->screenNumsLayout->addWidget(fieldsCB[l][c], l, c, 1, 1);
connect(fieldsCB[l][c], SIGNAL(activated(int)), this, SLOT(customFieldChanged(int)));
}
}
- for (int l=0; l<4; l++) {
+ for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensBars); l++) {
barsCB[l] = new QComboBox(this);
barsCB[l]->setProperty("index", l);
barsCB[l]->setModel(srcModel);
@@ -377,8 +88,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()))
@@ -409,18 +119,18 @@ void TelemetryCustomScreen::update()
ui->screenNums->setVisible(screen.type == TELEMETRY_SCREEN_NUMBERS);
ui->screenBars->setVisible(screen.type == TELEMETRY_SCREEN_BARS);
- for (int l=0; l<4; l++) {
- for (int c=0; cgetCapability(TelemetryCustomScreensFieldsPerLine); c++) {
+ for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensLines); l++) {
+ for (int c = 0; c < firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) {
fieldsCB[l][c]->setCurrentIndex(fieldsCB[l][c]->findData(screen.body.lines[l].source[c].toValue()));
}
}
- for (int l=0; l<4; l++) {
+ for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensBars); l++) {
barsCB[l]->setCurrentIndex(barsCB[l]->findData(screen.body.bars[l].source.toValue()));
}
if (screen.type == TELEMETRY_SCREEN_BARS) {
- for (int i=0; i<4; i++) {
+ for (int i = 0; i < firmware->getCapability(TelemetryCustomScreensBars); i++) {
updateBar(i);
}
}
@@ -439,14 +149,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 +256,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 +266,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,10 +281,7 @@ 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();
}
@@ -594,13 +289,14 @@ void TelemetryCustomScreen::barTimeChanged()
/******************************************************/
-TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
+TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::TelemetrySensor),
sensor(sensor),
lock(false),
sensorIndex(sensorIndex),
- selectedIndex(0)
+ selectedIndex(0),
+ sensorCapability(sensorCapability)
{
ui->setupUi(this);
ui->numLabel->setText(tr("TELE%1").arg(sensorIndex + 1));
@@ -628,7 +324,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 = SensorData::TELEM_CELL_INDEX_LOWEST + 1; i < SensorData::TELEM_CELL_INDEX_HIGHEST; 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);
@@ -777,8 +473,8 @@ void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model
{
cb->clear();
if (negative) {
- for (int i=-CPN_MAX_SENSORS; i<0; ++i) {
- const SensorData& sensor = model->sensorData[-i-1];
+ for (int i = -CPN_MAX_SENSORS; i < 0; ++i) {
+ const SensorData& sensor = model->sensorData[-i - 1];
if (sensor.isAvailable()) {
if (sensor.type == SensorData::TELEM_TYPE_CUSTOM)
cb->addItem(QString("-%1 (%2)").arg(sensor.label, sensor.getOrigin(model)), i);
@@ -788,7 +484,7 @@ void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model
}
}
cb->addItem("---", 0);
- for (unsigned i=1; i<=CPN_MAX_SENSORS; ++i) {
+ for (unsigned i = 1; i <= CPN_MAX_SENSORS; ++i) {
const SensorData& sensor = model->sensorData[i-1];
if (sensor.isAvailable()) {
if (sensor.type == SensorData::TELEM_TYPE_CUSTOM)
@@ -874,6 +570,11 @@ void TelemetrySensorPanel::on_customContextMenuRequested(QPoint pos)
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);
@@ -891,6 +592,21 @@ bool TelemetrySensorPanel::hasClipboardData(QByteArray * data) const
return false;
}
+bool TelemetrySensorPanel::insertAllowed() const
+{
+ return ((selectedIndex < sensorCapability - 1) && (model->sensorData[sensorCapability - 1].isEmpty()));
+}
+
+bool TelemetrySensorPanel::moveDownAllowed() const
+{
+ return selectedIndex < sensorCapability - 1;
+}
+
+bool TelemetrySensorPanel::moveUpAllowed() const
+{
+ return selectedIndex > 0;
+}
+
void TelemetrySensorPanel::cmCopy()
{
QByteArray data;
@@ -902,8 +618,11 @@ void TelemetrySensorPanel::cmCopy()
void TelemetrySensorPanel::cmCut()
{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Telemetry Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
cmCopy();
- cmClear();
+ cmClear(false);
}
void TelemetrySensorPanel::cmPaste()
@@ -916,12 +635,15 @@ void TelemetrySensorPanel::cmPaste()
}
}
-void TelemetrySensorPanel::cmClear()
+void TelemetrySensorPanel::cmClear(bool prompt)
{
- if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Telemetry Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
- return;
+ if (prompt) {
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Telemetry Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+ }
sensor.clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
emit dataModified();
emit modified();
}
@@ -934,6 +656,26 @@ void TelemetrySensorPanel::cmClearAll()
emit clearAllSensors();
}
+void TelemetrySensorPanel::cmInsert()
+{
+ emit insertSensor(selectedIndex);
+}
+
+void TelemetrySensorPanel::cmDelete()
+{
+ emit deleteSensor(selectedIndex);
+}
+
+void TelemetrySensorPanel::cmMoveUp()
+{
+ emit moveUpSensor(selectedIndex);
+}
+
+void TelemetrySensorPanel::cmMoveDown()
+{
+ emit moveDownSensor(selectedIndex);
+}
+
/******************************************************/
TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
@@ -942,33 +684,29 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
{
ui->setupUi(this);
+ sensorCapability = firmware->getCapability(Sensors);
+ if (sensorCapability > CPN_MAX_SENSORS) // TODO should be role of getCapability
+ sensorCapability = CPN_MAX_SENSORS;
+
if (firmware->getCapability(NoTelemetryProtocol)) {
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; 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()));
+ ui->varioSource->setField(model.frsky.varioSource, this);
+ ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this);
+ ui->A1GB->hide();
+ ui->A2GB->hide();
+ for (int i = 0; i < sensorCapability; ++i) {
+ TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, sensorCapability, 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()));
+ connect(panel, SIGNAL(insertSensor(int)), this, SLOT(on_insertSensor(int)));
+ connect(panel, SIGNAL(deleteSensor(int)), this, SLOT(on_deleteSensor(int)));
+ connect(panel, SIGNAL(moveUpSensor(int)), this, SLOT(on_moveUpSensor(int)));
+ connect(panel, SIGNAL(moveDownSensor(int)), this, SLOT(on_moveDownSensor(int)));
}
if (IS_TARANIS_X9(firmware->getBoard())) {
@@ -984,7 +722,7 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
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));
+ ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i + 1));
telemetryCustomScreens[i] = tab;
connect(tab, &TelemetryCustomScreen::modified, this, &TelemetryPanel::onModified);
connect(this, &TelemetryPanel::updated, tab, &TelemetryCustomScreen::update);
@@ -1017,10 +755,8 @@ void TelemetryPanel::update()
populateTelemetrySourcesComboBox(ui->varioSource, model, false);
}
- if (IS_ARM(firmware->getBoard())) {
- for (unsigned i=0; iupdate();
- }
+ for (int i = 0; i < sensorCapability; ++i) {
+ sensorPanels[i]->update();
}
emit updated();
@@ -1032,52 +768,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"));
- }
+ ui->rssiSourceLabel->show();
+ ui->rssiSourceLabel->setText(tr("Source"));
+ ui->rssiSourceCB->setField(model->rssiSource, this);
+ ui->rssiSourceCB->show();
+ populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false);
- /*if (IS_ARM(firmware->getBoard())) {
- for (int i=0; i, model, generalSettings, firmware);
- ui->sensorsLayout->addWidget(panel);
- sensorPanels[i] = panel;
- }
- }*/
+ 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) {
@@ -1100,16 +813,16 @@ void TelemetryPanel::setup()
ui->VarioLabel_1->hide();
ui->VarioLabel_2->hide();
}
- ui->varioLimitMin_DSB->setValue(model->frsky.varioMin-10);
- ui->varioLimitMax_DSB->setValue(model->frsky.varioMax+10);
- ui->varioLimitCenterMax_DSB->setValue((model->frsky.varioCenterMax/10.0)+0.5);
- ui->varioLimitCenterMin_DSB->setValue((model->frsky.varioCenterMin/10.0)-0.5);
+ ui->varioLimitMin_DSB->setValue(model->frsky.varioMin - 10);
+ ui->varioLimitMax_DSB->setValue(model->frsky.varioMax + 10);
+ ui->varioLimitCenterMax_DSB->setValue((model->frsky.varioCenterMax / 10.0) + 0.5);
+ ui->varioLimitCenterMin_DSB->setValue((model->frsky.varioCenterMin / 10.0) - 0.5);
}
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 {
@@ -1117,38 +830,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;
}
@@ -1170,10 +851,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);
}
@@ -1185,10 +864,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);
}
@@ -1217,24 +894,12 @@ void TelemetryPanel::on_frskyProtoCB_currentIndexChanged(int index)
{
if (!lock) {
model->frsky.usrProto = index;
- for (int i=0; igetCapability(TelemetryCustomScreens); i++)
+ for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++)
telemetryCustomScreens[i]->update();
emit modified();
}
}
-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();
@@ -1249,23 +914,23 @@ void TelemetryPanel::on_rssiAlarmCriticalSB_editingFinished()
void TelemetryPanel::on_varioLimitMin_DSB_editingFinished()
{
- model->frsky.varioMin = round(ui->varioLimitMin_DSB->value()+10);
+ model->frsky.varioMin = round(ui->varioLimitMin_DSB->value() + 10);
emit modified();
}
void TelemetryPanel::on_varioLimitMax_DSB_editingFinished()
{
- model->frsky.varioMax = round(ui->varioLimitMax_DSB->value()-10);
+ model->frsky.varioMax = round(ui->varioLimitMax_DSB->value() - 10);
emit modified();
}
void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished()
{
if (!lock) {
- if (ui->varioLimitCenterMin_DSB->value()>ui->varioLimitCenterMax_DSB->value()) {
+ if (ui->varioLimitCenterMin_DSB->value() > ui->varioLimitCenterMax_DSB->value()) {
ui->varioLimitCenterMax_DSB->setValue(ui->varioLimitCenterMin_DSB->value());
}
- model->frsky.varioCenterMin = round((ui->varioLimitCenterMin_DSB->value()+0.5)*10);
+ model->frsky.varioCenterMin = round((ui->varioLimitCenterMin_DSB->value() + 0.5) * 10);
emit modified();
}
}
@@ -1273,10 +938,10 @@ void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished()
void TelemetryPanel::on_varioLimitCenterMax_DSB_editingFinished()
{
if (!lock) {
- if (ui->varioLimitCenterMin_DSB->value()>ui->varioLimitCenterMax_DSB->value()) {
+ if (ui->varioLimitCenterMin_DSB->value() > ui->varioLimitCenterMax_DSB->value()) {
ui->varioLimitCenterMax_DSB->setValue(ui->varioLimitCenterMin_DSB->value());
}
- model->frsky.varioCenterMax = round((ui->varioLimitCenterMax_DSB->value()-0.5)*10);
+ model->frsky.varioCenterMax = round((ui->varioLimitCenterMax_DSB->value() - 0.5) * 10);
emit modified();
}
}
@@ -1304,8 +969,56 @@ void TelemetryPanel::on_clearAllSensors()
{
for (int i = 0; i < CPN_MAX_SENSORS; i++) {
model->sensorData[i].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, i);
}
update();
emit modified();
}
+
+void TelemetryPanel::on_insertSensor(int selectedIndex)
+{
+ memmove(&model->sensorData[selectedIndex + 1], &model->sensorData[selectedIndex], (CPN_MAX_SENSORS - (selectedIndex + 1)) * sizeof(SensorData));
+ model->sensorData[selectedIndex].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1);
+
+ update();
+ emit modified();
+}
+
+void TelemetryPanel::on_deleteSensor(int selectedIndex)
+{
+ if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return;
+
+ memmove(&model->sensorData[selectedIndex], &model->sensorData[selectedIndex + 1], (CPN_MAX_SENSORS - (selectedIndex + 1)) * sizeof(SensorData));
+ model->sensorData[CPN_MAX_SENSORS - 1].clear();
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1);
+
+ update();
+ emit modified();
+}
+
+void TelemetryPanel::on_moveUpSensor(int selectedIndex)
+{
+ swapData(selectedIndex, selectedIndex - 1);
+}
+
+void TelemetryPanel::on_moveDownSensor(int selectedIndex)
+{
+ swapData(selectedIndex, selectedIndex + 1);
+}
+
+void TelemetryPanel::swapData(int idx1, int idx2)
+{
+ if ((idx1 != idx2) && (!model->sensorData[idx1].isEmpty() || !model->sensorData[idx2].isEmpty())) {
+ SensorData sdtmp = model->sensorData[idx2];
+ SensorData *sd1 = &model->sensorData[idx1];
+ SensorData *sd2 = &model->sensorData[idx2];
+ memcpy(sd2, sd1, sizeof(SensorData));
+ memcpy(sd1, &sdtmp, sizeof(SensorData));
+ model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
+ update();
+ emit modified();
+ }
+}
diff --git a/companion/src/modeledit/telemetry.h b/companion/src/modeledit/telemetry.h
index 39f3a42ad..cddade217 100644
--- a/companion/src/modeledit/telemetry.h
+++ b/companion/src/modeledit/telemetry.h
@@ -31,45 +31,11 @@ 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
@@ -105,13 +71,18 @@ class TelemetrySensorPanel: public ModelPanel
Q_OBJECT
public:
- TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
+ TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
~TelemetrySensorPanel();
void update();
signals:
void dataModified();
void clearAllSensors();
+ void insertSensor(int index);
+ void deleteSensor(int index);
+ void moveUpSensor(int index);
+ void moveDownSensor(int index);
+
protected slots:
void on_name_editingFinished();
@@ -124,8 +95,12 @@ class TelemetrySensorPanel: public ModelPanel
void cmCopy();
void cmCut();
void cmPaste();
- void cmClear();
+ void cmClear(bool prompt = true);
void cmClearAll();
+ void cmInsert();
+ void cmDelete();
+ void cmMoveUp();
+ void cmMoveDown();
protected:
void updateSourcesComboBox(AutoComboBox * cb, bool negative);
@@ -136,6 +111,10 @@ class TelemetrySensorPanel: public ModelPanel
bool lock = false;
int sensorIndex = 0;
int selectedIndex = 0;
+ int sensorCapability;
+ bool insertAllowed() const;
+ bool moveDownAllowed() const;
+ bool moveUpAllowed() const;
};
class TelemetryPanel : public ModelPanel
@@ -155,8 +134,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();
@@ -167,18 +144,23 @@ class TelemetryPanel : public ModelPanel
void on_mahCount_SB_editingFinished();
void on_mahCount_ChkB_toggled(bool checked);
void on_clearAllSensors();
+ void on_insertSensor(int index);
+ void on_deleteSensor(int index);
+ void on_moveUpSensor(int index);
+ void on_moveDownSensor(int index);
private:
Ui::Telemetry *ui;
- TelemetryAnalog * analogs[4];
TelemetryCustomScreen * telemetryCustomScreens[4];
TelemetrySensorPanel * sensorPanels[CPN_MAX_SENSORS];
+ int sensorCapability;
void setup();
void telBarUpdate();
void populateVoltsSource();
void populateCurrentSource();
void populateVarioSource();
+ void swapData(int idx1, int idx2);
};
#endif // _TELEMETRY_H_
diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp
index dde8517e0..3dc945f5d 100644
--- a/companion/src/modelprinter.cpp
+++ b/companion/src/modelprinter.cpp
@@ -212,7 +212,7 @@ QString ModelPrinter::printModule(int idx)
str << printLabelValue(tr("Delay"), QString("%1us").arg(module.ppm.delay));
}
else {
- if (!(module.protocol == PULSES_PXX_XJT_D8 || module.protocol == PULSES_CROSSFIRE || module.protocol == PULSES_SBUS)) {
+ if (!(module.protocol == PULSES_PXX_XJT_D8 || module.protocol == PULSES_CROSSFIRE || module.protocol == PULSES_GHOST || module.protocol == PULSES_SBUS)) {
str << printLabelValue(tr("Receiver"), QString::number(module.modelId));
}
if (module.protocol == PULSES_MULTIMODULE) {
@@ -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(" ");
@@ -968,8 +973,7 @@ QString ModelPrinter::printSettingsTrim()
{
QStringList str;
str << printLabelValue(tr("Step"), printTrimIncrementMode());
- if (IS_ARM(firmware->getBoard()))
- 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/multimodelprinter.cpp b/companion/src/multimodelprinter.cpp
index f9d039d69..4da889cb1 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)) {
@@ -310,7 +310,9 @@ QString MultiModelPrinter::printSetup()
MultiColumns columns(modelPrinterMap.size());
columns.appendSectionTableStart();
ROWLABELCOMPARECELL(tr("Name"), 20, model->name, 80);
- ROWLABELCOMPARECELL(tr("EEprom Size"), 0, modelPrinter->printEEpromSize(), 0);
+ if (!IS_FAMILY_HORUS_OR_T16(firmware->getBoard())) {
+ ROWLABELCOMPARECELL(tr("EEprom Size"), 0, modelPrinter->printEEpromSize(), 0);
+ }
if (firmware->getCapability(ModelImage)) {
ROWLABELCOMPARECELL(tr("Model Image"), 0, model->bitmap, 0);
}
@@ -751,32 +753,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 +807,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/profilechooser.cpp b/companion/src/profilechooser.cpp
index 17a9570e5..a8942652e 100644
--- a/companion/src/profilechooser.cpp
+++ b/companion/src/profilechooser.cpp
@@ -28,6 +28,7 @@ ProfileChooserDialog::ProfileChooserDialog(QWidget * parent):
{
ui->setupUi(this);
setWindowIcon(QIcon(":/icon.png"));
+ setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
QComboBox *prof = ui->cboProfiles;
prof->clear();
diff --git a/companion/src/radiointerface.cpp b/companion/src/radiointerface.cpp
index fbc03186f..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,87 +125,8 @@ 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) {
- 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();
+ return getSambaArgs(QString("receive_file {Flash} \"") + filename + "\" 0x400000 0x80000 0\n");
}
}
@@ -264,13 +141,11 @@ 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) {
@@ -288,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);
@@ -339,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);
@@ -375,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)) {
@@ -396,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/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt
index 767933edf..462d5693f 100644
--- a/companion/src/simulation/CMakeLists.txt
+++ b/companion/src/simulation/CMakeLists.txt
@@ -14,6 +14,7 @@ set(simulation_SRCS
simulateduiwidgetX12.cpp
simulateduiwidgetJumperT12.cpp
simulateduiwidgetJumperT16.cpp
+ simulateduiwidgetJumperT18.cpp
simulateduiwidgetTX16S.cpp
simulatorinterface.cpp
simulatormainwindow.cpp
@@ -39,6 +40,7 @@ set(simulation_UIS
simulateduiwidgetX12.ui
simulateduiwidgetJumperT12.ui
simulateduiwidgetJumperT16.ui
+ simulateduiwidgetJumperT18.ui
simulateduiwidgetTX16S.ui
simulatormainwindow.ui
simulatorstartupdialog.ui
diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h
index 75dd3ebfd..8419840c5 100644
--- a/companion/src/simulation/simulateduiwidget.h
+++ b/companion/src/simulation/simulateduiwidget.h
@@ -113,6 +113,7 @@ namespace Ui {
class SimulatedUIWidgetX12;
class SimulatedUIWidgetJumperT12;
class SimulatedUIWidgetJumperT16;
+ class SimulatedUIWidgetJumperT18;
class SimulatedUIWidgetTX16S;
}
@@ -252,6 +253,18 @@ 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
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/simulatorstartupdialog.cpp b/companion/src/simulation/simulatorstartupdialog.cpp
index 32d343321..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|16)", 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 d20e34cc7..f70813442 100644
--- a/companion/src/simulation/simulatorwidget.cpp
+++ b/companion/src/simulation/simulatorwidget.cpp
@@ -94,6 +94,9 @@ 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;
diff --git a/companion/src/storage/rlefile.cpp b/companion/src/storage/rlefile.cpp
index fe297339f..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)
@@ -244,10 +182,7 @@ unsigned int RleFile::EeFsGetFree()
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;
@@ -266,14 +201,8 @@ void RleFile::EeFsFree(unsigned int blk)
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
}
/*
@@ -283,12 +212,9 @@ unsigned int RleFile::EeFsAlloc()
{
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;
@@ -299,7 +225,7 @@ unsigned int RleFile::size(unsigned int id)
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)
@@ -327,15 +253,12 @@ 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;
}
}
@@ -344,14 +267,14 @@ unsigned int RleFile::read(uint8_t *buf, unsigned int i_len)
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);
}
@@ -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,23 +447,15 @@ 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
}
diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts
index fff65e6d9..9b18ec30e 100644
--- a/companion/src/translations/companion_fr.ts
+++ b/companion/src/translations/companion_fr.ts
@@ -743,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
@@ -908,57 +908,62 @@ Manche Droit: Profondeur, Direction
Supprimer la Voie. Êtes-vous sûr?
-
+
+ Cut Channel. Are you sure?
+ Couper 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?
@@ -1596,17 +1601,22 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
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?
-
+
+ Cut Curve. Are you sure?
+ Couper la Courbe. Êtes-vous sûr?
+
+
+
Delete Curve. Are you sure?
Supprimer la Courbe. Êtes-vous sûr?
@@ -1640,8 +1650,8 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
- Trainer
- Écolage Manches
+ Trainer Sticks
+ Manches Écolage
@@ -1784,79 +1794,79 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
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
@@ -1916,84 +1926,89 @@ 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?
+
+ Delete Function. Are you sure?
+ Supprimer la Fonction. Êtes-vous sûr?
-
+
+ Cut Special Function. Are you sure?
+ Couper la Fonction. Ê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 Function. Are you sure?
+ Effacer la Fonction. Êtes-vous sûr?
-
- Clear all Special Functions. Are you sure?
- Supprimer toutes les Fonctions Spéciales. Êtes-vous sûr?
+
+ Clear all Functions. Are you sure?
+ Effacer toutes les Fonctions. Êtes-vous sûr?
@@ -2159,48 +2174,48 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import
Erreur de conversion du champ %1
-
+
Switch
Interrupteur
-
+
Switch
L'interrupteur
-
+
cannot be exported on this board!
n'est pas supporté sur cette carte !
-
+
Source
-
+
Source %1 cannot be exported on this board!
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
@@ -2327,62 +2342,47 @@ Pour <b>retirer un filtre de l'historique</b>, sélectionnez-le
- - Eeprom is not from Th9X
- - L'EEPROM n'est pas une EEPROM TX9X
-
-
-
- - Eeprom is not from Gruvin9X
- - L'EEPROM n'est pas une EEPROM Gruvin9X
-
-
-
- Eeprom is not from ErSky9X
- L'EEPROM n'est pas une EEPROM ErSky9X
-
- - Eeprom is not from Er9X
- - L'EEPROM n'est pas une EEPROM Er9X
-
-
-
+
- Eeprom size is invalid
- La taille de l'EEPROM est invalide
-
+
- Eeprom file system is invalid
- Le système de fichier de l'EEPROM est invalide
-
+
- Eeprom is from a unknown board
- L'EEPROM ne correspond à aucune carte supportée
-
+
- Eeprom is from the wrong board
- L'EEPROM ne correspond pas au type de radio sélectionné
-
+
- Eeprom backup not supported
- Sauvegarde d'EEPROM non supportée
-
+
- Something that couldn't be guessed, sorry
- Erreur inconnue
-
+
Warning:
Avertissement:
-
-
+
+
- Your radio probably uses a wrong firmware,
eeprom size is 4096 but only the first 2048 are used
- Le firmware de la radio est probablement incorrect,
@@ -2390,7 +2390,7 @@ la taille de l'EEPROM est de 4096 mais seulement 2048 bytes sont utilisés.
Vérifier la sélection (M64/M128)
-
+
- 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.
- Votre eeprom provient d'une ancienne version d'OpenTX, mettez à niveau!
@@ -2553,22 +2553,22 @@ Si vide, la ligne est toujours active.
Éditer %1
-
+
Popup menu available
Menu contextuel disponible
-
+
Clear All
Effacer Tout
-
+
Set All
Définir Tout
-
+
Invert All
Inverser Tout
@@ -2937,282 +2937,258 @@ 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
-
+
+ Enable AFHDS3 support
+ Activer le support du AFHDS3
+
+
+
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
-
-
+
+
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
-
+
+ Jumper T18
+
+
+
+
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
-
FirmwarePreferencesDialog
@@ -3471,62 +3447,62 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont
Transférer
-
+
Open Firmware File
Sélectionner le firmware
-
+
%1 may not be a valid firmware file
%1 ne semble pas être un firmware valide
-
+
The firmware file is not valid.
Le firmware est invalide.
-
+
There is no start screen image in the firmware file.
Aucun écran d'accueil trouvé dans le firmware.
-
+
Profile image %1 is invalid.
L'image du profil %1 est invalide.
-
+
Open image file to use as radio start screen
Ouvrir l'image à utiliser comme écran d'accueil
-
+
Images (%1)
Images (%1)
-
+
Image could not be loaded from %1
L'image %1 n'a pu être chargée
-
+
The library image could not be loaded
L'image n'a pu être chargée depuis la bibliothèque
-
+
Splash image not found
Ecran d'accueil sélectionné introuvable
-
+
Cannot save customized firmware
Impossible d'enregistrer le firmware personnalisé
-
+
Write Firmware to Radio
Transférer le firmware à la radio
@@ -3547,27 +3523,27 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont
Le nouveau firmware ne correspond pas à la version installée, vérifiez le type de radio !
-
+
Conversion failed
La conversion a échoué
-
+
Cannot convert Models and Settings for use with this firmware, original data will be used
Impossible de convertir les paramètres et modèles pour ce firmware, les données originales vont être utilisées
-
+
Restore failed
Echec de la restauration
-
+
Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1
Impossible de restaurer les paramètres et modèles sur la radio. Le fichier peut être récupéré ici: %1
-
+
Flashing done
Programmation terminée
@@ -3580,42 +3556,42 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont
Exécutable %1 introuvable
-
+
Writing...
Ecriture...
-
+
Reading...
Lecture...
-
+
Verifying...
Vérification...
-
+
unknown
inconnu
-
+
ie: OpenTX for 9X board or OpenTX for 9XR board
ex: OpenTX pour carte d'origine 9x ou OpenTX pour 9XR
-
+
ie: OpenTX for M128 / 9X board or OpenTX for 9XR board with M128 chip
ex:. OpenTX pour carte d'origine 9x avec m128 ou OpenTX pour 9XR avec m128
-
+
ie: OpenTX for Gruvin9X board
ex: OpenTX pour carte gruvin9x
-
+
Your radio uses a %1 CPU!!!
Please check advanced burn options to set the correct cpu type.
@@ -3624,7 +3600,7 @@ Please check advanced burn options to set the correct cpu type.
Vérifiez les options de programmateur et choisissez le bon type de processeur.
-
+
Your radio uses a %1 CPU!!!
Please select an appropriate firmware type to program it.
@@ -3633,7 +3609,7 @@ Please select an appropriate firmware type to program it.
Veuillez choisir le firmware approprié.
-
+
You are currently using:
%1
@@ -3642,22 +3618,22 @@ Vous utilisez actuellement:
%1
-
+
Your radio does not seem connected to USB or the driver is not initialized!!!.
Votre radio ne semble pas être connectée en USB, ou le pilote n'est pas initialisé !!!.
-
+
Flashing done (exit code = %1)
Terminé (code de sortie = %1)
-
+
Flashing done with errors
Terminé avec des erreurs
-
+
FUSES: Low=%1 High=%2 Ext=%3
Fusibles: Bas=%1 Haut=%2 Ext=%3
@@ -3762,79 +3738,109 @@ Vous utilisez actuellement:
-
+
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?
-
+
+ Cut Flight Mode. Are you sure?
+ Couper la Phase 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 Global Variable across all Flight Modes. Are you sure?
+ Effacer la Variable Globale pour toutes les Phases de Vol. Êtes-vous sûr?
-
+
+ Clear Global Variable. Are you sure?
+ Effacer la Variable Globale. Êtes-vous sûr?
+
+
+
+ Cut Global Variable across all Flight Modes. Are you sure?
+ Couper la Variable Globale pour toutes les Phases de Vol. Êtes-vous sûr?
+
+
+
+ Cut Global Variable. Are you sure?
+ Couper la Variable Globale. Êtes-vous sûr?
+
+
+
+ Delete Global Variable. Are you sure?
+ Supprimer la Variable Globale. Êtes-vous sûr?
+
+
+
+ Paste to selected Global Variable across all Flight Modes. Are you sure?
+ Coller la Variable Globale pour 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?
@@ -3881,7 +3887,7 @@ Vous utilisez actuellement:
-
+
Clear
Effacer
@@ -3889,17 +3895,17 @@ Vous utilisez actuellement:
FlightModesPanel
-
+
Flight Mode %1
Phase de vol %1
-
+
(%1)
-
+
(default)
(par défaut)
@@ -4169,7 +4175,7 @@ These will be relevant for all models in the same EEPROM.
Communs à tous les modèles d'une même EEPROM.
-
+
Trainer
Écolage
@@ -4184,42 +4190,42 @@ Communs à tous les modèles d'une même EEPROM.
Lire étalonnage et paramètres hw du profil
-
+
Global Functions
Fonctions globales
-
+
Hardware
Matériel
-
+
Calibration
-
+
Wrong data in profile, radio calibration was not retrieved
Données du profil erronnées, l'étalonnage n'a pas été lu
-
+
Wrong data in profile, Switch/pot config not retrieved
Données incorecte, Interrupteurs/Pot non trouvés
-
+
Wrong data in profile, hw related parameters were not retrieved
Données du profil erronnées, les paramètres hw n'ont pas été lus
-
+
Do you want to store calibration in %1 profile<br>overwriting existing calibration?
Voulez-vous stocker l'étalonnage dans le profil %1<br> et écraser l'étalonnage existant ?
-
+
Calibration and HW parameters saved.
Etalonnage et paramètres hw enregistrés avec succès.
@@ -4227,7 +4233,7 @@ Communs à tous les modèles d'une même EEPROM.
GeneralSettings
-
+
Radio Settings
Paramètres de la radio
@@ -4285,169 +4291,169 @@ Communs à tous les modèles d'une même EEPROM.
-
+
Timeshift from UTC
Décalage horaire (UTC)
-
+
Voice Language
Langue des voix
-
+
Country Code
Zone géographique RF
-
+
Stick reverse
Inversion des manches
-
+
FAI Mode
Mode FAI
-
+
Adjust RTC
Ajuster l'heure par GPS
-
+
Vario pitch at max
Tonalité du vario au max
-
-
+
+
Hz
-
+
Speaker Volume
Volume haut-parleur
-
+
Backlight Switch
Inter de rétroéclairage
-
+
Sound Mode
Mode Son
-
+
Color 1
Couleur 1
-
+
Color 2
Couleur 2
-
+
Speaker Pitch (spkr only)
Tonalité (HP uniquement)
-
+
If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds.
Si cette valeur est différente de 0, l'appui sur une touche de navigation déclenche le rétroéclairage qui s'éteint après la durée spécifiée (en secondes).
-
-
-
+
+
+
sec
-
+
Backlight color
Couleur du rétroéclairage
-
+
Beeper
Bipeur
-
+
Speaker
Haut-parleur
-
+
BeeperVoice
Bipeur/Voix
-
+
SpeakerVoice
Haut-parleur/Voix
-
+
Beep volume
Volume des bips
-
+
Wav volume
Volume des fichiers audio
-
+
Vario volume
Volume du variomètre
-
+
Background volume
Volume de la musique d'ambiance
-
-
+
+
ms
-
+
Backlight Auto OFF after
Arrêt rétroéclairage après
-
+
Backlight flash on alarm
Clignotement rétroécl. alarmes
-
+
Vario pitch at zero
Tonalité du vario à 0
-
+
Vario repeat at zero
Répétition du vario à 0
-
+
This is the switch selectrion for turning on the backlight (if installed).
Interrupteur déclenchant le rétroéclairage' (si installé).
-
-
+
+
<!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; }
@@ -4462,42 +4468,42 @@ 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-size:8pt;">Plage de valeurs: 20...45</span></p></body></html>
-
+
Backlight Brightness
Luminosité du rétroéclairage
-
+
RotEnc Navigation
Navigation sélecteur rotatif
-
+
Automatically adjust the radio's clock if a GPS is connected to telemetry.
Régle automatique l'heure de la radio si un GPS est présent.
-
+
America
Amérique
-
+
Japan
Japon
-
+
Europe
-
+
Backlight OFF Brightness
Luminosité écran éteint
-
+
Mode selection:
Mode 1:
@@ -4538,332 +4544,337 @@ Mode 4:
-
+
Mode 1 (RUD ELE THR AIL)
Mode 1 (DIR PRF GAZ AIL)
-
+
Mode 2 (RUD THR ELE AIL)
Mode 2 (DIR GAZ PRF AIL)
-
+
Mode 3 (AIL ELE THR RUD)
Mode 3 (AIL PRF GAZ DIR)
-
+
Mode 4 (AIL THR ELE RUD)
Mode 4 (AIL GAZ PRF DIR)
-
+
<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>
-
+
If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio.
Si vous activez l'option FAI, seuls les capteurs RSSI et BtRx vont fonctionner. Cette fonction ne peut pas être désactivée sur la radio.
-
+
Owner Registration ID
Enregistrement ID du propriétaire
-
+
+ Keys Backlight
+ Rétroéclairage des touches
+
+
+
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
-
+
Power Off Delay
Délai mise hors tension
-
+
USB Mode
Mode USB
-
+
Jack Mode
Mode Jack
-
+
Audio
-
+
Trainer
Écolage
-
-
+
+
Ask on Connect
Demander à la connexion
-
+
Joystick (HID)
-
+
USB Mass Storage
Stockage USB (SD)
-
+
USB Serial (CDC)
Port série USB (Debug)
-
+
Stick Mode
Mode
-
+
Metric
Métrique
-
+
Imperial
Impérial
-
+
Default Channel Order
Ordre des voies par défaut
-
+
GPS Coordinates
Coordonnées GPS
-
+
Min
-
-
+
+
v
-
+
Max
-
+
RSSI Poweroff Warning
Vérifier RSSI à l'extinction
-
+
DMS
-
+
Inactivity Timer
Alerte d'inactivité
-
+
Show Splash Screen on Startup
Afficher l'écran de démarrage
-
+
Contrast
Contraste
-
+
Battery Meter Range
Plage de l'indicateur de batterie
-
+
Haptic Strength
Puissance vibreur
-
+
LCD Display Type
Type de LCD
-
+
"No Sound" Warning
Alerte "son coupé"
-
+
Battery Warning
Alerte batterie
-
+
Haptic Length
Durée vibreur
-
+
MAVLink Baud Rate
Baudrate Mavlink
-
-
+
+
Quiet
Mode silencieux
-
+
Only Alarms
Seulement les alarmes
-
-
+
+
No Keys
Touches silencieuses
-
-
+
+
All
Tous
-
+
Battery warning voltage.
This is the threashhold where the battery warning sounds.
@@ -4874,126 +4885,126 @@ Seuil auquel se déclenche l'alarme de batterie.
Plage de valeurs: 5v...10v
-
+
Standard
-
+
Optrex
-
+
If not zero will sound beeps if the transmitter has been left without inputs for the specified number of minutes.
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
-
+
Power On Delay
Délai mise sous tension
-
-
+
+
Show splash screen on startup
Affiche l'écran d'accueil au démarrage
-
+
---
-
+
2s
-
+
3s
-
+
4s
-
+
6s
-
+
8s
-
+
10s
-
+
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; }
@@ -5018,72 +5029,72 @@ 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;">Alerte mode silencieux - Avertissement si les bips sont désactivés</p></body></html>
-
-
+
+
X-Short
Très court
-
-
+
+
Short
Court
-
-
+
+
Normal
-
-
+
+
Long
-
-
+
+
X-Long
Très long
-
+
Low EEPROM Warning
Avertissement EEPROM faible
-
+
NMEA
-
+
Play Delay (switch mid position)
Délai position centrale inters
-
+
Measurement Units
Unités de mesure
-
+
Haptic Mode
Mode du vibreur
-
+
Beeper Length
Durée des bips
-
+
Beeper Mode
Paramètre des bips
-
+
Beeper volume
0 - Quiet. No beeps at all.
@@ -5100,7 +5111,7 @@ Long : bips plus longs.
Extra long : bips extra longs.
-
+
Alarms Only
Seulement les Alarmes
@@ -5108,127 +5119,127 @@ Extra long : bips extra longs.
GeneralSetupPanel
-
+
OFF
-
+
Keys
Touches
-
+
Sticks
Manches
-
+
Keys + Sticks
Touches + manches
-
+
ON
-
+
English
Anglais
-
+
Dutch
Hollandais
-
+
French
Français
-
+
Italian
Italien
-
+
German
Allemand
-
+
Czech
Tchèque
-
+
Slovak
Slovaque
-
+
Spanish
Espagnol
-
+
Polish
Polonais
-
+
Portuguese
Portugais
-
+
Swedish
Suédois
-
+
Hungarian
Hongrois
-
+
Russian
Russe
-
+
No
Non
-
+
RotEnc A
Sel.Rot. A
-
+
Rot Enc B
Sel.Rot. B
-
+
Rot Enc C
Sel.Rot. C
-
+
Rot Enc D
Sel.Rot. D
-
+
Rot Enc E
Sel.Rot. E
-
+
If you enable FAI, only RSSI and RxBt sensors will keep working.
This function cannot be disabled by the radio.
Are you sure ?
@@ -5760,9 +5771,14 @@ Cette fonction ne peut pas être désactivée sur la radio.
Pas assez d'Entrées disponibles!
-
- Delete selected Inputs. Are you sure?
- Supprimer les Entrées selectionnés. Êtes-vous sûr?
+
+ Delete selected Input lines. Are you sure?
+ Supprimer les lignes Entrée sélectionnées. Êtes-vous sûr?
+
+
+
+ Cut selected Input lines. Are you sure?
+ Couper les lignes Entrée sélectionnées. Êtes-vous sûr?
@@ -5862,18 +5878,18 @@ Cette fonction ne peut pas être désactivée sur la radio.
- Clear all Inputs. Are you sure?
- Effacer toutes les Entrées. Êtes-vous sûr?
+ Clear all Input lines. Are you sure?
+ Effacer toutes les lignes Entrée. Êtes-vous sûr?
- Clear Input. Are you sure?
- Effacer l'Entrée. Êtes-vous sûr?
+ Clear all lines for the selected Inputs. Are you sure?
+ Effacer toutes les lignes Entrée sélectionnées. Êtes-vous sûr?
- Delete Input. Are you sure?
- Supprimer l'Entrée. Êtes-vous sûr?
+ Delete all lines for the selected Inputs. Are you sure?
+ Supprimer toutes les lignes Entrée sélectionnées. Êtes-vous sûr?
@@ -6073,57 +6089,67 @@ Cette fonction ne peut pas être désactivée sur la radio.
(infini)
-
+
Delete Logical Switch. Are you sure?
Supprimer l'Interrupteur Logique. Êtes-vous sûr?
-
+
+ Cut Logical Switch. Are you sure?
+ Couper l'Interrupteur Logique. Ê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 Logical Switch. Are you sure?
+ Effacer l'Interrupteur Logique. Êtes-vous sûr?
+
+
+
Clear all Logical Switches. Are you sure?
Effacer tous les Interrupteurs Logiques. Êtes-vous sûr?
@@ -6305,79 +6331,74 @@ 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
@@ -6394,511 +6415,501 @@ 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?
@@ -6911,18 +6922,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?
@@ -6931,355 +6942,350 @@ 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
@@ -7937,25 +7943,25 @@ Mixage actif par défaut si non-renseigné.
MixesPanel
-
+
Move Up
Monter
-
+
Ctrl+Up
Ctrl+Haut
-
+
Move Down
Descendre
-
+
Ctrl+Down
Ctrl+Bas
@@ -7970,97 +7976,102 @@ Mixage actif par défaut si non-renseigné.
Plus de mixages disponibles !
-
- Delete Selected Mixes?
- Supprimer les mixages sélectionnés ?
+
+ Delete selected Mix lines. Are you sure?
+ Supprimer les lignes Mixeur sélectionnées. Êtes-vous sûr?
-
+
+ Cut selected Mix lines. Are you sure?
+ Couper les lignes Mixeur sélectionnées. Êtes-vous sûr?
+
+
+
&Add
&Ajouter
-
+
Ctrl+A
-
+
&Edit
&Édition
-
+
Enter
Entrée
-
+
Ctrl+T
-
+
&Toggle highlight
&(Dé)sélectionner
-
+
&Delete
&Supprimer
-
+
Delete
Supprimer
-
+
&Copy
&Copier
-
+
Ctrl+C
-
+
Ctrl+X
-
+
C&ut
&Couper
-
+
&Paste
&Coller
-
+
Ctrl+V
-
+
Du&plicate
&Dupliquer
-
+
Ctrl+U
-
+
Clear Mixes?
Effacer tous les mixages ?
-
+
Really clear all the mixes?
Êtes-vous sûr de vraiment vouloir effacer tous les mixages ?
@@ -8068,12 +8079,12 @@ Mixage actif par défaut si non-renseigné.
ModelData
-
+
Model:
Modèle:
-
+
Throttle Source
Source des gaz
@@ -8174,27 +8185,27 @@ Mixage actif par défaut si non-renseigné.
Inconnu
-
+
Slave/Jack
Elève/Jack
-
+
Master/SBUS Module
Maître/SBUS module
-
+
Master/CPPM Module
Maître/CPPM Module
-
+
Master/SBUS in battery compartment
Maître/SBUS compartiment batterie
-
+
Master/Jack
Maître/Jack
@@ -8235,9 +8246,9 @@ Mixage actif par défaut si non-renseigné.
-
-
-
+
+
+
OFF
@@ -8248,7 +8259,7 @@ Mixage actif par défaut si non-renseigné.
-
+
Mode
@@ -8282,14 +8293,14 @@ Mixage actif par défaut si non-renseigné.
-
-
+
+
Delay
Délai
-
+
Receiver
Récepteur
@@ -8315,581 +8326,592 @@ Mixage actif par défaut si non-renseigné.
+
RF Output Power
Puissance RF
-
+
+ Output Type
+ Type de sortie
+
+
+
+ RX Output Frequency
+ Fréquence de sortie du RX
+
+
+
90
-
+
120
-
+
120X
-
+
140
-
+
MULT!
-
-
+
+
Offset
Décalage
-
+
Slow
Ralenti
-
+
Warn
Attn
-
+
Flight modes
Phases de vol
-
+
Flight mode
Phase de vol
-
+
All
Tous
-
+
Edge
Flanc
-
+
Sticky
Bistable
-
+
Timer
Chrono
-
+
missing
absent
-
+
Duration
Durée
-
+
Extended Limits
Limites étendues
-
+
Display Checklist
Afficher la checklist
-
+
Global Functions
Fonctions globales
-
+
Manual
Manuel
-
+
Auto
-
+
Failsafe Mode
Mode Failsafe
-
-
+
+
Hold
Maintien
-
+
No Pulse
Pas d'impulsion
-
+
Not set
Non défini
-
+
No pulses
Pas d'impulsions
-
+
Silent
Aucun
-
+
Beeps
Bips
-
+
Voice
Voix
-
+
Haptic
Vibreur
-
+
Flight
Vol
-
+
Manual reset
RAZ manuelle
-
+
Step
Pas
-
+
Display
Affichage
-
+
Extended
Étendu
-
+
Never
Jamais
-
+
On Change
Sur changement
-
+
Always
Toujours
-
-
-
+
+
+
Source
-
+
Trim idle only
Trim ralenti uniquement
-
+
Warning
Avertissement
-
+
Reversed
Inversé
-
+
Tmr
Chrono
-
+
FrSky S.PORT
-
+
FrSky D
-
+
FrSky D (cable)
FrSky D (câble)
-
+
Alti
Alt
-
+
Alti+
Alt+
-
+
VSpeed
Vitesse verticale
-
-
-
+
+
+
A1
-
-
-
+
+
+
A2
-
-
+
+
A3
-
-
+
+
A4
-
-
+
+
FAS
-
+
Cells
Velm
-
+
Calculated
Calculé
-
+
Add
Addition
-
+
Average
Moyenne
-
-
+
+
Min
-
-
+
+
Max
-
+
Multiply
Multiplication
-
+
Totalise
-
+
Cell
Element LiPo
-
+
Consumption
Consommation
-
+
Distance
-
+
Lowest
Min
-
+
Cell %1
Elém. %1
-
+
Highest
Max
-
+
Delta
-
+
Formula
Formule
-
-
+
+
Id
-
+
Instance
-
-
-
-
+
+
+
+
Sensor
Capteur
-
-
+
+
Sources
-
-
+
+
GPS
-
+
Alt.
-
-
+
+
Blades
Pales
-
+
Multi.
-
+
F
-
+
Inst
-
+
Alt
Altitude
-
+
Unit
Unité
-
+
Prec
-
+
Ratio
-
+
Multi
-
+
A/Offset
-
+
Filter
Filtre
-
+
Persist
-
+
Positive
-
+
Log
-
+
Numbers
Chiffres
-
+
Bars
Barres
-
+
Script
-
+
Filename
Nom de fichier
-
+
Error: Unable to open or read file!
Erreur: Impossible d'ouvrir ou de lire le fichier!
-
+
Persistent
Persistant
-
+
Off
-
-
-
-
-
-
+
+
+
+
+
+
None
Aucun
-
+
Name
Nom
-
+
Countdown
Compte à rebours
-
+
Minute call
Annonces minutes
-
-
-
+
+
+
FM%1
PV%1
-
+
FM%1%2
PV%1%2
-
+
FM%1+%2
PV%1+%2
-
-
+
+
Weight
Ratio
-
-
+
+
Switch
Inter
-
-
+
+
NoTrim
Pas de trim
-
+
No DR/Expo
Pas d'expo/DR
-
+
Offset(%1)
Décalage(%1)
@@ -8904,24 +8926,24 @@ Mixage actif par défaut si non-renseigné.
-
+
Disabled in all flight modes
Désactivé pour toutes les phases de vol
-
+
instant
immédiat
-
-
-
+
+
+
Custom
Prédéfini
-
+
Standard
@@ -8957,7 +8979,7 @@ Mixage actif par défaut si non-renseigné.
Module
-
+
Failsafe Mode
Mode Failsafe
@@ -8967,241 +8989,251 @@ Mixage actif par défaut si non-renseigné.
1ère voie
-
+
PPM delay
Impulsion
-
+
Negative
Négative
-
+
Positive
-
+
Polarity
Polarité
-
+
Trainer Mode
Mode écolage
-
+
PPM Frame Length
Longueur de trame PPM
-
+
CH
VOIE
-
+
Antenna
Antenne
-
+
Option value
-
+
us
µs
-
+
Master/Jack
Maître/Jack
-
+
Slave/Jack
Elève/Jack
-
+
Master/SBUS Module
Maître/SBUS module
-
+
Master/CPPM Module
Maître/CPPM Module
-
+
Master/SBUS in battery compartment
Maître/SBUS dans compartiment batterie
-
+
RF Output Power
Puissance RF
-
+
Sub Type
Sous-Type
-
+
Master/Bluetooth
Maître/Bluetooth
-
+
Slave/Bluetooth
Elève/Bluetooth
-
+
Master/Multi
Maître/Multi
-
+
Disable Telemetry
Désactiver la télémétrie
-
+
Disable Ch. Map
Désactiver "Mapping" des VOIES
-
+
Show values in:
Afficher les valeurs en:
-
+
%
abbreviation for percent
-
+
μs
abbreviation for microseconds
-
+
ms
-
+
Receiver 1
Récepteur 1
-
-
-
+
+
+
X
-
+
Receiver 2
Récepteur 2
-
+
Receiver 3
Récepteur 3
-
+
WARNING: changing RF Output Power needs RE-BIND
ATTENTION: RE-BIND nécessaire pour tout changement de puissance RF
-
+
Channels
Nb de voies
-
+
+ RX Frequency
+ Fréquence RX
+
+
+
+ Hz
+
+
+
+
Not set
Non défini
-
+
Hold
Maintien
-
+
Custom
Prédéfini
-
+
No Pulses
Pas d'impulsions
-
+
Receiver
Récepteur
-
+
WARNING: Requires non-certified firmware!
ATTENTION: Nécessite un firmware non certifié!
-
+
Registration ID
ID d'enregistrement
-
+
Failsafe Positions
Positions Failsafe
-
+
Protocol
Protocole
-
+
Multi Radio Protocol
Protocole Multi
-
+
Receiver No.
Récepteur No.
-
+
Output type
Type de sortie
-
+
Open Drain
-
+
Push Pull
-
+
Low Power
Puissance Réduite
@@ -9209,133 +9241,153 @@ Mixage actif par défaut si non-renseigné.
ModuleData
-
+
Positive
-
+
Negative
Négative
-
+
Trainer Port
Port écolage
-
+
Internal Radio System
Module HF interne
-
+
External Radio Module
Module HF externe
-
+
Extra Radio System
Module HF supplémentaire
-
+
Radio System
Module HF
-
+
10mW - 16CH
10mW - 16 VOIES
-
-
+
+
100mW - 16CH
100mW - 16 VOIES
-
+
500mW - 16CH
500mW - 16 VOIES
-
+
Auto <= 1W - 16CH
Auto <= 1W - 16 VOIES
-
-
+
+
25mW - 8CH
25mW - 8 VOIES
-
-
+
+
25mW - 16CH
25mW - 16 VOIES
-
+
200mW - 16CH (no telemetry)
200mW - 16 VOIES (pas de télémétrie)
-
+
500mW - 16CH (no telemetry)
500mW - 16 VOIES (pas de télémétrie)
-
+
100mW - 16CH (no telemetry)
100mW - 16 VOIES (pas de télémétrie)
+
+
+ 25 mW
+
+
+
+
+ 100 mW
+
+
+
+
+ 500 mW
+
+
+
+
+ 1 W
+
+
+
+
+ 2 W
+
+
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
@@ -9425,11 +9477,6 @@ Mixage actif par défaut si non-renseigné.
Telemetry
Télémétrie
-
-
- Offset
- Décalage
-
@@ -9480,7 +9527,7 @@ Mixage actif par défaut si non-renseigné.
-
+
Name
Nom
@@ -9551,7 +9598,7 @@ Mixage actif par défaut si non-renseigné.
-
+
Type
@@ -9626,165 +9673,118 @@ Mixage actif par défaut si non-renseigné.
Fonctions spéciales
-
+
Protocol
Protocole
-
+
Low
Faible
-
+
Critical
Critique
-
+
Telemetry audio
Audio télémétrie
-
+
Altimetry
Altimétrie
-
-
+
+
Vario source
Source vario
-
+
Vario limits >
Limites vario >
-
+
Sink max
Chute max
-
+
Sink min
Chute min
-
+
Climb min
Pompe min
-
+
Climb max
Pompe max
-
+
Center silent
Silence centrer
-
+
Top Bar
Barre de titre de l'écran d'accueil
-
-
+
Volts source
Source de la tension
-
+
Altitude source
Source de l'altitude
-
- Various
- Divers
-
-
-
- Serial protocol
- Protocole série
-
-
-
- FAS offset
- Décalage FAS
-
-
-
- mAh count
- Compteur mAh
-
-
-
- Persistent mAh
- Mémorisation des mAh
-
-
-
- Current source
- Source de mesure de courant
-
-
-
- Blades
- Pales
-
-
-
+
Parameters
Paramètres
-
+
Telemetry Sensors
Capteurs Télémétrie
-
+
Telemetry Screens
Écrans Télémétrie
-
+
GF%1
FG%1
-
+
Global Functions
Fonctions globales
-
+
Checklist
-
-
- Analogs
- Analogiques
-
-
Unit
Unité
-
- Scale
- Echelle
-
-
-
+
RSSI Alarms
Alarmes RSSI
@@ -9808,13 +9808,13 @@ Mixage actif par défaut si non-renseigné.
- Telemetry
- Télémetrie
+ RF power
+ Puissance HF
- Radio output power
- Puissance de sortie
+ Telemetry
+ Télémetrie
@@ -9863,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
@@ -10145,25 +10145,20 @@ Mixage actif par défaut si non-renseigné.
RadioInterface
-
+
Cannot write file %1:
%2.
Impossible d'écrire le fichier %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>AVERTISSEMENT !</u></b><br>Ceci réinitialisera les fusibles %1 à leur valeur par défaut.<br>Modifier les fusibles peut entraîner le blocage de votre émetteur.<br>Ne l'effectuer que si vous êtes certain qu'ils sont incorrects !<br>Etes-vous sûr de vouloir continuer ?
-
-
-
-
+
+
Could not delete temporary file: %1
Impossible d'effacer le fichier temporaire %1
-
+
Unable to find radio SD card!
Impossible de trouver la carte SD de la radio!
@@ -10303,439 +10298,131 @@ E
RawSource
-
-
-
-
+
V
-
-
-
-
+
+
s
-
- ft
-
-
-
-
-
- m
-
-
-
-
- °C
-
-
-
-
- °
-
-
-
-
- %
-
-
-
-
-
- mph
-
-
-
-
-
- km/h
-
-
-
-
- m/s
-
-
-
-
- A
-
-
-
-
- mAh
-
-
-
-
- W
-
-
-
-
- g
-
-
-
-
+
TrmR
TrmD
-
+
TrmE
TrmP
-
+
TrmT
TrmG
-
+
TrmA
TrmA
-
+
Trm5
-
+
Trm6
-
+
TrmH
-
+
TrmV
-
-
+
Batt
-
-
+
Time
Temps
-
-
+
Timer1
Chrono 1
-
-
+
Timer2
Chrono 2
-
-
+
Timer3
Chrono 3
-
- RSSI Tx
-
-
-
-
- RSSI Rx
-
-
-
-
- RAS
-
-
-
-
- A1
-
-
-
-
- A2
-
-
-
-
- A3
-
-
-
-
- A4
-
-
-
-
- Alt
- Altitude
-
-
-
- Rpm
-
-
-
-
- Fuel
- Carburant
-
-
-
- T1
-
-
-
-
- T2
-
-
-
-
- Speed
- Vitesse
-
-
-
- Dist
- Distance
-
-
-
- GPS Alt
- Altitude GPS
-
-
-
- Cell
- Element LiPo
-
-
-
- Cells
- Velm
-
-
-
- Vfas
- Vfas
-
-
-
- Curr
- Courant
-
-
-
- Cnsp
- Consommation
-
-
-
- Powr
- Puissance
-
-
-
- AccX
-
-
-
-
- AccY
-
-
-
-
- AccZ
-
-
-
-
- Hdg
- Cap
-
-
-
- VSpd
- Vitesse Verticale
-
-
-
- AirSpeed
- Vitesse Air
-
-
-
- dTE
-
-
-
-
- A1-
-
-
-
-
- A2-
-
-
-
-
- A3-
-
-
-
-
- A4-
-
-
-
-
- Alt-
-
-
-
-
- Alt+
-
-
-
-
- Rpm+
-
-
-
-
- T1+
-
-
-
-
- T2+
-
-
-
-
- Speed+
- Vit+
-
-
-
- Dist+
-
-
-
-
- AirSpeed+
- VitA+
-
-
-
- Cell-
- Elem-
-
-
-
- Cells-
- Velm-
-
-
-
- Vfas-
-
-
-
-
- Curr+
- Cour+
-
-
-
- Powr+
- Puis+
-
-
-
- ACC
-
-
-
-
- GPS Time
- Heure GPS
-
-
-
+
REa
-
+
REb
-
-
+
+
???
-
+
----
-
+
I
as in Input
E
-
+
LUA%1%2
-
+
MAX
-
+
CYC%1
-
+
TR
as in Trainer
-
+
SRC
@@ -11104,7 +10791,22 @@ E
-
+
+ Hertz
+
+
+
+
+ mS
+
+
+
+
+ uS
+
+
+
+
TELE
@@ -11286,87 +10988,92 @@ 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?
-
+
+ Cut Timer. Are you sure?
+ Couper le Chrono. Êtes-vous sûr?
+
+
+
Delete Timer. Are you sure?
Supprimer le Chrono. Êtes-vous sûr?
@@ -12090,62 +11797,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)
@@ -12791,11 +12498,6 @@ Trop d'erreurs, abandon.
mAmps (mA)
Courant (mA)
-
-
- Range
- Plage
-
TelemetryCustomScreen
@@ -12805,22 +12507,22 @@ Trop d'erreurs, abandon.
Type d'écran personnalisé
-
+
None
Aucun
-
+
Numbers
Chiffres
-
+
Bars
Barres
-
+
Script
@@ -12848,107 +12550,112 @@ 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
-
+
---
+
+
+ Delete Sensor. Are you sure?
+ Supprimer le Capteur. Êtes-vous sûr?
+
TelemetrySensor
@@ -13243,67 +12950,92 @@ 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
-
+
+ Insert
+ Insérer
+
+
+
+ Delete
+ Supprimer
+
+
+
+ Move Up
+ Monter
+
+
+
+ Move Down
+ Descendre
+
+
+
Clear All
Effacer Tout
-
+
+ Cut Telemetry Sensor. Are you sure?
+ Couper le capteur de télémétrie. Êtes-vous sûr?
+
+
+
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?
@@ -13695,6 +13427,12 @@ hh:mm:ss
Timer %1
Chrono %1
+
+
+ TMR
+ as in Timer
+
+
TimerEdit
@@ -13724,37 +13462,37 @@ Utilisez CTRL + le défilement de la souris ou les touches PAGE HAUT/PAGE BAS po
TimerPanel
-
+
Silent
Aucun
-
+
Beeps
Bips
-
+
Voice
Voix
-
+
Haptic
Vibreur
-
+
Not persistent
Non persistant
-
+
Persistent (flight)
Persistant (vol)
-
+
Persistent (manual reset)
Persistant (RAZ manuelle)
@@ -14309,128 +14047,68 @@ Extra long : bips extra longs.
burnConfigDialog
-
-
+
Port
-
- List all available programmers.
- Lister tous les programmateurs supportés.
-
-
-
-
-
-
+
+
+
The location of the AVRDUDE executable.
The location of the AVRDUDE.EXE executable.
Chemin d'accès de l'exécutable AVRDUDE.
-
+
DFU-Util Location
Chemin de DFU-UTIL
-
-
-
+
+
Use this button to browse and look for the AVRDUDE executable file.
Utiliser ce bouton pour parcourir à la recherche du fichier exécutable AVRDUDE.EXE.
-
- Programmer used for communicating with the controller.
-Please consult the programmer's documentation and the AVRDUDE documentation to select the appropriate programmer.
- Programmateur utilisé pour la communication avec le contrôleur.
-Consulter la documentation du programmateur utilisé et celle d'AVRDUDE pour effectuer le choix approprié.
-
-
-
- Communication port to the programmer.
-
- Port de communication pour le programmateur.
-
-
-
-
- MCU
- Processeur
-
-
-
+
at91sam3s8-9xr
-
+
Alternate device
Dispositif alternatif
-
+
Use advanced controls
Utiliser les contrôles avancés
-
- Extra Arguments
- Paramètres supplémentaires
-
-
-
- Show Help
- Aide
-
-
-
-
-
+
+
Browse...
Parcourir...
-
+
DFU-UTIL Configuration
Configuration de DFU-UTIL
-
+
SAM-BA Configuration
Configuration de SAM-BA
-
-
-
+
+
Select Location
Choisir l'emplacement
-
- List available programmers
- Lister les programmateurs supportés
-
-
-
- Avrdude help
- Aide d'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>ATTENTION !</u></b><br>Le type de processeur est normalement choisi automatiquement pour le firmware sélectionné.<br>Si vous le changez, l'EEPROM peut être corrompue lors du transfert.
-
-
-
- List Available
- Affiche Liste
-
-
-
-
+
Extra arguments used in AVRDUDE.
This can be used for providing extra information to AVRDUDE.
@@ -14440,16 +14118,6 @@ Permet de fournir des informations supplémentaires à AVRDUDE.
A n'utiliser qu'en connaissance de cause: il n'y a pas de contrôle d'erreur et votre programmateur pourrait être endommagé.
-
-
- AVRDUDE Location
- Emplacement d'AVRDUDE
-
-
-
- Show AVRDUDE help
- Affiche l'aide d'AVRDUDE
-
Programmer Configuration
@@ -14457,58 +14125,40 @@ A n'utiliser qu'en connaissance de cause: il n'y a pas de contrô
Configuration du programmateur
-
-
+
Extra arguments that will be passed to AVRDUDE on every call
Paramètres complémentaires passés à chaque appel d'AVRDUDE
-
- AVRDUDE Configuration
- Configuration d'AVRDUDE
-
-
-
- Location of AVRDUDE executable
- Chemin d'accès de l'exécutable AVRDUDE
-
-
-
- Programmer
- Programmateur
-
-
-
-
+
CPU of your TX
CPU de l'émetteur
-
-
+
CPU present on your 9x radio
Should be m64 for stock radios
m2560 for v4.1 boards
CPU de l'émetteur. Devrait être m64 pour les cartes d'origine, m2560 pour les cartes Gruvin9x v4.x
-
+
SAM-BA Location
Emplacement de SAM-BA
-
-
+
+
Location of sam-ba executable
Emplacement de l'exécutable SAM-BA
-
+
ARM MCU
Processeur ARM
-
+
sam-ba serial port
Port série de SAM-BA
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/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/DSM FwdPrg.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/DSM FwdPrg.lua
new file mode 100644
index 000000000..c756634d9
--- /dev/null
+++ b/radio/sdcard/horus/SCRIPTS/TOOLS/DSM FwdPrg.lua
@@ -0,0 +1,557 @@
+local toolName = "TNS|DSM Forward Programming|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. #
+---- # #
+---- #########################################################################
+
+
+--###############################################################################
+-- Multi buffer for DSM description
+-- Multi_Buffer[0..2]=="DSM" -> Lua script is running
+-- Multi_Buffer[3]==0x70+len -> TX to RX data ready to be sent
+-- Multi_Buffer[4..9]=6 bytes of TX to RX data
+-- Multi_Buffer[10..25]=16 bytes of RX to TX data
+--
+-- To start operation:
+-- Write 0x00 at address 3
+-- Write 0x00 at address 10
+-- Write "DSM" at address 0..2
+--###############################################################################
+
+local RX_VERSION, WAIT_CMD, MENU_TITLE, MENU_LINES, MENU_VALUES, VALUE_CHANGING, VALUE_CHANGING_WAIT, VALUE_CHANGED = 0, 1, 2, 3, 4, 5, 6, 7
+local MENU, LIST_MENU_NOCHANGING, LIST_MENU2, PERCENTAGE_VALUE = 0x1C, 0x6C, 0x4C, 0xC0
+local Phase = RX_VERSION
+local Waiting_RX = 0
+local Text = {}
+local Retry=100
+local Blink = 0
+local Value_Changed=0
+
+local Menu = { Cur=nil, Id=nil, Title="", Prev=nil, PrevId=nil, Next=nil, NextId=nil, Back=nil, BackId=nil, CurLine=nil, SelLine=nil, EditLine=nil }
+local Line = {}
+local RX = { Name="", Version="" }
+
+local function conv_int16(number)
+ if number >= 0x8000 then
+ return number - 0x10000
+ end
+ return number
+end
+
+local function Get_Text(index)
+ out = Text[index]
+ if out == nil then -- unknown...
+ out = "Unknown_"..string.format("%X",index)
+ end
+ return out
+end
+
+local function DSM_Release()
+ multiBuffer( 0, 0 )
+end
+
+local function DSM_Send(...)
+ local arg = {...}
+ for i = 1 , #arg do
+ multiBuffer( 3+i, arg[i])
+ end
+ multiBuffer( 3, 0x70+#arg)
+end
+
+local function Value_Add(dir)
+ local line=Line[Menu.SelLine]
+ Speed = getRotEncSpeed()
+ if Speed == ROTENC_MIDSPEED then
+ line.Val = line.Val + (5 * dir)
+ elseif Speed == ROTENC_HIGHSPEED then
+ line.Val = line.Val + (15 * dir)
+ else
+ line.Val = line.Val + dir
+ end
+ if line.Val > line.Max then
+ line.Val = line.Max
+ elseif line.Val < line.Min then
+ line.Val = line.Min
+ end
+ if Line[Menu.SelLine].Type ~= LIST_MENU_NOCHANGING then
+ Phase = VALUE_CHANGING
+ Waiting_RX = 0
+ end
+end
+
+local function DSM_Menu(event)
+ local Speed = 0
+ if event == EVT_VIRTUAL_NEXT then
+ if Menu.EditLine == nil then
+ -- not changing a value
+ if Menu.SelLine ~= nil then
+ if Menu.SelLine < 7 then
+ local num = Menu.SelLine
+ for i = Menu.SelLine + 1, 6, 1 do
+ if Line[i].Type ~= nil and Line[i].Next ~= nil then
+ Menu.SelLine=i
+ break
+ end
+ end
+ if num == Menu.SelLine then
+ if Menu.Next ~= 0 then -- Next
+ Menu.SelLine = 7
+ elseif Menu.Prev ~= 0 then -- Prev
+ Menu.SelLine = 8
+ end
+ end
+ elseif Menu.Prev ~= 0 then -- Prev
+ Menu.SelLine = 8
+ end
+ end
+ else -- need to inc the value
+ Value_Add(1)
+ end
+ elseif event == EVT_VIRTUAL_PREV then
+ if Menu.EditLine == nil then
+ if Menu.SelLine ~= nil then
+ if Menu.SelLine == 8 and Menu.Next ~= 0 then
+ Menu.SelLine = 7
+ elseif Menu.SelLine > 0 then
+ if Menu.SelLine > 6 then
+ Menu.SelLine = 7
+ end
+ local num = Menu.SelLine
+ for i = Menu.SelLine-1, 0, -1 do
+ if Line[i].Type ~= nil and Line[i].Next ~= nil then
+ Menu.SelLine=i
+ break
+ end
+ end
+ if num == Menu.SelLine then -- Back
+ Menu.SelLine = -1
+ end
+ else
+ Menu.SelLine = -1 -- Back
+ end
+ end
+ else -- need to dec the value
+ Value_Add(-1)
+ end
+ elseif event == EVT_VIRTUAL_ENTER then
+ if Menu.SelLine == -1 then -- Back
+ Menu.Cur = Menu.Back
+ Menu.Id = Menu.BackId
+ Menu.SelLine = 0
+ Phase = MENU_TITLE
+ Waiting_RX = 0
+ elseif Menu.SelLine == 7 then -- Next
+ Menu.Cur = Menu.Next
+ Menu.Id = Menu.NextId
+ Menu.SelLine = 0
+ Phase = MENU_TITLE
+ Waiting_RX = 0
+ elseif Menu.SelLine == 8 then -- Prev
+ Menu.Cur = Menu.Prev
+ Menu.Id = Menu.PrevId
+ Menu.SelLine = 0
+ Phase = MENU_TITLE
+ Waiting_RX = 0
+ elseif Menu.SelLine ~= nil and Line[Menu.SelLine].Next ~= nil then
+ if Line[Menu.SelLine].Type == MENU then -- Next menu exist
+ Menu.Cur = Line[Menu.SelLine].Next
+ Menu.Id = Line[Menu.SelLine].NextId
+ Phase = MENU_TITLE
+ Waiting_RX = 0
+ else
+ -- value entry
+ if Menu.EditLine == Menu.SelLine then
+ Menu.EditLine = nil
+ Value_Changed = 0
+ Phase = VALUE_CHANGED
+ Waiting_RX = 0
+ else
+ Menu.EditLine = Menu.SelLine
+ end
+ end
+ end
+ end
+end
+
+local function DSM_Send_Receive()
+ if Waiting_RX == 0 then
+ Waiting_RX = 1
+ -- Need to send a request
+ if Phase == RX_VERSION then -- request RX version
+ DSM_Send(0x11,0x06,0x00,0x14,0x00,0x00)
+ elseif Phase == WAIT_CMD then -- keep connection open
+ DSM_Send(0x00,0x04,0x00,0x00)
+ elseif Phase == MENU_TITLE then -- request menu title
+ if Menu.Cur == nil then
+ DSM_Send(0x12,0x06,0x00,0x14,0x00,0x00) -- first menu only
+ Menu.Cur = 0
+ else
+ DSM_Send(0x16,0x06,Menu.Id,Menu.Cur,0x00,Menu.SelLine)
+ end
+ elseif Phase == MENU_LINES then -- request menu lines
+ if Menu.CurLine == nil then
+ DSM_Send(0x13,0x04,Menu.Id,Menu.Cur) -- line 0
+ elseif Menu.CurLine >= 0x80 then
+ local last_byte={0x40,0x01,0x02,0x04,0x00,0x00} -- unknown...
+ DSM_Send(0x20,0x06,Menu.CurLine-0x80,Menu.CurLine-0x80,0x00,last_byte[Menu.CurLine-0x80+1]) -- line X
+ else
+ DSM_Send(0x14,0x06,Menu.Id,Menu.Cur,0x00,Menu.CurLine) -- line X
+ end
+ elseif Phase == MENU_VALUES then -- request menu values
+ DSM_Send(0x15,0x06,Menu.Id,Menu.Cur,Line[Menu.CurLine].ValId,Menu.CurLine) -- line X
+ elseif Phase == VALUE_CHANGING then -- send value
+ local value=Line[Menu.SelLine].Val
+ if value < 0 then
+ value = 0x10000 + value
+ end
+ DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Menu.SelLine,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value
+ Phase = VALUE_CHANGING_WAIT
+ elseif Phase == VALUE_CHANGED then -- send value
+ if Value_Changed == 0 then
+ local value=Line[Menu.SelLine].Val
+ if value < 0 then
+ value = 0x10000 + value
+ end
+ DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Menu.SelLine,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value
+ Value_Changed = Value_Changed + 1
+ Waiting_RX = 0
+ elseif Value_Changed == 1 then
+ DSM_Send(0x19,0x06,Line[Menu.SelLine].ValId,Menu.SelLine) -- validate
+ -- Value_Changed = Value_Changed + 1
+ -- Waiting_RX = 0
+ --elseif Value_Changed == 2 then
+ -- DSM_Send(0x1B,0x06,0x10,Menu.SelLine) -- validate again?
+ -- Value_Changed = Value_Changed + 1
+ end
+ elseif Phase == VALUE_CHANGING_WAIT then
+ DSM_Send(0x1A,0x06,Line[Menu.SelLine].ValId,Menu.SelLine)
+ end
+ multiBuffer(10,0x00);
+ Retry = 50
+ elseif multiBuffer(10) == 0x09 then
+ -- Answer received
+ --if multiBuffer(11) == 0x00 then -- waiting for commands?
+ if multiBuffer(11) == 0x01 then -- read version
+ --ex: 0x09 0x01 0x00 0x15 0x02 0x22 0x01 0x00 0x14 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ RX.Name = Get_Text(multiBuffer(13))
+ RX.Version = multiBuffer(14).."."..multiBuffer(15).."."..multiBuffer(16)
+ Phase = MENU_TITLE
+ elseif multiBuffer(11) == 0x02 then -- read menu title
+ --ex: 0x09 0x02 0x4F 0x10 0xA5 0x00 0x00 0x00 0x50 0x10 0x10 0x10 0x00 0x00 0x00 0x00
+ Menu.Cur = multiBuffer(12)
+ Menu.Id = multiBuffer(13)
+ Menu.Title = Get_Text(multiBuffer(14)+multiBuffer(15)*256)
+ Menu.Prev = multiBuffer(16)
+ Menu.PrevId = multiBuffer(17)
+ Menu.Next = multiBuffer(18)
+ Menu.NextId = multiBuffer(19)
+ Menu.Back = multiBuffer(20)
+ Menu.BackId = multiBuffer(21)
+ for i = 0, 6 do -- clear menu
+ Line[i] = { Menu = nil, Id = nil, Type = nil, Text="", Next = nil, NextId = nil, ValLine = nil, ValId = nil, Min, Max, Def, Val, Unit, Step }
+ end
+ Menu.CurLine = nil
+ if Menu.Next ~= 0 then
+ Menu.SelLine = 7 -- highlight Next
+ else
+ Menu.SelLine = -1 -- highlight Back
+ end
+ Blink = 0
+ Phase = MENU_LINES
+ elseif multiBuffer(11) == 0x03 then -- read menu lines
+ --ex: 0x09 0x03 0x00 0x10 0x00 0x1C 0xF9 0x00 0x10 0x10 0x00 0x00 0x00 0x00 0x03 0x00
+ -- Menu Id line Type Text_idx Next V_Id Val_Min Val_Max Val_Def
+ --ex: 0x09 0x03 0x61 0x10 0x00 0x6C 0x50 0x00 0x00 0x10 0x36 0x00 0x49 0x00 0x36 0x00
+ Menu.CurLine = multiBuffer(14)
+ local line = Line[Menu.CurLine]
+ line.Menu = multiBuffer(12)
+ line.Id = multiBuffer(13) -- not quite sure yet
+ line.Type = multiBuffer(15) -- not quite sure yet: 1C is text menu only, 4C/6C is text followed by text list, C0 is text followed by percentage value
+ line.Text = Get_Text(multiBuffer(16)+multiBuffer(17)*256)
+ if multiBuffer(18) == Menu.Cur then
+ line.Next = nil
+ else
+ line.Next = multiBuffer(18) -- not quite sure yet: 1C=text menu=>next menu, others=>line number of the value
+ end
+ if Menu.SelLine == -1 and line.Next ~= nil then -- Auto select first line of the menu
+ Menu.SelLine = Menu.CurLine
+ end
+ line.NextId = multiBuffer(19) -- not quite sure yet
+ line.ValLine = multiBuffer(18) -- not quite sure yet
+ line.ValId = multiBuffer(19) -- not quite sure yet
+ line.Min = conv_int16(multiBuffer(20)+multiBuffer(21)*256)
+ line.Max = conv_int16(multiBuffer(22)+multiBuffer(23)*256)
+ line.Def = conv_int16(multiBuffer(24)+multiBuffer(25)*256)
+ if line.Type == MENU then
+ -- nothing to do on menu entries
+ elseif line.Type == LIST_MENU_NOCHANGING or line.Type == LIST_MENU2 then
+ line.Val = nil --line.Def - line.Min -- use default value not sure if needed
+ line.Def = line.Min -- pointer to the start of the list in Text
+ line.Max = line.Max - line.Min -- max index
+ line.Min = 0 -- min index
+ else -- default to numerical value
+ line.Val = nil --line.Def -- use default value not sure if needed
+ end
+ if line.Type ~= 0x1C then -- value to follow
+ line.Text = line.Text..":"
+ end
+ Phase = MENU_LINES
+ elseif multiBuffer(11) == 0x04 then -- read menu values
+ --ex: 0x09 0x04 0x53 0x10 0x00 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ -- Menu MeId line VaId Value
+ --ex: 0x09 0x04 0x61 0x10 0x02 0x10 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ Menu.CurLine = multiBuffer(14)
+ Line[Menu.CurLine].Val = conv_int16(multiBuffer(16)+multiBuffer(17)*256)
+ Phase = MENU_VALUES
+ elseif multiBuffer(11) == 0x05 then -- unknown... need to get through the lines...
+ Menu.CurLine = 0x80 + multiBuffer(12)
+ Phase = MENU_LINES
+ elseif multiBuffer(11) == 0x00 and Phase == VALUE_CHANGING then
+ Phase = VALUE_CHANGING_WAIT
+ end
+ -- Data processed
+ Waiting_RX = 0
+ multiBuffer(10,0x00)
+ Retry = 50
+ else
+ Retry = Retry - 1
+ if Retry <= 0 then
+ -- Retry the RX request
+ Retry = 50
+ Waiting_RX = 0
+ if Phase ~= RX_VERSION and Phase ~= VALUE_CHANGING_WAIT then
+ Phase = WAIT_CMD
+ end
+ end
+ end
+end
+
+local function DSM_Display()
+ lcd.clear()
+ if LCD_W == 480 then
+ --Draw title
+ lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
+ lcd.drawText(1, 5, "DSM Forward Programming", MENU_TITLE_COLOR)
+ --Draw RX Menu
+ if Phase == RX_VERSION then
+ lcd.drawText(10,50,"No compatible DSM RX...", BLINK)
+ else
+ if Menu.Title ~= nil then
+ local attrib=0;
+ lcd.drawText(80,32,Menu.Title,MIDSIZE)
+ for i = 0, 6 do
+ if i == Menu.SelLine then
+ attrib = INVERS
+ else
+ attrib = 0
+ end
+ if Line[i] ~= nil and Line[i].Type ~= nil then
+ if Line[i].Type ~= MENU then -- list/value
+ if Line[i].Val ~= nil then
+ local text=""
+ if Line[i].Type == LIST_MENU_NOCHANGING or Line[i].Type == LIST_MENU2 then
+ text = Get_Text(Line[i].Val+Line[i].Def)
+ elseif Line[i].Type == PERCENTAGE_VALUE then
+ text = Line[i].Val.." %"
+ else
+ text = Line[i].Val
+ end
+ if Menu.EditLine == Menu.SelLine then -- blink edited entry
+ Blink = Blink + 1
+ if Blink > 25 then
+ attrib = 0
+ if Blink > 50 then
+ Blink = 0
+ end
+ end
+ end
+ lcd.drawText(240,32+20*(i+2), text, attrib) -- display value
+ end
+ attrib = 0
+ end
+ lcd.drawText(10,32+20*(i+2), Line[i].Text, attrib) -- display text
+ end
+ end
+ if Menu.SelLine == -1 then
+ lcd.drawText(437,32, "Back", INVERS)
+ else
+ lcd.drawText(437,32, "Back", 0)
+ end
+ lcd.drawRectangle(437-5, 32-2, 47, 25)
+ if Menu.Next ~= 0 then
+ if Menu.SelLine == 7 then
+ lcd.drawText(437,220, "Next",INVERS)
+ else
+ lcd.drawText(437,220, "Next")
+ end
+ lcd.drawRectangle(437-5, 220-2, 47, 25)
+ end
+ if Menu.Prev ~= 0 then
+ if Menu.SelLine == 8 then
+ lcd.drawText(5,220, "Prev",INVERS)
+ else
+ lcd.drawText(5,220, "Prev")
+ end
+ lcd.drawRectangle(5-5, 220-2, 47, 25)
+ end
+ end
+ lcd.drawText(170,252, "RX "..RX.Name.." v"..RX.Version) -- display RX info
+ end
+ else
+ -- --Draw RX Menu on LCD_W=128
+ -- if multiBuffer( 4 ) == 0xFF then
+ -- lcd.drawText(2,17,"No compatible DSM RX...",SMLSIZE)
+ -- else
+ -- if Retry_128 ~= 0 then
+ -- --Intro page
+ -- Retry_128 = Retry_128 - 1
+ -- lcd.drawScreenTitle("DSM Forward Programming",0,0)
+ -- lcd.drawText(2,17,"Press Prev Page for previous Menu" ,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
+ -- end
+ end
+end
+
+-- Init
+local function DSM_Init()
+ --Set protocol to talk to
+ multiBuffer( 0, string.byte('D') )
+ --test if value has been written
+ if multiBuffer( 0 ) ~= string.byte('D') then
+ error("Not enough memory!")
+ return 2
+ end
+ --Init TX buffer
+ multiBuffer( 3, 0x00 )
+ --Init RX buffer
+ multiBuffer( 10, 0x00 )
+ --Init telemetry
+ multiBuffer( 0, string.byte('D') )
+ multiBuffer( 1, string.byte('S') )
+ multiBuffer( 2, string.byte('M') )
+
+ --Text to be displayed -> need to use a file instead?
+ --RX names--
+ Text[0x0014]="SPM4651T"
+ Text[0x0015]="AR637T"
+ --Lists--
+ Text[0x0036]="Throttle"
+ Text[0x0037]="Aileron"
+ Text[0x0038]="Elevator"
+ Text[0x0039]="Rudder"
+ Text[0x003A]="Gear"
+ for i=1,7 do -- 3B..41
+ Text[0x003A+i]="Aux"..i
+ end
+ for i=1,8 do -- 41..49
+ Text[0x0041+i]="XPlus-"..i
+ end
+ Text[0x004A]="Failsafe"
+ Text[0x004B]="Main Menu"
+ Text[0x004E]="Position"
+ Text[0x0050]="Outputs"
+ --Text[0x005E]="Inhibit"
+ Text[0x005F]="Hold Last"
+ Text[0x0060]="Preset"
+ --Text[0x0061]="Custom"
+ --Messages--
+ Text[0x0090]="Apply"
+ Text[0x0093]="Complete"
+ Text[0x0094]="Done"
+ Text[0x0097]="Factory Reset"
+ Text[0x009A]="Capture Failsafe Positions"
+ Text[0x009C]="Custom Failsafe"
+ Text[0x00A5]="First Time Setup"
+ Text[0x00F9]="Gyro settings"
+ Text[0x0100]="Make sure the model has been"
+ Text[0x0101]="configured, including wing type,"
+ Text[0x0102]="reversing, travel, trimmed, etc."
+ Text[0x0103]="before continuing setup."
+ Text[0x0104]=""
+ Text[0x0105]=""
+ Text[0x0106]="Any wing type, channel assignment,"
+ Text[0x0107]="subtrim, or servo reversing changes"
+ Text[0x0108]="require running through initial"
+ Text[0x0109]="setup again."
+ Text[0x010A]=""
+ Text[0x010B]=""
+
+ Text[0x019C]="Enter Receiver Bind Mode"
+ Text[0x020A]="Restore from Backup"
+ Text[0x0209]="Save to Backup"
+
+ Text[0x021A]="Set the model level,"
+ Text[0x021B]="and press Continue."
+ Text[0x021C]=""
+ Text[0x021D]=""
+
+ Text[0x021F]="Set the model on its nose,"
+ Text[0x0220]="and press Continue. If the"
+ Text[0x0221]="orientation on the next"
+ Text[0x0222]="screen is wrong go back"
+ Text[0x0223]="and try again."
+ Text[0x0224]="Continue"
+ Text[0x0229]="Set Orientation Manually"
+
+ Text[0x0227]="Other settings"
+ Text[0x022B]="WARNING!"
+ Text[0x022C]="This will reset the"
+ Text[0x022D]="configuration to factory"
+ Text[0x022E]="defaults. This does not"
+ Text[0x022F]="affect the backup config."
+ Text[0x0230]=""
+ Text[0x0231]="This will overwrite the"
+ Text[0x0232]="backup memory with your"
+ Text[0x0233]="current configuartion."
+ Text[0x0234]=""
+ Text[0x0235]=""
+ Text[0x0236]="This will overwrite the"
+ Text[0x0237]="current config with"
+ Text[0x0238]="that which is in"
+ Text[0x0239]="the backup memory."
+ Text[0x023A]=""
+end
+
+-- Main
+local function DSM_Run(event)
+ if event == nil then
+ error("Cannot be run as a model script!")
+ return 2
+ elseif event == EVT_VIRTUAL_EXIT then
+ DSM_Release()
+ return 2
+ else
+ DSM_Menu(event)
+ DSM_Send_Receive()
+ DSM_Display()
+ return 0
+ end
+end
+
+return { init=DSM_Init, run=DSM_Run }
diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky RB30_RB40.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky RB30_RB40.lua
new file mode 100644
index 000000000..213faa6cf
--- /dev/null
+++ b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky RB30_RB40.lua
@@ -0,0 +1,464 @@
+--- - #########################################################################
+---- # #
+---- # 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 version = "v1.01"
+
+local VALUE = 0
+local COMBO = 1
+
+local edit = false
+local page = 1
+local current = 1
+local refreshState = 0
+local refreshIndex = 0
+local pageOffset = 0
+local pages = {}
+local fields = {}
+local modifications = {}
+local margin = 1
+local spacing = 8
+local numberPerPage = 7
+
+local configFields = {
+ { "Self_stable mode", COMBO, 0x80, nil, { "disable", "enable"} },
+ { "Sbus out", COMBO, 0x81, nil, { "disable", "enable"} },
+ { "VOut1(V)", VALUE, 0xB2, nil, 50, 84},
+ { "VOut2(V)", VALUE, 0xB3, nil, 50, 84},
+}
+
+
+local failsafeFields = {
+ { "CH1 failsafe", VALUE, 0x82, 150, 80, 220},
+ { "CH2 failsafe", VALUE, 0x82, 150, 80, 220},
+ { "CH3 failsafe", VALUE, 0x83, 150, 80, 220},
+ { "CH4 failsafe", VALUE, 0x83, 150, 80, 220},
+ { "CH5 failsafe", VALUE, 0x84, 150, 80, 220},
+ { "CH6 failsafe", VALUE, 0x84, 150, 80, 220},
+ { "CH7 failsafe", VALUE, 0x85, 150, 80, 220},
+ { "CH8 failsafe", VALUE, 0x85, 150, 80, 220},
+ { "CH9 failsafe", VALUE, 0x86, 150, 80, 220},
+ { "CH10 failsafe", VALUE, 0x86, 150, 80, 220},
+ { "CH11 failsafe", VALUE, 0x87, 150, 80, 220},
+ { "CH12 failsafe", VALUE, 0x87, 150, 80, 220},
+ { "CH13 failsafe", VALUE, 0x88, 150, 80, 220},
+ { "CH14 failsafe", VALUE, 0x88, 150, 80, 220},
+ { "CH15 failsafe", VALUE, 0x89, 150, 80, 220},
+ { "CH16 failsafe", VALUE, 0x89, 150, 80, 220},
+ { "CH17 failsafe", VALUE, 0x8A, 150, 80, 220},
+ { "CH18 failsafe", VALUE, 0x8A, 150, 80, 220},
+ { "CH19 failsafe", VALUE, 0x8B, 150, 80, 220},
+ { "CH20 failsafe", VALUE, 0x8B, 150, 80, 220},
+ { "CH21 failsafe", VALUE, 0x8C, 150, 80, 220},
+ { "CH22 failsafe", VALUE, 0x8C, 150, 80, 220},
+ { "CH23 failsafe", VALUE, 0x8D, 150, 80, 220},
+ { "CH24 failsafe", VALUE, 0x8D, 150, 80, 220},
+}
+
+local rx1PinMapFields = {
+ { "CH1 RX1 map", VALUE, 0x8E, 1, 0, 16},
+ { "CH2 RX1 map", VALUE, 0x8E, 2, 0, 16},
+ { "CH3 RX1 map", VALUE, 0x8F, 3, 0, 16},
+ { "CH4 RX1 map", VALUE, 0x8F, 4, 0, 16},
+ { "CH5 RX1 map", VALUE, 0x90, 5, 0, 16},
+ { "CH6 RX1 map", VALUE, 0x90, 6, 0, 16},
+ { "CH7 RX1 map", VALUE, 0x91, 7, 0, 16},
+ { "CH8 RX1 map", VALUE, 0x91, 8, 0, 16},
+ { "CH9 RX1 map", VALUE, 0x92, 9, 0, 16},
+ { "CH10 RX1 map", VALUE, 0x92, 10, 0, 16},
+ { "CH11 RX1 map", VALUE, 0x93, 11, 0, 16},
+ { "CH12 RX1 map", VALUE, 0x93, 12, 0, 16},
+ { "CH13 RX1 map", VALUE, 0x94, 13, 0, 16},
+ { "CH14 RX1 map", VALUE, 0x94, 14, 0, 16},
+ { "CH15 RX1 map", VALUE, 0x95, 15, 0, 16},
+ { "CH16 RX1 map", VALUE, 0x95, 16, 0, 16},
+ { "CH17 RX1 map", VALUE, 0x96, 1, 0, 16},
+ { "CH18 RX1 map", VALUE, 0x96, 2, 0, 16},
+ { "CH19 RX1 map", VALUE, 0x97, 3, 0, 16},
+ { "CH20 RX1 map", VALUE, 0x97, 4, 0, 16},
+ { "CH21 RX1 map", VALUE, 0x98, 5, 0, 16},
+ { "CH22 RX1 map", VALUE, 0x98, 6, 0, 16},
+ { "CH23 RX1 map", VALUE, 0x99, 7, 0, 16},
+ { "CH24 RX1 map", VALUE, 0x99, 8, 0, 16},
+}
+
+local rx2PinMapFields = {
+ { "CH1 RX2 map", VALUE, 0x9A, 1, 0, 16},
+ { "CH2 RX2 map", VALUE, 0x9A, 2, 0, 16},
+ { "CH3 RX2 map", VALUE, 0x9B, 3, 0, 16},
+ { "CH4 RX2 map", VALUE, 0x9B, 4, 0, 16},
+ { "CH5 RX2 map", VALUE, 0x9C, 5, 0, 16},
+ { "CH6 RX2 map", VALUE, 0x9C, 6, 0, 16},
+ { "CH7 RX2 map", VALUE, 0x9D, 7, 0, 16},
+ { "CH8 RX2 map", VALUE, 0x9D, 8, 0, 16},
+ { "CH9 RX2 map", VALUE, 0x9E, 9, 0, 16},
+ { "CH10 RX2 map", VALUE, 0x9E, 10, 0, 16},
+ { "CH11 RX2 map", VALUE, 0x9F, 11, 0, 16},
+ { "CH12 RX2 map", VALUE, 0x9F, 12, 0, 16},
+ { "CH13 RX2 map", VALUE, 0xA0, 13, 0, 16},
+ { "CH14 RX2 map", VALUE, 0xA0, 14, 0, 16},
+ { "CH15 RX2 map", VALUE, 0xA1, 15, 0, 16},
+ { "CH16 RX2 map", VALUE, 0xA0, 16, 0, 16},
+ { "CH17 RX2 map", VALUE, 0xA2, 1, 0, 16},
+ { "CH18 RX2 map", VALUE, 0xA2, 2, 0, 16},
+ { "CH19 RX2 map", VALUE, 0xA3, 3, 0, 16},
+ { "CH20 RX2 map", VALUE, 0xA3, 4, 0, 16},
+ { "CH21 RX2 map", VALUE, 0xA4, 5, 0, 16},
+ { "CH22 RX2 map", VALUE, 0xA4, 6, 0, 16},
+ { "CH23 RX2 map", VALUE, 0xA5, 7, 0, 16},
+ { "CH24 RX2 map", VALUE, 0xA5, 8, 0, 16},
+}
+
+local rx3PinMapFields = {
+ { "CH1 RX3 map", VALUE, 0xA6, 1, 0, 16},
+ { "CH2 RX3 map", VALUE, 0xA6, 2, 0, 16},
+ { "CH3 RX3 map", VALUE, 0xA7, 3, 0, 16},
+ { "CH4 RX3 map", VALUE, 0xA7, 4, 0, 16},
+ { "CH5 RX3 map", VALUE, 0xA8, 5, 0, 16},
+ { "CH6 RX3 map", VALUE, 0xA8, 6, 0, 16},
+ { "CH7 RX3 map", VALUE, 0xA9, 7, 0, 16},
+ { "CH8 RX3 map", VALUE, 0xA9, 8, 0, 16},
+ { "CH9 RX3 map", VALUE, 0xAA, 9, 0, 16},
+ { "CH10 RX3 map", VALUE, 0xAA, 10, 0, 16},
+ { "CH11 RX3 map", VALUE, 0xAB, 11, 0, 16},
+ { "CH12 RX3 map", VALUE, 0xAB, 12, 0, 16},
+ { "CH13 RX3 map", VALUE, 0xAC, 13, 0, 16},
+ { "CH14 RX3 map", VALUE, 0xAC, 14, 0, 16},
+ { "CH15 RX3 map", VALUE, 0xAD, 15, 0, 16},
+ { "CH16 RX3 map", VALUE, 0xAD, 16, 0, 16},
+ { "CH17 RX3 map", VALUE, 0xAE, 1, 0, 16},
+ { "CH18 RX3 map", VALUE, 0xAE, 2, 0, 16},
+ { "CH19 RX3 map", VALUE, 0xAF, 3, 0, 16},
+ { "CH20 RX3 map", VALUE, 0xAF, 4, 0, 16},
+ { "CH21 RX3 map", VALUE, 0xB0, 5, 0, 16},
+ { "CH22 RX3 map", VALUE, 0xB0, 6, 0, 16},
+ { "CH23 RX3 map", VALUE, 0xB1, 7, 0, 16},
+ { "CH24 RX3 map", VALUE, 0xB1, 8, 0, 16},
+}
+
+
+
+
+local function drawScreenTitle(title, page, pages)
+ if math.fmod(math.floor(getTime() / 100), 10) == 0 then
+ title = version
+ end
+ if LCD_W == 480 then
+ lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
+ lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
+ lcd.drawText(LCD_W - 40, 5, page .. "/" .. pages, MENU_TITLE_COLOR)
+ else
+ lcd.drawScreenTitle(title, page, pages)
+ end
+end
+
+-- Change display attribute to current field
+local function addField(step)
+ local field = fields[current]
+ local min, max
+ if field[2] == VALUE then
+ min = field[5]
+ max = field[6]
+ elseif field[2] == COMBO then
+ min = 0
+ max = #(field[5]) - 1
+ end
+ if page == 2 and step < 0 and field[4] == min then
+ field[4] = 0
+ elseif page == 2 and step > 0 and field[4] == 0 then
+ field[4] = min
+ else
+ if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then
+ field[4] = field[4] + step
+ end
+ end
+end
+
+-- Select the next or previous page
+local function selectPage(step)
+ local pagesNum = #pages
+ if configFields[1][4] == 1 then
+ pagesNum = 1
+ elseif configFields[2][4] == 1 then
+ pagesNum = pagesNum - 1
+ end
+ page = 1 + ((page + step - 1 + pagesNum) % pagesNum)
+ refreshIndex = 0
+ pageOffset = 0
+end
+
+-- Select the next or previous editable field
+local function selectField(step)
+ current = 1 + ((current + step - 1 + #fields) % #fields)
+ if current > numberPerPage + pageOffset then
+ pageOffset = current - numberPerPage
+ elseif current <= pageOffset then
+ pageOffset = current - 1
+ end
+end
+
+local function drawProgressBar()
+ if LCD_W == 480 then
+ local width = (300 * refreshIndex) / #fields
+ lcd.drawRectangle(100, 10, 300, 6)
+ lcd.drawFilledRectangle(102, 12, width, 2)
+ else
+ local width = (60 * refreshIndex) / #fields
+ lcd.drawRectangle(45, 1, 60, 6)
+ lcd.drawFilledRectangle(47, 3, width, 2)
+ end
+end
+
+-- Redraw the current page
+local function redrawFieldPage()
+ lcd.clear()
+
+ local pagesNum = #pages
+ if configFields[1][4] == 1 then
+ pagesNum = 1
+ elseif configFields[2][4] == 1 then
+ pagesNum = pagesNum - 1
+ end
+ drawScreenTitle("RB30/RB40", page, pagesNum)
+
+ if refreshIndex < #fields then
+ drawProgressBar()
+ end
+
+ for index = 1, numberPerPage, 1 do
+ local field = fields[pageOffset + index]
+ if field == nil then
+ break
+ end
+
+ local attr = current == (pageOffset + index) and ((edit == true and BLINK or 0) + INVERS) or 0
+
+ lcd.drawText(1, margin + spacing * index, field[1], attr)
+
+ if field[4] == nil then
+ lcd.drawText(LCD_W, margin + spacing * index, "---", RIGHT + attr)
+ else
+ if field[2] == VALUE then
+ if page == 2 then
+ if field[4] == 0 then
+ lcd.drawText(LCD_W, margin + spacing * index, "No pulse", RIGHT + attr)
+ else
+ lcd.drawNumber(LCD_W, margin + spacing * index, field[4] * 10, RIGHT + attr)
+ end
+ else
+ if field[4] == 0 then
+ lcd.drawText(LCD_W, margin + spacing * index, "No map", RIGHT + attr)
+ else
+ if field[3] == 0xB2 or field[3] == 0xB3 then
+ lcd.drawNumber(LCD_W, margin + spacing * index, field[4] , attr + RIGHT + PREC1)
+ else
+ lcd.drawNumber(LCD_W, margin + spacing * index, field[4], RIGHT + attr)
+ end
+ end
+ end
+ elseif field[2] == COMBO then
+ if field[4] >= 0 and field[4] < #(field[5]) then
+ lcd.drawText(LCD_W, margin + spacing * index, field[5][field[4] + 1], RIGHT + attr)
+ end
+ end
+ end
+ end
+end
+
+local function telemetryIdle(field)
+ return sportTelemetryPush(0x1C, 0x21, 0x0b80, field)
+end
+
+local function telemetryUnIdle(field)
+ return sportTelemetryPush(0x1C, 0x20, 0x0b80, field)
+end
+
+local function telemetryRead(field)
+ return sportTelemetryPush(0x1C, 0x30, 0x0b80, field)
+end
+
+local function telemetryWrite(field, value)
+ return sportTelemetryPush(0x1C, 0x31, 0x0b80, field + value * 256)
+end
+
+local telemetryPopTimeout = 0
+local function refreshNext()
+ if refreshState == 0 then
+ if #modifications > 0 then
+ telemetryWrite(modifications[1][1], modifications[1][2])
+ modifications[1] = nil
+ refreshIndex = 0
+ refreshState = 0
+ elseif refreshIndex < #fields then
+ local field = fields[refreshIndex + 1]
+ if page > 1 then
+ field = fields[refreshIndex + 2]
+ end
+ if telemetryRead(field[3]) == true then
+ refreshState = 1
+ telemetryPopTimeout = getTime() + 100 -- normal delay is 500ms
+ end
+ end
+ elseif refreshState == 1 then
+ local physicalId, primId, dataId, value = sportTelemetryPop()
+ if primId == 0x32 and (dataId >= 0x0b80 or dataId <= 0x0b8f) then
+ local fieldId = value % 256
+ local field = fields[refreshIndex + 1]
+ if fieldId == field[3] then
+ value = math.floor(value / 256)
+ if field[2] == COMBO then
+ fields[refreshIndex + 1][4] = value
+ else
+ fields[refreshIndex + 1][4] = value % 256
+ if page > 1 then
+ value = math.floor(value / 256)
+ fields[refreshIndex + 2][4] = value
+ end
+ end
+ if page > 1 then
+ refreshIndex = refreshIndex + 2
+ else
+ refreshIndex = refreshIndex + 1
+ end
+ refreshState = 0
+ end
+ elseif getTime() > telemetryPopTimeout then
+ fields[refreshIndex + 1][4] = nil
+ if page > 1 then
+ fields[refreshIndex + 2][4] = nil
+ refreshIndex = refreshIndex + 2
+ else
+ refreshIndex = refreshIndex + 1
+ end
+ refreshState = 0
+ end
+ end
+end
+
+local function updateField(field)
+ local value = field[4]
+ if field[2] == COMBO and #field == 6 then
+ value = field[6][1 + value]
+ elseif field[2] == VALUE and #field == 8 then
+ value = value + field[8] - field[5]
+ end
+
+ if page > 1 then
+ if current % 2 == 1 then
+ value = value + fields[current + 1][4] * 256
+ elseif current % 2 == 0 then
+ value = fields[current - 1][4] + value * 256
+ end
+ end
+ modifications[#modifications + 1] = { field[3], value }
+end
+
+-- Main
+local function runFieldsPage(event)
+ if event == EVT_VIRTUAL_EXIT then -- exit script
+ telemetryUnIdle(0x80)
+ return 2
+ elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
+ if fields[current][4] ~= nil then
+ edit = not edit
+ if edit == false then
+ updateField(fields[current])
+ end
+ end
+ elseif edit then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
+ addField(1)
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
+ addField(-1)
+ end
+ else
+ if event == EVT_VIRTUAL_NEXT then
+ selectField(1)
+ elseif event == EVT_VIRTUAL_PREV then
+ selectField(-1)
+ end
+ end
+ redrawFieldPage()
+ return 0
+end
+
+local function runConfigPage(event)
+ fields = configFields
+ return runFieldsPage(event)
+end
+
+local function runFailsafePage(event)
+ fields = failsafeFields
+ return runFieldsPage(event)
+end
+
+local function runRx1PinMapPage(event)
+ fields = rx1PinMapFields
+ return runFieldsPage(event)
+end
+
+local function runRx2PinMapPage(event)
+ fields = rx2PinMapFields
+ return runFieldsPage(event)
+end
+
+local function runRx3PinMapPage(event)
+ fields = rx3PinMapFields
+ return runFieldsPage(event)
+end
+
+-- Init
+local function init()
+ current, edit, refreshState, refreshIndex = 1, false, 0, 0
+ if LCD_W == 480 then
+ margin = 10
+ spacing = 20
+ numberPerPage = 12
+ end
+ pages = {
+ runConfigPage,
+ runFailsafePage,
+ runRx1PinMapPage,
+ runRx2PinMapPage,
+ runRx3PinMapPage
+ }
+ telemetryIdle(0x80)
+end
+
+-- Main
+local function run(event)
+ if event == nil then
+ error("Cannot be run as a model script!")
+ return 2
+ elseif event == EVT_VIRTUAL_NEXT_PAGE then
+ if edit == false then
+ selectPage(1)
+ end
+ elseif event == EVT_VIRTUAL_PREV_PAGE then
+ if edit == false then
+ killEvents(event)
+ selectPage(-1)
+ end
+ end
+
+ local result = pages[page](event)
+ refreshNext()
+
+ return result
+end
+
+return { init = init, run = run }
+
diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt
index bf61d8ca6..b03b2c860 100644
--- a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt
+++ b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt
@@ -1,3 +1,47 @@
+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
+14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
+59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
+41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
+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
+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
+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
+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
+33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
+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
+6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+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
+69,0,ESKY150V2,Std,0,CH5_RA,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
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
@@ -7,15 +51,11 @@
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
+28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+53,0,Height,5ch,0,Gear
+53,1,Height,8ch,0,Gear,Gyro,Flap,Light
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
@@ -26,78 +66,50 @@
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
+15,5,FrSkyX,D16Cloned_8CH,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
+64,5,FrSkyX2,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+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
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
+58,0,FX816,P38,1
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
+47,0,GD00x,V1,1,Trim,LED,Rate
+47,1,GD00x,V2,1,Trim,LED,Rate
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
+4,1,Hisky,HK310,0,Aux
+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
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
+57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+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
+22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+71,0,JJRC345,Std,1,Flip,HLess,RTH
+49,0,KF606,Std,1,Trim
+9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
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
@@ -111,6 +123,9 @@
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
+77,0,OMP,M2,0,THold,IdleUp,6G_3D
+60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
+60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8
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
@@ -120,8 +135,15 @@
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
+72,0,Q90C,Std,0,FMode,VTX+
+74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
+74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
+76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK
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
+21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
+19,0,Shenqi,Cycle,1
+68,0,Skyartec,Std,0,CH5,CH6,CH7
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
@@ -129,11 +151,21 @@
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
+61,0,Tiger,Std,1,Flip,Light
+43,0,Traxxas,6519,0
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
+48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
+48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
+46,0,V911s,V911s,1,Calib
+46,1,V911s,E119,1,Calib
+22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
+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
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
@@ -141,17 +173,4 @@
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
index 42de75e4f..14902b782 100644
--- a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
+++ b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
@@ -249,13 +249,13 @@ local function Multi_Init()
--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
+ 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
+ elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH
stick_names[4] = "n-a"
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
stick_names[1] = "n-a"
@@ -278,6 +278,15 @@ local function Multi_Init()
ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = stick_names[1]
end
+
+ --Exceptions on first 4 channels...
+ if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface
+ channel_names[1] = "ST"
+ channel_names[2] = "THR"
+ channel_names[3] = "CH3"
+ channel_names[4] = "CH4"
+ end
+
--Check MultiChan.txt
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
if f == nil then return end
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/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/Flexi/X10.bmp b/radio/sdcard/horus/THEMES/Flexi/X10.bmp
new file mode 100755
index 000000000..32a730cde
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/X10.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/X10S.bmp b/radio/sdcard/horus/THEMES/Flexi/X10S.bmp
new file mode 100644
index 000000000..221e25ec4
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/X10S.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/asterisk.bmp b/radio/sdcard/horus/THEMES/Flexi/asterisk.bmp
new file mode 100644
index 000000000..3dd3cfef4
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/asterisk.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/busy.bmp b/radio/sdcard/horus/THEMES/Flexi/busy.bmp
new file mode 100644
index 000000000..8e6a8b7f7
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/busy.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/horus.bmp b/radio/sdcard/horus/THEMES/Flexi/horus.bmp
new file mode 100644
index 000000000..98bc631cd
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/horus.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_bg.png b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_bg.png
new file mode 100644
index 000000000..715792023
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_bg.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_dot.png b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_dot.png
new file mode 100644
index 000000000..6f76965a9
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_dot.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_shadow.png b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_shadow.png
new file mode 100644
index 000000000..97bf6c577
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_currentmenu_shadow.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_library.png b/radio/sdcard/horus/THEMES/Flexi/mask_library.png
new file mode 100644
index 000000000..237883fc5
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_library.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_menu_model.png b/radio/sdcard/horus/THEMES/Flexi/mask_menu_model.png
new file mode 100644
index 000000000..9832267b7
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_menu_model.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_menu_radio.png b/radio/sdcard/horus/THEMES/Flexi/mask_menu_radio.png
new file mode 100644
index 000000000..6d93fbccc
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_menu_radio.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_menu_stats.png b/radio/sdcard/horus/THEMES/Flexi/mask_menu_stats.png
new file mode 100644
index 000000000..ebd482588
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_menu_stats.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_menu_theme.png b/radio/sdcard/horus/THEMES/Flexi/mask_menu_theme.png
new file mode 100644
index 000000000..3a9fc15e7
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_menu_theme.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_curves.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_curves.png
new file mode 100644
index 000000000..6e1e19e8e
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_curves.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_flight_modes.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_flight_modes.png
new file mode 100644
index 000000000..e963f0abb
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_flight_modes.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_gvars.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_gvars.png
new file mode 100644
index 000000000..0b5015dac
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_gvars.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_heli.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_heli.png
new file mode 100644
index 000000000..ecd93d2ff
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_heli.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_inputs.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_inputs.png
new file mode 100644
index 000000000..720099c47
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_inputs.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_logical_switches.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_logical_switches.png
new file mode 100644
index 000000000..5cd1e3834
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_logical_switches.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_lua_scripts.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_lua_scripts.png
new file mode 100644
index 000000000..a20c1ccbd
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_lua_scripts.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_mixer.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_mixer.png
new file mode 100644
index 000000000..009b360f1
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_mixer.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_outputs.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_outputs.png
new file mode 100644
index 000000000..a209ae8d3
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_outputs.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_setup.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_setup.png
new file mode 100644
index 000000000..afe526c8f
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_setup.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_special_functions.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_special_functions.png
new file mode 100644
index 000000000..a12a2a50d
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_special_functions.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_model_telemetry.png b/radio/sdcard/horus/THEMES/Flexi/mask_model_telemetry.png
new file mode 100644
index 000000000..d95d3b25f
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_model_telemetry.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor.png
new file mode 100644
index 000000000..68ddd4516
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels1.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels1.png
new file mode 100644
index 000000000..b886fc1bc
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels1.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels2.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels2.png
new file mode 100644
index 000000000..4d0354e25
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels2.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels3.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels3.png
new file mode 100644
index 000000000..d9ba27de7
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels3.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels4.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels4.png
new file mode 100644
index 000000000..fb321151f
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_channels4.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_gvars.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_gvars.png
new file mode 100644
index 000000000..55b488d1e
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_gvars.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_inver.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_inver.png
new file mode 100644
index 000000000..64f251238
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_inver.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_lockch.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_lockch.png
new file mode 100644
index 000000000..360923a09
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_lockch.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_logsw.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_logsw.png
new file mode 100644
index 000000000..dc6355143
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_logsw.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes1.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes1.png
new file mode 100644
index 000000000..7b0c71f60
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes1.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes2.png b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes2.png
new file mode 100644
index 000000000..f8c04780e
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_monitor_mixes2.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_mplex_add.png b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_add.png
new file mode 100644
index 000000000..14f4ecc23
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_add.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_mplex_multi.png b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_multi.png
new file mode 100644
index 000000000..bcf79695f
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_multi.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_mplex_replace.png b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_replace.png
new file mode 100644
index 000000000..faccba0ea
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_mplex_replace.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_opentx.png b/radio/sdcard/horus/THEMES/Flexi/mask_opentx.png
new file mode 100644
index 000000000..df2b0b356
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_opentx.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_opentx_testmode.png b/radio/sdcard/horus/THEMES/Flexi/mask_opentx_testmode.png
new file mode 100644
index 000000000..b535cf8ee
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_opentx_testmode.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_calibration.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_calibration.png
new file mode 100644
index 000000000..db696778b
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_calibration.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_global_functions.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_global_functions.png
new file mode 100644
index 000000000..3b3efefb5
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_global_functions.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_hardware.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_hardware.png
new file mode 100644
index 000000000..f51a1aee1
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_hardware.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_sd_browser.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_sd_browser.png
new file mode 100644
index 000000000..75b6a9296
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_sd_browser.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_setup.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_setup.png
new file mode 100644
index 000000000..0010a06ab
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_setup.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_spectrum_analyser.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_spectrum_analyser.png
new file mode 100755
index 000000000..2908833ec
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_spectrum_analyser.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_tools.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_tools.png
new file mode 100755
index 000000000..711d499de
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_tools.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_trainer.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_trainer.png
new file mode 100644
index 000000000..7a0b56970
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_trainer.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_radio_version.png b/radio/sdcard/horus/THEMES/Flexi/mask_radio_version.png
new file mode 100644
index 000000000..8730f6c1a
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_radio_version.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_sbar_mixer.png b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_mixer.png
new file mode 100644
index 000000000..154406419
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_mixer.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_sbar_output.png b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_output.png
new file mode 100644
index 000000000..12d599823
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_output.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_sbar_to.png b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_to.png
new file mode 100644
index 000000000..813610307
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_sbar_to.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_analogs.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_analogs.png
new file mode 100644
index 000000000..96fc0c8a2
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_analogs.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_debug.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_debug.png
new file mode 100644
index 000000000..0dce13d46
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_debug.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_lua.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_lua.png
new file mode 100644
index 000000000..d1b54a4d6
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_lua.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_throttle_graph.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_throttle_graph.png
new file mode 100644
index 000000000..a3720a005
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_throttle_graph.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_timers.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_timers.png
new file mode 100644
index 000000000..78bf00064
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_timers.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_stats_value.png b/radio/sdcard/horus/THEMES/Flexi/mask_stats_value.png
new file mode 100644
index 000000000..180f16e8c
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_stats_value.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_switches.png b/radio/sdcard/horus/THEMES/Flexi/mask_switches.png
new file mode 100644
index 000000000..4097ed751
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_switches.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_curve.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_curve.png
new file mode 100644
index 000000000..050229393
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_curve.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_delay.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_delay.png
new file mode 100644
index 000000000..9b771a94a
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_delay.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_delayslow.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_delayslow.png
new file mode 100644
index 000000000..de2f7d1f7
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_delayslow.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_fm.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_fm.png
new file mode 100644
index 000000000..b9a2c4a32
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_fm.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_label.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_label.png
new file mode 100644
index 000000000..8be12e39b
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_label.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_slow.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_slow.png
new file mode 100644
index 000000000..1afbea37d
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_slow.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_textline_switch.png b/radio/sdcard/horus/THEMES/Flexi/mask_textline_switch.png
new file mode 100644
index 000000000..7c7d646e4
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_textline_switch.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_add_view.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_add_view.png
new file mode 100644
index 000000000..7e240372f
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_add_view.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_setup.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_setup.png
new file mode 100644
index 000000000..2a39d1e40
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_setup.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view1.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view1.png
new file mode 100644
index 000000000..9e67515ec
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view1.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view2.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view2.png
new file mode 100644
index 000000000..45cec234d
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view2.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view3.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view3.png
new file mode 100644
index 000000000..e5a776b06
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view3.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view4.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view4.png
new file mode 100644
index 000000000..9064b9403
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view4.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view5.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view5.png
new file mode 100644
index 000000000..724bcc141
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view5.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view6.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view6.png
new file mode 100644
index 000000000..2aa43514b
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view6.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view7.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view7.png
new file mode 100644
index 000000000..d6a0540f5
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view7.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/mask_theme_view8.png b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view8.png
new file mode 100644
index 000000000..82dfd7875
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/mask_theme_view8.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat1.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat1.png
new file mode 100644
index 000000000..a9335c4bc
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat1.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat2.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat2.png
new file mode 100644
index 000000000..e3c899d18
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_boat2.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_default.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_default.png
new file mode 100644
index 000000000..6f3042c67
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_default.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_favorites.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_favorites.png
new file mode 100644
index 000000000..e4a37dacb
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_favorites.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane1.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane1.png
new file mode 100644
index 000000000..a49a50271
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane1.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane2.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane2.png
new file mode 100644
index 000000000..8305b4150
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane2.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane3.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane3.png
new file mode 100644
index 000000000..d998144b2
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/icon_plane3.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_iconback.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_iconback.png
new file mode 100644
index 000000000..966f6b7f2
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_iconback.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelname.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelname.png
new file mode 100644
index 000000000..2edca73ea
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelname.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelqty.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelqty.png
new file mode 100644
index 000000000..9a38e4f13
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_modelqty.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveback.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveback.png
new file mode 100644
index 000000000..63f56df92
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveback.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveico.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveico.png
new file mode 100644
index 000000000..3662b9bb0
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_moveico.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_sdfree.png b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_sdfree.png
new file mode 100644
index 000000000..f0ae81982
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/modelsel/mask_sdfree.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/question.bmp b/radio/sdcard/horus/THEMES/Flexi/question.bmp
new file mode 100644
index 000000000..101d7ed53
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/question.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/shutdown.bmp b/radio/sdcard/horus/THEMES/Flexi/shutdown.bmp
new file mode 100755
index 000000000..be7034db7
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/shutdown.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/stick_background.png b/radio/sdcard/horus/THEMES/Flexi/stick_background.png
new file mode 100644
index 000000000..9f6d53d92
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/stick_background.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/stick_pointer.png b/radio/sdcard/horus/THEMES/Flexi/stick_pointer.png
new file mode 100644
index 000000000..0d75765f9
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/stick_pointer.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/t16.bmp b/radio/sdcard/horus/THEMES/Flexi/t16.bmp
new file mode 100755
index 000000000..9c78cb498
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/t16.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/t18.bmp b/radio/sdcard/horus/THEMES/Flexi/t18.bmp
new file mode 100755
index 000000000..c1220ca1b
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/t18.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/thumb.bmp b/radio/sdcard/horus/THEMES/Flexi/thumb.bmp
new file mode 100644
index 000000000..c0494a694
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/thumb.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/topleft.png b/radio/sdcard/horus/THEMES/Flexi/topleft.png
new file mode 100644
index 000000000..603bfe1cf
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/topleft.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/topmenu_opentx.bmp b/radio/sdcard/horus/THEMES/Flexi/topmenu_opentx.bmp
new file mode 100644
index 000000000..cbc7f8149
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/topmenu_opentx.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/trackp_background.png b/radio/sdcard/horus/THEMES/Flexi/trackp_background.png
new file mode 100644
index 000000000..5beada59e
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/trackp_background.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/tx16s.bmp b/radio/sdcard/horus/THEMES/Flexi/tx16s.bmp
new file mode 100644
index 000000000..bb44eda41
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/tx16s.bmp differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/wizard/background.png b/radio/sdcard/horus/THEMES/Flexi/wizard/background.png
new file mode 100644
index 000000000..6b31b2914
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/wizard/background.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/wizard/itembg.png b/radio/sdcard/horus/THEMES/Flexi/wizard/itembg.png
new file mode 100644
index 000000000..b899446b2
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/wizard/itembg.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/wizard/pgdn.png b/radio/sdcard/horus/THEMES/Flexi/wizard/pgdn.png
new file mode 100644
index 000000000..6a1377620
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/wizard/pgdn.png differ
diff --git a/radio/sdcard/horus/THEMES/Flexi/wizard/pgup.png b/radio/sdcard/horus/THEMES/Flexi/wizard/pgup.png
new file mode 100644
index 000000000..06fab5cac
Binary files /dev/null and b/radio/sdcard/horus/THEMES/Flexi/wizard/pgup.png differ
diff --git a/radio/sdcard/horus/WIDGETS/Ghost/img/background.png b/radio/sdcard/horus/WIDGETS/Ghost/img/background.png
new file mode 100644
index 000000000..887c022fa
Binary files /dev/null and b/radio/sdcard/horus/WIDGETS/Ghost/img/background.png differ
diff --git a/radio/sdcard/horus/WIDGETS/Ghost/main.lua b/radio/sdcard/horus/WIDGETS/Ghost/main.lua
new file mode 100644
index 000000000..dfaef17c9
--- /dev/null
+++ b/radio/sdcard/horus/WIDGETS/Ghost/main.lua
@@ -0,0 +1,88 @@
+---- #########################################################################
+---- # #
+---- # 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 backgroundBitmap
+local offsetX
+local offsetY
+local sensors = {}
+
+local options = {
+ { "VTX", BOOL, 0 },
+}
+
+local function getValues(wgt)
+ if wgt.options.VTX == 0 then
+ sensors[1] = string.format("%s", getValue("RFMD"))
+ sensors[2] = string.format("%d Hz", getValue("FRat"))
+ sensors[3] = string.format("%d %%", getValue("RQly"))
+ if (getValue("TPWR") == 0) then
+ sensors[4] = "Range"
+ else
+ sensors[4] = string.format("%d mW", getValue("TPWR"))
+ end
+ else
+ sensors[1] = string.format("%s", getValue("VBan"))
+ sensors[2] = string.format("%dMHz", getValue("VFrq"))
+ sensors[3] = string.format("CH: %d", getValue("VChn"))
+ sensors[4] = string.format("%d mW", getValue("VPwr"))
+ end
+end
+
+local function create(zone, options)
+ local wgt = { zone=zone, options=options}
+ backgroundBitmap = Bitmap.open("/WIDGETS/Ghost/img/background.png")
+ offsetX = (wgt.zone.w - 178) / 2
+ offsetY = (wgt.zone.h - 148) / 2
+ return wgt
+end
+
+local function update(wgt, options)
+ wgt.options = options
+end
+
+local function background(wgt)
+end
+
+function refresh(wgt)
+ -- runs onty on large enough zone
+ if wgt.zone.w < 180 or wgt.zone.h < 145 then
+ return
+ end
+
+ if backgroundBitmap ~= nil then
+ lcd.drawBitmap(backgroundBitmap, wgt.zone.x + offsetX, wgt.zone.y + offsetY)
+ end
+
+ if getRSSI() ~= 0 then
+ getValues(wgt)
+
+ -- RF Mode/Band
+ lcd.drawText(wgt.zone.x + offsetX + 75, wgt.zone.y + offsetY + 2, sensors[1], CENTER + DBLSIZE)
+
+ -- Frame rate / Frequency
+ lcd.drawText(wgt.zone.x + offsetX + 85, wgt.zone.y + offsetY + 35, sensors[2], CENTER + DBLSIZE)
+
+ -- RSSI / Channel
+ lcd.drawText(wgt.zone.x + offsetX + 85, wgt.zone.y + offsetY + 70, sensors[3], CENTER + DBLSIZE)
+
+ -- Transmit power
+ lcd.drawText(wgt.zone.x + offsetX + 85, wgt.zone.y + offsetY + 105, sensors[4], CENTER + DBLSIZE)
+ end
+
+end
+
+return { name="Ghost", options=options, create=create, update=update, refresh=refresh, background=background }
\ No newline at end of file
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky RB30_RB40.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky RB30_RB40.lua
new file mode 100644
index 000000000..213faa6cf
--- /dev/null
+++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky RB30_RB40.lua
@@ -0,0 +1,464 @@
+--- - #########################################################################
+---- # #
+---- # 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 version = "v1.01"
+
+local VALUE = 0
+local COMBO = 1
+
+local edit = false
+local page = 1
+local current = 1
+local refreshState = 0
+local refreshIndex = 0
+local pageOffset = 0
+local pages = {}
+local fields = {}
+local modifications = {}
+local margin = 1
+local spacing = 8
+local numberPerPage = 7
+
+local configFields = {
+ { "Self_stable mode", COMBO, 0x80, nil, { "disable", "enable"} },
+ { "Sbus out", COMBO, 0x81, nil, { "disable", "enable"} },
+ { "VOut1(V)", VALUE, 0xB2, nil, 50, 84},
+ { "VOut2(V)", VALUE, 0xB3, nil, 50, 84},
+}
+
+
+local failsafeFields = {
+ { "CH1 failsafe", VALUE, 0x82, 150, 80, 220},
+ { "CH2 failsafe", VALUE, 0x82, 150, 80, 220},
+ { "CH3 failsafe", VALUE, 0x83, 150, 80, 220},
+ { "CH4 failsafe", VALUE, 0x83, 150, 80, 220},
+ { "CH5 failsafe", VALUE, 0x84, 150, 80, 220},
+ { "CH6 failsafe", VALUE, 0x84, 150, 80, 220},
+ { "CH7 failsafe", VALUE, 0x85, 150, 80, 220},
+ { "CH8 failsafe", VALUE, 0x85, 150, 80, 220},
+ { "CH9 failsafe", VALUE, 0x86, 150, 80, 220},
+ { "CH10 failsafe", VALUE, 0x86, 150, 80, 220},
+ { "CH11 failsafe", VALUE, 0x87, 150, 80, 220},
+ { "CH12 failsafe", VALUE, 0x87, 150, 80, 220},
+ { "CH13 failsafe", VALUE, 0x88, 150, 80, 220},
+ { "CH14 failsafe", VALUE, 0x88, 150, 80, 220},
+ { "CH15 failsafe", VALUE, 0x89, 150, 80, 220},
+ { "CH16 failsafe", VALUE, 0x89, 150, 80, 220},
+ { "CH17 failsafe", VALUE, 0x8A, 150, 80, 220},
+ { "CH18 failsafe", VALUE, 0x8A, 150, 80, 220},
+ { "CH19 failsafe", VALUE, 0x8B, 150, 80, 220},
+ { "CH20 failsafe", VALUE, 0x8B, 150, 80, 220},
+ { "CH21 failsafe", VALUE, 0x8C, 150, 80, 220},
+ { "CH22 failsafe", VALUE, 0x8C, 150, 80, 220},
+ { "CH23 failsafe", VALUE, 0x8D, 150, 80, 220},
+ { "CH24 failsafe", VALUE, 0x8D, 150, 80, 220},
+}
+
+local rx1PinMapFields = {
+ { "CH1 RX1 map", VALUE, 0x8E, 1, 0, 16},
+ { "CH2 RX1 map", VALUE, 0x8E, 2, 0, 16},
+ { "CH3 RX1 map", VALUE, 0x8F, 3, 0, 16},
+ { "CH4 RX1 map", VALUE, 0x8F, 4, 0, 16},
+ { "CH5 RX1 map", VALUE, 0x90, 5, 0, 16},
+ { "CH6 RX1 map", VALUE, 0x90, 6, 0, 16},
+ { "CH7 RX1 map", VALUE, 0x91, 7, 0, 16},
+ { "CH8 RX1 map", VALUE, 0x91, 8, 0, 16},
+ { "CH9 RX1 map", VALUE, 0x92, 9, 0, 16},
+ { "CH10 RX1 map", VALUE, 0x92, 10, 0, 16},
+ { "CH11 RX1 map", VALUE, 0x93, 11, 0, 16},
+ { "CH12 RX1 map", VALUE, 0x93, 12, 0, 16},
+ { "CH13 RX1 map", VALUE, 0x94, 13, 0, 16},
+ { "CH14 RX1 map", VALUE, 0x94, 14, 0, 16},
+ { "CH15 RX1 map", VALUE, 0x95, 15, 0, 16},
+ { "CH16 RX1 map", VALUE, 0x95, 16, 0, 16},
+ { "CH17 RX1 map", VALUE, 0x96, 1, 0, 16},
+ { "CH18 RX1 map", VALUE, 0x96, 2, 0, 16},
+ { "CH19 RX1 map", VALUE, 0x97, 3, 0, 16},
+ { "CH20 RX1 map", VALUE, 0x97, 4, 0, 16},
+ { "CH21 RX1 map", VALUE, 0x98, 5, 0, 16},
+ { "CH22 RX1 map", VALUE, 0x98, 6, 0, 16},
+ { "CH23 RX1 map", VALUE, 0x99, 7, 0, 16},
+ { "CH24 RX1 map", VALUE, 0x99, 8, 0, 16},
+}
+
+local rx2PinMapFields = {
+ { "CH1 RX2 map", VALUE, 0x9A, 1, 0, 16},
+ { "CH2 RX2 map", VALUE, 0x9A, 2, 0, 16},
+ { "CH3 RX2 map", VALUE, 0x9B, 3, 0, 16},
+ { "CH4 RX2 map", VALUE, 0x9B, 4, 0, 16},
+ { "CH5 RX2 map", VALUE, 0x9C, 5, 0, 16},
+ { "CH6 RX2 map", VALUE, 0x9C, 6, 0, 16},
+ { "CH7 RX2 map", VALUE, 0x9D, 7, 0, 16},
+ { "CH8 RX2 map", VALUE, 0x9D, 8, 0, 16},
+ { "CH9 RX2 map", VALUE, 0x9E, 9, 0, 16},
+ { "CH10 RX2 map", VALUE, 0x9E, 10, 0, 16},
+ { "CH11 RX2 map", VALUE, 0x9F, 11, 0, 16},
+ { "CH12 RX2 map", VALUE, 0x9F, 12, 0, 16},
+ { "CH13 RX2 map", VALUE, 0xA0, 13, 0, 16},
+ { "CH14 RX2 map", VALUE, 0xA0, 14, 0, 16},
+ { "CH15 RX2 map", VALUE, 0xA1, 15, 0, 16},
+ { "CH16 RX2 map", VALUE, 0xA0, 16, 0, 16},
+ { "CH17 RX2 map", VALUE, 0xA2, 1, 0, 16},
+ { "CH18 RX2 map", VALUE, 0xA2, 2, 0, 16},
+ { "CH19 RX2 map", VALUE, 0xA3, 3, 0, 16},
+ { "CH20 RX2 map", VALUE, 0xA3, 4, 0, 16},
+ { "CH21 RX2 map", VALUE, 0xA4, 5, 0, 16},
+ { "CH22 RX2 map", VALUE, 0xA4, 6, 0, 16},
+ { "CH23 RX2 map", VALUE, 0xA5, 7, 0, 16},
+ { "CH24 RX2 map", VALUE, 0xA5, 8, 0, 16},
+}
+
+local rx3PinMapFields = {
+ { "CH1 RX3 map", VALUE, 0xA6, 1, 0, 16},
+ { "CH2 RX3 map", VALUE, 0xA6, 2, 0, 16},
+ { "CH3 RX3 map", VALUE, 0xA7, 3, 0, 16},
+ { "CH4 RX3 map", VALUE, 0xA7, 4, 0, 16},
+ { "CH5 RX3 map", VALUE, 0xA8, 5, 0, 16},
+ { "CH6 RX3 map", VALUE, 0xA8, 6, 0, 16},
+ { "CH7 RX3 map", VALUE, 0xA9, 7, 0, 16},
+ { "CH8 RX3 map", VALUE, 0xA9, 8, 0, 16},
+ { "CH9 RX3 map", VALUE, 0xAA, 9, 0, 16},
+ { "CH10 RX3 map", VALUE, 0xAA, 10, 0, 16},
+ { "CH11 RX3 map", VALUE, 0xAB, 11, 0, 16},
+ { "CH12 RX3 map", VALUE, 0xAB, 12, 0, 16},
+ { "CH13 RX3 map", VALUE, 0xAC, 13, 0, 16},
+ { "CH14 RX3 map", VALUE, 0xAC, 14, 0, 16},
+ { "CH15 RX3 map", VALUE, 0xAD, 15, 0, 16},
+ { "CH16 RX3 map", VALUE, 0xAD, 16, 0, 16},
+ { "CH17 RX3 map", VALUE, 0xAE, 1, 0, 16},
+ { "CH18 RX3 map", VALUE, 0xAE, 2, 0, 16},
+ { "CH19 RX3 map", VALUE, 0xAF, 3, 0, 16},
+ { "CH20 RX3 map", VALUE, 0xAF, 4, 0, 16},
+ { "CH21 RX3 map", VALUE, 0xB0, 5, 0, 16},
+ { "CH22 RX3 map", VALUE, 0xB0, 6, 0, 16},
+ { "CH23 RX3 map", VALUE, 0xB1, 7, 0, 16},
+ { "CH24 RX3 map", VALUE, 0xB1, 8, 0, 16},
+}
+
+
+
+
+local function drawScreenTitle(title, page, pages)
+ if math.fmod(math.floor(getTime() / 100), 10) == 0 then
+ title = version
+ end
+ if LCD_W == 480 then
+ lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
+ lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
+ lcd.drawText(LCD_W - 40, 5, page .. "/" .. pages, MENU_TITLE_COLOR)
+ else
+ lcd.drawScreenTitle(title, page, pages)
+ end
+end
+
+-- Change display attribute to current field
+local function addField(step)
+ local field = fields[current]
+ local min, max
+ if field[2] == VALUE then
+ min = field[5]
+ max = field[6]
+ elseif field[2] == COMBO then
+ min = 0
+ max = #(field[5]) - 1
+ end
+ if page == 2 and step < 0 and field[4] == min then
+ field[4] = 0
+ elseif page == 2 and step > 0 and field[4] == 0 then
+ field[4] = min
+ else
+ if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then
+ field[4] = field[4] + step
+ end
+ end
+end
+
+-- Select the next or previous page
+local function selectPage(step)
+ local pagesNum = #pages
+ if configFields[1][4] == 1 then
+ pagesNum = 1
+ elseif configFields[2][4] == 1 then
+ pagesNum = pagesNum - 1
+ end
+ page = 1 + ((page + step - 1 + pagesNum) % pagesNum)
+ refreshIndex = 0
+ pageOffset = 0
+end
+
+-- Select the next or previous editable field
+local function selectField(step)
+ current = 1 + ((current + step - 1 + #fields) % #fields)
+ if current > numberPerPage + pageOffset then
+ pageOffset = current - numberPerPage
+ elseif current <= pageOffset then
+ pageOffset = current - 1
+ end
+end
+
+local function drawProgressBar()
+ if LCD_W == 480 then
+ local width = (300 * refreshIndex) / #fields
+ lcd.drawRectangle(100, 10, 300, 6)
+ lcd.drawFilledRectangle(102, 12, width, 2)
+ else
+ local width = (60 * refreshIndex) / #fields
+ lcd.drawRectangle(45, 1, 60, 6)
+ lcd.drawFilledRectangle(47, 3, width, 2)
+ end
+end
+
+-- Redraw the current page
+local function redrawFieldPage()
+ lcd.clear()
+
+ local pagesNum = #pages
+ if configFields[1][4] == 1 then
+ pagesNum = 1
+ elseif configFields[2][4] == 1 then
+ pagesNum = pagesNum - 1
+ end
+ drawScreenTitle("RB30/RB40", page, pagesNum)
+
+ if refreshIndex < #fields then
+ drawProgressBar()
+ end
+
+ for index = 1, numberPerPage, 1 do
+ local field = fields[pageOffset + index]
+ if field == nil then
+ break
+ end
+
+ local attr = current == (pageOffset + index) and ((edit == true and BLINK or 0) + INVERS) or 0
+
+ lcd.drawText(1, margin + spacing * index, field[1], attr)
+
+ if field[4] == nil then
+ lcd.drawText(LCD_W, margin + spacing * index, "---", RIGHT + attr)
+ else
+ if field[2] == VALUE then
+ if page == 2 then
+ if field[4] == 0 then
+ lcd.drawText(LCD_W, margin + spacing * index, "No pulse", RIGHT + attr)
+ else
+ lcd.drawNumber(LCD_W, margin + spacing * index, field[4] * 10, RIGHT + attr)
+ end
+ else
+ if field[4] == 0 then
+ lcd.drawText(LCD_W, margin + spacing * index, "No map", RIGHT + attr)
+ else
+ if field[3] == 0xB2 or field[3] == 0xB3 then
+ lcd.drawNumber(LCD_W, margin + spacing * index, field[4] , attr + RIGHT + PREC1)
+ else
+ lcd.drawNumber(LCD_W, margin + spacing * index, field[4], RIGHT + attr)
+ end
+ end
+ end
+ elseif field[2] == COMBO then
+ if field[4] >= 0 and field[4] < #(field[5]) then
+ lcd.drawText(LCD_W, margin + spacing * index, field[5][field[4] + 1], RIGHT + attr)
+ end
+ end
+ end
+ end
+end
+
+local function telemetryIdle(field)
+ return sportTelemetryPush(0x1C, 0x21, 0x0b80, field)
+end
+
+local function telemetryUnIdle(field)
+ return sportTelemetryPush(0x1C, 0x20, 0x0b80, field)
+end
+
+local function telemetryRead(field)
+ return sportTelemetryPush(0x1C, 0x30, 0x0b80, field)
+end
+
+local function telemetryWrite(field, value)
+ return sportTelemetryPush(0x1C, 0x31, 0x0b80, field + value * 256)
+end
+
+local telemetryPopTimeout = 0
+local function refreshNext()
+ if refreshState == 0 then
+ if #modifications > 0 then
+ telemetryWrite(modifications[1][1], modifications[1][2])
+ modifications[1] = nil
+ refreshIndex = 0
+ refreshState = 0
+ elseif refreshIndex < #fields then
+ local field = fields[refreshIndex + 1]
+ if page > 1 then
+ field = fields[refreshIndex + 2]
+ end
+ if telemetryRead(field[3]) == true then
+ refreshState = 1
+ telemetryPopTimeout = getTime() + 100 -- normal delay is 500ms
+ end
+ end
+ elseif refreshState == 1 then
+ local physicalId, primId, dataId, value = sportTelemetryPop()
+ if primId == 0x32 and (dataId >= 0x0b80 or dataId <= 0x0b8f) then
+ local fieldId = value % 256
+ local field = fields[refreshIndex + 1]
+ if fieldId == field[3] then
+ value = math.floor(value / 256)
+ if field[2] == COMBO then
+ fields[refreshIndex + 1][4] = value
+ else
+ fields[refreshIndex + 1][4] = value % 256
+ if page > 1 then
+ value = math.floor(value / 256)
+ fields[refreshIndex + 2][4] = value
+ end
+ end
+ if page > 1 then
+ refreshIndex = refreshIndex + 2
+ else
+ refreshIndex = refreshIndex + 1
+ end
+ refreshState = 0
+ end
+ elseif getTime() > telemetryPopTimeout then
+ fields[refreshIndex + 1][4] = nil
+ if page > 1 then
+ fields[refreshIndex + 2][4] = nil
+ refreshIndex = refreshIndex + 2
+ else
+ refreshIndex = refreshIndex + 1
+ end
+ refreshState = 0
+ end
+ end
+end
+
+local function updateField(field)
+ local value = field[4]
+ if field[2] == COMBO and #field == 6 then
+ value = field[6][1 + value]
+ elseif field[2] == VALUE and #field == 8 then
+ value = value + field[8] - field[5]
+ end
+
+ if page > 1 then
+ if current % 2 == 1 then
+ value = value + fields[current + 1][4] * 256
+ elseif current % 2 == 0 then
+ value = fields[current - 1][4] + value * 256
+ end
+ end
+ modifications[#modifications + 1] = { field[3], value }
+end
+
+-- Main
+local function runFieldsPage(event)
+ if event == EVT_VIRTUAL_EXIT then -- exit script
+ telemetryUnIdle(0x80)
+ return 2
+ elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
+ if fields[current][4] ~= nil then
+ edit = not edit
+ if edit == false then
+ updateField(fields[current])
+ end
+ end
+ elseif edit then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
+ addField(1)
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
+ addField(-1)
+ end
+ else
+ if event == EVT_VIRTUAL_NEXT then
+ selectField(1)
+ elseif event == EVT_VIRTUAL_PREV then
+ selectField(-1)
+ end
+ end
+ redrawFieldPage()
+ return 0
+end
+
+local function runConfigPage(event)
+ fields = configFields
+ return runFieldsPage(event)
+end
+
+local function runFailsafePage(event)
+ fields = failsafeFields
+ return runFieldsPage(event)
+end
+
+local function runRx1PinMapPage(event)
+ fields = rx1PinMapFields
+ return runFieldsPage(event)
+end
+
+local function runRx2PinMapPage(event)
+ fields = rx2PinMapFields
+ return runFieldsPage(event)
+end
+
+local function runRx3PinMapPage(event)
+ fields = rx3PinMapFields
+ return runFieldsPage(event)
+end
+
+-- Init
+local function init()
+ current, edit, refreshState, refreshIndex = 1, false, 0, 0
+ if LCD_W == 480 then
+ margin = 10
+ spacing = 20
+ numberPerPage = 12
+ end
+ pages = {
+ runConfigPage,
+ runFailsafePage,
+ runRx1PinMapPage,
+ runRx2PinMapPage,
+ runRx3PinMapPage
+ }
+ telemetryIdle(0x80)
+end
+
+-- Main
+local function run(event)
+ if event == nil then
+ error("Cannot be run as a model script!")
+ return 2
+ elseif event == EVT_VIRTUAL_NEXT_PAGE then
+ if edit == false then
+ selectPage(1)
+ end
+ elseif event == EVT_VIRTUAL_PREV_PAGE then
+ if edit == false then
+ killEvents(event)
+ selectPage(-1)
+ end
+ end
+
+ local result = pages[page](event)
+ refreshNext()
+
+ return result
+end
+
+return { init = init, run = run }
+
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt
index bf61d8ca6..b03b2c860 100644
--- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt
+++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt
@@ -1,3 +1,47 @@
+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
+14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
+59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
+41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
+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
+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
+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
+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
+33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
+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
+6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+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
+69,0,ESKY150V2,Std,0,CH5_RA,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
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
@@ -7,15 +51,11 @@
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
+28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+53,0,Height,5ch,0,Gear
+53,1,Height,8ch,0,Gear,Gyro,Flap,Light
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
@@ -26,78 +66,50 @@
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
+15,5,FrSkyX,D16Cloned_8CH,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
+64,5,FrSkyX2,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+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
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
+58,0,FX816,P38,1
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
+47,0,GD00x,V1,1,Trim,LED,Rate
+47,1,GD00x,V2,1,Trim,LED,Rate
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
+4,1,Hisky,HK310,0,Aux
+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
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
+57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+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
+22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+71,0,JJRC345,Std,1,Flip,HLess,RTH
+49,0,KF606,Std,1,Trim
+9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
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
@@ -111,6 +123,9 @@
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
+77,0,OMP,M2,0,THold,IdleUp,6G_3D
+60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
+60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8
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
@@ -120,8 +135,15 @@
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
+72,0,Q90C,Std,0,FMode,VTX+
+74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
+74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
+76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK
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
+21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
+19,0,Shenqi,Cycle,1
+68,0,Skyartec,Std,0,CH5,CH6,CH7
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
@@ -129,11 +151,21 @@
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
+61,0,Tiger,Std,1,Flip,Light
+43,0,Traxxas,6519,0
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
+48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
+48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
+46,0,V911s,V911s,1,Calib
+46,1,V911s,E119,1,Calib
+22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
+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
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
@@ -141,17 +173,4 @@
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
index 42de75e4f..14902b782 100644
--- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
@@ -249,13 +249,13 @@ local function Multi_Init()
--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
+ 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
+ elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH
stick_names[4] = "n-a"
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
stick_names[1] = "n-a"
@@ -278,6 +278,15 @@ local function Multi_Init()
ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = stick_names[1]
end
+
+ --Exceptions on first 4 channels...
+ if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface
+ channel_names[1] = "ST"
+ channel_names[2] = "THR"
+ channel_names[3] = "CH3"
+ channel_names[4] = "CH4"
+ end
+
--Check MultiChan.txt
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
if f == nil then return end
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua
index bcd9238f4..9cf7fdefd 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_VIRTUAL_PREV or event == EVT_VIRTUAL_PREV_REPT then
+ if event == EVT_VIRTUAL_INC then
value = (value + max)
dirty = true
- elseif event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then
+ elseif event == EVT_VIRTUAL_DEC then
value = (value + max + 2)
dirty = true
end
@@ -93,11 +93,11 @@ local function navigate(event, fieldMax, prevPage, nextPage)
dirty = blinkChanged()
end
else
- if event == EVT_VIRTUAL_NEXT then
+ if event == EVT_VIRTUAL_NEXT_PAGE then
page = nextPage
field = 0
dirty = true
- elseif event == EVT_VIRTUAL_PREV then
+ elseif event == EVT_VIRTUAL_PREV_PAGE then
page = prevPage
field = 0
killEvents(event);
@@ -335,7 +335,7 @@ local function drawConfirmationMenu()
if rudderMode == 1 then
drawNextLine(x, y, "Rudder", rudCH1)
end
- lcd.drawText(48, LCD_H-8, "[Enter Long] to confirm", 0);
+ lcd.drawText(0, LCD_H-8, "[Enter Long] to confirm", 0);
lcd.drawFilledRectangle(0, LCD_H-9, LCD_W, 9, 0)
fieldsMax = 0
end
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua
index 321b7324f..923acc43b 100755
--- a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua
@@ -99,11 +99,11 @@ local function navigate(event, fieldMax, prevPage, nextPage)
dirty = blinkChanged()
end
else
- if event == EVT_PAGE_BREAK or event == EVT_RIGHT_FIRST then
+ if event == EVT_VIRTUAL_NEXT_PAGE then
page = nextPage
field = 0
dirty = true
- elseif event == EVT_PAGE_LONG or event == EVT_LEFT_FIRST then
+ elseif event == EVT_VIRTUAL_PREV_PAGE then
page = prevPage
field = 0
killEvents(event);
diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua
index 26282cdf7..d52c1f936 100755
--- a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua
+++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua
@@ -103,11 +103,11 @@ local function navigate(event, fieldMax, prevPage, nextPage)
dirty = blinkChanged()
end
else
- if event == EVT_PAGE_BREAK or event==EVT_RIGHT_BREAK then
+ if event == EVT_VIRTUAL_NEXT_PAGE then
page = nextPage
field = 0
dirty = true
- elseif event == EVT_PAGE_LONG or event==EVT_LEFT_BREAK then
+ elseif event == EVT_VIRTUAL_PREV_PAGE then
page = prevPage
field = 0
killEvents(event);
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky RB30_RB40.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky RB30_RB40.lua
new file mode 100644
index 000000000..213faa6cf
--- /dev/null
+++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky RB30_RB40.lua
@@ -0,0 +1,464 @@
+--- - #########################################################################
+---- # #
+---- # 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 version = "v1.01"
+
+local VALUE = 0
+local COMBO = 1
+
+local edit = false
+local page = 1
+local current = 1
+local refreshState = 0
+local refreshIndex = 0
+local pageOffset = 0
+local pages = {}
+local fields = {}
+local modifications = {}
+local margin = 1
+local spacing = 8
+local numberPerPage = 7
+
+local configFields = {
+ { "Self_stable mode", COMBO, 0x80, nil, { "disable", "enable"} },
+ { "Sbus out", COMBO, 0x81, nil, { "disable", "enable"} },
+ { "VOut1(V)", VALUE, 0xB2, nil, 50, 84},
+ { "VOut2(V)", VALUE, 0xB3, nil, 50, 84},
+}
+
+
+local failsafeFields = {
+ { "CH1 failsafe", VALUE, 0x82, 150, 80, 220},
+ { "CH2 failsafe", VALUE, 0x82, 150, 80, 220},
+ { "CH3 failsafe", VALUE, 0x83, 150, 80, 220},
+ { "CH4 failsafe", VALUE, 0x83, 150, 80, 220},
+ { "CH5 failsafe", VALUE, 0x84, 150, 80, 220},
+ { "CH6 failsafe", VALUE, 0x84, 150, 80, 220},
+ { "CH7 failsafe", VALUE, 0x85, 150, 80, 220},
+ { "CH8 failsafe", VALUE, 0x85, 150, 80, 220},
+ { "CH9 failsafe", VALUE, 0x86, 150, 80, 220},
+ { "CH10 failsafe", VALUE, 0x86, 150, 80, 220},
+ { "CH11 failsafe", VALUE, 0x87, 150, 80, 220},
+ { "CH12 failsafe", VALUE, 0x87, 150, 80, 220},
+ { "CH13 failsafe", VALUE, 0x88, 150, 80, 220},
+ { "CH14 failsafe", VALUE, 0x88, 150, 80, 220},
+ { "CH15 failsafe", VALUE, 0x89, 150, 80, 220},
+ { "CH16 failsafe", VALUE, 0x89, 150, 80, 220},
+ { "CH17 failsafe", VALUE, 0x8A, 150, 80, 220},
+ { "CH18 failsafe", VALUE, 0x8A, 150, 80, 220},
+ { "CH19 failsafe", VALUE, 0x8B, 150, 80, 220},
+ { "CH20 failsafe", VALUE, 0x8B, 150, 80, 220},
+ { "CH21 failsafe", VALUE, 0x8C, 150, 80, 220},
+ { "CH22 failsafe", VALUE, 0x8C, 150, 80, 220},
+ { "CH23 failsafe", VALUE, 0x8D, 150, 80, 220},
+ { "CH24 failsafe", VALUE, 0x8D, 150, 80, 220},
+}
+
+local rx1PinMapFields = {
+ { "CH1 RX1 map", VALUE, 0x8E, 1, 0, 16},
+ { "CH2 RX1 map", VALUE, 0x8E, 2, 0, 16},
+ { "CH3 RX1 map", VALUE, 0x8F, 3, 0, 16},
+ { "CH4 RX1 map", VALUE, 0x8F, 4, 0, 16},
+ { "CH5 RX1 map", VALUE, 0x90, 5, 0, 16},
+ { "CH6 RX1 map", VALUE, 0x90, 6, 0, 16},
+ { "CH7 RX1 map", VALUE, 0x91, 7, 0, 16},
+ { "CH8 RX1 map", VALUE, 0x91, 8, 0, 16},
+ { "CH9 RX1 map", VALUE, 0x92, 9, 0, 16},
+ { "CH10 RX1 map", VALUE, 0x92, 10, 0, 16},
+ { "CH11 RX1 map", VALUE, 0x93, 11, 0, 16},
+ { "CH12 RX1 map", VALUE, 0x93, 12, 0, 16},
+ { "CH13 RX1 map", VALUE, 0x94, 13, 0, 16},
+ { "CH14 RX1 map", VALUE, 0x94, 14, 0, 16},
+ { "CH15 RX1 map", VALUE, 0x95, 15, 0, 16},
+ { "CH16 RX1 map", VALUE, 0x95, 16, 0, 16},
+ { "CH17 RX1 map", VALUE, 0x96, 1, 0, 16},
+ { "CH18 RX1 map", VALUE, 0x96, 2, 0, 16},
+ { "CH19 RX1 map", VALUE, 0x97, 3, 0, 16},
+ { "CH20 RX1 map", VALUE, 0x97, 4, 0, 16},
+ { "CH21 RX1 map", VALUE, 0x98, 5, 0, 16},
+ { "CH22 RX1 map", VALUE, 0x98, 6, 0, 16},
+ { "CH23 RX1 map", VALUE, 0x99, 7, 0, 16},
+ { "CH24 RX1 map", VALUE, 0x99, 8, 0, 16},
+}
+
+local rx2PinMapFields = {
+ { "CH1 RX2 map", VALUE, 0x9A, 1, 0, 16},
+ { "CH2 RX2 map", VALUE, 0x9A, 2, 0, 16},
+ { "CH3 RX2 map", VALUE, 0x9B, 3, 0, 16},
+ { "CH4 RX2 map", VALUE, 0x9B, 4, 0, 16},
+ { "CH5 RX2 map", VALUE, 0x9C, 5, 0, 16},
+ { "CH6 RX2 map", VALUE, 0x9C, 6, 0, 16},
+ { "CH7 RX2 map", VALUE, 0x9D, 7, 0, 16},
+ { "CH8 RX2 map", VALUE, 0x9D, 8, 0, 16},
+ { "CH9 RX2 map", VALUE, 0x9E, 9, 0, 16},
+ { "CH10 RX2 map", VALUE, 0x9E, 10, 0, 16},
+ { "CH11 RX2 map", VALUE, 0x9F, 11, 0, 16},
+ { "CH12 RX2 map", VALUE, 0x9F, 12, 0, 16},
+ { "CH13 RX2 map", VALUE, 0xA0, 13, 0, 16},
+ { "CH14 RX2 map", VALUE, 0xA0, 14, 0, 16},
+ { "CH15 RX2 map", VALUE, 0xA1, 15, 0, 16},
+ { "CH16 RX2 map", VALUE, 0xA0, 16, 0, 16},
+ { "CH17 RX2 map", VALUE, 0xA2, 1, 0, 16},
+ { "CH18 RX2 map", VALUE, 0xA2, 2, 0, 16},
+ { "CH19 RX2 map", VALUE, 0xA3, 3, 0, 16},
+ { "CH20 RX2 map", VALUE, 0xA3, 4, 0, 16},
+ { "CH21 RX2 map", VALUE, 0xA4, 5, 0, 16},
+ { "CH22 RX2 map", VALUE, 0xA4, 6, 0, 16},
+ { "CH23 RX2 map", VALUE, 0xA5, 7, 0, 16},
+ { "CH24 RX2 map", VALUE, 0xA5, 8, 0, 16},
+}
+
+local rx3PinMapFields = {
+ { "CH1 RX3 map", VALUE, 0xA6, 1, 0, 16},
+ { "CH2 RX3 map", VALUE, 0xA6, 2, 0, 16},
+ { "CH3 RX3 map", VALUE, 0xA7, 3, 0, 16},
+ { "CH4 RX3 map", VALUE, 0xA7, 4, 0, 16},
+ { "CH5 RX3 map", VALUE, 0xA8, 5, 0, 16},
+ { "CH6 RX3 map", VALUE, 0xA8, 6, 0, 16},
+ { "CH7 RX3 map", VALUE, 0xA9, 7, 0, 16},
+ { "CH8 RX3 map", VALUE, 0xA9, 8, 0, 16},
+ { "CH9 RX3 map", VALUE, 0xAA, 9, 0, 16},
+ { "CH10 RX3 map", VALUE, 0xAA, 10, 0, 16},
+ { "CH11 RX3 map", VALUE, 0xAB, 11, 0, 16},
+ { "CH12 RX3 map", VALUE, 0xAB, 12, 0, 16},
+ { "CH13 RX3 map", VALUE, 0xAC, 13, 0, 16},
+ { "CH14 RX3 map", VALUE, 0xAC, 14, 0, 16},
+ { "CH15 RX3 map", VALUE, 0xAD, 15, 0, 16},
+ { "CH16 RX3 map", VALUE, 0xAD, 16, 0, 16},
+ { "CH17 RX3 map", VALUE, 0xAE, 1, 0, 16},
+ { "CH18 RX3 map", VALUE, 0xAE, 2, 0, 16},
+ { "CH19 RX3 map", VALUE, 0xAF, 3, 0, 16},
+ { "CH20 RX3 map", VALUE, 0xAF, 4, 0, 16},
+ { "CH21 RX3 map", VALUE, 0xB0, 5, 0, 16},
+ { "CH22 RX3 map", VALUE, 0xB0, 6, 0, 16},
+ { "CH23 RX3 map", VALUE, 0xB1, 7, 0, 16},
+ { "CH24 RX3 map", VALUE, 0xB1, 8, 0, 16},
+}
+
+
+
+
+local function drawScreenTitle(title, page, pages)
+ if math.fmod(math.floor(getTime() / 100), 10) == 0 then
+ title = version
+ end
+ if LCD_W == 480 then
+ lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
+ lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
+ lcd.drawText(LCD_W - 40, 5, page .. "/" .. pages, MENU_TITLE_COLOR)
+ else
+ lcd.drawScreenTitle(title, page, pages)
+ end
+end
+
+-- Change display attribute to current field
+local function addField(step)
+ local field = fields[current]
+ local min, max
+ if field[2] == VALUE then
+ min = field[5]
+ max = field[6]
+ elseif field[2] == COMBO then
+ min = 0
+ max = #(field[5]) - 1
+ end
+ if page == 2 and step < 0 and field[4] == min then
+ field[4] = 0
+ elseif page == 2 and step > 0 and field[4] == 0 then
+ field[4] = min
+ else
+ if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then
+ field[4] = field[4] + step
+ end
+ end
+end
+
+-- Select the next or previous page
+local function selectPage(step)
+ local pagesNum = #pages
+ if configFields[1][4] == 1 then
+ pagesNum = 1
+ elseif configFields[2][4] == 1 then
+ pagesNum = pagesNum - 1
+ end
+ page = 1 + ((page + step - 1 + pagesNum) % pagesNum)
+ refreshIndex = 0
+ pageOffset = 0
+end
+
+-- Select the next or previous editable field
+local function selectField(step)
+ current = 1 + ((current + step - 1 + #fields) % #fields)
+ if current > numberPerPage + pageOffset then
+ pageOffset = current - numberPerPage
+ elseif current <= pageOffset then
+ pageOffset = current - 1
+ end
+end
+
+local function drawProgressBar()
+ if LCD_W == 480 then
+ local width = (300 * refreshIndex) / #fields
+ lcd.drawRectangle(100, 10, 300, 6)
+ lcd.drawFilledRectangle(102, 12, width, 2)
+ else
+ local width = (60 * refreshIndex) / #fields
+ lcd.drawRectangle(45, 1, 60, 6)
+ lcd.drawFilledRectangle(47, 3, width, 2)
+ end
+end
+
+-- Redraw the current page
+local function redrawFieldPage()
+ lcd.clear()
+
+ local pagesNum = #pages
+ if configFields[1][4] == 1 then
+ pagesNum = 1
+ elseif configFields[2][4] == 1 then
+ pagesNum = pagesNum - 1
+ end
+ drawScreenTitle("RB30/RB40", page, pagesNum)
+
+ if refreshIndex < #fields then
+ drawProgressBar()
+ end
+
+ for index = 1, numberPerPage, 1 do
+ local field = fields[pageOffset + index]
+ if field == nil then
+ break
+ end
+
+ local attr = current == (pageOffset + index) and ((edit == true and BLINK or 0) + INVERS) or 0
+
+ lcd.drawText(1, margin + spacing * index, field[1], attr)
+
+ if field[4] == nil then
+ lcd.drawText(LCD_W, margin + spacing * index, "---", RIGHT + attr)
+ else
+ if field[2] == VALUE then
+ if page == 2 then
+ if field[4] == 0 then
+ lcd.drawText(LCD_W, margin + spacing * index, "No pulse", RIGHT + attr)
+ else
+ lcd.drawNumber(LCD_W, margin + spacing * index, field[4] * 10, RIGHT + attr)
+ end
+ else
+ if field[4] == 0 then
+ lcd.drawText(LCD_W, margin + spacing * index, "No map", RIGHT + attr)
+ else
+ if field[3] == 0xB2 or field[3] == 0xB3 then
+ lcd.drawNumber(LCD_W, margin + spacing * index, field[4] , attr + RIGHT + PREC1)
+ else
+ lcd.drawNumber(LCD_W, margin + spacing * index, field[4], RIGHT + attr)
+ end
+ end
+ end
+ elseif field[2] == COMBO then
+ if field[4] >= 0 and field[4] < #(field[5]) then
+ lcd.drawText(LCD_W, margin + spacing * index, field[5][field[4] + 1], RIGHT + attr)
+ end
+ end
+ end
+ end
+end
+
+local function telemetryIdle(field)
+ return sportTelemetryPush(0x1C, 0x21, 0x0b80, field)
+end
+
+local function telemetryUnIdle(field)
+ return sportTelemetryPush(0x1C, 0x20, 0x0b80, field)
+end
+
+local function telemetryRead(field)
+ return sportTelemetryPush(0x1C, 0x30, 0x0b80, field)
+end
+
+local function telemetryWrite(field, value)
+ return sportTelemetryPush(0x1C, 0x31, 0x0b80, field + value * 256)
+end
+
+local telemetryPopTimeout = 0
+local function refreshNext()
+ if refreshState == 0 then
+ if #modifications > 0 then
+ telemetryWrite(modifications[1][1], modifications[1][2])
+ modifications[1] = nil
+ refreshIndex = 0
+ refreshState = 0
+ elseif refreshIndex < #fields then
+ local field = fields[refreshIndex + 1]
+ if page > 1 then
+ field = fields[refreshIndex + 2]
+ end
+ if telemetryRead(field[3]) == true then
+ refreshState = 1
+ telemetryPopTimeout = getTime() + 100 -- normal delay is 500ms
+ end
+ end
+ elseif refreshState == 1 then
+ local physicalId, primId, dataId, value = sportTelemetryPop()
+ if primId == 0x32 and (dataId >= 0x0b80 or dataId <= 0x0b8f) then
+ local fieldId = value % 256
+ local field = fields[refreshIndex + 1]
+ if fieldId == field[3] then
+ value = math.floor(value / 256)
+ if field[2] == COMBO then
+ fields[refreshIndex + 1][4] = value
+ else
+ fields[refreshIndex + 1][4] = value % 256
+ if page > 1 then
+ value = math.floor(value / 256)
+ fields[refreshIndex + 2][4] = value
+ end
+ end
+ if page > 1 then
+ refreshIndex = refreshIndex + 2
+ else
+ refreshIndex = refreshIndex + 1
+ end
+ refreshState = 0
+ end
+ elseif getTime() > telemetryPopTimeout then
+ fields[refreshIndex + 1][4] = nil
+ if page > 1 then
+ fields[refreshIndex + 2][4] = nil
+ refreshIndex = refreshIndex + 2
+ else
+ refreshIndex = refreshIndex + 1
+ end
+ refreshState = 0
+ end
+ end
+end
+
+local function updateField(field)
+ local value = field[4]
+ if field[2] == COMBO and #field == 6 then
+ value = field[6][1 + value]
+ elseif field[2] == VALUE and #field == 8 then
+ value = value + field[8] - field[5]
+ end
+
+ if page > 1 then
+ if current % 2 == 1 then
+ value = value + fields[current + 1][4] * 256
+ elseif current % 2 == 0 then
+ value = fields[current - 1][4] + value * 256
+ end
+ end
+ modifications[#modifications + 1] = { field[3], value }
+end
+
+-- Main
+local function runFieldsPage(event)
+ if event == EVT_VIRTUAL_EXIT then -- exit script
+ telemetryUnIdle(0x80)
+ return 2
+ elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
+ if fields[current][4] ~= nil then
+ edit = not edit
+ if edit == false then
+ updateField(fields[current])
+ end
+ end
+ elseif edit then
+ if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
+ addField(1)
+ elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
+ addField(-1)
+ end
+ else
+ if event == EVT_VIRTUAL_NEXT then
+ selectField(1)
+ elseif event == EVT_VIRTUAL_PREV then
+ selectField(-1)
+ end
+ end
+ redrawFieldPage()
+ return 0
+end
+
+local function runConfigPage(event)
+ fields = configFields
+ return runFieldsPage(event)
+end
+
+local function runFailsafePage(event)
+ fields = failsafeFields
+ return runFieldsPage(event)
+end
+
+local function runRx1PinMapPage(event)
+ fields = rx1PinMapFields
+ return runFieldsPage(event)
+end
+
+local function runRx2PinMapPage(event)
+ fields = rx2PinMapFields
+ return runFieldsPage(event)
+end
+
+local function runRx3PinMapPage(event)
+ fields = rx3PinMapFields
+ return runFieldsPage(event)
+end
+
+-- Init
+local function init()
+ current, edit, refreshState, refreshIndex = 1, false, 0, 0
+ if LCD_W == 480 then
+ margin = 10
+ spacing = 20
+ numberPerPage = 12
+ end
+ pages = {
+ runConfigPage,
+ runFailsafePage,
+ runRx1PinMapPage,
+ runRx2PinMapPage,
+ runRx3PinMapPage
+ }
+ telemetryIdle(0x80)
+end
+
+-- Main
+local function run(event)
+ if event == nil then
+ error("Cannot be run as a model script!")
+ return 2
+ elseif event == EVT_VIRTUAL_NEXT_PAGE then
+ if edit == false then
+ selectPage(1)
+ end
+ elseif event == EVT_VIRTUAL_PREV_PAGE then
+ if edit == false then
+ killEvents(event)
+ selectPage(-1)
+ end
+ end
+
+ local result = pages[page](event)
+ refreshNext()
+
+ return result
+end
+
+return { init = init, run = run }
+
diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt
index bf61d8ca6..b03b2c860 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt
+++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt
@@ -1,3 +1,47 @@
+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
+14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
+59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
+41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
+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
+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
+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
+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
+33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
+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
+6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
+70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+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
+69,0,ESKY150V2,Std,0,CH5_RA,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
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
@@ -7,15 +51,11 @@
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
+28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
+53,0,Height,5ch,0,Gear
+53,1,Height,8ch,0,Gear,Gyro,Flap,Light
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
@@ -26,78 +66,50 @@
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
+15,5,FrSkyX,D16Cloned_8CH,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
+64,5,FrSkyX2,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
+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
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
+58,0,FX816,P38,1
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
+47,0,GD00x,V1,1,Trim,LED,Rate
+47,1,GD00x,V2,1,Trim,LED,Rate
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
+4,1,Hisky,HK310,0,Aux
+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
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
+57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+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
+22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
+71,0,JJRC345,Std,1,Flip,HLess,RTH
+49,0,KF606,Std,1,Trim
+9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
+73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
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
@@ -111,6 +123,9 @@
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
+77,0,OMP,M2,0,THold,IdleUp,6G_3D
+60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
+60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8
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
@@ -120,8 +135,15 @@
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
+72,0,Q90C,Std,0,FMode,VTX+
+74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
+74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
+76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK
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
+21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
+19,0,Shenqi,Cycle,1
+68,0,Skyartec,Std,0,CH5,CH6,CH7
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
@@ -129,11 +151,21 @@
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
+61,0,Tiger,Std,1,Flip,Light
+43,0,Traxxas,6519,0
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
+48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
+48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
+46,0,V911s,V911s,1,Calib
+46,1,V911s,E119,1,Calib
+22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
+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
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
@@ -141,17 +173,4 @@
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
index 42de75e4f..14902b782 100644
--- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
+++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChannelsUpdater.lua
@@ -249,13 +249,13 @@ local function Multi_Init()
--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
+ 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
+ elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH
stick_names[4] = "n-a"
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
stick_names[1] = "n-a"
@@ -278,6 +278,15 @@ local function Multi_Init()
ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = stick_names[1]
end
+
+ --Exceptions on first 4 channels...
+ if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface
+ channel_names[1] = "ST"
+ channel_names[2] = "THR"
+ channel_names[3] = "CH3"
+ channel_names[4] = "CH4"
+ end
+
--Check MultiChan.txt
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
if f == nil then return end
diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt
index 972a805a1..03ec58003 100644
--- a/radio/src/CMakeLists.txt
+++ b/radio/src/CMakeLists.txt
@@ -53,6 +53,7 @@ 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(IMRC_RELEASE "Used to build IMRC released firmware" OFF)
option(HARDWARE_TRAINER_MULTI "Allow multi trainer" OFF)
option(BOOTLOADER "Include Bootloader" ON)
@@ -370,6 +371,10 @@ if(TBS_RELEASE)
add_definitions(-DTBS_RELEASE)
endif()
+if(IMRC_RELEASE)
+ add_definitions(-DIMRC_RELEASE)
+endif()
+
if(FRSKY_RELEASE)
add_definitions(-DFRSKY_RELEASE)
set(POPUP_LEVEL 3)
diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp
index be53e8921..ac7294877 100644
--- a/radio/src/audio.cpp
+++ b/radio/src/audio.cpp
@@ -158,9 +158,9 @@ const char * const unitsFilenames[] = {
"ml",
"founce",
"mlpm",
- "spare1",
- "spare2",
- "spare3",
+ "hertz",
+ "ms",
+ "us",
"spare4",
"spare5",
"spare6",
diff --git a/radio/src/crc.cpp b/radio/src/crc.cpp
index 26a1af500..c0be4d7fa 100644
--- a/radio/src/crc.cpp
+++ b/radio/src/crc.cpp
@@ -79,3 +79,48 @@ uint8_t crc8(const uint8_t * ptr, uint32_t len)
}
return crc;
}
+
+// CRC8 implementation with polynom = 0xBA
+const unsigned char crc8tab_BA[256] = {
+ 0x00, 0xBA, 0xCE, 0x74, 0x26, 0x9C, 0xE8, 0x52,
+ 0x4C, 0xF6, 0x82, 0x38, 0x6A, 0xD0, 0xA4, 0x1E,
+ 0x98, 0x22, 0x56, 0xEC, 0xBE, 0x04, 0x70, 0xCA,
+ 0xD4, 0x6E, 0x1A, 0xA0, 0xF2, 0x48, 0x3C, 0x86,
+ 0x8A, 0x30, 0x44, 0xFE, 0xAC, 0x16, 0x62, 0xD8,
+ 0xC6, 0x7C, 0x08, 0xB2, 0xE0, 0x5A, 0x2E, 0x94,
+ 0x12, 0xA8, 0xDC, 0x66, 0x34, 0x8E, 0xFA, 0x40,
+ 0x5E, 0xE4, 0x90, 0x2A, 0x78, 0xC2, 0xB6, 0x0C,
+ 0xAE, 0x14, 0x60, 0xDA, 0x88, 0x32, 0x46, 0xFC,
+ 0xE2, 0x58, 0x2C, 0x96, 0xC4, 0x7E, 0x0A, 0xB0,
+ 0x36, 0x8C, 0xF8, 0x42, 0x10, 0xAA, 0xDE, 0x64,
+ 0x7A, 0xC0, 0xB4, 0x0E, 0x5C, 0xE6, 0x92, 0x28,
+ 0x24, 0x9E, 0xEA, 0x50, 0x02, 0xB8, 0xCC, 0x76,
+ 0x68, 0xD2, 0xA6, 0x1C, 0x4E, 0xF4, 0x80, 0x3A,
+ 0xBC, 0x06, 0x72, 0xC8, 0x9A, 0x20, 0x54, 0xEE,
+ 0xF0, 0x4A, 0x3E, 0x84, 0xD6, 0x6C, 0x18, 0xA2,
+ 0xE6, 0x5C, 0x28, 0x92, 0xC0, 0x7A, 0x0E, 0xB4,
+ 0xAA, 0x10, 0x64, 0xDE, 0x8C, 0x36, 0x42, 0xF8,
+ 0x7E, 0xC4, 0xB0, 0x0A, 0x58, 0xE2, 0x96, 0x2C,
+ 0x32, 0x88, 0xFC, 0x46, 0x14, 0xAE, 0xDA, 0x60,
+ 0x6C, 0xD6, 0xA2, 0x18, 0x4A, 0xF0, 0x84, 0x3E,
+ 0x20, 0x9A, 0xEE, 0x54, 0x06, 0xBC, 0xC8, 0x72,
+ 0xF4, 0x4E, 0x3A, 0x80, 0xD2, 0x68, 0x1C, 0xA6,
+ 0xB8, 0x02, 0x76, 0xCC, 0x9E, 0x24, 0x50, 0xEA,
+ 0x48, 0xF2, 0x86, 0x3C, 0x6E, 0xD4, 0xA0, 0x1A,
+ 0x04, 0xBE, 0xCA, 0x70, 0x22, 0x98, 0xEC, 0x56,
+ 0xD0, 0x6A, 0x1E, 0xA4, 0xF6, 0x4C, 0x38, 0x82,
+ 0x9C, 0x26, 0x52, 0xE8, 0xBA, 0x00, 0x74, 0xCE,
+ 0xC2, 0x78, 0x0C, 0xB6, 0xE4, 0x5E, 0x2A, 0x90,
+ 0x8E, 0x34, 0x40, 0xFA, 0xA8, 0x12, 0x66, 0xDC,
+ 0x5A, 0xE0, 0x94, 0x2E, 0x7C, 0xC6, 0xB2, 0x08,
+ 0x16, 0xAC, 0xD8, 0x62, 0x30, 0x8A, 0xFE, 0x44
+};
+
+uint8_t crc8_BA(const uint8_t * ptr, uint32_t len)
+{
+ uint8_t crc = 0;
+ for (uint32_t i=0; i> 8;
}
} afhds3));
#endif
@@ -617,8 +617,9 @@ PACK(struct ModelData {
NOBACKUP(RssiAlarmData rssiAlarms);
- NOBACKUP(uint8_t spare1:6 SKIP);
- NOBACKUP(uint8_t potsWarnMode:2);
+ uint8_t spare1:3;
+ uint8_t thrTrimSw:3;
+ uint8_t potsWarnMode:2;
ModuleData moduleData[NUM_MODULES];
int16_t failsafeChannels[MAX_OUTPUT_CHANNELS];
@@ -637,6 +638,20 @@ PACK(struct ModelData {
CUSTOM_SCREENS_DATA
char modelRegistrationID[PXX2_LEN_REGISTRATION_ID];
+
+
+ uint8_t getThrottleStickTrimSource() const
+ {
+ // The order here is TERA, so that 0 (default) means Throttle
+ switch (thrTrimSw) {
+ case 0:
+ return MIXSRC_TrimThr;
+ case 2:
+ return MIXSRC_TrimRud;
+ default:
+ return thrTrimSw + MIXSRC_FIRST_TRIM;
+ }
+ }
});
/*
@@ -756,7 +771,8 @@ PACK(struct RadioData {
uint8_t backlightMode:3;
int8_t antennaMode:2;
uint8_t disableRtcWarning:1;
- int8_t spare1:2 SKIP;
+ uint8_t keysBacklight:1;
+ int8_t spare1:1 SKIP;
NOBACKUP(TrainerData trainer);
NOBACKUP(uint8_t view); // index of view in main screen
NOBACKUP(BUZZER_FIELD); /* 2bits */
diff --git a/radio/src/functions.cpp b/radio/src/functions.cpp
index 5b1fb2dae..20de19e9a 100644
--- a/radio/src/functions.cpp
+++ b/radio/src/functions.cpp
@@ -343,7 +343,7 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext
#if defined(VARIO)
case FUNC_VARIO:
- newActiveFunctions |= (1 << FUNCTION_VARIO);
+ newActiveFunctions |= (1u << FUNCTION_VARIO);
break;
#endif
@@ -351,15 +351,22 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext
#if defined(SDCARD)
case FUNC_LOGS:
if (CFN_PARAM(cfn)) {
- newActiveFunctions |= (1 << FUNCTION_LOGS);
+ newActiveFunctions |= (1u << FUNCTION_LOGS);
logDelay = CFN_PARAM(cfn);
}
break;
#endif
case FUNC_BACKLIGHT:
- newActiveFunctions |= (1 << FUNCTION_BACKLIGHT);
+ {
+ getvalue_t raw = getValue(CFN_PARAM(cfn));
+#if defined(COLORLCD)
+ requiredBacklightBright = (1024 - raw) * (BACKLIGHT_LEVEL_MAX - BACKLIGHT_LEVEL_MIN) / 2048;
+#else
+ requiredBacklightBright = (1024 - raw) * 100 / 2048;
+#endif
break;
+ }
case FUNC_SCREENSHOT:
if (!(functionsContext.activeSwitches & switch_mask)) {
diff --git a/radio/src/globals.h b/radio/src/globals.h
index cf67dbc4a..f63dfefe0 100644
--- a/radio/src/globals.h
+++ b/radio/src/globals.h
@@ -50,6 +50,7 @@ extern uint8_t trimsDisplayMask;
extern uint16_t maxMixerDuration;
extern uint8_t requiredSpeakerVolume;
+extern uint8_t requiredBacklightBright;
enum MainRequest {
REQUEST_SCREENSHOT,
diff --git a/radio/src/gui/128x64/gui.h b/radio/src/gui/128x64/gui.h
index e7367524f..40773737e 100644
--- a/radio/src/gui/128x64/gui.h
+++ b/radio/src/gui/128x64/gui.h
@@ -215,6 +215,8 @@ extern int8_t s_copySrcRow;
extern int8_t s_copyTgtOfs;
extern uint8_t s_currIdx;
extern uint8_t s_currIdxSubMenu;
+extern uint16_t s_currSrcRaw;
+extern uint16_t s_currScale;
extern uint8_t s_copySrcIdx;
extern uint8_t s_copySrcCh;
extern int8_t s_currCh;
@@ -274,9 +276,6 @@ uint8_t getMixesCount();
void insertMix(uint8_t idx);
void deleteMix(uint8_t idx);
-typedef int (*FnFuncP) (int x);
-void drawFunction(FnFuncP fn, uint8_t offset=0);
-
void onSourceLongEnterPress(const char *result);
uint8_t switchToMix(uint8_t source);
diff --git a/radio/src/gui/128x64/menu_model.cpp b/radio/src/gui/128x64/menu_model.cpp
index b6f5b3bb3..b98372bd3 100644
--- a/radio/src/gui/128x64/menu_model.cpp
+++ b/radio/src/gui/128x64/menu_model.cpp
@@ -46,3 +46,5 @@ void editSingleName(coord_t x, coord_t y, const char * label, char * name, uint8
uint8_t s_currIdx;
uint8_t s_currIdxSubMenu;
+uint16_t s_currSrcRaw;
+uint16_t s_currScale;
diff --git a/radio/src/gui/128x64/model_curve_edit.cpp b/radio/src/gui/128x64/model_curve_edit.cpp
index 5aa43b05d..dbdc09eb1 100644
--- a/radio/src/gui/128x64/model_curve_edit.cpp
+++ b/radio/src/gui/128x64/model_curve_edit.cpp
@@ -171,14 +171,18 @@ void menuModelCurveOne(event_t event)
killEvents(event);
break;
#elif defined(NAVIGATION_XLITE)
- case EVT_KEY_LONG(KEY_SHIFT):
- pushMenu(menuChannelsView);
- killEvents(event);
+ case EVT_KEY_FIRST(KEY_ENTER):
+ if (IS_SHIFT_PRESSED()) {
+ pushMenu(menuChannelsView);
+ killEvents(event);
+ }
break;
#endif
}
- drawCurve(0);
+ drawCurve();
+ if (s_currSrcRaw != MIXSRC_NONE)
+ drawCursor(applyCurrentCurve);
attr = (s_editMode > 0 ? INVERS|BLINK : INVERS);
for (uint8_t i=0; i<5+crv.points; i++) {
diff --git a/radio/src/gui/128x64/model_display.cpp b/radio/src/gui/128x64/model_display.cpp
index 6c5bf2f47..39b8d196a 100644
--- a/radio/src/gui/128x64/model_display.cpp
+++ b/radio/src/gui/128x64/model_display.cpp
@@ -242,10 +242,10 @@ void menuModelDisplay(event_t event)
}
break;
case 1:
- bar.barMin = checkIncDec(event, bar.barMin, barMin, bar.barMax, EE_MODEL|NO_INCDEC_MARKS);
+ bar.barMin = checkIncDec(event, bar.barMin, barMin, barMax, EE_MODEL|NO_INCDEC_MARKS);
break;
case 2:
- bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, barMax, EE_MODEL|NO_INCDEC_MARKS);
+ bar.barMax = checkIncDec(event, bar.barMax, barMin, barMax, EE_MODEL|NO_INCDEC_MARKS);
break;
}
}
diff --git a/radio/src/gui/128x64/model_flightmodes.cpp b/radio/src/gui/128x64/model_flightmodes.cpp
index 0002bf23b..07f5f0163 100644
--- a/radio/src/gui/128x64/model_flightmodes.cpp
+++ b/radio/src/gui/128x64/model_flightmodes.cpp
@@ -64,13 +64,8 @@ void menuModelFlightModeOne(event_t event)
drawFlightMode(13*FW, 0, s_currIdx+1, (getFlightMode()==s_currIdx ? BOLD : 0));
#if defined(GVARS) && !defined(GVARS_IN_CURVES_SCREEN)
-#if defined(PCBTARANIS)
#define VERTICAL_SHIFT (ITEM_MODEL_FLIGHT_MODE_FADE_IN-ITEM_MODEL_FLIGHT_MODE_TRIMS)
static const uint8_t mstate_tab_fm1[] = {0, 3, 0, 0, (uint8_t)-1, 1, 1, 1, 1, 1, 1};
-#else
- #define VERTICAL_SHIFT (ITEM_MODEL_FLIGHT_MODE_FADE_IN-ITEM_MODEL_FLIGHT_MODE_SWITCH)
- static const uint8_t mstate_tab_fm1[] = {0, 0, 0, (uint8_t)-1, 1, 1, 1, 1, 1};
-#endif
static const uint8_t mstate_tab_others[] = {0, 0, 3, 0, 0, (uint8_t)-1, 2, 2, 2, 2, 2};
check(event, 0, nullptr, 0, (s_currIdx == 0) ? mstate_tab_fm1 : mstate_tab_others, DIM(mstate_tab_others)-1, ITEM_MODEL_FLIGHT_MODE_MAX - HEADER_LINE - (s_currIdx==0 ? (ITEM_MODEL_FLIGHT_MODE_FADE_IN-ITEM_MODEL_FLIGHT_MODE_SWITCH-1) : 0));
diff --git a/radio/src/gui/128x64/model_input_edit.cpp b/radio/src/gui/128x64/model_input_edit.cpp
index 575ce4fb7..077d84cb3 100644
--- a/radio/src/gui/128x64/model_input_edit.cpp
+++ b/radio/src/gui/128x64/model_input_edit.cpp
@@ -21,7 +21,6 @@
#include "opentx.h"
#define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2)
-#define EXPO_ONE_FM_WIDTH (5*FW)
int expoFn(int x)
{
@@ -31,28 +30,6 @@ int expoFn(int x)
return anas[ed->chn];
}
-void drawFunction(FnFuncP fn, uint8_t offset)
-{
- lcdDrawVerticalLine(CURVE_CENTER_X-offset, 0/*TODO CURVE_CENTER_Y-CURVE_SIDE_WIDTH*/, CURVE_SIDE_WIDTH*2, 0xee);
- lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee);
-
- coord_t prev_yv = (coord_t)-1;
-
- for (int xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) {
- coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX);
- if (prev_yv != (coord_t)-1) {
- if (abs((int8_t)yv-prev_yv) <= 1) {
- lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE);
- }
- else {
- uint8_t tmp = (prev_yv < yv ? 0 : 1);
- lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv);
- }
- }
- prev_yv = yv;
- }
-}
-
enum ExposFields {
EXPO_FIELD_INPUT_NAME,
EXPO_FIELD_LINE_NAME,
@@ -78,7 +55,7 @@ void menuModelExpoOne(event_t event)
killEvents(event);
}
#elif defined(NAVIGATION_XLITE)
- if (event == EVT_KEY_LONG(KEY_SHIFT)) {
+ if (event == EVT_KEY_FIRST(KEY_ENTER) && IS_SHIFT_PRESSED()) {
pushMenu(menuChannelsView);
killEvents(event);
}
@@ -113,13 +90,15 @@ void menuModelExpoOne(event_t event)
case EXPO_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, STR_SOURCE);
drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, RIGHT|STREXPANDED|attr);
- if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs);
+ if (attr)
+ ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs);
break;
case EXPO_FIELD_SCALE:
lcdDrawTextAlignedLeft(y, STR_SCALE);
- drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), attr);
- if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL);
+ drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), RIGHT | attr);
+ if (attr)
+ ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL);
break;
case EXPO_FIELD_WEIGHT:
@@ -159,34 +138,20 @@ void menuModelExpoOne(event_t event)
break;
case EXPO_FIELD_TRIM:
- uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail);
+ uint8_t notStick = (ed->srcRaw > MIXSRC_Ail);
int8_t carryTrim = -ed->carryTrim;
lcdDrawTextAlignedLeft(y, STR_TRIM);
- lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, RIGHT | (menuHorizontalPosition==0 ? attr : 0));
- if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_LAST);
+ lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (notStick && carryTrim == 0) ? 0 : carryTrim+1, RIGHT | (menuHorizontalPosition==0 ? attr : 0));
+ if (attr)
+ ed->carryTrim = -checkIncDecModel(event, carryTrim, notStick ? TRIM_ON : -TRIM_OFF, -TRIM_LAST);
break;
}
y += FH;
}
drawFunction(expoFn);
-
- int x512 = getValue(ed->srcRaw);
- if (ed->srcRaw >= MIXSRC_FIRST_TELEM) {
- drawSensorCustomValue(LCD_W-FW, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0);
- if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale);
- }
- else {
- lcdDrawNumber(LCD_W-FW, 6*FH, calcRESXto1000(x512), RIGHT | PREC1);
- }
- x512 = limit(-1024, x512, 1024);
- int y512 = expoFn(x512);
- y512 = limit(-1024, y512, 1024);
- lcdDrawNumber(CURVE_CENTER_X-FWNUM, 1*FH, calcRESXto1000(y512), RIGHT | PREC1);
-
- x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH);
- y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX;
-
- lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1);
- lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1);
+ // those parameters are global so that they can be reused in the curve edit screen
+ s_currSrcRaw = ed->srcRaw;
+ s_currScale = ed->scale;
+ drawCursor(expoFn);
}
diff --git a/radio/src/gui/128x64/model_inputs_mixes.cpp b/radio/src/gui/128x64/model_inputs_mixes.cpp
deleted file mode 100644
index 93342bf24..000000000
--- a/radio/src/gui/128x64/model_inputs_mixes.cpp
+++ /dev/null
@@ -1,849 +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 "opentx.h"
-
-#define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2)
-#define EXPO_ONE_FM_WIDTH (5*FW)
-
-int expoFn(int x)
-{
- ExpoData *ed = expoAddress(s_currIdx);
- int16_t anas[MAX_INPUTS] = {0};
- anas[ed->chn] = x;
- applyExpos(anas, e_perout_mode_inactive_flight_mode);
- return anas[ed->chn];
-}
-
-void drawFunction(FnFuncP fn, uint8_t offset)
-{
- lcdDrawVerticalLine(CURVE_CENTER_X-offset, 0, LCD_H, 0xee);
- lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee);
-
- coord_t prev_yv = (coord_t)-1;
-
- for (int8_t xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) {
- coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX);
- if (prev_yv != (coord_t)-1) {
- if (abs((int8_t)yv-prev_yv) <= 1) {
- lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE);
- }
- else {
- uint8_t tmp = (prev_yv < yv ? 0 : 1);
- lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv);
- }
- }
- prev_yv = yv;
- }
-}
-
-
-uint8_t getExpoMixCount(uint8_t expo)
-{
- uint8_t count = 0;
- uint8_t ch ;
-
- for(int8_t i=(expo ? MAX_EXPOS-1 : MAX_MIXERS-1); i>=0; i--) {
- ch = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw);
- if (ch != 0) {
- count++;
- }
- }
- return count;
-}
-
-bool reachExpoMixCountLimit(uint8_t expo)
-{
- // check mixers count limit
- if (getExpoMixCount(expo) >= (expo ? MAX_EXPOS : MAX_MIXERS)) {
- POPUP_WARNING(expo ? STR_NOFREEEXPO : STR_NOFREEMIXER);
- return true;
- }
- return false;
-}
-
-void deleteExpoMix(uint8_t expo, uint8_t idx)
-{
- pauseMixerCalculations();
- if (expo) {
- ExpoData *expo = expoAddress(idx);
- memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
- memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData));
- }
- else {
- MixData *mix = mixAddress(idx);
- memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData));
- memclear(&g_model.mixData[MAX_MIXERS-1], sizeof(MixData));
- }
- resumeMixerCalculations();
- storageDirty(EE_MODEL);
-}
-
-// TODO avoid this global s_currCh on ARM boards ...
-int8_t s_currCh;
-void insertExpoMix(uint8_t expo, uint8_t idx)
-{
- pauseMixerCalculations();
- if (expo) {
- ExpoData *expo = expoAddress(idx);
- memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
- memclear(expo, sizeof(ExpoData));
- expo->mode = 3; // pos&neg
- expo->chn = s_currCh - 1;
- expo->weight = 100;
- }
- else {
- MixData *mix = mixAddress(idx);
- memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData));
- memclear(mix, sizeof(MixData));
- mix->destCh = s_currCh-1;
- mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channelOrder(s_currCh));
- mix->weight = 100;
- }
- resumeMixerCalculations();
- storageDirty(EE_MODEL);
-}
-
-void copyExpoMix(uint8_t expo, uint8_t idx)
-{
- pauseMixerCalculations();
- if (expo) {
- ExpoData *expo = expoAddress(idx);
- memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
- }
- else {
- MixData *mix = mixAddress(idx);
- memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData));
- }
- resumeMixerCalculations();
- storageDirty(EE_MODEL);
-}
-
-bool swapExpoMix(uint8_t expo, uint8_t &idx, uint8_t up)
-{
- void *x, *y;
- uint8_t size;
- int8_t tgt_idx = (up ? idx-1 : idx+1);
-
- if (expo) {
- x = (ExpoData *)expoAddress(idx);
-
- if (tgt_idx < 0) {
- if (((ExpoData *)x)->chn == 0)
- return false;
- ((ExpoData *)x)->chn--;
- return true;
- }
-
- if (tgt_idx == MAX_EXPOS) {
- if (((ExpoData *)x)->chn == MAX_INPUTS-1)
- return false;
- ((ExpoData *)x)->chn++;
- return true;
- }
-
- y = (ExpoData *)expoAddress(tgt_idx);
- if(((ExpoData *)x)->chn != ((ExpoData *)y)->chn || !EXPO_VALID((ExpoData *)y)) {
- if (up) {
- if (((ExpoData *)x)->chn>0) ((ExpoData *)x)->chn--;
- else return false;
- }
- else {
- if (((ExpoData *)x)->chnchn++;
- else return false;
- }
- return true;
- }
-
- size = sizeof(ExpoData);
- }
- else {
- x = (MixData *)mixAddress(idx);
-
- if (tgt_idx < 0) {
- if (((MixData *)x)->destCh == 0)
- return false;
- ((MixData *)x)->destCh--;
- return true;
- }
-
- if (tgt_idx == MAX_MIXERS) {
- if (((MixData *)x)->destCh == MAX_OUTPUT_CHANNELS-1)
- return false;
- ((MixData *)x)->destCh++;
- return true;
- }
-
- y = (MixData *)mixAddress(tgt_idx);
- uint8_t destCh = ((MixData *)x)->destCh;
- if(!((MixData *)y)->srcRaw || destCh != ((MixData *)y)->destCh) {
- if (up) {
- if (destCh>0) ((MixData *)x)->destCh--;
- else return false;
- }
- else {
- if (destChdestCh++;
- else return false;
- }
- return true;
- }
-
- size = sizeof(MixData);
- }
-
- pauseMixerCalculations();
- memswap(x, y, size);
- resumeMixerCalculations();
-
- idx = tgt_idx;
- return true;
-}
-
-enum ExposFields {
- EXPO_FIELD_NAME,
- EXPO_FIELD_WEIGHT,
- EXPO_FIELD_EXPO,
- EXPO_FIELD_CURVE,
- CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES)
- EXPO_FIELD_SWITCH,
- EXPO_FIELD_SIDE,
- EXPO_FIELD_MAX
-};
-
-#define CURVE_ROWS 0
-
-void menuModelExpoOne(event_t event)
-{
- ExpoData * ed = expoAddress(s_currIdx);
- drawSource(7*FW+FW/2, 0, MIXSRC_Rud+ed->chn, 0);
-
- SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {0, 0, 0, CURVE_ROWS, CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/});
-
- int8_t sub = menuVerticalPosition;
-
- coord_t y = MENU_HEADER_HEIGHT + 1;
-
- for (uint8_t i=0; i0 ? BLINK|INVERS : INVERS) : 0);
- switch (i) {
- case EXPO_FIELD_NAME:
- editSingleName(EXPO_ONE_2ND_COLUMN-sizeof(ed->name)*FW, y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr);
- break;
-
- case EXPO_FIELD_WEIGHT:
- lcdDrawTextAlignedLeft(y, STR_WEIGHT);
- ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, -100, 100, attr, 0, event);
- break;
-
- case EXPO_FIELD_EXPO:
- lcdDrawTextAlignedLeft(y, STR_EXPO);
- if (ed->curveMode==MODE_EXPO || ed->curveParam==0) {
- ed->curveMode = MODE_EXPO;
- ed->curveParam = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->curveParam, -100, 100, attr, 0, event);
- }
- else {
- lcdDrawText(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr);
- }
- break;
-
- case EXPO_FIELD_CURVE:
- lcdDrawTextAlignedLeft(y, STR_CURVE);
- if (ed->curveMode!=MODE_EXPO || ed->curveParam==0) {
- drawCurveName(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->curveParam, attr);
- if (attr) {
- 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_currIdxSubMenu = ed->curveParam - CURVE_BASE;
- pushMenu(menuModelCurveOne);
- }
- }
- }
- else {
- lcdDrawText(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr);
- }
- break;
-
-#if defined(FLIGHT_MODES)
- case EXPO_FIELD_FLIGHT_MODES:
- ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN-EXPO_ONE_FM_WIDTH, y, event, ed->flightModes, attr);
- break;
-#endif
-
- case EXPO_FIELD_SWITCH:
- ed->swtch = editSwitch(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->swtch, attr, event);
- break;
-
- case EXPO_FIELD_SIDE:
- ed->mode = 4 - editChoice(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_SIDE, STR_VCURVEFUNC, 4-ed->mode, 1, 3, attr, event);
- break;
- }
- y += FH;
- }
-
- drawFunction(expoFn);
-
- int16_t x512 = calibratedAnalogs[ed->chn];
- lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto100(x512), 0);
- int16_t y512 = expoFn(x512);
- lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto100(y512), 0);
-
- x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH);
- y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX;
-
- lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1);
- lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1);
-}
-
-enum MixFields {
- MIX_FIELD_NAME,
- MIX_FIELD_SOURCE,
- MIX_FIELD_WEIGHT,
- MIX_FIELD_OFFSET,
- MIX_FIELD_TRIM,
- MIX_FIELD_CURVE,
- CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_PHASE)
- MIX_FIELD_SWITCH,
- MIX_FIELD_WARNING,
- MIX_FIELD_MLTPX,
- MIX_FIELD_DELAY_UP,
- MIX_FIELD_DELAY_DOWN,
- MIX_FIELD_SLOW_UP,
- MIX_FIELD_SLOW_DOWN,
- MIX_FIELD_COUNT
-};
-
-#define GAUGE_WIDTH 33
-#define GAUGE_HEIGHT 6
-void drawOffsetBar(uint8_t x, uint8_t y, MixData * md)
-{
- int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
- int weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
- int barMin = offset - weight;
- int barMax = offset + weight;
- if (y > 15) {
- lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT);
- lcdDrawNumber(x+GAUGE_WIDTH+1, y-6, barMax, TINSIZE);
- }
- if (weight < 0) {
- barMin = -barMin;
- barMax = -barMax;
- }
- if (barMin < -101)
- barMin = -101;
- if (barMax > 101)
- barMax = 101;
- lcdDrawHorizontalLine(x-2, y, GAUGE_WIDTH+2, DOTTED);
- lcdDrawHorizontalLine(x-2, y+GAUGE_HEIGHT, GAUGE_WIDTH+2, DOTTED);
- lcdDrawSolidVerticalLine(x-2, y+1, GAUGE_HEIGHT-1);
- lcdDrawSolidVerticalLine(x+GAUGE_WIDTH-1, y+1, GAUGE_HEIGHT-1);
- if (barMin <= barMax) {
- int8_t right = (barMax * GAUGE_WIDTH) / 200;
- int8_t left = ((barMin * GAUGE_WIDTH) / 200)-1;
- lcdDrawSolidFilledRect(x+GAUGE_WIDTH/2+left, y+2, right-left, GAUGE_HEIGHT-3);
- }
- lcdDrawSolidVerticalLine(x+GAUGE_WIDTH/2-1, y, GAUGE_HEIGHT+1);
- if (barMin == -101) {
- for (uint8_t i=0; i<3; ++i) {
- lcdDrawPoint(x+i, y+4-i);
- lcdDrawPoint(x+3+i, y+4-i);
- }
- }
- if (barMax == 101) {
- for (uint8_t i=0; i<3; ++i) {
- lcdDrawPoint(x+GAUGE_WIDTH-8+i, y+4-i);
- lcdDrawPoint(x+GAUGE_WIDTH-5+i, y+4-i);
- }
- }
-}
-#undef GAUGE_WIDTH
-#undef GAUGE_HEIGHT
-
-void menuModelMixOne(event_t event)
-{
- title(STR_MIXES);
- MixData * md2 = mixAddress(s_currIdx) ;
- putsChn(lcdLastRightPos+1*FW, 0, md2->destCh+1,0);
-
- SUBMENU_NOTITLE(MIX_FIELD_COUNT, {0, 0, 0, 0, 1, 1, CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/});
-
- int8_t sub = menuVerticalPosition;
- int8_t editMode = s_editMode;
-
- for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0);
- switch (i) {
- case MIX_FIELD_NAME:
- editSingleName(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr);
- break;
- case MIX_FIELD_SOURCE:
- drawFieldLabel(COLUMN_X, y, STR_SOURCE);
- drawSource(COLUMN_X+MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr);
- if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST);
- break;
- case MIX_FIELD_WEIGHT:
- drawFieldLabel(COLUMN_X, y, STR_WEIGHT);
- gvarWeightItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2, attr|LEFT, event);
- break;
- case MIX_FIELD_OFFSET:
- {
- drawFieldLabel(COLUMN_X, y, STR_OFFSET);
- u_int8int16_t offset;
- MD_OFFSET_TO_UNION(md2, offset);
- offset.word = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN, y, offset.word, MIX_OFFSET_MIN, MIX_OFFSET_MAX, attr|LEFT, 0, event);
- MD_UNION_TO_OFFSET(offset, md2);
- drawOffsetBar(COLUMN_X+MIXES_2ND_COLUMN+22, y, md2);
- break;
- }
-
- case MIX_FIELD_TRIM:
- {
- uint8_t not_stick = (md2->srcRaw > NUM_STICKS);
- int8_t carryTrim = -md2->carryTrim;
- drawFieldLabel(COLUMN_X, y, STR_TRIM);
- lcdDrawTextAtIndex((not_stick ? COLUMN_X+MIXES_2ND_COLUMN : COLUMN_X+6*FW-3), y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, menuHorizontalPosition==0 ? attr : 0);
- if (attr && menuHorizontalPosition==0 && (not_stick || editMode>0)) md2->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL);
- if (!not_stick) {
- lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, STR_DREX);
- drawCheckBox(COLUMN_X+MIXES_2ND_COLUMN+DREX_CHBOX_OFFSET, y, !md2->noExpo, menuHorizontalPosition==1 ? attr : 0);
- if (attr && menuHorizontalPosition==1 && editMode>0) md2->noExpo = !checkIncDecModel(event, !md2->noExpo, 0, 1);
- }
- else if (attr) {
- REPEAT_LAST_CURSOR_MOVE();
- }
- break;
- }
-
- case MIX_FIELD_CURVE:
- {
- drawFieldLabel(COLUMN_X, y, STR_CURVE);
- int8_t curveParam = md2->curveParam;
- if (md2->curveMode == MODE_CURVE) {
- drawCurveName(COLUMN_X+MIXES_2ND_COLUMN, y, curveParam, attr);
- if (attr) {
- if (event==EVT_KEY_LONG(KEY_ENTER) && (curveParam<0 || curveParam>=CURVE_BASE)){
- s_currIdxSubMenu = (curveParam<0 ? -curveParam-1 : curveParam-CURVE_BASE);
- pushMenu(menuModelCurveOne);
- }
- else {
- CHECK_INCDEC_MODELVAR(event, md2->curveParam, -MAX_CURVES, CURVE_BASE+MAX_CURVES-1);
- if (md2->curveParam == 0)
- md2->curveMode = MODE_DIFFERENTIAL;
- }
- }
- }
- else {
- lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, "Diff", menuHorizontalPosition==0 ? attr : 0);
- md2->curveParam = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN+5*FW, y, curveParam, -100, 100, LEFT|(menuHorizontalPosition==1 ? attr : 0), 0, editMode>0 ? event : 0);
- if (attr && editMode>0 && menuHorizontalPosition==0) {
- int8_t tmp = 0;
- CHECK_INCDEC_MODELVAR(event, tmp, -1, 1);
- if (tmp != 0) {
- md2->curveMode = MODE_CURVE;
- md2->curveParam = tmp;
- }
- }
- }
- break;
- }
-#if defined(FLIGHT_MODES)
- case MIX_FIELD_FLIGHT_PHASE:
- md2->flightModes = editFlightModes(COLUMN_X+MIXES_2ND_COLUMN, y, event, md2->flightModes, attr);
- break;
-#endif
- case MIX_FIELD_SWITCH:
- md2->swtch = editSwitch(COLUMN_X+MIXES_2ND_COLUMN, y, md2->swtch, attr, event);
- break;
- case MIX_FIELD_WARNING:
- drawFieldLabel(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXWARNING);
- if (md2->mixWarn)
- lcdDrawNumber(COLUMN_X+MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT);
- else
- lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, STR_OFF, attr);
- if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3);
- break;
- case MIX_FIELD_MLTPX:
- md2->mltpx = editChoice(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event);
- break;
- case MIX_FIELD_DELAY_UP:
- md2->delayUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYUP, md2->delayUp);
- break;
- case MIX_FIELD_DELAY_DOWN:
- md2->delayDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYDOWN, md2->delayDown);
- break;
- case MIX_FIELD_SLOW_UP:
- md2->speedUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWUP, md2->speedUp);
- break;
- case MIX_FIELD_SLOW_DOWN:
- md2->speedDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWDOWN, md2->speedDown);
- break;
- }
- }
-}
-
-#define _STR_MAX(x) "/" #x
-#define STR_MAX(x) _STR_MAX(x)
-
- #define EXPO_LINE_WEIGHT_POS 7*FW+1
- #define EXPO_LINE_EXPO_POS 10*FW+5
- #define EXPO_LINE_SWITCH_POS 11*FW+2
- #define EXPO_LINE_SIDE_POS 14*FW+2
- #define EXPO_LINE_SELECT_POS 24
- #define EXPO_LINE_FM_POS
- #define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW
- #define MIX_LINE_SRC_POS 4*FW-1
- #define MIX_LINE_WEIGHT_POS 11*FW+3
- #define MIX_LINE_CURVE_POS 12*FW+2
- #define MIX_LINE_SWITCH_POS 16*FW
- #define MIX_LINE_DELAY_POS 19*FW+7
-
-void onExpoMixMenu(const char *result)
-{
- bool expo = (menuHandlers[menuLevel] == menuModelExposAll);
- uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1);
-
- if (result == STR_EDIT) {
- pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
- }
- else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) {
- if (!reachExpoMixCountLimit(expo)) {
- s_currCh = chn;
- if (result == STR_INSERT_AFTER) { s_currIdx++; menuVerticalPosition++; }
- insertExpoMix(expo, s_currIdx);
- pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
- }
- }
- else if (result == STR_COPY || result == STR_MOVE) {
- s_copyMode = (result == STR_COPY ? COPY_MODE : MOVE_MODE);
- s_copySrcIdx = s_currIdx;
- s_copySrcCh = chn;
- s_copySrcRow = menuVerticalPosition;
- }
- else if (result == STR_DELETE) {
- deleteExpoMix(expo, s_currIdx);
- }
-}
-
-void displayMixInfos(coord_t y, MixData *md)
-{
- if (md->curveParam) {
- if (md->curveMode == MODE_CURVE)
- drawCurveName(MIX_LINE_CURVE_POS, y, md->curveParam);
- else
- displayGVar(MIX_LINE_CURVE_POS+3*FW, y, md->curveParam, -100, 100);
- }
-
- if (md->swtch) {
- drawSwitch(MIX_LINE_SWITCH_POS, y, md->swtch);
- }
-}
-
-void displayMixLine(coord_t y, MixData * md)
-{
- if (md->name[0]) {
- lcdDrawSizedText(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR);
- }
- else {
- displayMixInfos(y, md);
- }
-}
-
-void displayExpoInfos(coord_t y, ExpoData *ed)
-{
- if (ed->curveMode == MODE_CURVE)
- drawCurveName(EXPO_LINE_EXPO_POS-3*FW, y, ed->curveParam);
- else
- displayGVar(EXPO_LINE_EXPO_POS, y, ed->curveParam, -100, 100);
-
- drawSwitch(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0);
-}
-
-void displayExpoLine(coord_t y, ExpoData *ed)
-{
- displayExpoInfos(y, ed);
-
- if (ed->name[0]) {
- lcdDrawSizedText(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR);
- }
-}
-
-void menuModelExpoMix(uint8_t expo, event_t event)
-{
- uint8_t sub = menuVerticalPosition;
-
- if (s_editMode > 0)
- s_editMode = 0;
-
- uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1);
-
- switch (event)
- {
- case EVT_ENTRY:
- case EVT_ENTRY_UP:
- s_copyMode = 0;
- s_copyTgtOfs = 0;
- break;
- case EVT_KEY_LONG(KEY_EXIT):
- if (s_copyMode && s_copyTgtOfs == 0) {
- deleteExpoMix(expo, s_currIdx);
- killEvents(event);
- event = 0;
- }
- // no break
-#if defined(ROTARY_ENCODER_NAVIGATION)
- case EVT_ROTARY_LONG:
- if (s_copyMode) {
- killEvents(event);
- }
-#endif
- case EVT_KEY_BREAK(KEY_EXIT):
- if (s_copyMode) {
- if (s_copyTgtOfs) {
- // cancel the current copy / move operation
- if (s_copyMode == COPY_MODE) {
- deleteExpoMix(expo, s_currIdx);
- }
- else {
- do {
- swapExpoMix(expo, s_currIdx, s_copyTgtOfs > 0);
- s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1);
- } while (s_copyTgtOfs != 0);
- storageDirty(EE_MODEL);
- }
- menuVerticalPosition = s_copySrcRow;
- s_copyTgtOfs = 0;
- }
- s_copyMode = 0;
- event = 0;
- }
- break;
- case EVT_KEY_BREAK(KEY_ENTER):
- if (sub != 0 && (!s_currCh || (s_copyMode && !s_copyTgtOfs)) && !READ_ONLY()) {
- s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
- s_copySrcIdx = s_currIdx;
- s_copySrcCh = chn;
- s_copySrcRow = sub;
- break;
- }
- // no break
-
- case EVT_KEY_LONG(KEY_ENTER):
- killEvents(event);
- if (s_copyTgtOfs) {
- s_copyMode = 0;
- s_copyTgtOfs = 0;
- }
- else if (sub != 0) {
- if (READ_ONLY()) {
- if (!s_currCh) {
- pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
- return;
- }
- }
- else {
- if (s_copyMode) s_currCh = 0;
- if (s_currCh) {
- if (reachExpoMixCountLimit(expo)) break;
- insertExpoMix(expo, s_currIdx);
- pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
- s_copyMode = 0;
- return;
- }
- else {
- event = 0;
- s_copyMode = 0;
- POPUP_MENU_ADD_ITEM(STR_EDIT);
- POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE);
- POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER);
- POPUP_MENU_ADD_ITEM(STR_COPY);
- POPUP_MENU_ADD_ITEM(STR_MOVE);
- POPUP_MENU_ADD_ITEM(STR_DELETE);
- POPUP_MENU_START(onExpoMixMenu);
- }
- }
- }
- break;
- case EVT_KEY_LONG(KEY_LEFT):
- case EVT_KEY_LONG(KEY_RIGHT):
- if (s_copyMode && !s_copyTgtOfs) {
- if (reachExpoMixCountLimit(expo)) break;
- s_currCh = chn;
- if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; menuVerticalPosition++; }
- insertExpoMix(expo, s_currIdx);
- pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
- s_copyMode = 0;
- killEvents(event);
- return;
- }
- break;
-#if defined(ROTARY_ENCODER_NAVIGATION)
- case EVT_ROTARY_LEFT:
- case EVT_ROTARY_RIGHT:
-#endif
- case EVT_KEY_FIRST(KEY_UP):
- case EVT_KEY_REPT(KEY_UP):
- case EVT_KEY_FIRST(KEY_DOWN):
- case EVT_KEY_REPT(KEY_DOWN):
- if (s_copyMode) {
- uint8_t key = (event & 0x1f);
- uint8_t next_ofs = ((IS_ROTARY_LEFT(event) || key==KEY_UP) ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1);
-
- if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) {
- // insert a mix on the same channel (just above / just below)
- if (reachExpoMixCountLimit(expo)) break;
- copyExpoMix(expo, s_currIdx);
- if (IS_ROTARY_RIGHT(event) || key==KEY_DOWN) s_currIdx++;
- else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++;
- }
- else if (next_ofs==0 && s_copyMode==COPY_MODE) {
- // delete the mix
- deleteExpoMix(expo, s_currIdx);
- if (IS_ROTARY_LEFT(event) || key==KEY_UP) s_currIdx--;
- }
- else {
- // only swap the mix with its neighbor
- if (!swapExpoMix(expo, s_currIdx, IS_ROTARY_LEFT(event) || key==KEY_UP)) break;
- storageDirty(EE_MODEL);
- }
-
- s_copyTgtOfs = next_ofs;
- }
- break;
- }
-
- lcdDrawNumber(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXES))+FW+FW/2, 0, getExpoMixCount(expo));
- lcdDrawText(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXES))+FW+FW/2, 0, expo ? STR_MAX(MAX_EXPOS) : STR_MAX(MAX_MIXERS));
-
- SIMPLE_MENU(expo ? STR_MENUINPUTS : STR_MIXES, menuTabModel, expo ? MENU_MODEL_INPUTS : MENU_MODEL_MIXES, s_maxLines);
-
- sub = menuVerticalPosition;
- s_currCh = 0;
- uint8_t cur = 1;
- uint8_t i = 0;
-
- for (uint8_t ch=1; ch<=(expo ? MAX_INPUTS : MAX_OUTPUT_CHANNELS); ch++) {
- void *pointer = nullptr; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer;
- coord_t y = MENU_HEADER_HEIGHT-FH+1+(cur-menuVerticalOffset)*FH;
- if (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)) {
- if (menuVerticalOffset < cur && cur-menuVerticalOffset < LCD_LINES) {
- if (expo) {
- drawSource(0, y, MIXSRC_Rud+ch-1, 0);
- }
- else {
- putsChn(0, y, ch, 0); // show CHx
- }
- }
- uint8_t mixCnt = 0;
- do {
- if (s_copyMode) {
- if (s_copyMode == MOVE_MODE && menuVerticalOffset < cur && cur-menuVerticalOffset < 8 && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
- lcdDrawRect(expo ? 18 : 22, y-1, expo ? LCD_W-18 : LCD_W-22, 9, DOTTED);
- cur++; y+=FH;
- }
- if (s_currIdx == i) {
- sub = menuVerticalPosition = cur;
- s_currCh = ch;
- }
- }
- else if (sub == cur) {
- s_currIdx = i;
- }
- if (menuVerticalOffset < cur && cur-menuVerticalOffset < 8) {
- uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
- if (expo) {
- ed->weight = GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, -100, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, event);
- displayExpoLine(y, ed);
- if (ed->mode!=3) {
- lcdDrawChar(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127);
- }
- }
- else {
- if (mixCnt > 0) lcdDrawTextAtIndex(FW, y, STR_VMLTPX2, md->mltpx, 0);
-
- drawSource(MIX_LINE_SRC_POS, y, md->srcRaw, 0);
-
- gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), event);
-
- displayMixLine(y, md);
-
- char cs = ' ';
- if (md->speedDown || md->speedUp)
- cs = 'S';
- if (md->delayUp || md->delayDown)
- cs = (cs =='S' ? '*' : 'D');
- lcdDrawChar(MIX_LINE_DELAY_POS, y, cs);
- }
- if (s_copyMode) {
- if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
- /* draw a border around the raw on selection mode (copy/move) */
- lcdDrawRect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, s_copyMode == COPY_MODE ? SOLID : DOTTED);
- }
- if (cur == sub) {
- /* invert the raw when it's the current one */
- lcdDrawSolidFilledRect(expo ? EXPO_LINE_SELECT_POS+1 : 23, y, expo ? (LCD_W-EXPO_LINE_SELECT_POS-2) : (LCD_W-24), 7);
- }
- }
- }
- cur++; y+=FH; mixCnt++; i++; if (expo) ed++; else md++;
- } while (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch));
- if (s_copyMode == MOVE_MODE && menuVerticalOffset < cur && cur-menuVerticalOffset < LCD_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
- lcdDrawRect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? LCD_W-EXPO_LINE_SELECT_POS : LCD_W-22, 9, DOTTED);
- cur++; y+=FH;
- }
- }
- else {
- uint8_t attr = 0;
- if (sub == cur) {
- s_currIdx = i;
- s_currCh = ch;
- if (!s_copyMode) {
- attr = INVERS;
- }
- }
- if (menuVerticalOffset < cur && cur-menuVerticalOffset < LCD_LINES) {
- if (expo) {
- drawSource(0, y, MIXSRC_Rud+ch-1, attr);
- }
- else {
- putsChn(0, y, ch, attr); // show CHx
- }
- if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) {
- lcdDrawRect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, DOTTED);
- }
- }
- cur++; y+=FH;
- }
- }
- s_maxLines = cur;
- if (sub >= s_maxLines-1) menuVerticalPosition = s_maxLines-1;
-}
-
-void menuModelExposAll(event_t event)
-{
- return menuModelExpoMix(1, event);
-}
-
-void menuModelMixAll(event_t event)
-{
- return menuModelExpoMix(0, event);
-}
diff --git a/radio/src/gui/128x64/model_mix_edit.cpp b/radio/src/gui/128x64/model_mix_edit.cpp
index d21e76e6f..a0168b0d7 100644
--- a/radio/src/gui/128x64/model_mix_edit.cpp
+++ b/radio/src/gui/128x64/model_mix_edit.cpp
@@ -91,7 +91,7 @@ void menuModelMixOne(event_t event)
killEvents(event);
}
#elif defined(NAVIGATION_XLITE)
- if (event == EVT_KEY_LONG(KEY_SHIFT)) {
+ if (event == EVT_KEY_FIRST(KEY_ENTER) && IS_SHIFT_PRESSED()) {
pushMenu(menuChannelsView);
killEvents(event);
}
@@ -150,6 +150,8 @@ void menuModelMixOne(event_t event)
case MIX_FIELD_CURVE:
lcdDrawTextAlignedLeft(y, STR_CURVE);
+ s_currSrcRaw = md2->srcRaw;
+ s_currScale = 0;
editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, s_editMode > 0 ? event : 0, attr);
break;
diff --git a/radio/src/gui/128x64/model_select.cpp b/radio/src/gui/128x64/model_select.cpp
index 19ee6a702..24f2b39fc 100644
--- a/radio/src/gui/128x64/model_select.cpp
+++ b/radio/src/gui/128x64/model_select.cpp
@@ -36,6 +36,10 @@ void onModelSelectMenu(const char * result)
int8_t sub = menuVerticalPosition;
if (result == STR_SELECT_MODEL || result == STR_CREATE_MODEL) {
+ if (!g_eeGeneral.disableRssiPoweroffAlarm) {
+ if (!confirmModelChange())
+ return;
+ }
selectModel(sub);
}
else if (result == STR_COPY_MODEL) {
diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp
index 94252ffbc..1ba46c035 100644
--- a/radio/src/gui/128x64/model_setup.cpp
+++ b/radio/src/gui/128x64/model_setup.cpp
@@ -69,6 +69,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_THROTTLE_REVERSED,
ITEM_MODEL_SETUP_THROTTLE_TRACE,
ITEM_MODEL_SETUP_THROTTLE_TRIM,
+ ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH,
ITEM_MODEL_SETUP_PREFLIGHT_LABEL,
ITEM_MODEL_SETUP_CHECKLIST_DISPLAY,
ITEM_MODEL_SETUP_THROTTLE_WARNING,
@@ -121,12 +122,22 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_EXTERNAL_MODULE_SUBTYPE,
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,
@@ -135,6 +146,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,
@@ -207,11 +219,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 0;
- }
-#endif
else
return 0;
}
@@ -303,6 +310,9 @@ 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 \
@@ -348,6 +358,7 @@ void menuModelSetup(event_t event)
0, // Throttle reverse
0, // Throttle trace source
0, // Throttle trim
+ 0, // Throttle trim switch
LABEL(PreflightCheck),
0, // Checklist
@@ -367,9 +378,12 @@ void menuModelSetup(event_t event)
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)
@@ -396,6 +410,7 @@ void menuModelSetup(event_t event)
0, // Throttle reverse
0, // Throttle trace source
0, // Throttle trim
+ 0, // Throttle trim switch
LABEL(PreflightCheck),
0, // Checklist
@@ -407,8 +422,10 @@ void menuModelSetup(event_t event)
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
@@ -607,6 +624,13 @@ void menuModelSetup(event_t event)
g_model.thrTrim = editCheckBox(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event);
break;
+ case ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH:
+ lcdDrawTextAlignedLeft(y, STR_TTRIM_SW);
+ if (attr)
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.thrTrimSw, NUM_TRIMS - 1);
+ drawSource(MODEL_SETUP_2ND_COLUMN, y, g_model.getThrottleStickTrimSource(), attr);
+ break;
+
case ITEM_MODEL_SETUP_PREFLIGHT_LABEL:
lcdDrawTextAlignedLeft(y, STR_PREFLIGHT);
break;
@@ -1051,6 +1075,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);
@@ -1060,7 +1099,7 @@ void menuModelSetup(event_t event)
lcdDrawTextAlignedLeft(y, INDENT TR_MODE);
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerData.mode, attr);
if (attr) {
- g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX, EE_MODEL, isTrainerModeAvailable);
+ g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable);
#if defined(BLUETOOTH)
if (checkIncDec_Ret) {
bluetooth.state = BLUETOOTH_STATE_OFF;
@@ -1320,15 +1359,12 @@ void menuModelSetup(event_t event)
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 if (attr) {
- l_posHorz += 1;
- }
- if (isModuleBindRangeAvailable(moduleIdx)) {
if (attr && l_posHorz == 0) {
if (s_editMode > 0) {
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], getMaxRxNum(moduleIdx));
if (checkIncDec_Ret) {
+ if (isModuleCrossfire(moduleIdx))
+ moduleState[EXTERNAL_MODULE].counter = CRSF_FRAME_MODELID;
modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx];
}
else if (event == EVT_KEY_LONG(KEY_ENTER)) {
@@ -1341,6 +1377,11 @@ void menuModelSetup(event_t event)
}
}
}
+ }
+ else if (attr) {
+ l_posHorz += 1;
+ }
+ if (isModuleBindRangeAvailable(moduleIdx)) {
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);
@@ -1356,7 +1397,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)
@@ -1365,6 +1406,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;
}
@@ -1510,15 +1557,35 @@ void menuModelSetup(event_t event)
}
}
+ int8_t min, max;
+ getMultiOptionValues(multi_proto, min, max);
- if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A)
- optionValue = 50 + 5 * optionValue;
-
- lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
+ 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
@@ -1608,6 +1675,14 @@ void menuModelSetup(event_t 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;
@@ -1617,42 +1692,89 @@ 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:
#endif
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM:
g_model.moduleData[moduleIdx].multi.disableTelemetry = editCheckBox(g_model.moduleData[moduleIdx].multi.disableTelemetry, MODEL_SETUP_2ND_COLUMN, y, INDENT TR_DISABLE_TELEM, attr, event);
break;
+
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_MAPPING:
#endif
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
- case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS: {
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS:
lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS);
-
- getMultiModuleStatus(moduleIdx).getStatusString(reusableBuffer.moduleSetup.msg);
+ getModuleStatusString(EXTERNAL_MODULE, reusableBuffer.moduleSetup.msg);
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, reusableBuffer.moduleSetup.msg);
break;
- }
+
#if defined(HARDWARE_INTERNAL_MODULE)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS:
#endif
- case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: {
+ case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS:
lcdDrawTextAlignedLeft(y, STR_MODULE_SYNC);
+ getModuleSyncStatusString(moduleIdx, reusableBuffer.moduleSetup.msg);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, reusableBuffer.moduleSetup.msg);
+ 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;
}
@@ -1702,7 +1824,6 @@ void menuModelSetup(event_t event)
}
break;
#endif
-
}
}
diff --git a/radio/src/gui/128x64/model_special_functions.cpp b/radio/src/gui/128x64/model_special_functions.cpp
index 2eaad8f2b..c85cdf2f2 100644
--- a/radio/src/gui/128x64/model_special_functions.cpp
+++ b/radio/src/gui/128x64/model_special_functions.cpp
@@ -338,6 +338,14 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
INCDEC_ENABLE_CHECK(isSourceAvailable);
}
}
+ else if (func == FUNC_BACKLIGHT) {
+ val_max = MIXSRC_LAST_CH;
+ drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr);
+ if (active) {
+ INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE);
+ INCDEC_ENABLE_CHECK(isSourceAvailable);
+ }
+ }
#if defined(SDCARD)
else if (func == FUNC_LOGS) {
if (val_displayed) {
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_telemetry.cpp b/radio/src/gui/128x64/view_telemetry.cpp
index 86d369377..3b6835f64 100644
--- a/radio/src/gui/128x64/view_telemetry.cpp
+++ b/radio/src/gui/128x64/view_telemetry.cpp
@@ -68,27 +68,20 @@ bool displayGaugesTelemetryScreen(TelemetryScreenData & screen)
barMin = calc100toRESX(barMin);
barMax = calc100toRESX(barMax);
}
- if (source && barMax > barMin) {
+ if (source) {
uint8_t y = barHeight+6+i*(barHeight+6);
drawSource(0, y+barHeight/2-3, source, SMLSIZE);
lcdDrawRect(BAR_LEFT, y, BAR_WIDTH+1, barHeight+2);
getvalue_t value = getValue(source);
-
uint8_t thresholdX = 0;
-
-
- uint8_t width = barCoord(value, barMin, barMax);
-
+ uint8_t width = (barMin < barMax) ? barCoord(value, barMin, barMax) : 99 - barCoord(value, barMax, barMin);
uint8_t barShade = SOLID;
-
lcdDrawFilledRect(BAR_LEFT+1, y+1, width, barHeight, barShade);
-
for (uint8_t j=24; j<99; j+=25) {
if (j>thresholdX || j>width) {
lcdDrawSolidVerticalLine(j*BAR_WIDTH/100+BAR_LEFT+1, y+1, barHeight);
}
}
-
if (thresholdX) {
lcdDrawVerticalLine(BAR_LEFT+1+thresholdX, y-2, barHeight+3, DOTTED);
lcdDrawSolidHorizontalLine(BAR_LEFT+thresholdX, y-2, 3);
diff --git a/radio/src/gui/128x64/widgets.cpp b/radio/src/gui/128x64/widgets.cpp
index 6116cc2f9..3df4e3a31 100644
--- a/radio/src/gui/128x64/widgets.cpp
+++ b/radio/src/gui/128x64/widgets.cpp
@@ -67,7 +67,11 @@ void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uin
void drawGauge(coord_t x, coord_t y, coord_t w, coord_t h, int32_t val, int32_t max)
{
+#if defined(PCBX7) || defined(PCBX9LITES) // X7 LCD doesn't like too many horizontal lines
+ h++;
+#else
lcdDrawRect(x, y, w+1, h);
+#endif
lcdDrawFilledRect(x+1, y+1, w-1, 4, SOLID, ERASE);
coord_t len = limit((uint8_t)1, uint8_t((abs(val) * w/2 + max/2) / max), uint8_t(w/2));
coord_t x0 = (val>0) ? x+w/2 : x+1+w/2-len;
diff --git a/radio/src/gui/212x64/gui.h b/radio/src/gui/212x64/gui.h
index 763c5f7c6..bb2e0d630 100644
--- a/radio/src/gui/212x64/gui.h
+++ b/radio/src/gui/212x64/gui.h
@@ -245,6 +245,8 @@ extern int8_t s_copySrcRow;
extern int8_t s_copyTgtOfs;
extern uint8_t s_currIdx;
extern uint8_t s_currIdxSubMenu;
+extern uint16_t s_currSrcRaw;
+extern uint16_t s_currScale;
extern uint8_t s_maxLines;
extern uint8_t s_copySrcIdx;
extern uint8_t s_copySrcCh;
@@ -282,9 +284,6 @@ void menuChannelsView(event_t event);
#define POS_HORZ_INIT(posVert) ((COLATTR(posVert) & NAVIGATION_LINE_BY_LINE) ? -1 : 0)
#define EDIT_MODE_INIT 0 // TODO enum
-typedef int (*FnFuncP) (int x);
-void drawFunction(FnFuncP fn, uint8_t offset=0);
-
void onSourceLongEnterPress(const char *result);
uint8_t switchToMix(uint8_t source);
diff --git a/radio/src/gui/212x64/menu_model.cpp b/radio/src/gui/212x64/menu_model.cpp
index 329220305..a2143d61e 100644
--- a/radio/src/gui/212x64/menu_model.cpp
+++ b/radio/src/gui/212x64/menu_model.cpp
@@ -69,3 +69,5 @@ void editSingleName(coord_t x, coord_t y, const char * label, char *name, uint8_
uint8_t s_currIdx;
uint8_t s_currIdxSubMenu;
+uint16_t s_currSrcRaw;
+uint16_t s_currScale;
diff --git a/radio/src/gui/212x64/model_curve_edit.cpp b/radio/src/gui/212x64/model_curve_edit.cpp
index c98af6ba1..5a79d07a2 100644
--- a/radio/src/gui/212x64/model_curve_edit.cpp
+++ b/radio/src/gui/212x64/model_curve_edit.cpp
@@ -180,6 +180,8 @@ void menuModelCurveOne(event_t event)
}
drawCurve(FW);
+ if (s_currSrcRaw != MIXSRC_NONE)
+ drawCursor(applyCurrentCurve, FW);
uint8_t posY = FH+1;
attr = (s_editMode > 0 ? INVERS|BLINK : INVERS);
diff --git a/radio/src/gui/212x64/model_display.cpp b/radio/src/gui/212x64/model_display.cpp
index 081b70f67..de7dc48a9 100644
--- a/radio/src/gui/212x64/model_display.cpp
+++ b/radio/src/gui/212x64/model_display.cpp
@@ -245,10 +245,10 @@ void menuModelDisplay(event_t event)
}
break;
case 1:
- bar.barMin = checkIncDec(event, bar.barMin, barMin, bar.barMax, EE_MODEL|NO_INCDEC_MARKS);
+ bar.barMin = checkIncDec(event, bar.barMin, barMin, barMax, EE_MODEL|NO_INCDEC_MARKS);
break;
case 2:
- bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, barMax, EE_MODEL|NO_INCDEC_MARKS);
+ bar.barMax = checkIncDec(event, bar.barMax, barMin, barMax, EE_MODEL|NO_INCDEC_MARKS);
break;
}
}
diff --git a/radio/src/gui/212x64/model_input_edit.cpp b/radio/src/gui/212x64/model_input_edit.cpp
index dc5e6085b..6882f040b 100644
--- a/radio/src/gui/212x64/model_input_edit.cpp
+++ b/radio/src/gui/212x64/model_input_edit.cpp
@@ -30,28 +30,6 @@ int expoFn(int x)
return anas[ed->chn];
}
-void drawFunction(FnFuncP fn, uint8_t offset)
-{
- lcdDrawVerticalLine(CURVE_CENTER_X-offset, CURVE_CENTER_Y-CURVE_SIDE_WIDTH, CURVE_SIDE_WIDTH*2, 0xee);
- lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee);
-
- coord_t prev_yv = (coord_t)-1;
-
- for (int xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) {
- coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX);
- if (prev_yv != (coord_t)-1) {
- if (abs((int8_t)yv-prev_yv) <= 1) {
- lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE);
- }
- else {
- uint8_t tmp = (prev_yv < yv ? 0 : 1);
- lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv);
- }
- }
- prev_yv = yv;
- }
-}
-
enum ExposFields {
EXPO_FIELD_INPUT_NAME,
EXPO_FIELD_LINE_NAME,
@@ -109,7 +87,15 @@ void menuModelExpoOne(event_t event)
case EXPO_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, STR_SOURCE);
drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr);
- if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs);
+ if (attr && menuHorizontalPosition==0)
+ ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs);
+ if (ed->srcRaw >= MIXSRC_FIRST_TELEM) {
+ drawSensorCustomValue(EXPO_ONE_2ND_COLUMN+30, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, getValue(ed->srcRaw), LEFT|(menuHorizontalPosition==1?attr:0));
+ if (attr && menuHorizontalPosition == 1) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL);
+ }
+ else if (attr) {
+ menuHorizontalPosition = 0;
+ }
break;
case EXPO_FIELD_SCALE:
@@ -160,23 +146,8 @@ void menuModelExpoOne(event_t event)
}
drawFunction(expoFn);
-
- int x512 = getValue(ed->srcRaw);
- if (ed->srcRaw >= MIXSRC_FIRST_TELEM) {
- drawSensorCustomValue(LCD_W-8, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0);
- if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale);
- }
- else {
- lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto1000(x512), RIGHT | PREC1);
- }
- x512 = limit(-1024, x512, 1024);
- int y512 = expoFn(x512);
- y512 = limit(-1024, y512, 1024);
- lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), RIGHT | PREC1);
-
- x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH);
- y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX;
-
- lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1);
- lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1);
+ // those parameters are global so that they can be reused in the curve edit screen
+ s_currSrcRaw = ed->srcRaw;
+ s_currScale = ed->scale;
+ drawCursor(expoFn);
}
diff --git a/radio/src/gui/212x64/model_mix_edit.cpp b/radio/src/gui/212x64/model_mix_edit.cpp
index 0007d91ee..b46d678a9 100644
--- a/radio/src/gui/212x64/model_mix_edit.cpp
+++ b/radio/src/gui/212x64/model_mix_edit.cpp
@@ -140,6 +140,8 @@ void menuModelMixOne(event_t event)
case MIX_FIELD_CURVE:
lcdDrawTextAlignedLeft(y, STR_CURVE);
+ s_currSrcRaw = md2->srcRaw;
+ s_currScale = 0;
editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr);
break;
diff --git a/radio/src/gui/212x64/model_select.cpp b/radio/src/gui/212x64/model_select.cpp
index 6b5282c15..0de110afc 100644
--- a/radio/src/gui/212x64/model_select.cpp
+++ b/radio/src/gui/212x64/model_select.cpp
@@ -27,6 +27,10 @@ void onModelSelectMenu(const char * result)
int8_t sub = menuVerticalPosition;
if (result == STR_SELECT_MODEL || result == STR_CREATE_MODEL) {
+ if (!g_eeGeneral.disableRssiPoweroffAlarm) {
+ if (!confirmModelChange())
+ return;
+ }
selectModel(sub);
}
else if (result == STR_COPY_MODEL) {
diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp
index 8d836e13e..ec57909de 100644
--- a/radio/src/gui/212x64/model_setup.cpp
+++ b/radio/src/gui/212x64/model_setup.cpp
@@ -66,6 +66,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_THROTTLE_REVERSED,
ITEM_MODEL_SETUP_THROTTLE_TRACE,
ITEM_MODEL_SETUP_THROTTLE_TRIM,
+ ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH,
ITEM_MODEL_SETUP_PREFLIGHT_LABEL,
ITEM_MODEL_SETUP_CHECKLIST_DISPLAY,
ITEM_MODEL_SETUP_THROTTLE_WARNING,
@@ -101,6 +102,11 @@ enum MenuModelSetupItems {
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_RXNUM_BIND_RANGE,
@@ -110,6 +116,10 @@ enum MenuModelSetupItems {
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,
@@ -247,7 +257,7 @@ 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;
else
return 0;
@@ -304,6 +314,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)
{
@@ -331,6 +345,7 @@ void menuModelSetup(event_t event)
0, // Thrxottle reverse
0, // Throttle trace source
0, // Throttle trim
+ 0, // Throttle trim switch
LABEL(PreflightCheck),
0, // Checklist
@@ -360,11 +375,13 @@ void menuModelSetup(event_t event)
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
@@ -556,6 +573,13 @@ void menuModelSetup(event_t event)
g_model.thrTrim = editCheckBox(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event);
break;
+ case ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH:
+ lcdDrawTextAlignedLeft(y, STR_TTRIM_SW);
+ if (attr)
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.thrTrimSw, NUM_TRIMS - 1);
+ drawSource(MODEL_SETUP_2ND_COLUMN, y, g_model.getThrottleStickTrimSource(), attr);
+ break;
+
case ITEM_MODEL_SETUP_PREFLIGHT_LABEL:
lcdDrawTextAlignedLeft(y, STR_PREFLIGHT);
break;
@@ -810,6 +834,11 @@ 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(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) {
if (s_editMode > 0) {
g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_NONE;
@@ -850,6 +879,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,
@@ -898,6 +932,7 @@ void menuModelSetup(event_t event)
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))
@@ -946,7 +981,6 @@ void menuModelSetup(event_t event)
}
break;
#endif
-
case ITEM_MODEL_SETUP_TRAINER_LABEL:
lcdDrawTextAlignedLeft(y, STR_TRAINER);
break;
@@ -955,7 +989,7 @@ void menuModelSetup(event_t event)
lcdDrawTextAlignedLeft(y, INDENT TR_MODE);
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerData.mode, attr);
if (attr) {
- g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX, EE_MODEL, isTrainerModeAvailable);
+ g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable);
#if defined(BLUETOOTH)
if (checkIncDec_Ret) {
bluetooth.state = BLUETOOTH_STATE_OFF;
@@ -1135,15 +1169,12 @@ void menuModelSetup(event_t event)
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 if (attr) {
- l_posHorz += 1;
- }
- if (isModuleBindRangeAvailable(moduleIdx)) {
if (attr && l_posHorz == 0) {
if (s_editMode > 0) {
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], getMaxRxNum(moduleIdx));
if (checkIncDec_Ret) {
+ if (isModuleCrossfire(moduleIdx))
+ moduleState[EXTERNAL_MODULE].counter = CRSF_FRAME_MODELID;
modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx];
}
else if (event == EVT_KEY_LONG(KEY_ENTER)) {
@@ -1156,6 +1187,11 @@ void menuModelSetup(event_t event)
}
}
}
+ }
+ else if (attr) {
+ l_posHorz += 1;
+ }
+ if (isModuleBindRangeAvailable(moduleIdx)) {
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);
@@ -1170,8 +1206,14 @@ 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 (event == EVT_KEY_BREAK(KEY_ENTER)) {
+#if defined(AFHDS3)
+ if (isModuleAFHDS3(moduleIdx)) {
+ startBindMenuAfhds3(moduleIdx);
+ continue;
+ }
+#endif
startBindMenu(moduleIdx);
continue;
}
@@ -1275,14 +1317,35 @@ void menuModelSetup(event_t event)
}
}
- if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A)
- optionValue = 50 + 5 * optionValue;
+ int8_t min, max;
+ getMultiOptionValues(multi_proto, min, max);
- lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
+ 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
@@ -1327,16 +1390,35 @@ void menuModelSetup(event_t event)
else if (isModuleMultimodule(moduleIdx)) {
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;
}
#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:
@@ -1346,25 +1428,63 @@ 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);
- getMultiModuleStatus(EXTERNAL_MODULE).getStatusString(reusableBuffer.moduleSetup.msg);
+ getModuleStatusString(EXTERNAL_MODULE, reusableBuffer.moduleSetup.msg);
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, reusableBuffer.moduleSetup.msg);
break;
- }
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS:
+ lcdDrawText(INDENT_WIDTH, y, STR_MODULE_SYNC);
+ getModuleSyncStatusString(EXTERNAL_MODULE, reusableBuffer.moduleSetup.msg);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, reusableBuffer.moduleSetup.msg);
+ 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, STR_MODULE_SYNC);
+ lcdDrawTextAlignedLeft(y, TR_MODULE_STATUS);
char statusText[64];
- getMultiSyncStatus(EXTERNAL_MODULE).getRefreshString(statusText);
+ 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);
diff --git a/radio/src/gui/212x64/model_special_functions.cpp b/radio/src/gui/212x64/model_special_functions.cpp
index 7c2d1e139..c8b74a124 100644
--- a/radio/src/gui/212x64/model_special_functions.cpp
+++ b/radio/src/gui/212x64/model_special_functions.cpp
@@ -338,14 +338,14 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
lcdDrawMMM(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, attr);
}
}
-#if defined(PCBX9E) || defined(PCBX9DP)
else if (func == FUNC_BACKLIGHT) {
- drawSlider(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, CFN_PARAM(cfn), 100, attr);
- if (active) INCDEC_SET_FLAG(eeFlags | NO_INCDEC_MARKS);
- val_min = 0;
- val_max = 100;
+ val_max = MIXSRC_LAST_CH;
+ drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr);
+ if (active) {
+ INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE);
+ INCDEC_ENABLE_CHECK(isSourceAvailable);
+ }
}
-#endif
#if defined(GVARS)
else if (func == FUNC_ADJUST_GVAR) {
switch (CFN_GVAR_MODE(cfn)) {
diff --git a/radio/src/gui/212x64/radio_diagkeys.cpp b/radio/src/gui/212x64/radio_diagkeys.cpp
index 56b8d102c..acb883513 100644
--- a/radio/src/gui/212x64/radio_diagkeys.cpp
+++ b/radio/src/gui/212x64/radio_diagkeys.cpp
@@ -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_telemetry.cpp b/radio/src/gui/212x64/view_telemetry.cpp
index fa8740667..e15fc5781 100644
--- a/radio/src/gui/212x64/view_telemetry.cpp
+++ b/radio/src/gui/212x64/view_telemetry.cpp
@@ -66,14 +66,14 @@ void displayGaugesTelemetryScreen(TelemetryScreenData & screen)
barMin = calc100toRESX(barMin);
barMax = calc100toRESX(barMax);
}
- if (source && barMax > barMin) {
+ if (source) {
int y = barHeight+6+i*(barHeight+6);
drawSource(0, y+barHeight-5, source, 0);
lcdDrawRect(BAR_LEFT, y, BAR_WIDTH+1, barHeight+2);
getvalue_t value = getValue(source);
drawSourceValue(BAR_LEFT+2+BAR_WIDTH, y+barHeight-5, source, LEFT);
uint8_t thresholdX = 0;
- int width = barCoord(value, barMin, barMax);
+ uint8_t width = (barMin < barMax) ? barCoord(value, barMin, barMax) : limit(0, 151 - barCoord(value, barMax, barMin), 151);
uint8_t barShade = SOLID;
lcdDrawFilledRect(BAR_LEFT+1, y+1, width, barHeight, barShade);
for (uint8_t j=24; j<99; j+=25) {
diff --git a/radio/src/gui/colorlcd/colors.h b/radio/src/gui/colorlcd/colors.h
index 1394c8652..4943e5f77 100644
--- a/radio/src/gui/colorlcd/colors.h
+++ b/radio/src/gui/colorlcd/colors.h
@@ -24,6 +24,7 @@
#include "libopenui_config.h"
#define WHITE RGB(0xFF, 0xFF, 0xFF)
+#define LIGHTWHITE RGB(238, 234, 238)
#define BLACK RGB(0, 0, 0)
#define YELLOW RGB(0xF0, 0xD0, 0x10)
#define BLUE RGB(0x30, 0xA0, 0xE0)
@@ -34,6 +35,10 @@
#define RED RGB(229, 32, 30)
#define DARKRED RGB(160, 0, 6)
#define GREEN RGB(25, 150, 50)
+#define LIGHTBROWN RGB(156, 109, 32)
+#define DARKBROWN RGB(106, 72, 16)
+#define BRIGHTGREEN RGB(0, 180, 60)
+#define ORANGE RGB(229, 100, 30)
#define TEXT_STATUSBAR_COLOR COLOR(TEXT_STATUSBAR_COLOR_INDEX)
#define LINE_COLOR COLOR(LINE_COLOR_INDEX)
diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h
index 0c7239107..b39f07c62 100644
--- a/radio/src/gui/colorlcd/layout.h
+++ b/radio/src/gui/colorlcd/layout.h
@@ -18,8 +18,7 @@
* GNU General Public License for more details.
*/
-#ifndef _LAYOUT_H_
-#define _LAYOUT_H_
+#pragma once
#include
#include "widgets_container.h"
@@ -125,5 +124,3 @@ Layout * loadLayout(const char * name, Layout::PersistentData * persistentData);
void loadCustomScreens();
std::list & getRegisteredLayouts();
-
-#endif // _LAYOUT_H_
diff --git a/radio/src/gui/colorlcd/model_select_old.cpp b/radio/src/gui/colorlcd/model_select_old.cpp
index 0b70b2966..0f268dfd8 100644
--- a/radio/src/gui/colorlcd/model_select_old.cpp
+++ b/radio/src/gui/colorlcd/model_select_old.cpp
@@ -242,6 +242,10 @@ void onDeleteModelConfirm(const char * result)
void onModelSelectMenu(const char * result)
{
if (result == STR_SELECT_MODEL) {
+ if (!g_eeGeneral.disableRssiPoweroffAlarm) {
+ if (!confirmModelChange())
+ return;
+ }
// we store the latest changes if any
storageFlushCurrentModel();
storageCheck(true);
@@ -259,6 +263,10 @@ void onModelSelectMenu(const char * result)
deleteMode = MODE_DELETE_MODEL;
}
else if (result == STR_CREATE_MODEL) {
+ if (!g_eeGeneral.disableRssiPoweroffAlarm) {
+ if (!confirmModelChange())
+ return;
+ }
storageCheck(true);
modelslist.addModel(currentCategory, createModel());
selectMode = MODE_SELECT_MODEL;
diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp
index 1b125dd7e..f12a6aaa7 100644
--- a/radio/src/gui/colorlcd/model_setup.cpp
+++ b/radio/src/gui/colorlcd/model_setup.cpp
@@ -711,9 +711,9 @@ class ModuleWindow : public FormGroup {
}
#endif
#if defined (PCBNV14)
- else if (isModuleFlysky(moduleIdx)) {
+ else if (isModuleAFHDS3(moduleIdx)) {
grid.nextLine();
- rfChoice = new Choice(this, grid.getFieldSlot(), STR_FLYSKY_PROTOCOLS, 0, 3,
+ rfChoice = new Choice(this, grid.getFieldSlot(), STR_AFHDS3_PROTOCOLS, 0, 3,
GET_DEFAULT(g_model.moduleData[moduleIdx].flysky.mode),
[=](int32_t newValue) -> void {
g_model.moduleData[moduleIdx].flysky.mode = newValue;
diff --git a/radio/src/gui/colorlcd/widgets/gauge.cpp b/radio/src/gui/colorlcd/widgets/gauge.cpp
index 6b3dfac5c..bbba31857 100644
--- a/radio/src/gui/colorlcd/widgets/gauge.cpp
+++ b/radio/src/gui/colorlcd/widgets/gauge.cpp
@@ -49,14 +49,16 @@ void GaugeWidget::refresh()
uint16_t color = persistentData->options[3].value.unsignedValue;
int32_t value = getValue(index);
- int32_t value_in_range = value;
- if (value < min)
- value_in_range = min;
- else if (value > max)
- value_in_range = max;
- int w = divRoundClosest(zone.w * (value_in_range - min), (max - min));
- int percent = divRoundClosest(100 * (value_in_range - min), (max - min));
+ if (min > max) {
+ SWAP(min, max);
+ value = value - min - max;
+ }
+
+ value = limit(min, value, max);
+
+ int w = divRoundClosest(zone.w * (value - min), (max - min));
+ int percent = divRoundClosest(100 * (value - min), (max - min));
// Gauge label
drawSource(zone.x, zone.y, index, FONT(XS) | FOCUS_COLOR);
diff --git a/radio/src/gui/colorlcd/widgets/modelbmp.cpp b/radio/src/gui/colorlcd/widgets/modelbmp.cpp
index 71605a858..cc2e3e591 100644
--- a/radio/src/gui/colorlcd/widgets/modelbmp.cpp
+++ b/radio/src/gui/colorlcd/widgets/modelbmp.cpp
@@ -30,7 +30,7 @@ class ModelBitmapWidget: public Widget
{
}
- virtual ~ModelBitmapWidget()
+ ~ModelBitmapWidget() override
{
delete buffer;
}
diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp
index 4bfab133e..a00c1200a 100644
--- a/radio/src/gui/colorlcd/widgets/value.cpp
+++ b/radio/src/gui/colorlcd/widgets/value.cpp
@@ -97,7 +97,7 @@ void ValueWidget::refresh()
if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER) {
TimerState & timerState = timersStates[field-MIXSRC_FIRST_TIMER];
if (timerState.val < 0) {
- lcdSetColor(ALARM_COLOR_INDEX);
+ lcdSetColor(lcdColorTable[ALARM_COLOR_INDEX]);
}
drawSource(x+NUMBERS_PADDING, y+2, field, CUSTOM_COLOR);
drawSource(x+NUMBERS_PADDING + 1, y + 3, field, BLACK);
@@ -108,7 +108,7 @@ void ValueWidget::refresh()
if (field >= MIXSRC_FIRST_TELEM) {
TelemetryItem & telemetryItem = telemetryItems[(field-MIXSRC_FIRST_TELEM)/3]; // TODO macro to convert a source to a telemetry index
if (!telemetryItem.isAvailable() || telemetryItem.isOld()) {
- lcdSetColor(ALARM_COLOR_INDEX);
+ lcdSetColor(lcdColorTable[TEXT_DISABLE_COLOR_INDEX]);
}
}
diff --git a/radio/src/gui/colorlcd/widgets_container.h b/radio/src/gui/colorlcd/widgets_container.h
index af7dda379..c29c71e6b 100644
--- a/radio/src/gui/colorlcd/widgets_container.h
+++ b/radio/src/gui/colorlcd/widgets_container.h
@@ -80,7 +80,7 @@ class WidgetsContainer: public WidgetsContainerInterface
}
}
- virtual void createWidget(unsigned int index, const WidgetFactory * factory)
+ void createWidget(unsigned int index, const WidgetFactory * factory) override
{
if (widgets) {
memset(persistentData->zones[index].widgetName, 0, sizeof(persistentData->zones[index].widgetName));
@@ -123,9 +123,9 @@ class WidgetsContainer: public WidgetsContainerInterface
return &persistentData->options[index].value;
}
- virtual unsigned int getZonesCount() const = 0;
+ unsigned int getZonesCount() const override = 0;
- virtual Zone getZone(unsigned int index) const = 0;
+ Zone getZone(unsigned int index) const override = 0;
virtual void refresh()
{
diff --git a/radio/src/gui/common/stdlcd/draw_functions.cpp b/radio/src/gui/common/stdlcd/draw_functions.cpp
index 155450fc3..bce732dae 100644
--- a/radio/src/gui/common/stdlcd/draw_functions.cpp
+++ b/radio/src/gui/common/stdlcd/draw_functions.cpp
@@ -390,6 +390,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];
@@ -434,6 +439,10 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value,
"Rx2 Lost",
"Rx1 NS",
"Rx2 NS",
+ "Rx3 FS",
+ "Rx3 LF",
+ "Rx3 Lost",
+ "Rx3 NS"
};
for (uint8_t i = 0; i < DIM(RXS_STATUS); i++) {
if (value & (1u << i)) {
diff --git a/radio/src/gui/common/stdlcd/draw_functions.h b/radio/src/gui/common/stdlcd/draw_functions.h
index 5cbc9c271..5b61dde6b 100644
--- a/radio/src/gui/common/stdlcd/draw_functions.h
+++ b/radio/src/gui/common/stdlcd/draw_functions.h
@@ -47,4 +47,9 @@ void drawSleepBitmap();
void lcdDrawMMM(coord_t x, coord_t y, LcdFlags flags=0);
void drawTrimMode(coord_t x, coord_t y, uint8_t flightMode, uint8_t idx, LcdFlags att=0);
+typedef int (*FnFuncP) (int x);
+void drawFunction(FnFuncP fn, uint8_t offset = 0);
+void drawCursor(FnFuncP fn, uint8_t offset = 0);
+void drawCurve(coord_t offset = 0);
+
#endif // _STDLCD_DRAW_FUNCTIONS_H_
diff --git a/radio/src/gui/common/stdlcd/model_curves.cpp b/radio/src/gui/common/stdlcd/model_curves.cpp
index 659e8beae..2b3c3cb07 100644
--- a/radio/src/gui/common/stdlcd/model_curves.cpp
+++ b/radio/src/gui/common/stdlcd/model_curves.cpp
@@ -62,6 +62,7 @@ void menuModelCurvesAll(event_t event)
case EVT_KEY_FIRST(KEY_ENTER):
if (CURVE_SELECTED() && !READ_ONLY()) {
s_currIdxSubMenu = sub;
+ s_currSrcRaw = MIXSRC_NONE;
pushMenu(menuModelCurveOne);
}
break;
@@ -141,9 +142,9 @@ void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlag
break;
case CURVE_REF_CUSTOM:
drawCurveName(x, y, curve.value, flags);
- if (active && menuHorizontalPosition==1) {
- if (event==EVT_KEY_LONG(KEY_ENTER) && curve.value!=0) {
- s_currIdxSubMenu = (curve.value<0 ? -curve.value-1 : curve.value-1);
+ if (active && menuHorizontalPosition == 1) {
+ if (event == EVT_KEY_LONG(KEY_ENTER) && curve.value != 0) {
+ s_currIdxSubMenu = abs(curve.value) - 1;
pushMenu(menuModelCurveOne);
}
else {
@@ -153,3 +154,48 @@ void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlag
break;
}
}
+
+void drawFunction(FnFuncP fn, uint8_t offset)
+{
+ lcdDrawVerticalLine(CURVE_CENTER_X - offset, CURVE_CENTER_Y-CURVE_SIDE_WIDTH, CURVE_SIDE_WIDTH * 2, 0xee);
+ lcdDrawHorizontalLine(CURVE_CENTER_X - CURVE_SIDE_WIDTH - offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH * 2, 0xee);
+
+ coord_t prev_yv = (coord_t) - 1;
+
+ for (int xv = -CURVE_SIDE_WIDTH; xv <= CURVE_SIDE_WIDTH; xv++) {
+ coord_t yv = (LCD_H - 1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H - 1) / RESX);
+ if (prev_yv != (coord_t) - 1) {
+ if (abs((int8_t)yv-prev_yv) <= 1) {
+ lcdDrawPoint(CURVE_CENTER_X + xv - offset - 1, prev_yv, FORCE);
+ }
+ else {
+ uint8_t tmp = (prev_yv < yv ? 0 : 1);
+ lcdDrawSolidVerticalLine(CURVE_CENTER_X + xv - offset - 1, yv + tmp, prev_yv - yv);
+ }
+ }
+ prev_yv = yv;
+ }
+}
+
+void drawCursor(FnFuncP fn, uint8_t offset)
+{
+ int x512 = getValue(s_currSrcRaw);
+ if (s_currSrcRaw >= MIXSRC_FIRST_TELEM) {
+ if (s_currScale > 0)
+ x512 = (x512 * 1024) / convertTelemValue(s_currSrcRaw - MIXSRC_FIRST_TELEM + 1, s_currScale);
+ drawSensorCustomValue(LCD_W - FW - offset, 6 * FH, (s_currSrcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0);
+ }
+ else {
+ lcdDrawNumber(LCD_W - FW - offset, 6*FH, calcRESXto1000(x512), RIGHT | PREC1);
+ }
+ x512 = limit(-1024, x512, 1024);
+ int y512 = fn(x512);
+ y512 = limit(-1024, y512, 1024);
+ lcdDrawNumber(CURVE_CENTER_X - FWNUM - offset, 1*FH, calcRESXto1000(y512), RIGHT | PREC1);
+
+ x512 = CURVE_CENTER_X + x512/(RESX / CURVE_SIDE_WIDTH);
+ y512 = (LCD_H - 1) - ((y512 + RESX) / 2) * (LCD_H - 1) / RESX;
+
+ lcdDrawSolidVerticalLine(x512 - offset, y512-3, 3 * 2 + 1);
+ lcdDrawSolidHorizontalLine(x512 - 3 - offset, y512, 3 * 2 + 1);
+}
diff --git a/radio/src/gui/common/stdlcd/model_receiver_options.cpp b/radio/src/gui/common/stdlcd/model_receiver_options.cpp
index 6ce66ee29..de3547b75 100644
--- a/radio/src/gui/common/stdlcd/model_receiver_options.cpp
+++ b/radio/src/gui/common/stdlcd/model_receiver_options.cpp
@@ -48,6 +48,7 @@ enum {
ITEM_RECEIVER_SETTINGS_TELEMETRY,
ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW,
ITEM_RECEIVER_SETTINGS_SPORT_FPORT,
+ ITEM_RECEIVER_SETTINGS_FPORT2,
ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1,
ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED2,
ITEM_RECEIVER_SETTINGS_PINMAP_FIRST
@@ -82,6 +83,7 @@ void menuModelReceiverOptions(event_t event)
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),
+ IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_FPORT2, 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),
0 // channels ...
@@ -171,6 +173,13 @@ void menuModelReceiverOptions(event_t event)
}
break;
+ case ITEM_RECEIVER_SETTINGS_FPORT2:
+ reusableBuffer.hardwareAndSettings.receiverSettings.fport2 = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.fport2, RECEIVER_OPTIONS_2ND_COLUMN, y, "F.Port2", attr, event);
+ if (attr && checkIncDec_Ret) {
+ reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY;
+ }
+ break;
+
case ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1:
lcdDrawText(LCD_W/2, y+1, STR_MORE_OPTIONS_AVAILABLE, SMLSIZE|CENTERED);
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/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp
index ddeccb348..caedaa074 100644
--- a/radio/src/gui/common/stdlcd/radio_hardware.cpp
+++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp
@@ -162,7 +162,7 @@ enum {
ITEM_RADIO_HARDWARE_CAPACITY_CALIB,
#endif
-#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000
+#if (defined(CROSSFIRE) || defined(GHOST)) && SPORT_MAX_BAUDRATE < 400000
ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE,
#endif
@@ -278,7 +278,7 @@ void onHardwareAntennaSwitchConfirm(const char * result)
#define TX_CAPACITY_MEASUREMENT_ROWS
#endif
-#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000
+#if (defined(CROSSFIRE) || defined(GHOST)) && SPORT_MAX_BAUDRATE < 400000
#define MAX_BAUD_ROWS 0,
#else
#define MAX_BAUD_ROWS
@@ -292,7 +292,7 @@ void onHardwareAntennaSwitchConfirm(const char * result)
#if LCD_W >= 212
#define HW_SETTINGS_COLUMN1 12*FW
- #define HW_SETTINGS_COLUMN2 (HW_SETTINGS_COLUMN1 + 6*FW)
+ #define HW_SETTINGS_COLUMN2 (20*FW - 3)
#else
#define HW_SETTINGS_COLUMN1 30
#define HW_SETTINGS_COLUMN2 (HW_SETTINGS_COLUMN1 + 5*FW)
@@ -544,7 +544,7 @@ void menuRadioHardware(event_t event)
break;
#endif
-#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000
+#if (defined(CROSSFIRE) || defined(GHOST)) && SPORT_MAX_BAUDRATE < 400000
case ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE:
lcdDrawTextAlignedLeft(y, STR_MAXBAUDRATE);
lcdDrawNumber(HW_SETTINGS_COLUMN2, y, CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate], attr|LEFT);
@@ -569,7 +569,7 @@ void menuRadioHardware(event_t event)
lcdDrawTextAlignedLeft(y, STR_BLUETOOTH);
lcdDrawTextAtIndex(HW_SETTINGS_COLUMN2, y, STR_BLUETOOTH_MODES, g_eeGeneral.bluetoothMode, attr);
if (attr) {
- g_eeGeneral.bluetoothMode = checkIncDecGen(event, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_TRAINER);
+ g_eeGeneral.bluetoothMode = checkIncDecGen(event, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_MAX);
}
break;
diff --git a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp
index 80c2f7207..b07eee74d 100644
--- a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp
+++ b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp
@@ -251,10 +251,16 @@ void onSdManagerMenu(const char * result)
}
#endif
#if defined(PXX2)
- else if (result == STR_FLASH_RECEIVER_OTA_BY_INTERNAL || result == STR_FLASH_RECEIVER_OTA_BY_EXTERNAL) {
+ else if (result == STR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA || result == STR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA) {
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;
+ reusableBuffer.sdManager.otaUpdateInformation.module = (result == STR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA ? INTERNAL_MODULE : EXTERNAL_MODULE);
+ moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].startBind(&reusableBuffer.sdManager.otaUpdateInformation, onUpdateStateChanged);
+ }
+ else if (result == STR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA || result == STR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA) {
+ memclear(&reusableBuffer.sdManager.otaUpdateInformation, sizeof(OtaUpdateInformation));
+ getSelectionFullPath(reusableBuffer.sdManager.otaUpdateInformation.filename);
+ reusableBuffer.sdManager.otaUpdateInformation.module = (result == STR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA ? INTERNAL_MODULE : EXTERNAL_MODULE);
moduleState[reusableBuffer.sdManager.otaUpdateInformation.module].startBind(&reusableBuffer.sdManager.otaUpdateInformation, onUpdateStateChanged);
}
#endif
@@ -408,14 +414,18 @@ void menuRadioSdManager(event_t _event)
else if (!READ_ONLY() && !strcasecmp(ext, SPORT_FIRMWARE_EXT)) {
if (HAS_SPORT_UPDATE_CONNECTOR())
POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_DEVICE);
+#if defined(INTERNAL_MODULE_PXX1) || defined(INTERNAL_MODULE_PXX2)
POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE);
+#endif
POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MODULE);
}
else if (!READ_ONLY() && !strcasecmp(ext, FRSKY_FIRMWARE_EXT)) {
FrSkyFirmwareInformation information;
if (readFrSkyFirmwareInformation(line, information) == nullptr) {
+#if defined(INTERNAL_MODULE_PXX1) || defined(INTERNAL_MODULE_PXX2)
if (information.productFamily == FIRMWARE_FAMILY_INTERNAL_MODULE)
POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE);
+#endif
if (information.productFamily == FIRMWARE_FAMILY_EXTERNAL_MODULE)
POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MODULE);
if (information.productFamily == FIRMWARE_FAMILY_RECEIVER || information.productFamily == FIRMWARE_FAMILY_SENSOR) {
@@ -427,9 +437,13 @@ void menuRadioSdManager(event_t _event)
#if defined(PXX2)
if (information.productFamily == FIRMWARE_FAMILY_RECEIVER) {
if (isReceiverOTAEnabledFromModule(INTERNAL_MODULE, information.productId))
- POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA_BY_INTERNAL);
+ POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_BY_INTERNAL_MODULE_OTA);
if (isReceiverOTAEnabledFromModule(EXTERNAL_MODULE, information.productId))
- POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA_BY_EXTERNAL);
+ POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_BY_EXTERNAL_MODULE_OTA);
+ }
+ if (information.productFamily == FIRMWARE_FAMILY_FLIGHT_CONTROLLER) {
+ POPUP_MENU_ADD_ITEM(STR_FLASH_FLIGHT_CONTROLLER_BY_INTERNAL_MODULE_OTA);
+ POPUP_MENU_ADD_ITEM(STR_FLASH_FLIGHT_CONTROLLER_BY_EXTERNAL_MODULE_OTA);
}
#endif
#if defined(BLUETOOTH)
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/gui_common.cpp b/radio/src/gui/gui_common.cpp
index fbc3073b4..76af36527 100644
--- a/radio/src/gui/gui_common.cpp
+++ b/radio/src/gui/gui_common.cpp
@@ -387,6 +387,32 @@ 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;
+#if defined(RADIO_TX16S)
+ else
+ return (g_model.trainerData.mode != TRAINER_MODE_MASTER_BATTERY_COMPARTMENT || g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER);
+#endif
+#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;
+#if defined(RADIO_TX16S)
+ else
+ return (g_model.trainerData.mode != TRAINER_MODE_MASTER_BATTERY_COMPARTMENT || g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER);
+#endif
+#endif
+ return true;
+}
+
bool isSwitchAvailableInLogicalSwitches(int swtch)
{
return isSwitchAvailable(swtch, LogicalSwitchesContext);
@@ -552,6 +578,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:
@@ -566,17 +593,20 @@ bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType)
}
}
+bool areModulesConflicting(int intModuleType, int extModuleType)
+{
+ if (intModuleType == MODULE_TYPE_ISRM_PXX2)
+ return (extModuleType == MODULE_TYPE_GHOST);
+
+ return false;
+}
+
#if defined(HARDWARE_INTERNAL_MODULE)
bool isInternalModuleAvailable(int moduleType)
{
if (moduleType == MODULE_TYPE_NONE)
return true;
-#if defined(PCBNV14)
- if (moduleType == MODULE_TYPE_FLYSKY)
- return true;
-#endif
-
#if defined(INTERNAL_MODULE_MULTI)
if (moduleType == MODULE_TYPE_MULTIMODULE)
return true;
@@ -592,7 +622,7 @@ bool isInternalModuleAvailable(int moduleType)
if (moduleType == MODULE_TYPE_ISRM_PXX2) {
#if defined(PXX2) && defined(INTERNAL_MODULE_PXX2)
- return true;
+ return !areModulesConflicting(moduleType, g_model.moduleData[EXTERNAL_MODULE].type);
#endif
}
@@ -612,12 +642,6 @@ bool isInternalModuleAvailable(int moduleType)
bool isExternalModuleAvailable(int moduleType)
{
- if (moduleType == MODULE_TYPE_FLYSKY)
- return false; // doesn't exist for now
-
- if (moduleType == MODULE_TYPE_R9M_LITE_PRO_PXX1)
- return false;
-
#if !defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
if (isModuleTypeR9MLite(moduleType) || moduleType == MODULE_TYPE_XJT_LITE_PXX2)
return false;
@@ -653,6 +677,11 @@ bool isExternalModuleAvailable(int moduleType)
return false;
#endif
+#if !defined(GHOST)
+ if (moduleType == MODULE_TYPE_GHOST)
+ return false;
+#endif
+
#if !defined(DSM2)
if (moduleType == MODULE_TYPE_DSM2)
return false;
@@ -669,6 +698,9 @@ bool isExternalModuleAvailable(int moduleType)
#endif
#if defined(HARDWARE_INTERNAL_MODULE)
+ if (areModulesConflicting(g_model.moduleData[INTERNAL_MODULE].type, moduleType))
+ return false;
+
if (isTrainerUsingModuleBay() || (isModuleUsingSport(EXTERNAL_MODULE, moduleType) && isModuleUsingSport(INTERNAL_MODULE, g_model.moduleData[INTERNAL_MODULE].type)))
return false;
#endif
@@ -678,6 +710,11 @@ bool isExternalModuleAvailable(int moduleType)
return false;
#endif
+#if !defined(AFHDS3)
+ if (moduleType == MODULE_TYPE_AFHDS3)
+ return false;
+#endif
+
return true;
}
@@ -688,6 +725,11 @@ bool isRfProtocolAvailable(int protocol)
return false;
}
#endif
+#if defined(GHOST)
+ if (protocol != MODULE_SUBTYPE_PXX1_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_GHOST) {
+ return false;
+ }
+#endif
#if !defined(MODULE_PROTOCOL_D8)
if (protocol == MODULE_SUBTYPE_PXX1_ACCST_D8) {
return false;
@@ -717,12 +759,22 @@ bool isTelemetryProtocolAvailable(int protocol)
return false;
}
+ if ( protocol== PROTOCOL_TELEMETRY_GHOST) {
+ return false;
+ }
+
#if !defined(MULTIMODULE)
if (protocol == PROTOCOL_TELEMETRY_SPEKTRUM || protocol == PROTOCOL_TELEMETRY_FLYSKY_IBUS || protocol == PROTOCOL_TELEMETRY_MULTIMODULE) {
return false;
}
#endif
+#if !defined(AFHDS3)
+ if (protocol == PROTOCOL_TELEMETRY_AFHDS3) {
+ return false;
+ }
+#endif
+
#if defined(PCBHORUS)
if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
return false;
@@ -746,7 +798,10 @@ bool isTrainerModeAvailable(int mode)
}
#endif
-#if defined(PCBTARANIS) && !defined(TRAINER_BATTERY_COMPARTMENT)
+#if defined(RADIO_TX16S)
+ if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
+ return (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER || g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER);
+#elif defined(PCBTARANIS) && !defined(TRAINER_BATTERY_COMPARTMENT)
if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
return false;
#elif defined(PCBTARANIS)
@@ -790,6 +845,25 @@ bool modelHasNotes()
return false;
}
+bool confirmModelChange()
+{
+ if (TELEMETRY_STREAMING()) {
+ RAISE_ALERT(STR_MODEL, STR_MODEL_STILL_POWERED, STR_PRESS_ENTER_TO_CONFIRM, AU_MODEL_STILL_POWERED);
+ while (TELEMETRY_STREAMING()) {
+ RTOS_WAIT_MS(20);
+ if (readKeys() == (1 << KEY_ENTER)) {
+ killEvents(KEY_ENTER);
+ return true;
+ }
+ else if (readKeys() == (1 << KEY_EXIT)) {
+ killEvents(KEY_EXIT);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
int getFirstAvailable(int min, int max, IsValueAvailable isValueAvailable)
{
int retval = 0;
@@ -869,8 +943,8 @@ 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[] = "\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";
@@ -899,6 +973,7 @@ 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";
@@ -908,7 +983,7 @@ const char STR_SUBTYPE_HOTT[] = "\007""Sync\0 ""No_Sync";
const char STR_SUBTYPE_FX816[] = "\003""P38";
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";
+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";
@@ -924,7 +999,8 @@ 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[] = {
@@ -933,7 +1009,7 @@ const mm_protocol_definition multi_protocols[] = {
{MODULE_SUBTYPE_MULTI_HUBSAN, 2, false, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
{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},
@@ -966,6 +1042,7 @@ const mm_protocol_definition multi_protocols[] = {
{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},
@@ -976,7 +1053,7 @@ const mm_protocol_definition multi_protocols[] = {
{MODULE_SUBTYPE_MULTI_FX816, 0, false, false, STR_SUBTYPE_FX816, nullptr},
{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, 3, false, false, STR_SUBTYPE_XN297DUMP, STR_MULTI_RFCHAN},
+ {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},
diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h
index 493d08339..c1968960c 100644
--- a/radio/src/gui/gui_common.h
+++ b/radio/src/gui/gui_common.h
@@ -85,6 +85,8 @@ bool isSourceAvailableInCustomSwitches(int source);
bool isSourceAvailableInResetSpecialFunction(int index);
bool isSourceAvailableInGlobalResetSpecialFunction(int index);
bool isSwitchAvailable(int swtch, SwitchContext context);
+bool isAux1ModeAvailable(int mode);
+bool isAux2ModeAvailable(int mode);
bool isSwitchAvailableInLogicalSwitches(int swtch);
bool isSwitchAvailableInCustomFunctions(int swtch);
bool isSwitchAvailableInMixes(int swtch);
@@ -114,6 +116,8 @@ bool isRssiSensorAvailable(int sensor);
bool modelHasNotes();
+bool confirmModelChange();
+
#if defined(COLORLCD)
bool isSwitch2POSWarningStateAvailable(int state);
#endif
@@ -128,6 +132,7 @@ bool isSwitch2POSWarningStateAvailable(int state);
swsrc_t checkIncDecMovedSwitch(swsrc_t val);
+// TODO move this to stdlcd/draw_functions.h ?
void drawCurveRef(coord_t x, coord_t y, CurveRef & curve, LcdFlags flags=0);
void drawDate(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags flags=0);
void drawTelemScreenDate(coord_t x, coord_t y, source_t sensor, LcdFlags flags=0);
@@ -139,21 +144,22 @@ void drawSourceValue(coord_t x, coord_t y, source_t channel, LcdFlags flags=0);
int convertMultiToOtx(int type);
-void drawCurve(coord_t offset=0);
-
// model_setup Defines that are used in all uis in the same way
#define IF_INTERNAL_MODULE_ON(x) (IS_INTERNAL_MODULE_ENABLED() ? (uint8_t)(x) : HIDDEN_ROW)
#define IF_MODULE_ON(moduleIndex, x) (IS_MODULE_ENABLED(moduleIndex) ? (uint8_t)(x) : HIDDEN_ROW)
inline uint8_t MODULE_BIND_ROWS(int moduleIdx)
{
+ if (isModuleCrossfire(moduleIdx))
+ return 0;
+
if (isModuleMultimodule(moduleIdx)) {
- if (IS_RX_MULTI(moduleIdx))
- return 1;
- else
- return 2;
+ if (IS_RX_MULTI(moduleIdx))
+ return 1;
+ else
+ return 2;
}
- else if (isModuleXJTD8(moduleIdx) || isModuleSBUS(moduleIdx)) {
+ else if (isModuleXJTD8(moduleIdx) || isModuleSBUS(moduleIdx) || isModuleAFHDS3(moduleIdx)) {
return 1;
}
else if (isModulePPM(moduleIdx) || isModulePXX1(moduleIdx) || isModulePXX2(moduleIdx) || isModuleDSM2(moduleIdx)) {
@@ -177,7 +183,7 @@ inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx)
else
return 0;
}
- else if (isModuleDSM2(moduleIdx) || isModuleCrossfire(moduleIdx) || isModuleSBUS(moduleIdx)) {
+ else if (isModuleDSM2(moduleIdx) || isModuleCrossfire(moduleIdx) || isModuleGhost(moduleIdx) || isModuleSBUS(moduleIdx)) {
return 0;
}
else {
@@ -282,9 +288,10 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx)
#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)) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (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)
@@ -292,11 +299,28 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t 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) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : 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))
+
+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/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp
index 43dac1678..fdb230f47 100644
--- a/radio/src/io/frsky_firmware_update.cpp
+++ b/radio/src/io/frsky_firmware_update.cpp
@@ -161,7 +161,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)) {
@@ -488,7 +488,7 @@ const char * FrskyDeviceFirmwareUpdate::flashFirmware(const char * filename, Pro
uint8_t extPwr = IS_EXTERNAL_MODULE_ON();
EXTERNAL_MODULE_OFF();
-#if HAS_SPORT_UPDATE_CONNECTOR()
+#if defined(SPORT_UPDATE_PWR_GPIO)
uint8_t spuPwr = IS_SPORT_UPDATE_POWER_ON();
SPORT_UPDATE_POWER_OFF();
#endif
@@ -534,7 +534,7 @@ const char * FrskyDeviceFirmwareUpdate::flashFirmware(const char * filename, Pro
setupPulsesExternalModule();
}
-#if HAS_SPORT_UPDATE_CONNECTOR()
+#if defined(SPORT_UPDATE_PWR_GPIO)
if (spuPwr) {
SPORT_UPDATE_POWER_ON();
}
@@ -761,7 +761,7 @@ const char * FrskyChipFirmwareUpdate::flashFirmware(const char * filename, Progr
uint8_t extPwr = IS_EXTERNAL_MODULE_ON();
EXTERNAL_MODULE_OFF();
-#if HAS_SPORT_UPDATE_CONNECTOR()
+#if defined(SPORT_UPDATE_PWR_GPIO)
uint8_t spuPwr = IS_SPORT_UPDATE_POWER_ON();
SPORT_UPDATE_POWER_OFF();
#endif
@@ -802,7 +802,7 @@ const char * FrskyChipFirmwareUpdate::flashFirmware(const char * filename, Progr
setupPulsesExternalModule();
}
-#if HAS_SPORT_UPDATE_CONNECTOR()
+#if defined(SPORT_UPDATE_PWR_GPIO)
if (spuPwr) {
SPORT_UPDATE_POWER_ON();
}
diff --git a/radio/src/io/frsky_firmware_update.h b/radio/src/io/frsky_firmware_update.h
index 16b99e224..a6750d2cf 100644
--- a/radio/src/io/frsky_firmware_update.h
+++ b/radio/src/io/frsky_firmware_update.h
@@ -35,6 +35,7 @@ enum FrskyFirmwareProductFamily {
FIRMWARE_FAMILY_SENSOR,
FIRMWARE_FAMILY_BLUETOOTH_CHIP,
FIRMWARE_FAMILY_POWER_MANAGEMENT_UNIT,
+ FIRMWARE_FAMILY_FLIGHT_CONTROLLER,
};
enum FrskyFirmwareModuleProductId {
diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp
index ee89017d0..21dc934e1 100644
--- a/radio/src/io/multi_firmware_update.cpp
+++ b/radio/src/io/multi_firmware_update.cpp
@@ -534,7 +534,7 @@ bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, ProgressHan
uint8_t extPwr = IS_EXTERNAL_MODULE_ON();
EXTERNAL_MODULE_OFF();
-#if HAS_SPORT_UPDATE_CONNECTOR()
+#if defined(SPORT_UPDATE_PWR_GPIO)
uint8_t spuPwr = IS_SPORT_UPDATE_POWER_ON();
SPORT_UPDATE_POWER_OFF();
#endif
@@ -583,7 +583,7 @@ bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, ProgressHan
setupPulsesExternalModule();
}
-#if HAS_SPORT_UPDATE_CONNECTOR()
+#if defined(SPORT_UPDATE_PWR_GPIO)
if (spuPwr) {
SPORT_UPDATE_POWER_ON();
}
diff --git a/radio/src/io/multi_firmware_update.h b/radio/src/io/multi_firmware_update.h
index 100b9012d..00dd5588f 100644
--- a/radio/src/io/multi_firmware_update.h
+++ b/radio/src/io/multi_firmware_update.h
@@ -76,7 +76,7 @@ class MultiFirmwareInformation {
bool isMultiExternalFirmware() const
{
- return (telemetryInversion == true && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY);
+ return ((telemetryInversion == true || boardType == FIRMWARE_MULTI_STM ) && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY);
}
const char * readMultiFirmwareInformation(const char * filename);
diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp
index a2556453e..b5fba0dc6 100644
--- a/radio/src/lua/api_general.cpp
+++ b/radio/src/lua/api_general.cpp
@@ -375,6 +375,26 @@ bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags)
return false; // not found
}
+/*luadoc
+@function getRotEncSpeed()
+
+Return rotary encoder current speed
+
+@retval number in list: ROTENC_LOWSPEED, ROTENC_MIDSPEED, ROTENC_HIGHSPEED
+ return 0 on radio without rotary encoder
+
+@status current Introduced in 2.3.10
+*/
+static int luaGetRotEncSpeed(lua_State * L)
+{
+#if defined(ROTARY_ENCODER_NAVIGATION)
+ lua_pushunsigned(L, rotencSpeed);
+#else
+ lua_pushunsigned(L, 0);
+#endif
+ return 1;
+}
+
/*luadoc
@function sportTelemetryPop()
@@ -847,7 +867,7 @@ Return the internal GPS position or nil if no valid hardware found
static int luaGetTxGPS(lua_State * L)
{
#if defined(INTERNAL_GPS)
- lua_createtable(L, 0, 7);
+ lua_createtable(L, 0, 8);
lua_pushtablenumber(L, "lat", gpsData.latitude * 0.000001);
lua_pushtablenumber(L, "lon", gpsData.longitude * 0.000001);
lua_pushtableinteger(L, "numsat", gpsData.numSat);
@@ -1680,6 +1700,7 @@ const luaL_Reg opentxLib[] = {
{ "getVersion", luaGetVersion },
{ "getGeneralSettings", luaGetGeneralSettings },
{ "getGlobalTimer", luaGetGlobalTimer },
+ { "getRotEncSpeed", luaGetRotEncSpeed },
{ "getValue", luaGetValue },
{ "getRAS", luaGetRAS },
{ "getTxGPS", luaGetTxGPS },
@@ -1742,6 +1763,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 },
@@ -1813,6 +1835,9 @@ const luaR_value_entry opentxConstants[] = {
{ "EVT_VIRTUAL_NEXT", EVT_ROTARY_RIGHT },
{ "EVT_VIRTUAL_DEC", EVT_ROTARY_LEFT },
{ "EVT_VIRTUAL_INC", EVT_ROTARY_RIGHT },
+ { "ROTENC_LOWSPEED", ROTENC_LOWSPEED },
+ { "ROTENC_MIDSPEED", ROTENC_MIDSPEED },
+ { "ROTENC_HIGHSPEED", ROTENC_HIGHSPEED },
#elif defined(PCBX9D) || defined(PCBX9DP) // key reverted between field nav and value change
{ "EVT_VIRTUAL_PREV", EVT_KEY_FIRST(KEY_PLUS) },
{ "EVT_VIRTUAL_PREV_REPT", EVT_KEY_REPT(KEY_PLUS) },
@@ -1980,6 +2005,9 @@ const luaR_value_entry opentxConstants[] = {
{"UNIT_MILLILITERS", UNIT_MILLILITERS },
{"UNIT_FLOZ", UNIT_FLOZ },
{"UNIT_MILLILITERS_PER_MINUTE", UNIT_MILLILITERS_PER_MINUTE },
+ {"UNIT_HERTZ", UNIT_HERTZ },
+ {"UNIT_MS", UNIT_MS },
+ {"UNIT_US", UNIT_US },
{"UNIT_HOURS", UNIT_HOURS },
{"UNIT_MINUTES", UNIT_MINUTES },
{"UNIT_SECONDS", UNIT_SECONDS },
diff --git a/radio/src/lua/api_model.cpp b/radio/src/lua/api_model.cpp
index d2d5f767a..9e9aa310c 100644
--- a/radio/src/lua/api_model.cpp
+++ b/radio/src/lua/api_model.cpp
@@ -363,6 +363,136 @@ static int luaModelGetInputsCount(lua_State *L)
return 1;
}
+/*luadoc
+@function model.deleteFlightModes()
+
+Clear all flightModes
+
+@status current Introduced in 2.3.10
+*/
+static int luaModelDeleteFlightModes(lua_State *L)
+{
+ memset(g_model.flightModeData, 0, sizeof(g_model.flightModeData));
+ return 0;
+}
+
+/*luadoc
+@function model.getFlightMode(index)
+
+@param index (unsigned number) flight mode number (use 0 for FM0)
+
+Return input data for given input and line number
+
+@retval nil requested input or line does not exist
+
+@retval table input data:
+ * `name` (string) input line name
+ * `switch` (number) input switch index
+ * `fadeIn` (number) fade in value (in 0.1s)
+ * `fadeOut` (number) fade out value (in 0.1s)
+ * `trimsValues` (table) table of trim values:
+ * `key` is trim number (zero based)
+ * `value` is trim value
+ * `trimsModes` (table) table of trim mode:
+ * `key` is trim number (zero based)
+ * `value` is trim mode
+
+@status current Introduced in 2.3.10
+*/
+static int luaModelGetFlightMode(lua_State * L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < MAX_FLIGHT_MODES) {
+ FlightModeData * fm = flightModeAddress(idx);
+ lua_newtable(L);
+ lua_pushtablezstring(L, "name", fm->name);
+ lua_pushtableinteger(L, "switch", fm->swtch);
+ lua_pushtableinteger(L, "fadeIn", fm->fadeIn);
+ lua_pushtableinteger(L, "fadeOut", fm->fadeOut);
+ lua_pushstring(L, "trimsValues");
+ lua_newtable(L);
+ for (uint8_t i = 0; i < NUM_TRIMS; i++) {
+ lua_pushinteger(L, i);
+ lua_pushinteger(L, fm->trim[i].value);
+ lua_settable(L, -3);
+ }
+ lua_settable(L, -3);
+ lua_pushstring(L, "trimsModes");
+ lua_newtable(L);
+ for (uint8_t i = 0; i < NUM_TRIMS; i++) {
+ lua_pushinteger(L, i);
+ lua_pushinteger(L, fm->trim[i].mode);
+ lua_settable(L, -3);
+ }
+ lua_settable(L, -3);
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/*luadoc
+@function model.setFlightMode(index, params)
+
+Set Flight mode parameters
+
+@param index (unsigned number) flight mode number (use 0 for FM0)
+
+@param params see model.getFlightMode return format for table format.
+
+@status current Introduced in 2.3.10
+*/
+static int luaModelSetFlightMode(lua_State * L)
+{
+ unsigned int flightMode = luaL_checkunsigned(L, 1);
+
+ if (flightMode >= MAX_FLIGHT_MODES) {
+ lua_pushinteger(L, 2);
+ return 1;
+ }
+ FlightModeData * fm = flightModeAddress(flightMode);
+ luaL_checktype(L, -1, LUA_TTABLE);
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ luaL_checktype(L, -2, LUA_TSTRING); // key is string
+ const char * key = luaL_checkstring(L, -2);
+ if (!strcmp(key, "name")) {
+ const char * name = luaL_checkstring(L, -1);
+ str2zchar(fm->name, name, sizeof(fm->name));
+ }
+ else if (!strcmp(key, "switch")) {
+ fm->swtch = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "fadeIn")) {
+ fm->fadeIn = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "fadeOut")) {
+ fm->fadeOut = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "trimsValues")) {
+ luaL_checktype(L, -1, LUA_TTABLE);
+ uint8_t idx = 0;
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1), idx++) {
+ int16_t val = luaL_checkinteger(L, -1);
+ if (idx < NUM_TRIMS)
+ fm->trim[idx].value = (val & 0x3FF);
+ }
+ }
+ else if (!strcmp(key, "trimsModes")) {
+ luaL_checktype(L, -1, LUA_TTABLE);
+ uint8_t idx = 0;
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1), idx++) {
+ uint16_t val = luaL_checkinteger(L, -1);
+ if (idx < NUM_TRIMS)
+ fm->trim[idx].mode = (val & 0x1F);
+ }
+ }
+ }
+ storageDirty(EE_MODEL);
+ lua_pushinteger(L, 0);
+ return 1;
+}
+
/*luadoc
@function model.getInput(input, line)
@@ -376,6 +506,7 @@ Return input data for given input and line number
@retval table input data:
* `name` (string) input line name
+ * `inputName` (string) input input name
* `source` (number) input source index
* `weight` (number) input weight
* `offset` (number) input offset
@@ -383,8 +514,9 @@ Return input data for given input and line number
* `curveType` (number) curve type (function, expo, custom curve)
* `curveValue` (number) curve index
* `carryTrim` (boolean) input trims applied
+ * 'flightModes' (table) table of enabled flightModes {0,2,7} means that the input is enabled for FM0, FM2 and FM7
-@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3
+@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3, flightModes, inputName added 2.3.10
*/
static int luaModelGetInput(lua_State *L)
{
@@ -396,6 +528,7 @@ static int luaModelGetInput(lua_State *L)
ExpoData * expo = expoAddress(first+idx);
lua_newtable(L);
lua_pushtablezstring(L, "name", expo->name);
+ lua_pushtablezstring(L, "inputName", g_model.inputNames[chn]);
lua_pushtableinteger(L, "source", expo->srcRaw);
lua_pushtableinteger(L, "weight", expo->weight);
lua_pushtableinteger(L, "offset", expo->offset);
@@ -403,6 +536,16 @@ static int luaModelGetInput(lua_State *L)
lua_pushtableinteger(L, "curveType", expo->curve.type);
lua_pushtableinteger(L, "curveValue", expo->curve.value);
lua_pushtableinteger(L, "carryTrim", expo->carryTrim);
+ lua_pushstring(L, "flightModes");
+ lua_newtable(L);
+ for (int i = 0, cnt = 0; i < MAX_FLIGHT_MODES; i++) {
+ if (!(expo->flightModes & (1 << i))) {
+ lua_pushinteger(L, cnt++);
+ lua_pushinteger(L, i);
+ lua_settable(L, -3);
+ }
+ }
+ lua_settable(L, -3);
}
else {
lua_pushnil(L);
@@ -421,7 +564,7 @@ Insert an Input at specified line
@param value (table) input data, see model.getInput()
-@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3
+@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3, inputName added 2.3.10
*/
static int luaModelInsertInput(lua_State *L)
{
@@ -444,6 +587,10 @@ static int luaModelInsertInput(lua_State *L)
const char * name = luaL_checkstring(L, -1);
str2zchar(expo->name, name, sizeof(expo->name));
}
+ else if (!strcmp(key, "inputName")) {
+ const char * name = luaL_checkstring(L, -1);
+ str2zchar(g_model.inputNames[chn], name, LEN_INPUT_NAME);
+ }
else if (!strcmp(key, "source")) {
expo->srcRaw = luaL_checkinteger(L, -1);
}
@@ -465,6 +612,16 @@ static int luaModelInsertInput(lua_State *L)
else if (!strcmp(key, "carryTrim")) {
expo->carryTrim = lua_toboolean(L, -1);
}
+ else if (!strcmp(key, "flightModes")) {
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int flighModes = 0x1FF;
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ uint16_t val = luaL_checkinteger(L, -1);
+ if (val < MAX_FLIGHT_MODES)
+ flighModes &= ~(1 << val);
+ }
+ expo->flightModes = flighModes;
+ }
}
}
@@ -596,8 +753,9 @@ Get configuration for specified Mix
* `delayDown` (number) delay down
* `speedUp` (number) speed up
* `speedDown` (number) speed down
+ * 'flightModes' (table) table of enabled flightModes {0,2,7} means that the input is enabled for FM0, FM2 and FM7
-@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13
+@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13, flightModes added 2.3.10
*/
static int luaModelGetMix(lua_State *L)
{
@@ -623,6 +781,16 @@ static int luaModelGetMix(lua_State *L)
lua_pushtableinteger(L, "delayDown", mix->delayDown);
lua_pushtableinteger(L, "speedUp", mix->speedUp);
lua_pushtableinteger(L, "speedDown", mix->speedDown);
+ lua_pushstring(L, "flightModes");
+ lua_newtable(L);
+ for (int i = 0, cnt = 0; i < MAX_FLIGHT_MODES; i++) {
+ if (!(mix->flightModes & (1 << i))) {
+ lua_pushinteger(L, cnt++);
+ lua_pushinteger(L, i);
+ lua_settable(L, -3);
+ }
+ }
+ lua_settable(L, -3);
}
else {
lua_pushnil(L);
@@ -641,7 +809,7 @@ Insert a mixer line into Channel
@param value (table) see model.getMix() for table format
-@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13
+@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13, flightModes added 2.3.10
*/
static int luaModelInsertMix(lua_State *L)
{
@@ -706,6 +874,16 @@ static int luaModelInsertMix(lua_State *L)
else if (!strcmp(key, "speedDown")) {
mix->speedDown = luaL_checkinteger(L, -1);
}
+ else if (!strcmp(key, "flightModes")) {
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int flighModes = 0x1FF;
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ uint16_t val = luaL_checkinteger(L, -1);
+ if (val < MAX_FLIGHT_MODES)
+ flighModes &= ~(1 << val);
+ }
+ mix->flightModes = flighModes;
+ }
}
}
@@ -997,7 +1175,7 @@ static int luaModelSetCurve(lua_State *L)
bool isX = !strcmp(key, "x");
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- int idx = luaL_checkinteger(L, -2)-1;
+ int idx = luaL_checkinteger(L, -2) - 1;
if (idx < 0 || idx > MAX_POINTS_PER_CURVE) {
lua_pushinteger(L, 4);
return 1;
@@ -1418,6 +1596,9 @@ const luaL_Reg modelLib[] = {
{ "getTimer", luaModelGetTimer },
{ "setTimer", luaModelSetTimer },
{ "resetTimer", luaModelResetTimer },
+ { "deleteFlightModes", luaModelDeleteFlightModes },
+ { "getFlightMode", luaModelGetFlightMode },
+ { "setFlightMode", luaModelSetFlightMode },
{ "getInputsCount", luaModelGetInputsCount },
{ "getInput", luaModelGetInput },
{ "insertInput", luaModelInsertInput },
diff --git a/radio/src/lua/widgets.cpp b/radio/src/lua/widgets.cpp
index 271a6ffaf..75260b068 100644
--- a/radio/src/lua/widgets.cpp
+++ b/radio/src/lua/widgets.cpp
@@ -253,23 +253,23 @@ class LuaWidget: public Widget
LuaWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData, int widgetData):
Widget(factory, zone, persistentData),
widgetData(widgetData),
- errorMessage(0)
+ errorMessage(nullptr)
{
}
- virtual ~LuaWidget()
+ ~LuaWidget() override
{
luaL_unref(lsWidgets, LUA_REGISTRYINDEX, widgetData);
- if (errorMessage) free(errorMessage);
+ free(errorMessage);
}
- virtual void update();
+ void update() override;
void refresh() override;
- virtual void background();
+ void background() override;
- virtual const char * getErrorMessage() const;
+ const char * getErrorMessage() const override;
protected:
int widgetData;
@@ -300,7 +300,7 @@ class LuaWidgetFactory: public WidgetFactory
{
}
- virtual Widget * create(const Zone & zone, Widget::PersistentData * persistentData, bool init=true) const
+ Widget * create(const Zone & zone, Widget::PersistentData * persistentData, bool init=true) const override
{
if (lsWidgets == 0) return 0;
if (init) {
diff --git a/radio/src/main.cpp b/radio/src/main.cpp
index d17c4d0a7..4f634c340 100644
--- a/radio/src/main.cpp
+++ b/radio/src/main.cpp
@@ -26,6 +26,8 @@
uint8_t currentSpeakerVolume = 255;
uint8_t requiredSpeakerVolume = 255;
+uint8_t currentBacklightBright = 255;
+uint8_t requiredBacklightBright = 255;
uint8_t mainRequestFlags = 0;
#if defined(LIBOPENUI)
diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp
index 61be1aeef..8b67e9dc8 100644
--- a/radio/src/mixer.cpp
+++ b/radio/src/mixer.cpp
@@ -524,13 +524,13 @@ int getStickTrimValue(int stick, int stickValue)
return 0;
int trim = trims[stick];
- if (stick == THR_STICK) {
- if (g_model.thrTrim) {
- int trimMin = g_model.extendedTrims ? 2*TRIM_EXTENDED_MIN : 2*TRIM_MIN;
- trim = ((g_model.throttleReversed ? (trim+trimMin) : (trim-trimMin)) * (RESX-stickValue)) >> (RESX_SHIFT+1);
- }
- if (g_model.throttleReversed) {
+ uint8_t thrTrimSw = g_model.getThrottleStickTrimSource() - MIXSRC_FIRST_TRIM;
+ if (stick == thrTrimSw) {
+ if (g_model.throttleReversed)
trim = -trim;
+ if (g_model.thrTrim) {
+ trim = (g_model.extendedTrims) ? 2*TRIM_EXTENDED_MAX + trim : 2*TRIM_MAX + trim;
+ trim = trim * (1024 - stickValue) / (2*RESX);
}
}
return trim;
@@ -956,6 +956,7 @@ void evalMixes(uint8_t tick10ms)
// must be done before limits because of the applyLimit function: it checks for safety switches which would be not initialized otherwise
if (tick10ms) {
requiredSpeakerVolume = g_eeGeneral.speakerVolume + VOLUME_LEVEL_DEF;
+ requiredBacklightBright = g_eeGeneral.backlightBright;
if (!g_model.noGlobalFunctions) {
evalFunctions(g_eeGeneral.customFn, globalFunctionsContext);
diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h
index 7fe8492f1..6733fc17f 100644
--- a/radio/src/myeeprom.h
+++ b/radio/src/myeeprom.h
@@ -38,7 +38,8 @@
#else
#define IS_TRAINER_EXTERNAL_MODULE() false
#endif
-#define IS_TRAINER_AUX_SERIAL() (g_eeGeneral.auxSerialMode==UART_MODE_SBUS_TRAINER)
+
+#define IS_TRAINER_AUX_SERIAL() (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER)
#define IS_PLAY_FUNC(func) ((func) >= FUNC_PLAY_SOUND && func <= FUNC_PLAY_VALUE)
@@ -54,7 +55,7 @@
#define IS_HAPTIC_FUNC(func) (0)
#endif
-#define HAS_ENABLE_PARAM(func) ((func) < FUNC_FIRST_WITHOUT_ENABLE)
+#define HAS_ENABLE_PARAM(func) ((func) < FUNC_FIRST_WITHOUT_ENABLE || (func == FUNC_BACKLIGHT))
#define HAS_REPEAT_PARAM(func) (IS_PLAY_FUNC(func) || IS_HAPTIC_FUNC(func))
#define CFN_EMPTY(p) (!(p)->swtch)
diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp
index 603a5cd27..1928eee0f 100644
--- a/radio/src/opentx.cpp
+++ b/radio/src/opentx.cpp
@@ -27,6 +27,10 @@
#include "view_main.h"
#endif
+#if defined(PCBSKY9X)
+#include "audio_driver.h"
+#endif
+
RadioData g_eeGeneral;
ModelData g_model;
@@ -276,7 +280,9 @@ void generalDefault()
#if defined(PCBHORUS)
g_eeGeneral.blOffBright = 20;
-#else
+#endif
+
+#if defined(LCD_CONTRAST_DEFAULT)
g_eeGeneral.contrast = LCD_CONTRAST_DEFAULT;
#endif
@@ -694,12 +700,19 @@ void checkBacklight()
}
}
- bool backlightOn = (g_eeGeneral.backlightMode == e_backlight_mode_on || (g_eeGeneral.backlightMode != e_backlight_mode_off && lightOffCounter) || isFunctionActive(FUNCTION_BACKLIGHT));
- if (flashCounter) backlightOn = !backlightOn;
- if (backlightOn)
+ bool backlightOn = (g_eeGeneral.backlightMode == e_backlight_mode_on || (g_eeGeneral.backlightMode != e_backlight_mode_off && lightOffCounter));
+
+ if (flashCounter) {
+ backlightOn = !backlightOn;
+ }
+
+ if (backlightOn) {
+ currentBacklightBright = requiredBacklightBright;
BACKLIGHT_ENABLE();
- else
+ }
+ else {
BACKLIGHT_DISABLE();
+ }
}
}
@@ -1690,28 +1703,40 @@ void opentxResume()
void instantTrim()
{
- int16_t anas_0[MAX_INPUTS];
+ int16_t anas_0[MAX_INPUTS];
evalInputs(e_perout_mode_notrainer | e_perout_mode_nosticks);
memcpy(anas_0, anas, sizeof(anas_0));
evalInputs(e_perout_mode_notrainer);
- for (uint8_t stick=0; sticksrcRaw-MIXSRC_Rud == stick) {
- delta = anas[ed->chn] - anas_0[ed->chn];
- break;
+ uint8_t trimFlightMode = getTrimFlightMode(mixerCurrentFlightMode, stick);
+ for (uint8_t i = 0; i < MAX_EXPOS; i++) {
+ ExpoData * expo = expoAddress(i);
+ if (!EXPO_VALID(expo))
+ break; // end of list
+ if (stick == expo->srcRaw - MIXSRC_FIRST_STICK) {
+ if (expo->carryTrim < 0) {
+ // only default trims will be taken into account
+ addTrim = false;
+ break;
+ }
+ auto newDelta = anas[expo->chn] - anas_0[expo->chn];
+ if (addTrim && delta != newDelta) {
+ // avoid 2 different delta values
+ addTrim = false;
+ break;
+ }
+ addTrim = true;
+ delta = newDelta;
}
}
- if (abs(delta) >= INSTANT_TRIM_MARGIN) {
+ if (addTrim && abs(delta) >= INSTANT_TRIM_MARGIN) {
int16_t trim = limit(TRIM_EXTENDED_MIN, (delta + trims[stick]) / 2, TRIM_EXTENDED_MAX);
- setTrimValue(trim_phase, stick, trim);
+ setTrimValue(trimFlightMode, stick, trim);
}
}
}
@@ -2005,6 +2030,7 @@ void opentxInit()
#endif
currentSpeakerVolume = requiredSpeakerVolume = g_eeGeneral.speakerVolume + VOLUME_LEVEL_DEF;
+ currentBacklightBright = requiredBacklightBright = g_eeGeneral.backlightBright;
#if !defined(SOFTWARE_VOLUME)
setScaledVolume(currentSpeakerVolume);
#endif
@@ -2086,7 +2112,7 @@ int main()
// important to disable it before commencing with system initialisation (or
// we could put a bunch more WDG_RESET()s in. But I don't like that approach
// during boot up.)
-#if defined(PCBTARANIS)
+#if defined(LCD_CONTRAST_DEFAULT)
g_eeGeneral.contrast = LCD_CONTRAST_DEFAULT;
#endif
@@ -2127,6 +2153,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 b6d870889..cf77902ab 100644
--- a/radio/src/opentx.h
+++ b/radio/src/opentx.h
@@ -501,6 +501,7 @@ void doMixerCalculations();
void scheduleNextMixerCalculation(uint8_t module, uint32_t period_ms);
void checkTrims();
+extern uint8_t currentBacklightBright;
void perMain();
void per10ms();
@@ -550,7 +551,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_FAMILY_T16)
+#elif defined(RADIO_FAMILY_T16) && !defined(RADIO_T18)
#define ROTARY_ENCODER_GRANULARITY (1)
#else
#define ROTARY_ENCODER_GRANULARITY (2)
@@ -685,6 +686,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[];
@@ -821,7 +823,6 @@ enum FunctionsActive {
FUNCTION_TRAINER_CHANNELS = FUNCTION_TRAINER_STICK1 + NUM_STICKS,
FUNCTION_INSTANT_TRIM,
FUNCTION_VARIO,
- FUNCTION_BACKLIGHT,
#if defined(SDCARD)
FUNCTION_LOGS,
#endif
diff --git a/radio/src/options.h b/radio/src/options.h
index e8bf634c1..f2b3c8369 100644
--- a/radio/src/options.h
+++ b/radio/src/options.h
@@ -22,25 +22,31 @@
#ifndef OPENTX_OPTIONS_H
#define OPENTX_OPTIONS_H
-static const char * options[] = {
+static const char * const options[] = {
#if defined(AUTOUPDATE)
"autoupdate",
#endif
#if defined(CROSSFIRE)
"crossfire",
#endif
+#if defined(GHOST)
+ "ghost",
+#endif
#if !defined(MODULE_PROTOCOL_D8)
"eu",
#endif
#if defined(FAI)
- "faimode",
+ "FAImode",
#endif
#if defined(FAI_CHOICE)
- "faichoice",
+ "FAIchoice",
#endif
#if defined(MODULE_PROTOCOL_FLEX)
"flexr9m",
#endif
+#if defined(AFHDS3)
+ "afhds3",
+#endif
#if !defined(GVARS)
"nogvars",
#endif
diff --git a/radio/src/pulses/afhds2.h b/radio/src/pulses/afhds2.h
index baa1caa06..e6bab681b 100644
--- a/radio/src/pulses/afhds2.h
+++ b/radio/src/pulses/afhds2.h
@@ -21,6 +21,8 @@
#ifndef PULSES_AFHDS2_H_
#define PULSES_AFHDS2_H_
+
+#include
#include
#include