1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-19 14:25:11 +03:00

Merge with latest 2.3

This commit is contained in:
Bertrand Songis 2020-10-07 21:01:45 +02:00
commit 42a3198568
No known key found for this signature in database
GPG key ID: F189F79290FEC50F
376 changed files with 10566 additions and 8633 deletions

View file

@ -6,7 +6,7 @@ set(VERSION_REVISION "0")
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX}) set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR}) set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX}) 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}) set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)

View file

@ -8,6 +8,7 @@ Romolo Manfredini (romoloman)
Martin Hotař (mhotar) Martin Hotař (mhotar)
Maxim (Max) Paperno (mpaperno) Maxim (Max) Paperno (mpaperno)
Arne Schwabe (schwabe) Arne Schwabe (schwabe)
Daniel Gorbea (dgatf)
[Translators] [Translators]
[fr] Sebastien Charpentier (LapinFou) [fr] Sebastien Charpentier (LapinFou)
@ -31,6 +32,7 @@ Michael Byrne
<a href="https://www.flysky-cn.com/home">FlySky (monthly)</a> <a href="https://www.flysky-cn.com/home">FlySky (monthly)</a>
<a href="https://www.jumper-rc.com">JumperRC (monthly)</a> <a href="https://www.jumper-rc.com">JumperRC (monthly)</a>
<a href="https://www.radiomasterrc.com">RadioMaster (monthly)</a> <a href="https://www.radiomasterrc.com">RadioMaster (monthly)</a>
<a href="http://www.happymodel.cn">HappyModel (monthly)</a>
<a href="https://alofthobbies.com">Aloft Hobbies</a> <a href="https://alofthobbies.com">Aloft Hobbies</a>
<a href="https://jonathan.it">Jonathan Modellismo</a> <a href="https://jonathan.it">Jonathan Modellismo</a>
<a href="http://wstech.de">WsTech</a> <a href="http://wstech.de">WsTech</a>
@ -1761,3 +1763,182 @@ Paul Pearson
Stuart Olson Stuart Olson
Pierre Connan Pierre Connan
Henk Eeltink 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

View file

@ -56,7 +56,7 @@ else()
set(FOX_LIBRARIES ${FOX_LIBRARY}) set(FOX_LIBRARIES ${FOX_LIBRARY})
endif() endif()
find_package_handle_standard_args(FOX find_package_handle_standard_args(Fox
DEFAULT_MSG DEFAULT_MSG
FOX_INCLUDE_DIR FOX_INCLUDE_DIR
FOX_LIBRARY FOX_LIBRARY

View file

@ -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 # On OS X we copy dfu-util to the application bundle. This the path from which we copy
# the binary (default homebrew path) # the binary (default homebrew path)
set(DFU_UTIL_PATH "/usr/local/bin/dfu-util") 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 option(ALLOW_NIGHTLY_BUILDS "Allow nightly builds download / update") # Disabled by default
if(ALLOW_NIGHTLY_BUILDS) if(ALLOW_NIGHTLY_BUILDS)
@ -239,7 +237,6 @@ set(companion_SRCS
flasheepromdialog.cpp flasheepromdialog.cpp
printdialog.cpp printdialog.cpp
modelprinter.cpp modelprinter.cpp
fusesdialog.cpp
logsdialog.cpp logsdialog.cpp
downloaddialog.cpp downloaddialog.cpp
splashlibrarydialog.cpp splashlibrarydialog.cpp
@ -259,7 +256,6 @@ set(companion_MOC_HDRS
burnconfigdialog.h burnconfigdialog.h
comparedialog.h comparedialog.h
printdialog.h printdialog.h
fusesdialog.h
logsdialog.h logsdialog.h
creditsdialog.h creditsdialog.h
releasenotesdialog.h releasenotesdialog.h
@ -291,7 +287,6 @@ set(companion_MOC_HDRS
set(companion_UIS set(companion_UIS
mdichild.ui mdichild.ui
comparedialog.ui comparedialog.ui
fusesdialog.ui
logsdialog.ui logsdialog.ui
apppreferencesdialog.ui apppreferencesdialog.ui
fwpreferencesdialog.ui fwpreferencesdialog.ui
@ -356,6 +351,8 @@ elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T16)
set(FLAVOUR t16) set(FLAVOUR t16)
elseif(PCB STREQUAL X10 AND PCBREV STREQUAL TX16S) elseif(PCB STREQUAL X10 AND PCBREV STREQUAL TX16S)
set(FLAVOUR tx16s) set(FLAVOUR tx16s)
elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T18)
set(FLAVOUR t18)
else() else()
string(TOLOWER ${PCB} FLAVOUR) string(TOLOWER ${PCB} FLAVOUR)
endif() endif()
@ -406,7 +403,7 @@ elseif(WIN32)
install(TARGETS ${SIMULATOR_NAME} DESTINATION ${INSTALL_DESTINATION}) install(TARGETS ${SIMULATOR_NAME} DESTINATION ${INSTALL_DESTINATION})
install(FILES ${simulator_plugins} DESTINATION "${INSTALL_DESTINATION}") install(FILES ${simulator_plugins} DESTINATION "${INSTALL_DESTINATION}")
# supporting utilities # 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}) foreach(tmpfile ${INSTALL_TEMP_FILES})
install(FILES "${COMPANION_SRC_DIRECTORY}/../targets/windows/${tmpfile}" DESTINATION ${INSTALL_DESTINATION}) install(FILES "${COMPANION_SRC_DIRECTORY}/../targets/windows/${tmpfile}" DESTINATION ${INSTALL_DESTINATION})
endforeach() endforeach()
@ -552,14 +549,11 @@ IF(APPLE)
set(${COMPANION_SOURCES} ${COMPANION_SOURCES} ${PROJECT_SOURCE_DIR}/images/${MACOSX_BUNDLE_ICON_FILE}) set(${COMPANION_SOURCES} ${COMPANION_SOURCES} ${PROJECT_SOURCE_DIR}/images/${MACOSX_BUNDLE_ICON_FILE})
install(FILES ${MAC_ICON_FILE} DESTINATION ${companion_res_dir} COMPONENT Runtime) 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(DFU_UTIL_ABSOLUTE_PATH ${DFU_UTIL_PATH} REALPATH)
get_filename_component(AVRDUDE_ABSOLUTE_PATH ${AVRDUDE_PATH} REALPATH) install(PROGRAMS ${DFU_UTIL_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime)
get_filename_component(AVRDUDECONF_ABSOLUTE_PATH ${AVRDUDE_CONF} REALPATH)
install(PROGRAMS ${DFU_UTIL_ABSOLUTE_PATH} ${AVRDUDE_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime)
install(FILES ${AVRDUDECONF_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime)
set(bundle_tools_path "\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/dfu-util;\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/avrdude") set(bundle_tools_path "\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/dfu-util;")
# Include depencies (adding frameworks, fixing the embbeded libraries) # Include depencies (adding frameworks, fixing the embbeded libraries)

View file

@ -36,61 +36,23 @@ burnConfigDialog::burnConfigDialog(QWidget *parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowIcon(CompanionIcon("configure.png")); setWindowIcon(CompanionIcon("configure.png"));
ui->avrdude_programmer->model()->sort(0);
getSettings(); getSettings();
populateProgrammers();
Board::Type board = getCurrentBoard(); Board::Type board = getCurrentBoard();
if (IS_STM32(board)) { if (IS_STM32(board)) {
setWindowTitle(tr("DFU-UTIL Configuration")); 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_sb1->hide();
ui->label_sb3->hide(); ui->label_sb3->hide();
ui->samba_location->hide(); ui->samba_location->hide();
ui->samba_port->hide(); ui->samba_port->hide();
ui->sb_browse->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 { else {
setWindowTitle(tr("AVRDUDE Configuration")); setWindowTitle(tr("SAM-BA Configuration"));
ui->label_sb1->hide();
ui->label_sb3->hide();
ui->samba_location->hide();
ui->samba_port->hide();
ui->sb_browse->hide();
ui->label_dfu1->hide(); ui->label_dfu1->hide();
ui->label_dfu2->hide();
ui->dfu_location->hide(); ui->dfu_location->hide();
ui->dfu_browse->hide(); ui->dfu_browse->hide();
} }
ui->label_av3->hide();
ui->avrdude_mcu->hide();
ui->label_sb2->hide(); ui->label_sb2->hide();
ui->arm_mcu->hide(); ui->arm_mcu->hide();
ui->label_dfu2->hide(); ui->label_dfu2->hide();
@ -105,46 +67,26 @@ burnConfigDialog::~burnConfigDialog()
delete ui; 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() void burnConfigDialog::getSettings()
{ {
avrLoc = g.avrdudeLocation();
sambaLoc = g.sambaLocation(); sambaLoc = g.sambaLocation();
dfuLoc = g.dfuLocation(); dfuLoc = g.dfuLocation();
#if defined WIN32 || !defined __GNUC__ #if defined WIN32 || !defined __GNUC__
if ( avrLoc.isEmpty())
avrLoc = QFileInfo("avrdude.exe").absoluteFilePath();
if ( sambaLoc.isEmpty()) if ( sambaLoc.isEmpty())
sambaLoc = QFileInfo("sam-ba.exe").absoluteFilePath(); sambaLoc = QFileInfo("sam-ba.exe").absoluteFilePath();
if ( dfuLoc.isEmpty()) if ( dfuLoc.isEmpty())
dfuLoc = QFileInfo("dfu-util.exe").absoluteFilePath(); dfuLoc = QFileInfo("dfu-util.exe").absoluteFilePath();
#elif defined __APPLE__ #elif defined __APPLE__
if ( avrLoc.isEmpty())
avrLoc = QFileInfo(QApplication::applicationDirPath() + "/../Resources/avrdude").absoluteFilePath();
if ( sambaLoc.isEmpty()) if ( sambaLoc.isEmpty())
sambaLoc = "/usr/local/bin/sam-ba"; sambaLoc = "/usr/local/bin/sam-ba";
if ( dfuLoc.isEmpty()) if ( dfuLoc.isEmpty())
dfuLoc = QFileInfo(QApplication::applicationDirPath() + "/../Resources/dfu-util").absoluteFilePath(); dfuLoc = QFileInfo(QApplication::applicationDirPath() + "/../Resources/dfu-util").absoluteFilePath();
#elif defined __FreeBSD__ #elif defined __FreeBSD__
if (avrLoc.isEmpty())
avrLoc = "/usr/local/bin/avrdude";
if (dfuLoc.isEmpty()) if (dfuLoc.isEmpty())
dfuLoc = "/usr/local/bin/dfu-util"; dfuLoc = "/usr/local/bin/dfu-util";
#else #else
if ( avrLoc.isEmpty())
avrLoc = "/usr/bin/avrdude";
if ( sambaLoc.isEmpty()) if ( sambaLoc.isEmpty())
sambaLoc = "/usr/bin/sam-ba"; sambaLoc = "/usr/bin/sam-ba";
if ( dfuLoc.isEmpty()) if ( dfuLoc.isEmpty())
@ -152,45 +94,22 @@ void burnConfigDialog::getSettings()
#endif #endif
dfuArgs = g.dfuArguments().split(" ", QString::SkipEmptyParts); dfuArgs = g.dfuArguments().split(" ", QString::SkipEmptyParts);
avrArgs = g.avrArguments().split(" ", QString::SkipEmptyParts);
avrProgrammer = g.programmer();
avrPort = g.avrPort();
avrMCU = g.mcu();
armMCU = g.armMcu(); armMCU = g.armMcu();
sambaPort = g.sambaPort(); sambaPort = g.sambaPort();
ui->avrdude_location->setText(getAVRDUDE());
ui->avrArgs->setText(avrArgs.join(" "));
ui->samba_location->setText(getSAMBA()); ui->samba_location->setText(getSAMBA());
ui->samba_port->setText(getSambaPort()); ui->samba_port->setText(getSambaPort());
ui->dfu_location->setText(getDFU()); ui->dfu_location->setText(getDFU());
ui->dfuArgs->setText(getDFUArgs().join(" ")); 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()); 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); if(idx4>=0) ui->arm_mcu->setCurrentIndex(idx4);
QFile file; QFile file;
if (file.exists(avrLoc)) {
ui->pushButton_3->setEnabled(true);
} else {
ui->pushButton_3->setDisabled(true);
}
} }
void burnConfigDialog::putSettings() void burnConfigDialog::putSettings()
{ {
g.avrdudeLocation( avrLoc );
g.programmer( avrProgrammer);
g.mcu( avrMCU );
g.avrPort( avrPort );
g.avrArguments( avrArgs.join(" ") );
g.sambaLocation( sambaLoc ); g.sambaLocation( sambaLoc );
g.sambaPort( sambaPort ); g.sambaPort( sambaPort );
g.armMcu( armMCU ); g.armMcu( armMCU );
@ -198,73 +117,6 @@ void burnConfigDialog::putSettings()
g.dfuArguments( dfuArgs.join(" ") ); 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() void burnConfigDialog::on_samba_location_editingFinished()
{ {
sambaLoc = ui->samba_location->text(); sambaLoc = ui->samba_location->text();
@ -280,17 +132,6 @@ void burnConfigDialog::on_arm_mcu_currentIndexChanged(QString )
armMCU = ui->arm_mcu->currentText(); 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() void burnConfigDialog::on_sb_browse_clicked()
{ {
QString fileName = QFileDialog::getOpenFileName(this, tr("Select Location"),ui->samba_location->text()); 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); 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) void burnConfigDialog::on_advCtrChkB_toggled(bool checked)
{ {
Board::Type board = getCurrentBoard(); Board::Type board = getCurrentBoard();
@ -351,31 +171,20 @@ void burnConfigDialog::on_advCtrChkB_toggled(bool checked)
ui->label_dfu2->show(); ui->label_dfu2->show();
ui->dfuArgs->show(); ui->dfuArgs->show();
} }
else if (IS_SKY9X(board)) { else {
ui->label_sb2->show(); ui->label_sb2->show();
ui->arm_mcu->show(); ui->arm_mcu->show();
} }
else {
ui->label_av3->show();
ui->avrdude_mcu->show();
QMessageBox::warning(this, CPN_STR_APP_NAME,
tr("<b><u>WARNING!</u></b><br>Normally CPU type is automatically selected according to the chosen firmware.<br>If you change the CPU type the resulting eeprom could be inconsistent."),
QMessageBox::Ok);
}
} }
else { else {
if (IS_STM32(board)) { if (IS_STM32(board)) {
ui->label_dfu2->hide(); ui->label_dfu2->hide();
ui->dfuArgs->hide(); ui->dfuArgs->hide();
} }
else if (IS_SKY9X(board)) { else {
ui->label_sb2->hide(); ui->label_sb2->hide();
ui->arm_mcu->hide(); ui->arm_mcu->hide();
} }
else {
ui->label_av3->hide();
ui->avrdude_mcu->hide();
}
} }
QTimer::singleShot(0, this, SLOT(shrink())); QTimer::singleShot(0, this, SLOT(shrink()));
} }

View file

@ -39,45 +39,25 @@ public:
burnConfigDialog(QWidget *parent = 0); burnConfigDialog(QWidget *parent = 0);
~burnConfigDialog(); ~burnConfigDialog();
QString getAVRDUDE() {return avrLoc;}
QString getSAMBA() {return sambaLoc;} QString getSAMBA() {return sambaLoc;}
QString getDFU() {return dfuLoc;} QString getDFU() {return dfuLoc;}
QStringList getAvrdudeArgs();
QStringList getDFUArgs() {return dfuArgs;} QStringList getDFUArgs() {return dfuArgs;}
QString getProgrammer() {return avrProgrammer;}
QString getMCU() {return avrMCU;}
QString getArmMCU() {return armMCU;} QString getArmMCU() {return armMCU;}
QString getPort() {return avrPort;}
QString getSambaPort() {return sambaPort;} QString getSambaPort() {return sambaPort;}
void listAvrdudeProgrammers();
private: private:
Ui::burnConfigDialog *ui; Ui::burnConfigDialog *ui;
void populateProgrammers(); void populateProgrammers();
QString avrLoc;
QString sambaLoc; QString sambaLoc;
QString dfuLoc; QString dfuLoc;
QStringList avrArgs;
QString avrProgrammer;
QString avrMCU;
QString armMCU; QString armMCU;
QString avrPort;
QString sambaPort; QString sambaPort;
QStringList dfuArgs; QStringList dfuArgs;
private slots: private slots:
void shrink(); 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_location_editingFinished();
void on_samba_port_editingFinished(); void on_samba_port_editingFinished();
void on_arm_mcu_currentIndexChanged(QString ); void on_arm_mcu_currentIndexChanged(QString );

View file

@ -45,615 +45,7 @@
</item> </item>
<item row="0" column="0"> <item row="0" column="0">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="9" column="2"> <item row="1" column="2">
<widget class="QLineEdit" name="dfu_location">
<property name="toolTip">
<string>Location of sam-ba executable</string>
</property>
<property name="whatsThis">
<string>The location of the AVRDUDE executable.</string>
</property>
<property name="text">
<string notr="true">dfu-util</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_dfu1">
<property name="text">
<string>DFU-Util Location</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="avrdude_location">
<property name="toolTip">
<string>Location of AVRDUDE executable</string>
</property>
<property name="whatsThis">
<string>The location of the AVRDUDE executable.</string>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="0" column="4" rowspan="2">
<widget class="QPushButton" name="pushButton">
<property name="whatsThis">
<string>Use this button to browse and look for the AVRDUDE executable file.</string>
</property>
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_av2">
<property name="text">
<string>Programmer</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="avrdude_programmer">
<property name="whatsThis">
<string>Programmer used for communicating with the controller.
Please consult the programmer's documentation and the AVRDUDE documentation to select the appropriate programmer.</string>
</property>
<property name="insertPolicy">
<enum>QComboBox::InsertAlphabetically</enum>
</property>
<item>
<property name="text">
<string notr="true">c2n232i</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dasa3</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dasa</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">siprog</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">ponyser</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">89isp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">frank-stk200</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">blaster</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">ere-isp-avr</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">atisp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dapa</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">xil</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">futurlec</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">abcmini</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">picoweb</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">sp12</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">alf</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">bascom</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dt006</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">pony-stk200</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">stk200</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">bsd</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">pavr</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dragon_pdi</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dragon_dw</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dragon_hvsp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dragon_pp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dragon_isp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dragon_jtag</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtag2pdi</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtag2avr32</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtagmkII_avr32</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtag2dw</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtag2isp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtag2</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtag2fast</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtag2slow</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtagmkII</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtag1slow</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtag1</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">jtagmkI</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">avr911</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">avr109</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">butterfly</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">usbtiny</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">usbasp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">avr910</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">stk600hvsp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">stk600pp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">stk600</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">stk500hvsp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">stk500pp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">stk500v2</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">mib510</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">stk500v1</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">stk500</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">buspirate</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">avrisp2</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">avrispmkII</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">avrispv2</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">avrisp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">arduino</string>
</property>
</item>
</widget>
</item>
<item row="2" column="4">
<widget class="QPushButton" name="pushButton_3">
<property name="whatsThis">
<string>List all available programmers.</string>
</property>
<property name="text">
<string>List Available</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLineEdit" name="avrArgs">
<property name="toolTip">
<string>Extra arguments that will be passed to AVRDUDE on every call</string>
</property>
<property name="whatsThis">
<string>Extra arguments used in AVRDUDE.
This can be used for providing extra information to AVRDUDE.
Please only use this if you know what you are doing. There are no error checks and you could cripple your controller.</string>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_av5">
<property name="text">
<string>Extra Arguments</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QPushButton" name="pushButton_4">
<property name="whatsThis">
<string>Show AVRDUDE help</string>
</property>
<property name="text">
<string>Show Help</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QComboBox" name="avrdude_port">
<property name="whatsThis">
<string>Communication port to the programmer.
</string>
</property>
<item>
<property name="text">
<string notr="true"/>
</property>
</item>
<item>
<property name="text">
<string notr="true">usb</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com1</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com2</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com3</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com4</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com5</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com6</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com7</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com8</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com9</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com10</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com11</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com12</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com13</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com14</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">com15</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">lpt1</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">lpt2</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">lpt3</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">lpt4</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">avrdoper</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">/dev/ttyUSB0</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">/dev/ttyUSB1</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_av4">
<property name="text">
<string>Port</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_av1">
<property name="text">
<string>AVRDUDE Location</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_av3">
<property name="text">
<string>MCU</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QComboBox" name="avrdude_mcu">
<property name="toolTip">
<string>CPU of your TX</string>
</property>
<property name="whatsThis">
<string>CPU present on your 9x radio
Should be m64 for stock radios
m2560 for v4.1 boards</string>
</property>
<property name="insertPolicy">
<enum>QComboBox::InsertAlphabetically</enum>
</property>
<item>
<property name="text">
<string notr="true">m64</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">m128</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">m2560</string>
</property>
</item>
</widget>
</item>
<item row="7" column="2">
<widget class="QComboBox" name="arm_mcu"> <widget class="QComboBox" name="arm_mcu">
<property name="toolTip"> <property name="toolTip">
<string>CPU of your TX</string> <string>CPU of your TX</string>
@ -678,7 +70,27 @@ m2560 for v4.1 boards</string>
</item> </item>
</widget> </widget>
</item> </item>
<item row="6" column="0"> <item row="3" column="2">
<widget class="QLineEdit" name="dfu_location">
<property name="toolTip">
<string>Location of sam-ba executable</string>
</property>
<property name="whatsThis">
<string>The location of the AVRDUDE executable.</string>
</property>
<property name="text">
<string notr="true">dfu-util</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_dfu1">
<property name="text">
<string>DFU-Util Location</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_sb1"> <widget class="QLabel" name="label_sb1">
<property name="text"> <property name="text">
<string>SAM-BA Location</string> <string>SAM-BA Location</string>
@ -688,7 +100,7 @@ m2560 for v4.1 boards</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="2"> <item row="0" column="2">
<widget class="QLineEdit" name="samba_location"> <widget class="QLineEdit" name="samba_location">
<property name="toolTip"> <property name="toolTip">
<string>Location of sam-ba executable</string> <string>Location of sam-ba executable</string>
@ -701,7 +113,7 @@ m2560 for v4.1 boards</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_sb2"> <widget class="QLabel" name="label_sb2">
<property name="text"> <property name="text">
<string>ARM MCU</string> <string>ARM MCU</string>
@ -711,7 +123,7 @@ m2560 for v4.1 boards</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_sb3"> <widget class="QLabel" name="label_sb3">
<property name="text"> <property name="text">
<string>Port</string> <string>Port</string>
@ -721,7 +133,7 @@ m2560 for v4.1 boards</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="2"> <item row="2" column="2">
<widget class="QLineEdit" name="samba_port"> <widget class="QLineEdit" name="samba_port">
<property name="toolTip"> <property name="toolTip">
<string>sam-ba serial port</string> <string>sam-ba serial port</string>
@ -734,14 +146,14 @@ m2560 for v4.1 boards</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="0"> <item row="4" column="0">
<widget class="QLabel" name="label_dfu2"> <widget class="QLabel" name="label_dfu2">
<property name="text"> <property name="text">
<string>Alternate device</string> <string>Alternate device</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="2"> <item row="4" column="2">
<widget class="QLineEdit" name="dfuArgs"> <widget class="QLineEdit" name="dfuArgs">
<property name="toolTip"> <property name="toolTip">
<string>Extra arguments that will be passed to AVRDUDE on every call</string> <string>Extra arguments that will be passed to AVRDUDE on every call</string>
@ -757,7 +169,7 @@ Please only use this if you know what you are doing. There are no error checks
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="4"> <item row="0" column="4">
<widget class="QPushButton" name="sb_browse"> <widget class="QPushButton" name="sb_browse">
<property name="whatsThis"> <property name="whatsThis">
<string>Use this button to browse and look for the AVRDUDE executable file.</string> <string>Use this button to browse and look for the AVRDUDE executable file.</string>
@ -767,7 +179,7 @@ Please only use this if you know what you are doing. There are no error checks
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="4"> <item row="3" column="4">
<widget class="QPushButton" name="dfu_browse"> <widget class="QPushButton" name="dfu_browse">
<property name="whatsThis"> <property name="whatsThis">
<string>Use this button to browse and look for the AVRDUDE executable file.</string> <string>Use this button to browse and look for the AVRDUDE executable file.</string>
@ -777,14 +189,14 @@ Please only use this if you know what you are doing. There are no error checks
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="2"> <item row="5" column="2">
<widget class="QCheckBox" name="advCtrChkB"> <widget class="QCheckBox" name="advCtrChkB">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="0"> <item row="5" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Use advanced controls</string> <string>Use advanced controls</string>
@ -809,14 +221,6 @@ Please only use this if you know what you are doing. There are no error checks
</layout> </layout>
</widget> </widget>
<tabstops> <tabstops>
<tabstop>avrdude_location</tabstop>
<tabstop>pushButton</tabstop>
<tabstop>avrdude_programmer</tabstop>
<tabstop>pushButton_3</tabstop>
<tabstop>avrdude_mcu</tabstop>
<tabstop>avrdude_port</tabstop>
<tabstop>avrArgs</tabstop>
<tabstop>pushButton_4</tabstop>
<tabstop>samba_location</tabstop> <tabstop>samba_location</tabstop>
<tabstop>sb_browse</tabstop> <tabstop>sb_browse</tabstop>
<tabstop>arm_mcu</tabstop> <tabstop>arm_mcu</tabstop>

View file

@ -190,6 +190,16 @@
<file>images/simulator/JumperT16/left_tele.png</file> <file>images/simulator/JumperT16/left_tele.png</file>
<file>images/simulator/JumperT16/right_ent.png</file> <file>images/simulator/JumperT16/right_ent.png</file>
<file>images/simulator/JumperT16/right_rtn.png</file> <file>images/simulator/JumperT16/right_rtn.png</file>
<file>images/simulator/JumperT18/left.png</file>
<file>images/simulator/JumperT18/right.png</file>
<file>images/simulator/JumperT18/top.png</file>
<file>images/simulator/JumperT18/bottom.png</file>
<file>images/simulator/JumperT18/left_mdl.png</file>
<file>images/simulator/JumperT18/left_page.png</file>
<file>images/simulator/JumperT18/left_sys.png</file>
<file>images/simulator/JumperT18/left_tele.png</file>
<file>images/simulator/JumperT18/right_ent.png</file>
<file>images/simulator/JumperT18/right_rtn.png</file>
<file>images/simulator/TX16S/left.png</file> <file>images/simulator/TX16S/left.png</file>
<file>images/simulator/TX16S/right.png</file> <file>images/simulator/TX16S/right.png</file>
<file>images/simulator/TX16S/top.png</file> <file>images/simulator/TX16S/top.png</file>

View file

@ -18,8 +18,7 @@ set(firmwares_SRCS
rawswitch.cpp rawswitch.cpp
sensordata.cpp sensordata.cpp
telem_data.cpp telem_data.cpp
er9x/er9xeeprom.cpp afhds3.cpp
er9x/er9xinterface.cpp
ersky9x/ersky9xeeprom.cpp ersky9x/ersky9xeeprom.cpp
ersky9x/ersky9xinterface.cpp ersky9x/ersky9xinterface.cpp
opentx/opentxeeprom.cpp opentx/opentxeeprom.cpp

View file

@ -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);
}

View file

@ -0,0 +1,12 @@
#ifndef AFHDS3_H
#define AFHDS3_H
#include <QtCore>
class Afhds3Data
{
Q_DECLARE_TR_FUNCTIONS(Afhds3)
public:
static QString protocolToString(unsigned int protocol);
};
#endif // AFHDS3_H

View file

@ -25,18 +25,13 @@
// Update: These are now all only used within this class. // Update: These are now all only used within this class.
// External access is only via getEEpromSize() and getFlashSize() // 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_TARANIS (32*1024)
#define EESIZE_SKY9X (128*4096) #define EESIZE_SKY9X (128*4096)
#define EESIZE_9XRPRO (128*4096) #define EESIZE_9XRPRO (128*4096)
#define EESIZE_MAX EESIZE_9XRPRO #define EESIZE_MAX EESIZE_9XRPRO
// getFlashSize() (and these macros) is only used by radiointerface::getDfuArgs (perhaps can find a better way?) // 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_TARANIS (512*1024)
#define FSIZE_SKY9X (256*1024) #define FSIZE_SKY9X (256*1024)
#define FSIZE_9XRPRO (512*1024) #define FSIZE_9XRPRO (512*1024)
@ -82,16 +77,12 @@ uint32_t Boards::getFourCC(Type board)
case BOARD_AR9X: case BOARD_AR9X:
case BOARD_9XRPRO: case BOARD_9XRPRO:
return 0x3278746F; return 0x3278746F;
case BOARD_MEGA2560:
case BOARD_GRUVIN9X:
return 0x3178746F;
case BOARD_9X_M64:
case BOARD_9X_M128:
return 0;
case BOARD_JUMPER_T12: case BOARD_JUMPER_T12:
return 0x3D78746F; return 0x3D78746F;
case BOARD_JUMPER_T16: case BOARD_JUMPER_T16:
return 0x3F78746F; return 0x3F78746F;
case BOARD_JUMPER_T18:
return 0x4078746F;
case BOARD_RADIOMASTER_TX16S: case BOARD_RADIOMASTER_TX16S:
return 0x3878746F; return 0x3878746F;
case BOARD_UNKNOWN: case BOARD_UNKNOWN:
@ -104,13 +95,6 @@ uint32_t Boards::getFourCC(Type board)
int Boards::getEEpromSize(Board::Type board) int Boards::getEEpromSize(Board::Type board)
{ {
switch (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: case BOARD_SKY9X:
return EESIZE_SKY9X; return EESIZE_SKY9X;
case BOARD_9XRPRO: case BOARD_9XRPRO:
@ -134,6 +118,7 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_X10: case BOARD_X10:
case BOARD_X10_EXPRESS: case BOARD_X10_EXPRESS:
case BOARD_JUMPER_T16: case BOARD_JUMPER_T16:
case BOARD_JUMPER_T18:
case BOARD_RADIOMASTER_TX16S: case BOARD_RADIOMASTER_TX16S:
return 0; return 0;
} }
@ -144,13 +129,6 @@ int Boards::getEEpromSize(Board::Type board)
int Boards::getFlashSize(Type board) int Boards::getFlashSize(Type board)
{ {
switch (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: case BOARD_SKY9X:
return FSIZE_SKY9X; return FSIZE_SKY9X;
case BOARD_9XRPRO: case BOARD_9XRPRO:
@ -172,6 +150,7 @@ int Boards::getFlashSize(Type board)
case BOARD_X10: case BOARD_X10:
case BOARD_X10_EXPRESS: case BOARD_X10_EXPRESS:
case BOARD_JUMPER_T16: case BOARD_JUMPER_T16:
case BOARD_JUMPER_T18:
case BOARD_RADIOMASTER_TX16S: case BOARD_RADIOMASTER_TX16S:
return FSIZE_HORUS; return FSIZE_HORUS;
case BOARD_UNKNOWN: case BOARD_UNKNOWN:
@ -310,7 +289,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 0; return 0;
case MouseAnalogs: case MouseAnalogs:
if (IS_FAMILY_HORUS_OR_T16(board)) if (IS_HORUS_X12S(board))
return 2; return 2;
else else
return 0; return 0;
@ -412,7 +391,7 @@ QString Boards::getAnalogInputName(Board::Type board, int index)
index -= getCapability(board, Board::Sticks); index -= getCapability(board, Board::Sticks);
if (IS_9X(board) || IS_2560(board) || IS_SKY9X(board)) { if (IS_SKY9X(board)) {
const QString pots[] = { const QString pots[] = {
"P1", "P1",
"P2", "P2",
@ -496,14 +475,6 @@ bool Boards::isBoardCompatible(Type board1, Type board2)
QString Boards::getBoardName(Board::Type board) QString Boards::getBoardName(Board::Type board)
{ {
switch (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: case BOARD_TARANIS_X7:
return "Taranis X7/X7S"; return "Taranis X7/X7S";
case BOARD_TARANIS_X7_ACCESS: case BOARD_TARANIS_X7_ACCESS:
@ -540,6 +511,8 @@ QString Boards::getBoardName(Board::Type board)
return "Horus X10/X10S Express"; return "Horus X10/X10S Express";
case BOARD_JUMPER_T16: case BOARD_JUMPER_T16:
return "Jumper T16"; return "Jumper T16";
case BOARD_JUMPER_T18:
return "Jumper T18";
case BOARD_RADIOMASTER_TX16S: case BOARD_RADIOMASTER_TX16S:
return "Radiomaster TX16S"; return "Radiomaster TX16S";
default: default:

View file

@ -32,10 +32,6 @@ namespace Board {
enum Type enum Type
{ {
BOARD_UNKNOWN = -1, BOARD_UNKNOWN = -1,
BOARD_9X_M64 = 0,
BOARD_9X_M128,
BOARD_MEGA2560,
BOARD_GRUVIN9X,
BOARD_SKY9X, BOARD_SKY9X,
BOARD_9XRPRO, BOARD_9XRPRO,
BOARD_AR9X, BOARD_AR9X,
@ -55,9 +51,10 @@ namespace Board {
BOARD_JUMPER_T12, BOARD_JUMPER_T12,
BOARD_JUMPER_T16, BOARD_JUMPER_T16,
BOARD_RADIOMASTER_TX16S, BOARD_RADIOMASTER_TX16S,
BOARD_JUMPER_T18,
}; };
constexpr int BOARD_TYPE_MAX = BOARD_RADIOMASTER_TX16S ; constexpr int BOARD_TYPE_MAX = BOARD_JUMPER_T18;
enum PotType enum PotType
{ {
@ -191,26 +188,6 @@ class Boards
// temporary aliases for transition period, use Boards class instead. // temporary aliases for transition period, use Boards class instead.
#define getBoardCapability(b__, c__) Boards::getCapability(b__, c__) #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) inline bool IS_SKY9X(Board::Type board)
{ {
return board == Board::BOARD_SKY9X || board == Board::BOARD_9XRPRO || board == Board::BOARD_AR9X; 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; 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) inline bool IS_RADIOMASTER_TX16S(Board::Type board)
{ {
return board == Board::BOARD_RADIOMASTER_TX16S; 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) 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) 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))); 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) || 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"))); (IS_FAMILY_HORUS_OR_T16(board) && id.contains("internalaccess")));

View file

@ -46,7 +46,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32)
return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model)); return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model));
else if (func == FuncTrainer) else if (func == FuncTrainer)
return tr("Trainer"); return tr("Trainer Sticks");
else if (func == FuncTrainerRUD) else if (func == FuncTrainerRUD)
return tr("Trainer RUD"); return tr("Trainer RUD");
else if (func == FuncTrainerELE) else if (func == FuncTrainerELE)
@ -112,13 +112,10 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox
{ {
int val = 0; int val = 0;
Firmware * firmware = Firmware::getCurrentVariant(); Firmware * firmware = Firmware::getCurrentVariant();
Board::Type board = firmware->getBoard();
b->addItem(tr("Timer1"), val++); b->addItem(tr("Timer1"), val++);
b->addItem(tr("Timer2"), 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("Flight"), val++);
b->addItem(tr("Telemetry"), val++); b->addItem(tr("Telemetry"), val++);
int reCount = firmware->getCapability(RotaryEncoders); int reCount = firmware->getCapability(RotaryEncoders);
@ -132,7 +129,7 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox
if ((int)value < b->count()) { if ((int)value < b->count()) {
b->setCurrentIndex(value); b->setCurrentIndex(value);
} }
if (model && IS_ARM(board)) { if (model) {
for (unsigned i=0; i<CPN_MAX_SENSORS; ++i) { for (unsigned i=0; i<CPN_MAX_SENSORS; ++i) {
if (model->sensorData[i].isAvailable()) { if (model->sensorData[i].isAvailable()) {
RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i); RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i);
@ -162,24 +159,24 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
if (func <= FuncInstantTrim) { if (func <= FuncInstantTrim) {
return QString("%1").arg(param); return QString("%1").arg(param);
} }
else if (func==FuncLogs) { else if (func == FuncLogs) {
return QString("%1").arg(param/10.0) + tr("s"); return QString("%1").arg(param/10.0) + tr("s");
} }
else if (func==FuncPlaySound) { else if (func == FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs); CustomFunctionData::populatePlaySoundParams(qs);
if (param>=0 && param<(int)qs.count()) if (param>=0 && param<(int)qs.count())
return qs.at(param); return qs.at(param);
else else
return tr("<font color=red><b>Inconsistent parameter</b></font>"); return tr("<font color=red><b>Inconsistent parameter</b></font>");
} }
else if (func==FuncPlayHaptic) { else if (func == FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs); CustomFunctionData::populateHapticParams(qs);
if (param>=0 && param<(int)qs.count()) if (param>=0 && param<(int)qs.count())
return qs.at(param); return qs.at(param);
else else
return tr("<font color=red><b>Inconsistent parameter</b></font>"); return tr("<font color=red><b>Inconsistent parameter</b></font>");
} }
else if (func==FuncReset) { else if (func == FuncReset) {
QComboBox cb; QComboBox cb;
CustomFunctionData::populateResetParams(model, &cb); CustomFunctionData::populateResetParams(model, &cb);
int pos = cb.findData(param); int pos = cb.findData(param);
@ -188,11 +185,11 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
else else
return tr("<font color=red><b>Inconsistent parameter</b></font>"); return tr("<font color=red><b>Inconsistent parameter</b></font>");
} }
else if ((func==FuncVolume)|| (func==FuncPlayValue)) { else if (func == FuncVolume || func == FuncPlayValue || func == FuncBacklight) {
RawSource item(param); RawSource item(param);
return item.toString(model); return item.toString(model);
} }
else if ((func==FuncPlayPrompt) || (func==FuncPlayBoth)) { else if (func == FuncPlayPrompt || func == FuncPlayBoth) {
if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) { if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) {
return QString("%1").arg(param); return QString("%1").arg(param);
} }
@ -200,7 +197,7 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
return paramarm; return paramarm;
} }
} }
else if ((func>=FuncAdjustGV1) && (func<FuncCount)) { else if (func >= FuncAdjustGV1 && func < FuncCount) {
switch (adjustMode) { switch (adjustMode) {
case FUNC_ADJUST_GVAR_CONSTANT: case FUNC_ADJUST_GVAR_CONSTANT:
return tr("Value ")+QString("%1").arg(param); return tr("Value ")+QString("%1").arg(param);
@ -210,14 +207,8 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
case FUNC_ADJUST_GVAR_INCDEC: case FUNC_ADJUST_GVAR_INCDEC:
float val; float val;
QString unit; QString unit;
if (IS_ARM(getCurrentBoard())) { val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet();
val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet(); unit = model->gvarData[func - FuncAdjustGV1].unitToString();
unit = model->gvarData[func - FuncAdjustGV1].unitToString();
}
else {
val = param;
unit = "";
}
return QString("Increment: %1%2").arg(val).arg(unit); return QString("Increment: %1%2").arg(val).arg(unit);
} }
} }
@ -233,18 +224,19 @@ QString CustomFunctionData::repeatToString() const
return ""; return "";
} }
else { else {
unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10; unsigned int step = 1;
return tr("repeat(%1s)").arg(step*repeatParam); return tr("repeat(%1s)").arg(step*repeatParam);
} }
} }
QString CustomFunctionData::enabledToString() const QString CustomFunctionData::enabledToString() const
{ {
if ((func>=FuncOverrideCH1 && func<=FuncOverrideCH32) || if ((func >= FuncOverrideCH1 && func <= FuncOverrideCH32) ||
(func>=FuncAdjustGV1 && func<=FuncAdjustGVLast) || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) ||
(func==FuncReset) || (func == FuncReset) ||
(func>=FuncSetTimer1 && func<=FuncSetTimer2) || (func >= FuncSetTimer1 && func <= FuncSetTimer2) ||
(func==FuncVolume) || (func == FuncVolume) ||
(func == FuncBacklight) ||
(func <= FuncInstantTrim)) { (func <= FuncInstantTrim)) {
if (!enabled) { if (!enabled) {
return tr("DISABLED"); return tr("DISABLED");
@ -258,7 +250,7 @@ void CustomFunctionData::convert(RadioDataConversionState & cstate)
cstate.setComponent(tr("CFN"), 8); cstate.setComponent(tr("CFN"), 8);
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true))); cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
swtch.convert(cstate); 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(); param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue();
} }
} }

View file

@ -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(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_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_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_SIZE)) { errorsList << tr("- Eeprom size is invalid"); }
if (errors.test(WRONG_FILE_SYSTEM)) { errorsList << tr("- Eeprom file system is invalid"); } if (errors.test(WRONG_FILE_SYSTEM)) { errorsList << tr("- Eeprom file system is invalid"); }
if (errors.test(UNKNOWN_BOARD)) { errorsList << tr("- Eeprom is from a unknown board"); } if (errors.test(UNKNOWN_BOARD)) { errorsList << tr("- Eeprom is from a unknown board"); }

View file

@ -235,10 +235,7 @@ enum EepromLoadErrors {
WRONG_SIZE, WRONG_SIZE,
WRONG_FILE_SYSTEM, WRONG_FILE_SYSTEM,
NOT_OPENTX, NOT_OPENTX,
NOT_TH9X,
NOT_GRUVIN9X,
NOT_ERSKY9X, NOT_ERSKY9X,
NOT_ER9X,
UNKNOWN_BOARD, UNKNOWN_BOARD,
WRONG_BOARD, WRONG_BOARD,
BACKUP_NOT_SUPPORTED, BACKUP_NOT_SUPPORTED,

View file

@ -110,9 +110,7 @@ GeneralSettings::GeneralSettings()
backlightOffBright = 20; backlightOffBright = 20;
} }
if (IS_ARM(board)) { speakerVolume = 12;
speakerVolume = 12;
}
if (IS_JUMPER_T16(board)) if (IS_JUMPER_T16(board))
strcpy(bluetoothName, "t16"); strcpy(bluetoothName, "t16");

View file

@ -142,6 +142,7 @@ class GeneralSettings {
unsigned int countryCode; unsigned int countryCode;
bool jitterFilter; bool jitterFilter;
bool rtcCheckDisable; bool rtcCheckDisable;
bool keysBacklight;
unsigned int imperial; unsigned int imperial;
char ttsLanguage[2+1]; char ttsLanguage[2+1];
int beepVolume; int beepVolume;

View file

@ -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*/); 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 * ModelData
*/ */
@ -207,36 +212,25 @@ bool ModelData::isEmpty() const
void ModelData::setDefaultInputs(const GeneralSettings & settings) void ModelData::setDefaultInputs(const GeneralSettings & settings)
{ {
Board::Type board = getCurrentBoard(); for (int i = 0; i < CPN_MAX_STICKS; i++) {
if (IS_ARM(board)) { ExpoData * expo = &expoData[i];
for (int i = 0; i < CPN_MAX_STICKS; i++) { expo->chn = i;
ExpoData * expo = &expoData[i]; expo->mode = INPUT_MODE_BOTH;
expo->chn = i; expo->srcRaw = settings.getDefaultSource(i);
expo->mode = INPUT_MODE_BOTH; expo->weight = 100;
expo->srcRaw = settings.getDefaultSource(i); strncpy(inputNames[i], Helpers::removeAccents(expo->srcRaw.toString(this)).toLatin1().constData(), sizeof(inputNames[i]) - 1);
expo->weight = 100;
strncpy(inputNames[i], Helpers::removeAccents(expo->srcRaw.toString(this)).toLatin1().constData(), sizeof(inputNames[i]) - 1);
}
} }
} }
void ModelData::setDefaultMixes(const GeneralSettings & settings) void ModelData::setDefaultMixes(const GeneralSettings & settings)
{ {
Board::Type board = getCurrentBoard(); setDefaultInputs(settings);
if (IS_ARM(board)) {
setDefaultInputs(settings);
}
for (int i = 0; i < CPN_MAX_STICKS; i++) { for (int i = 0; i < CPN_MAX_STICKS; i++) {
MixData * mix = &mixData[i]; MixData * mix = &mixData[i];
mix->destCh = i + 1; mix->destCh = i + 1;
mix->weight = 100; mix->weight = 100;
if (IS_ARM(board)) { mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i);
mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i);
}
else {
mix->srcRaw = RawSource(SOURCE_TYPE_STICK, i);
}
} }
} }
@ -538,6 +532,8 @@ int ModelData::updateReference()
Firmware *fw = getCurrentFirmware(); Firmware *fw = getCurrentFirmware();
updRefInfo.occurences = 1;
switch (updRefInfo.type) switch (updRefInfo.type)
{ {
case REF_UPD_TYPE_CHANNEL: case REF_UPD_TYPE_CHANNEL:
@ -572,6 +568,7 @@ int ModelData::updateReference()
updRefInfo.srcType = SOURCE_TYPE_TELEMETRY; updRefInfo.srcType = SOURCE_TYPE_TELEMETRY;
updRefInfo.swtchType = SWITCH_TYPE_SENSOR; updRefInfo.swtchType = SWITCH_TYPE_SENSOR;
updRefInfo.maxindex = fw->getCapability(Sensors); updRefInfo.maxindex = fw->getCapability(Sensors);
updRefInfo.occurences = 3;
break; break;
case REF_UPD_TYPE_TIMER: case REF_UPD_TYPE_TIMER:
updRefInfo.srcType = SOURCE_TYPE_SPECIAL; updRefInfo.srcType = SOURCE_TYPE_SPECIAL;
@ -662,6 +659,8 @@ int ModelData::updateReference()
} }
} }
} }
if (updRefInfo.type == REF_UPD_TYPE_CHANNEL)
sortMixes();
//s1.report("Mixes"); //s1.report("Mixes");
for (int i = 0; i < CPN_MAX_CHNOUT; i++) { for (int i = 0; i < CPN_MAX_CHNOUT; i++) {
@ -724,7 +723,7 @@ int ModelData::updateReference()
updateAssignFunc(cfd); updateAssignFunc(cfd);
if (!cfd->isEmpty()) { if (!cfd->isEmpty()) {
updateSwitchRef(cfd->swtch); 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); updateSourceIntRef(cfd->param);
if (cfd->param == 0) if (cfd->param == 0)
cfd->clear(); cfd->clear();
@ -773,15 +772,35 @@ int ModelData::updateReference()
//s1.report("Telemetry"); //s1.report("Telemetry");
} }
// TODO maybe less risk to leave it up to the user??
/*
for (int i = 0; i < CPN_MAX_SENSORS; i++) { for (int i = 0; i < CPN_MAX_SENSORS; i++) {
SensorData *sd = &sensorData[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 // 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.type = curRef.type;
newRef.index = abs(curRef.index); newRef.index = abs(curRef.index);
div_t idx = div(newRef.index, updRefInfo.occurences);
switch (updRefInfo.action) switch (updRefInfo.action)
{ {
case REF_UPD_ACT_CLEAR: case REF_UPD_ACT_CLEAR:
if (newRef.index != (updRefInfo.index1 + idxAdj)) if (idx.quot != (updRefInfo.index1 + idxAdj))
return; return;
if (defClear) if (defClear)
newRef.clear(); newRef.clear();
else { else {
newRef.type = (T)defType; newRef.type = (T)defType;
newRef.index = defIndex; newRef.index = defIndex + idxAdj;
} }
break; break;
case REF_UPD_ACT_SHIFT: case REF_UPD_ACT_SHIFT:
if (newRef.index < (updRefInfo.index1 + idxAdj)) if (idx.quot < (updRefInfo.index1 + idxAdj))
return; return;
newRef.index += updRefInfo.shift; 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) if (defClear)
newRef.clear(); newRef.clear();
else { else {
newRef.type = (T)defType; newRef.type = (T)defType;
newRef.index = defIndex; newRef.index = defIndex + idxAdj;
} }
} }
break; break;
case REF_UPD_ACT_SWAP: case REF_UPD_ACT_SWAP:
if (newRef.index == updRefInfo.index1 + idxAdj) if (idx.quot == updRefInfo.index1 + idxAdj)
newRef.index = updRefInfo.index2 + idxAdj; newRef.index = ((updRefInfo.index2 + idxAdj) * updRefInfo.occurences) + idx.rem;
else if (newRef.index == updRefInfo.index2 + idxAdj) else if (idx.quot == updRefInfo.index2 + idxAdj)
newRef.index = updRefInfo.index1 + idxAdj; newRef.index = ((updRefInfo.index1 + idxAdj) * updRefInfo.occurences) + idx.rem;
break; break;
default: default:
qDebug() << "Error - unhandled action:" << updRefInfo.action; qDebug() << "Error - unhandled action:" << updRefInfo.action;
@ -883,7 +904,7 @@ void ModelData::updateTypeValueRef(R & curRef, const T type, const int idxAdj, c
newRef.clear(); newRef.clear();
else { else {
newRef.type = (T)defType; newRef.type = (T)defType;
newRef.value = defValue; newRef.value = defValue + idxAdj;
} }
break; break;
case REF_UPD_ACT_SHIFT: case REF_UPD_ACT_SHIFT:
@ -897,7 +918,7 @@ void ModelData::updateTypeValueRef(R & curRef, const T type, const int idxAdj, c
newRef.clear(); newRef.clear();
else { else {
newRef.type = (T)defType; newRef.type = (T)defType;
newRef.value = defValue; newRef.value = defValue + idxAdj;
} }
} }
break; 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) if (updRefInfo.type != REF_UPD_TYPE_SENSOR)
return; return;
const int idxAdj = 1; const int idxAdj = 1;
int newRef = curRef; int newRef = curRef;
switch (updRefInfo.action) switch (updRefInfo.action)
{ {
case REF_UPD_ACT_CLEAR: case REF_UPD_ACT_CLEAR:
@ -1160,13 +1182,23 @@ void ModelData::updateTelemetryRef(unsigned int & curRef)
return; return;
} }
if (curRef != static_cast<unsigned int>(newRef)) { if (curRef != newRef) {
//qDebug() << "Updated reference:" << curRef << " -> " << newRef; //qDebug() << "Updated reference:" << curRef << " -> " << newRef;
curRef = newRef; curRef = newRef;
updRefInfo.updcnt++; updRefInfo.updcnt++;
} }
} }
void ModelData::updateTelemetryRef(unsigned int & curRef)
{
int newRef = (int)curRef;
updateTelemetryRef(newRef);
if (curRef != static_cast<unsigned int>(newRef)) {
curRef = (unsigned int)newRef;
}
}
void ModelData::updateModuleFailsafes(ModuleData * md) void ModelData::updateModuleFailsafes(ModuleData * md)
{ {
if (updRefInfo.type != REF_UPD_TYPE_CHANNEL) 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)); memmove(&mixData[idx], &mixData[idx + 1], (CPN_MAX_MIXERS - (idx + 1)) * sizeof(MixData));
mixData[CPN_MAX_MIXERS - 1].clear(); 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<int, int> 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<int, int>::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));
}

View file

@ -41,13 +41,10 @@ class RadioDataConversionState;
class RSSIAlarmData { class RSSIAlarmData {
public: public:
RSSIAlarmData() { clear(); } RSSIAlarmData() { clear(); }
unsigned int level[2]; // AVR Only
int warning; int warning;
int critical; int critical;
bool disabled; bool disabled;
void clear() { void clear() {
this->level[0] = 2;
this->level[1] = 3;
this->warning = 45; this->warning = 45;
this->critical = 42; this->critical = 42;
this->disabled = false; this->disabled = false;
@ -78,6 +75,7 @@ class TimerData {
void convert(RadioDataConversionState & cstate); void convert(RadioDataConversionState & cstate);
bool isEmpty(); bool isEmpty();
bool isModeOff() { return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); } bool isModeOff() { return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
QString nameToString(int index) const;
}; };
#define CPN_MAX_SCRIPTS 9 #define CPN_MAX_SCRIPTS 9
@ -184,6 +182,7 @@ class ModelData {
unsigned int thrTraceSrc; unsigned int thrTraceSrc;
uint64_t switchWarningStates; uint64_t switchWarningStates;
unsigned int switchWarningEnable; unsigned int switchWarningEnable;
unsigned int thrTrimSwitch;
unsigned int potsWarningMode; unsigned int potsWarningMode;
bool potsWarnEnabled[CPN_MAX_POTS]; bool potsWarnEnabled[CPN_MAX_POTS];
int potsWarnPosition[CPN_MAX_POTS]; int potsWarnPosition[CPN_MAX_POTS];
@ -300,6 +299,7 @@ class ModelData {
int shift; int shift;
int updcnt; int updcnt;
int maxindex; int maxindex;
int occurences;
RawSourceType srcType; RawSourceType srcType;
RawSwitchType swtchType; RawSwitchType swtchType;
}; };
@ -317,6 +317,7 @@ class ModelData {
void updateDestCh(MixData * md); void updateDestCh(MixData * md);
void updateLimitCurveRef(CurveReference & crv); void updateLimitCurveRef(CurveReference & crv);
void updateFlightModeFlags(unsigned int & flags); void updateFlightModeFlags(unsigned int & flags);
void updateTelemetryRef(int & idx);
void updateTelemetryRef(unsigned int & idx); void updateTelemetryRef(unsigned int & idx);
void updateModuleFailsafes(ModuleData * md); void updateModuleFailsafes(ModuleData * md);
inline void updateSourceRef(RawSource & src) { updateTypeIndexRef<RawSource, RawSourceType>(src, updRefInfo.srcType); } inline void updateSourceRef(RawSource & src) { updateTypeIndexRef<RawSource, RawSourceType>(src, updRefInfo.srcType); }
@ -336,6 +337,7 @@ class ModelData {
if (value != swtch.toValue()) if (value != swtch.toValue())
value = swtch.toValue(); value = swtch.toValue();
} }
void sortMixes();
}; };
#endif // MODELDATA_H #endif // MODELDATA_H

View file

@ -21,6 +21,7 @@
#include "moduledata.h" #include "moduledata.h"
#include "eeprominterface.h" #include "eeprominterface.h"
#include "multiprotocols.h" #include "multiprotocols.h"
#include "afhds3.h"
#include "radiodataconversionstate.h" #include "radiodataconversionstate.h"
void ModuleData::convert(RadioDataConversionState & cstate) void ModuleData::convert(RadioDataConversionState & cstate)
@ -65,6 +66,7 @@ bool ModuleData::supportRxNum() const
case PULSES_PXX_R9M_LITE: case PULSES_PXX_R9M_LITE:
case PULSES_PXX_R9M_LITE_PRO: case PULSES_PXX_R9M_LITE_PRO:
case PULSES_MULTIMODULE: case PULSES_MULTIMODULE:
case PULSES_CROSSFIRE:
case PULSES_ACCESS_ISRM: case PULSES_ACCESS_ISRM:
case PULSES_ACCST_ISRM_D16: case PULSES_ACCST_ISRM_D16:
case PULSES_ACCESS_R9M: case PULSES_ACCESS_R9M:
@ -87,7 +89,6 @@ QString ModuleData::rfProtocolToString() const
switch (protocol) { switch (protocol) {
case PULSES_MULTIMODULE: case PULSES_MULTIMODULE:
return Multiprotocols::protocolToString((int)multi.rfProtocol); return Multiprotocols::protocolToString((int)multi.rfProtocol);
default: default:
return CPN_STR_UNKNOWN_ITEM; return CPN_STR_UNKNOWN_ITEM;
} }
@ -108,10 +109,10 @@ QString ModuleData::subTypeToString(int type) const
switch (protocol) { switch (protocol) {
case PULSES_MULTIMODULE: case PULSES_MULTIMODULE:
return Multiprotocols::subTypeToString((int)multi.rfProtocol, (unsigned)type); return Multiprotocols::subTypeToString((int)multi.rfProtocol, (unsigned)type);
case PULSES_PXX_R9M: case PULSES_PXX_R9M:
return CHECK_IN_ARRAY(strings, type); return CHECK_IN_ARRAY(strings, type);
case PULSES_AFHDS3:
return Afhds3Data::protocolToString(type);
default: default:
return CPN_STR_UNKNOWN_ITEM; return CPN_STR_UNKNOWN_ITEM;
} }
@ -119,8 +120,8 @@ QString ModuleData::subTypeToString(int type) const
QString ModuleData::powerValueToString(Firmware * fw) const QString ModuleData::powerValueToString(Firmware * fw) const
{ {
const QStringList & strRef = powerValueStrings(subType, fw); const QStringList & strRef = powerValueStrings((enum PulsesProtocol)protocol, subType, fw);
return strRef.value(pxx.power, CPN_STR_UNKNOWN_ITEM); return strRef.value(protocol == PULSES_AFHDS3 ? afhds3.rfPower : pxx.power, CPN_STR_UNKNOWN_ITEM);
} }
// static // static
@ -159,14 +160,16 @@ QString ModuleData::protocolToString(unsigned protocol)
"FrSky ACCESS R9M 2019", "FrSky ACCESS R9M 2019",
"FrSky ACCESS R9M Lite", "FrSky ACCESS R9M Lite",
"FrSky ACCESS R9M Lite Pro", "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); return CHECK_IN_ARRAY(strings, protocol);
} }
// static // static
QStringList ModuleData::powerValueStrings(int subType, Firmware * fw) QStringList ModuleData::powerValueStrings(enum PulsesProtocol protocol, int subType, Firmware * fw)
{ {
static const QStringList strings[] = { static const QStringList strings[] = {
{ tr("10mW - 16CH"), tr("100mW - 16CH"), tr("500mW - 16CH"), tr("Auto <= 1W - 16CH") }, // full-size FCC { 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("100mW - 16CH") }, // mini FCC
{ tr("25mW - 8CH"), tr("25mW - 16CH"), tr("100mW - 16CH (no telemetry)") } // mini EU { tr("25mW - 8CH"), tr("25mW - 16CH"), tr("100mW - 16CH (no telemetry)") } // mini EU
}; };
int strIdx = 0; static const QStringList afhds3Strings = {
if (subType == MODULE_SUBTYPE_R9M_EU) tr("25 mW"), tr("100 mW"), tr("500 mW"), tr("1 W"), tr("2 W")
strIdx += 1; };
if (fw->getCapability(HasModuleR9MMini))
strIdx += 2; switch(protocol) {
return strings[strIdx]; 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 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 ||
protocol == PULSES_ACCESS_R9M_LITE_PRO || protocol == PULSES_ACCESS_R9M_LITE_PRO ||
protocol == PULSES_XJT_LITE_X16 || 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_XJT_LITE_X16:
case PULSES_PXX_XJT_X16: case PULSES_PXX_XJT_X16:
case PULSES_CROSSFIRE: case PULSES_CROSSFIRE:
case PULSES_GHOST:
case PULSES_SBUS: case PULSES_SBUS:
case PULSES_PPM: case PULSES_PPM:
return 16; return 16;
@ -230,6 +244,8 @@ int ModuleData::getMaxChannelCount()
else else
return 16; return 16;
break; break;
case PULSES_AFHDS3:
return 18;
case PULSES_OFF: case PULSES_OFF:
break; break;
default: default:

View file

@ -58,6 +58,8 @@ enum PulsesProtocol {
PULSES_XJT_LITE_X16, PULSES_XJT_LITE_X16,
PULSES_XJT_LITE_D8, PULSES_XJT_LITE_D8,
PULSES_XJT_LITE_LR12, PULSES_XJT_LITE_LR12,
PULSES_AFHDS3,
PULSES_GHOST,
PULSES_PROTOCOL_LAST PULSES_PROTOCOL_LAST
}; };
@ -190,6 +192,11 @@ class ModuleData {
int optionValue; int optionValue;
} multi; } multi;
struct Afhds3 {
unsigned int rxFreq;
unsigned int rfPower;
} afhds3;
struct PXX { struct PXX {
unsigned int power; // 0 10 mW, 1 100 mW, 2 500 mW, 3 1W unsigned int power; // 0 10 mW, 1 100 mW, 2 500 mW, 3 1W
bool receiverTelemetryOff; // false = receiver telem enabled bool receiverTelemetryOff; // false = receiver telem enabled
@ -213,7 +220,7 @@ class ModuleData {
QString powerValueToString(Firmware * fw) const; QString powerValueToString(Firmware * fw) const;
static QString indexToString(int index, Firmware * fw); static QString indexToString(int index, Firmware * fw);
static QString protocolToString(unsigned protocol); 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; bool hasFailsafes(Firmware * fw) const;
int getMaxChannelCount(); int getMaxChannelCount();
}; };

View file

@ -26,8 +26,8 @@
#define STR_MULTI_SUBTYPE QT_TRANSLATE_NOOP("Multiprotocols", "Subtype") #define STR_MULTI_SUBTYPE QT_TRANSLATE_NOOP("Multiprotocols", "Subtype")
#define STR_MULTI_VIDFREQ QT_TRANSLATE_NOOP("Multiprotocols", "Video TX frequency") #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_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_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_SERVOFREQ QT_TRANSLATE_NOOP("Multiprotocols", "Servo output frequency")
#define STR_MULTI_OPTION QT_TRANSLATE_NOOP("Multiprotocols", "Option value") #define STR_MULTI_OPTION QT_TRANSLATE_NOOP("Multiprotocols", "Option value")
#define STR_MULTI_FIXEDID QT_TRANSLATE_NOOP("Multiprotocols", "Fixed ID 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_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_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_HISKY {"Standard", "HK310"};
static const QStringList STR_SUBTYPE_V2X2 {"Standard", "JXD506"}; static const QStringList STR_SUBTYPE_V2X2 {"Standard", "JXD506", "MR101"};
static const QStringList STR_SUBTYPE_DSM {"DSM2 22ms", "DSM2 11ms", "DSMX 22ms", "DSMX 11ms"}; 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_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_YD717 {"Standard", "Skywalker", "Syma X4", "XINXUN", "NIHUI"};
static const QStringList STR_SUBTYPE_KN {"WLtoys", "FeiLun"}; 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_E01X {"E012", "E015", "E016H"};
static const QStringList STR_SUBTYPE_V911S {"Standard", "E119"}; static const QStringList STR_SUBTYPE_V911S {"Standard", "E119"};
static const QStringList STR_SUBTYPE_GD00X {"GD V1", "GD V2"}; 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_REDPINE {"Fast", "Slow"};
static const QStringList STR_SUBTYPE_POTENSIC {"A20 Firefly"}; static const QStringList STR_SUBTYPE_POTENSIC {"A20 Firefly"};
static const QStringList STR_SUBTYPE_ZSX {"JJRC ZSX-280"}; 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_FX816 {"P38"};
static const QStringList STR_SUBTYPE_PELIKAN {"Pro", "Lite"}; static const QStringList STR_SUBTYPE_PELIKAN {"Pro", "Lite"};
static const QStringList STR_SUBTYPE_XK {"X450", "X420"}; 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_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_FRSKYR9 {"915 MHz", "868 MHz", "915 MHz 8-Channel", "868 MHz 8-Channel"};
static const QStringList STR_SUBTYPE_PROPEL {"74-Z"}; static const QStringList STR_SUBTYPE_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_HUBSAN, 2, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
{MODULE_SUBTYPE_MULTI_FRSKY, 7, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_FRSKY, 7, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_HISKY, 1, false, STR_SUBTYPE_HISKY, nullptr}, {MODULE_SUBTYPE_MULTI_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_DSM2, 3, false, STR_SUBTYPE_DSM, nullptr},
{MODULE_SUBTYPE_MULTI_DEVO, 4, false, STR_SUBTYPE_DEVO, STR_MULTI_FIXEDID}, {MODULE_SUBTYPE_MULTI_DEVO, 4, false, STR_SUBTYPE_DEVO, STR_MULTI_FIXEDID},
{MODULE_SUBTYPE_MULTI_YD717, 4, false, STR_SUBTYPE_YD717, nullptr}, {MODULE_SUBTYPE_MULTI_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_E01X, 2, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION},
{MODULE_SUBTYPE_MULTI_V911S, 1, false, STR_SUBTYPE_V911S, STR_MULTI_RFTUNE}, {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_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_KF606, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_REDPINE, 1, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_REDPINE, 1, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, STR_SUBTYPE_POTENSIC, nullptr}, {MODULE_SUBTYPE_MULTI_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_FX816, 0, false, STR_SUBTYPE_FX816, nullptr},
{MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, STR_SUBTYPE_PELIKAN, 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_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_FRSKYX2, 4, true, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, STR_SUBTYPE_FRSKYR9, nullptr}, {MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, STR_SUBTYPE_FRSKYR9, nullptr},
{MODULE_SUBTYPE_MULTI_PROPEL, 0, false, STR_SUBTYPE_PROPEL, nullptr}, {MODULE_SUBTYPE_MULTI_PROPEL, 0, false, STR_SUBTYPE_PROPEL, nullptr},

View file

@ -128,6 +128,14 @@ inline int SWITCHES_CONFIG_SIZE(Board::Type board, int version)
return 16; 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_ROTARY_ENCODERS(board) 0
#define MAX_FLIGHT_MODES(board, version) 9 #define MAX_FLIGHT_MODES(board, version) 9
#define MAX_TIMERS(board, version) 3 #define MAX_TIMERS(board, version) 3
@ -300,7 +308,7 @@ class SourcesConversionTable: public ConversionTable {
} }
} }
for (int i=0; i<CPN_MAX_STICKS + MAX_POTS_SOURCES(board, version) + MAX_SLIDERS_SOURCES(board, version) + Boards::getCapability(board, Board::MouseAnalogs) + MAX_GYRO_ANALOGS(board, version); i++) { for (int i=0; i<CPN_MAX_STICKS + MAX_POTS_SOURCES(board, version) + MAX_SLIDERS_SOURCES(board, version) + MAX_MOUSE_ANALOG_SOURCES(board, version) + MAX_GYRO_ANALOGS(board, version); i++) {
int offset = 0; int offset = 0;
if (version <= 218 && IS_HORUS_X10(board) && i >= CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version)) if (version <= 218 && IS_HORUS_X10(board) && i >= CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version))
offset += 2; offset += 2;
@ -721,13 +729,7 @@ class FlightModeField: public TransformedField {
trim = 501 + phase.trimRef[i] - (phase.trimRef[i] > index ? 1 : 0); trim = 501 + phase.trimRef[i] - (phase.trimRef[i] > index ? 1 : 0);
else else
trim = std::max(-500, std::min(500, phase.trim[i])); trim = std::max(-500, std::min(500, phase.trim[i]));
if (board == BOARD_9X_M64 || (board == BOARD_9X_M128 && version >= 215)) { trimBase[i] = trim;
trimBase[i] = trim >> 2;
trimExt[i] = (trim & 0x03);
}
else {
trimBase[i] = trim;
}
} }
} }
} }
@ -751,11 +753,7 @@ class FlightModeField: public TransformedField {
phase.trim[i] = 0; phase.trim[i] = 0;
} }
else { else {
int trim; int trim = trimBase[i];
if (board == BOARD_9X_M64 || (board == BOARD_9X_M128 && version >= 215))
trim = ((trimBase[i]) << 2) + (trimExt[i] & 0x03);
else
trim = trimBase[i];
if (trim > 500) { if (trim > 500) {
phase.trimRef[i] = trim - 501; phase.trimRef[i] = trim - 501;
if (phase.trimRef[i] >= index) if (phase.trimRef[i] >= index)
@ -2113,6 +2111,40 @@ class ModuleUnionField: public UnionField<unsigned int> {
unsigned int version; 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 { class AccessField: public UnionField::TransformedMember {
public: public:
AccessField(DataField * parent, ModuleData& module): AccessField(DataField * parent, ModuleData& module):
@ -2173,8 +2205,10 @@ class ModuleUnionField: public UnionField<unsigned int> {
ModuleUnionField(DataField * parent, ModuleData & module, Board::Type board, unsigned int version): ModuleUnionField(DataField * parent, ModuleData & module, Board::Type board, unsigned int version):
UnionField<unsigned int>(parent, module.protocol) UnionField<unsigned int>(parent, module.protocol)
{ {
if (version >= 219) if (version >= 219) {
Append(new AccessField(parent, module)); Append(new AccessField(parent, module));
Append(new Afhds3Field(parent, module));
}
Append(new PxxField(parent, module, version)); Append(new PxxField(parent, module, version));
Append(new MultiField(parent, module)); Append(new MultiField(parent, module));
Append(new PPMField(parent, module.ppm)); 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)); internalField.Append(new UnsignedField<2>(this, modelData.potsWarningMode));
} }
else { 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)); internalField.Append(new UnsignedField<2>(this, modelData.potsWarningMode));
} }
@ -2543,7 +2578,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
generalData(generalData), generalData(generalData),
board(board), board(board),
version(version), 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); 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 else
internalField.Append(new SpareBitsField<2>(this)); internalField.Append(new SpareBitsField<2>(this));
internalField.Append(new BoolField<1>(this, generalData.rtcCheckDisable)); 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++) { for (int i=0; i<4; i++) {
internalField.Append(new SignedField<16>(this, generalData.trainer.calib[i])); internalField.Append(new SignedField<16>(this, generalData.trainer.calib[i]));

View file

@ -37,9 +37,6 @@
#define TARANIS_X9LITES_VARIANT 0x0801 #define TARANIS_X9LITES_VARIANT 0x0801
#define JUMPER_T12_VARIANT 0x4001 #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 { class OpenTxGeneralData: public TransformedField {
public: public:
OpenTxGeneralData(GeneralSettings & generalData, Board::Type board, unsigned int version, unsigned int variant=0); 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_ACCESS_R9M, val++);
addConversion(PULSES_PXX_R9M_LITE, val++); addConversion(PULSES_PXX_R9M_LITE, val++);
addConversion(PULSES_ACCESS_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_ACCESS_R9M_LITE_PRO, val++);
addConversion(PULSES_SBUS, val++); addConversion(PULSES_SBUS, val++);
@ -107,6 +104,10 @@ class ProtocolsConversionTable: public ConversionTable
addConversion(PULSES_XJT_LITE_X16, val); addConversion(PULSES_XJT_LITE_X16, val);
addConversion(PULSES_XJT_LITE_D8, val); addConversion(PULSES_XJT_LITE_D8, val);
addConversion(PULSES_XJT_LITE_LR12, val++); addConversion(PULSES_XJT_LITE_LR12, val++);
if (version >= 219) {
addConversion(PULSES_AFHDS3, val++);
}
} }
}; };

View file

@ -58,18 +58,12 @@ OpenTxEepromInterface::~OpenTxEepromInterface()
const char * OpenTxEepromInterface::getName() const char * OpenTxEepromInterface::getName()
{ {
switch (board) { 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: case BOARD_JUMPER_T12:
return "OpenTX for Jumper T12"; return "OpenTX for Jumper T12";
case BOARD_JUMPER_T16: case BOARD_JUMPER_T16:
return "OpenTX for Jumper T16"; return "OpenTX for Jumper T16";
case BOARD_JUMPER_T18:
return "OpenTX for Jumper T18";
case BOARD_RADIOMASTER_TX16S: case BOARD_RADIOMASTER_TX16S:
return "OpenTX for Radiomaster TX16S"; return "OpenTX for Radiomaster TX16S";
case BOARD_TARANIS_X9D: case BOARD_TARANIS_X9D:
@ -280,16 +274,7 @@ unsigned long OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *
uint8_t OpenTxEepromInterface::getLastDataVersion(Board::Type board) uint8_t OpenTxEepromInterface::getLastDataVersion(Board::Type board)
{ {
switch (board) { return 219;
case BOARD_9X_M64:
return 216;
case BOARD_GRUVIN9X:
case BOARD_MEGA2560:
case BOARD_9X_M128:
return 217;
default:
return 219;
}
} }
void OpenTxEepromInterface::showErrors(const QString & title, const QStringList & errors) 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); efile->EeFsCreate(eeprom, size, board, version);
if (board == BOARD_9X_M128) { if (IS_TARANIS_X9E(board)) {
variant |= M128_VARIANT;
}
else if (IS_TARANIS_X9E(board)) {
variant |= TARANIS_X9E_VARIANT; variant |= TARANIS_X9E_VARIANT;
} }
else if (IS_TARANIS_X9LITES(board)) { else if (IS_TARANIS_X9LITES(board)) {
@ -445,43 +427,26 @@ int OpenTxFirmware::getCapability(::Capability capability)
case Models: case Models:
if (IS_FAMILY_HORUS_OR_T16(board)) if (IS_FAMILY_HORUS_OR_T16(board))
return 0; return 0;
else if (IS_ARM(board)) else
return 60; return 60;
else if (board == BOARD_9X_M128)
return 30;
else if (IS_2560(board))
return 30;
else
return 16;
case Imperial: case Imperial:
if (IS_ARM(board)) return 0;
return 0;
else
return id.contains("imperial") ? 1 : 0;
case ModelImage: case ModelImage:
return (board == BOARD_TARANIS_X9D || IS_TARANIS_PLUS(board) || board == BOARD_TARANIS_X9DP_2019 || IS_FAMILY_HORUS_OR_T16(board)); return (board == BOARD_TARANIS_X9D || IS_TARANIS_PLUS(board) || board == BOARD_TARANIS_X9DP_2019 || IS_FAMILY_HORUS_OR_T16(board));
case HasBeeper: case HasBeeper:
return (!IS_ARM(board)); return false;
case HasPxxCountry: case HasPxxCountry:
return 1; return 1;
case HasGeneralUnits: case HasGeneralUnits:
if (IS_ARM(board)) return true;
return 1;
else
return 0;
case HasNegAndSwitches: case HasNegAndSwitches:
return IS_ARM(board); return true;
case PPMExtCtrl: case PPMExtCtrl:
return 1; return 1;
case PPMFrameLength: case PPMFrameLength:
return 40; return 40;
case FlightModes: case FlightModes:
if (IS_ARM(board)) return 9;
return 9;
else if (IS_2560(board))
return 6;
else
return 5;
case FlightModesHaveFades: case FlightModesHaveFades:
return 1; return 1;
case Heli: case Heli:
@ -493,7 +458,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
if (IS_HORUS_OR_TARANIS(board)) if (IS_HORUS_OR_TARANIS(board))
return id.contains("nogvars") ? 0 : 9; return id.contains("nogvars") ? 0 : 9;
else if (id.contains("gvars")) else if (id.contains("gvars"))
return IS_ARM(board) ? 9 : 5; return 9;
else else
return 0; return 0;
case ModelName: case ModelName:
@ -501,66 +466,48 @@ int OpenTxFirmware::getCapability(::Capability capability)
case FlightModesName: case FlightModesName:
return (IS_HORUS_OR_TARANIS(board) ? 10 : 6); return (IS_HORUS_OR_TARANIS(board) ? 10 : 6);
case GvarsName: case GvarsName:
return (IS_9X(board) ? 0 : 3); return 3;
case GvarsInCS: case GvarsInCS:
case HasFAIMode: case HasFAIMode:
return 1; return 1;
case GvarsAreNamed: case GvarsAreNamed:
case GvarsFlightModes: case GvarsFlightModes:
return ((IS_ARM(board) || IS_2560(board)) ? 1 : 0); return 1;
case Mixes: case Mixes:
return (IS_ARM(board) ? 64 : 32); return 64;
case OffsetWeight: case OffsetWeight:
return (IS_ARM(board) ? 500 : 245); return 500;
case Timers: case Timers:
return (IS_ARM(board) ? 3 : 2); return 3;
case TimersName: case TimersName:
if (HAS_LARGE_LCD(board)) if (HAS_LARGE_LCD(board))
return 8; return 8;
else if (IS_ARM(board)) else
return 3; return 3;
else
return 0;
case PermTimers: case PermTimers:
return (IS_2560(board) || IS_ARM(board)); return true;
case CustomFunctions: case CustomFunctions:
if (IS_ARM(board)) return 64;
return 64;
else if (IS_2560(board) || board == BOARD_9X_M128)
return 24;
else
return 16;
case SafetyChannelCustomFunction: case SafetyChannelCustomFunction:
return id.contains("nooverridech") ? 0 : 1; return id.contains("nooverridech") ? 0 : 1;
case LogicalSwitches: case LogicalSwitches:
if (IS_ARM(board)) return 64;
return 64;
else
return 12;
case CustomAndSwitches: case CustomAndSwitches:
if (IS_ARM(board)) return getCapability(LogicalSwitches);
return getCapability(LogicalSwitches);
else
return 15/*4bits*/- 9/*sw positions*/;
case LogicalSwitchesExt: case LogicalSwitchesExt:
return (IS_ARM(board) ? true : false); return true;
case RotaryEncoders: case RotaryEncoders:
if (board == BOARD_GRUVIN9X)
return 2;
else if (IS_SKY9X(board))
return 1;
else
return 0; return 0;
case Outputs: case Outputs:
return (IS_ARM(board) ? 32 : 16); return 32;
case NumCurvePoints: case NumCurvePoints:
return (IS_ARM(board) ? 512 : 104); return 512;
case VoicesAsNumbers: case VoicesAsNumbers:
return (IS_ARM(board) ? 0 : 1); return 0;
case VoicesMaxLength: case VoicesMaxLength:
return (IS_ARM(board) ? (IS_TARANIS_X9(board) ? 8 : 6) : 0); return (IS_TARANIS_X9(board) ? 8 : 6);
case MultiLangVoice: case MultiLangVoice:
return (IS_ARM(board) ? 1 : 0); return 1;
case SoundPitch: case SoundPitch:
return 1; return 1;
case Haptic: case Haptic:
@ -571,7 +518,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
else else
return 0; return 0;
case MaxVolume: case MaxVolume:
return (IS_ARM(board) ? 23 : 7); return 23;
case MaxContrast: case MaxContrast:
if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board)) if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board))
return 30; return 30;
@ -583,7 +530,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
else else
return 10; return 10;
case HasSoundMixer: case HasSoundMixer:
return (IS_ARM(board) ? 1 : 0); return 1;
case ExtraInputs: case ExtraInputs:
return 1; return 1;
case TrimsRange: case TrimsRange:
@ -593,29 +540,26 @@ int OpenTxFirmware::getCapability(::Capability capability)
case Simulation: case Simulation:
return 1; return 1;
case NumCurves: case NumCurves:
return (HAS_LARGE_LCD(board) ? 32 : (IS_ARM(board) ? 16 : 8)); return 32;
case HasMixerNames: case HasMixerNames:
return (IS_ARM(board) ? (IS_TARANIS_X9(board) ? 8 : 6) : false); return (IS_TARANIS_X9(board) ? 8 : 6);
case HasExpoNames: case HasExpoNames:
return (IS_ARM(board) ? (IS_TARANIS_X9(board) ? 8 : 6) : false); return (IS_TARANIS_X9(board) ? 8 : 6);
case HasNoExpo: case HasNoExpo:
return (IS_HORUS_OR_TARANIS(board) ? false : true); return (IS_HORUS_OR_TARANIS(board) ? false : true);
case ChannelsName: case ChannelsName:
return (IS_ARM(board) ? (HAS_LARGE_LCD(board) ? 6 : 4) : 0); return (HAS_LARGE_LCD(board) ? 6 : 4);
case HasCvNames: case HasCvNames:
return (IS_ARM(board) ? 1 : 0); return 1;
case Telemetry: case Telemetry:
if (IS_2560(board) || IS_ARM(board) || id.contains("frsky") || id.contains("telemetrez")) return 1;
return TM_HASTELEMETRY | TM_HASOFFSET | TM_HASWSHH;
else
return 0;
case TelemetryBars: case TelemetryBars:
return 1; return 1;
case TelemetryCustomScreens: case TelemetryCustomScreens:
if (IS_FAMILY_HORUS_OR_T16(board)) if (IS_FAMILY_HORUS_OR_T16(board))
return 0; return 0;
else else
return IS_ARM(board) ? 4 : 2; return 4;
case TelemetryCustomScreensBars: case TelemetryCustomScreensBars:
return (getCapability(TelemetryCustomScreens) ? 4 : 0); return (getCapability(TelemetryCustomScreens) ? 4 : 0);
case TelemetryCustomScreensLines: case TelemetryCustomScreensLines:
@ -627,7 +571,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case TelemetryUnits: case TelemetryUnits:
return 0; return 0;
case TelemetryMaxMultiplier: case TelemetryMaxMultiplier:
return (IS_ARM(board) ? 32 : 8); return 32;
case PPMCenter: case PPMCenter:
return (IS_HORUS_OR_TARANIS(board) ? 500 : (id.contains("ppmca") ? 125 : 0)); return (IS_HORUS_OR_TARANIS(board) ? 500 : (id.contains("ppmca") ? 125 : 0));
case PPMUnitMicroseconds: case PPMUnitMicroseconds:
@ -639,35 +583,35 @@ int OpenTxFirmware::getCapability(::Capability capability)
case HasVario: case HasVario:
return 1; return 1;
case HasVarioSink: case HasVarioSink:
return ((IS_2560(board) || IS_ARM(board)) ? true : false); return true;
case HasFailsafe: case HasFailsafe:
return (IS_ARM(board) ? 32 : 0); return 32;
case NumModules: case NumModules:
return (IS_ARM(board) ? 2 : 1); return 2;
case NumFirstUsableModule: case NumFirstUsableModule:
return (IS_JUMPER_T12(board) ? 1 : 0); return (IS_JUMPER_T12(board) && !id.contains("internalmulti") ? 1 : 0);
case HasModuleR9MFlex: case HasModuleR9MFlex:
return id.contains("flexr9m"); return id.contains("flexr9m");
case HasModuleR9MMini: case HasModuleR9MMini:
return IS_TARANIS_XLITE(board) && !id.contains("stdr9m"); return IS_TARANIS_XLITE(board) && !id.contains("stdr9m");
case HasPPMStart: case HasPPMStart:
return (IS_ARM(board) ? true : false); return true;
case HastxCurrentCalibration: case HastxCurrentCalibration:
return (IS_SKY9X(board) ? true : false); return (IS_SKY9X(board) ? true : false);
case HasVolume: case HasVolume:
return (IS_ARM(board) ? true : false); return true;
case HasBrightness: case HasBrightness:
return (IS_ARM(board) ? true : false); return true;
case PerModelTimers: case PerModelTimers:
return 1; return 1;
case SlowScale: case SlowScale:
return (IS_ARM(board) ? 10 : 2); return 10;
case SlowRange: case SlowRange:
return (IS_ARM(board) ? 250 : 15); return 250;
case CSFunc: case CSFunc:
return 18; return 18;
case HasSDLogs: case HasSDLogs:
return ((IS_2560(board) || IS_ARM(board)) ? true : false); return true;
case LcdWidth: case LcdWidth:
if (IS_FAMILY_HORUS_OR_T16(board)) if (IS_FAMILY_HORUS_OR_T16(board))
return 480; return 480;
@ -694,19 +638,19 @@ int OpenTxFirmware::getCapability(::Capability capability)
case GetThrSwitch: case GetThrSwitch:
return (IS_HORUS_OR_TARANIS(board) ? SWITCH_SF1 : SWITCH_THR); return (IS_HORUS_OR_TARANIS(board) ? SWITCH_SF1 : SWITCH_THR);
case HasDisplayText: case HasDisplayText:
return IS_ARM(board) ? 1 : 0; return 1;
case HasTopLcd: case HasTopLcd:
return IS_TARANIS_X9E(board) ? 1 : 0; return IS_TARANIS_X9E(board) ? 1 : 0;
case GlobalFunctions: case GlobalFunctions:
return IS_ARM(board) ? 64 : 0; return 64;
case VirtualInputs: case VirtualInputs:
return IS_ARM(board) ? 32 : 0; return 32;
case InputsLength: case InputsLength:
return HAS_LARGE_LCD(board) ? 4 : 3; return HAS_LARGE_LCD(board) ? 4 : 3;
case TrainerInputs: case TrainerInputs:
return IS_ARM(board) ? 16 : 8; return 16;
case RtcTime: case RtcTime:
return IS_ARM(board) || IS_2560(board) ? 1 : 0; return 1;
case LuaScripts: case LuaScripts:
return IS_HORUS_OR_TARANIS(board) && id.contains("lua") ? 7 : 0; return IS_HORUS_OR_TARANIS(board) && id.contains("lua") ? 7 : 0;
case LuaInputsPerScript: case LuaInputsPerScript:
@ -715,17 +659,13 @@ int OpenTxFirmware::getCapability(::Capability capability)
return IS_HORUS_OR_TARANIS(board) ? 6 : 0; return IS_HORUS_OR_TARANIS(board) ? 6 : 0;
case LimitsPer1000: case LimitsPer1000:
case EnhancedCurves: case EnhancedCurves:
return IS_ARM(board); return 1;
case HasFasOffset: case HasFasOffset:
return (IS_STOCK(board) ? false : true); return true;
case HasMahPersistent: case HasMahPersistent:
return (IS_ARM(board) ? true : false); return true;
case SimulatorVariant: case SimulatorVariant:
if (board == BOARD_9X_M64) if (IS_TARANIS_X9E(board))
return SIMU_STOCK_VARIANTS;
else if (board == BOARD_9X_M128)
return SIMU_M128_VARIANTS;
else if (IS_TARANIS_X9E(board))
return TARANIS_X9E_VARIANT; return TARANIS_X9E_VARIANT;
else if (IS_TARANIS_X9LITES(board)) else if (IS_TARANIS_X9LITES(board))
return TARANIS_X9LITES_VARIANT; return TARANIS_X9LITES_VARIANT;
@ -744,7 +684,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case MavlinkTelemetry: case MavlinkTelemetry:
return id.contains("mavlink") ? 1 : 0; return id.contains("mavlink") ? 1 : 0;
case SportTelemetry: case SportTelemetry:
return IS_ARM(board) ? 1 : 0; return 1;
case HasInputDiff: case HasInputDiff:
case HasMixerExpo: case HasMixerExpo:
return (IS_HORUS_OR_TARANIS(board) ? true : false); return (IS_HORUS_OR_TARANIS(board) ? true : false);
@ -777,10 +717,8 @@ QTime OpenTxFirmware::getMaxTimerStart()
{ {
if (IS_HORUS_OR_TARANIS(board)) if (IS_HORUS_OR_TARANIS(board))
return QTime(23, 59, 59); return QTime(23, 59, 59);
else if (IS_ARM(board))
return QTime(8, 59, 59);
else else
return QTime(0, 59, 59); return QTime(8, 59, 59);
} }
bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port) bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
@ -793,16 +731,14 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
return true; return true;
case PULSES_PXX_XJT_X16: case PULSES_PXX_XJT_X16:
case PULSES_PXX_XJT_LR12: 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: case PULSES_PXX_XJT_D8:
return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")) && !IS_FAMILY_T16(board); return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")) && !IS_FAMILY_T16(board) && !IS_JUMPER_T12(board);
case PULSES_PPM:
return id.contains("internalppm");
case PULSES_ACCESS_ISRM: case PULSES_ACCESS_ISRM:
case PULSES_ACCST_ISRM_D16: case PULSES_ACCST_ISRM_D16:
return IS_ACCESS_RADIO(board, id); return IS_ACCESS_RADIO(board, id);
case PULSES_MULTIMODULE: case PULSES_MULTIMODULE:
return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board); return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board) || IS_JUMPER_T18(board);
default: default:
return false; return false;
} }
@ -823,9 +759,11 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
case PULSES_SBUS: case PULSES_SBUS:
case PULSES_MULTIMODULE: case PULSES_MULTIMODULE:
case PULSES_CROSSFIRE: case PULSES_CROSSFIRE:
case PULSES_AFHDS3:
case PULSES_GHOST:
return true; return true;
case PULSES_ACCESS_R9M: 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_PXX_R9M_LITE:
case PULSES_ACCESS_R9M_LITE: case PULSES_ACCESS_R9M_LITE:
case PULSES_ACCESS_R9M_LITE_PRO: case PULSES_ACCESS_R9M_LITE_PRO:
@ -946,14 +884,9 @@ EepromLoadErrors OpenTxEepromInterface::checkVersion(unsigned int version)
// M128 revert because too much RAM used! // M128 revert because too much RAM used!
case 216: case 216:
// A lot of things (first github release) // A lot of things (first github release)
if (IS_2560(board) || IS_M128(board)) {
return OLD_VERSION;
}
case 217: case 217:
// 3 logical switches removed on M128 / gruvin9x boards // 3 logical switches removed on M128 / gruvin9x boards
if (IS_ARM(board)) {
return OLD_VERSION; return OLD_VERSION;
}
case 218: case 218:
// ACCESS // ACCESS
// switches add for X7/X10/X12S // 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 OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int variant)
{ {
bool variantError = false; bool variantError = false;
if (board == BOARD_9X_M128 && !(variant & M128_VARIANT)) { if (IS_TARANIS_X9E(board)) {
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 (variant != TARANIS_X9E_VARIANT) { if (variant != TARANIS_X9E_VARIANT) {
variantError = true; variantError = true;
} }
@ -1079,9 +998,6 @@ unsigned long OpenTxEepromInterface::loadBackup(RadioData &radioData, const uint
case 0x32: case 0x32:
backupBoard = BOARD_SKY9X; backupBoard = BOARD_SKY9X;
break; break;
case 0x31:
backupBoard = BOARD_GRUVIN9X;
break;
default: default:
dbg << " unknown board"; dbg << " unknown board";
errors.set(UNKNOWN_BOARD); errors.set(UNKNOWN_BOARD);
@ -1184,19 +1100,25 @@ void addOpenTxCommonOptions(OpenTxFirmware * firmware)
enum RfOptions { enum RfOptions {
NONE = 0, NONE = 0,
EU = 1 << 0, EU = 1 << 0,
FLEX = 1 << 1 FLEX = 1 << 1,
AFHDS3 = 1 << 2
}; };
void addOpenTxRfOptions(OpenTxFirmware * firmware, uint8_t options) 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_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")); 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}); firmware->addOptionsGroup({opt_eu, opt_fl});
else if (options == EU) else if ((options & EU) != 0)
firmware->addOption(opt_eu); firmware->addOption(opt_eu);
else if (options == FLEX) else if ((options & FLEX) != 0)
firmware->addOption(opt_fl); firmware->addOption(opt_fl);
if ((options & AFHDS3) != 0)
firmware->addOption(opt_afhds3);
} }
void addOpenTxFontOptions(OpenTxFirmware * firmware) void addOpenTxFontOptions(OpenTxFirmware * firmware)
@ -1245,7 +1167,7 @@ void registerOpenTxFirmwares()
firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)")); firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)"));
addOpenTxTaranisOptions(firmware); addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX); addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3);
/* FrSky Taranis X9D+ 2019 board */ /* FrSky Taranis X9D+ 2019 board */
firmware = new OpenTxFirmware("opentx-x9d+2019", Firmware::tr("FrSky Taranis X9D+ 2019"), BOARD_TARANIS_X9DP_2019); 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")); firmware->addOption("haptic", Firmware::tr("Haptic module installed"));
addOpenTxTaranisOptions(firmware); addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX); addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3);
/* FrSky Taranis X9E board */ /* FrSky Taranis X9E board */
firmware = new OpenTxFirmware("opentx-x9e", Firmware::tr("FrSky Taranis X9E"), BOARD_TARANIS_X9E); 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)")); firmware->addOption("horussticks", Firmware::tr("Horus gimbals installed (Hall sensors)"));
addOpenTxTaranisOptions(firmware); addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX); addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3);
/* FrSky X9-Lite board */ /* FrSky X9-Lite board */
firmware = new OpenTxFirmware("opentx-x9lite", Firmware::tr("FrSky Taranis X9-Lite"), BOARD_TARANIS_X9LITE); firmware = new OpenTxFirmware("opentx-x9lite", Firmware::tr("FrSky Taranis X9-Lite"), BOARD_TARANIS_X9LITE);
addOpenTxTaranisOptions(firmware); addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX); addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* FrSky X9-LiteS board */ /* FrSky X9-LiteS board */
firmware = new OpenTxFirmware("opentx-x9lites", Firmware::tr("FrSky Taranis X9-Lite S"), BOARD_TARANIS_X9LITES); firmware = new OpenTxFirmware("opentx-x9lites", Firmware::tr("FrSky Taranis X9-Lite S"), BOARD_TARANIS_X9LITES);
addOpenTxTaranisOptions(firmware); addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX); addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* FrSky X7 board */ /* FrSky X7 board */
firmware = new OpenTxFirmware("opentx-x7", Firmware::tr("FrSky Taranis X7 / X7S"), BOARD_TARANIS_X7); 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); firmware = new OpenTxFirmware("opentx-xlites", Firmware::tr("FrSky Taranis X-Lite S/PRO"), BOARD_TARANIS_XLITES);
addOpenTxTaranisOptions(firmware); addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX); addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* FrSky X-Lite board */ /* FrSky X-Lite board */
firmware = new OpenTxFirmware("opentx-xlite", Firmware::tr("FrSky Taranis X-Lite"), BOARD_TARANIS_XLITE); 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")); firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
addOpenTxFontOptions(firmware); addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX); addOpenTxRfOptions(firmware, FLEX + AFHDS3);
/* Jumper T16 board */ /* Jumper T16 board */
firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16); firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16);
@ -1347,7 +1269,7 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
/* Radiomaster TX16S board */ /* 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); addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX); addOpenTxRfOptions(firmware, FLEX);
static const Firmware::Option opt_bt("bluetooth", Firmware::tr("Support for bluetooth module")); 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}); firmware->addOptionsGroup({opt_bt, opt_internal_gps});
registerOpenTxFirmware(firmware); 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 */ /* 9XR-Pro */
firmware = new OpenTxFirmware("opentx-9xrpro", Firmware::tr("Turnigy 9XR-PRO"), BOARD_9XRPRO); firmware = new OpenTxFirmware("opentx-9xrpro", Firmware::tr("Turnigy 9XR-PRO"), BOARD_9XRPRO);
addOpenTxArm9xOptions(firmware, false); addOpenTxArm9xOptions(firmware, false);
@ -1372,14 +1301,6 @@ void registerOpenTxFirmwares()
addOpenTxArm9xOptions(firmware); addOpenTxArm9xOptions(firmware);
registerOpenTxFirmware(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::setDefaultVariant(Firmware::getFirmwareForId("opentx-x9d+"));
Firmware::setCurrentVariant(Firmware::getDefaultVariant()); Firmware::setCurrentVariant(Firmware::getDefaultVariant());
} }

View file

@ -32,10 +32,7 @@
float RawSourceRange::getValue(int value) float RawSourceRange::getValue(int value)
{ {
if (IS_ARM(getCurrentBoard())) return float(value) * step;
return float(value) * step;
else
return min + float(value) * step;
} }
@ -48,11 +45,10 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting
RawSourceRange result; RawSourceRange result;
Firmware * firmware = Firmware::getCurrentVariant(); Firmware * firmware = Firmware::getCurrentVariant();
Board::Type board = firmware->getBoard();
switch (type) { switch (type) {
case SOURCE_TYPE_TELEMETRY: case SOURCE_TYPE_TELEMETRY:
if (IS_ARM(board)) { {
div_t qr = div(index, 3); div_t qr = div(index, 3);
const SensorData & sensor = model->sensorData[qr.quot]; const SensorData & sensor = model->sensorData[qr.quot];
if (sensor.prec == 2) if (sensor.prec == 2)
@ -65,192 +61,8 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting
result.max = +30000 * result.step; result.max = +30000 * result.step;
result.decimals = sensor.prec; result.decimals = sensor.prec;
result.unit = sensor.unitString(); 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: case SOURCE_TYPE_LUA_OUTPUT:
result.max = 30000; 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"), 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") }; static const QString rotary[] = { tr("REa"), tr("REb") };
if (index<0) { if (index<0) {
@ -411,10 +208,22 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
return LimitData().nameToString(index); return LimitData().nameToString(index);
case SOURCE_TYPE_SPECIAL: 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: case SOURCE_TYPE_TELEMETRY:
if (IS_ARM(board)) { {
div_t qr = div(index, 3); div_t qr = div(index, 3);
if (model) if (model)
result = model->sensorData[qr.quot].nameToString(qr.quot); 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 ? "-" : "+"); result += (qr.rem == 1 ? "-" : "+");
return result; return result;
} }
else {
return CHECK_IN_ARRAY(telemetry, index);
}
case SOURCE_TYPE_GVAR: case SOURCE_TYPE_GVAR:
if (model) if (model)
@ -486,13 +292,7 @@ bool RawSource::isSlider(int * sliderIndex, Board::Type board) const
bool RawSource::isTimeBased(Board::Type board) const bool RawSource::isTimeBased(Board::Type board) const
{ {
if (board == Board::BOARD_UNKNOWN) return (type == SOURCE_TYPE_SPECIAL && index > 0);
board = getCurrentBoard();
if (IS_ARM(board))
return (type == SOURCE_TYPE_SPECIAL && index > 0);
else
return (type==SOURCE_TYPE_TELEMETRY && (index==TELEMETRY_SOURCE_TX_TIME || index==TELEMETRY_SOURCE_TIMER1 || index==TELEMETRY_SOURCE_TIMER2 || index==TELEMETRY_SOURCE_TIMER3));
} }
bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings * const gs, Board::Type board) const 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; return false;
if (type == SOURCE_TYPE_TELEMETRY) { 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; 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)); RadioDataConversionState::LogField oldData(index, toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType));
if (type == SOURCE_TYPE_STICK) { if (type == SOURCE_TYPE_STICK) {
if (cstate.toBoard.getCapability(Board::Sliders)) { QStringList fromStickList(getStickList(cstate.fromBoard));
if (index >= cstate.fromBoard.getCapability(Board::Sticks) + cstate.fromBoard.getCapability(Board::Pots)) { QStringList toStickList(getStickList(cstate.toBoard));
// 1st slider alignment index = toStickList.indexOf(fromStickList.at(oldData.id));
index += cstate.toBoard.getCapability(Board::Pots) - cstate.fromBoard.getCapability(Board::Pots); // index set to -1 if no match found
} // perform forced mapping
}
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
if (type == SOURCE_TYPE_SWITCH) { if (type == SOURCE_TYPE_SWITCH) {
// SWI to SWR don't exist on !X9E board QStringList fromSwitchList(getSwitchList(cstate.fromBoard));
if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) { QStringList toSwitchList(getSwitchList(cstate.toBoard));
if (index >= 8) { index = toSwitchList.indexOf(fromSwitchList.at(oldData.id));
index = index % 8; // index set to -1 if no match found
evt = RadioDataConversionState::EVT_CVRT; // 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) // 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); cstate.setInvalid(oldData);
index = -1; // TODO: better way to flag invalid sources? // no source is safer than an invalid one
type = MAX_SOURCE_TYPE; clear();
} }
else if (evt == RadioDataConversionState::EVT_CVRT) { else if (evt == RadioDataConversionState::EVT_CVRT) {
cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toModel(), cstate.toGS(), cstate.toType))); cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toModel(), cstate.toGS(), cstate.toType)));
@ -671,3 +389,24 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
return *this; 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;
}

View file

@ -159,10 +159,6 @@ enum TelemetrySource {
TELEMETRY_SOURCE_RESERVE = -1 TELEMETRY_SOURCE_RESERVE = -1
}; };
#define TM_HASTELEMETRY 0x01
#define TM_HASOFFSET 0x02
#define TM_HASWSHH 0x04
enum RawSourceType { enum RawSourceType {
SOURCE_TYPE_NONE, SOURCE_TYPE_NONE,
SOURCE_TYPE_VIRTUAL_INPUT, 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 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; } bool isSet() const { return type != SOURCE_TYPE_NONE || index != 0; }
void clear() { 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 { bool operator == ( const RawSource & other) const {
return (this->type == other.type) && (this->index == other.index); return (this->type == other.type) && (this->index == other.index);

View file

@ -184,77 +184,39 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
RadioDataConversionState::EventType evt = RadioDataConversionState::EVT_NONE; RadioDataConversionState::EventType evt = RadioDataConversionState::EVT_NONE;
RadioDataConversionState::LogField oldData(index, toString(cstate.fromType, cstate.fromGS(), cstate.fromModel())); RadioDataConversionState::LogField oldData(index, toString(cstate.fromType, cstate.fromGS(), cstate.fromModel()));
int newIdx = 0;
if (type == SWITCH_TYPE_SWITCH) { if (type == SWITCH_TYPE_SWITCH) {
int srcIdx = div(abs(index)-1, 3).quot; // raw source index div_t swtch = div(abs(index) - 1, 3); // rawsource index
int delta = 0; QStringList fromSwitchList(getSwitchList(cstate.fromBoard));
QStringList toSwitchList(getSwitchList(cstate.toBoard));
// SWI to SWR don't exist on !X9E board // set to -1 if no match found
if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) { newIdx = toSwitchList.indexOf(fromSwitchList.at(swtch.quot));
if (srcIdx > 7) { // perform forced mapping
index %= 24; if (newIdx < 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
} newIdx = toSwitchList.indexOf("SD");
if (newIdx >= 0)
// 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)
evt = RadioDataConversionState::EVT_CVRT; evt = RadioDataConversionState::EVT_CVRT;
} }
else if (srcIdx == 6) { else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
delta = 9; // SG to SD // No SE and SG on T12 board
evt = RadioDataConversionState::EVT_CVRT; newIdx = toSwitchList.indexOf("SD");
} if (newIdx >= 0)
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)
evt = RadioDataConversionState::EVT_CVRT; 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) { if (newIdx >= 0)
delta = -delta; // invert for !switch index = (newIdx * 3 + 1 + swtch.rem) * (index < 0 ? -1 : 1);
}
index -= delta;
} // SWITCH_TYPE_SWITCH } // SWITCH_TYPE_SWITCH
// final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted) // 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); 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) { else if (evt == RadioDataConversionState::EVT_CVRT) {
cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toType, cstate.toGS(), cstate.toModel()))); cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toType, cstate.toGS(), cstate.toModel())));
@ -266,3 +228,13 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
return *this; 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;
}

View file

@ -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 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; } bool isSet() const { return type != SWITCH_TYPE_NONE || index != 0; }
void clear() { 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 { bool operator== ( const RawSwitch& other) const {
return (this->type == other.type) && (this->index == other.index); return (this->type == other.type) && (this->index == other.index);

View file

@ -84,6 +84,12 @@ QString SensorData::unitString() const
return tr("V"); return tr("V");
case UNIT_MILLILITERS_PER_MINUTE: case UNIT_MILLILITERS_PER_MINUTE:
return tr("ml/minute"); return tr("ml/minute");
case UNIT_HERZ:
return tr("Hertz");
case UNIT_MS:
return tr("mS");
case UNIT_US:
return tr("uS");
default: default:
return ""; return "";
} }
@ -98,7 +104,7 @@ QString SensorData::getOrigin(const ModelData * model) const
{ {
if (type != TELEM_TYPE_CUSTOM || !id) if (type != TELEM_TYPE_CUSTOM || !id)
return QString(); return QString();
const ModuleData & module = model->moduleData[moduleIdx]; const ModuleData & module = model->moduleData[moduleIdx];
if (module.isPxx2Module() && rxIdx <= 2 && module.access.receivers & (1 << rxIdx)) { if (module.isPxx2Module() && rxIdx <= 2 && module.access.receivers & (1 << rxIdx)) {
return QString(module.access.receiverName[rxIdx]); return QString(module.access.receiverName[rxIdx]);
@ -107,3 +113,8 @@ QString SensorData::getOrigin(const ModelData * model) const
return QString(); 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);
}

View file

@ -24,6 +24,7 @@
#include <QtCore> #include <QtCore>
constexpr int CPN_MAX_SENSORS = 60; constexpr int CPN_MAX_SENSORS = 60;
constexpr int SENSOR_LABEL_LEN = 4;
class ModelData; class ModelData;
@ -94,10 +95,10 @@ class SensorData {
UNIT_MILLILITERS, UNIT_MILLILITERS,
UNIT_FLOZ, UNIT_FLOZ,
UNIT_MILLILITERS_PER_MINUTE, UNIT_MILLILITERS_PER_MINUTE,
UNIT_MAX = UNIT_MILLILITERS_PER_MINUTE, UNIT_HERZ,
UNIT_SPARE1, UNIT_MS,
UNIT_SPARE2, UNIT_US,
UNIT_SPARE3, UNIT_MAX = UNIT_US,
UNIT_SPARE4, UNIT_SPARE4,
UNIT_SPARE5, UNIT_SPARE5,
UNIT_SPARE6, UNIT_SPARE6,
@ -133,7 +134,7 @@ class SensorData {
unsigned int moduleIdx; unsigned int moduleIdx;
unsigned int persistentValue; unsigned int persistentValue;
unsigned int formula; unsigned int formula;
char label[4+1]; char label[SENSOR_LABEL_LEN + 1];
unsigned int unit; unsigned int unit;
unsigned int prec; unsigned int prec;
bool autoOffset; bool autoOffset;
@ -166,6 +167,7 @@ class SensorData {
QString nameToString(int index) const; QString nameToString(int index) const;
QString getOrigin(const ModelData* model) const; QString getOrigin(const ModelData* model) const;
void clear() { memset(this, 0, sizeof(SensorData)); } void clear() { memset(this, 0, sizeof(SensorData)); }
bool isEmpty() const;
}; };
#endif // SENSORDATA_H #endif // SENSORDATA_H

View file

@ -48,9 +48,6 @@ RawSourceRange FrSkyChannelData::getRange() const
void FrSkyScreenData::clear() void FrSkyScreenData::clear()
{ {
memset(reinterpret_cast<void *>(this), 0, sizeof(FrSkyScreenData)); memset(reinterpret_cast<void *>(this), 0, sizeof(FrSkyScreenData));
if (!IS_ARM(getCurrentBoard())) {
type = TELEMETRY_SCREEN_NUMBERS;
}
} }
void FrSkyData::clear() void FrSkyData::clear()

View file

@ -275,11 +275,12 @@ void FlashFirmwareDialog::startFlash(const QString &filename)
ProgressDialog progressDialog(this, tr("Write Firmware to Radio"), CompanionIcon("write_flash.png")); ProgressDialog progressDialog(this, tr("Write Firmware to Radio"), CompanionIcon("write_flash.png"));
// check hardware compatibility if requested // check hardware compatibility if requested
bool checkPassed = true;
if (g.checkHardwareCompatibility()) { if (g.checkHardwareCompatibility()) {
QString tempFirmware = generateProcessUniqueTempFileName("flash-check.bin"); QString tempFirmware = generateProcessUniqueTempFileName("flash-check.bin");
if (!readFirmware(tempFirmware, progressDialog.progress())) { if (!readFirmware(tempFirmware, progressDialog.progress())) {
QMessageBox::warning(this, tr("Firmware check failed"), tr("Could not check firmware from radio")); QMessageBox::warning(this, tr("Firmware check failed"), tr("Could not check firmware from radio"));
return; checkPassed = false;
} }
FirmwareInterface previousFirmware(tempFirmware); FirmwareInterface previousFirmware(tempFirmware);
qunlink(tempFirmware); qunlink(tempFirmware);
@ -291,41 +292,44 @@ void FlashFirmwareDialog::startFlash(const QString &filename)
qDebug() << "startFlash: removing temporary file" << filename; qDebug() << "startFlash: removing temporary file" << filename;
qunlink(filename); qunlink(filename);
} }
return; checkPassed = false;
} }
} }
// backup if requested if (checkPassed) {
bool result = true; // backup if requested
QString backupFilename; bool result = true;
QString backupPath; QString backupFilename;
if (backup) { QString backupPath;
backupPath = g.profile[g.id()].pBackupDir(); if (backup) {
if (backupPath.isEmpty()) { backupPath = g.profile[g.id()].pBackupDir();
backupPath=g.backupDir(); 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()); // flash
sleep(2); 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(); progressDialog.exec();
if (isTempFileName(filename)) { if (isTempFileName(filename)) {

View file

@ -56,9 +56,7 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir
} }
addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup")); 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 TrainerPanel(this, generalSettings, firmware), tr("Trainer"));
addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware")); addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware"));
addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration")); addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration"));

View file

@ -158,7 +158,7 @@ ui(new Ui::GeneralSetup)
ui->usbModeLabel->hide(); ui->usbModeLabel->hide();
ui->usbModeCB->hide(); ui->usbModeCB->hide();
} }
if (firmware->getCapability(HasSwitchableJack)) { if (firmware->getCapability(HasSwitchableJack)) {
ui->jackModeCB->setCurrentIndex(generalSettings.jackMode); ui->jackModeCB->setCurrentIndex(generalSettings.jackMode);
} }
@ -197,6 +197,12 @@ ui(new Ui::GeneralSetup)
ui->label_OFFBright->hide(); 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)) { if (!firmware->getCapability(SoundMod)) {
ui->soundModeCB->setDisabled(true); ui->soundModeCB->setDisabled(true);
ui->label_soundMode->hide(); ui->label_soundMode->hide();
@ -234,12 +240,7 @@ ui(new Ui::GeneralSetup)
ui->memwarnChkB->setChecked(!generalSettings.disableMemoryWarning); // Default is zero=checked ui->memwarnChkB->setChecked(!generalSettings.disableMemoryWarning); // Default is zero=checked
ui->alarmwarnChkB->setChecked(!generalSettings.disableAlarmWarning); // 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
ui->rssiPowerOffWarnChkB->setChecked(!generalSettings.disableRssiPoweroffAlarm); // Default is zero=checked
}
else {
ui->rssiPowerOffWarnChkB->hide();
}
if (IS_FAMILY_HORUS_OR_T16(firmware->getBoard())) { if (IS_FAMILY_HORUS_OR_T16(firmware->getBoard())) {
ui->splashScreenChkB->hide(); ui->splashScreenChkB->hide();
@ -265,7 +266,7 @@ ui(new Ui::GeneralSetup)
ui->pwrOnDelayLabel->hide(); ui->pwrOnDelayLabel->hide();
ui->pwrOnDelay->hide(); ui->pwrOnDelay->hide();
} }
setValues(); setValues();
lock = false; lock = false;
@ -302,13 +303,7 @@ ui(new Ui::GeneralSetup)
ui->backlightColor2_label->hide(); ui->backlightColor2_label->hide();
} }
if (IS_ARM(firmware->getBoard())) { ui->switchesDelay->setValue(10*(generalSettings.switchesDelay+15));
ui->switchesDelay->setValue(10*(generalSettings.switchesDelay+15));
}
else {
ui->switchesDelay->hide();
ui->switchesDelayLabel->hide();
}
ui->blAlarm_ChkB->setChecked(generalSettings.flashBeep); ui->blAlarm_ChkB->setChecked(generalSettings.flashBeep);
if (!firmware->getCapability(HasBatMeterRange)) { if (!firmware->getCapability(HasBatMeterRange)) {
@ -510,13 +505,13 @@ void GeneralSetupPanel::on_splashScreenDuration_currentIndexChanged(int index)
emit modified(); emit modified();
} }
void GeneralSetupPanel::on_pwrOnDelay_valueChanged() void GeneralSetupPanel::on_pwrOnDelay_valueChanged(int)
{ {
generalSettings.pwrOnSpeed = 2 - ui->pwrOnDelay->value(); generalSettings.pwrOnSpeed = 2 - ui->pwrOnDelay->value();
emit modified(); emit modified();
} }
void GeneralSetupPanel::on_pwrOffDelay_valueChanged() void GeneralSetupPanel::on_pwrOffDelay_valueChanged(int)
{ {
generalSettings.pwrOffSpeed = 2 - ui->pwrOffDelay->value(); generalSettings.pwrOffSpeed = 2 - ui->pwrOffDelay->value();
emit modified(); 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; generalSettings.switchesDelay = (ui->switchesDelay->value() / 10) - 15;
emit modified(); emit modified();

View file

@ -65,7 +65,7 @@ class GeneralSetupPanel : public GeneralPanel
void on_mavbaud_CB_currentIndexChanged(int index); void on_mavbaud_CB_currentIndexChanged(int index);
void on_voiceLang_CB_currentIndexChanged(int index); void on_voiceLang_CB_currentIndexChanged(int index);
void stickReverseEdited(); void stickReverseEdited();
void on_switchesDelay_valueChanged(); void on_switchesDelay_valueChanged(int);
void on_blAlarm_ChkB_stateChanged(); void on_blAlarm_ChkB_stateChanged();
void unlockSwitchEdited(); void unlockSwitchEdited();
void on_beepVolume_SL_valueChanged(); void on_beepVolume_SL_valueChanged();
@ -89,8 +89,8 @@ class GeneralSetupPanel : public GeneralPanel
void on_contrastSB_editingFinished(); void on_contrastSB_editingFinished();
void on_registrationId_editingFinished(); void on_registrationId_editingFinished();
void on_pwrOnDelay_valueChanged(); void on_pwrOnDelay_valueChanged(int);
void on_pwrOffDelay_valueChanged(); void on_pwrOffDelay_valueChanged(int);
private: private:
Ui::GeneralSetup *ui; Ui::GeneralSetup *ui;

View file

@ -554,348 +554,13 @@
</item> </item>
<item row="0" column="3"> <item row="0" column="3">
<layout class="QGridLayout" name="gridLayout_3" columnstretch="0,0"> <layout class="QGridLayout" name="gridLayout_3" columnstretch="0,0">
<item row="2" column="1">
<widget class="QSpinBox" name="volume_SB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>23</number>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QLabel" name="re_label">
<property name="text">
<string>RotEnc Navigation</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QCheckBox" name="blAlarm_ChkB">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="stickReverseLB">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Stick reverse</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QComboBox" name="backlightswCB">
<property name="toolTip">
<string/>
</property>
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>This is the switch selectrion for turning on the backlight (if installed).
</string>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="blAlarm_LB">
<property name="text">
<string>Backlight flash on alarm</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Backlight Auto OFF after</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Backlight Switch</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="varioR0_SB">
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>200</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>500</number>
</property>
</widget>
</item>
<item row="18" column="0"> <item row="18" column="0">
<widget class="QLabel" name="VoiceLang_label">
<property name="text">
<string>Voice Language</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="varioP0_SB">
<property name="suffix">
<string> Hz</string>
</property>
<property name="minimum">
<number>300</number>
</property>
<property name="maximum">
<number>1100</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>700</number>
</property>
</widget>
</item>
<item row="14" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="stickReverse1">
<property name="text">
<string notr="true">1</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="stickReverse2">
<property name="text">
<string notr="true">2</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="stickReverse3">
<property name="text">
<string notr="true">3</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="stickReverse4">
<property name="text">
<string notr="true">4</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="0">
<widget class="QLabel" name="varioR0_label">
<property name="text">
<string>Vario repeat at zero</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="varioP0_label">
<property name="text">
<string>Vario pitch at zero</string>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="label_faimode">
<property name="text">
<string>FAI Mode</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_OFFBright">
<property name="text">
<string>Backlight OFF Brightness</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QSpinBox" name="BLBright_SB">
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QSpinBox" name="backlightautoSB">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string/>
</property>
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds.</string>
</property>
<property name="suffix">
<string> sec</string>
</property>
<property name="maximum">
<number>600</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="speakerPitchSB">
<property name="toolTip">
<string/>
</property>
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;LCD Screen Contrast&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Values can be 20-45&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>20</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="varioPMax_SB">
<property name="suffix">
<string> Hz</string>
</property>
<property name="minimum">
<number>1300</number>
</property>
<property name="maximum">
<number>2900</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>1700</number>
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QLabel" name="label_timezone"> <widget class="QLabel" name="label_timezone">
<property name="text"> <property name="text">
<string>Timeshift from UTC</string> <string>Timeshift from UTC</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="1">
<widget class="QSpinBox" name="OFFBright_SB">
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QComboBox" name="countrycode_CB">
<item>
<property name="text">
<string>America</string>
</property>
</item>
<item>
<property name="text">
<string>Japan</string>
</property>
</item>
<item>
<property name="text">
<string>Europe</string>
</property>
</item>
</widget>
</item>
<item row="15" column="1">
<widget class="QCheckBox" name="faimode_CB">
<property name="toolTip">
<string>If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="soundModeCB">
<item>
<property name="text">
<string>Beeper</string>
</property>
</item>
<item>
<property name="text">
<string>Speaker</string>
</property>
</item>
<item>
<property name="text">
<string>BeeperVoice</string>
</property>
</item>
<item>
<property name="text">
<string>SpeakerVoice</string>
</property>
</item>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_BLBright">
<property name="text">
<string>Backlight Brightness</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2"> <item row="3" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_9" columnstretch="1,0,1,0"> <layout class="QGridLayout" name="gridLayout_9" columnstretch="1,0,1,0">
<item row="0" column="0"> <item row="0" column="0">
@ -992,24 +657,288 @@ p, li { white-space: pre-wrap; }
</item> </item>
</layout> </layout>
</item> </item>
<item row="12" column="0"> <item row="19" column="1">
<widget class="QLabel" name="backlightColor_label"> <widget class="QComboBox" name="voiceLang_CB"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_soundMode">
<property name="text"> <property name="text">
<string>Backlight color</string> <string>Sound Mode</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="9" column="1">
<widget class="QLabel" name="varioPMax_label"> <widget class="QCheckBox" name="blAlarm_ChkB">
<property name="text"> <property name="text">
<string>Vario pitch at max</string> <string/>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="15" column="1">
<widget class="QLabel" name="label_speakerPitch"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="stickReverse1">
<property name="text">
<string notr="true">1</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="stickReverse2">
<property name="text">
<string notr="true">2</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="stickReverse3">
<property name="text">
<string notr="true">3</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="stickReverse4">
<property name="text">
<string notr="true">4</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="7" column="1">
<widget class="QComboBox" name="backlightswCB">
<property name="toolTip">
<string/>
</property>
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>This is the switch selectrion for turning on the backlight (if installed).
</string>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="varioP0_SB">
<property name="suffix">
<string> Hz</string>
</property>
<property name="minimum">
<number>300</number>
</property>
<property name="maximum">
<number>1100</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>700</number>
</property>
</widget>
</item>
<item row="21" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="varioR0_SB">
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>200</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>500</number>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="stickReverseLB">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Speaker Pitch (spkr only)</string> <string>Stick reverse</string>
</property>
</widget>
</item>
<item row="20" column="1">
<widget class="QLineEdit" name="registrationId">
<property name="inputMask">
<string>nnnnnnNN</string>
</property>
<property name="maxLength">
<number>8</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="soundModeCB">
<item>
<property name="text">
<string>Beeper</string>
</property>
</item>
<item>
<property name="text">
<string>Speaker</string>
</property>
</item>
<item>
<property name="text">
<string>BeeperVoice</string>
</property>
</item>
<item>
<property name="text">
<string>SpeakerVoice</string>
</property>
</item>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_OFFBright">
<property name="text">
<string>Backlight OFF Brightness</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="volume_SB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>23</number>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="re_label">
<property name="text">
<string>RotEnc Navigation</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QSpinBox" name="OFFBright_SB">
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Backlight Switch</string>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QComboBox" name="countrycode_CB">
<item>
<property name="text">
<string>America</string>
</property>
</item>
<item>
<property name="text">
<string>Japan</string>
</property>
</item>
<item>
<property name="text">
<string>Europe</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="varioP0_label">
<property name="text">
<string>Vario pitch at zero</string>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QCheckBox" name="faimode_CB">
<property name="toolTip">
<string>If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Backlight Auto OFF after</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="varioPMax_SB">
<property name="suffix">
<string> Hz</string>
</property>
<property name="minimum">
<number>1300</number>
</property>
<property name="maximum">
<number>2900</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>1700</number>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QSpinBox" name="BLBright_SB">
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="label_faimode">
<property name="text">
<string>FAI Mode</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -1044,31 +973,56 @@ p, li { white-space: pre-wrap; }
</item> </item>
</layout> </layout>
</item> </item>
<item row="16" column="0"> <item row="12" column="0">
<widget class="QLabel" name="backlightColor_label">
<property name="text">
<string>Backlight color</string>
</property>
</widget>
</item>
<item row="20" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Owner Registration ID</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QSpinBox" name="backlightautoSB">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string/>
</property>
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>If this value is not 0, any keypress will turn on the backlight and turn it off after the specified number of seconds.</string>
</property>
<property name="suffix">
<string> sec</string>
</property>
<property name="maximum">
<number>600</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QLabel" name="countrycode_label"> <widget class="QLabel" name="countrycode_label">
<property name="text"> <property name="text">
<string>Country Code</string> <string>Country Code</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="1"> <item row="18" column="1">
<widget class="QComboBox" name="re_CB"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_soundMode">
<property name="text">
<string>Sound Mode</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_volume">
<property name="text">
<string>Speaker Volume</string>
</property>
</widget>
</item>
<item row="17" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QSpinBox" name="timezoneSB"> <widget class="QSpinBox" name="timezoneSB">
@ -1098,36 +1052,96 @@ p, li { white-space: pre-wrap; }
</item> </item>
</layout> </layout>
</item> </item>
<item row="18" column="1"> <item row="10" column="0">
<widget class="QComboBox" name="voiceLang_CB"/> <widget class="QLabel" name="label_BLBright">
</item>
<item row="20" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="19" column="0">
<widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Owner Registration ID</string> <string>Backlight Brightness</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="19" column="1"> <item row="6" column="0">
<widget class="QLineEdit" name="registrationId"> <widget class="QLabel" name="varioR0_label">
<property name="inputMask"> <property name="text">
<string>nnnnnnNN</string> <string>Vario repeat at zero</string>
</property> </property>
<property name="maxLength"> </widget>
<number>8</number> </item>
<item row="19" column="0">
<widget class="QLabel" name="VoiceLang_label">
<property name="text">
<string>Voice Language</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="blAlarm_LB">
<property name="text">
<string>Backlight flash on alarm</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="varioPMax_label">
<property name="text">
<string>Vario pitch at max</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QComboBox" name="re_CB"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_speakerPitch">
<property name="text">
<string>Speaker Pitch (spkr only)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_volume">
<property name="text">
<string>Speaker Volume</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="speakerPitchSB">
<property name="toolTip">
<string/>
</property>
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;LCD Screen Contrast&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Values can be 20-45&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>20</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QLabel" name="label_KeysBl">
<property name="text">
<string>Keys Backlight</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QCheckBox" name="keysBl_ChkB">
<property name="text">
<string/>
</property> </property>
</widget> </widget>
</item> </item>

View file

@ -172,7 +172,7 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
ui->txCurrentCalibrationLabel->hide(); 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); ui->bluetoothMode->addItem(tr("OFF"), 0);
if (IS_TARANIS_X9E(board)) { if (IS_TARANIS_X9E(board)) {
ui->bluetoothMode->addItem(tr("Enabled"), 1); ui->bluetoothMode->addItem(tr("Enabled"), 1);

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

View file

@ -26,7 +26,6 @@
#include "apppreferencesdialog.h" #include "apppreferencesdialog.h"
#include "fwpreferencesdialog.h" #include "fwpreferencesdialog.h"
#include "firmwareinterface.h" #include "firmwareinterface.h"
#include "fusesdialog.h"
#include "downloaddialog.h" #include "downloaddialog.h"
#include "printdialog.h" #include "printdialog.h"
#include "version.h" #include "version.h"
@ -131,15 +130,9 @@ MainWindow::MainWindow():
else { else {
if (!g.previousVersion().isEmpty()) if (!g.previousVersion().isEmpty())
g.warningId(g.warningId() | AppMessages::MSG_UPGRADED); g.warningId(g.warningId() | AppMessages::MSG_UPGRADED);
if (g.promptProfile()) { if (g.promptProfile()) {
QTimer::singleShot(updateDelay, this, SLOT(chooseProfile())); // add an extra second to give mainwindow time to load chooseProfile();
updateDelay += 5000; // give user time to select profile before warnings
}
else {
if (checkProfileRadioExists(g.sessionId()))
QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates()));
else
g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
} }
} }
QTimer::singleShot(updateDelay, this, SLOT(displayWarnings())); QTimer::singleShot(updateDelay, this, SLOT(displayWarnings()));
@ -185,6 +178,11 @@ MainWindow::MainWindow():
if (printing) { if (printing) {
QTimer::singleShot(0, this, SLOT(autoClose())); 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() MainWindow::~MainWindow()
@ -939,10 +937,8 @@ void MainWindow::readEeprom()
QString tempFile; QString tempFile;
if (IS_FAMILY_HORUS_OR_T16(board)) if (IS_FAMILY_HORUS_OR_T16(board))
tempFile = generateProcessUniqueTempFileName("temp.otx"); tempFile = generateProcessUniqueTempFileName("temp.otx");
else if (IS_ARM(board))
tempFile = generateProcessUniqueTempFileName("temp.bin");
else else
tempFile = generateProcessUniqueTempFileName("temp.hex"); tempFile = generateProcessUniqueTempFileName("temp.bin");
qDebug() << "MainWindow::readEeprom(): using temp file: " << tempFile; qDebug() << "MainWindow::readEeprom(): using temp file: " << tempFile;
@ -1029,14 +1025,6 @@ void MainWindow::burnConfig()
void MainWindow::burnList() void MainWindow::burnList()
{ {
burnConfigDialog bcd(this); burnConfigDialog bcd(this);
bcd.listAvrdudeProgrammers();
}
void MainWindow::burnFuses()
{
FusesDialog *fd = new FusesDialog(this);
fd->exec();
delete fd;
} }
void MainWindow::compare() void MainWindow::compare()
@ -1065,7 +1053,7 @@ void MainWindow::about()
aboutStr.append("<br/><br/>"); aboutStr.append("<br/><br/>");
aboutStr.append(QString("Version %1, %2").arg(VERSION).arg(__DATE__)); aboutStr.append(QString("Version %1, %2").arg(VERSION).arg(__DATE__));
aboutStr.append("<br/><br/>"); aboutStr.append("<br/><br/>");
aboutStr.append(tr("Copyright OpenTX Team") + "<br/>&copy; 2011-2019<br/>"); aboutStr.append(tr("Copyright OpenTX Team") + QString("<br/>&copy; 2011-%1<br/>").arg(QString(__DATE__).right(4)));
QMessageBox msgBox(this); QMessageBox msgBox(this);
msgBox.setWindowIcon(CompanionIcon("information.png")); msgBox.setWindowIcon(CompanionIcon("information.png"));
msgBox.setWindowTitle(tr("About Companion")); msgBox.setWindowTitle(tr("About Companion"));
@ -1232,8 +1220,6 @@ void MainWindow::retranslateUi(bool showMsg)
trAct(changelogAct, tr("Release notes..."), tr("Show release notes")); trAct(changelogAct, tr("Release notes..."), tr("Show release notes"));
trAct(compareAct, tr("Compare Models..."), tr("Compare models")); trAct(compareAct, tr("Compare Models..."), tr("Compare models"));
trAct(editSplashAct, tr("Edit Radio Splash Image..."), tr("Edit the splash image of your Radio")); 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(readFlashAct, tr("Read Firmware from Radio"), tr("Read firmware from Radio"));
trAct(writeFlashAct, tr("Write Firmware to Radio"), tr("Write firmware to Radio")); trAct(writeFlashAct, tr("Write Firmware to Radio"), tr("Write firmware to Radio"));
trAct(sdsyncAct, tr("Synchronize SD"), tr("SD card synchronization")); trAct(sdsyncAct, tr("Synchronize SD"), tr("SD card synchronization"));
@ -1295,7 +1281,6 @@ void MainWindow::createActions()
editSplashAct = addAct("paintbrush.png", SLOT(customizeSplash())); editSplashAct = addAct("paintbrush.png", SLOT(customizeSplash()));
burnListAct = addAct("list.png", SLOT(burnList())); burnListAct = addAct("list.png", SLOT(burnList()));
burnFusesAct = addAct("fuses.png", SLOT(burnFuses()));
readFlashAct = addAct("read_flash.png", SLOT(readFlash())); readFlashAct = addAct("read_flash.png", SLOT(readFlash()));
writeFlashAct = addAct("write_flash.png", SLOT(writeFlash())); writeFlashAct = addAct("write_flash.png", SLOT(writeFlash()));
writeEepromAct = addAct("write_eeprom.png", SLOT(writeEeprom())); writeEepromAct = addAct("write_eeprom.png", SLOT(writeEeprom()));
@ -1400,10 +1385,6 @@ void MainWindow::createMenus()
burnMenu->addAction(readFlashAct); burnMenu->addAction(readFlashAct);
burnMenu->addSeparator(); burnMenu->addSeparator();
burnMenu->addSeparator(); burnMenu->addSeparator();
if (!IS_ARM(getCurrentBoard())) {
burnMenu->addAction(burnFusesAct);
burnMenu->addAction(burnListAct);
}
windowMenu = menuBar()->addMenu(""); windowMenu = menuBar()->addMenu("");
windowMenu->addAction(actTabbedWindows); windowMenu->addAction(actTabbedWindows);
@ -1823,10 +1804,8 @@ void MainWindow::chooseProfile()
connect(pcd, &ProfileChooserDialog::profileChanged, this, &MainWindow::loadProfileId); connect(pcd, &ProfileChooserDialog::profileChanged, this, &MainWindow::loadProfileId);
pcd->exec(); pcd->exec();
delete pcd; delete pcd;
// doi here as need to wait until dialog dismissed and current radio type is set
if (checkProfileRadioExists(g.sessionId())) if (!checkProfileRadioExists(g.sessionId()))
doAutoUpdates();
else
g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE); g.warningId(g.warningId() | AppMessages::MSG_NO_RADIO_TYPE);
} }
} }

View file

@ -111,7 +111,6 @@ class MainWindow : public QMainWindow
void readBackup(); void readBackup();
void burnConfig(); void burnConfig();
void burnList(); void burnList();
void burnFuses();
void contributors(); void contributors();
void sdsync(); void sdsync();
void changelog(); void changelog();
@ -210,7 +209,6 @@ class MainWindow : public QMainWindow
QAction *readEepromAct; QAction *readEepromAct;
QAction *burnConfigAct; QAction *burnConfigAct;
QAction *burnListAct; QAction *burnListAct;
QAction *burnFusesAct;
QAction *writeFlashAct; QAction *writeFlashAct;
QAction *readFlashAct; QAction *readFlashAct;
QAction *writeBUToRadioAct; QAction *writeBUToRadioAct;

View file

@ -42,7 +42,6 @@ set(modeledit_UIS
setup_timer.ui setup_timer.ui
setup_module.ui setup_module.ui
flightmode.ui flightmode.ui
telemetry_analog.ui
telemetry_customscreen.ui telemetry_customscreen.ui
telemetry_sensor.ui telemetry_sensor.ui
) )

View file

@ -45,7 +45,7 @@ LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row
spinbox->setSuffix("%"); spinbox->setSuffix("%");
} }
if (IS_ARM(board) || deflt == 0 /*it's the offset*/) { if (deflt == 0 /*it's the offset*/) {
spinbox->setDecimals(1); spinbox->setDecimals(1);
} }
else { else {
@ -349,8 +349,11 @@ void Channels::cmCopy()
void Channels::cmCut() 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(); cmCopy();
cmClear(); cmClear(false);
} }
void Channels::onCustomContextMenuRequested(QPoint pos) void Channels::onCustomContextMenuRequested(QPoint pos)
@ -412,10 +415,12 @@ void Channels::cmMoveDown()
swapData(selectedIndex, selectedIndex + 1); 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) if (prompt) {
return; 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->limitData[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);

View file

@ -75,7 +75,7 @@ class Channels : public ModelPanel
void cmMoveUp(); void cmMoveUp();
void cmMoveDown(); void cmMoveDown();
void cmInsert(); void cmInsert();
void cmClear(); void cmClear(bool prompt = true);
void cmClearAll(); void cmClearAll();
void onCustomContextMenuRequested(QPoint pos); void onCustomContextMenuRequested(QPoint pos);

View file

@ -699,10 +699,12 @@ bool Curves::moveUpAllowed() const
return selectedIndex > 0; 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) if (prompt) {
return; 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->curves[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
@ -734,8 +736,10 @@ void Curves::cmCopy()
void Curves::cmCut() 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(); cmCopy();
cmClear(); cmClear(false);
} }
void Curves::cmDelete() void Curves::cmDelete()

View file

@ -81,7 +81,7 @@ class Curves : public ModelPanel
void onPointSizeEdited(); void onPointSizeEdited();
void onNodeDelete(); void onNodeDelete();
void onCustomContextMenuRequested(QPoint pos); void onCustomContextMenuRequested(QPoint pos);
void cmClear(); void cmClear(bool prompt = true);
void cmClearAll(); void cmClearAll();
void cmCopy(); void cmCopy();
void cmCut(); void cmCut();

View file

@ -29,7 +29,7 @@ RepeatComboBox::RepeatComboBox(QWidget *parent, int & repeatParam):
QComboBox(parent), QComboBox(parent),
repeatParam(repeatParam) repeatParam(repeatParam)
{ {
unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10; unsigned int step = 1;
int value = repeatParam/step; int value = repeatParam/step;
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
@ -58,7 +58,7 @@ void RepeatComboBox::onIndexChanged(int index)
void RepeatComboBox::update() void RepeatComboBox::update()
{ {
unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10; unsigned int step = 1;
int value = repeatParam/step; int value = repeatParam/step;
if (step == 1) { if (step == 1) {
value++; 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 (cfn.adjustMode == FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) {
if (modified) if (modified)
cfn.param = fswtchParam[i]->value() * model->gvarData[gvidx].multiplierSet(); cfn.param = fswtchParam[i]->value() * model->gvarData[gvidx].multiplierSet();
if (IS_ARM(getCurrentBoard())) { fswtchParam[i]->setDecimals(model->gvarData[gvidx].prec);
fswtchParam[i]->setDecimals(model->gvarData[gvidx].prec); fswtchParam[i]->setSingleStep(model->gvarData[gvidx].multiplierGet());
fswtchParam[i]->setSingleStep(model->gvarData[gvidx].multiplierGet()); fswtchParam[i]->setSuffix(model->gvarData[gvidx].unitToString());
fswtchParam[i]->setSuffix(model->gvarData[gvidx].unitToString()); if (cfn.adjustMode==FUNC_ADJUST_GVAR_INCDEC) {
if (cfn.adjustMode==FUNC_ADJUST_GVAR_INCDEC) { double rng = abs(model->gvarData[gvidx].getMax() - model->gvarData[gvidx].getMin());
double rng = abs(model->gvarData[gvidx].getMax() - model->gvarData[gvidx].getMin()); rng *= model->gvarData[gvidx].multiplierGet();
rng *= model->gvarData[gvidx].multiplierGet(); fswtchParam[i]->setMinimum(-rng);
fswtchParam[i]->setMinimum(-rng); fswtchParam[i]->setMaximum(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());
} }
else { else {
fswtchParam[i]->setDecimals(0); fswtchParam[i]->setMinimum(model->gvarData[gvidx].getMinPrec());
fswtchParam[i]->setSingleStep(1); fswtchParam[i]->setMaximum(model->gvarData[gvidx].getMaxPrec());
fswtchParam[i]->setMinimum(-125);
fswtchParam[i]->setMaximum(125);
fswtchParam[i]->setValue(cfn.param);
} }
fswtchParam[i]->setValue(cfn.param * model->gvarData[gvidx].multiplierGet());
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM; widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM;
} }
else { else {
@ -471,7 +462,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
else if (func >= FuncSetFailsafeInternalModule && func <= FuncBindExternalModule) { else if (func >= FuncSetFailsafeInternalModule && func <= FuncBindExternalModule) {
widgetsMask |= CUSTOM_FUNCTION_ENABLE; widgetsMask |= CUSTOM_FUNCTION_ENABLE;
} }
else if (func == FuncVolume) { else if (func == FuncVolume || func == FuncBacklight) {
if (modified) if (modified)
cfn.param = fswtchParamT[i]->currentData().toInt(); cfn.param = fswtchParamT[i]->currentData().toInt();
populateFuncParamCB(fswtchParamT[i], func, cfn.param); populateFuncParamCB(fswtchParamT[i], func, cfn.param);
@ -563,12 +554,6 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
} }
Helpers::populateFileComboBox(fswtchParamArmT[i], scriptsSet, cfn.paramarm); 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 { else {
if (modified) if (modified)
cfn.param = fswtchParam[i]->value(); cfn.param = fswtchParam[i]->value();
@ -602,7 +587,7 @@ void CustomFunctionsPanel::update()
{ {
updateDataModels(); updateDataModels();
lock = true; lock = true;
for (int i=0; i<fswCapability; i++) { for (int i = 0; i < fswCapability; i++) {
refreshCustomFunction(i); refreshCustomFunction(i);
} }
lock = false; lock = false;
@ -620,13 +605,13 @@ void CustomFunctionsPanel::cmPaste()
void CustomFunctionsPanel::cmDelete() void CustomFunctionsPanel::cmDelete()
{ {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Special Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return; return;
memmove(&functions[selectedIndex], &functions[selectedIndex + 1], (CPN_MAX_SPECIAL_FUNCTIONS - (selectedIndex + 1)) * sizeof(CustomFunctionData)); memmove(&functions[selectedIndex], &functions[selectedIndex + 1], (CPN_MAX_SPECIAL_FUNCTIONS - (selectedIndex + 1)) * sizeof(CustomFunctionData));
functions[fswCapability - 1].clear(); functions[fswCapability - 1].clear();
for (int i = selectedIndex; i < (fswCapability - 1); i++) { for (int i = selectedIndex; i < fswCapability; i++) {
resetCBsAndRefresh(i); resetCBsAndRefresh(i);
} }
emit modified(); emit modified();
@ -643,8 +628,10 @@ void CustomFunctionsPanel::cmCopy()
void CustomFunctionsPanel::cmCut() void CustomFunctionsPanel::cmCut()
{ {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Special Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
cmCopy(); cmCopy();
cmClear(); cmClear(false);
} }
void CustomFunctionsPanel::onCustomContextMenuRequested(QPoint pos) void CustomFunctionsPanel::onCustomContextMenuRequested(QPoint pos)
@ -672,14 +659,13 @@ void CustomFunctionsPanel::onCustomContextMenuRequested(QPoint pos)
void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value) void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value)
{ {
b->clear(); b->clear();
for (unsigned int i=0; i<FuncCount; i++) { for (unsigned int i = 0; i < FuncCount; i++) {
if (((i>=FuncOverrideCH1 && i<=FuncOverrideCH32) && (!model || !firmware->getCapability(SafetyChannelCustomFunction))) || if (((i>=FuncOverrideCH1 && i<=FuncOverrideCH32) && (!model || !firmware->getCapability(SafetyChannelCustomFunction))) ||
((i==FuncVolume || i==FuncBackgroundMusic || i==FuncBackgroundMusicPause) && !firmware->getCapability(HasVolume)) || ((i==FuncVolume || i==FuncBackgroundMusic || i==FuncBackgroundMusicPause) && !firmware->getCapability(HasVolume)) ||
((i==FuncPlayScript && !IS_HORUS_OR_TARANIS(firmware->getBoard()))) || ((i==FuncPlayScript && !IS_HORUS_OR_TARANIS(firmware->getBoard()))) ||
((i==FuncPlayHaptic) && !firmware->getCapability(Haptic)) || ((i==FuncPlayHaptic) && !firmware->getCapability(Haptic)) ||
((i==FuncPlayBoth) && !firmware->getCapability(HasBeeper)) || ((i==FuncPlayBoth) && !firmware->getCapability(HasBeeper)) ||
((i==FuncLogs) && !firmware->getCapability(HasSDLogs)) || ((i==FuncLogs) && !firmware->getCapability(HasSDLogs)) ||
((i==FuncSetTimer1 || i==FuncSetTimer2) && !IS_ARM(firmware->getBoard())) ||
((i==FuncSetTimer3) && firmware->getCapability(Timers) < 3) || ((i==FuncSetTimer3) && firmware->getCapability(Timers) < 3) ||
((i==FuncScreenshot) && !IS_HORUS_OR_TARANIS(firmware->getBoard())) || ((i==FuncScreenshot) && !IS_HORUS_OR_TARANIS(firmware->getBoard())) ||
((i>=FuncRangeCheckInternalModule && i<=FuncBindExternalModule) && (!model || !firmware->getCapability(DangerousFunctions))) || ((i>=FuncRangeCheckInternalModule && i<=FuncBindExternalModule) && (!model || !firmware->getCapability(DangerousFunctions))) ||
@ -691,7 +677,7 @@ void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value)
else { else {
b->addItem(CustomFunctionData(AssignFunc(i)).funcToString(model), i); b->addItem(CustomFunctionData(AssignFunc(i)).funcToString(model), i);
if (i == value) { 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; QStringList qs;
b->setModel(new QStandardItemModel(b)); // clear combo box but not any shared item model b->setModel(new QStandardItemModel(b)); // clear combo box but not any shared item model
if (function==FuncPlaySound) { if (function == FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs); CustomFunctionData::populatePlaySoundParams(qs);
b->addItems(qs); b->addItems(qs);
b->setCurrentIndex(value); b->setCurrentIndex(value);
} }
else if (function==FuncPlayHaptic) { else if (function == FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs); CustomFunctionData::populateHapticParams(qs);
b->addItems(qs); b->addItems(qs);
b->setCurrentIndex(value); b->setCurrentIndex(value);
} }
else if (function==FuncReset) { else if (function == FuncReset) {
CustomFunctionData::populateResetParams(model, b, value); CustomFunctionData::populateResetParams(model, b, value);
} }
else if (function==FuncVolume) { else if (function == FuncVolume || function == FuncBacklight) {
b->setModel(rawSrcInputsItemModel); b->setModel(rawSrcInputsItemModel);
b->setCurrentIndex(b->findData(value)); b->setCurrentIndex(b->findData(value));
} }
else if (function==FuncPlayValue) { else if (function == FuncPlayValue) {
b->setModel(rawSrcAllItemModel); b->setModel(rawSrcAllItemModel);
b->setCurrentIndex(b->findData(value)); b->setCurrentIndex(b->findData(value));
} }
else if (function>=FuncAdjustGV1 && function<=FuncAdjustGVLast) { else if (function >= FuncAdjustGV1 && function <= FuncAdjustGVLast) {
switch (adjustmode) { switch (adjustmode) {
case 1: case 1:
b->setModel(rawSrcInputsItemModel); b->setModel(rawSrcInputsItemModel);
@ -759,10 +745,12 @@ void CustomFunctionsPanel::cmMoveDown()
swapData(selectedIndex, selectedIndex + 1); 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) if (prompt) {
return; if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Function. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
}
functions[selectedIndex].clear(); functions[selectedIndex].clear();
resetCBsAndRefresh(selectedIndex); resetCBsAndRefresh(selectedIndex);
@ -771,10 +759,10 @@ void CustomFunctionsPanel::cmClear()
void CustomFunctionsPanel::cmClearAll() 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; return;
for (int i=0; i<fswCapability; i++) { for (int i = 0; i < fswCapability; i++) {
functions[i].clear(); functions[i].clear();
resetCBsAndRefresh(i); resetCBsAndRefresh(i);
} }
@ -786,7 +774,7 @@ void CustomFunctionsPanel::cmInsert()
memmove(&functions[selectedIndex + 1], &functions[selectedIndex], (CPN_MAX_SPECIAL_FUNCTIONS - (selectedIndex + 1)) * sizeof(CustomFunctionData)); memmove(&functions[selectedIndex + 1], &functions[selectedIndex], (CPN_MAX_SPECIAL_FUNCTIONS - (selectedIndex + 1)) * sizeof(CustomFunctionData));
functions[selectedIndex].clear(); functions[selectedIndex].clear();
for (int i = selectedIndex; i < (fswCapability - 1); i++) { for (int i = selectedIndex; i < fswCapability; i++) {
resetCBsAndRefresh(i); resetCBsAndRefresh(i);
} }
} }
@ -830,7 +818,7 @@ bool CustomFunctionsPanel::hasClipboardData(QByteArray * data) const
bool CustomFunctionsPanel::insertAllowed() const bool CustomFunctionsPanel::insertAllowed() const
{ {
return ((selectedIndex < fswCapability - 1) && (model->curves[fswCapability - 1].isEmpty())); return ((selectedIndex < fswCapability - 1) && (functions[fswCapability - 1].isEmpty()));
} }
bool CustomFunctionsPanel::moveDownAllowed() const bool CustomFunctionsPanel::moveDownAllowed() const

View file

@ -82,7 +82,7 @@ class CustomFunctionsPanel : public GenericPanel
void cmMoveUp(); void cmMoveUp();
void cmMoveDown(); void cmMoveDown();
void cmInsert(); void cmInsert();
void cmClear(); void cmClear(bool prompt = true);
void cmClearAll(); void cmClearAll();
private: private:

View file

@ -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))); setWindowTitle(tr("Edit %1").arg(RawSource(srcType, ed->chn).toString(&model, &generalSettings)));
QRegExp rx(CHAR_FOR_NAMES_REGEX); 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);
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);
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();
}
curveGroup = new CurveGroup(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB, ed->curve, model, curveGroup = new CurveGroup(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB, ed->curve, model,
firmware->getCapability(HasInputDiff) ? 0 : (HIDE_DIFF | HIDE_NEGATIVE_CURVES)); firmware->getCapability(HasInputDiff) ? 0 : (HIDE_DIFF | HIDE_NEGATIVE_CURVES));

View file

@ -708,10 +708,12 @@ bool FlightModePanel::moveUpAllowed() const
return phaseIdx > 0; 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) if (prompt) {
return; 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); phase.clear(phaseIdx);
@ -780,8 +782,10 @@ void FlightModePanel::cmCopy()
void FlightModePanel::cmCut() 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(); cmCopy();
cmClear(); cmClear(false);
} }
void FlightModePanel::cmDelete() void FlightModePanel::cmDelete()
@ -1059,7 +1063,7 @@ void FlightModePanel::gvOnCustomContextMenuRequested(QPoint pos)
bool FlightModePanel::gvHasClipboardData() const bool FlightModePanel::gvHasClipboardData() const
{ {
if (gvHasDefnClipboardData() || gvHasValueClipboardData()) if ((phaseIdx == 0 && gvHasDefnClipboardData() && gvHasAllValuesClipboardData()) || (phaseIdx > 0 && gvHasValueClipboardData()))
return true; return true;
return false; return false;
} }
@ -1092,6 +1096,20 @@ bool FlightModePanel::gvHasValueClipboardData(QByteArray * data) const
return false; 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 bool FlightModePanel::gvDeleteAllowed() const
{ {
return phaseIdx == 0; return phaseIdx == 0;
@ -1124,11 +1142,13 @@ bool FlightModePanel::gvMoveUpAllowed() const
return (phaseIdx == 0 && gvIdx > 0); return (phaseIdx == 0 && gvIdx > 0);
} }
void FlightModePanel::gvCmClear() void FlightModePanel::gvCmClear(bool prompt)
{ {
if (phaseIdx == 0) { 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) if (prompt) {
return; 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(); model->gvarData[gvIdx].clear();
for (int i = 0; i < fmCount; i++) { for (int i = 0; i < fmCount; i++) {
model->flightModeData[i].gvars[gvIdx] = model->flightModeData[i].linkedGVarFlightModeZero(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); model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, gvIdx);
} }
else { 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); phase.gvars[gvIdx] = phase.linkedGVarFlightModeZero(phaseIdx);
} }
emit datachanged(); emit datachanged();
@ -1173,38 +1197,58 @@ void FlightModePanel::gvCmCopy()
if (phaseIdx == 0) { if (phaseIdx == 0) {
data.append((char*)&model->gvarData[gvIdx], sizeof(GVarData)); data.append((char*)&model->gvarData[gvIdx], sizeof(GVarData));
mimeData->setData(MIMETYPE_GVAR_PARAMS, data); 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 { else {
mimeData->removeFormat(MIMETYPE_GVAR_PARAMS); 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() void FlightModePanel::gvCmCut()
{ {
gvCmCopy(); if (phaseIdx == 0) {
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)
gvCmClear(); return;
} }
else { else {
model->gvarData[gvIdx].clear(); if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
phase.gvars[gvIdx] = 0; return;
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, gvIdx);
emit datachanged();
emit modified();
} }
gvCmCopy();
gvCmClear(false);
} }
void FlightModePanel::gvCmDelete() void FlightModePanel::gvCmDelete()
{ {
if (phaseIdx > 0) if (phaseIdx > 0)
return; 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; int maxidx = gvCount - 1;
for (int i = gvIdx; i < maxidx; i++) { for (int i = gvIdx; i < maxidx; i++) {
memcpy(&model->gvarData[i], &model->gvarData[i + 1], sizeof(GVarData)); memcpy(&model->gvarData[i], &model->gvarData[i + 1], sizeof(GVarData));
@ -1254,11 +1298,20 @@ void FlightModePanel::gvCmMoveUp()
void FlightModePanel::gvCmPaste() void FlightModePanel::gvCmPaste()
{ {
QByteArray data; QByteArray data;
if (phaseIdx == 0 && gvHasDefnClipboardData(&data)) { if (phaseIdx == 0) {
GVarData *gvd = &model->gvarData[gvIdx]; 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)
memcpy(gvd, data.constData(), sizeof(GVarData)); 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(); int val = data.toInt();
if (val > GVAR_MAX_VALUE) { if (val > GVAR_MAX_VALUE) {
if (phaseIdx > 0) if (phaseIdx > 0)

View file

@ -29,6 +29,7 @@ class RawSwitchFilterItemModel;
constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode"; constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode";
constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params"; constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params";
constexpr char MIMETYPE_GVAR_VALUE[] = "application/x-companion-gvar-value"; constexpr char MIMETYPE_GVAR_VALUE[] = "application/x-companion-gvar-value";
constexpr char MIMETYPE_GVAR_ALL_VALUES[] = "application/x-companion-gvar-all-values";
namespace Ui { namespace Ui {
class FlightMode; class FlightMode;
@ -67,7 +68,7 @@ class FlightModePanel : public ModelPanel
void phaseREValue_editingFinished(); void phaseREValue_editingFinished();
void phaseREUse_currentIndexChanged(int index); void phaseREUse_currentIndexChanged(int index);
void onCustomContextMenuRequested(QPoint pos); void onCustomContextMenuRequested(QPoint pos);
void cmClear(); void cmClear(bool prompt = true);
void cmClearAll(); void cmClearAll();
void cmCopy(); void cmCopy();
void cmCut(); void cmCut();
@ -77,7 +78,7 @@ class FlightModePanel : public ModelPanel
void cmMoveDown(); void cmMoveDown();
void cmMoveUp(); void cmMoveUp();
void gvOnCustomContextMenuRequested(QPoint pos); void gvOnCustomContextMenuRequested(QPoint pos);
void gvCmClear(); void gvCmClear(bool prompt = true);
void gvCmClearAll(); void gvCmClearAll();
void gvCmCopy(); void gvCmCopy();
void gvCmCut(); void gvCmCut();
@ -127,6 +128,7 @@ class FlightModePanel : public ModelPanel
bool gvHasClipboardData() const; bool gvHasClipboardData() const;
bool gvHasDefnClipboardData(QByteArray * data = nullptr) const; bool gvHasDefnClipboardData(QByteArray * data = nullptr) const;
bool gvHasValueClipboardData(QByteArray * data = nullptr) const; bool gvHasValueClipboardData(QByteArray * data = nullptr) const;
bool gvHasAllValuesClipboardData(QByteArray * data = nullptr) const;
bool gvDeleteAllowed() const; bool gvDeleteAllowed() const;
bool gvInsertAllowed() const; bool gvInsertAllowed() const;
bool gvMoveDownAllowed() const; bool gvMoveDownAllowed() const;

View file

@ -227,26 +227,27 @@ void InputsPanel::setSelectedByExpoList(QList<int> list)
} }
} }
void InputsPanel::exposDelete(bool ask) void InputsPanel::exposDelete(bool prompt)
{ {
QList<int> list = createExpoListFromSelected(); QList<int> list = createExpoListFromSelected();
if (list.isEmpty()) if (list.isEmpty())
return; return;
QMessageBox::StandardButton ret = QMessageBox::No; if (prompt) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete selected Input lines. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (ask) return;
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();
} }
exposDeleteList(list, prompt);
emit modified();
update();
} }
void InputsPanel::exposCut() 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(); exposCopy();
exposDelete(false); exposDelete(false);
} }
@ -317,7 +318,6 @@ void InputsPanel::pasteExpoMimeData(const QMimeData * mimeData, int destIdx)
} }
} }
void InputsPanel::exposPaste() void InputsPanel::exposPaste()
{ {
const QClipboard *clipboard = QApplication::clipboard(); const QClipboard *clipboard = QApplication::clipboard();
@ -515,7 +515,7 @@ void InputsPanel::exposDeleteList(QList<int> list, bool clearName)
void InputsPanel::clearExpos() 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(); model->clearInputs();
for (int i = 0; i < inputsCount; i++) { for (int i = 0; i < inputsCount; i++) {
model->updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, ModelData::REF_UPD_ACT_CLEAR, 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() 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; return;
for (int i = CPN_MAX_EXPOS - 1; i >= 0; i--) { for (int i = CPN_MAX_EXPOS - 1; i >= 0; i--) {
@ -574,7 +574,7 @@ void InputsPanel::cmInputClear()
void InputsPanel::cmInputDelete() 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; return;
for (int i = 0; i < CPN_MAX_EXPOS; i++) { for (int i = 0; i < CPN_MAX_EXPOS; i++) {

View file

@ -46,7 +46,7 @@ class InputsPanel : public ModelPanel
void expolistWidget_customContextMenuRequested(QPoint pos); void expolistWidget_customContextMenuRequested(QPoint pos);
void expolistWidget_doubleClicked(QModelIndex index); void expolistWidget_doubleClicked(QModelIndex index);
void expolistWidget_KeyPress(QKeyEvent *event); void expolistWidget_KeyPress(QKeyEvent *event);
void exposDelete(bool ask=true); void exposDelete(bool prompt = true);
void exposCut(); void exposCut();
void exposCopy(); void exposCopy();
void exposPaste(); void exposPaste();

View file

@ -479,10 +479,6 @@ void LogicalSwitchesPanel::populateFunctionCB(QComboBox *b)
int func = order[i]; int func = order[i];
if (func == LS_FN_NEQUAL || func == LS_FN_EGREATER || func == LS_FN_ELESS) if (func == LS_FN_NEQUAL || func == LS_FN_EGREATER || func == LS_FN_ELESS)
continue; continue;
if (!IS_ARM(firmware->getBoard())) {
if (func == LS_FN_VEQUAL || func == LS_FN_EDGE)
continue;
}
b->addItem(LogicalSwitchData(func).funcToString(), func); b->addItem(LogicalSwitchData(func).funcToString(), func);
} }
b->setMaxVisibleItems(10); b->setMaxVisibleItems(10);
@ -490,27 +486,7 @@ void LogicalSwitchesPanel::populateFunctionCB(QComboBox *b)
void LogicalSwitchesPanel::populateAndSwitchCB(QComboBox *b) void LogicalSwitchesPanel::populateAndSwitchCB(QComboBox *b)
{ {
if (IS_ARM(firmware->getBoard())) { b->setModel(rawSwitchItemModel);
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->setVisible(true); b->setVisible(true);
} }
@ -557,8 +533,10 @@ void LogicalSwitchesPanel::cmCopy()
void LogicalSwitchesPanel::cmCut() 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(); cmCopy();
cmClear(); cmClear(false);
} }
// TODO make something generic here! // TODO make something generic here!
@ -621,8 +599,13 @@ void LogicalSwitchesPanel::cmMoveDown()
swapData(selectedIndex, selectedIndex + 1); 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->logicalSw[selectedIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
update(); update();

View file

@ -59,7 +59,7 @@ class LogicalSwitchesPanel : public ModelPanel
void cmMoveUp(); void cmMoveUp();
void cmMoveDown(); void cmMoveDown();
void cmInsert(); void cmInsert();
void cmClear(); void cmClear(bool prompt = true);
void cmClearAll(); void cmClearAll();
private: private:

View file

@ -253,28 +253,27 @@ void MixesPanel::setSelectedByMixList(QList<int> list)
} }
void MixesPanel::mixersDelete(bool ask) void MixesPanel::mixersDelete(bool prompt)
{ {
QList<int> list = createMixListFromSelected(); QList<int> list = createMixListFromSelected();
if(list.isEmpty()) return; if(list.isEmpty())
return;
QMessageBox::StandardButton ret = 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)
if(ask) { return;
ret = QMessageBox::warning(this, "companion",
tr("Delete Selected Mixes?"),
QMessageBox::Yes | QMessageBox::No);
} }
if ((ret == QMessageBox::Yes) || (!ask)) { mixersDeleteList(list);
mixersDeleteList(list); emit modified();
emit modified(); update();
update();
}
} }
void MixesPanel::mixersCut() 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(); mixersCopy();
mixersDelete(false); mixersDelete(false);
} }

View file

@ -39,7 +39,7 @@ class MixesPanel : public ModelPanel
private slots: private slots:
// TODO all slots? // TODO all slots?
void clearMixes(); void clearMixes();
void mixersDelete(bool ask=true); void mixersDelete(bool prompt = true);
void mixersCut(); void mixersCut();
void mixersCopy(); void mixersCopy();
void mixersPaste(); void mixersPaste();

View file

@ -65,7 +65,7 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw
s1.report("LS"); s1.report("LS");
addTab(new CustomFunctionsPanel(this, &radioData.models[modelId], radioData.generalSettings, firmware), tr("Special Functions")); addTab(new CustomFunctionsPanel(this, &radioData.models[modelId], radioData.generalSettings, firmware), tr("Special Functions"));
s1.report("CF"); 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")); 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 onTabIndexChanged(ui->tabWidget->currentIndex()); // make sure to trigger update on default tab panel

View file

@ -36,7 +36,6 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
timer(timer), timer(timer),
ui(new Ui::Timer) ui(new Ui::Timer)
{ {
Board::Type board = firmware->getBoard();
ui->setupUi(this); ui->setupUi(this);
@ -65,10 +64,8 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
ui->countdownBeep->setField(timer.countdownBeep, this); ui->countdownBeep->setField(timer.countdownBeep, this);
ui->countdownBeep->addItem(tr("Silent"), TimerData::COUNTDOWN_SILENT); ui->countdownBeep->addItem(tr("Silent"), TimerData::COUNTDOWN_SILENT);
ui->countdownBeep->addItem(tr("Beeps"), TimerData::COUNTDOWN_BEEPS); 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("Voice"), TimerData::COUNTDOWN_VOICE); ui->countdownBeep->addItem(tr("Haptic"), TimerData::COUNTDOWN_HAPTIC);
ui->countdownBeep->addItem(tr("Haptic"), TimerData::COUNTDOWN_HAPTIC);
}
ui->value->setMaximumTime(firmware->getMaxTimerStart()); ui->value->setMaximumTime(firmware->getMaxTimerStart());
@ -192,6 +189,8 @@ void TimerPanel::on_name_editingFinished()
#define MASK_SBUSPPM_FIELDS (1<<11) #define MASK_SBUSPPM_FIELDS (1<<11)
#define MASK_SUBTYPES (1<<12) #define MASK_SUBTYPES (1<<12)
#define MASK_ACCESS (1<<13) #define MASK_ACCESS (1<<13)
#define MASK_RX_FREQ (1<<14)
#define MASK_RF_POWER (1<<15)
quint8 ModulePanel::failsafesValueDisplayType = ModulePanel::FAILSAFE_DISPLAY_PERCENT; 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)); ui->label_module->setText(ModuleData::indexToString(moduleIdx, firmware));
if (moduleIdx < 0) { 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_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_SBUS_EXTERNAL_MODULE, 0, Qt::UserRole - 1);
ui->trainerMode->setItemData(TRAINER_MODE_MASTER_BATTERY_COMPARTMENT, 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<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ModulePanel::onMultiProtocolChanged); connect(ui->multiProtocol, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ModulePanel::onMultiProtocolChanged);
connect(this, &ModulePanel::channelsRangeChanged, this, &ModulePanel::setupFailsafes); connect(this, &ModulePanel::channelsRangeChanged, this, &ModulePanel::setupFailsafes);
connect(ui->btnGrpValueType, static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &ModulePanel::onFailsafesDisplayValueTypeChanged); connect(ui->btnGrpValueType, static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &ModulePanel::onFailsafesDisplayValueTypeChanged);
connect(ui->rxFreq, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &ModulePanel::onRfFreqChanged);
connect(ui->clearRx1, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked())); connect(ui->clearRx1, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked()));
connect(ui->clearRx2, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked())); connect(ui->clearRx2, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked()));
connect(ui->clearRx3, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked())); connect(ui->clearRx3, SIGNAL(clicked()), this, SLOT(onClearAccessRxClicked()));
@ -391,7 +390,7 @@ void ModulePanel::update()
mask |= MASK_PROTOCOL; mask |= MASK_PROTOCOL;
switch (protocol) { switch (protocol) {
case PULSES_PXX_R9M: 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:
case PULSES_ACCESS_R9M_LITE: case PULSES_ACCESS_R9M_LITE:
case PULSES_ACCESS_R9M_LITE_PRO: case PULSES_ACCESS_R9M_LITE_PRO:
@ -425,6 +424,8 @@ void ModulePanel::update()
max_rx_num = 20; max_rx_num = 20;
break; break;
case PULSES_CROSSFIRE: case PULSES_CROSSFIRE:
mask |= MASK_CHANNELS_RANGE | MASK_RX_NUMBER;
case PULSES_GHOST:
mask |= MASK_CHANNELS_RANGE; mask |= MASK_CHANNELS_RANGE;
module.channelsCount = 16; module.channelsCount = 16;
break; 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 ))) if (pdef.hasFailsafe || (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_FRSKY && (module.subType == 0 || module.subType == 2 || module.subType > 3 )))
mask |= MASK_FAILSAFES; mask |= MASK_FAILSAFES;
break; 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: case PULSES_OFF:
break; break;
default: default:
@ -516,16 +522,16 @@ void ModulePanel::update()
} }
// R9M options // R9M options
ui->r9mPower->setVisible(mask & MASK_R9M); ui->r9mPower->setVisible(mask & MASK_RF_POWER);
ui->label_r9mPower->setVisible(mask & MASK_R9M); ui->label_r9mPower->setVisible(mask & MASK_RF_POWER);
ui->warning_r9mPower->setVisible((mask & MASK_R9M) && module.subType == MODULE_SUBTYPE_R9M_EU); 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); 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); const QSignalBlocker blocker(ui->r9mPower);
ui->r9mPower->clear(); ui->r9mPower->clear();
ui->r9mPower->addItems(ModuleData::powerValueStrings(module.subType, firmware)); ui->r9mPower->addItems(ModuleData::powerValueStrings(protocol, module.subType, firmware));
ui->r9mPower->setCurrentIndex(module.pxx.power); ui->r9mPower->setCurrentIndex(mask & MASK_R9M ? module.pxx.power : module.afhds3.rfPower);
} }
// module subtype // module subtype
@ -542,6 +548,9 @@ void ModulePanel::update()
if (firmware->getCapability(HasModuleR9MFlex)) if (firmware->getCapability(HasModuleR9MFlex))
i = 2; i = 2;
break; break;
case PULSES_AFHDS3:
numEntries = 4;
break;
default: default:
break; break;
} }
@ -563,7 +572,7 @@ void ModulePanel::update()
ui->lowPower->setVisible(mask & MASK_MULTIMODULE); ui->lowPower->setVisible(mask & MASK_MULTIMODULE);
ui->autoBind->setVisible(mask & MASK_MULTIMODULE); ui->autoBind->setVisible(mask & MASK_MULTIMODULE);
if (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2) if (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2)
ui->autoBind->setText(tr("Autodetect Format")); ui->autoBind->setVisible(false);
else else
ui->autoBind->setText(tr("Bind on channel")); ui->autoBind->setText(tr("Bind on channel"));
@ -606,6 +615,8 @@ void ModulePanel::update()
// Failsafes // Failsafes
ui->label_failsafeMode->setVisible(mask & MASK_FAILSAFES); ui->label_failsafeMode->setVisible(mask & MASK_FAILSAFES);
ui->failsafeMode->setVisible(mask & MASK_FAILSAFES); ui->failsafeMode->setVisible(mask & MASK_FAILSAFES);
//hide reciever mode for afhds3
qobject_cast<QListView *>(ui->failsafeMode->view())->setRowHidden(FAILSAFE_RECEIVER, protocol == PULSES_AFHDS3);
if ((mask & MASK_FAILSAFES) && module.failsafeMode == FAILSAFE_CUSTOM) { if ((mask & MASK_FAILSAFES) && module.failsafeMode == FAILSAFE_CUSTOM) {
if (ui->failsafesGroupBox->isHidden()) { 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) 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) void ModulePanel::on_r9mPower_currentIndexChanged(int index)
{ {
if (!lock && module.pxx.power != (unsigned int)index) { if (!lock) {
module.pxx.power = index;
emit modified(); 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) { if (!lock && module.subType != type) {
lock=true; lock=true;
module.subType = type; module.subType = type;
update(); if (module.protocol != PULSES_AFHDS3) {
update();
}
emit modified(); emit modified();
lock = false; 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) void ModulePanel::on_disableTelem_stateChanged(int state)
{ {
module.multi.disableTelemetry = (state == Qt::Checked); module.multi.disableTelemetry = (state == Qt::Checked);
@ -1176,13 +1204,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
ui->potWarningMode->hide(); ui->potWarningMode->hide();
} }
if (IS_ARM(board)) { ui->trimsDisplay->setField(model.trimsDisplay, this);
ui->trimsDisplay->setField(model.trimsDisplay, this);
}
else {
ui->labelTrimsDisplay->hide();
ui->trimsDisplay->hide();
}
for (int i = firmware->getCapability(NumFirstUsableModule); i < firmware->getCapability(NumModules); i++) { for (int i = firmware->getCapability(NumFirstUsableModule); i < firmware->getCapability(NumModules); i++) {
modules[i] = new ModulePanel(this, model, model.moduleData[i], generalSettings, firmware, i); 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() void SetupPanel::on_name_editingFinished()
{ {
if (QString(model->name) != ui->name->text()) { if (QString(model->name) != ui->name->text()) {
@ -1326,11 +1356,29 @@ void SetupPanel::populateThrottleSourceCB()
lock = false; lock = false;
} }
void SetupPanel::populateThrottleTrimSwitchCB()
{
Board::Type board = firmware->getBoard();
lock = true;
ui->throttleTrimSwitch->clear();
int idx=0;
for (int i=0; i<getBoardCapability(board, Board::NumTrims); i++, idx++) {
QString trim = RawSource(SOURCE_TYPE_TRIM, i).toString(model, &generalSettings);
trim = (trim == "TrmR") ? "TrmT" : (trim == "TmrT") ? "TmrR" : trim;
ui->throttleTrimSwitch->addItem(trim, idx);
}
int thrTrimSwitchIdx = ui->throttleTrimSwitch->findData(model->thrTrimSwitch);
ui->throttleTrimSwitch->setCurrentIndex(thrTrimSwitchIdx);
lock = false;
}
void SetupPanel::update() void SetupPanel::update()
{ {
ui->name->setText(model->name); ui->name->setText(model->name);
ui->throttleReverse->setChecked(model->throttleReversed); ui->throttleReverse->setChecked(model->throttleReversed);
populateThrottleSourceCB(); populateThrottleSourceCB();
populateThrottleTrimSwitchCB();
ui->throttleWarning->setChecked(!model->disableThrottleWarning); ui->throttleWarning->setChecked(!model->disableThrottleWarning);
ui->trimIncrement->setCurrentIndex(model->trimInc+2); ui->trimIncrement->setCurrentIndex(model->trimInc+2);
ui->throttleTrim->setChecked(model->thrTrim); ui->throttleTrim->setChecked(model->thrTrim);
@ -1570,10 +1618,12 @@ bool SetupPanel::moveTimerUpAllowed() const
return selectedTimerIndex > 0; 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) if (prompt) {
return; 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->timers[selectedTimerIndex].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, selectedTimerIndex); model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, selectedTimerIndex);
@ -1605,8 +1655,10 @@ void SetupPanel::cmTimerCopy()
void SetupPanel::cmTimerCut() 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(); cmTimerCopy();
cmTimerClear(); cmTimerClear(false);
} }
void SetupPanel::cmTimerDelete() void SetupPanel::cmTimerDelete()

View file

@ -97,6 +97,7 @@ class ModulePanel : public ModelPanel
void onFailsafeUsecChanged(int value); void onFailsafeUsecChanged(int value);
void onFailsafePercentChanged(double value); void onFailsafePercentChanged(double value);
void onFailsafesDisplayValueTypeChanged(int type); void onFailsafesDisplayValueTypeChanged(int type);
void onRfFreqChanged(int freq);
void updateFailsafe(unsigned channel); void updateFailsafe(unsigned channel);
void on_optionValue_editingFinished(); void on_optionValue_editingFinished();
void onClearAccessRxClicked(); void onClearAccessRxClicked();
@ -137,6 +138,7 @@ class SetupPanel : public ModelPanel
private slots: private slots:
void on_name_editingFinished(); void on_name_editingFinished();
void on_throttleSource_currentIndexChanged(int index); void on_throttleSource_currentIndexChanged(int index);
void on_throttleTrimSwitch_currentIndexChanged(int index);
void on_throttleTrim_toggled(bool checked); void on_throttleTrim_toggled(bool checked);
void on_extendedLimits_toggled(bool checked); void on_extendedLimits_toggled(bool checked);
void on_extendedTrims_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_potWarningMode_currentIndexChanged(int index);
void on_editText_clicked(); void on_editText_clicked();
void onTimerCustomContextMenuRequested(QPoint pos); void onTimerCustomContextMenuRequested(QPoint pos);
void cmTimerClear(); void cmTimerClear(bool prompt = true);
void cmTimerClearAll(); void cmTimerClearAll();
void cmTimerCopy(); void cmTimerCopy();
void cmTimerCut(); void cmTimerCut();
@ -175,6 +177,7 @@ class SetupPanel : public ModelPanel
void updatePotWarnings(); void updatePotWarnings();
void updateBeepCenter(); void updateBeepCenter();
void populateThrottleSourceCB(); void populateThrottleSourceCB();
void populateThrottleTrimSwitchCB();
int timersCount; int timersCount;
int selectedTimerIndex; int selectedTimerIndex;
bool hasTimerClipboardData(QByteArray * data = nullptr) const; bool hasTimerClipboardData(QByteArray * data = nullptr) const;

View file

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>893</width> <width>1007</width>
<height>405</height> <height>405</height>
</rect> </rect>
</property> </property>
@ -32,22 +32,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QLabel" name="toplcdTimerLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Top LCD Timer</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_5"> <layout class="QVBoxLayout" name="verticalLayout_5">
<item> <item>
@ -149,6 +133,106 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="0" column="0" alignment="Qt::AlignLeft|Qt::AlignTop">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Model</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_timer3">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Timer 3</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="label_ttrace">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Throttle Source</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Trim Step</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelTrimsDisplay">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Trims Display</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="toplcdTimerLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Top LCD Timer</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="10" column="0" alignment="Qt::AlignLeft|Qt::AlignTop"> <item row="10" column="0" alignment="Qt::AlignLeft|Qt::AlignTop">
<widget class="QLabel" name="swwarn_label"> <widget class="QLabel" name="swwarn_label">
<property name="sizePolicy"> <property name="sizePolicy">
@ -171,6 +255,66 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1">
<widget class="AutoComboBox" name="toplcdTimer">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="8" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<layout class="QGridLayout" name="centerBeepLayout"/>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="7" column="1">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0" alignment="Qt::AlignRight|Qt::AlignVCenter">
<widget class="QLabel" name="label_timer2">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Timer 2</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="0" colspan="2">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="10" column="1"> <item row="10" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_8"> <layout class="QHBoxLayout" name="horizontalLayout_8">
<item> <item>
@ -275,44 +419,8 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="0" column="0" alignment="Qt::AlignLeft|Qt::AlignTop"> <item row="5" column="1">
<widget class="QLabel" name="label"> <widget class="Line" name="line_2">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Model</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="8" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<layout class="QGridLayout" name="centerBeepLayout"/>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="9" column="0" colspan="2">
<widget class="Line" name="line_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -334,86 +442,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="1"> <item row="6" column="1">
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0,0,0,0,0,0">
<item row="1" column="3"> <property name="verticalSpacing">
<widget class="QCheckBox" name="displayText"> <number>6</number>
<property name="layoutDirection"> </property>
<enum>Qt::LeftToRight</enum> <item row="0" column="5">
</property> <widget class="QComboBox" name="throttleTrimSwitch"/>
<property name="text">
<string>Display Checklist</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="AutoComboBox" name="trimsDisplay">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Never</string>
</property>
</item>
<item>
<property name="text">
<string>On change</string>
</property>
</item>
<item>
<property name="text">
<string>Always</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="throttleTrim">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Throttle Trim Idle Only</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="gfEnabled">
<property name="text">
<string>Global Functions</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="throttleWarning">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Throttle Warning</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QComboBox" name="throttleSource">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QComboBox" name="trimIncrement"> <widget class="QComboBox" name="trimIncrement">
@ -450,6 +485,81 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="AutoComboBox" name="trimsDisplay">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Never</string>
</property>
</item>
<item>
<property name="text">
<string>On change</string>
</property>
</item>
<item>
<property name="text">
<string>Always</string>
</property>
</item>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="throttleWarning">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Throttle Warning</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QCheckBox" name="displayText">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Display Checklist</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="gfEnabled">
<property name="text">
<string>Global Functions</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="editText">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Edit Checklist...</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="throttleTrim">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Throttle Trim Idle Only</string>
</property>
</widget>
</item>
<item row="0" column="3"> <item row="0" column="3">
<widget class="QCheckBox" name="throttleReverse"> <widget class="QCheckBox" name="throttleReverse">
<property name="whatsThis"> <property name="whatsThis">
@ -466,16 +576,10 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="4"> <item row="0" column="4">
<widget class="QPushButton" name="editText"> <widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Edit Checklist...</string> <string>Throttle trim switch</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -499,7 +603,17 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="5"> <item row="0" column="0">
<widget class="QComboBox" name="throttleSource">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="6">
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -514,107 +628,6 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
</item> </item>
</layout> </layout>
</item> </item>
<item row="6" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="label_ttrace">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Throttle Source</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Trim Step</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelTrimsDisplay">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Trims Display</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="1">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0" alignment="Qt::AlignRight|Qt::AlignVCenter">
<widget class="QLabel" name="label_timer2">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Timer 2</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_timer3">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Timer 3</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="AutoComboBox" name="toplcdTimer">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View file

@ -126,6 +126,12 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
@ -173,6 +179,15 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="suffix"> <property name="suffix">
<string/> <string/>
</property> </property>
@ -214,6 +229,12 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum> <enum>QComboBox::AdjustToContents</enum>
</property> </property>
@ -417,6 +438,7 @@
<item> <item>
<widget class="QCheckBox" name="autoBind"> <widget class="QCheckBox" name="autoBind">
<property name="text"> <property name="text">
<string/>
</property> </property>
</widget> </widget>
</item> </item>
@ -485,6 +507,12 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
@ -529,6 +557,12 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
@ -573,6 +607,15 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="suffix"> <property name="suffix">
<string> ms</string> <string> ms</string>
</property> </property>
@ -617,19 +660,58 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum> <enum>QComboBox::AdjustToContents</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QLabel" name="label_rxFreq">
<property name="text">
<string>RX Frequency</string>
</property>
</widget>
</item>
<item row="5" column="0"> <item row="5" column="0">
<widget class="QLabel" name="label_option">
<property name="text">
<string>Option value</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="optionValue">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_ppmOutputType"> <widget class="QLabel" name="label_ppmOutputType">
<property name="text"> <property name="text">
<string>Output type</string> <string>Output type</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="6" column="1">
<widget class="QComboBox" name="ppmOutputType"> <widget class="QComboBox" name="ppmOutputType">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
@ -652,21 +734,7 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="7" column="0" colspan="2">
<widget class="QLabel" name="label_option">
<property name="text">
<string>Option value</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="optionValue">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -679,6 +747,34 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="4" column="1">
<widget class="QSpinBox" name="rxFreq">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="suffix">
<string> Hz</string>
</property>
<property name="minimum">
<number>50</number>
</property>
<property name="maximum">
<number>400</number>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="0" column="0"> <item row="0" column="0">
@ -711,11 +807,17 @@
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="protocol"> <widget class="QComboBox" name="protocol">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>180</width>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum> <enum>QComboBox::AdjustToContents</enum>
</property> </property>
@ -754,11 +856,17 @@
<item row="2" column="1"> <item row="2" column="1">
<widget class="QComboBox" name="multiProtocol"> <widget class="QComboBox" name="multiProtocol">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum> <enum>QComboBox::AdjustToContents</enum>
</property> </property>
@ -774,11 +882,17 @@
<item row="3" column="1"> <item row="3" column="1">
<widget class="QComboBox" name="multiSubType"> <widget class="QComboBox" name="multiSubType">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum> <enum>QComboBox::AdjustToContents</enum>
</property> </property>
@ -847,11 +961,17 @@
<item row="5" column="1"> <item row="5" column="1">
<widget class="QComboBox" name="failsafeMode"> <widget class="QComboBox" name="failsafeMode">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum> <enum>QComboBox::AdjustToContents</enum>
</property> </property>
@ -901,11 +1021,17 @@
<item row="6" column="1"> <item row="6" column="1">
<widget class="QComboBox" name="trainerMode"> <widget class="QComboBox" name="trainerMode">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum> <enum>QComboBox::AdjustToContents</enum>
</property> </property>
@ -934,17 +1060,17 @@
<string>Master/SBUS in battery compartment</string> <string>Master/SBUS in battery compartment</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Master/Bluetooth</string> <string>Master/Bluetooth</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Slave/Bluetooth</string> <string>Slave/Bluetooth</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Master/Multi</string> <string>Master/Multi</string>
</property> </property>

View file

@ -20,7 +20,6 @@
#include "telemetry.h" #include "telemetry.h"
#include "ui_telemetry.h" #include "ui_telemetry.h"
#include "ui_telemetry_analog.h"
#include "ui_telemetry_customscreen.h" #include "ui_telemetry_customscreen.h"
#include "ui_telemetry_sensor.h" #include "ui_telemetry_sensor.h"
#include "helpers.h" #include "helpers.h"
@ -29,294 +28,6 @@
#include <TimerEdit> #include <TimerEdit>
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<<i)) {
mult = i+1;
break;
}
}
return mult;
}
void TelemetryAnalog::on_UnitCB_currentIndexChanged(int index)
{
float ratio = analog.getRatio();
analog.type = index;
switch (index) {
case 0:
case 1:
case 2:
ui->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<<analog.multiplier)/10.0;
lock=true;
ui->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<<analog.multiplier);
lock = true;
ui->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<<analog.multiplier)/10.0);
ui->alarm1ValueSB->setSingleStep((1<<analog.multiplier)/10.0);
ui->alarm2ValueSB->setSingleStep((1<<analog.multiplier)/10.0);
analog.ratio = ((int)(round(ui->RatioSB->value()*10))/(1 <<analog.multiplier));
}
else {
analog.multiplier = findmult(ui->RatioSB->value(), 255);
ui->CalibSB->setSingleStep(1<<analog.multiplier);
ui->alarm1ValueSB->setSingleStep(1<<analog.multiplier);
ui->alarm2ValueSB->setSingleStep(1<<analog.multiplier);
analog.ratio = (ui->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<<analog.multiplier))/(analog.ratio<<analog.multiplier));
analog.alarms[1].value=round((alarm2value*255-analog.offset*(analog.ratio<<analog.multiplier))/(analog.ratio<<analog.multiplier));
update();
emit modified();
}
}
void TelemetryAnalog::on_CalibSB_editingFinished()
{
float ratio = analog.getRatio();
float calib,alarm1value,alarm2value;
if (ratio!=0) {
analog.offset = round((255*ui->CalibSB->value()/ratio));
calib=ratio*analog.offset/255.0;
alarm1value=ui->alarm1ValueSB->value();
alarm2value=ui->alarm2ValueSB->value();
if (alarm1value<calib) {
alarm1value=calib;
}
else if (alarm1value>(ratio+calib)) {
alarm1value=ratio+calib;
}
if (alarm2value<calib) {
alarm2value=calib;
}
else 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): TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawSourceFilterItemModel * srcModel):
ModelPanel(parent, model, generalSettings, firmware), ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::TelemetryCustomScreen), ui(new Ui::TelemetryCustomScreen),
@ -324,17 +35,17 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model,
{ {
ui->setupUi(this); ui->setupUi(this);
for (int l=0; l<4; l++) { for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensLines); l++) {
for (int c=0; c<firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) { for (int c = 0; c < firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) {
fieldsCB[l][c] = new QComboBox(this); 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); fieldsCB[l][c]->setModel(srcModel);
ui->screenNumsLayout->addWidget(fieldsCB[l][c], l, c, 1, 1); ui->screenNumsLayout->addWidget(fieldsCB[l][c], l, c, 1, 1);
connect(fieldsCB[l][c], SIGNAL(activated(int)), this, SLOT(customFieldChanged(int))); 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] = new QComboBox(this);
barsCB[l]->setProperty("index", l); barsCB[l]->setProperty("index", l);
barsCB[l]->setModel(srcModel); barsCB[l]->setModel(srcModel);
@ -377,8 +88,7 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model,
disableMouseScrolling(); disableMouseScrolling();
lock = true; 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("Numbers"), TELEMETRY_SCREEN_NUMBERS);
ui->screenType->addItem(tr("Bars"), TELEMETRY_SCREEN_BARS); ui->screenType->addItem(tr("Bars"), TELEMETRY_SCREEN_BARS);
if (IS_TARANIS(firmware->getBoard())) if (IS_TARANIS(firmware->getBoard()))
@ -409,18 +119,18 @@ void TelemetryCustomScreen::update()
ui->screenNums->setVisible(screen.type == TELEMETRY_SCREEN_NUMBERS); ui->screenNums->setVisible(screen.type == TELEMETRY_SCREEN_NUMBERS);
ui->screenBars->setVisible(screen.type == TELEMETRY_SCREEN_BARS); ui->screenBars->setVisible(screen.type == TELEMETRY_SCREEN_BARS);
for (int l=0; l<4; l++) { for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensLines); l++) {
for (int c=0; c<firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) { for (int c = 0; c < firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) {
fieldsCB[l][c]->setCurrentIndex(fieldsCB[l][c]->findData(screen.body.lines[l].source[c].toValue())); 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())); barsCB[l]->setCurrentIndex(barsCB[l]->findData(screen.body.bars[l].source.toValue()));
} }
if (screen.type == TELEMETRY_SCREEN_BARS) { if (screen.type == TELEMETRY_SCREEN_BARS) {
for (int i=0; i<4; i++) { for (int i = 0; i < firmware->getCapability(TelemetryCustomScreensBars); i++) {
updateBar(i); updateBar(i);
} }
} }
@ -439,14 +149,8 @@ void TelemetryCustomScreen::updateBar(int line)
if (source.type != SOURCE_TYPE_NONE) { if (source.type != SOURCE_TYPE_NONE) {
RawSourceRange range = source.getRange(model, generalSettings); 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 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); maxVal = range.getValue(maxVal);
if (source.isTimeBased()) { if (source.isTimeBased()) {
@ -552,10 +256,7 @@ void TelemetryCustomScreen::barMinChanged(double value)
{ {
if (!lock) { if (!lock) {
int line = sender()->property("index").toInt(); int line = sender()->property("index").toInt();
if (IS_ARM(getCurrentBoard())) screen.body.bars[line].barMin = round(value / minSB[line]->singleStep());
screen.body.bars[line].barMin = round(value / minSB[line]->singleStep());
else
screen.body.bars[line].barMin = round((value-minSB[line]->minimum()) / minSB[line]->singleStep());
// TODO set min (maxSB) // TODO set min (maxSB)
emit modified(); emit modified();
} }
@ -565,10 +266,7 @@ void TelemetryCustomScreen::barMaxChanged(double value)
{ {
if (!lock) { if (!lock) {
int line = sender()->property("index").toInt(); int line = sender()->property("index").toInt();
if (IS_ARM(getCurrentBoard())) screen.body.bars[line].barMax = round((value) / maxSB[line]->singleStep());
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());
// TODO set max (minSB) // TODO set max (minSB)
emit modified(); emit modified();
} }
@ -583,10 +281,7 @@ void TelemetryCustomScreen::barTimeChanged()
if (!te) if (!te)
return; return;
if (IS_ARM(getCurrentBoard())) valRef = round(te->timeInSeconds() / te->singleStep());
valRef = round(te->timeInSeconds() / te->singleStep());
else
valRef = round((te->timeInSeconds() - te->minimumTime()) / te->singleStep());
emit modified(); 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), ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::TelemetrySensor), ui(new Ui::TelemetrySensor),
sensor(sensor), sensor(sensor),
lock(false), lock(false),
sensorIndex(sensorIndex), sensorIndex(sensorIndex),
selectedIndex(0) selectedIndex(0),
sensorCapability(sensorCapability)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->numLabel->setText(tr("TELE%1").arg(sensorIndex + 1)); 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->ampsSensor->setField(sensor.amps, this);
ui->cellsSensor->setField(sensor.source, this); ui->cellsSensor->setField(sensor.source, this);
ui->cellsIndex->addItem(tr("Lowest"), SensorData::TELEM_CELL_INDEX_LOWEST); 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("Cell %1").arg(i), i);
ui->cellsIndex->addItem(tr("Highest"), SensorData::TELEM_CELL_INDEX_HIGHEST); ui->cellsIndex->addItem(tr("Highest"), SensorData::TELEM_CELL_INDEX_HIGHEST);
ui->cellsIndex->addItem(tr("Delta"), SensorData::TELEM_CELL_INDEX_DELTA); ui->cellsIndex->addItem(tr("Delta"), SensorData::TELEM_CELL_INDEX_DELTA);
@ -777,8 +473,8 @@ void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model
{ {
cb->clear(); cb->clear();
if (negative) { if (negative) {
for (int i=-CPN_MAX_SENSORS; i<0; ++i) { for (int i = -CPN_MAX_SENSORS; i < 0; ++i) {
const SensorData& sensor = model->sensorData[-i-1]; const SensorData& sensor = model->sensorData[-i - 1];
if (sensor.isAvailable()) { if (sensor.isAvailable()) {
if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) if (sensor.type == SensorData::TELEM_TYPE_CUSTOM)
cb->addItem(QString("-%1 (%2)").arg(sensor.label, sensor.getOrigin(model)), i); 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); 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]; const SensorData& sensor = model->sensorData[i-1];
if (sensor.isAvailable()) { if (sensor.isAvailable()) {
if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) 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("paste.png"), tr("Paste"),this,SLOT(cmPaste()))->setEnabled(hasClipboardData());
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear())); contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"),this,SLOT(cmClear()));
contextMenu.addSeparator(); 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.addAction(CompanionIcon("clear.png"), tr("Clear All"),this,SLOT(cmClearAll()));
contextMenu.exec(globalPos); contextMenu.exec(globalPos);
@ -891,6 +592,21 @@ bool TelemetrySensorPanel::hasClipboardData(QByteArray * data) const
return false; 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() void TelemetrySensorPanel::cmCopy()
{ {
QByteArray data; QByteArray data;
@ -902,8 +618,11 @@ void TelemetrySensorPanel::cmCopy()
void TelemetrySensorPanel::cmCut() 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(); cmCopy();
cmClear(); cmClear(false);
} }
void TelemetrySensorPanel::cmPaste() 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) if (prompt) {
return; if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Telemetry Sensor. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
}
sensor.clear(); sensor.clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, selectedIndex);
emit dataModified(); emit dataModified();
emit modified(); emit modified();
} }
@ -934,6 +656,26 @@ void TelemetrySensorPanel::cmClearAll()
emit clearAllSensors(); 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): TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
@ -942,33 +684,29 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
{ {
ui->setupUi(this); 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)) { if (firmware->getCapability(NoTelemetryProtocol)) {
model.frsky.usrProto = 1; model.frsky.usrProto = 1;
} }
if (IS_ARM(firmware->getBoard())) { ui->varioSource->setField(model.frsky.varioSource, this);
ui->varioSource->setField(model.frsky.varioSource, this); ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this);
ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this); ui->A1GB->hide();
ui->A1GB->hide(); ui->A2GB->hide();
ui->A2GB->hide(); for (int i = 0; i < sensorCapability; ++i) {
for (unsigned i= 0; i < CPN_MAX_SENSORS; ++i) { TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, sensorCapability, model, generalSettings, firmware);
TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, model, generalSettings, firmware); ui->sensorsLayout->addWidget(panel);
ui->sensorsLayout->addWidget(panel); sensorPanels[i] = panel;
sensorPanels[i] = panel; connect(panel, SIGNAL(dataModified()), this, SLOT(update()));
connect(panel, SIGNAL(dataModified()), this, SLOT(update())); connect(panel, SIGNAL(modified()), this, SLOT(onModified()));
connect(panel, SIGNAL(modified()), this, SLOT(onModified())); connect(panel, SIGNAL(clearAllSensors()), this, SLOT(on_clearAllSensors()));
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)));
else { connect(panel, SIGNAL(moveDownSensor(int)), this, SLOT(on_moveDownSensor(int)));
ui->sensorsGB->hide();
ui->altimetryGB->hide();
analogs[0] = new TelemetryAnalog(this, model.frsky.channels[0], model, generalSettings, firmware);
ui->A1Layout->addWidget(analogs[0]);
connect(analogs[0], SIGNAL(modified()), this, SLOT(onAnalogModified()));
analogs[1] = new TelemetryAnalog(this, model.frsky.channels[1], model, generalSettings, firmware);
ui->A2Layout->addWidget(analogs[1]);
connect(analogs[1], SIGNAL(modified()), this, SLOT(onModified()));
} }
if (IS_TARANIS_X9(firmware->getBoard())) { 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++) { for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) {
TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, srcModel); 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; telemetryCustomScreens[i] = tab;
connect(tab, &TelemetryCustomScreen::modified, this, &TelemetryPanel::onModified); connect(tab, &TelemetryCustomScreen::modified, this, &TelemetryPanel::onModified);
connect(this, &TelemetryPanel::updated, tab, &TelemetryCustomScreen::update); connect(this, &TelemetryPanel::updated, tab, &TelemetryCustomScreen::update);
@ -1017,10 +755,8 @@ void TelemetryPanel::update()
populateTelemetrySourcesComboBox(ui->varioSource, model, false); populateTelemetrySourcesComboBox(ui->varioSource, model, false);
} }
if (IS_ARM(firmware->getBoard())) { for (int i = 0; i < sensorCapability; ++i) {
for (unsigned i=0; i<CPN_MAX_SENSORS; ++i) { sensorPanels[i]->update();
sensorPanels[i]->update();
}
} }
emit updated(); emit updated();
@ -1032,52 +768,29 @@ void TelemetryPanel::setup()
lock = true; lock = true;
if (IS_ARM(firmware->getBoard())) { ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0);
ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0); ui->telemetryProtocol->addItem(tr("FrSky D"), 1);
ui->telemetryProtocol->addItem(tr("FrSky D"), 1); if (IS_9XRPRO(firmware->getBoard()) ||
if (IS_9XRPRO(firmware->getBoard()) || (IS_TARANIS(firmware->getBoard()) && generalSettings.auxSerialMode == 2)) {
(IS_TARANIS(firmware->getBoard()) && generalSettings.auxSerialMode == 2)) { ui->telemetryProtocol->addItem(tr("FrSky D (cable)"), 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->setCurrentIndex(model->telemetryProtocol);
ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this);
ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled);
ui->rssiAlarmWarningSB->setValue(model->rssiAlarms.warning); ui->rssiAlarmWarningSB->setValue(model->rssiAlarms.warning);
ui->rssiAlarmCriticalSB->setValue(model->rssiAlarms.critical); 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->rssiSourceLabel->show();
ui->rssiAlarmCriticalCB->hide(); ui->rssiSourceLabel->setText(tr("Source"));
ui->rssiAlarmWarningLabel->setText(tr("Low Alarm")); ui->rssiSourceCB->setField(model->rssiSource, this);
ui->rssiAlarmCriticalLabel->setText(tr("Critical Alarm")); ui->rssiSourceCB->show();
} populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false);
/*if (IS_ARM(firmware->getBoard())) { ui->rssiAlarmWarningCB->hide();
for (int i=0; i<CPN_MAX_SENSORS; ++i) { ui->rssiAlarmCriticalCB->hide();
TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model->, model, generalSettings, firmware); ui->rssiAlarmWarningLabel->setText(tr("Low Alarm"));
ui->sensorsLayout->addWidget(panel); ui->rssiAlarmCriticalLabel->setText(tr("Critical Alarm"));
sensorPanels[i] = panel;
}
}*/
int varioCap = firmware->getCapability(HasVario); int varioCap = firmware->getCapability(HasVario);
if (!varioCap) { if (!varioCap) {
@ -1100,16 +813,16 @@ void TelemetryPanel::setup()
ui->VarioLabel_1->hide(); ui->VarioLabel_1->hide();
ui->VarioLabel_2->hide(); ui->VarioLabel_2->hide();
} }
ui->varioLimitMin_DSB->setValue(model->frsky.varioMin-10); ui->varioLimitMin_DSB->setValue(model->frsky.varioMin - 10);
ui->varioLimitMax_DSB->setValue(model->frsky.varioMax+10); ui->varioLimitMax_DSB->setValue(model->frsky.varioMax + 10);
ui->varioLimitCenterMax_DSB->setValue((model->frsky.varioCenterMax/10.0)+0.5); ui->varioLimitCenterMax_DSB->setValue((model->frsky.varioCenterMax / 10.0) + 0.5);
ui->varioLimitCenterMin_DSB->setValue((model->frsky.varioCenterMin/10.0)-0.5); ui->varioLimitCenterMin_DSB->setValue((model->frsky.varioCenterMin / 10.0) - 0.5);
} }
ui->altimetryGB->setVisible(firmware->getCapability(HasVario)), ui->altimetryGB->setVisible(firmware->getCapability(HasVario)),
ui->frskyProtoCB->setDisabled(firmware->getCapability(NoTelemetryProtocol)); ui->frskyProtoCB->setDisabled(firmware->getCapability(NoTelemetryProtocol));
if (firmware->getCapability(Telemetry) & TM_HASWSHH) { if (firmware->getCapability(Telemetry)) {
ui->frskyProtoCB->addItem(tr("Winged Shadow How High")); ui->frskyProtoCB->addItem(tr("Winged Shadow How High"));
} }
else { else {
@ -1117,38 +830,6 @@ void TelemetryPanel::setup()
} }
ui->variousGB->hide(); 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; lock = false;
} }
@ -1170,10 +851,8 @@ void TelemetryPanel::populateVoltsSource()
cb->setField(model->frsky.voltsSource, this); cb->setField(model->frsky.voltsSource, this);
cb->addItem(tr("A1"), TELEMETRY_VOLTS_SOURCE_A1); cb->addItem(tr("A1"), TELEMETRY_VOLTS_SOURCE_A1);
cb->addItem(tr("A2"), TELEMETRY_VOLTS_SOURCE_A2); cb->addItem(tr("A2"), TELEMETRY_VOLTS_SOURCE_A2);
if (IS_ARM(firmware->getBoard())) { cb->addItem(tr("A3"), TELEMETRY_VOLTS_SOURCE_A3);
cb->addItem(tr("A3"), TELEMETRY_VOLTS_SOURCE_A3); cb->addItem(tr("A4"), TELEMETRY_VOLTS_SOURCE_A4);
cb->addItem(tr("A4"), TELEMETRY_VOLTS_SOURCE_A4);
}
cb->addItem(tr("FAS"), TELEMETRY_VOLTS_SOURCE_FAS); cb->addItem(tr("FAS"), TELEMETRY_VOLTS_SOURCE_FAS);
cb->addItem(tr("Cells"), TELEMETRY_VOLTS_SOURCE_CELLS); 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("---"), TELEMETRY_CURRENT_SOURCE_NONE);
cb->addItem(tr("A1"), TELEMETRY_CURRENT_SOURCE_A1); cb->addItem(tr("A1"), TELEMETRY_CURRENT_SOURCE_A1);
cb->addItem(tr("A2"), TELEMETRY_CURRENT_SOURCE_A2); cb->addItem(tr("A2"), TELEMETRY_CURRENT_SOURCE_A2);
if (IS_ARM(firmware->getBoard())) { cb->addItem(tr("A3"), TELEMETRY_CURRENT_SOURCE_A3);
cb->addItem(tr("A3"), TELEMETRY_CURRENT_SOURCE_A3); cb->addItem(tr("A4"), TELEMETRY_CURRENT_SOURCE_A4);
cb->addItem(tr("A4"), TELEMETRY_CURRENT_SOURCE_A4);
}
cb->addItem(tr("FAS"), TELEMETRY_CURRENT_SOURCE_FAS); cb->addItem(tr("FAS"), TELEMETRY_CURRENT_SOURCE_FAS);
} }
@ -1217,24 +894,12 @@ void TelemetryPanel::on_frskyProtoCB_currentIndexChanged(int index)
{ {
if (!lock) { if (!lock) {
model->frsky.usrProto = index; model->frsky.usrProto = index;
for (int i=0; i<firmware->getCapability(TelemetryCustomScreens); i++) for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++)
telemetryCustomScreens[i]->update(); telemetryCustomScreens[i]->update();
emit modified(); 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() void TelemetryPanel::on_rssiAlarmWarningSB_editingFinished()
{ {
model->rssiAlarms.warning= ui->rssiAlarmWarningSB->value(); model->rssiAlarms.warning= ui->rssiAlarmWarningSB->value();
@ -1249,23 +914,23 @@ void TelemetryPanel::on_rssiAlarmCriticalSB_editingFinished()
void TelemetryPanel::on_varioLimitMin_DSB_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(); emit modified();
} }
void TelemetryPanel::on_varioLimitMax_DSB_editingFinished() 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(); emit modified();
} }
void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished() void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished()
{ {
if (!lock) { 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()); 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(); emit modified();
} }
} }
@ -1273,10 +938,10 @@ void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished()
void TelemetryPanel::on_varioLimitCenterMax_DSB_editingFinished() void TelemetryPanel::on_varioLimitCenterMax_DSB_editingFinished()
{ {
if (!lock) { 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()); 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(); emit modified();
} }
} }
@ -1304,8 +969,56 @@ void TelemetryPanel::on_clearAllSensors()
{ {
for (int i = 0; i < CPN_MAX_SENSORS; i++) { for (int i = 0; i < CPN_MAX_SENSORS; i++) {
model->sensorData[i].clear(); model->sensorData[i].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, i);
} }
update(); update();
emit modified(); 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();
}
}

View file

@ -31,45 +31,11 @@ class RawSourceFilterItemModel;
class TimerEdit; class TimerEdit;
namespace Ui { namespace Ui {
class TelemetryAnalog;
class TelemetryCustomScreen; class TelemetryCustomScreen;
class TelemetrySensor; class TelemetrySensor;
class Telemetry; 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 class TelemetryCustomScreen: public ModelPanel
{ {
Q_OBJECT Q_OBJECT
@ -105,13 +71,18 @@ class TelemetrySensorPanel: public ModelPanel
Q_OBJECT Q_OBJECT
public: 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(); ~TelemetrySensorPanel();
void update(); void update();
signals: signals:
void dataModified(); void dataModified();
void clearAllSensors(); void clearAllSensors();
void insertSensor(int index);
void deleteSensor(int index);
void moveUpSensor(int index);
void moveDownSensor(int index);
protected slots: protected slots:
void on_name_editingFinished(); void on_name_editingFinished();
@ -124,8 +95,12 @@ class TelemetrySensorPanel: public ModelPanel
void cmCopy(); void cmCopy();
void cmCut(); void cmCut();
void cmPaste(); void cmPaste();
void cmClear(); void cmClear(bool prompt = true);
void cmClearAll(); void cmClearAll();
void cmInsert();
void cmDelete();
void cmMoveUp();
void cmMoveDown();
protected: protected:
void updateSourcesComboBox(AutoComboBox * cb, bool negative); void updateSourcesComboBox(AutoComboBox * cb, bool negative);
@ -136,6 +111,10 @@ class TelemetrySensorPanel: public ModelPanel
bool lock = false; bool lock = false;
int sensorIndex = 0; int sensorIndex = 0;
int selectedIndex = 0; int selectedIndex = 0;
int sensorCapability;
bool insertAllowed() const;
bool moveDownAllowed() const;
bool moveUpAllowed() const;
}; };
class TelemetryPanel : public ModelPanel class TelemetryPanel : public ModelPanel
@ -155,8 +134,6 @@ class TelemetryPanel : public ModelPanel
void onModified(); void onModified();
void on_frskyProtoCB_currentIndexChanged(int index); void on_frskyProtoCB_currentIndexChanged(int index);
void on_bladesCount_editingFinished(); void on_bladesCount_editingFinished();
void on_rssiAlarmWarningCB_currentIndexChanged(int index);
void on_rssiAlarmCriticalCB_currentIndexChanged(int index);
void on_rssiAlarmWarningSB_editingFinished(); void on_rssiAlarmWarningSB_editingFinished();
void on_rssiAlarmCriticalSB_editingFinished(); void on_rssiAlarmCriticalSB_editingFinished();
void on_varioLimitMin_DSB_editingFinished(); void on_varioLimitMin_DSB_editingFinished();
@ -167,18 +144,23 @@ class TelemetryPanel : public ModelPanel
void on_mahCount_SB_editingFinished(); void on_mahCount_SB_editingFinished();
void on_mahCount_ChkB_toggled(bool checked); void on_mahCount_ChkB_toggled(bool checked);
void on_clearAllSensors(); void on_clearAllSensors();
void on_insertSensor(int index);
void on_deleteSensor(int index);
void on_moveUpSensor(int index);
void on_moveDownSensor(int index);
private: private:
Ui::Telemetry *ui; Ui::Telemetry *ui;
TelemetryAnalog * analogs[4];
TelemetryCustomScreen * telemetryCustomScreens[4]; TelemetryCustomScreen * telemetryCustomScreens[4];
TelemetrySensorPanel * sensorPanels[CPN_MAX_SENSORS]; TelemetrySensorPanel * sensorPanels[CPN_MAX_SENSORS];
int sensorCapability;
void setup(); void setup();
void telBarUpdate(); void telBarUpdate();
void populateVoltsSource(); void populateVoltsSource();
void populateCurrentSource(); void populateCurrentSource();
void populateVarioSource(); void populateVarioSource();
void swapData(int idx1, int idx2);
}; };
#endif // _TELEMETRY_H_ #endif // _TELEMETRY_H_

View file

@ -212,7 +212,7 @@ QString ModelPrinter::printModule(int idx)
str << printLabelValue(tr("Delay"), QString("%1us").arg(module.ppm.delay)); str << printLabelValue(tr("Delay"), QString("%1us").arg(module.ppm.delay));
} }
else { 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)); str << printLabelValue(tr("Receiver"), QString::number(module.modelId));
} }
if (module.protocol == PULSES_MULTIMODULE) { if (module.protocol == PULSES_MULTIMODULE) {
@ -224,6 +224,11 @@ QString ModelPrinter::printModule(int idx)
str << printLabelValue(tr("Sub Type"), module.subTypeToString()); str << printLabelValue(tr("Sub Type"), module.subTypeToString());
str << printLabelValue(tr("RF Output Power"), module.powerValueToString(firmware)); 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(" "); result = str.join(" ");
@ -968,8 +973,7 @@ QString ModelPrinter::printSettingsTrim()
{ {
QStringList str; QStringList str;
str << printLabelValue(tr("Step"), printTrimIncrementMode()); 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)); str << printLabelValue(tr("Extended"), printBoolean(model.extendedTrims, BOOLEAN_YESNO));
return str.join(" "); return str.join(" ");
} }

View file

@ -292,7 +292,7 @@ QString MultiModelPrinter::print(QTextDocument * document)
if (firmware->getCapability(GlobalFunctions)) if (firmware->getCapability(GlobalFunctions))
str.append(printGlobalFunctions()); str.append(printGlobalFunctions());
str.append(printSpecialFunctions()); str.append(printSpecialFunctions());
if (firmware->getCapability(Telemetry) & TM_HASTELEMETRY) { if (firmware->getCapability(Telemetry)) {
str.append(printTelemetry()); str.append(printTelemetry());
str.append(printSensors()); str.append(printSensors());
if (firmware->getCapability(TelemetryCustomScreens)) { if (firmware->getCapability(TelemetryCustomScreens)) {
@ -310,7 +310,9 @@ QString MultiModelPrinter::printSetup()
MultiColumns columns(modelPrinterMap.size()); MultiColumns columns(modelPrinterMap.size());
columns.appendSectionTableStart(); columns.appendSectionTableStart();
ROWLABELCOMPARECELL(tr("Name"), 20, model->name, 80); 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)) { if (firmware->getCapability(ModelImage)) {
ROWLABELCOMPARECELL(tr("Model Image"), 0, model->bitmap, 0); ROWLABELCOMPARECELL(tr("Model Image"), 0, model->bitmap, 0);
} }
@ -751,32 +753,19 @@ QString MultiModelPrinter::printTelemetry()
MultiColumns columns(modelPrinterMap.size()); MultiColumns columns(modelPrinterMap.size());
columns.appendSectionTableStart(); columns.appendSectionTableStart();
// Analogs on non ARM boards // Protocol
if (!IS_ARM(firmware->getBoard())) { columns.appendRowStart(tr("Protocol"), 20);
columns.appendRowHeader(QStringList() << tr("Analogs") << tr("Unit") << tr("Scale") << tr("Offset")); COMPARECELL(modelPrinter->printTelemetryProtocol(model->telemetryProtocol));
for (int i=0; i<2; i++) { columns.appendRowEnd();
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();
}
// RSSI alarms // RSSI alarms
{ {
columns.appendRowStart(tr("RSSI Alarms"), 20); columns.appendRowStart(tr("RSSI Alarms"), 20);
columns.appendCellStart(80); columns.appendCellStart(80);
COMPARESTRING("", (IS_ARM(getCurrentBoard()) ? tr("Low") : FrSkyAlarmData::alarmLevelName(model->rssiAlarms.level[0])), false); COMPARESTRING("", tr("Low"), false);
columns.append(": "); columns.append(": ");
COMPARESTRING("", QString("&lt; %1").arg(QString::number(model->rssiAlarms.warning, 10)), true); COMPARESTRING("", QString("&lt; %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(": "); columns.append(": ");
COMPARESTRING("", QString("&lt; %1").arg(QString::number(model->rssiAlarms.critical, 10)), true); COMPARESTRING("", QString("&lt; %1").arg(QString::number(model->rssiAlarms.critical, 10)), true);
COMPARESTRING(tr("Telemetry audio"), modelPrinter->printRssiAlarmsDisabled(model->rssiAlarms.disabled), false); COMPARESTRING(tr("Telemetry audio"), modelPrinter->printRssiAlarmsDisabled(model->rssiAlarms.disabled), false);
@ -818,39 +807,9 @@ QString MultiModelPrinter::printTelemetry()
columns.appendRowEnd(); 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 // 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(); columns.appendTableEnd();
str.append(columns.print()); str.append(columns.print());
return str; return str;

View file

@ -28,6 +28,7 @@ ProfileChooserDialog::ProfileChooserDialog(QWidget * parent):
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowIcon(QIcon(":/icon.png")); setWindowIcon(QIcon(":/icon.png"));
setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
QComboBox *prof = ui->cboProfiles; QComboBox *prof = ui->cboProfiles;
prof->clear(); prof->clear();

View file

@ -36,43 +36,8 @@ QString getRadioInterfaceCmd()
if (IS_STM32(board)) { if (IS_STM32(board)) {
return bcd.getDFU(); return bcd.getDFU();
} }
else if (IS_SKY9X(board)) { else
return bcd.getSAMBA(); 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) QStringList getDfuArgs(const QString & cmd, const QString & filename)
@ -119,11 +84,8 @@ QStringList getReadEEpromCmd(const QString & filename)
if (IS_STM32(eepromInterface->getBoard())) { if (IS_STM32(eepromInterface->getBoard())) {
// impossible // impossible
} }
else if (IS_SKY9X(eepromInterface->getBoard())) {
result = getSambaArgs(QString("SERIALFLASH::Init 0\n") + "receive_file {SerialFlash AT25} \"" + filename + "\" 0x0 0x80000 0\n");
}
else { else {
result = getAvrdudeArgs("eeprom:r:", filename); result = getSambaArgs(QString("SERIALFLASH::Init 0\n") + "receive_file {SerialFlash AT25} \"" + filename + "\" 0x0 0x80000 0\n");
} }
return result; return result;
} }
@ -135,11 +97,8 @@ QStringList getWriteEEpromCmd(const QString & filename)
// impossible // impossible
return QStringList(); return QStringList();
} }
else if (IS_SKY9X(board)) {
return getSambaArgs(QString("SERIALFLASH::Init 0\n") + "send_file {SerialFlash AT25} \"" + filename + "\" 0x0 0\n");
}
else { 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) { else if (board == Board::BOARD_SKY9X) {
return getSambaArgs(QString("send_file {Flash} \"") + filename + "\" 0x400000 0\n" + "FLASH::ScriptGPNMV 2\n"); 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 { 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) { else if (board == Board::BOARD_SKY9X) {
return getSambaArgs(QString("receive_file {Flash} \"") + filename + "\" 0x400000 0x40000 0\n"); 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 { else {
return getAvrdudeArgs("flash:r:", filename); return getSambaArgs(QString("receive_file {Flash} \"") + filename + "\" 0x400000 0x80000 0\n");
}
}
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",
"<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?").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();
} }
} }
@ -264,13 +141,11 @@ bool readFirmware(const QString & filename, ProgressWidget * progress)
return false; return false;
} }
if (IS_ARM(getCurrentBoard())) { QString path = findMassstoragePath("FIRMWARE.BIN");
QString path = findMassstoragePath("FIRMWARE.BIN"); if (!path.isEmpty()) {
if (!path.isEmpty()) { qDebug() << "readFirmware: reading" << path << "into" << filename;
qDebug() << "readFirmware: reading" << path << "into" << filename; CopyProcess copyProcess(path, filename, progress);
CopyProcess copyProcess(path, filename, progress); result = copyProcess.run();
result = copyProcess.run();
}
} }
if (!result) { if (!result) {
@ -288,13 +163,11 @@ bool readFirmware(const QString & filename, ProgressWidget * progress)
bool writeFirmware(const QString & filename, ProgressWidget * progress) bool writeFirmware(const QString & filename, ProgressWidget * progress)
{ {
if (IS_ARM(getCurrentBoard())) { QString path = findMassstoragePath("FIRMWARE.BIN");
QString path = findMassstoragePath("FIRMWARE.BIN"); if (!path.isEmpty()) {
if (!path.isEmpty()) { qDebug() << "writeFirmware: writing" << path << "from" << filename;
qDebug() << "writeFirmware: writing" << path << "from" << filename; CopyProcess copyProcess(filename, path, progress);
CopyProcess copyProcess(filename, path, progress); return copyProcess.run();
return copyProcess.run();
}
} }
qDebug() << "writeFirmware: writing" << filename << "with" << getRadioInterfaceCmd() << getWriteFirmwareArgs(filename); qDebug() << "writeFirmware: writing" << filename << "with" << getRadioInterfaceCmd() << getWriteFirmwareArgs(filename);
@ -339,26 +212,25 @@ bool readEeprom(const QString & filename, ProgressWidget * progress)
} }
} }
else { else {
if (IS_ARM(board)) { QString path = findMassstoragePath("EEPROM.BIN");
QString path = findMassstoragePath("EEPROM.BIN"); if (path.isEmpty()) {
if (path.isEmpty()) { // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :(
// On previous OpenTX we called the EEPROM file "TARANIS.BIN" :( path = findMassstoragePath("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 (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)) { if (!IS_STM32(board)) {
FlashProcess flashProcess(getRadioInterfaceCmd(), getReadEEpromCmd(filename), progress); FlashProcess flashProcess(getRadioInterfaceCmd(), getReadEEpromCmd(filename), progress);
@ -375,20 +247,18 @@ bool writeEeprom(const QString & filename, ProgressWidget * progress)
{ {
Board::Type board = getCurrentBoard(); Board::Type board = getCurrentBoard();
if (IS_ARM(board)) { QString path = findMassstoragePath("EEPROM.BIN");
QString path = findMassstoragePath("EEPROM.BIN"); if (path.isEmpty()) {
if (path.isEmpty()) { // On previous OpenTX we called the EEPROM file "TARANIS.BIN" :(
// On previous OpenTX we called the EEPROM file "TARANIS.BIN" :( path = findMassstoragePath("TARANIS.BIN");
path = findMassstoragePath("TARANIS.BIN"); }
} if (path.isEmpty()) {
if (path.isEmpty()) { // Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :(
// Mike's bootloader calls the EEPROM file "ERSKY9X.BIN" :( path = findMassstoragePath("ERSKY9X.BIN");
path = findMassstoragePath("ERSKY9X.BIN"); }
} if (!path.isEmpty()) {
if (!path.isEmpty()) { CopyProcess copyProcess(filename, path, progress);
CopyProcess copyProcess(filename, path, progress); return copyProcess.run();
return copyProcess.run();
}
} }
if (!IS_TARANIS(board)) { if (!IS_TARANIS(board)) {
@ -396,10 +266,8 @@ bool writeEeprom(const QString & filename, ProgressWidget * progress)
return flashProcess.run(); return flashProcess.run();
} }
if (IS_ARM(board)) { RadioNotFoundDialog dialog(progress);
RadioNotFoundDialog dialog(progress); dialog.exec();
dialog.exec();
}
return false; return false;
} }

View file

@ -30,13 +30,9 @@ QString getRadioInterfaceCmd();
QString findMassstoragePath(const QString &filename, bool onlyPath = false); QString findMassstoragePath(const QString &filename, bool onlyPath = false);
QStringList getAvrdudeArgs(const QString &cmd, const QString &filename);
QStringList getSambaArgs(const QString &tcl); QStringList getSambaArgs(const QString &tcl);
QStringList getDfuArgs(const QString &cmd, const QString &filename); QStringList getDfuArgs(const QString &cmd, const QString &filename);
void readAvrdudeFuses(ProgressWidget *progress);
void resetAvrdudeFuses(bool eepromProtect, ProgressWidget *progress);
QStringList getReadEEpromCmd(const QString &filename); QStringList getReadEEpromCmd(const QString &filename);
QStringList getWriteEEpromCmd(const QString &filename); QStringList getWriteEEpromCmd(const QString &filename);
QStringList getReadFirmwareArgs(const QString &filename); QStringList getReadFirmwareArgs(const QString &filename);

View file

@ -14,6 +14,7 @@ set(simulation_SRCS
simulateduiwidgetX12.cpp simulateduiwidgetX12.cpp
simulateduiwidgetJumperT12.cpp simulateduiwidgetJumperT12.cpp
simulateduiwidgetJumperT16.cpp simulateduiwidgetJumperT16.cpp
simulateduiwidgetJumperT18.cpp
simulateduiwidgetTX16S.cpp simulateduiwidgetTX16S.cpp
simulatorinterface.cpp simulatorinterface.cpp
simulatormainwindow.cpp simulatormainwindow.cpp
@ -39,6 +40,7 @@ set(simulation_UIS
simulateduiwidgetX12.ui simulateduiwidgetX12.ui
simulateduiwidgetJumperT12.ui simulateduiwidgetJumperT12.ui
simulateduiwidgetJumperT16.ui simulateduiwidgetJumperT16.ui
simulateduiwidgetJumperT18.ui
simulateduiwidgetTX16S.ui simulateduiwidgetTX16S.ui
simulatormainwindow.ui simulatormainwindow.ui
simulatorstartupdialog.ui simulatorstartupdialog.ui

View file

@ -113,6 +113,7 @@ namespace Ui {
class SimulatedUIWidgetX12; class SimulatedUIWidgetX12;
class SimulatedUIWidgetJumperT12; class SimulatedUIWidgetJumperT12;
class SimulatedUIWidgetJumperT16; class SimulatedUIWidgetJumperT16;
class SimulatedUIWidgetJumperT18;
class SimulatedUIWidgetTX16S; class SimulatedUIWidgetTX16S;
} }
@ -252,6 +253,18 @@ class SimulatedUIWidgetJumperT16: public SimulatedUIWidget
Ui::SimulatedUIWidgetJumperT16 * ui; 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 class SimulatedUIWidgetTX16S: public SimulatedUIWidget
{ {
Q_OBJECT Q_OBJECT

View file

@ -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<int>() << 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<int>() << 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<int>() << 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<int>() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace,
SIMU_STR_HLP_KEY_DN % "<br>" % 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<int>() << 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<int>() << 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<int>() << 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<int>() << 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;
}

View file

@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SimulatedUIWidgetJumperT18</class>
<widget class="QWidget" name="SimulatedUIWidgetJumperT18">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>825</width>
<height>292</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>825</width>
<height>292</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>825</width>
<height>292</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="2" rowspan="3">
<widget class="ButtonsWidget" name="rightbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>131 </width>
<height>289</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>131</width>
<height>289</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/JumperT18/right.png)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LcdWidget" name="lcd" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>272</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>272</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
</font>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<widget class="ButtonsWidget" name="leftbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>131</width>
<height>289</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>131</width>
<height>289</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/JumperT18/left.png);</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QWidget" name="top" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>10</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/JumperT18/top.png)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QWidget" name="bottom" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>10</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
<kerning>false</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/JumperT18/bottom.png)</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LcdWidget</class>
<extends>QWidget</extends>
<header>lcdwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ButtonsWidget</class>
<extends>QWidget</extends>
<header>buttonswidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -86,7 +86,7 @@ void SimulatorStartupDialog::changeEvent(QEvent *e)
// FIXME : need a better way to check for this // FIXME : need a better way to check for this
bool SimulatorStartupDialog::usesCategorizedStorage(const QString & name) 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() bool SimulatorStartupDialog::usesCategorizedStorage()

View file

@ -94,6 +94,9 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato
case Board::BOARD_JUMPER_T16: case Board::BOARD_JUMPER_T16:
radioUiWidget = new SimulatedUIWidgetJumperT16(simulator, this); radioUiWidget = new SimulatedUIWidgetJumperT16(simulator, this);
break; break;
case Board::BOARD_JUMPER_T18:
radioUiWidget = new SimulatedUIWidgetJumperT18(simulator, this);
break;
case Board::BOARD_RADIOMASTER_TX16S: case Board::BOARD_RADIOMASTER_TX16S:
radioUiWidget = new SimulatedUIWidgetTX16S(simulator, this); radioUiWidget = new SimulatedUIWidgetTX16S(simulator, this);
break; break;

View file

@ -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; eeFsArm = (EeFsArm *)eeprom;
eeFsVersion = 5; eeFsVersion = 5;
eeFsSize = 8+4*62; eeFsSize = 8+4*62;
@ -84,36 +84,6 @@ void RleFile::EeFsCreate(uint8_t *eeprom, int size, Board::Type board, unsigned
eeFsArm->freeList = eeFsFirstBlock; eeFsArm->freeList = eeFsFirstBlock;
// EeFsFlush(); // 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; i<eeFsBlocksMax-1; i++)
EeFsSetLink(i, i+1);
EeFsSetLink(eeFsBlocksMax-1, 0);
eeFs->freeList = eeFsFirstBlock;
// EeFsFlush();
}
} }
PACK(struct EepromFileHeader PACK(struct EepromFileHeader
@ -146,7 +116,7 @@ bool RleFile::EeFsOpen(uint8_t *eeprom, int size, Board::Type board)
searchFat(); searchFat();
return 1; return 1;
} }
else if (IS_TARANIS(board)) { else {
eeFsArm = (EeFsArm *)eeprom; eeFsArm = (EeFsArm *)eeprom;
eeFsVersion = eeFsArm->version; eeFsVersion = eeFsArm->version;
eeFsSize = 8+4*62; 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; eeFsBlocksMax = 1 + (Boards::getEEpromSize(board)-eeFsSize) / eeFsBlockSize;
return eeFsArm->mySize == eeFsSize; 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) 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) unsigned int RleFile::EeFsGetLink(unsigned int blk)
{ {
if (IS_ARM(board)) { int16_t ret;
int16_t ret; eeprom_read_block((uint8_t *)&ret, blk*eeFsBlockSize+eeFsBlocksOffset, eeFsLinkSize);
eeprom_read_block((uint8_t *)&ret, blk*eeFsBlockSize+eeFsBlocksOffset, eeFsLinkSize); return ret;
return ret;
}
else {
return EeFsRead(blk, 0);
}
} }
void RleFile::EeFsSetLink(unsigned int blk, unsigned int val) void RleFile::EeFsSetLink(unsigned int blk, unsigned int val)
{ {
if (IS_ARM(board)) { int16_t s_link = val;
int16_t s_link = val; eeprom_write_block((uint8_t *)&s_link, (blk*eeFsBlockSize)+eeFsBlocksOffset, eeFsLinkSize);
eeprom_write_block((uint8_t *)&s_link, (blk*eeFsBlockSize)+eeFsBlocksOffset, eeFsLinkSize);
}
else {
EeFsWrite(blk, 0, val);
}
} }
uint8_t RleFile::EeFsGetDat(unsigned int blk, unsigned int ofs) uint8_t RleFile::EeFsGetDat(unsigned int blk, unsigned int ofs)
@ -244,10 +182,7 @@ unsigned int RleFile::EeFsGetFree()
unsigned int ret = 0; unsigned int ret = 0;
unsigned int i; unsigned int i;
if (IS_ARM(board)) i = eeFsArm->freeList;
i = eeFsArm->freeList;
else
i = eeFs->freeList;
while (i) { while (i) {
ret += eeFsBlockSize-eeFsLinkSize; ret += eeFsBlockSize-eeFsLinkSize;
@ -266,14 +201,8 @@ void RleFile::EeFsFree(unsigned int blk)
unsigned int i = blk; unsigned int i = blk;
while (EeFsGetLink(i)) i = EeFsGetLink(i); while (EeFsGetLink(i)) i = EeFsGetLink(i);
if (IS_ARM(board)) { EeFsSetLink(i, eeFsArm->freeList);
EeFsSetLink(i, eeFsArm->freeList); eeFsArm->freeList = blk; //chain in front
eeFsArm->freeList = blk; //chain in front
}
else {
EeFsSetLink(i, eeFs->freeList);
eeFs->freeList = blk; //chain in front
}
} }
/* /*
@ -283,12 +212,9 @@ unsigned int RleFile::EeFsAlloc()
{ {
if (IS_FAMILY_HORUS_OR_T16(board)) if (IS_FAMILY_HORUS_OR_T16(board))
return 0; return 0;
unsigned int ret = (IS_ARM(board) ? eeFsArm->freeList : eeFs->freeList); unsigned int ret = eeFsArm->freeList;
if (ret) { if (ret) {
if (IS_ARM(board)) eeFsArm->freeList = EeFsGetLink(ret);
eeFsArm->freeList = EeFsGetLink(ret);
else
eeFs->freeList = EeFsGetLink(ret);
EeFsSetLink(ret, 0); EeFsSetLink(ret, 0);
} }
return ret; return ret;
@ -299,7 +225,7 @@ unsigned int RleFile::size(unsigned int id)
if (IS_FAMILY_HORUS_OR_T16(board)) if (IS_FAMILY_HORUS_OR_T16(board))
return 0; return 0;
else 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) unsigned int RleFile::openRd(unsigned int i_fileId)
@ -327,15 +253,12 @@ unsigned int RleFile::openRd(unsigned int i_fileId)
else { else {
m_fileId = i_fileId; m_fileId = i_fileId;
m_pos = 0; 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_ofs = 0;
m_zeroes = 0; m_zeroes = 0;
m_bRlc = 0; m_bRlc = 0;
m_err = ERR_NONE; //error reasons m_err = ERR_NONE; //error reasons
if (IS_ARM(board)) return eeFsArm->files[m_fileId].typ;
return eeFsArm->files[m_fileId].typ;
else
return eeFs->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)) if (IS_FAMILY_HORUS_OR_T16(board))
return 0; 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; len -= m_pos;
if (i_len > len) i_len = len; if (i_len > len) i_len = len;
len = i_len; len = i_len;
while(len) { while(len) {
if (!m_currBlk) break; if (!m_currBlk) break;
*buf++ = EeFsGetDat(m_currBlk, m_ofs++); *buf++ = EeFsGetDat(m_currBlk, m_ofs++);
if (m_ofs >= (eeFsBlockSize-(IS_ARM(board)? 2 : 1))) { if (m_ofs >= (eeFsBlockSize - 2)) {
m_ofs = 0; m_ofs = 0;
m_currBlk = EeFsGetLink(m_currBlk); 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; unsigned int len = i_len;
if (!m_currBlk && m_pos==0) if (!m_currBlk && m_pos==0)
{ {
if (IS_ARM(board)) eeFsArm->files[m_fileId].startBlk = m_currBlk = EeFsAlloc();
eeFsArm->files[m_fileId].startBlk = m_currBlk = EeFsAlloc();
else
eeFs->files[m_fileId].startBlk = m_currBlk = EeFsAlloc();
} }
while (len) 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) void RleFile::create(unsigned int i_fileId, unsigned int typ)
{ {
openRd(i_fileId); //internal use openRd(i_fileId); //internal use
if (IS_ARM(board)) { eeFsArm->files[i_fileId].typ = typ;
eeFsArm->files[i_fileId].typ = typ; eeFsArm->files[i_fileId].size = 0;
eeFsArm->files[i_fileId].size = 0;
}
else {
eeFs->files[i_fileId].typ = typ;
eeFs->files[i_fileId].size = 0;
}
} }
void RleFile::closeTrunc() void RleFile::closeTrunc()
{ {
unsigned int fri=0; unsigned int fri=0;
if (IS_ARM(board)) eeFsArm->files[m_fileId].size = m_pos;
eeFsArm->files[m_fileId].size = m_pos;
else
eeFs->files[m_fileId].size = m_pos;
if (m_currBlk && ( fri = EeFsGetLink(m_currBlk))) EeFsSetLink(m_currBlk, 0); if (m_currBlk && ( fri = EeFsGetLink(m_currBlk))) EeFsSetLink(m_currBlk, 0);
if(fri) EeFsFree( fri ); //chain in if(fri) EeFsFree( fri ); //chain in
} }

File diff suppressed because it is too large Load diff

View file

@ -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) void WizMix::addMix(ModelData &model, Input input, int weight, int channel, int & mixIndex)
{ {
if (input != NO_INPUT) { if (input != NO_INPUT) {
bool isHorusOrTaranis = IS_ARM(getCurrentBoard());
if (input >= RUDDER_INPUT && input <= AILERONS_INPUT) { if (input >= RUDDER_INPUT && input <= AILERONS_INPUT) {
MixData & mix = model.mixData[mixIndex++]; MixData & mix = model.mixData[mixIndex++];
mix.destCh = channel+1; 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); int channel = settings.getDefaultChannel(input-1);
mix.srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, channel); mix.srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, channel);
} }
else
mix.srcRaw = RawSource(SOURCE_TYPE_STICK, input-1);
mix.weight = weight; mix.weight = weight;
} }
else if (input==FLAPS_INPUT){ else if (input==FLAPS_INPUT){
// There ought to be some kind of constants for switches somewhere... // 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 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, isHorusOrTaranis ? SWITCH_SA2 : SWITCH_ELE , -weight); //Taranis-Horus SA-DOWN, 9X ELE-DOWN 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){ 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 *)"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, isHorusOrTaranis ? SWITCH_SE2 : SWITCH_RUD , weight); //Tatanis-Horus SE-DOWN, 9X RUD-DOWN 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.srcRaw = SOURCE_TYPE_MAX;
mix.weight = -100; mix.weight = -100;
mix.swtch.type = SWITCH_TYPE_SWITCH; 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; mix.mltpx = MLTPX_REP;
memset(mix.name, 0, sizeof(mix.name)); memset(mix.name, 0, sizeof(mix.name));
strncpy(mix.name, "Cut", MIXDATA_NAME_LEN); strncpy(mix.name, "Cut", MIXDATA_NAME_LEN);

View file

@ -15,9 +15,6 @@ STM32_OPTIONS = -DLUA=YES
build: build:
mkdir $(BUILDDIR); 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=SKY9X ../ ; make libsimulator
cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=9XRPRO ../ ; make libsimulator cd $(BUILDDIR); cmake $(COMMON_OPTIONS) -DPCB=9XRPRO ../ ; make libsimulator

View file

@ -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 }

View file

@ -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 }

View file

@ -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,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
1,1,Flysky,V9x9,1,Flip,Light,Pict,Video 1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL 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,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,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 28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
53,0,Flyzone,FZ-410,0 28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess 28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
2,1,Hubsan,H301,0,RTH,Light,Stab,Video 56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes 53,0,Height,5ch,0,Gear
41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED 53,1,Height,8ch,0,Gear,Gyro,Flap,Light
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8 25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8 3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
3,0,FrSkyD,D8Cloned,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,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,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,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,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,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,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,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,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,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
55,1,FrSkyRX,CloneTX,0 55,1,FrSkyRX,CloneTX,0
39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9 58,0,FX816,P38,1
39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
57,0,HoTT,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8
68,0,Skyartec,Std,0,CH5,CH6,CH7
7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
7,3,Devo,6CH,0,CH5,CH6
7,4,Devo,7CH,0,CH5,CH6,CH7
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
30,1,WK2x01,WK2401,0
30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
24,0,Assan,Std,0,CH5,CH6,CH7,CH8
14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
12,0,CX10,Green,1,Flip,Rate
12,1,CX10,Blue,1,Flip,Rate,Pict,Video
12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
16,0,ESKY,Std,0,Gyro,Pitch
16,1,ESKY,ET4,0,Gyro,Pitch
35,0,ESKY150,4CH,0
35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib 20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
20,1,FY326,FY319,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 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 32,0,GW008,FY326,1,Flip
36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1 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,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,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 36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8 4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim 4,1,Hisky,HK310,0,Aux
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim 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,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
26,1,Hontai,JJRCX1,1,Flip,Arm,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,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
26,3,Hontai,FQ777_951,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,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,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate 18,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,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess 17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
44,0,NCC1701,Std,1,Warp 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 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 66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal 29,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,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
31,2,Q303,CX10D,1,Arm,Flip 31,2,Q303,CX10D,1,Arm,Flip
31,3,Q303,CX10WD,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,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 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,0,SLT,V1,0,Gear,Pitch
11,1,SLT,V2,0,CH5,CH6,CH7,CH8 11,1,SLT,V2,0,CH5,CH6,CH7,CH8
11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib 11,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 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,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
10,1,Symax,X5C,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,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 5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
61,0,Tiger,Std,1,Flip,Light 48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
46,0,V911s,Std,1,Calib 48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
46,1,E119,Std,1,Calib 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,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video 62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess 8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
@ -141,17 +173,4 @@
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess 8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess 8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
8,4,YD717,NiHui,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 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

View file

@ -249,13 +249,13 @@ local function Multi_Init()
--Exceptions on first 4 channels... --Exceptions on first 4 channels...
local stick_names = { "Rud", "Ele", "Thr", "Ail" } 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[2] = "n-a"
stick_names[4] = "n-a" stick_names[4] = "n-a"
elseif protocol == 43 then -- Traxxas elseif protocol == 43 then -- Traxxas
stick_names[2] = "Aux4" stick_names[2] = "Aux4"
stick_names[4] = "Aux3" stick_names[4] = "Aux3"
elseif protocol == 48 then -- V761 elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH
stick_names[4] = "n-a" stick_names[4] = "n-a"
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816 elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
stick_names[1] = "n-a" stick_names[1] = "n-a"
@ -278,6 +278,15 @@ local function Multi_Init()
ch_order = math.floor(ch_order/4) ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = stick_names[1] channel_names[bitand(ch_order,3)+1] = stick_names[1]
end 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 --Check MultiChan.txt
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r") local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
if f == nil then return end if f == nil then return end

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Some files were not shown because too many files have changed in this diff Show more